annotate zipfile26.py @ 80:809b77302b21

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