예제 #1
0
파일: py26.py 프로젝트: damycra/pyslet
def is_zipfile(filename):
    # patched to accept a file that is already open we use the
    # _EndRecData method directly, we're all grown-ups here
    try:
        if is_text(filename):
            fpin = open(filename, "rb")
            endrec = zipfile._EndRecData(fpin)
            fpin.close()
        else:
            endrec = zipfile._EndRecData(filename)
        if endrec:
            return True
    except IOError:
        pass
    return False
예제 #2
0
파일: py26.py 프로젝트: sreylindoung/pyslet
def is_zipfile(filename):
    # patched to accept a file that is already open we use the
    # _EndRecData method directly, we're all grown-ups here
    try:
        if is_text(filename):
            fpin = open(filename, "rb")
            endrec = zipfile._EndRecData(fpin)
            fpin.close()
        else:
            endrec = zipfile._EndRecData(filename)
        if endrec:
            return True
    except IOError:
        pass
    return False
예제 #3
0
def is_zipstream(data):
    """
    just like zipfile.is_zipfile, but works upon buffers and streams
    rather than filenames.

    If data supports the read method, it will be treated as a stream
    and read from to test whether it is a valid ZipFile.

    If data also supports the tell and seek methods, it will be
    rewound after being tested.
    """

    if isinstance(data, (str, buffer)):
        data = StringIO(data)

    if hasattr(data, "read"):
        tell = 0
        if hasattr(data, "tell"):
            tell = data.tell()

        try:
            result = bool(_EndRecData(data))
        except IOError:
            result = False

        if hasattr(data, "seek"):
            data.seek(tell)

    else:
        raise TypeError("requies str, buffer, or stream-like object")

    return result
예제 #4
0
def is_zipstream(data):
    """
    just like zipfile.is_zipfile, but works upon buffers and streams
    rather than filenames.

    If data supports the read method, it will be treated as a stream
    and read from to test whether it is a valid ZipFile.

    If data also supports the tell and seek methods, it will be
    rewound after being tested.
    """

    if isinstance(data, (str, buffer)):
        data = BytesIO(data)

    if hasattr(data, "read"):
        tell = 0
        if hasattr(data, "tell"):
            tell = data.tell()

        try:
            result = bool(_EndRecData(data))
        except IOError:
            result = False

        if hasattr(data, "seek"):
            data.seek(tell)

    else:
        raise TypeError("requies str, buffer, or stream-like object")

    return result
예제 #5
0
 def _check_zipfile(fp):
     try:
         if _EndRecData(fp):
             return True         # file has correct magic number
     except IOError:
         pass
     return False
예제 #6
0
파일: upload.py 프로젝트: jsgf/imagestore2
def is_zip_fp(fp):
    from zipfile import _EndRecData

    try:
        here = fp.tell()
        ret = _EndRecData(fp)
        fp.seek(here)
        return ret
    except IOError:
        pass
    return False
예제 #7
0
def is_zipfile(fp):
    """
    This is a version of zipfile.is_zipfile, adjusted to only work for file
    pointers, but to work in both python 2.6 and 2.7.

    """
    try:
        if zipfile._EndRecData(fp):
            return True  # file has correct magic number
    except IOError:
        pass
    return False
예제 #8
0
파일: janus.py 프로젝트: Disane/janus
def get_endrec(file):
    '''
    Look up and return the end of central directory record
    move the file stream cursor to the end of central directory record
    '''
    pos = file.tell()
    # return end of central directory record content
    endrec = _EndRecData(file)
    # move file stream cursor to the end of central directory record
    file.seek(pos)
    # return end of central directory record
    return endrec
예제 #9
0
def is_zipfile(fp):
    """
    This is a version of zipfile.is_zipfile, adjusted to only work for file
    pointers, but to work in both python 2.6 and 2.7.

    """
    try:
        if zipfile._EndRecData(fp):
            return True         # file has correct magic number
    except IOError:
        pass
    return False
