1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 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   
 27      """a ZipFile that can handle replacing objects""" 
 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                  deleted_size   = (self.filelist[i].file_offset - self.filelist[i].header_offset) + self.filelist[i].compress_size 
 37                  zinfo_size = struct.calcsize(structCentralDir) + len(self.filelist[i].filename) + len(self.filelist[i].extra) 
 38                   
 39                  current_offset = self.fp.tell() 
 40                   
 41                  self.fp.seek(0, 2) 
 42                  archive_size = self.fp.tell() 
 43                  self.fp.seek(deleted_offset + deleted_size) 
 44                  buf = self.fp.read() 
 45                  self.fp.seek(deleted_offset) 
 46                  self.fp.write(buf) 
 47                  self.fp.truncate(archive_size - deleted_size - zinfo_size) 
 48                   
 49                  self.fp.seek(0, 2) 
 50                  if self.debug >= 2: 
 51                      if self.fp.tell() != archive_size - deleted_size - zinfo_size: 
 52                          print "truncation failed: %r != %r" % (self.fp.tell(), archive_size - deleted_size - zinfo_size) 
 53                  if current_offset > deleted_offset + deleted_size: 
 54                      current_offset -= deleted_size 
 55                  elif current_offset > deleted_offset: 
 56                      current_offset = deleted_offset 
 57                  self.fp.seek(current_offset, 0) 
 58                   
 59                  del self.filelist[i] 
 60                   
 61                  for j in range (i, len(self.filelist)): 
 62                      if self.filelist[j].header_offset > deleted_offset: 
 63                          self.filelist[j].header_offset -= deleted_size 
 64                      if self.filelist[j].file_offset > deleted_offset: 
 65                          self.filelist[j].file_offset -= deleted_size 
 66                  del self.NameToInfo[name] 
 67                  return 
 68          if self.debug: 
 69              print name, "not in archive" 
  70   
 72          """Close the file, and for mode "w" and "a" write the ending 
 73          records.""" 
 74          if self.fp is None: 
 75              return 
 76          self.writeendrec() 
 77          if not self._filePassed: 
 78              self.fp.close() 
 79          self.fp = None 
  80   
 82          """Write the ending records (without neccessarily closing the file)""" 
 83          if self.mode in ("w", "a"):              
 84              count = 0 
 85              current_offset = self.fp.tell() 
 86              pos1 = self.fp.tell() 
 87              for zinfo in self.filelist:          
 88                  count = count + 1 
 89                  dt = zinfo.date_time 
 90                  dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2] 
 91                  dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2) 
 92                  centdir = struct.pack(structCentralDir, 
 93                    stringCentralDir, zinfo.create_version, 
 94                    zinfo.create_system, zinfo.extract_version, zinfo.reserved, 
 95                    zinfo.flag_bits, zinfo.compress_type, dostime, dosdate, 
 96                    zinfo.CRC, zinfo.compress_size, zinfo.file_size, 
 97                    len(zinfo.filename), len(zinfo.extra), len(zinfo.comment), 
 98                    0, zinfo.internal_attr, zinfo.external_attr, 
 99                    zinfo.header_offset) 
100                  self.fp.write(centdir) 
101                  self.fp.write(zinfo.filename) 
102                  self.fp.write(zinfo.extra) 
103                  self.fp.write(zinfo.comment) 
104              pos2 = self.fp.tell() 
105               
106              endrec = struct.pack(structEndArchive, stringEndArchive, 
107                       0, 0, count, count, pos2 - pos1, pos1, 0) 
108              self.fp.write(endrec) 
109              self.fp.seek(pos1) 
  110