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