예제 #10
0
 def __v2_zipfindsig(self):
     ret_sig_start = -1
     ret_offset_cd = -1
     ret_cd_end = -1
     filesize = -1
     apk_sig_block_min_size = 32
     ret_v2sigs = {}
     break_goto_fail = True
     while break_goto_fail:
         break_goto_fail = False
         endrec = _EndRecData(self.zip_file.fp)
         size_cd = endrec[_ECD_SIZE]  # bytes in central directory
         offset_cd = endrec[_ECD_OFFSET]  # offset of central directory
         if offset_cd < apk_sig_block_min_size:
             break
         self.zip_file.fp.seek(0, 2)
         filesize = self.zip_file.fp.tell()
         if offset_cd + size_cd > filesize:
             break
         ret_offset_cd = offset_cd
         ret_cd_end = offset_cd + size_cd
         self.zip_file.fp.seek(offset_cd - 24)
         buf = self.zip_file.fp.read(24)
         if buf[8:] != b'APK Sig Block 42':
             break
         sigin_foot = struct.unpack('<Q', buf[:8])[0]
         if sigin_foot < 24 or sigin_foot > filesize:
             break
         ret_sig_start = offset_cd - sigin_foot - 8
         if ret_sig_start < 0 or ret_sig_start > filesize:
             break
         self.zip_file.fp.seek(ret_sig_start)
         buf = self.zip_file.fp.read(sigin_foot + 8)
         sigin_head = struct.unpack('<Q', buf[:8])[0]
         if sigin_foot != sigin_head:
             break
         idx = 8
         while idx + 12 <= sigin_head - 24:
             length = struct.unpack('<Q', buf[idx:idx + 8])[0]
             index = struct.unpack('<L', buf[idx + 8:idx + 12])[0]
             s = buf[idx + 12:idx + 12 + length - 4]
             ret_v2sigs[index] = s
             idx += 12
             idx += length - 4
             # buff2 = buf[idx:]
             # print(repr(buff2))
         # print(v2sig)
     return ret_v2sigs, ret_sig_start, ret_offset_cd, ret_cd_end, filesize
예제 #11
0
 def __v2_zipfindsig(self):
     ret_sig_start = -1
     ret_offset_cd = -1
     ret_cd_end = -1
     filesize = -1
     apk_sig_block_min_size = 32
     ret_v2sigs = {}
     break_goto_fail = True
     while break_goto_fail:
         break_goto_fail = False
         endrec = _EndRecData(self.zip_file.fp)
         size_cd = endrec[_ECD_SIZE]  # bytes in central directory
         offset_cd = endrec[_ECD_OFFSET]  # offset of central directory
         if offset_cd < apk_sig_block_min_size:
             break
         self.zip_file.fp.seek(0, 2)
         filesize = self.zip_file.fp.tell()
         if offset_cd + size_cd > filesize:
             break
         ret_offset_cd = offset_cd
         ret_cd_end = offset_cd + size_cd
         self.zip_file.fp.seek(offset_cd - 24)
         buf = self.zip_file.fp.read(24)
         if buf[8:] != b'APK Sig Block 42':
             break
         sigin_foot = struct.unpack(b'<Q', buf[:8])[0]
         if sigin_foot < 24 or sigin_foot > filesize:
             break
         ret_sig_start = offset_cd - sigin_foot - 8
         if ret_sig_start < 0 or ret_sig_start > filesize:
             break
         self.zip_file.fp.seek(ret_sig_start)
         buf = self.zip_file.fp.read(sigin_foot + 8)
         sigin_head = struct.unpack(b'<Q', buf[:8])[0]
         if sigin_foot != sigin_head:
             break
         idx = 8
         while idx + 12 <= sigin_head - 24:
             length = struct.unpack(b'<Q', buf[idx:idx + 8])[0]
             index = struct.unpack(b'<L', buf[idx + 8:idx + 12])[0]
             s = buf[idx + 12:idx + 12 + length - 4]
             ret_v2sigs[index] = s
             idx += 12
             idx += length - 4
             # buff2 = buf[idx:]
             # print(repr(buff2))
         # print(v2sig)
     return ret_v2sigs, ret_sig_start, ret_offset_cd, ret_cd_end, filesize
