[go: up one dir, main page]

Menu

[r1437]: / mcomix / archive / zip.py  Maximize  Restore  History

Download this file

75 lines (56 with data), 2.5 kB

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# -*- coding: utf-8 -*-
""" Unicode-aware wrapper for zipfile.ZipFile. """
import os
from contextlib import closing
from mcomix import log
from mcomix.archive import archive_base
# Try to use czipfile if available as it's much faster at decryption.
try:
import czipfile as zipfile
except ImportError:
log.warning('czipfile not available! using zipfile')
import zipfile
def is_py_supported_zipfile(path):
"""Check if a given zipfile has all internal files stored with Python supported compression
"""
# Use contextlib's closing for 2.5 compatibility
with closing(zipfile.ZipFile(path, 'r')) as zip_file:
for file_info in zip_file.infolist():
if file_info.compress_type not in (zipfile.ZIP_STORED, zipfile.ZIP_DEFLATED):
return False
return True
class ZipArchive(archive_base.NonUnicodeArchive):
def __init__(self, archive):
super(ZipArchive, self).__init__(archive)
self.zip = zipfile.ZipFile(archive, 'r')
# Encryption is supported starting with Python 2.6
self._encryption_supported = hasattr(self.zip, "setpassword")
self._password = None
def iter_contents(self):
if self._encryption_supported and self._has_encryption():
self._get_password()
self.zip.setpassword(self._password)
for filename in self.zip.namelist():
yield self._unicode_filename(filename)
def extract(self, filename, destination_dir):
new = self._create_file(os.path.join(destination_dir, filename))
content = self.zip.read(self._original_filename(filename))
new.write(content)
new.close()
zipinfo = self.zip.getinfo(self._original_filename(filename))
if len(content) != zipinfo.file_size:
log.warning(_('%(filename)s\'s extracted size is %(actual_size)d bytes,'
' but should be %(expected_size)d bytes.'
' The archive might be corrupt or in an unsupported format.'),
{ 'filename' : filename, 'actual_size' : len(content),
'expected_size' : zipinfo.file_size })
def close(self):
self.zip.close()
def _has_encryption(self):
""" Checks all files in the archive for encryption.
Returns True if at least one encrypted file was found. """
for zipinfo in self.zip.infolist():
if zipinfo.flag_bits & 0x1: # File is encrypted
return True
return False
# vim: expandtab:sw=4:ts=4