Package translate :: Package misc :: Module zipfileext |
[hide private]
[frames] | no frames]

# Source Code for Module translate.misc.zipfileext

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2004, 2005 Zuza Software Foundation
      5  #
      6  # This file is part of translate.
      7  #
      8  # translate is free software; you can redistribute it and/or modify
      9  # it under the terms of the GNU General Public License as published by
     10  # the Free Software Foundation; either version 2 of the License, or
     11  # (at your option) any later version.
     12  #
     13  # translate is distributed in the hope that it will be useful,
     14  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  # GNU General Public License for more details.
     17  #
     18  # You should have received a copy of the GNU General Public License
     19  # along with translate; if not, write to the Free Software
     20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     21
     22  """extensions to zipfile standard module that will hopefully get included in future..."""
     23
     24  from zipfile import ZipFile, struct, structCentralDir, stringCentralDir, structEndArchive, stringEndArchive
     25
     26 -class ZipFileExt(ZipFile, object):
     27      """a ZipFile that can handle replacing objects"""
     28 -    def delete(self, name):
     29          """Delete the file from the archive. If it appears multiple
     30          times only the first instance will be deleted."""
     31          for i in range (0, len(self.filelist)):
     32              if self.filelist[i].filename == name:
     33                  if self.debug:
     34                      print "Removing", name
     35                  deleted_offset = self.filelist[i].header_offset
     36                  # "file_offset" is only available in python up to 2.4
     37                  if hasattr(self.filelist[i], "file_offset"):
     38                      deleted_size   = (self.filelist[i].file_offset - self.filelist[i].header_offset) + self.filelist[i].compress_size
     39                  else:
     40                      deleted_size   = (len(self.filelist[i].FileHeader()) - self.filelist[i].header_offset) + self.filelist[i].compress_size
     41                  zinfo_size = struct.calcsize(structCentralDir) + len(self.filelist[i].filename) + len(self.filelist[i].extra)
     42                  # Remove the file's data from the archive.
     43                  current_offset = self.fp.tell()
     44                  # go to the end of the archive to calculate the total archive_size
     45                  self.fp.seek(0, 2)
     46                  archive_size = self.fp.tell()
     47                  self.fp.seek(deleted_offset + deleted_size)
     48                  buf = self.fp.read()
     49                  self.fp.seek(deleted_offset)
     50                  self.fp.write(buf)
     51                  self.fp.truncate(archive_size - deleted_size - zinfo_size)
     52                  # go to the end of the archive to calculate the total archive_size
     53                  self.fp.seek(0, 2)
     54                  if self.debug >= 2:
     55                      if self.fp.tell() != archive_size - deleted_size - zinfo_size:
     56                          print "truncation failed: %r != %r" % (self.fp.tell(), archive_size - deleted_size - zinfo_size)
     57                  if current_offset > deleted_offset + deleted_size:
     58                      current_offset -= deleted_size
     59                  elif current_offset > deleted_offset:
     60                      current_offset = deleted_offset
     61                  self.fp.seek(current_offset, 0)
     62                  # Remove file from central directory.
     63                  del self.filelist[i]
     64                  # Adjust the remaining offsets in the central directory.
     65                  for j in range (i, len(self.filelist)):
     66                      if self.filelist[j].header_offset > deleted_offset:
     67                          self.filelist[j].header_offset -= deleted_size
     68                      # "file_offset" is only available in python up to 2.4
     69                      if hasattr(self.filelist[i], "file_offset"):
     70                          if self.filelist[j].file_offset > deleted_offset:
     71                              self.filelist[j].file_offset -= deleted_size
     72                  del self.NameToInfo[name]
     73                  return
     74          if self.debug:
     75              print name, "not in archive"
     76
     77 -    def close(self):
     78          """Close the file, and for mode "w" and "a" write the ending
     79          records."""
     80          if self.fp is None:
     81              return
     82          self.writeendrec()
     83          if not self._filePassed:
     84              self.fp.close()
     85          self.fp = None
     86
     87 -    def writeendrec(self):
     88          """Write the ending records (without neccessarily closing the file)"""
     89          if self.mode in ("w", "a"):             # write ending records
     90              count = 0
     91              current_offset = self.fp.tell()
     92              pos1 = self.fp.tell()
     93              for zinfo in self.filelist:         # write central directory
     94                  count = count + 1
     95                  dt = zinfo.date_time
     96                  dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
     97                  dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
     98                  centdir = struct.pack(structCentralDir,
     99                    stringCentralDir, zinfo.create_version,
    100                    zinfo.create_system, zinfo.extract_version, zinfo.reserved,
    101                    zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
    102                    zinfo.CRC, zinfo.compress_size, zinfo.file_size,
    103                    len(zinfo.filename), len(zinfo.extra), len(zinfo.comment),
    104                    0, zinfo.internal_attr, zinfo.external_attr,
    105                    zinfo.header_offset)
    106                  self.fp.write(centdir)
    107                  self.fp.write(zinfo.filename)
    108                  self.fp.write(zinfo.extra)
    109                  self.fp.write(zinfo.comment)
    110              pos2 = self.fp.tell()
    111              # Write end-of-zip-archive record
    112              endrec = struct.pack(structEndArchive, stringEndArchive,
    113                       0, 0, count, count, pos2 - pos1, pos1, 0)
    114              self.fp.write(endrec)
    115              self.fp.seek(pos1)
    116