예제 #12
0
파일: zipfix.py 프로젝트: xinghun61/infra
def _read_central_directory_offsets(zfile):
  """Read in the table of contents for the ZIP file."""

  fp = zfile.fp
  try:
    endrec = zipfile._EndRecData(fp)
  except IOError:
    raise zipfile.BadZipfile("File is not a zip file")
  if not endrec:
    raise zipfile.BadZipfile, "File is not a zip file"
  size_cd = endrec[_ECD_SIZE]             # bytes in central directory
  offset_cd = endrec[_ECD_OFFSET]         # offset of central directory

  # "concat" is zero, unless zip was concatenated to another file
  concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
  if endrec[_ECD_SIGNATURE] == stringEndArchive64:
    # If Zip64 extension structures are present, account for them
    concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator)

  # Go to start of central directory
  fp.seek(offset_cd + concat, 0)
  data = fp.read(size_cd)
  fp = cStringIO.StringIO(data)
  total = 0
  offsets = []
  while total < size_cd:
    # Tell gives use the offset inside the CD. We want the offset relative
    # to the beginning of file.
    offsets.append(fp.tell() + offset_cd + concat)
    centdir = fp.read(sizeCentralDir)
    if len(centdir) != sizeCentralDir:
      raise zipfile.BadZipfile("Truncated central directory")
    centdir = struct.unpack(structCentralDir, centdir)
    if centdir[_CD_SIGNATURE] != stringCentralDir:
      raise zipfile.BadZipfile("Bad magic number for central directory")

    # Skip everything else
    fp.seek(centdir[_CD_FILENAME_LENGTH]
            + centdir[_CD_EXTRA_FIELD_LENGTH]
            + centdir[_CD_COMMENT_LENGTH], 1)

    # update total bytes read from central directory
    total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH]
             + centdir[_CD_EXTRA_FIELD_LENGTH]
             + centdir[_CD_COMMENT_LENGTH])

  return offsets
예제 #13
0
def h5_open_zip(filename, file_obj=None, mode='rb', **kw):
    """
    Open a NeXus file, even if it is in a zip file,
    or if it is a NeXus-zip file.

    If the filename ends in '.zip', it will be unzipped to a temporary
    directory before opening and deleted on :func:`closezip`.  If opened
    for writing, then the file will be created in a temporary directory,
    then zipped and deleted on :func:`closezip`.

    If it is a zipfile but doesn't end in '.zip', it is assumed
    to be a NeXus-zip file and is opened with that library.

    Arguments are the same as for :func:`open`.
    """
    if file_obj is None:
        file_obj = open(filename, mode=mode, buffering=-1)
    is_zip = _EndRecData(
        file_obj)  # is_zipfile(file_obj) doens't work in py2.6
    if is_zip and '.attrs' in ZipFile(file_obj).namelist():
        # then it's a nexus-zip file, rather than
        # a zipped hdf5 nexus file
        f = hzf.File(filename, file_obj)
        f.delete_on_close = False
        f.zip_on_close = False
    else:
        zip_on_close = None
        if is_zip:
            path = tempfile.gettempdir()
            if mode == 'r':
                zf = ZipFile(filename)
                members = zf.namelist()
                assert len(members) == 1
                zf.extract(members[0], path)
                filename = os.path.join(path, members[0])
            elif mode == 'w':
                zip_on_close = filename
                filename = os.path.join(path, os.path.basename(filename)[:-4])
            else:
                raise TypeError("zipped nexus files only support mode r and w")

        f = h5.File(filename, mode=mode, **kw)
        f.delete_on_close = is_zip
        f.zip_on_close = zip_on_close
    return f
예제 #14
0
def h5_open_zip(filename, file_obj=None, mode="r", **kw):
    """
    Open a NeXus file, even if it is in a zip file, 
    or if it is a NeXus-zip file.

    If the filename ends in '.zip', it will be unzipped to a temporary
    directory before opening and deleted on :func:`closezip`.  If opened
    for writing, then the file will be created in a temporary directory,
    then zipped and deleted on :func:`closezip`.
    
    If it is a zipfile but doesn't end in '.zip', it is assumed
    to be a NeXus-zip file and is opened with that library.

    Arguments are the same as for :func:`open`.
    """
    if file_obj is None:
        file_obj = open(filename, mode=mode)
    is_zip = _EndRecData(file_obj)  # is_zipfile(file_obj) doens't work in py2.6
    if is_zip and not filename.endswith(".zip"):
        # then it's a nexus-zip file, rather than
        # a zipped hdf5 nexus file
        f = hzf.File(filename, file_obj)
        f.delete_on_close = False
        f.zip_on_close = False
    else:
        zip_on_close = None
        if is_zip:
            path = tempfile.gettempdir()
            if mode == "r":
                zf = ZipFile(filename)
                members = zf.namelist()
                assert len(members) == 1
                zf.extract(members[0], path)
                filename = os.path.join(path, members[0])
            elif mode == "w":
                zip_on_close = filename
                filename = os.path.join(path, os.path.basename(filename)[:-4])
            else:
                raise TypeError("zipped nexus files only support mode r and w")

        f = h5.File(filename, mode=mode, **kw)
        f.delete_on_close = is_zip
        f.zip_on_close = zip_on_close
    return f
