annotate 1.20/zipfile.py @ 40:af9c45708987

Cemented a decision previously being unsure about The mere presense of the tasknames configuration variable now always makes problem names to be printed. This is not new, but the old behaviour (only printing names if we test more than one problem), previously commented out, has now been removed altogether.
author Oleg Oshmyan <chortos@inbox.lv>
date Sun, 05 Dec 2010 14:34:24 +0100
parents a99db3631d10
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
7
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
2 Read and write ZIP files.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
3 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
4 # Improved by Chortos-2 in 2009 (added bzip2 support)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
5 import struct, os, time, sys, shutil
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
6 import binascii, cStringIO, stat
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
7
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
8 try:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
9 import zlib # We may need its compression method
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
10 crc32 = zlib.crc32
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
11 except ImportError:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
12 zlib = None
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
13 crc32 = binascii.crc32
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
14
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
15 try:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
16 import bz2 # We may need its compression method
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
17 except ImportError:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
18 bz2 = None
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
19
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
20 __all__ = ["BadZipfile", "error", "ZIP_STORED", "ZIP_DEFLATED", "is_zipfile",
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
21 "ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile" ]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
22
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
23 class BadZipfile(Exception):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
24 pass
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
25
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
26
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
27 class LargeZipFile(Exception):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
28 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
29 Raised when writing a zipfile, the zipfile requires ZIP64 extensions
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
30 and those extensions are disabled.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
31 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
32
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
33 error = BadZipfile # The exception raised by this module
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
34
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
35 ZIP64_LIMIT = (1 << 31) - 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
36 ZIP_FILECOUNT_LIMIT = 1 << 16
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
37 ZIP_MAX_COMMENT = (1 << 16) - 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
38
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
39 # constants for Zip file compression methods
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
40 ZIP_STORED = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
41 ZIP_DEFLATED = 8
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
42 ZIP_BZIP2 = 12
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
43 # Other ZIP compression methods not supported
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
44
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
45 # Below are some formats and associated data for reading/writing headers using
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
46 # the struct module. The names and structures of headers/records are those used
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
47 # in the PKWARE description of the ZIP file format:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
48 # http://www.pkware.com/documents/casestudies/APPNOTE.TXT
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
49 # (URL valid as of January 2008)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
50
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
51 # The "end of central directory" structure, magic number, size, and indices
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
52 # (section V.I in the format document)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
53 structEndArchive = "<4s4H2LH"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
54 stringEndArchive = "PK\005\006"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
55 sizeEndCentDir = struct.calcsize(structEndArchive)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
56
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
57 _ECD_SIGNATURE = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
58 _ECD_DISK_NUMBER = 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
59 _ECD_DISK_START = 2
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
60 _ECD_ENTRIES_THIS_DISK = 3
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
61 _ECD_ENTRIES_TOTAL = 4
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
62 _ECD_SIZE = 5
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
63 _ECD_OFFSET = 6
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
64 _ECD_COMMENT_SIZE = 7
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
65 # These last two indices are not part of the structure as defined in the
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
66 # spec, but they are used internally by this module as a convenience
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
67 _ECD_COMMENT = 8
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
68 _ECD_LOCATION = 9
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
69
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
70 # The "central directory" structure, magic number, size, and indices
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
71 # of entries in the structure (section V.F in the format document)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
72 structCentralDir = "<4s4B4HL2L5H2L"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
73 stringCentralDir = "PK\001\002"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
74 sizeCentralDir = struct.calcsize(structCentralDir)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
75
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
76 # indexes of entries in the central directory structure
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
77 _CD_SIGNATURE = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
78 _CD_CREATE_VERSION = 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
79 _CD_CREATE_SYSTEM = 2
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
80 _CD_EXTRACT_VERSION = 3
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
81 _CD_EXTRACT_SYSTEM = 4
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
82 _CD_FLAG_BITS = 5
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
83 _CD_COMPRESS_TYPE = 6
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
84 _CD_TIME = 7
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
85 _CD_DATE = 8
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
86 _CD_CRC = 9
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
87 _CD_COMPRESSED_SIZE = 10
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
88 _CD_UNCOMPRESSED_SIZE = 11
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
89 _CD_FILENAME_LENGTH = 12
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
90 _CD_EXTRA_FIELD_LENGTH = 13
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
91 _CD_COMMENT_LENGTH = 14
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
92 _CD_DISK_NUMBER_START = 15
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
93 _CD_INTERNAL_FILE_ATTRIBUTES = 16
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
94 _CD_EXTERNAL_FILE_ATTRIBUTES = 17
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
95 _CD_LOCAL_HEADER_OFFSET = 18
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
96
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
97 # The "local file header" structure, magic number, size, and indices
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
98 # (section V.A in the format document)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
99 structFileHeader = "<4s2B4HL2L2H"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
100 stringFileHeader = "PK\003\004"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
101 sizeFileHeader = struct.calcsize(structFileHeader)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
102
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
103 _FH_SIGNATURE = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
104 _FH_EXTRACT_VERSION = 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
105 _FH_EXTRACT_SYSTEM = 2
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
106 _FH_GENERAL_PURPOSE_FLAG_BITS = 3
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
107 _FH_COMPRESSION_METHOD = 4
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
108 _FH_LAST_MOD_TIME = 5
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
109 _FH_LAST_MOD_DATE = 6
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
110 _FH_CRC = 7
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
111 _FH_COMPRESSED_SIZE = 8
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
112 _FH_UNCOMPRESSED_SIZE = 9
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
113 _FH_FILENAME_LENGTH = 10
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
114 _FH_EXTRA_FIELD_LENGTH = 11
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
115
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
116 # The "Zip64 end of central directory locator" structure, magic number, and size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
117 structEndArchive64Locator = "<4sLQL"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
118 stringEndArchive64Locator = "PK\x06\x07"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
119 sizeEndCentDir64Locator = struct.calcsize(structEndArchive64Locator)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
120
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
121 # The "Zip64 end of central directory" record, magic number, size, and indices
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
122 # (section V.G in the format document)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
123 structEndArchive64 = "<4sQ2H2L4Q"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
124 stringEndArchive64 = "PK\x06\x06"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
125 sizeEndCentDir64 = struct.calcsize(structEndArchive64)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
126
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
127 _CD64_SIGNATURE = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
128 _CD64_DIRECTORY_RECSIZE = 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
129 _CD64_CREATE_VERSION = 2
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
130 _CD64_EXTRACT_VERSION = 3
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
131 _CD64_DISK_NUMBER = 4
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
132 _CD64_DISK_NUMBER_START = 5
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
133 _CD64_NUMBER_ENTRIES_THIS_DISK = 6
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
134 _CD64_NUMBER_ENTRIES_TOTAL = 7
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
135 _CD64_DIRECTORY_SIZE = 8
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
136 _CD64_OFFSET_START_CENTDIR = 9
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
137
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
138 def is_zipfile(filename):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
139 """Quickly see if file is a ZIP file by checking the magic number."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
140 try:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
141 fpin = open(filename, "rb")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
142 endrec = _EndRecData(fpin)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
143 fpin.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
144 if endrec:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
145 return True # file has correct magic number
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
146 except IOError:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
147 pass
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
148 return False
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
149
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
150 def _EndRecData64(fpin, offset, endrec):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
151 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
152 Read the ZIP64 end-of-archive records and use that to update endrec
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
153 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
154 fpin.seek(offset - sizeEndCentDir64Locator, 2)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
155 data = fpin.read(sizeEndCentDir64Locator)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
156 sig, diskno, reloff, disks = struct.unpack(structEndArchive64Locator, data)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
157 if sig != stringEndArchive64Locator:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
158 return endrec
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
159
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
160 if diskno != 0 or disks != 1:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
161 raise BadZipfile("zipfiles that span multiple disks are not supported")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
162
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
163 # Assume no 'zip64 extensible data'
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
164 fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
165 data = fpin.read(sizeEndCentDir64)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
166 sig, sz, create_version, read_version, disk_num, disk_dir, \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
167 dircount, dircount2, dirsize, diroffset = \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
168 struct.unpack(structEndArchive64, data)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
169 if sig != stringEndArchive64:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
170 return endrec
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
171
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
172 # Update the original endrec using data from the ZIP64 record
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
173 endrec[_ECD_SIGNATURE] = sig
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
174 endrec[_ECD_DISK_NUMBER] = disk_num
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
175 endrec[_ECD_DISK_START] = disk_dir
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
176 endrec[_ECD_ENTRIES_THIS_DISK] = dircount
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
177 endrec[_ECD_ENTRIES_TOTAL] = dircount2
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
178 endrec[_ECD_SIZE] = dirsize
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
179 endrec[_ECD_OFFSET] = diroffset
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
180 return endrec
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
181
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
182
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
183 def _EndRecData(fpin):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
184 """Return data from the "End of Central Directory" record, or None.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
185
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
186 The data is a list of the nine items in the ZIP "End of central dir"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
187 record followed by a tenth item, the file seek offset of this record."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
188
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
189 # Determine file size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
190 fpin.seek(0, 2)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
191 filesize = fpin.tell()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
192
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
193 # Check to see if this is ZIP file with no archive comment (the
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
194 # "end of central directory" structure should be the last item in the
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
195 # file if this is the case).
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
196 fpin.seek(-sizeEndCentDir, 2)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
197 data = fpin.read()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
198 if data[0:4] == stringEndArchive and data[-2:] == "\000\000":
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
199 # the signature is correct and there's no comment, unpack structure
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
200 endrec = struct.unpack(structEndArchive, data)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
201 endrec=list(endrec)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
202
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
203 # Append a blank comment and record start offset
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
204 endrec.append("")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
205 endrec.append(filesize - sizeEndCentDir)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
206
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
207 # Try to read the "Zip64 end of central directory" structure
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
208 return _EndRecData64(fpin, -sizeEndCentDir, endrec)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
209
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
210 # Either this is not a ZIP file, or it is a ZIP file with an archive
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
211 # comment. Search the end of the file for the "end of central directory"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
212 # record signature. The comment is the last item in the ZIP file and may be
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
213 # up to 64K long. It is assumed that the "end of central directory" magic
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
214 # number does not appear in the comment.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
215 maxCommentStart = max(filesize - (1 << 16) - sizeEndCentDir, 0)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
216 fpin.seek(maxCommentStart, 0)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
217 data = fpin.read()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
218 start = data.rfind(stringEndArchive)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
219 if start >= 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
220 # found the magic number; attempt to unpack and interpret
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
221 recData = data[start:start+sizeEndCentDir]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
222 endrec = list(struct.unpack(structEndArchive, recData))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
223 comment = data[start+sizeEndCentDir:]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
224 # check that comment length is correct
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
225 if endrec[_ECD_COMMENT_SIZE] == len(comment):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
226 # Append the archive comment and start offset
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
227 endrec.append(comment)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
228 endrec.append(maxCommentStart + start)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
229
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
230 # Try to read the "Zip64 end of central directory" structure
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
231 return _EndRecData64(fpin, maxCommentStart + start - filesize,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
232 endrec)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
233
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
234 # Unable to find a valid end of central directory structure
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
235 return
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
236
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
237
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
238 class ZipInfo (object):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
239 """Class with attributes describing each file in the ZIP archive."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
240
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
241 __slots__ = (
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
242 'orig_filename',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
243 'filename',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
244 'date_time',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
245 'compress_type',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
246 'comment',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
247 'extra',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
248 'create_system',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
249 'create_version',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
250 'extract_version',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
251 'reserved',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
252 'flag_bits',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
253 'volume',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
254 'internal_attr',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
255 'external_attr',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
256 'header_offset',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
257 'CRC',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
258 'compress_size',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
259 'file_size',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
260 '_raw_time',
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
261 )
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
262
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
263 def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
264 self.orig_filename = filename # Original file name in archive
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
265
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
266 # Terminate the file name at the first null byte. Null bytes in file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
267 # names are used as tricks by viruses in archives.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
268 null_byte = filename.find(chr(0))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
269 if null_byte >= 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
270 filename = filename[0:null_byte]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
271 # This is used to ensure paths in generated ZIP files always use
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
272 # forward slashes as the directory separator, as required by the
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
273 # ZIP format specification.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
274 if os.sep != "/" and os.sep in filename:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
275 filename = filename.replace(os.sep, "/")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
276
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
277 self.filename = filename # Normalized file name
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
278 self.date_time = date_time # year, month, day, hour, min, sec
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
279 # Standard values:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
280 self.compress_type = ZIP_STORED # Type of compression for the file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
281 self.comment = "" # Comment for each file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
282 self.extra = "" # ZIP extra data
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
283 if sys.platform == 'win32':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
284 self.create_system = 0 # System which created ZIP archive
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
285 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
286 # Assume everything else is unix-y
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
287 self.create_system = 3 # System which created ZIP archive
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
288 self.create_version = 20 # Version which created ZIP archive
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
289 self.extract_version = 20 # Version needed to extract archive
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
290 self.reserved = 0 # Must be zero
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
291 self.flag_bits = 0 # ZIP flag bits
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
292 self.volume = 0 # Volume number of file header
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
293 self.internal_attr = 0 # Internal attributes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
294 self.external_attr = 0 # External file attributes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
295 # Other attributes are set by class ZipFile:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
296 # header_offset Byte offset to the file header
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
297 # CRC CRC-32 of the uncompressed file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
298 # compress_size Size of the compressed file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
299 # file_size Size of the uncompressed file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
300
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
301 def FileHeader(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
302 """Return the per-file header as a string."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
303 dt = self.date_time
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
304 dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
305 dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
306 if self.flag_bits & 0x08:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
307 # Set these to zero because we write them after the file data
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
308 CRC = compress_size = file_size = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
309 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
310 CRC = self.CRC
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
311 compress_size = self.compress_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
312 file_size = self.file_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
313
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
314 extra = self.extra
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
315
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
316 if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
317 # File is larger than what fits into a 4 byte integer,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
318 # fall back to the ZIP64 extension
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
319 fmt = '<HHQQ'
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
320 extra = extra + struct.pack(fmt,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
321 1, struct.calcsize(fmt)-4, file_size, compress_size)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
322 file_size = 0xffffffff
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
323 compress_size = 0xffffffff
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
324 self.extract_version = max(45, self.extract_version)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
325 self.create_version = max(45, self.extract_version)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
326
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
327 filename, flag_bits = self._encodeFilenameFlags()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
328 header = struct.pack(structFileHeader, stringFileHeader,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
329 self.extract_version, self.reserved, flag_bits,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
330 self.compress_type, dostime, dosdate, CRC,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
331 compress_size, file_size,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
332 len(filename), len(extra))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
333 return header + filename + extra
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
334
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
335 def _encodeFilenameFlags(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
336 if isinstance(self.filename, unicode):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
337 try:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
338 return self.filename.encode('ascii'), self.flag_bits
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
339 except UnicodeEncodeError:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
340 return self.filename.encode('utf-8'), self.flag_bits | 0x800
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
341 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
342 return self.filename, self.flag_bits
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
343
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
344 def _decodeFilename(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
345 if self.flag_bits & 0x800:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
346 return self.filename.decode('utf-8')
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
347 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
348 return self.filename
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
349
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
350 def _decodeExtra(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
351 # Try to decode the extra field.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
352 extra = self.extra
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
353 unpack = struct.unpack
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
354 while extra:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
355 tp, ln = unpack('<HH', extra[:4])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
356 if tp == 1:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
357 if ln >= 24:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
358 counts = unpack('<QQQ', extra[4:28])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
359 elif ln == 16:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
360 counts = unpack('<QQ', extra[4:20])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
361 elif ln == 8:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
362 counts = unpack('<Q', extra[4:12])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
363 elif ln == 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
364 counts = ()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
365 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
366 raise RuntimeError, "Corrupt extra field %s"%(ln,)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
367
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
368 idx = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
369
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
370 # ZIP64 extension (large files and/or large archives)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
371 if self.file_size in (0xffffffffffffffffL, 0xffffffffL):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
372 self.file_size = counts[idx]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
373 idx += 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
374
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
375 if self.compress_size == 0xFFFFFFFFL:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
376 self.compress_size = counts[idx]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
377 idx += 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
378
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
379 if self.header_offset == 0xffffffffL:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
380 old = self.header_offset
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
381 self.header_offset = counts[idx]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
382 idx+=1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
383
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
384 extra = extra[ln+4:]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
385
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
386
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
387 class _ZipDecrypter:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
388 """Class to handle decryption of files stored within a ZIP archive.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
389
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
390 ZIP supports a password-based form of encryption. Even though known
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
391 plaintext attacks have been found against it, it is still useful
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
392 to be able to get data out of such a file.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
393
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
394 Usage:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
395 zd = _ZipDecrypter(mypwd)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
396 plain_char = zd(cypher_char)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
397 plain_text = map(zd, cypher_text)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
398 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
399
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
400 def _GenerateCRCTable():
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
401 """Generate a CRC-32 table.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
402
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
403 ZIP encryption uses the CRC32 one-byte primitive for scrambling some
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
404 internal keys. We noticed that a direct implementation is faster than
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
405 relying on binascii.crc32().
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
406 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
407 poly = 0xedb88320
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
408 table = [0] * 256
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
409 for i in range(256):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
410 crc = i
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
411 for j in range(8):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
412 if crc & 1:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
413 crc = ((crc >> 1) & 0x7FFFFFFF) ^ poly
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
414 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
415 crc = ((crc >> 1) & 0x7FFFFFFF)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
416 table[i] = crc
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
417 return table
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
418 crctable = _GenerateCRCTable()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
419
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
420 def _crc32(self, ch, crc):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
421 """Compute the CRC32 primitive on one byte."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
422 return ((crc >> 8) & 0xffffff) ^ self.crctable[(crc ^ ord(ch)) & 0xff]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
423
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
424 def __init__(self, pwd):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
425 self.key0 = 305419896
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
426 self.key1 = 591751049
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
427 self.key2 = 878082192
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
428 for p in pwd:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
429 self._UpdateKeys(p)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
430
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
431 def _UpdateKeys(self, c):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
432 self.key0 = self._crc32(c, self.key0)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
433 self.key1 = (self.key1 + (self.key0 & 255)) & 4294967295
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
434 self.key1 = (self.key1 * 134775813 + 1) & 4294967295
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
435 self.key2 = self._crc32(chr((self.key1 >> 24) & 255), self.key2)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
436
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
437 def __call__(self, c):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
438 """Decrypt a single character."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
439 c = ord(c)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
440 k = self.key2 | 2
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
441 c = c ^ (((k * (k^1)) >> 8) & 255)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
442 c = chr(c)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
443 self._UpdateKeys(c)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
444 return c
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
445
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
446 class ZipExtFile:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
447 """File-like object for reading an archive member.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
448 Is returned by ZipFile.open().
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
449 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
450
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
451 def __init__(self, fileobj, zipinfo, decrypt=None):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
452 self.fileobj = fileobj
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
453 self.decrypter = decrypt
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
454 self.bytes_read = 0L
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
455 self.rawbuffer = ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
456 self.readbuffer = ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
457 self.linebuffer = ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
458 self.eof = False
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
459 self.univ_newlines = False
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
460 self.nlSeps = ("\n", )
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
461 self.lastdiscard = ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
462
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
463 self.compress_type = zipinfo.compress_type
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
464 self.compress_size = zipinfo.compress_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
465
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
466 self.closed = False
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
467 self.mode = "r"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
468 self.name = zipinfo.filename
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
469
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
470 # read from compressed files in 64k blocks
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
471 self.compreadsize = 64*1024
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
472 if self.compress_type == ZIP_DEFLATED:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
473 self.dc = zlib.decompressobj(-15)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
474 elif self.compress_type == ZIP_BZIP2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
475 self.dc = bz2.BZ2Decompressor()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
476 self.compreadsize = 900000
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
477 elif self.compress_type != ZIP_STORED:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
478 raise RuntimeError, "The compression method of this file is not supported"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
479
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
480 def set_univ_newlines(self, univ_newlines):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
481 self.univ_newlines = univ_newlines
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
482
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
483 # pick line separator char(s) based on universal newlines flag
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
484 self.nlSeps = ("\n", )
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
485 if self.univ_newlines:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
486 self.nlSeps = ("\r\n", "\r", "\n")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
487
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
488 def __iter__(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
489 return self
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
490
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
491 def next(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
492 nextline = self.readline()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
493 if not nextline:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
494 raise StopIteration()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
495
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
496 return nextline
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
497
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
498 def close(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
499 self.closed = True
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
500
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
501 def _checkfornewline(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
502 nl, nllen = -1, -1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
503 if self.linebuffer:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
504 # ugly check for cases where half of an \r\n pair was
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
505 # read on the last pass, and the \r was discarded. In this
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
506 # case we just throw away the \n at the start of the buffer.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
507 if (self.lastdiscard, self.linebuffer[0]) == ('\r','\n'):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
508 self.linebuffer = self.linebuffer[1:]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
509
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
510 for sep in self.nlSeps:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
511 nl = self.linebuffer.find(sep)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
512 if nl >= 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
513 nllen = len(sep)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
514 return nl, nllen
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
515
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
516 return nl, nllen
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
517
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
518 def readline(self, size = -1):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
519 """Read a line with approx. size. If size is negative,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
520 read a whole line.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
521 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
522 if size < 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
523 size = sys.maxint
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
524 elif size == 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
525 return ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
526
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
527 # check for a newline already in buffer
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
528 nl, nllen = self._checkfornewline()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
529
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
530 if nl >= 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
531 # the next line was already in the buffer
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
532 nl = min(nl, size)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
533 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
534 # no line break in buffer - try to read more
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
535 size -= len(self.linebuffer)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
536 while nl < 0 and size > 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
537 buf = self.read(min(size, 100))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
538 if not buf:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
539 break
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
540 self.linebuffer += buf
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
541 size -= len(buf)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
542
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
543 # check for a newline in buffer
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
544 nl, nllen = self._checkfornewline()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
545
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
546 # we either ran out of bytes in the file, or
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
547 # met the specified size limit without finding a newline,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
548 # so return current buffer
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
549 if nl < 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
550 s = self.linebuffer
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
551 self.linebuffer = ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
552 return s
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
553
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
554 buf = self.linebuffer[:nl]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
555 self.lastdiscard = self.linebuffer[nl:nl + nllen]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
556 self.linebuffer = self.linebuffer[nl + nllen:]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
557
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
558 # line is always returned with \n as newline char (except possibly
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
559 # for a final incomplete line in the file, which is handled above).
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
560 return buf + "\n"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
561
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
562 def readlines(self, sizehint = -1):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
563 """Return a list with all (following) lines. The sizehint parameter
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
564 is ignored in this implementation.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
565 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
566 result = []
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
567 while True:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
568 line = self.readline()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
569 if not line: break
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
570 result.append(line)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
571 return result
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
572
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
573 def read(self, size = None):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
574 # act like file() obj and return empty string if size is 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
575 if size == 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
576 return ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
577
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
578 # determine read size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
579 bytesToRead = self.compress_size - self.bytes_read
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
580
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
581 # adjust read size for encrypted files since the first 12 bytes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
582 # are for the encryption/password information
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
583 if self.decrypter is not None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
584 bytesToRead -= 12
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
585
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
586 if size is not None and size >= 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
587 if self.compress_type == ZIP_STORED:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
588 lr = len(self.readbuffer)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
589 bytesToRead = min(bytesToRead, size - lr)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
590 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
591 if len(self.readbuffer) > size:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
592 # the user has requested fewer bytes than we've already
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
593 # pulled through the decompressor; don't read any more
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
594 bytesToRead = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
595 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
596 # user will use up the buffer, so read some more
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
597 lr = len(self.rawbuffer)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
598 bytesToRead = min(bytesToRead, self.compreadsize - lr)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
599
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
600 # avoid reading past end of file contents
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
601 if bytesToRead + self.bytes_read > self.compress_size:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
602 bytesToRead = self.compress_size - self.bytes_read
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
603
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
604 # try to read from file (if necessary)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
605 if bytesToRead > 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
606 bytes = self.fileobj.read(bytesToRead)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
607 self.bytes_read += len(bytes)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
608 self.rawbuffer += bytes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
609
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
610 # handle contents of raw buffer
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
611 if self.rawbuffer:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
612 newdata = self.rawbuffer
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
613 self.rawbuffer = ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
614
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
615 # decrypt new data if we were given an object to handle that
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
616 if newdata and self.decrypter is not None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
617 newdata = ''.join(map(self.decrypter, newdata))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
618
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
619 # decompress newly read data if necessary
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
620 if newdata and self.compress_type != ZIP_STORED:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
621 newdata = self.dc.decompress(newdata)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
622 self.rawbuffer = self.dc.unconsumed_tail if self.compress_type == ZIP_DEFLATED else ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
623 if self.eof and len(self.rawbuffer) == 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
624 # we're out of raw bytes (both from the file and
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
625 # the local buffer); flush just to make sure the
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
626 # decompressor is done
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
627 newdata += self.dc.flush()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
628 # prevent decompressor from being used again
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
629 self.dc = None
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
630
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
631 self.readbuffer += newdata
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
632
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
633
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
634 # return what the user asked for
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
635 if size is None or len(self.readbuffer) <= size:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
636 bytes = self.readbuffer
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
637 self.readbuffer = ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
638 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
639 bytes = self.readbuffer[:size]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
640 self.readbuffer = self.readbuffer[size:]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
641
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
642 return bytes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
643
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
644
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
645 class ZipFile:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
646 """ Class with methods to open, read, write, close, list zip files.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
647
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
648 z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
649
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
650 file: Either the path to the file, or a file-like object.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
651 If it is a path, the file will be opened and closed by ZipFile.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
652 mode: The mode can be either read "r", write "w" or append "a".
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
653 compression: ZIP_STORED (no compression), ZIP_DEFLATED (requires zlib) or ZIP_BZIP2 (requires bz2).
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
654 allowZip64: if True ZipFile will create files with ZIP64 extensions when
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
655 needed, otherwise it will raise an exception when this would
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
656 be necessary.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
657
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
658 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
659
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
660 fp = None # Set here since __del__ checks it
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
661
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
662 def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
663 """Open the ZIP file with mode read "r", write "w" or append "a"."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
664 if mode not in ("r", "w", "a"):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
665 raise RuntimeError('ZipFile() requires mode "r", "w", or "a"')
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
666
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
667 if compression == ZIP_STORED:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
668 pass
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
669 elif compression == ZIP_DEFLATED:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
670 if not zlib:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
671 raise RuntimeError,\
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
672 "Compression requires the (missing) zlib module"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
673 elif compression == ZIP_BZIP2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
674 if not bz2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
675 raise RuntimeError,\
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
676 "Compression requires the (missing) bz2 module"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
677 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
678 raise RuntimeError, "That compression method is not supported"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
679
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
680 self._allowZip64 = allowZip64
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
681 self._didModify = False
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
682 self.debug = 0 # Level of printing: 0 through 3
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
683 self.NameToInfo = {} # Find file info given name
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
684 self.filelist = [] # List of ZipInfo instances for archive
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
685 self.compression = compression # Method of compression
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
686 self.mode = key = mode.replace('b', '')[0]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
687 self.pwd = None
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
688 self.comment = ''
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
689
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
690 # Check if we were passed a file-like object
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
691 if isinstance(file, basestring):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
692 self._filePassed = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
693 self.filename = file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
694 modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
695 try:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
696 self.fp = open(file, modeDict[mode])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
697 except IOError:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
698 if mode == 'a':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
699 mode = key = 'w'
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
700 self.fp = open(file, modeDict[mode])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
701 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
702 raise
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
703 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
704 self._filePassed = 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
705 self.fp = file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
706 self.filename = getattr(file, 'name', None)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
707
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
708 if key == 'r':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
709 self._GetContents()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
710 elif key == 'w':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
711 pass
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
712 elif key == 'a':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
713 try: # See if file is a zip file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
714 self._RealGetContents()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
715 # seek to start of directory and overwrite
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
716 self.fp.seek(self.start_dir, 0)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
717 except BadZipfile: # file is not a zip file, just append
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
718 self.fp.seek(0, 2)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
719 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
720 if not self._filePassed:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
721 self.fp.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
722 self.fp = None
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
723 raise RuntimeError, 'Mode must be "r", "w" or "a"'
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
724
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
725 def _GetContents(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
726 """Read the directory, making sure we close the file if the format
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
727 is bad."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
728 try:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
729 self._RealGetContents()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
730 except BadZipfile:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
731 if not self._filePassed:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
732 self.fp.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
733 self.fp = None
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
734 raise
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
735
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
736 def _RealGetContents(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
737 """Read in the table of contents for the ZIP file."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
738 fp = self.fp
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
739 endrec = _EndRecData(fp)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
740 if not endrec:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
741 raise BadZipfile, "File is not a zip file"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
742 if self.debug > 1:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
743 print endrec
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
744 size_cd = endrec[_ECD_SIZE] # bytes in central directory
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
745 offset_cd = endrec[_ECD_OFFSET] # offset of central directory
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
746 self.comment = endrec[_ECD_COMMENT] # archive comment
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
747
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
748 # "concat" is zero, unless zip was concatenated to another file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
749 concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
750 if endrec[_ECD_SIGNATURE] == stringEndArchive64:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
751 # If Zip64 extension structures are present, account for them
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
752 concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
753
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
754 if self.debug > 2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
755 inferred = concat + offset_cd
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
756 print "given, inferred, offset", offset_cd, inferred, concat
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
757 # self.start_dir: Position of start of central directory
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
758 self.start_dir = offset_cd + concat
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
759 fp.seek(self.start_dir, 0)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
760 data = fp.read(size_cd)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
761 fp = cStringIO.StringIO(data)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
762 total = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
763 while total < size_cd:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
764 centdir = fp.read(sizeCentralDir)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
765 if centdir[0:4] != stringCentralDir:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
766 raise BadZipfile, "Bad magic number for central directory"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
767 centdir = struct.unpack(structCentralDir, centdir)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
768 if self.debug > 2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
769 print centdir
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
770 filename = fp.read(centdir[_CD_FILENAME_LENGTH])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
771 # Create ZipInfo instance to store file information
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
772 x = ZipInfo(filename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
773 x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
774 x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
775 x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
776 (x.create_version, x.create_system, x.extract_version, x.reserved,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
777 x.flag_bits, x.compress_type, t, d,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
778 x.CRC, x.compress_size, x.file_size) = centdir[1:12]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
779 x.volume, x.internal_attr, x.external_attr = centdir[15:18]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
780 # Convert date/time code to (year, month, day, hour, min, sec)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
781 x._raw_time = t
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
782 x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
783 t>>11, (t>>5)&0x3F, (t&0x1F) * 2 )
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
784
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
785 x._decodeExtra()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
786 x.header_offset = x.header_offset + concat
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
787 x.filename = x._decodeFilename()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
788 self.filelist.append(x)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
789 self.NameToInfo[x.filename] = x
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
790
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
791 # update total bytes read from central directory
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
792 total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
793 + centdir[_CD_EXTRA_FIELD_LENGTH]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
794 + centdir[_CD_COMMENT_LENGTH])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
795
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
796 if self.debug > 2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
797 print "total", total
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
798
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
799
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
800 def namelist(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
801 """Return a list of file names in the archive."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
802 l = []
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
803 for data in self.filelist:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
804 l.append(data.filename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
805 return l
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
806
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
807 def infolist(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
808 """Return a list of class ZipInfo instances for files in the
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
809 archive."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
810 return self.filelist
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
811
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
812 def printdir(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
813 """Print a table of contents for the zip file."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
814 print "%-46s %19s %12s" % ("File Name", "Modified ", "Size")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
815 for zinfo in self.filelist:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
816 date = "%d-%02d-%02d %02d:%02d:%02d" % zinfo.date_time[:6]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
817 print "%-46s %s %12d" % (zinfo.filename, date, zinfo.file_size)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
818
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
819 def testzip(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
820 """Read all the files and check the CRC."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
821 chunk_size = 2 ** 20
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
822 for zinfo in self.filelist:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
823 try:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
824 # Read by chunks, to avoid an OverflowError or a
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
825 # MemoryError with very large embedded files.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
826 f = self.open(zinfo.filename, "r")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
827 while f.read(chunk_size): # Check CRC-32
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
828 pass
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
829 except BadZipfile:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
830 return zinfo.filename
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
831
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
832 def getinfo(self, name):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
833 """Return the instance of ZipInfo given 'name'."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
834 info = self.NameToInfo.get(name)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
835 if info is None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
836 raise KeyError(
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
837 'There is no item named %r in the archive' % name)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
838
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
839 return info
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
840
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
841 def setpassword(self, pwd):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
842 """Set default password for encrypted files."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
843 self.pwd = pwd
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
844
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
845 def read(self, name, pwd=None):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
846 """Return file bytes (as a string) for name."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
847 return self.open(name, "r", pwd).read()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
848
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
849 def open(self, name, mode="r", pwd=None):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
850 """Return file-like object for 'name'."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
851 if mode not in ("r", "U", "rU"):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
852 raise RuntimeError, 'open() requires mode "r", "U", or "rU"'
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
853 if not self.fp:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
854 raise RuntimeError, \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
855 "Attempt to read ZIP archive that was already closed"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
856
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
857 # Only open a new file for instances where we were not
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
858 # given a file object in the constructor
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
859 if self._filePassed:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
860 zef_file = self.fp
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
861 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
862 zef_file = open(self.filename, 'rb')
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
863
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
864 # Make sure we have an info object
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
865 if isinstance(name, ZipInfo):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
866 # 'name' is already an info object
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
867 zinfo = name
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
868 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
869 # Get info object for name
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
870 zinfo = self.getinfo(name)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
871
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
872 zef_file.seek(zinfo.header_offset, 0)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
873
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
874 # Skip the file header:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
875 fheader = zef_file.read(sizeFileHeader)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
876 if fheader[0:4] != stringFileHeader:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
877 raise BadZipfile, "Bad magic number for file header"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
878
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
879 fheader = struct.unpack(structFileHeader, fheader)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
880 fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
881 if fheader[_FH_EXTRA_FIELD_LENGTH]:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
882 zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
883
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
884 if fname != zinfo.orig_filename:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
885 raise BadZipfile, \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
886 'File name in directory "%s" and header "%s" differ.' % (
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
887 zinfo.orig_filename, fname)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
888
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
889 # check for encrypted flag & handle password
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
890 is_encrypted = zinfo.flag_bits & 0x1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
891 zd = None
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
892 if is_encrypted:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
893 if not pwd:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
894 pwd = self.pwd
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
895 if not pwd:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
896 raise RuntimeError, "File %s is encrypted, " \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
897 "password required for extraction" % name
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
898
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
899 zd = _ZipDecrypter(pwd)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
900 # The first 12 bytes in the cypher stream is an encryption header
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
901 # used to strengthen the algorithm. The first 11 bytes are
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
902 # completely random, while the 12th contains the MSB of the CRC,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
903 # or the MSB of the file time depending on the header type
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
904 # and is used to check the correctness of the password.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
905 bytes = zef_file.read(12)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
906 h = map(zd, bytes[0:12])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
907 if zinfo.flag_bits & 0x8:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
908 # compare against the file type from extended local headers
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
909 check_byte = (zinfo._raw_time >> 8) & 0xff
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
910 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
911 # compare against the CRC otherwise
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
912 check_byte = (zinfo.CRC >> 24) & 0xff
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
913 if ord(h[11]) != check_byte:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
914 raise RuntimeError("Bad password for file", name)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
915
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
916 # build and return a ZipExtFile
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
917 if zd is None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
918 zef = ZipExtFile(zef_file, zinfo)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
919 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
920 zef = ZipExtFile(zef_file, zinfo, zd)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
921
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
922 # set universal newlines on ZipExtFile if necessary
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
923 if "U" in mode:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
924 zef.set_univ_newlines(True)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
925 return zef
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
926
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
927 def extract(self, member, path=None, pwd=None):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
928 """Extract a member from the archive to the current working directory,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
929 using its full name. Its file information is extracted as accurately
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
930 as possible. `member' may be a filename or a ZipInfo object. You can
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
931 specify a different directory using `path'.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
932 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
933 if not isinstance(member, ZipInfo):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
934 member = self.getinfo(member)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
935
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
936 if path is None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
937 path = os.getcwd()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
938
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
939 return self._extract_member(member, path, pwd)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
940
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
941 def extractall(self, path=None, members=None, pwd=None):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
942 """Extract all members from the archive to the current working
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
943 directory. `path' specifies a different directory to extract to.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
944 `members' is optional and must be a subset of the list returned
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
945 by namelist().
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
946 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
947 if members is None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
948 members = self.namelist()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
949
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
950 for zipinfo in members:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
951 self.extract(zipinfo, path, pwd)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
952
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
953 def _extract_member(self, member, targetpath, pwd):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
954 """Extract the ZipInfo object 'member' to a physical
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
955 file on the path targetpath.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
956 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
957 # build the destination pathname, replacing
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
958 # forward slashes to platform specific separators.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
959 # Strip trailing path separator, unless it represents the root.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
960 if (targetpath[-1:] in (os.path.sep, os.path.altsep)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
961 and len(os.path.splitdrive(targetpath)[1]) > 1):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
962 targetpath = targetpath[:-1]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
963
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
964 # don't include leading "/" from file name if present
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
965 if member.filename[0] == '/':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
966 targetpath = os.path.join(targetpath, member.filename[1:])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
967 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
968 targetpath = os.path.join(targetpath, member.filename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
969
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
970 targetpath = os.path.normpath(targetpath)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
971
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
972 # Create all upper directories if necessary.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
973 upperdirs = os.path.dirname(targetpath)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
974 if upperdirs and not os.path.exists(upperdirs):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
975 os.makedirs(upperdirs)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
976
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
977 if member.filename[-1] == '/':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
978 if not os.path.isdir(targetpath):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
979 os.mkdir(targetpath)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
980 return targetpath
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
981
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
982 source = self.open(member, pwd=pwd)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
983 target = file(targetpath, "wb")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
984 shutil.copyfileobj(source, target)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
985 source.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
986 target.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
987
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
988 return targetpath
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
989
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
990 def _writecheck(self, zinfo):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
991 """Check for errors before writing a file to the archive."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
992 if zinfo.filename in self.NameToInfo:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
993 if self.debug: # Warning for duplicate names
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
994 print "Duplicate name:", zinfo.filename
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
995 if self.mode not in ("w", "a"):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
996 raise RuntimeError, 'write() requires mode "w" or "a"'
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
997 if not self.fp:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
998 raise RuntimeError, \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
999 "Attempt to write ZIP archive that was already closed"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1000 if zinfo.compress_type == ZIP_DEFLATED and not zlib:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1001 raise RuntimeError, \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1002 "Compression requires the (missing) zlib module"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1003 if zinfo.compress_type == ZIP_BZIP2 and not bz2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1004 raise RuntimeError, \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1005 "Compression requires the (missing) bz2 module"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1006 if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED, ZIP_BZIP2):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1007 raise RuntimeError, \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1008 "That compression method is not supported"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1009 if zinfo.file_size > ZIP64_LIMIT:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1010 if not self._allowZip64:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1011 raise LargeZipFile("Filesize would require ZIP64 extensions")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1012 if zinfo.header_offset > ZIP64_LIMIT:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1013 if not self._allowZip64:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1014 raise LargeZipFile("Zipfile size would require ZIP64 extensions")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1015
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1016 def write(self, filename, arcname=None, compress_type=None):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1017 """Put the bytes from filename into the archive under the name
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1018 arcname."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1019 if not self.fp:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1020 raise RuntimeError(
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1021 "Attempt to write to ZIP archive that was already closed")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1022
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1023 st = os.stat(filename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1024 isdir = stat.S_ISDIR(st.st_mode)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1025 mtime = time.localtime(st.st_mtime)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1026 date_time = mtime[0:6]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1027 # Create ZipInfo instance to store file information
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1028 if arcname is None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1029 arcname = filename
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1030 arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1031 while arcname[0] in (os.sep, os.altsep):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1032 arcname = arcname[1:]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1033 if isdir:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1034 arcname += '/'
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1035 zinfo = ZipInfo(arcname, date_time)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1036 zinfo.external_attr = (st[0] & 0xFFFF) << 16L # Unix attributes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1037 if compress_type is None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1038 zinfo.compress_type = self.compression
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1039 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1040 zinfo.compress_type = compress_type
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1041
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1042 zinfo.file_size = st.st_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1043 zinfo.flag_bits = 0x00
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1044 zinfo.header_offset = self.fp.tell() # Start of header bytes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1045
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1046 self._writecheck(zinfo)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1047 self._didModify = True
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1048
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1049 if isdir:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1050 zinfo.file_size = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1051 zinfo.compress_size = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1052 zinfo.CRC = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1053 self.filelist.append(zinfo)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1054 self.NameToInfo[zinfo.filename] = zinfo
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1055 self.fp.write(zinfo.FileHeader())
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1056 return
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1057
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1058 fp = open(filename, "rb")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1059 # Must overwrite CRC and sizes with correct data later
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1060 zinfo.CRC = CRC = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1061 zinfo.compress_size = compress_size = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1062 zinfo.file_size = file_size = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1063 self.fp.write(zinfo.FileHeader())
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1064 if zinfo.compress_type == ZIP_DEFLATED:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1065 cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1066 zlib.DEFLATED, -15)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1067 elif zinfo.compress_type == ZIP_BZIP2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1068 cmpr = bz2.BZ2Compressor()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1069 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1070 cmpr = None
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1071 while 1:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1072 buf = fp.read(1024 * 8)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1073 if not buf:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1074 break
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1075 file_size = file_size + len(buf)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1076 CRC = crc32(buf, CRC) & 0xffffffff
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1077 if cmpr:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1078 buf = cmpr.compress(buf)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1079 compress_size = compress_size + len(buf)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1080 self.fp.write(buf)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1081 fp.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1082 if cmpr:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1083 buf = cmpr.flush()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1084 compress_size = compress_size + len(buf)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1085 self.fp.write(buf)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1086 zinfo.compress_size = compress_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1087 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1088 zinfo.compress_size = file_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1089 zinfo.CRC = CRC
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1090 zinfo.file_size = file_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1091 # Seek backwards and write CRC and file sizes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1092 position = self.fp.tell() # Preserve current position in file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1093 self.fp.seek(zinfo.header_offset + 14, 0)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1094 self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1095 zinfo.file_size))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1096 self.fp.seek(position, 0)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1097 self.filelist.append(zinfo)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1098 self.NameToInfo[zinfo.filename] = zinfo
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1099
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1100 def writestr(self, zinfo_or_arcname, bytes):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1101 """Write a file into the archive. The contents is the string
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1102 'bytes'. 'zinfo_or_arcname' is either a ZipInfo instance or
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1103 the name of the file in the archive."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1104 if not isinstance(zinfo_or_arcname, ZipInfo):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1105 zinfo = ZipInfo(filename=zinfo_or_arcname,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1106 date_time=time.localtime(time.time())[:6])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1107 zinfo.compress_type = self.compression
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1108 zinfo.external_attr = 0600 << 16
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1109 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1110 zinfo = zinfo_or_arcname
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1111
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1112 if not self.fp:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1113 raise RuntimeError(
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1114 "Attempt to write to ZIP archive that was already closed")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1115
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1116 zinfo.file_size = len(bytes) # Uncompressed size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1117 zinfo.header_offset = self.fp.tell() # Start of header bytes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1118 self._writecheck(zinfo)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1119 self._didModify = True
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1120 zinfo.CRC = crc32(bytes) & 0xffffffff # CRC-32 checksum
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1121 if zinfo.compress_type == ZIP_DEFLATED:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1122 co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1123 zlib.DEFLATED, -15)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1124 bytes = co.compress(bytes) + co.flush()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1125 zinfo.compress_size = len(bytes) # Compressed size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1126 elif zinfo.compress_type == ZIP_BZIP2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1127 co = bz2.BZ2Compressor()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1128 bytes = co.compress(bytes) + co.flush()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1129 zinfo.compress_size = len(bytes) # Compressed size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1130 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1131 zinfo.compress_size = zinfo.file_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1132 zinfo.header_offset = self.fp.tell() # Start of header bytes
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1133 self.fp.write(zinfo.FileHeader())
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1134 self.fp.write(bytes)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1135 self.fp.flush()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1136 if zinfo.flag_bits & 0x08:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1137 # Write CRC and file sizes after the file data
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1138 self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1139 zinfo.file_size))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1140 self.filelist.append(zinfo)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1141 self.NameToInfo[zinfo.filename] = zinfo
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1142
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1143 def __del__(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1144 """Call the "close()" method in case the user forgot."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1145 self.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1146
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1147 def close(self):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1148 """Close the file, and for mode "w" and "a" write the ending
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1149 records."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1150 if self.fp is None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1151 return
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1152
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1153 if self.mode in ("w", "a") and self._didModify: # write ending records
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1154 count = 0
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1155 pos1 = self.fp.tell()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1156 for zinfo in self.filelist: # write central directory
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1157 count = count + 1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1158 dt = zinfo.date_time
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1159 dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1160 dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1161 extra = []
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1162 if zinfo.file_size > ZIP64_LIMIT \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1163 or zinfo.compress_size > ZIP64_LIMIT:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1164 extra.append(zinfo.file_size)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1165 extra.append(zinfo.compress_size)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1166 file_size = 0xffffffff
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1167 compress_size = 0xffffffff
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1168 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1169 file_size = zinfo.file_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1170 compress_size = zinfo.compress_size
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1171
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1172 if zinfo.header_offset > ZIP64_LIMIT:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1173 extra.append(zinfo.header_offset)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1174 header_offset = 0xffffffffL
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1175 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1176 header_offset = zinfo.header_offset
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1177
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1178 extra_data = zinfo.extra
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1179 if extra:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1180 # Append a ZIP64 field to the extra's
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1181 extra_data = struct.pack(
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1182 '<HH' + 'Q'*len(extra),
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1183 1, 8*len(extra), *extra) + extra_data
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1184
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1185 extract_version = max(45, zinfo.extract_version)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1186 create_version = max(45, zinfo.create_version)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1187 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1188 extract_version = zinfo.extract_version
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1189 create_version = zinfo.create_version
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1190
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1191 try:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1192 filename, flag_bits = zinfo._encodeFilenameFlags()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1193 centdir = struct.pack(structCentralDir,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1194 stringCentralDir, create_version,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1195 zinfo.create_system, extract_version, zinfo.reserved,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1196 flag_bits, zinfo.compress_type, dostime, dosdate,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1197 zinfo.CRC, compress_size, file_size,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1198 len(filename), len(extra_data), len(zinfo.comment),
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1199 0, zinfo.internal_attr, zinfo.external_attr,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1200 header_offset)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1201 except DeprecationWarning:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1202 print >>sys.stderr, (structCentralDir,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1203 stringCentralDir, create_version,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1204 zinfo.create_system, extract_version, zinfo.reserved,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1205 zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1206 zinfo.CRC, compress_size, file_size,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1207 len(zinfo.filename), len(extra_data), len(zinfo.comment),
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1208 0, zinfo.internal_attr, zinfo.external_attr,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1209 header_offset)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1210 raise
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1211 self.fp.write(centdir)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1212 self.fp.write(filename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1213 self.fp.write(extra_data)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1214 self.fp.write(zinfo.comment)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1215
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1216 pos2 = self.fp.tell()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1217 # Write end-of-zip-archive record
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1218 centDirCount = count
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1219 centDirSize = pos2 - pos1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1220 centDirOffset = pos1
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1221 if (centDirCount >= ZIP_FILECOUNT_LIMIT or
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1222 centDirOffset > ZIP64_LIMIT or
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1223 centDirSize > ZIP64_LIMIT):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1224 # Need to write the ZIP64 end-of-archive records
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1225 zip64endrec = struct.pack(
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1226 structEndArchive64, stringEndArchive64,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1227 44, 45, 45, 0, 0, centDirCount, centDirCount,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1228 centDirSize, centDirOffset)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1229 self.fp.write(zip64endrec)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1230
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1231 zip64locrec = struct.pack(
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1232 structEndArchive64Locator,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1233 stringEndArchive64Locator, 0, pos2, 1)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1234 self.fp.write(zip64locrec)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1235 centDirCount = min(centDirCount, 0xFFFF)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1236 centDirSize = min(centDirSize, 0xFFFFFFFF)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1237 centDirOffset = min(centDirOffset, 0xFFFFFFFF)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1238
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1239 # check for valid comment length
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1240 if len(self.comment) >= ZIP_MAX_COMMENT:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1241 if self.debug > 0:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1242 msg = 'Archive comment is too long; truncating to %d bytes' \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1243 % ZIP_MAX_COMMENT
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1244 self.comment = self.comment[:ZIP_MAX_COMMENT]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1245
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1246 endrec = struct.pack(structEndArchive, stringEndArchive,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1247 0, 0, centDirCount, centDirCount,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1248 centDirSize, centDirOffset, len(self.comment))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1249 self.fp.write(endrec)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1250 self.fp.write(self.comment)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1251 self.fp.flush()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1252
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1253 if not self._filePassed:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1254 self.fp.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1255 self.fp = None
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1256
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1257
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1258 class PyZipFile(ZipFile):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1259 """Class to create ZIP archives with Python library files and packages."""
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1260
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1261 def writepy(self, pathname, basename = ""):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1262 """Add all files from "pathname" to the ZIP archive.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1263
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1264 If pathname is a package directory, search the directory and
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1265 all package subdirectories recursively for all *.py and enter
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1266 the modules into the archive. If pathname is a plain
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1267 directory, listdir *.py and enter all modules. Else, pathname
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1268 must be a Python *.py file and the module will be put into the
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1269 archive. Added modules are always module.pyo or module.pyc.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1270 This method will compile the module.py into module.pyc if
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1271 necessary.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1272 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1273 dir, name = os.path.split(pathname)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1274 if os.path.isdir(pathname):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1275 initname = os.path.join(pathname, "__init__.py")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1276 if os.path.isfile(initname):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1277 # This is a package directory, add it
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1278 if basename:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1279 basename = "%s/%s" % (basename, name)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1280 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1281 basename = name
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1282 if self.debug:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1283 print "Adding package in", pathname, "as", basename
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1284 fname, arcname = self._get_codename(initname[0:-3], basename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1285 if self.debug:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1286 print "Adding", arcname
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1287 self.write(fname, arcname)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1288 dirlist = os.listdir(pathname)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1289 dirlist.remove("__init__.py")
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1290 # Add all *.py files and package subdirectories
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1291 for filename in dirlist:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1292 path = os.path.join(pathname, filename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1293 root, ext = os.path.splitext(filename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1294 if os.path.isdir(path):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1295 if os.path.isfile(os.path.join(path, "__init__.py")):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1296 # This is a package directory, add it
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1297 self.writepy(path, basename) # Recursive call
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1298 elif ext == ".py":
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1299 fname, arcname = self._get_codename(path[0:-3],
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1300 basename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1301 if self.debug:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1302 print "Adding", arcname
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1303 self.write(fname, arcname)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1304 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1305 # This is NOT a package directory, add its files at top level
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1306 if self.debug:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1307 print "Adding files from directory", pathname
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1308 for filename in os.listdir(pathname):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1309 path = os.path.join(pathname, filename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1310 root, ext = os.path.splitext(filename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1311 if ext == ".py":
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1312 fname, arcname = self._get_codename(path[0:-3],
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1313 basename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1314 if self.debug:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1315 print "Adding", arcname
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1316 self.write(fname, arcname)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1317 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1318 if pathname[-3:] != ".py":
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1319 raise RuntimeError, \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1320 'Files added with writepy() must end with ".py"'
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1321 fname, arcname = self._get_codename(pathname[0:-3], basename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1322 if self.debug:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1323 print "Adding file", arcname
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1324 self.write(fname, arcname)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1325
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1326 def _get_codename(self, pathname, basename):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1327 """Return (filename, archivename) for the path.
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1328
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1329 Given a module name path, return the correct file path and
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1330 archive name, compiling if necessary. For example, given
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1331 /python/lib/string, return (/python/lib/string.pyc, string).
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1332 """
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1333 file_py = pathname + ".py"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1334 file_pyc = pathname + ".pyc"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1335 file_pyo = pathname + ".pyo"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1336 if os.path.isfile(file_pyo) and \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1337 os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1338 fname = file_pyo # Use .pyo file
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1339 elif not os.path.isfile(file_pyc) or \
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1340 os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1341 import py_compile
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1342 if self.debug:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1343 print "Compiling", file_py
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1344 try:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1345 py_compile.compile(file_py, file_pyc, None, True)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1346 except py_compile.PyCompileError,err:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1347 print err.msg
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1348 fname = file_pyc
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1349 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1350 fname = file_pyc
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1351 archivename = os.path.split(fname)[1]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1352 if basename:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1353 archivename = "%s/%s" % (basename, archivename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1354 return (fname, archivename)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1355
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1356
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1357 def main(args = None):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1358 import textwrap
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1359 USAGE=textwrap.dedent("""\
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1360 Usage:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1361 zipfile.py -l zipfile.zip # Show listing of a zipfile
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1362 zipfile.py -t zipfile.zip # Test if a zipfile is valid
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1363 zipfile.py -e zipfile.zip target # Extract zipfile into target dir
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1364 zipfile.py -c zipfile.zip src ... # Create zipfile from sources
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1365 """)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1366 if args is None:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1367 args = sys.argv[1:]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1368
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1369 if not args or args[0] not in ('-l', '-c', '-e', '-t'):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1370 print USAGE
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1371 sys.exit(1)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1372
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1373 if args[0] == '-l':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1374 if len(args) != 2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1375 print USAGE
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1376 sys.exit(1)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1377 zf = ZipFile(args[1], 'r')
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1378 zf.printdir()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1379 zf.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1380
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1381 elif args[0] == '-t':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1382 if len(args) != 2:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1383 print USAGE
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1384 sys.exit(1)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1385 zf = ZipFile(args[1], 'r')
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1386 zf.testzip()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1387 print "Done testing"
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1388
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1389 elif args[0] == '-e':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1390 if len(args) != 3:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1391 print USAGE
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1392 sys.exit(1)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1393
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1394 zf = ZipFile(args[1], 'r')
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1395 out = args[2]
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1396 for path in zf.namelist():
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1397 if path.startswith('./'):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1398 tgt = os.path.join(out, path[2:])
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1399 else:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1400 tgt = os.path.join(out, path)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1401
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1402 tgtdir = os.path.dirname(tgt)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1403 if not os.path.exists(tgtdir):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1404 os.makedirs(tgtdir)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1405 fp = open(tgt, 'wb')
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1406 fp.write(zf.read(path))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1407 fp.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1408 zf.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1409
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1410 elif args[0] == '-c':
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1411 if len(args) < 3:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1412 print USAGE
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1413 sys.exit(1)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1414
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1415 def addToZip(zf, path, zippath):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1416 if os.path.isfile(path):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1417 zf.write(path, zippath, ZIP_DEFLATED)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1418 elif os.path.isdir(path):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1419 for nm in os.listdir(path):
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1420 addToZip(zf,
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1421 os.path.join(path, nm), os.path.join(zippath, nm))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1422 # else: ignore
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1423
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1424 zf = ZipFile(args[1], 'w', allowZip64=True)
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1425 for src in args[2:]:
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1426 addToZip(zf, src, os.path.basename(src))
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1427
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1428 zf.close()
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1429
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1430 if __name__ == "__main__":
a99db3631d10 1.20 directory created
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
1431 main()