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

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