예제 #15
0
def get_last_zip_begin(fname):
    with zipfile.ZipFile(fname) as zfin:
        central_directory_begin = zfin.start_dir

        last_zip_first_file_entity_begin = min(
            (info.header_offset for info in zfin.infolist()), default=None)
        # NOTE:
        #   * when infolist is empty
        #   * when there are some deleted file entry in front of last zip file

    with open(fname, 'rb') as fin:
        endrec = _EndRecData(fin)
        # [b'PK\x05\x06', 0, 0, 2, 2, 183, 32592, 0, b'', 65296]
        offset_cd = endrec[_ECD_OFFSET]  # offset of central directory

        # offset_cd is the old central_directory_begin
        # central_directory_begin is new, i.e. prefix_size + offset_cd
        concat_prefix_file_size = central_directory_begin - offset_cd

    if last_zip_first_file_entity_begin is not None:
        assert concat_prefix_file_size <= last_zip_first_file_entity_begin
    last_zip_begin = concat_prefix_file_size
    return last_zip_begin
예제 #16
0
파일: janus.py 프로젝트: yege0201/janus
def get_endrec(file):
    pos = file.tell()
    endrec = _EndRecData(file)
    file.seek(pos)

    return endrec
예제 #17
0
    def _RealGetContents(self):
        """Read in the table of contents for the ZIP file."""
        fp = self.fp
        try:
            endrec = zipfile._EndRecData(fp)
        except OSError:
            raise zipfile.BadZipFile("File is not a zip file")
        if not endrec:
            raise zipfile.BadZipFile("File is not a zip file")
        if self.debug > 1:
            print(endrec)
        size_cd = endrec[zipfile._ECD_SIZE]  # bytes in central directory
        offset_cd = endrec[zipfile._ECD_OFFSET]  # offset of central directory
        self._comment = endrec[zipfile._ECD_COMMENT]  # archive comment

        # "concat" is zero, unless zip was concatenated to another file
        concat = endrec[zipfile._ECD_LOCATION] - size_cd - offset_cd
        if endrec[zipfile._ECD_SIGNATURE] == zipfile.stringEndArchive64:
            # If Zip64 extension structures are present, account for them
            concat -= zipfile.sizeEndCentDir64 + zipfile.sizeEndCentDir64Locator

        if self.debug > 2:
            inferred = concat + offset_cd
            print("given, inferred, offset", offset_cd, inferred, concat)
        # self.start_dir:  Position of start of central directory
        self.start_dir = offset_cd + concat
        fp.seek(self.start_dir, 0)
        data = fp.read(size_cd)
        fp = io.BytesIO(data)
        total = 0
        while total < size_cd:
            centdir = fp.read(zipfile.sizeCentralDir)
            if len(centdir) != zipfile.sizeCentralDir:
                raise zipfile.BadZipFile("Truncated central directory")
            centdir = struct.unpack(zipfile.structCentralDir, centdir)
            if centdir[zipfile._CD_SIGNATURE] != zipfile.stringCentralDir:
                raise zipfile.BadZipFile(
                    "Bad magic number for central directory")
            if self.debug > 2:
                print(centdir)
            filename = fp.read(centdir[zipfile._CD_FILENAME_LENGTH])
            flags = centdir[5]
            if flags & 0x800:
                # UTF-8 file names extension
                filename = filename.decode("utf-8")
            else:
                # Historical ZIP filename encoding
                filename = filename.decode("cp437")
            # Create ZipInfo instance to store file information
            x = P4KInfo(filename)
            x.extra = fp.read(centdir[zipfile._CD_EXTRA_FIELD_LENGTH])
            x.comment = fp.read(centdir[zipfile._CD_COMMENT_LENGTH])
            x.header_offset = centdir[zipfile._CD_LOCAL_HEADER_OFFSET]
            (
                x.create_version,
                x.create_system,
                x.extract_version,
                x.reserved,
                x.flag_bits,
                x.compress_type,
                t,
                d,
                x.CRC,
                x.compress_size,
                x.file_size,
            ) = centdir[1:12]
            if x.extract_version > zipfile.MAX_EXTRACT_VERSION:
                raise NotImplementedError("zip file version %.1f" %
                                          (x.extract_version / 10))
            x.volume, x.internal_attr, x.external_attr = centdir[15:18]
            # Convert date/time code to (year, month, day, hour, min, sec)
            x._raw_time = t
            x.date_time = (
                (d >> 9) + 1980,
                (d >> 5) & 0xF,
                d & 0x1F,
                t >> 11,
                (t >> 5) & 0x3F,
                (t & 0x1F) * 2,
            )

            x._decodeExtra()
            x.header_offset = x.header_offset + concat
            self.filelist.append(x)
            self.NameToInfo[x.filename] = x

            # update total bytes read from central directory
            total = (total + zipfile.sizeCentralDir +
                     centdir[zipfile._CD_FILENAME_LENGTH] +
                     centdir[zipfile._CD_EXTRA_FIELD_LENGTH] +
                     centdir[zipfile._CD_COMMENT_LENGTH])

            if self.debug > 2:
                print("total", total)
    def _RealGetContents1(self,filename_to_open):
        """Read in the table of contents for the ZIP file."""
        fp = self.fp
        endrec = zipfile._EndRecData(fp)
        if not endrec:
            raise BadZipfile, "File is not a zip file"
        if self.debug > 1:
            print endrec
        size_cd = endrec[5]             # bytes in central directory
        offset_cd = endrec[6]   # offset of central directory
        self.comment = endrec[8]        # archive comment
        # endrec[9] is the offset of the "End of Central Dir" record
        x = endrec[9] - size_cd
        # "concat" is zero, unless zip was concatenated to another file
        concat = x - offset_cd
        if self.debug > 2:
            print "given, inferred, offset", offset_cd, x, concat
        # self.start_dir:  Position of start of central directory
        self.start_dir = offset_cd + concat
        fp.seek(self.start_dir, 0)
        total = 0

        # >>>create just once instance of ZipInfo
        x = zipfile.ZipInfo('_')

        while total < size_cd:
            centdir = fp.read(46)
            total = total + 46
            if centdir[0:4] != stringCentralDir:
                raise BadZipfile, "Bad magic number for central directory"
            centdir = struct.unpack(structCentralDir, centdir)
            if self.debug > 2:
                print centdir
            filename = fp.read(centdir[_CD_FILENAME_LENGTH])
            # Create ZipInfo instance to store file information
            #x = ZipInfo(filename)


    # >>>Initialize x assuming it will match filename_to_open
            x.orig_filename = filename

    # >>>Below includes filename cleanup code is borrowed from ZipFile.__init__
    # Terminate the file name at the first null byte.  Null bytes in file
    # names are used as tricks by viruses in archives.
            null_byte = filename.find(chr(0))
            if null_byte >= 0:
                filename = filename[0:null_byte]
    # This is used to ensure paths in generated ZIP files always use
    # forward slashes as the directory separator, as required by the
    # ZIP format specification.
            if os.sep != "/":
                filename = filename.replace(os.sep, "/")
            x.filename = filename


            x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
            x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
            total = (total + centdir[_CD_FILENAME_LENGTH]
                     + centdir[_CD_EXTRA_FIELD_LENGTH]
                     + centdir[_CD_COMMENT_LENGTH])
            x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET] + concat
            # file_offset must be computed below...
            (x.create_version, x.create_system, x.extract_version, x.reserved,
                x.flag_bits, x.compress_type, t, d,
                x.CRC, x.compress_size, x.file_size) = centdir[1:12]
            x.volume, x.internal_attr, x.external_attr = centdir[15:18]
            # Convert date/time code to (year, month, day, hour, min, sec)
            x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F,
                                     t>>11, (t>>5)&0x3F, (t&0x1F) * 2 )
            #self.filelist.append(x)
            #self.NameToInfo[x.filename] = x
            #if self.debug > 2:
            #    print "total", total

            #>>> break the loop as soon as we find a matching filename
            if filename == filename_to_open:
                break
        else:
            raise KeyError, filename_to_open

        #>>>Use x as data. No need to loop all files
        data = x
        #for data in self.filelist:

        fp.seek(data.header_offset, 0)
        fheader = fp.read(30)
        if fheader[0:4] != stringFileHeader:
            raise BadZipfile, "Bad magic number for file header"
        fheader = struct.unpack(structFileHeader, fheader)
        # file_offset is computed here, since the extra field for
        # the central directory and for the local file header
        # refer to different fields, and they can have different
        # lengths
        data.file_offset = (data.header_offset + 30
                            + fheader[_FH_FILENAME_LENGTH]
                            + fheader[_FH_EXTRA_FIELD_LENGTH])
        fname = fp.read(fheader[_FH_FILENAME_LENGTH])
        if fname != data.orig_filename:
            raise RuntimeError, \
                  'File name in directory "%s" and header "%s" differ.' % (
                      data.orig_filename, fname)
        return data
