From 615b123cef0dc7afb6b6047705e3fe4876ceb663 Mon Sep 17 00:00:00 2001 From: JackDandy Date: Mon, 26 Mar 2018 20:12:41 +0100 Subject: [PATCH] =?UTF-8?q?Update=20rarfile=203.0=20(3e54b22)=20=E2=86=92?= =?UTF-8?q?=203.0=20(2704344).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES.md | 1 + lib/rarfile/rarfile.py | 70 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fe2ba62b..42864bfe 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,7 @@ * Update profilehooks 1.9.0 (de7d59b) to 1.10.0 (0ce1e29) * Update Certifi 2017.07.27 (f808089) to 2018.01.18 (e225253) * Update PySocks 1.6.5 (b4323df) to 1.6.8 (524ceb4) +* Update rarfile 3.0 (3e54b22) to 3.0 (2704344) [develop changelog] diff --git a/lib/rarfile/rarfile.py b/lib/rarfile/rarfile.py index 78148c19..10e242c9 100644 --- a/lib/rarfile/rarfile.py +++ b/lib/rarfile/rarfile.py @@ -170,6 +170,9 @@ else: # pragma: no cover unicode = str _byte_code = int # noqa +# don't break 2.6 completely +if sys.hexversion < 0x2070000: + memoryview = lambda x: x # noqa __version__ = '3.0' @@ -215,6 +218,12 @@ ALT_EXTRACT_ARGS = ('-x', '-f') ALT_TEST_ARGS = ('-t', '-f') ALT_CHECK_ARGS = ('--help',) +#ALT_TOOL = 'unar' +#ALT_OPEN_ARGS = ('-o', '-') +#ALT_EXTRACT_ARGS = () +#ALT_TEST_ARGS = ('-test',) # does not work +#ALT_CHECK_ARGS = ('-v',) + #: whether to speed up decompression by using tmp archive USE_EXTRACT_HACK = 1 @@ -2525,6 +2534,53 @@ class Blake2SP(object): """Hexadecimal digest.""" return tohex(self.digest()) + +class Rar3Sha1(object): + """Bug-compat for SHA1 + """ + digest_size = 20 + block_size = 64 + + _BLK_BE = struct.Struct(b'>16L') + _BLK_LE = struct.Struct(b'<16L') + + __slots__ = ('_nbytes', '_md', '_rarbug') + + def __init__(self, data=b'', rarbug=False): + self._md = sha1() + self._nbytes = 0 + self._rarbug = rarbug + self.update(data) + + def update(self, data): + """Process more data.""" + self._md.update(data) + bufpos = self._nbytes & 63 + self._nbytes += len(data) + + if self._rarbug and len(data) > 64: + dpos = self.block_size - bufpos + while dpos + self.block_size <= len(data): + self._corrupt(data, dpos) + dpos += self.block_size + + def digest(self): + """Return final state.""" + return self._md.digest() + + def hexdigest(self): + """Return final state as hex string.""" + return self._md.hexdigest() + + def _corrupt(self, data, dpos): + """Corruption from SHA1 core.""" + ws = list(self._BLK_BE.unpack_from(data, dpos)) + for t in range(16, 80): + tmp = ws[(t - 3) & 15] ^ ws[(t - 8) & 15] ^ ws[(t - 14) & 15] ^ ws[(t - 16) & 15] + ws[t & 15] = ((tmp << 1) | (tmp >> (32 - 1))) & 0xFFFFFFFF + self._BLK_LE.pack_into(data, dpos, *ws) + + ## ## Utility functions ## @@ -2672,7 +2728,7 @@ def _parse_xtime(flag, data, pos, basetime=None): def is_filelike(obj): """Filename or file object? """ - if isinstance(obj, str) or isinstance(obj, unicode): + if isinstance(obj, (bytes, unicode)): return False res = True for a in ('read', 'tell', 'seek'): @@ -2686,13 +2742,14 @@ def rar3_s2k(psw, salt): """ if not isinstance(psw, unicode): psw = psw.decode('utf8') - seed = psw.encode('utf-16le') + salt + seed = bytearray(psw.encode('utf-16le') + salt) + h = Rar3Sha1(rarbug=True) iv = EMPTY - h = sha1() for i in range(16): for j in range(0x4000): cnt = S_LONG.pack(i * 0x4000 + j) - h.update(seed + cnt[:3]) + h.update(seed) + h.update(cnt[:3]) if j == 0: iv += h.digest()[19:20] key_be = h.digest()[:16] @@ -2814,6 +2871,8 @@ def custom_popen(cmd): except OSError as ex: if ex.errno == errno.ENOENT: raise RarCannotExec("Unrar not installed? (rarfile.UNRAR_TOOL=%r)" % UNRAR_TOOL) + if ex.errno == errno.EACCES or ex.errno == errno.EPERM: + raise RarCannotExec("Cannot execute unrar (rarfile.UNRAR_TOOL=%r)" % UNRAR_TOOL) raise return p @@ -2945,7 +3004,8 @@ def _check_unrar_tool(): TEST_ARGS = ALT_TEST_ARGS except RarCannotExec: # no usable tool, only uncompressed archives work - pass + return False + return True _check_unrar_tool()