--- ../../zipfile.py	2010-11-24 01:47:05.000000000 +0000
+++ zipfile271.py	2010-11-24 01:51:31.000000000 +0000
@@ -1,6 +1,7 @@
 """
 Read and write ZIP files.
 """
+# Improved by Chortos-2 in 2010 (added bzip2 support)
 import struct, os, time, sys, shutil
 import binascii, cStringIO, stat
 import io
@@ -13,8 +14,13 @@
     zlib = None
     crc32 = binascii.crc32
 
+try:
+    import bz2 # We may need its compression method
+except ImportError:
+    bz2 = None
+
 __all__ = ["BadZipfile", "error", "ZIP_STORED", "ZIP_DEFLATED", "is_zipfile",
-           "ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile" ]
+           "ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile", "ZIP_BZIP2" ]
 
 class BadZipfile(Exception):
     pass
@@ -35,6 +41,7 @@
 # constants for Zip file compression methods
 ZIP_STORED = 0
 ZIP_DEFLATED = 8
+ZIP_BZIP2 = 12
 # Other ZIP compression methods not supported
 
 # Below are some formats and associated data for reading/writing headers using
@@ -477,6 +484,9 @@
 
         if self._compress_type == ZIP_DEFLATED:
             self._decompressor = zlib.decompressobj(-15)
+        elif self._compress_type == ZIP_BZIP2:
+            self._decompressor = bz2.BZ2Decompressor()
+            self.MIN_READ_SIZE = 900000
         self._unconsumed = ''
 
         self._readbuffer = ''
@@ -635,6 +645,13 @@
             self._update_crc(data, eof=eof)
             self._readbuffer = self._readbuffer[self._offset:] + data
             self._offset = 0
+        elif (len(self._unconsumed) > 0 and n > len_readbuffer and
+            self._compress_type == ZIP_BZIP2):
+            data = self._decompressor.decompress(self._unconsumed)
+
+            self._unconsumed = ''
+            self._readbuffer = self._readbuffer[self._offset:] + data
+            self._offset = 0
 
         # Read from buffer.
         data = self._readbuffer[self._offset: self._offset + n]
@@ -651,7 +668,8 @@
     file: Either the path to the file, or a file-like object.
           If it is a path, the file will be opened and closed by ZipFile.
     mode: The mode can be either read "r", write "w" or append "a".
-    compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib).
+    compression: ZIP_STORED (no compression), ZIP_DEFLATED (requires zlib),
+                 or ZIP_BZIP2 (requires bz2).
     allowZip64: if True ZipFile will create files with ZIP64 extensions when
                 needed, otherwise it will raise an exception when this would
                 be necessary.
@@ -671,6 +689,10 @@
             if not zlib:
                 raise RuntimeError,\
                       "Compression requires the (missing) zlib module"
+        elif compression == ZIP_BZIP2:
+            if not bz2:
+                raise RuntimeError,\
+                      "Compression requires the (missing) bz2 module"
         else:
             raise RuntimeError, "That compression method is not supported"
 
@@ -994,7 +1016,10 @@
         if zinfo.compress_type == ZIP_DEFLATED and not zlib:
             raise RuntimeError, \
                   "Compression requires the (missing) zlib module"
-        if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED):
+        if zinfo.compress_type == ZIP_BZIP2 and not bz2:
+            raise RuntimeError, \
+                  "Compression requires the (missing) bz2 module"
+        if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED, ZIP_BZIP2):
             raise RuntimeError, \
                   "That compression method is not supported"
         if zinfo.file_size > ZIP64_LIMIT:
@@ -1055,6 +1080,8 @@
             if zinfo.compress_type == ZIP_DEFLATED:
                 cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
                      zlib.DEFLATED, -15)
+            elif zinfo.compress_type == ZIP_BZIP2:
+                cmpr = bz2.BZ2Compressor()
             else:
                 cmpr = None
             while 1:
@@ -1115,6 +1142,10 @@
                  zlib.DEFLATED, -15)
             bytes = co.compress(bytes) + co.flush()
             zinfo.compress_size = len(bytes)    # Compressed size
+        elif zinfo.compress_type == ZIP_BZIP2:
+            co = bz2.BZ2Compressor()
+            bytes = co.compress(bytes) + co.flush()
+            zinfo.compress_size = len(bytes)    # Compressed size
         else:
             zinfo.compress_size = zinfo.file_size
         zinfo.header_offset = self.fp.tell()    # Start of header bytes