예제 #19
0
파일: nodes.py 프로젝트: xxoolm/Ryven
 def update_event(self, inp=-1):
     self.set_output_val(0, zipfile._EndRecData(self.input(0)))
예제 #20
0
with zipfile.ZipFile(zpayload, 'w', zipfile.ZIP_DEFLATED) as zipf:
  for i in xrange(10):
    fn = uuid.uuid4()
    data = os.urandom(512)
    zipf.writestr(str(fn), data)
    fs.append((fn, SHA.new(data).hexdigest()))
zipblob = zpayload.getvalue()

crxpayload = iofactory()
cf = CRXFile.CRXFile(crxpayload, mode='w', log=log.getChild('wcrx'))
cf.setprivatekey(k)

sha1sum = '\n'.join(["%s %s" % (fn, ss) for fn, ss in fs])
cf.setsha1sum(sha1sum)

_endrec = zipfile._EndRecData(zpayload)
zpayload.seek(_endrec[zipfile._ECD_OFFSET])
zipdir = zpayload.read(zipfile._ECD_SIZE)
cf.setzcd(zipdir)
cf.setpayloadblob(zipblob)
cf.write_crx_header()
cf.write_payload()

# REWIND THE TAPE WHIRR WHIRR WHIRR
crxpayload.seek(0)
rcf = CRXFile.CRXFile(crxpayload, log=log.getChild('rcrx'))
rzip = zipfile.ZipFile(rcf)

