home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_2882 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  30.8 KB  |  1,038 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import struct
  5. import os
  6. import time
  7. import sys
  8. import shutil
  9. import binascii
  10. import cStringIO
  11. import stat
  12.  
  13. try:
  14.     import zlib
  15.     crc32 = zlib.crc32
  16. except ImportError:
  17.     zlib = None
  18.     crc32 = binascii.crc32
  19.  
  20. __all__ = [
  21.     'BadZipfile',
  22.     'error',
  23.     'ZIP_STORED',
  24.     'ZIP_DEFLATED',
  25.     'is_zipfile',
  26.     'ZipInfo',
  27.     'ZipFile',
  28.     'PyZipFile',
  29.     'LargeZipFile']
  30.  
  31. class BadZipfile(Exception):
  32.     pass
  33.  
  34.  
  35. class LargeZipFile(Exception):
  36.     pass
  37.  
  38. error = BadZipfile
  39. ZIP64_LIMIT = (1 << 31) - 1
  40. ZIP_FILECOUNT_LIMIT = 1 << 16
  41. ZIP_MAX_COMMENT = (1 << 16) - 1
  42. ZIP_STORED = 0
  43. ZIP_DEFLATED = 8
  44. structEndArchive = '<4s4H2LH'
  45. stringEndArchive = 'PK\x05\x06'
  46. sizeEndCentDir = struct.calcsize(structEndArchive)
  47. _ECD_SIGNATURE = 0
  48. _ECD_DISK_NUMBER = 1
  49. _ECD_DISK_START = 2
  50. _ECD_ENTRIES_THIS_DISK = 3
  51. _ECD_ENTRIES_TOTAL = 4
  52. _ECD_SIZE = 5
  53. _ECD_OFFSET = 6
  54. _ECD_COMMENT_SIZE = 7
  55. _ECD_COMMENT = 8
  56. _ECD_LOCATION = 9
  57. structCentralDir = '<4s4B4HL2L5H2L'
  58. stringCentralDir = 'PK\x01\x02'
  59. sizeCentralDir = struct.calcsize(structCentralDir)
  60. _CD_SIGNATURE = 0
  61. _CD_CREATE_VERSION = 1
  62. _CD_CREATE_SYSTEM = 2
  63. _CD_EXTRACT_VERSION = 3
  64. _CD_EXTRACT_SYSTEM = 4
  65. _CD_FLAG_BITS = 5
  66. _CD_COMPRESS_TYPE = 6
  67. _CD_TIME = 7
  68. _CD_DATE = 8
  69. _CD_CRC = 9
  70. _CD_COMPRESSED_SIZE = 10
  71. _CD_UNCOMPRESSED_SIZE = 11
  72. _CD_FILENAME_LENGTH = 12
  73. _CD_EXTRA_FIELD_LENGTH = 13
  74. _CD_COMMENT_LENGTH = 14
  75. _CD_DISK_NUMBER_START = 15
  76. _CD_INTERNAL_FILE_ATTRIBUTES = 16
  77. _CD_EXTERNAL_FILE_ATTRIBUTES = 17
  78. _CD_LOCAL_HEADER_OFFSET = 18
  79. structFileHeader = '<4s2B4HL2L2H'
  80. stringFileHeader = 'PK\x03\x04'
  81. sizeFileHeader = struct.calcsize(structFileHeader)
  82. _FH_SIGNATURE = 0
  83. _FH_EXTRACT_VERSION = 1
  84. _FH_EXTRACT_SYSTEM = 2
  85. _FH_GENERAL_PURPOSE_FLAG_BITS = 3
  86. _FH_COMPRESSION_METHOD = 4
  87. _FH_LAST_MOD_TIME = 5
  88. _FH_LAST_MOD_DATE = 6
  89. _FH_CRC = 7
  90. _FH_COMPRESSED_SIZE = 8
  91. _FH_UNCOMPRESSED_SIZE = 9
  92. _FH_FILENAME_LENGTH = 10
  93. _FH_EXTRA_FIELD_LENGTH = 11
  94. structEndArchive64Locator = '<4sLQL'
  95. stringEndArchive64Locator = 'PK\x06\x07'
  96. sizeEndCentDir64Locator = struct.calcsize(structEndArchive64Locator)
  97. structEndArchive64 = '<4sQ2H2L4Q'
  98. stringEndArchive64 = 'PK\x06\x06'
  99. sizeEndCentDir64 = struct.calcsize(structEndArchive64)
  100. _CD64_SIGNATURE = 0
  101. _CD64_DIRECTORY_RECSIZE = 1
  102. _CD64_CREATE_VERSION = 2
  103. _CD64_EXTRACT_VERSION = 3
  104. _CD64_DISK_NUMBER = 4
  105. _CD64_DISK_NUMBER_START = 5
  106. _CD64_NUMBER_ENTRIES_THIS_DISK = 6
  107. _CD64_NUMBER_ENTRIES_TOTAL = 7
  108. _CD64_DIRECTORY_SIZE = 8
  109. _CD64_OFFSET_START_CENTDIR = 9
  110.  
  111. def is_zipfile(filename):
  112.     
  113.     try:
  114.         fpin = open(filename, 'rb')
  115.         endrec = _EndRecData(fpin)
  116.         fpin.close()
  117.         if endrec:
  118.             return True
  119.     except IOError:
  120.         pass
  121.  
  122.     return False
  123.  
  124.  
  125. def _EndRecData64(fpin, offset, endrec):
  126.     fpin.seek(offset - sizeEndCentDir64Locator, 2)
  127.     data = fpin.read(sizeEndCentDir64Locator)
  128.     (sig, diskno, reloff, disks) = struct.unpack(structEndArchive64Locator, data)
  129.     if sig != stringEndArchive64Locator:
  130.         return endrec
  131.     if diskno != 0 or disks != 1:
  132.         raise BadZipfile('zipfiles that span multiple disks are not supported')
  133.     disks != 1
  134.     fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2)
  135.     data = fpin.read(sizeEndCentDir64)
  136.     (sig, sz, create_version, read_version, disk_num, disk_dir, dircount, dircount2, dirsize, diroffset) = struct.unpack(structEndArchive64, data)
  137.     if sig != stringEndArchive64:
  138.         return endrec
  139.     endrec[_ECD_SIGNATURE] = sig
  140.     endrec[_ECD_DISK_NUMBER] = disk_num
  141.     endrec[_ECD_DISK_START] = disk_dir
  142.     endrec[_ECD_ENTRIES_THIS_DISK] = dircount
  143.     endrec[_ECD_ENTRIES_TOTAL] = dircount2
  144.     endrec[_ECD_SIZE] = dirsize
  145.     endrec[_ECD_OFFSET] = diroffset
  146.     return endrec
  147.  
  148.  
  149. def _EndRecData(fpin):
  150.     fpin.seek(0, 2)
  151.     filesize = fpin.tell()
  152.     fpin.seek(-sizeEndCentDir, 2)
  153.     data = fpin.read()
  154.     if data[0:4] == stringEndArchive and data[-2:] == '\x00\x00':
  155.         endrec = struct.unpack(structEndArchive, data)
  156.         endrec = list(endrec)
  157.         endrec.append('')
  158.         endrec.append(filesize - sizeEndCentDir)
  159.         return _EndRecData64(fpin, -sizeEndCentDir, endrec)
  160.     maxCommentStart = max(filesize - 65536 - sizeEndCentDir, 0)
  161.     fpin.seek(maxCommentStart, 0)
  162.     data = fpin.read()
  163.     start = data.rfind(stringEndArchive)
  164.  
  165.  
  166. class ZipInfo(object):
  167.     __slots__ = ('orig_filename', 'filename', 'date_time', 'compress_type', 'comment', 'extra', 'create_system', 'create_version', 'extract_version', 'reserved', 'flag_bits', 'volume', 'internal_attr', 'external_attr', 'header_offset', 'CRC', 'compress_size', 'file_size', '_raw_time')
  168.     
  169.     def __init__(self, filename = 'NoName', date_time = (1980, 1, 1, 0, 0, 0)):
  170.         self.orig_filename = filename
  171.         null_byte = filename.find(chr(0))
  172.         if null_byte >= 0:
  173.             filename = filename[0:null_byte]
  174.         
  175.         if os.sep != '/' and os.sep in filename:
  176.             filename = filename.replace(os.sep, '/')
  177.         
  178.         self.filename = filename
  179.         self.date_time = date_time
  180.         self.compress_type = ZIP_STORED
  181.         self.comment = ''
  182.         self.extra = ''
  183.         if sys.platform == 'win32':
  184.             self.create_system = 0
  185.         else:
  186.             self.create_system = 3
  187.         self.create_version = 20
  188.         self.extract_version = 20
  189.         self.reserved = 0
  190.         self.flag_bits = 0
  191.         self.volume = 0
  192.         self.internal_attr = 0
  193.         self.external_attr = 0
  194.  
  195.     
  196.     def FileHeader(self):
  197.         dt = self.date_time
  198.         dosdate = dt[0] - 1980 << 9 | dt[1] << 5 | dt[2]
  199.         dostime = dt[3] << 11 | dt[4] << 5 | dt[5] // 2
  200.         if self.flag_bits & 8:
  201.             CRC = compress_size = file_size = 0
  202.         else:
  203.             CRC = self.CRC
  204.             compress_size = self.compress_size
  205.             file_size = self.file_size
  206.         extra = self.extra
  207.         if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
  208.             fmt = '<HHQQ'
  209.             extra = extra + struct.pack(fmt, 1, struct.calcsize(fmt) - 4, file_size, compress_size)
  210.             file_size = 0xFFFFFFFFL
  211.             compress_size = 0xFFFFFFFFL
  212.             self.extract_version = max(45, self.extract_version)
  213.             self.create_version = max(45, self.extract_version)
  214.         
  215.         (filename, flag_bits) = self._encodeFilenameFlags()
  216.         header = struct.pack(structFileHeader, stringFileHeader, self.extract_version, self.reserved, flag_bits, self.compress_type, dostime, dosdate, CRC, compress_size, file_size, len(filename), len(extra))
  217.         return header + filename + extra
  218.  
  219.     
  220.     def _encodeFilenameFlags(self):
  221.         if isinstance(self.filename, unicode):
  222.             
  223.             try:
  224.                 return (self.filename.encode('ascii'), self.flag_bits)
  225.             except UnicodeEncodeError:
  226.                 return (self.filename.encode('utf-8'), self.flag_bits | 2048)
  227.             
  228.  
  229.         None<EXCEPTION MATCH>UnicodeEncodeError
  230.         return (self.filename, self.flag_bits)
  231.  
  232.     
  233.     def _decodeFilename(self):
  234.         if self.flag_bits & 2048:
  235.             return self.filename.decode('utf-8')
  236.         return self.filename
  237.  
  238.     
  239.     def _decodeExtra(self):
  240.         extra = self.extra
  241.         unpack = struct.unpack
  242.         while extra:
  243.             (tp, ln) = unpack('<HH', extra[:4])
  244.             if tp == 1:
  245.                 if ln >= 24:
  246.                     counts = unpack('<QQQ', extra[4:28])
  247.                 elif ln == 16:
  248.                     counts = unpack('<QQ', extra[4:20])
  249.                 elif ln == 8:
  250.                     counts = unpack('<Q', extra[4:12])
  251.                 elif ln == 0:
  252.                     counts = ()
  253.                 else:
  254.                     raise RuntimeError, 'Corrupt extra field %s' % (ln,)
  255.                 idx = ln >= 24
  256.                 if self.file_size in (0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFL):
  257.                     self.file_size = counts[idx]
  258.                     idx += 1
  259.                 
  260.                 if self.compress_size == 0xFFFFFFFFL:
  261.                     self.compress_size = counts[idx]
  262.                     idx += 1
  263.                 
  264.                 if self.header_offset == 0xFFFFFFFFL:
  265.                     old = self.header_offset
  266.                     self.header_offset = counts[idx]
  267.                     idx += 1
  268.                 
  269.             
  270.             extra = extra[ln + 4:]
  271.  
  272.  
  273.  
  274. class _ZipDecrypter:
  275.     
  276.     def _GenerateCRCTable():
  277.         poly = 0xEDB88320L
  278.         table = [
  279.             0] * 256
  280.         for i in range(256):
  281.             crc = i
  282.             for j in range(8):
  283.                 if crc & 1:
  284.                     crc = crc >> 1 & 2147483647 ^ poly
  285.                     continue
  286.                 crc = crc >> 1 & 2147483647
  287.             
  288.             table[i] = crc
  289.         
  290.         return table
  291.  
  292.     crctable = _GenerateCRCTable()
  293.     
  294.     def _crc32(self, ch, crc):
  295.         return crc >> 8 & 16777215 ^ self.crctable[(crc ^ ord(ch)) & 255]
  296.  
  297.     
  298.     def __init__(self, pwd):
  299.         self.key0 = 305419896
  300.         self.key1 = 591751049
  301.         self.key2 = 878082192
  302.         for p in pwd:
  303.             self._UpdateKeys(p)
  304.         
  305.  
  306.     
  307.     def _UpdateKeys(self, c):
  308.         self.key0 = self._crc32(c, self.key0)
  309.         self.key1 = self.key1 + (self.key0 & 255) & 0xFFFFFFFFL
  310.         self.key1 = self.key1 * 134775813 + 1 & 0xFFFFFFFFL
  311.         self.key2 = self._crc32(chr(self.key1 >> 24 & 255), self.key2)
  312.  
  313.     
  314.     def __call__(self, c):
  315.         c = ord(c)
  316.         k = self.key2 | 2
  317.         c = c ^ k * (k ^ 1) >> 8 & 255
  318.         c = chr(c)
  319.         self._UpdateKeys(c)
  320.         return c
  321.  
  322.  
  323.  
  324. class ZipExtFile:
  325.     
  326.     def __init__(self, fileobj, zipinfo, decrypt = None):
  327.         self.fileobj = fileobj
  328.         self.decrypter = decrypt
  329.         self.bytes_read = 0x0L
  330.         self.rawbuffer = ''
  331.         self.readbuffer = ''
  332.         self.linebuffer = ''
  333.         self.eof = False
  334.         self.univ_newlines = False
  335.         self.nlSeps = ('\n',)
  336.         self.lastdiscard = ''
  337.         self.compress_type = zipinfo.compress_type
  338.         self.compress_size = zipinfo.compress_size
  339.         self.closed = False
  340.         self.mode = 'r'
  341.         self.name = zipinfo.filename
  342.         self.compreadsize = 65536
  343.         if self.compress_type == ZIP_DEFLATED:
  344.             self.dc = zlib.decompressobj(-15)
  345.         
  346.  
  347.     
  348.     def set_univ_newlines(self, univ_newlines):
  349.         self.univ_newlines = univ_newlines
  350.         self.nlSeps = ('\n',)
  351.         if self.univ_newlines:
  352.             self.nlSeps = ('\r\n', '\r', '\n')
  353.         
  354.  
  355.     
  356.     def __iter__(self):
  357.         return self
  358.  
  359.     
  360.     def next(self):
  361.         nextline = self.readline()
  362.         if not nextline:
  363.             raise StopIteration()
  364.         nextline
  365.         return nextline
  366.  
  367.     
  368.     def close(self):
  369.         self.closed = True
  370.  
  371.     
  372.     def _checkfornewline(self):
  373.         (nl, nllen) = (-1, -1)
  374.         if self.linebuffer:
  375.             if (self.lastdiscard, self.linebuffer[0]) == ('\r', '\n'):
  376.                 self.linebuffer = self.linebuffer[1:]
  377.             
  378.             for sep in self.nlSeps:
  379.                 nl = self.linebuffer.find(sep)
  380.                 if nl >= 0:
  381.                     nllen = len(sep)
  382.                     return (nl, nllen)
  383.             
  384.         
  385.         return (nl, nllen)
  386.  
  387.     
  388.     def readline(self, size = -1):
  389.         if size < 0:
  390.             size = sys.maxint
  391.         elif size == 0:
  392.             return ''
  393.         (nl, nllen) = self._checkfornewline()
  394.         buf = self.linebuffer[:nl]
  395.         self.lastdiscard = self.linebuffer[nl:nl + nllen]
  396.         self.linebuffer = self.linebuffer[nl + nllen:]
  397.         return buf + '\n'
  398.  
  399.     
  400.     def readlines(self, sizehint = -1):
  401.         result = []
  402.         while True:
  403.             line = self.readline()
  404.             if not line:
  405.                 break
  406.             
  407.             result.append(line)
  408.         return result
  409.  
  410.     
  411.     def read(self, size = None):
  412.         if size == 0:
  413.             return ''
  414.         bytesToRead = self.compress_size - self.bytes_read
  415.         if self.decrypter is not None:
  416.             bytesToRead -= 12
  417.         
  418.         if size is not None and size >= 0:
  419.             if self.compress_type == ZIP_STORED:
  420.                 lr = len(self.readbuffer)
  421.                 bytesToRead = min(bytesToRead, size - lr)
  422.             elif self.compress_type == ZIP_DEFLATED:
  423.                 if len(self.readbuffer) > size:
  424.                     bytesToRead = 0
  425.                 else:
  426.                     lr = len(self.rawbuffer)
  427.                     bytesToRead = min(bytesToRead, self.compreadsize - lr)
  428.             
  429.         
  430.         if bytesToRead + self.bytes_read > self.compress_size:
  431.             bytesToRead = self.compress_size - self.bytes_read
  432.         
  433.         if size is None or len(self.readbuffer) <= size:
  434.             bytes = self.readbuffer
  435.             self.readbuffer = ''
  436.         else:
  437.             bytes = self.readbuffer[:size]
  438.             self.readbuffer = self.readbuffer[size:]
  439.         return bytes
  440.  
  441.  
  442.  
  443. class ZipFile:
  444.     fp = None
  445.     
  446.     def __init__(self, file, mode = 'r', compression = ZIP_STORED, allowZip64 = False):
  447.         if mode not in ('r', 'w', 'a'):
  448.             raise RuntimeError('ZipFile() requires mode "r", "w", or "a"')
  449.         mode not in ('r', 'w', 'a')
  450.         if compression == ZIP_STORED:
  451.             pass
  452.         elif compression == ZIP_DEFLATED:
  453.             if not zlib:
  454.                 raise RuntimeError, 'Compression requires the (missing) zlib module'
  455.             zlib
  456.         else:
  457.             raise RuntimeError, 'That compression method is not supported'
  458.         self._allowZip64 = compression == ZIP_STORED
  459.         self._didModify = False
  460.         self.debug = 0
  461.         self.NameToInfo = { }
  462.         self.filelist = []
  463.         self.compression = compression
  464.         self.mode = key = mode.replace('b', '')[0]
  465.         self.pwd = None
  466.         self.comment = ''
  467.         if isinstance(file, basestring):
  468.             self._filePassed = 0
  469.             self.filename = file
  470.             modeDict = {
  471.                 'r': 'rb',
  472.                 'w': 'wb',
  473.                 'a': 'r+b' }
  474.             
  475.             try:
  476.                 self.fp = open(file, modeDict[mode])
  477.             except IOError:
  478.                 if mode == 'a':
  479.                     mode = key = 'w'
  480.                     self.fp = open(file, modeDict[mode])
  481.                 else:
  482.                     raise 
  483.                 mode == 'a'
  484.             
  485.  
  486.         None<EXCEPTION MATCH>IOError
  487.         self._filePassed = 1
  488.         self.fp = file
  489.         self.filename = getattr(file, 'name', None)
  490.         if key == 'r':
  491.             self._GetContents()
  492.         elif key == 'w':
  493.             pass
  494.         elif key == 'a':
  495.             
  496.             try:
  497.                 self._RealGetContents()
  498.                 self.fp.seek(self.start_dir, 0)
  499.             except BadZipfile:
  500.                 self.fp.seek(0, 2)
  501.             except:
  502.                 None<EXCEPTION MATCH>BadZipfile
  503.             
  504.  
  505.         None<EXCEPTION MATCH>BadZipfile
  506.         if not self._filePassed:
  507.             self.fp.close()
  508.             self.fp = None
  509.         
  510.         raise RuntimeError, 'Mode must be "r", "w" or "a"'
  511.  
  512.     
  513.     def _GetContents(self):
  514.         
  515.         try:
  516.             self._RealGetContents()
  517.         except BadZipfile:
  518.             if not self._filePassed:
  519.                 self.fp.close()
  520.                 self.fp = None
  521.             
  522.             raise 
  523.  
  524.  
  525.     
  526.     def _RealGetContents(self):
  527.         fp = self.fp
  528.         endrec = _EndRecData(fp)
  529.         if not endrec:
  530.             raise BadZipfile, 'File is not a zip file'
  531.         endrec
  532.         if self.debug > 1:
  533.             print endrec
  534.         
  535.         size_cd = endrec[_ECD_SIZE]
  536.         offset_cd = endrec[_ECD_OFFSET]
  537.         self.comment = endrec[_ECD_COMMENT]
  538.         concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
  539.         if endrec[_ECD_SIGNATURE] == stringEndArchive64:
  540.             concat -= sizeEndCentDir64 + sizeEndCentDir64Locator
  541.         
  542.         if self.debug > 2:
  543.             inferred = concat + offset_cd
  544.             print 'given, inferred, offset', offset_cd, inferred, concat
  545.         
  546.         self.start_dir = offset_cd + concat
  547.         fp.seek(self.start_dir, 0)
  548.         data = fp.read(size_cd)
  549.         fp = cStringIO.StringIO(data)
  550.         total = 0
  551.         while total < size_cd:
  552.             centdir = fp.read(sizeCentralDir)
  553.             if centdir[0:4] != stringCentralDir:
  554.                 raise BadZipfile, 'Bad magic number for central directory'
  555.             centdir[0:4] != stringCentralDir
  556.             centdir = struct.unpack(structCentralDir, centdir)
  557.             if self.debug > 2:
  558.                 print centdir
  559.             
  560.             filename = fp.read(centdir[_CD_FILENAME_LENGTH])
  561.             x = ZipInfo(filename)
  562.             x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
  563.             x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
  564.             x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
  565.             (x.create_version, x.create_system, x.extract_version, x.reserved, x.flag_bits, x.compress_type, t, d, x.CRC, x.compress_size, x.file_size) = centdir[1:12]
  566.             (x.volume, x.internal_attr, x.external_attr) = centdir[15:18]
  567.             x._raw_time = t
  568.             x.date_time = ((d >> 9) + 1980, d >> 5 & 15, d & 31, t >> 11, t >> 5 & 63, (t & 31) * 2)
  569.             x._decodeExtra()
  570.             x.header_offset = x.header_offset + concat
  571.             x.filename = x._decodeFilename()
  572.             self.filelist.append(x)
  573.             self.NameToInfo[x.filename] = x
  574.             total = total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH] + centdir[_CD_EXTRA_FIELD_LENGTH] + centdir[_CD_COMMENT_LENGTH]
  575.             if self.debug > 2:
  576.                 print 'total', total
  577.                 continue
  578.  
  579.     
  580.     def namelist(self):
  581.         l = []
  582.         for data in self.filelist:
  583.             l.append(data.filename)
  584.         
  585.         return l
  586.  
  587.     
  588.     def infolist(self):
  589.         return self.filelist
  590.  
  591.     
  592.     def printdir(self):
  593.         print '%-46s %19s %12s' % ('File Name', 'Modified    ', 'Size')
  594.         for zinfo in self.filelist:
  595.             date = '%d-%02d-%02d %02d:%02d:%02d' % zinfo.date_time[:6]
  596.             print '%-46s %s %12d' % (zinfo.filename, date, zinfo.file_size)
  597.         
  598.  
  599.     
  600.     def testzip(self):
  601.         chunk_size = 1048576
  602.         for zinfo in self.filelist:
  603.             
  604.             try:
  605.                 f = self.open(zinfo.filename, 'r')
  606.                 while f.read(chunk_size):
  607.                     pass
  608.             continue
  609.             except BadZipfile:
  610.                 return zinfo.filename
  611.             
  612.  
  613.         
  614.  
  615.     
  616.     def getinfo(self, name):
  617.         info = self.NameToInfo.get(name)
  618.         if info is None:
  619.             raise KeyError('There is no item named %r in the archive' % name)
  620.         info is None
  621.         return info
  622.  
  623.     
  624.     def setpassword(self, pwd):
  625.         self.pwd = pwd
  626.  
  627.     
  628.     def read(self, name, pwd = None):
  629.         return self.open(name, 'r', pwd).read()
  630.  
  631.     
  632.     def open(self, name, mode = 'r', pwd = None):
  633.         if mode not in ('r', 'U', 'rU'):
  634.             raise RuntimeError, 'open() requires mode "r", "U", or "rU"'
  635.         mode not in ('r', 'U', 'rU')
  636.         if not self.fp:
  637.             raise RuntimeError, 'Attempt to read ZIP archive that was already closed'
  638.         self.fp
  639.         if self._filePassed:
  640.             zef_file = self.fp
  641.         else:
  642.             zef_file = open(self.filename, 'rb')
  643.         if isinstance(name, ZipInfo):
  644.             zinfo = name
  645.         else:
  646.             zinfo = self.getinfo(name)
  647.         zef_file.seek(zinfo.header_offset, 0)
  648.         fheader = zef_file.read(sizeFileHeader)
  649.         if fheader[0:4] != stringFileHeader:
  650.             raise BadZipfile, 'Bad magic number for file header'
  651.         fheader[0:4] != stringFileHeader
  652.         fheader = struct.unpack(structFileHeader, fheader)
  653.         fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
  654.         if fheader[_FH_EXTRA_FIELD_LENGTH]:
  655.             zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])
  656.         
  657.         if fname != zinfo.orig_filename:
  658.             raise BadZipfile, 'File name in directory "%s" and header "%s" differ.' % (zinfo.orig_filename, fname)
  659.         fname != zinfo.orig_filename
  660.         is_encrypted = zinfo.flag_bits & 1
  661.         zd = None
  662.         if is_encrypted:
  663.             if not pwd:
  664.                 pwd = self.pwd
  665.             
  666.             if not pwd:
  667.                 raise RuntimeError, 'File %s is encrypted, password required for extraction' % name
  668.             pwd
  669.             zd = _ZipDecrypter(pwd)
  670.             bytes = zef_file.read(12)
  671.             h = map(zd, bytes[0:12])
  672.             if zinfo.flag_bits & 8:
  673.                 check_byte = zinfo._raw_time >> 8 & 255
  674.             else:
  675.                 check_byte = zinfo.CRC >> 24 & 255
  676.             if ord(h[11]) != check_byte:
  677.                 raise RuntimeError('Bad password for file', name)
  678.             ord(h[11]) != check_byte
  679.         
  680.         if zd is None:
  681.             zef = ZipExtFile(zef_file, zinfo)
  682.         else:
  683.             zef = ZipExtFile(zef_file, zinfo, zd)
  684.         if 'U' in mode:
  685.             zef.set_univ_newlines(True)
  686.         
  687.         return zef
  688.  
  689.     
  690.     def extract(self, member, path = None, pwd = None):
  691.         if not isinstance(member, ZipInfo):
  692.             member = self.getinfo(member)
  693.         
  694.         if path is None:
  695.             path = os.getcwd()
  696.         
  697.         return self._extract_member(member, path, pwd)
  698.  
  699.     
  700.     def extractall(self, path = None, members = None, pwd = None):
  701.         if members is None:
  702.             members = self.namelist()
  703.         
  704.         for zipinfo in members:
  705.             self.extract(zipinfo, path, pwd)
  706.         
  707.  
  708.     
  709.     def _extract_member(self, member, targetpath, pwd):
  710.         if targetpath[-1:] in (os.path.sep, os.path.altsep) and len(os.path.splitdrive(targetpath)[1]) > 1:
  711.             targetpath = targetpath[:-1]
  712.         
  713.         if member.filename[0] == '/':
  714.             targetpath = os.path.join(targetpath, member.filename[1:])
  715.         else:
  716.             targetpath = os.path.join(targetpath, member.filename)
  717.         targetpath = os.path.normpath(targetpath)
  718.         upperdirs = os.path.dirname(targetpath)
  719.         if upperdirs and not os.path.exists(upperdirs):
  720.             os.makedirs(upperdirs)
  721.         
  722.         if member.filename[-1] == '/':
  723.             if not os.path.isdir(targetpath):
  724.                 os.mkdir(targetpath)
  725.             
  726.             return targetpath
  727.         source = self.open(member, pwd = pwd)
  728.         target = file(targetpath, 'wb')
  729.         shutil.copyfileobj(source, target)
  730.         source.close()
  731.         target.close()
  732.         return targetpath
  733.  
  734.     
  735.     def _writecheck(self, zinfo):
  736.         if zinfo.filename in self.NameToInfo:
  737.             if self.debug:
  738.                 print 'Duplicate name:', zinfo.filename
  739.             
  740.         
  741.         if self.mode not in ('w', 'a'):
  742.             raise RuntimeError, 'write() requires mode "w" or "a"'
  743.         self.mode not in ('w', 'a')
  744.         if not self.fp:
  745.             raise RuntimeError, 'Attempt to write ZIP archive that was already closed'
  746.         self.fp
  747.         if zinfo.compress_type == ZIP_DEFLATED and not zlib:
  748.             raise RuntimeError, 'Compression requires the (missing) zlib module'
  749.         not zlib
  750.         if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED):
  751.             raise RuntimeError, 'That compression method is not supported'
  752.         zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED)
  753.         if zinfo.file_size > ZIP64_LIMIT:
  754.             if not self._allowZip64:
  755.                 raise LargeZipFile('Filesize would require ZIP64 extensions')
  756.             self._allowZip64
  757.         
  758.         if zinfo.header_offset > ZIP64_LIMIT:
  759.             if not self._allowZip64:
  760.                 raise LargeZipFile('Zipfile size would require ZIP64 extensions')
  761.             self._allowZip64
  762.         
  763.  
  764.     
  765.     def write(self, filename, arcname = None, compress_type = None):
  766.         if not self.fp:
  767.             raise RuntimeError('Attempt to write to ZIP archive that was already closed')
  768.         self.fp
  769.         st = os.stat(filename)
  770.         isdir = stat.S_ISDIR(st.st_mode)
  771.         mtime = time.localtime(st.st_mtime)
  772.         date_time = mtime[0:6]
  773.         if arcname is None:
  774.             arcname = filename
  775.         
  776.         arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
  777.         while arcname[0] in (os.sep, os.altsep):
  778.             arcname = arcname[1:]
  779.         if isdir:
  780.             arcname += '/'
  781.         
  782.         zinfo = ZipInfo(arcname, date_time)
  783.         zinfo.external_attr = (st[0] & 65535) << 0x10L
  784.         if compress_type is None:
  785.             zinfo.compress_type = self.compression
  786.         else:
  787.             zinfo.compress_type = compress_type
  788.         zinfo.file_size = st.st_size
  789.         zinfo.flag_bits = 0
  790.         zinfo.header_offset = self.fp.tell()
  791.         self._writecheck(zinfo)
  792.         self._didModify = True
  793.         if isdir:
  794.             zinfo.file_size = 0
  795.             zinfo.compress_size = 0
  796.             zinfo.CRC = 0
  797.             self.filelist.append(zinfo)
  798.             self.NameToInfo[zinfo.filename] = zinfo
  799.             self.fp.write(zinfo.FileHeader())
  800.             return None
  801.         fp = open(filename, 'rb')
  802.         self.fp.write(zinfo.FileHeader())
  803.         while None:
  804.             buf = fp.read(8192)
  805.             file_size = file_size + len(buf)
  806.             CRC = crc32(buf, CRC) & 0xFFFFFFFFL
  807.             if cmpr:
  808.                 buf = cmpr.compress(buf)
  809.                 compress_size = compress_size + len(buf)
  810.             
  811.             continue
  812.             fp.close()
  813.             if cmpr:
  814.                 buf = cmpr.flush()
  815.                 compress_size = compress_size + len(buf)
  816.                 self.fp.write(buf)
  817.                 zinfo.compress_size = compress_size
  818.             else:
  819.                 zinfo.compress_size = file_size
  820.         zinfo.CRC = CRC
  821.         zinfo.file_size = file_size
  822.         position = self.fp.tell()
  823.         self.fp.seek(zinfo.header_offset + 14, 0)
  824.         self.fp.write(struct.pack('<LLL', zinfo.CRC, zinfo.compress_size, zinfo.file_size))
  825.         self.fp.seek(position, 0)
  826.         self.filelist.append(zinfo)
  827.         self.NameToInfo[zinfo.filename] = zinfo
  828.  
  829.     
  830.     def writestr(self, zinfo_or_arcname, bytes):
  831.         if not isinstance(zinfo_or_arcname, ZipInfo):
  832.             zinfo = ZipInfo(filename = zinfo_or_arcname, date_time = time.localtime(time.time())[:6])
  833.             zinfo.compress_type = self.compression
  834.             zinfo.external_attr = 25165824
  835.         else:
  836.             zinfo = zinfo_or_arcname
  837.         if not self.fp:
  838.             raise RuntimeError('Attempt to write to ZIP archive that was already closed')
  839.         self.fp
  840.         zinfo.file_size = len(bytes)
  841.         zinfo.header_offset = self.fp.tell()
  842.         self._writecheck(zinfo)
  843.         self._didModify = True
  844.         zinfo.CRC = crc32(bytes) & 0xFFFFFFFFL
  845.         if zinfo.compress_type == ZIP_DEFLATED:
  846.             co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -15)
  847.             bytes = co.compress(bytes) + co.flush()
  848.             zinfo.compress_size = len(bytes)
  849.         else:
  850.             zinfo.compress_size = zinfo.file_size
  851.         zinfo.header_offset = self.fp.tell()
  852.         self.fp.write(zinfo.FileHeader())
  853.         self.fp.write(bytes)
  854.         self.fp.flush()
  855.         if zinfo.flag_bits & 8:
  856.             self.fp.write(struct.pack('<LLL', zinfo.CRC, zinfo.compress_size, zinfo.file_size))
  857.         
  858.         self.filelist.append(zinfo)
  859.         self.NameToInfo[zinfo.filename] = zinfo
  860.  
  861.     
  862.     def __del__(self):
  863.         self.close()
  864.  
  865.     
  866.     def close(self):
  867.         if self.fp is None:
  868.             return None
  869.         if not self._filePassed:
  870.             self.fp.close()
  871.         
  872.         self.fp = None
  873.  
  874.  
  875.  
  876. class PyZipFile(ZipFile):
  877.     
  878.     def writepy(self, pathname, basename = ''):
  879.         (dir, name) = os.path.split(pathname)
  880.         if os.path.isdir(pathname):
  881.             initname = os.path.join(pathname, '__init__.py')
  882.             if os.path.isfile(initname):
  883.                 if basename:
  884.                     basename = '%s/%s' % (basename, name)
  885.                 else:
  886.                     basename = name
  887.                 if self.debug:
  888.                     print 'Adding package in', pathname, 'as', basename
  889.                 
  890.                 (fname, arcname) = self._get_codename(initname[0:-3], basename)
  891.                 if self.debug:
  892.                     print 'Adding', arcname
  893.                 
  894.                 self.write(fname, arcname)
  895.                 dirlist = os.listdir(pathname)
  896.                 dirlist.remove('__init__.py')
  897.                 for filename in dirlist:
  898.                     path = os.path.join(pathname, filename)
  899.                     (root, ext) = os.path.splitext(filename)
  900.                     if os.path.isdir(path):
  901.                         if os.path.isfile(os.path.join(path, '__init__.py')):
  902.                             self.writepy(path, basename)
  903.                         
  904.                     os.path.isfile(os.path.join(path, '__init__.py'))
  905.                     if ext == '.py':
  906.                         (fname, arcname) = self._get_codename(path[0:-3], basename)
  907.                         if self.debug:
  908.                             print 'Adding', arcname
  909.                         
  910.                         self.write(fname, arcname)
  911.                         continue
  912.                 
  913.             elif self.debug:
  914.                 print 'Adding files from directory', pathname
  915.             
  916.             for filename in os.listdir(pathname):
  917.                 path = os.path.join(pathname, filename)
  918.                 (root, ext) = os.path.splitext(filename)
  919.                 if ext == '.py':
  920.                     (fname, arcname) = self._get_codename(path[0:-3], basename)
  921.                     if self.debug:
  922.                         print 'Adding', arcname
  923.                     
  924.                     self.write(fname, arcname)
  925.                     continue
  926.             
  927.         elif pathname[-3:] != '.py':
  928.             raise RuntimeError, 'Files added with writepy() must end with ".py"'
  929.         
  930.         (fname, arcname) = self._get_codename(pathname[0:-3], basename)
  931.         if self.debug:
  932.             print 'Adding file', arcname
  933.         
  934.         self.write(fname, arcname)
  935.  
  936.     
  937.     def _get_codename(self, pathname, basename):
  938.         file_py = pathname + '.py'
  939.         file_pyc = pathname + '.pyc'
  940.         file_pyo = pathname + '.pyo'
  941.         if os.path.isfile(file_pyo) and os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime:
  942.             fname = file_pyo
  943.         elif not os.path.isfile(file_pyc) or os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime:
  944.             import py_compile
  945.             if self.debug:
  946.                 print 'Compiling', file_py
  947.             
  948.             
  949.             try:
  950.                 py_compile.compile(file_py, file_pyc, None, True)
  951.             except py_compile.PyCompileError:
  952.                 err = None
  953.                 print err.msg
  954.  
  955.             fname = file_pyc
  956.         else:
  957.             fname = file_pyc
  958.         archivename = os.path.split(fname)[1]
  959.         if basename:
  960.             archivename = '%s/%s' % (basename, archivename)
  961.         
  962.         return (fname, archivename)
  963.  
  964.  
  965.  
  966. def main(args = None):
  967.     import textwrap
  968.     USAGE = textwrap.dedent('        Usage:\n            zipfile.py -l zipfile.zip        # Show listing of a zipfile\n            zipfile.py -t zipfile.zip        # Test if a zipfile is valid\n            zipfile.py -e zipfile.zip target # Extract zipfile into target dir\n            zipfile.py -c zipfile.zip src ... # Create zipfile from sources\n        ')
  969.     if args is None:
  970.         args = sys.argv[1:]
  971.     
  972.     if not args or args[0] not in ('-l', '-c', '-e', '-t'):
  973.         print USAGE
  974.         sys.exit(1)
  975.     
  976.     if args[0] == '-l':
  977.         if len(args) != 2:
  978.             print USAGE
  979.             sys.exit(1)
  980.         
  981.         zf = ZipFile(args[1], 'r')
  982.         zf.printdir()
  983.         zf.close()
  984.     elif args[0] == '-t':
  985.         if len(args) != 2:
  986.             print USAGE
  987.             sys.exit(1)
  988.         
  989.         zf = ZipFile(args[1], 'r')
  990.         zf.testzip()
  991.         print 'Done testing'
  992.     elif args[0] == '-e':
  993.         if len(args) != 3:
  994.             print USAGE
  995.             sys.exit(1)
  996.         
  997.         zf = ZipFile(args[1], 'r')
  998.         out = args[2]
  999.         for path in zf.namelist():
  1000.             if path.startswith('./'):
  1001.                 tgt = os.path.join(out, path[2:])
  1002.             else:
  1003.                 tgt = os.path.join(out, path)
  1004.             tgtdir = os.path.dirname(tgt)
  1005.             if not os.path.exists(tgtdir):
  1006.                 os.makedirs(tgtdir)
  1007.             
  1008.             fp = open(tgt, 'wb')
  1009.             fp.write(zf.read(path))
  1010.             fp.close()
  1011.         
  1012.         zf.close()
  1013.     elif args[0] == '-c':
  1014.         if len(args) < 3:
  1015.             print USAGE
  1016.             sys.exit(1)
  1017.         
  1018.         
  1019.         def addToZip(zf, path, zippath):
  1020.             if os.path.isfile(path):
  1021.                 zf.write(path, zippath, ZIP_DEFLATED)
  1022.             elif os.path.isdir(path):
  1023.                 for nm in os.listdir(path):
  1024.                     addToZip(zf, os.path.join(path, nm), os.path.join(zippath, nm))
  1025.                 
  1026.             
  1027.  
  1028.         zf = ZipFile(args[1], 'w', allowZip64 = True)
  1029.         for src in args[2:]:
  1030.             addToZip(zf, src, os.path.basename(src))
  1031.         
  1032.         zf.close()
  1033.     
  1034.  
  1035. if __name__ == '__main__':
  1036.     main()
  1037.  
  1038.