2 # -*- coding: utf-8 -*-
4 # Copyright 2004, 2005 Zuza Software Foundation
6 # This file is part of translate.
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.
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.
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
22 """extensions to zipfile standard module that will hopefully get included in future..."""
24 from zipfile
import ZipFile
, struct
, structCentralDir
, stringCentralDir
, structEndArchive
, stringEndArchive
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
:
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 # Remove the file's data from the archive.
39 current_offset
= self
.fp
.tell()
40 # go to the end of the archive to calculate the total archive_size
42 archive_size
= self
.fp
.tell()
43 self
.fp
.seek(deleted_offset
+ deleted_size
)
45 self
.fp
.seek(deleted_offset
)
47 self
.fp
.truncate(archive_size
- deleted_size
- zinfo_size
)
48 # go to the end of the archive to calculate the total archive_size
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 # Remove file from central directory.
60 # Adjust the remaining offsets in the central directory.
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
]
69 print name
, "not in archive"
72 """Close the file, and for mode "w" and "a" write the ending
77 if not self
._filePassed
:
81 def writeendrec(self
):
82 """Write the ending records (without neccessarily closing the file)"""
83 if self
.mode
in ("w", "a"): # write ending records
85 current_offset
= self
.fp
.tell()
87 for zinfo
in self
.filelist
: # write central directory
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
,
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 # Write end-of-zip-archive record
106 endrec
= struct
.pack(structEndArchive
, stringEndArchive
,
107 0, 0, count
, count
, pos2
- pos1
, pos1
, 0)
108 self
.fp
.write(endrec
)