code.interact(local=locals())

예제 #21
0
    def get_zip_infos(self, *filenames):
        """Read in the table of contents for the ZIP file."""
        fp = self.fp
        max_file_count = self.max_file_count

        if not fp:
            raise RuntimeError(
                "Attempt to read ZIP archive that was already closed")

        filenames = set(filenames)
        if len(filenames) == 0:
            return

        try:
            endrec = _EndRecData(fp)
        except OSError:
            raise BadZipFile("File is not a zip file")
        if not endrec:
            raise BadZipFile("File is not a zip file")

        size_cd = endrec[_ECD_SIZE]  # bytes in central directory
        offset_cd = endrec[_ECD_OFFSET]  # offset of central directory

        # "concat" is zero, unless zip was concatenated to another file
        concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
        if endrec[_ECD_SIGNATURE] == stringEndArchive64:
            # If Zip64 extension structures are present, account for them
            concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator)

        # start_dir:  Position of start of central directory
        start_dir = offset_cd + concat
        fp.seek(start_dir, 0)
        data = fp.read(size_cd)
        fp = BytesIO(data)
        total = 0
        file_count = 0
        while total < size_cd:
            centdir = fp.read(sizeCentralDir)
            if len(centdir) != sizeCentralDir:
                raise BadZipFile("Truncated central directory")
            centdir = struct.unpack(structCentralDir, centdir)
            if centdir[_CD_SIGNATURE] != stringCentralDir:
                raise BadZipFile("Bad magic number for central directory")
            filename = fp.read(centdir[_CD_FILENAME_LENGTH])
            flags = centdir[5]
            if flags & _UTF8_EXTENSION_FLAG:
                # UTF-8 file names extension
                filename = filename.decode('utf-8')
            else:
                # Historical ZIP filename encoding
                filename = filename.decode('cp437')
            # Create ZipInfo instance to store file information
            x = ZipInfo(filename)
            x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
            x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
            x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
            (x.create_version, x.create_system, x.extract_version, x.reserved,
             x.flag_bits, x.compress_type, t, d, x.CRC, x.compress_size,
             x.file_size) = centdir[1:12]
            if x.extract_version > MAX_EXTRACT_VERSION:
                raise NotImplementedError("zip file version %.1f" %
                                          (x.extract_version / 10))
            x.volume, x.internal_attr, x.external_attr = centdir[15:18]
            # Convert date/time code to (year, month, day, hour, min, sec)
            x._raw_time = t
            x.date_time = ((d >> 9) + 1980, (d >> 5) & 0xF, d & 0x1F, t >> 11,
                           (t >> 5) & 0x3F, (t & 0x1F) * 2)

            x._decodeExtra()
            x.header_offset = x.header_offset + concat

            # update total bytes read from central directory
            total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH] +
                     centdir[_CD_EXTRA_FIELD_LENGTH] +
                     centdir[_CD_COMMENT_LENGTH])

            file_count += 1
            if max_file_count is not None and file_count > max_file_count:
                raise TooManyFiles('Too many files in egg')

            if x.filename in filenames:
                filenames.discard(x.filename)
                yield x

            if len(filenames) == 0:
                return
예제 #22
0
    def get_zip_infos(self, *filenames):
        """Read in the table of contents for the ZIP file."""
        fp = self.fp
        max_file_count = self.max_file_count

        if not fp:
            raise RuntimeError(
                "Attempt to read ZIP archive that was already closed")

        filenames = set(filenames)
        if len(filenames) == 0:
            return

        try:
            endrec = _EndRecData(fp)
        except OSError:
            raise BadZipFile("File is not a zip file")
        if not endrec:
            raise BadZipFile("File is not a zip file")

        size_cd = endrec[_ECD_SIZE]             # bytes in central directory
        offset_cd = endrec[_ECD_OFFSET]         # offset of central directory

        # "concat" is zero, unless zip was concatenated to another file
        concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
        if endrec[_ECD_SIGNATURE] == stringEndArchive64:
            # If Zip64 extension structures are present, account for them
            concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator)

        # start_dir:  Position of start of central directory
        start_dir = offset_cd + concat
        fp.seek(start_dir, 0)
        data = fp.read(size_cd)
        fp = BytesIO(data)
        total = 0
        file_count = 0
        while total < size_cd:
            centdir = fp.read(sizeCentralDir)
            if len(centdir) != sizeCentralDir:
                raise BadZipFile("Truncated central directory")
            centdir = struct.unpack(structCentralDir, centdir)
            if centdir[_CD_SIGNATURE] != stringCentralDir:
                raise BadZipFile("Bad magic number for central directory")
            filename = fp.read(centdir[_CD_FILENAME_LENGTH])
            flags = centdir[5]
            if flags & _UTF8_EXTENSION_FLAG:
                # UTF-8 file names extension
                filename = filename.decode('utf-8')
            else:
                # Historical ZIP filename encoding
                filename = filename.decode('cp437')
            # Create ZipInfo instance to store file information
            x = ZipInfo(filename)
            x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
            x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
            x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
            (x.create_version, x.create_system, x.extract_version, x.reserved,
             x.flag_bits, x.compress_type, t, d,
             x.CRC, x.compress_size, x.file_size) = centdir[1:12]
            if x.extract_version > MAX_EXTRACT_VERSION:
                raise NotImplementedError("zip file version %.1f" %
                                          (x.extract_version / 10))
            x.volume, x.internal_attr, x.external_attr = centdir[15:18]
            # Convert date/time code to (year, month, day, hour, min, sec)
            x._raw_time = t
            x.date_time = ((d >> 9) + 1980, (d >> 5) & 0xF, d & 0x1F,
                           t >> 11, (t >> 5) & 0x3F, (t & 0x1F) * 2)

            x._decodeExtra()
            x.header_offset = x.header_offset + concat

            # update total bytes read from central directory
            total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH]
                     + centdir[_CD_EXTRA_FIELD_LENGTH]
                     + centdir[_CD_COMMENT_LENGTH])

            file_count += 1
            if max_file_count is not None and file_count > max_file_count:
                raise TooManyFiles('Too many files in egg')

            if x.filename in filenames:
                filenames.discard(x.filename)
                yield x

            if len(filenames) == 0:
                return