[Python-modules-commits] [python-rarfile] 01/03: New upstream version 3.0

Hugo Lefeuvre hle at moszumanska.debian.org
Fri Aug 4 16:30:25 UTC 2017


This is an automated email from the git hooks/post-receive script.

hle pushed a commit to branch master
in repository python-rarfile.

commit 92cc3665c01a2532535044cf7c36166d145ef912
Author: Hugo Lefeuvre <hle at debian.org>
Date:   Fri Aug 4 18:05:04 2017 +0200

    New upstream version 3.0
---
 Makefile                                |   22 +-
 PKG-INFO                                |   15 +-
 README.rst                              |   13 +-
 doc/api.rst                             |    5 +-
 doc/conf.py                             |    8 +-
 doc/index.rst                           |   18 +-
 doc/news.rst                            |   42 +
 dumprar.py                              |  355 ++++-
 PKG-INFO => rarfile.egg-info/PKG-INFO   |   15 +-
 rarfile.egg-info/SOURCES.txt            |   95 ++
 rarfile.egg-info/dependency_links.txt   |    1 +
 rarfile.egg-info/top_level.txt          |    1 +
 rarfile.py                              | 2465 +++++++++++++++++++++----------
 setup.cfg                               |    5 +
 setup.py                                |   12 +-
 test/Makefile                           |    9 -
 test/files/ctime0.rar.exp               |    8 +-
 test/files/ctime1.rar.exp               |   10 +-
 test/files/ctime2.rar.exp               |   10 +-
 test/files/ctime3.rar.exp               |   10 +-
 test/files/ctime4.rar.exp               |   10 +-
 test/files/rar15-comment-lock.rar.exp   |   10 +-
 test/files/rar15-comment.rar.exp        |   10 +-
 test/files/rar202-comment-nopsw.rar.exp |   10 +-
 test/files/rar202-comment-psw.rar.exp   |   10 +-
 test/files/rar3-comment-hpsw.rar.exp    |   14 +-
 test/files/rar3-comment-plain.rar.exp   |   14 +-
 test/files/rar3-comment-psw.rar.exp     |   14 +-
 test/files/rar3-old.rar                 |  Bin 0 -> 102400 bytes
 test/files/rar3-old.rar.exp             |   13 +
 test/files/rar3-vols.part1.rar          |  Bin 0 -> 102400 bytes
 test/files/rar3-vols.part1.rar.exp      |   13 +
 test/files/rar3-vols.part2.rar          |  Bin 0 -> 102400 bytes
 test/files/rar3-vols.part2.rar.exp      |    2 +
 test/files/rar3-vols.part3.rar          |  Bin 0 -> 2572 bytes
 test/files/rar3-vols.part3.rar.exp      |    2 +
 test/files/rar5-blake.rar               |  Bin 0 -> 2349 bytes
 test/files/rar5-blake.rar.exp           |   22 +
 test/files/rar5-crc.rar                 |  Bin 0 -> 2285 bytes
 test/files/rar5-crc.rar.exp             |   22 +
 test/files/rar5-dups.rar                |  Bin 0 -> 594 bytes
 test/files/rar5-dups.rar.exp            |   90 ++
 test/files/rar5-hlink.rar               |  Bin 0 -> 230 bytes
 test/files/rar5-hlink.rar.exp           |   30 +
 test/files/rar5-hpsw.rar                |  Bin 0 -> 2590 bytes
 test/files/rar5-hpsw.rar.exp            |   24 +
 test/files/rar5-psw-blake.rar           |  Bin 0 -> 2472 bytes
 test/files/rar5-psw-blake.rar.exp       |   24 +
 test/files/rar5-psw.rar                 |  Bin 0 -> 2403 bytes
 test/files/rar5-psw.rar.exp             |   24 +
 test/files/rar5-quick-open.rar          |  Bin 0 -> 326 bytes
 test/files/rar5-quick-open.rar.exp      |   19 +
 test/files/rar5-solid-qo.rar            |  Bin 0 -> 508 bytes
 test/files/rar5-solid-qo.rar.exp        |   37 +
 test/files/rar5-solid.rar               |  Bin 0 -> 169 bytes
 test/files/rar5-solid.rar.exp           |   15 +
 test/files/rar5-times.rar               |  Bin 0 -> 132 bytes
 test/files/rar5-times.rar.exp           |   11 +
 test/files/rar5-times2.rar              |  Bin 0 -> 73 bytes
 test/files/rar5-times2.rar.exp          |   10 +
 test/files/rar5-vols.part1.rar          |  Bin 0 -> 102400 bytes
 test/files/rar5-vols.part1.rar.exp      |   19 +
 test/files/rar5-vols.part2.rar          |  Bin 0 -> 102400 bytes
 test/files/rar5-vols.part2.rar.exp      |    2 +
 test/files/rar5-vols.part3.rar          |  Bin 0 -> 11384 bytes
 test/files/rar5-vols.part3.rar.exp      |    2 +
 test/files/seektest.rar.exp             |   14 +-
 test/files/unicode.rar.exp              |   10 +-
 test/files/unicode2.rar                 |  Bin 0 -> 152 bytes
 test/files/unicode2.rar.exp             |   11 +
 test/run_dump.sh                        |   43 +
 test/run_dump_all.sh                    |   18 +
 test/test1.sh                           |   32 -
 test/test2.sh                           |   19 -
 test/test_api.py                        |  233 +++
 test/test_crypto.py                     |   44 +
 test/test_format.py                     |  223 +++
 test/test_hashing.py                    |   78 +
 test/test_korrupt.py                    |   50 +
 test/test_reading.py                    |  150 ++
 test/test_seek.py                       |   93 ++
 test/testcorrupt.py                     |   85 --
 test/testio.py                          |   35 -
 test/testseek.py                        |  103 --
 84 files changed, 3577 insertions(+), 1256 deletions(-)

diff --git a/Makefile b/Makefile
index 45e3c2b..8bba3cd 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,8 @@
 prefix = /usr/local
 
 all:
-	python setup.py build
+	pyflakes3 rarfile.py
+	tox
 
 install:
 	python setup.py install --prefix=$(prefix)
@@ -13,15 +14,13 @@ tgz: clean
 clean:
 	rm -rf __pycache__ build dist
 	rm -f *.pyc MANIFEST *.orig *.rej *.html *.class
-	rm -rf doc/_build doc/_static doc/_templates
-	make -C test clean
+	rm -rf doc/_build doc/_static doc/_templates doc/html
+	rm -rf .coverage cover*
+	rm -rf *.egg-info
+	rm -f test/files/*.rar.[pjt]* *.diffs
 
-html:
-	rst2html README.rst > README.html
-	make -C doc html
-
-lint:
-	pylint -E rarfile.py
+toxclean: clean
+	rm -rf .tox
 
 rbuild:
 	curl -X POST https://readthedocs.org/build/6715
@@ -29,3 +28,8 @@ rbuild:
 upload:
 	python setup.py sdist upload
 
+ack:
+	for fn in test/files/*.py27; do \
+		cp $$fn `echo $$fn | sed 's/py27/exp/'` || exit 1; \
+	done
+
diff --git a/PKG-INFO b/PKG-INFO
index 282b56d..3a6d9a7 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: rarfile
-Version: 2.8
+Version: 3.0
 Summary: RAR archive reader for Python
 Home-page: https://github.com/markokr/rarfile
 Author: Marko Kreen
@@ -15,7 +15,7 @@ Description: rarfile - RAR archive reader for Python
         
         Features:
         
-        - Supports both RAR2 and RAR3 archives (WinRAR 2.x .. WinRAR 4.x).
+        - Supports both RAR3 and RAR5 format archives.
         - Supports multi volume archives.
         - Supports Unicode filenames.
         - Supports password-protected archives.
@@ -25,23 +25,18 @@ Description: rarfile - RAR archive reader for Python
           from RARLAB_ or ``bsdtar`` from libarchive_.
         - Works with both Python 2.7 and 3.x.
         
-        Notes:
-        
-        - Does not support the RAR5 format introduced in WinRAR 5.0.
-        - ``bsdtar`` does not support all RAR3 features.
-        
         Links:
         
         - `Documentation`_
         - `Downloads`_
         - `Git`_ repo
         
-        .. _RAR: https://en.wikipedia.org/wiki/RAR_%28file_format%29
-        .. _zipfile: https://docs.python.org/2/library/zipfile.html
-        .. _ISC: https://en.wikipedia.org/wiki/ISC_license
         .. _Git: https://github.com/markokr/rarfile
         .. _Downloads: https://pypi.python.org/pypi/rarfile
         .. _Documentation: https://rarfile.readthedocs.io/
+        .. _RAR: https://en.wikipedia.org/wiki/RAR_%28file_format%29
+        .. _zipfile: https://docs.python.org/2/library/zipfile.html
+        .. _ISC: https://en.wikipedia.org/wiki/ISC_license
         .. _libarchive: https://github.com/libarchive/libarchive
         .. _RARLAB: http://www.rarlab.com/
 Keywords: rar,unrar,archive
diff --git a/README.rst b/README.rst
index 596ca91..a356407 100644
--- a/README.rst
+++ b/README.rst
@@ -8,7 +8,7 @@ license.
 
 Features:
 
-- Supports both RAR2 and RAR3 archives (WinRAR 2.x .. WinRAR 4.x).
+- Supports both RAR3 and RAR5 format archives.
 - Supports multi volume archives.
 - Supports Unicode filenames.
 - Supports password-protected archives.
@@ -18,22 +18,17 @@ Features:
   from RARLAB_ or ``bsdtar`` from libarchive_.
 - Works with both Python 2.7 and 3.x.
 
-Notes:
-
-- Does not support the RAR5 format introduced in WinRAR 5.0.
-- ``bsdtar`` does not support all RAR3 features.
-
 Links:
 
 - `Documentation`_
 - `Downloads`_
 - `Git`_ repo
 
-.. _RAR: https://en.wikipedia.org/wiki/RAR_%28file_format%29
-.. _zipfile: https://docs.python.org/2/library/zipfile.html
-.. _ISC: https://en.wikipedia.org/wiki/ISC_license
 .. _Git: https://github.com/markokr/rarfile
 .. _Downloads: https://pypi.python.org/pypi/rarfile
 .. _Documentation: https://rarfile.readthedocs.io/
+.. _RAR: https://en.wikipedia.org/wiki/RAR_%28file_format%29
+.. _zipfile: https://docs.python.org/2/library/zipfile.html
+.. _ISC: https://en.wikipedia.org/wiki/ISC_license
 .. _libarchive: https://github.com/libarchive/libarchive
 .. _RARLAB: http://www.rarlab.com/
diff --git a/doc/api.rst b/doc/api.rst
index 9892e8b..5611abb 100644
--- a/doc/api.rst
+++ b/doc/api.rst
@@ -41,10 +41,7 @@ Module Configuration
 .. autodata:: UNRAR_TOOL
 .. autodata:: DEFAULT_CHARSET
 .. autodata:: TRY_ENCODINGS
-.. autodata:: USE_DATETIME
 .. autodata:: PATH_SEP
-.. autodata:: NEED_COMMENTS
-.. autodata:: UNICODE_COMMENTS
 .. autodata:: USE_EXTRACT_HACK
 .. autodata:: HACK_SIZE_LIMIT
 
@@ -105,7 +102,9 @@ Exceptions
 .. autoclass:: RarCreateError
 .. autoclass:: RarNoFilesError
 .. autoclass:: RarUserBreak
+.. autoclass:: RarWrongPassword
 .. autoclass:: RarUnknownError
 .. autoclass:: RarSignalExit
+.. autoclass:: RarCannotExec
 
 
diff --git a/doc/conf.py b/doc/conf.py
index 4709473..b391035 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -22,17 +22,17 @@ import rarfile
 # -- General configuration -----------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+needs_sphinx = '1.3'
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx']
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.napoleon']
 
 autodoc_member_order = 'bysource'
 autoclass_content = 'both'
 autodoc_default_flags = ['show-inheritance']
 
-intersphinx_mapping = {'python': ('http://docs.python.org/2', None)}
+intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -71,7 +71,7 @@ release = rarfile.__version__
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ['_build', 'html']
 
 # The reST default role (used for this markup: `text`) to use for all documents.
 #default_role = None
diff --git a/doc/index.rst b/doc/index.rst
index bbd4a51..473d62d 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -6,22 +6,17 @@ This is Python module for RAR_ archive reading.  The interface
 is made as zipfile_ like as possible.  Licensed under ISC_
 license.
 
-.. _RAR: http://en.wikipedia.org/wiki/RAR
-.. _zipfile: http://docs.python.org/library/zipfile.html
-.. _ISC: http://en.wikipedia.org/wiki/ISC_license
-
 Features:
 
-- Supports both RAR 2.x and 3.x archives.
+- Supports both RAR3 and RAR5 format archives.
 - Supports multi volume archives.
 - Supports Unicode filenames.
 - Supports password-protected archives.
 - Supports archive and file comments.
 - Archive parsing and non-compressed files are handled in pure Python code.
-- For compressed files runs ``unrar`` utility.
-- Works with both Python 2.x and 3.x.
-
-
+- Compressed files are extracted by executing external tool: either ``unrar``
+  from RARLAB_ or ``bsdtar`` from libarchive_.
+- Works with both Python 2.7 and 3.x.
 
 Documentation:
 
@@ -40,3 +35,8 @@ Indices and tables
 * :ref:`modindex`
 * :ref:`search`
 
+.. _RAR: http://en.wikipedia.org/wiki/RAR
+.. _zipfile: http://docs.python.org/library/zipfile.html
+.. _ISC: http://en.wikipedia.org/wiki/ISC_license
+.. _libarchive: https://github.com/libarchive/libarchive
+.. _RARLAB: http://www.rarlab.com/
diff --git a/doc/news.rst b/doc/news.rst
index 85d00f1..5d00391 100644
--- a/doc/news.rst
+++ b/doc/news.rst
@@ -4,6 +4,48 @@ rarfile history
 
 .. py:currentmodule:: rarfile
 
+Version 3.0 (2016-12-27)
+------------------------
+
+New feature:
+
+* Support RAR5 archive format.  It is actually completely different
+  archive format from RAR3 one, only is uses same file extension
+  and tools are old one.
+
+  Except incompatibilies noted below, most of code should notice no change,
+  existing :class:`RarInfo` fields will continue using RAR3-compatible
+  values (eg. :attr:`RarInfo.host_os`).  RAR5-specific values will use
+  new fields.
+
+Incompatibilities between rarfile v2.x and 3.x:
+
+* Default :data:`PATH_SEP` is now '/' instead '\\'.
+
+* Removed :data:`NEED_COMMENTS` option, comments are always extracted.
+
+* Removed :data:`UNICODE_COMMENTS` option, they are always decoded.
+
+* Removed :data:`USE_DATETIME` option, :attr:`RarInfo.date_time` is always tuple,
+  :attr:`RarInfo.mtime`, :attr:`RarInfo.atime`, :attr:`RarInfo.ctime` and
+  :attr:`RarInfo.arctime` are always :class:`datetime.datetime` objects.
+
+Fixes:
+
+* Fixed bug when calling rarfp.open() on a RarInfo structure.
+
+Cleanups:
+
+* Code refactor to allow 2 different file format parsers.
+
+* Code cleanups to pass modern linters.
+
+* New testing and linting setup based on Tox_.
+
+* Use setuptools instead distutils for install.
+
+.. _Tox: https://tox.readthedocs.io/en/latest/
+
 Version 2.8 (2016-06-07)
 ------------------------
 
diff --git a/dumprar.py b/dumprar.py
index f7ab062..4e17b1d 100755
--- a/dumprar.py
+++ b/dumprar.py
@@ -2,21 +2,16 @@
 
 """Dump archive contents, test extraction."""
 
+from __future__ import division, absolute_import, print_function
+
 import io
 import sys
-import rarfile as rf
-from binascii import crc32, hexlify
+import getopt
+
 from datetime import datetime
 
-try:
-    bytearray
-except NameError:
-    import array
-    def bytearray(v):
-        return array.array('B', v)
+import rarfile as rf
 
-rf.UNICODE_COMMENTS = 1
-rf.USE_DATETIME = 1
 
 usage = """
 dumprar [switches] [ARC1 ARC2 ...] [@ARCLIST]
@@ -37,11 +32,27 @@ os_list = ['DOS', 'OS2', 'WIN', 'UNIX', 'MACOS', 'BEOS']
 block_strs = ['MARK', 'MAIN', 'FILE', 'OLD_COMMENT', 'OLD_EXTRA',
               'OLD_SUB', 'OLD_RECOVERY', 'OLD_AUTH', 'SUB', 'ENDARC']
 
-def rarType(type):
-    if type < rf.RAR_BLOCK_MARK or type > rf.RAR_BLOCK_ENDARC:
+r5_block_types = {
+    rf.RAR5_BLOCK_MAIN: 'R5_MAIN',
+    rf.RAR5_BLOCK_FILE: 'R5_FILE',
+    rf.RAR5_BLOCK_SERVICE: 'R5_SVC',
+    rf.RAR5_BLOCK_ENCRYPTION: 'R5_ENC',
+    rf.RAR5_BLOCK_ENDARC: 'R5_ENDARC',
+}
+
+
+def rar3_type(btype):
+    """RAR3 type code as string."""
+    if btype < rf.RAR_BLOCK_MARK or btype > rf.RAR_BLOCK_ENDARC:
         return "*UNKNOWN*"
-    return block_strs[type - rf.RAR_BLOCK_MARK]
-                                 
+    return block_strs[btype - rf.RAR_BLOCK_MARK]
+
+
+def rar5_type(btype):
+    """RAR5 type code as string."""
+    return r5_block_types.get(btype, '*UNKNOWN*')
+
+
 main_bits = (
     (rf.RAR_MAIN_VOLUME, "VOL"),
     (rf.RAR_MAIN_COMMENT, "COMMENT"),
@@ -89,7 +100,62 @@ generic_bits = (
 file_parms = ("D64", "D128", "D256", "D512",
               "D1024", "D2048", "D4096", "DIR")
 
+r5_block_flags = (
+    (rf.RAR5_BLOCK_FLAG_EXTRA_DATA, 'EXTRA'),
+    (rf.RAR5_BLOCK_FLAG_DATA_AREA, 'DATA'),
+    (rf.RAR5_BLOCK_FLAG_SKIP_IF_UNKNOWN, 'SKIP'),
+    (rf.RAR5_BLOCK_FLAG_SPLIT_BEFORE, 'SPLIT_BEFORE'),
+    (rf.RAR5_BLOCK_FLAG_SPLIT_AFTER, 'SPLIT_AFTER'),
+    (rf.RAR5_BLOCK_FLAG_DEPENDS_PREV, 'DEPENDS'),
+    (rf.RAR5_BLOCK_FLAG_KEEP_WITH_PARENT, 'KEEP'),
+)
+
+r5_main_flags = (
+    (rf.RAR5_MAIN_FLAG_ISVOL, 'ISVOL'),
+    (rf.RAR5_MAIN_FLAG_HAS_VOLNR, 'VOLNR'),
+    (rf.RAR5_MAIN_FLAG_SOLID, 'SOLID'),
+    (rf.RAR5_MAIN_FLAG_RECOVERY, 'RECOVERY'),
+    (rf.RAR5_MAIN_FLAG_LOCKED, 'LOCKED'),
+)
+
+r5_file_flags = (
+    (rf.RAR5_FILE_FLAG_ISDIR, 'DIR'),
+    (rf.RAR5_FILE_FLAG_HAS_MTIME, 'MTIME'),
+    (rf.RAR5_FILE_FLAG_HAS_CRC32, 'CRC32'),
+    (rf.RAR5_FILE_FLAG_UNKNOWN_SIZE, 'NOSIZE'),
+)
+
+r5_enc_flags = (
+    (rf.RAR5_ENC_FLAG_HAS_CHECKVAL, 'CHECKVAL'),
+)
+
+r5_endarc_flags = (
+    (rf.RAR5_ENDARC_FLAG_NEXT_VOL, 'NEXTVOL'),
+)
+
+r5_file_enc_flags = (
+    (rf.RAR5_XENC_CHECKVAL, 'CHECKVAL'),
+    (rf.RAR5_XENC_TWEAKED, 'TWEAKED'),
+)
+
+r5_file_redir_types = {
+    rf.RAR5_XREDIR_UNIX_SYMLINK: 'UNIX_SYMLINK',
+    rf.RAR5_XREDIR_WINDOWS_SYMLINK: 'WINDOWS_SYMLINK',
+    rf.RAR5_XREDIR_WINDOWS_JUNCTION: 'WINDOWS_JUNCTION',
+    rf.RAR5_XREDIR_HARD_LINK: 'HARD_LINK',
+    rf.RAR5_XREDIR_FILE_COPY: 'FILE_COPY',
+}
+
+r5_file_redir_flags = (
+    (rf.RAR5_XREDIR_ISDIR, 'DIR'),
+)
+
+
 def xprint(m, *args):
+    """Print string to stdout.
+
+    Format unicode safely.
+    """
     if sys.hexversion < 0x3000000:
         m = m.decode('utf8')
     if args:
@@ -99,7 +165,10 @@ def xprint(m, *args):
     sys.stdout.write(m)
     sys.stdout.write('\n')
 
+
 def render_flags(flags, bit_list):
+    """Show bit names.
+    """
     res = []
     known = 0
     for bit in bit_list:
@@ -114,37 +183,48 @@ def render_flags(flags, bit_list):
         unknown = unknown >> 1
         n += 1
 
+    if not res:
+        return '-'
+
     return ",".join(res)
 
+
 def get_file_flags(flags):
+    """Show flag names and handle dict size.
+    """
     res = render_flags(flags & ~rf.RAR_FILE_DICTMASK, file_bits)
 
     xf = (flags & rf.RAR_FILE_DICTMASK) >> 5
     res += "," + file_parms[xf]
     return res
 
-def get_main_flags(flags):
-    return render_flags(flags, main_bits)
-
-def get_endarc_flags(flags):
-    return render_flags(flags, endarc_bits)
-
-def get_generic_flags(flags):
-    return render_flags(flags, generic_bits)
 
 def fmt_time(t):
+    """Format time.
+    """
+    if t is None:
+        return '(-)'
     if isinstance(t, datetime):
-        return t.isoformat(' ')
+        return t.isoformat('T')
     return "%04d-%02d-%02d %02d:%02d:%02d" % t
 
+
 def show_item(h):
-    st = rarType(h.type)
-    unknown = h.header_size - h.header_base
-    xprint("%s: hdrlen=%d datlen=%d hdr_unknown=%d", st, h.header_size,
-                h.add_size, unknown)
-    if unknown > 0 and cf_verbose > 1:
-        dat = h.header_data[h.header_base : ]
-        xprint("  unknown: %s", hexlify(dat))
+    """Show any RAR3/5 record.
+    """
+    if isinstance(h, rf.Rar3Info):
+        show_item_v3(h)
+    elif isinstance(h, rf.Rar5Info):
+        show_item_v5(h)
+    else:
+        xprint('Unknown info record')
+
+
+def show_item_v3(h):
+    """Show any RAR3 record.
+    """
+    st = rar3_type(h.type)
+    xprint("%s: hdrlen=%d datlen=%d", st, h.header_size, h.add_size)
     if h.type in (rf.RAR_BLOCK_FILE, rf.RAR_BLOCK_SUB):
         if h.host_os == rf.RAR_OS_UNIX:
             s_mode = "0%o" % h.mode
@@ -156,11 +236,11 @@ def show_item(h):
         else:
             s_os = "?"
         xprint("  os=%d:%s ver=%d mode=%s meth=%c cmp=%d dec=%d vol=%d",
-                h.host_os, s_os,
-                h.extract_version, s_mode, h.compress_type,
-                h.compress_size, h.file_size, h.volume)
+               h.host_os, s_os,
+               h.extract_version, s_mode, h.compress_type,
+               h.compress_size, h.file_size, h.volume)
         ucrc = (h.CRC + (1 << 32)) & ((1 << 32) - 1)
-        xprint("  crc=0x%08x (%d) time=%s", ucrc, h.CRC, fmt_time(h.date_time))
+        xprint("  crc=0x%08x (%d) date_time=%s", ucrc, h.CRC, fmt_time(h.date_time))
         xprint("  name=%s", h.filename)
         if h.mtime:
             xprint("  mtime=%s", fmt_time(h.mtime))
@@ -171,13 +251,93 @@ def show_item(h):
         if h.arctime:
             xprint("  arctime=%s", fmt_time(h.arctime))
     elif h.type == rf.RAR_BLOCK_MAIN:
-        xprint("  flags=0x%04x:%s", h.flags, get_main_flags(h.flags))
+        xprint("  flags=0x%04x:%s", h.flags, render_flags(h.flags, main_bits))
     elif h.type == rf.RAR_BLOCK_ENDARC:
-        xprint("  flags=0x%04x:%s", h.flags, get_endarc_flags(h.flags))
+        xprint("  flags=0x%04x:%s", h.flags, render_flags(h.flags, endarc_bits))
     elif h.type == rf.RAR_BLOCK_MARK:
         xprint("  flags=0x%04x:", h.flags)
     else:
-        xprint("  flags=0x%04x:%s", h.flags, get_generic_flags(h.flags))
+        xprint("  flags=0x%04x:%s", h.flags, render_flags(h.flags, generic_bits))
+
+    if h.comment is not None:
+        cm = repr(h.comment)
+        if cm[0] == 'u':
+            cm = cm[1:]
+        xprint("  comment=%s", cm)
+
+
+def show_item_v5(h):
+    """Show any RAR5 record.
+    """
+    st = rar5_type(h.block_type)
+    xprint("%s: hdrlen=%d datlen=%d hdr_extra=%d", st, h.header_size,
+           h.compress_size, h.block_extra_size)
+    xprint("  block_flags=0x%04x:%s", h.block_flags, render_flags(h.block_flags, r5_block_flags))
+    if h.block_type in (rf.RAR5_BLOCK_FILE, rf.RAR5_BLOCK_SERVICE):
+        xprint("  name=%s", h.filename)
+        if h.file_host_os == rf.RAR5_OS_UNIX:
+            s_os = 'UNIX'
+            s_mode = "0%o" % h.mode
+        else:
+            s_os = 'WINDOWS'
+            s_mode = "0x%x" % h.mode
+        xprint("  file_flags=0x%04x:%s", h.file_flags, render_flags(h.file_flags, r5_file_flags))
+
+        cmp_flags = h.file_compress_flags
+        xprint("  cmp_algo=%d cmp_meth=%d dict=%d solid=%r",
+               cmp_flags & 0x3f,
+               (cmp_flags >> 7) & 0x07,
+               cmp_flags >> 10,
+               cmp_flags & rf.RAR5_COMPR_SOLID > 0)
+        xprint("  os=%d:%s mode=%s cmp=%r dec=%r vol=%r",
+               h.file_host_os, s_os, s_mode,
+               h.compress_size, h.file_size, h.volume)
+        if h.CRC is not None:
+            xprint("  crc=0x%08x (%d)", h.CRC, h.CRC)
+        if h.blake2sp_hash is not None:
+            xprint("  blake2sp=%s", rf.tohex(h.blake2sp_hash))
+        if h.date_time is not None:
+            xprint("  date_time=%s", fmt_time(h.date_time))
+        if h.mtime:
+            xprint("  mtime=%s", fmt_time(h.mtime))
+        if h.ctime:
+            xprint("  ctime=%s", fmt_time(h.ctime))
+        if h.atime:
+            xprint("  atime=%s", fmt_time(h.atime))
+        if h.arctime:
+            xprint("  arctime=%s", fmt_time(h.arctime))
+        if h.flags & rf.RAR_FILE_PASSWORD:
+            enc_algo, enc_flags, kdf_count, salt, iv, checkval = h.file_encryption
+            algo_name = enc_algo == rf.RAR5_XENC_CIPHER_AES256 and 'AES256' or 'UnknownAlgo'
+            xprint('  algo=%d:%s enc_flags=%04x:%s kdf_lg=%d kdf_count=%d salt=%s iv=%s checkval=%s',
+                   enc_algo, algo_name, enc_flags, render_flags(enc_flags, r5_file_enc_flags),
+                   kdf_count, 1 << kdf_count, rf.tohex(salt), rf.tohex(iv),
+                   checkval and rf.tohex(checkval) or '-')
+        if h.file_redir:
+            redir_type, redir_flags, redir_name = h.file_redir
+            xprint('  redir: type=%s flags=%d:%s destination=%s',
+                   r5_file_redir_types.get(redir_type, 'Unknown'),
+                   redir_flags, render_flags(redir_flags, r5_file_redir_flags),
+                   redir_name)
+        if h.file_owner:
+            uname, gname, uid, gid = h.file_owner
+            xprint('  owner: name=%r group=%r uid=%r gid=%r',
+                   uname, gname, uid, gid)
+        if h.file_version:
+            flags, version = h.file_version
+            xprint('  version: flags=%r version=%r', flags, version)
+    elif h.block_type == rf.RAR5_BLOCK_MAIN:
+        xprint("  flags=0x%04x:%s", h.flags, render_flags(h.main_flags, r5_main_flags))
+    elif h.block_type == rf.RAR5_BLOCK_ENDARC:
+        xprint("  flags=0x%04x:%s", h.flags, render_flags(h.endarc_flags, r5_endarc_flags))
+    elif h.block_type == rf.RAR5_BLOCK_ENCRYPTION:
+        algo_name = h.encryption_algo == rf.RAR5_XENC_CIPHER_AES256 and 'AES256' or 'UnknownAlgo'
+        xprint("  algo=%d:%s flags=0x%04x:%s", h.encryption_algo, algo_name, h.flags,
+               render_flags(h.encryption_flags, r5_enc_flags))
+        xprint("  kdf_lg=%d kdf_count=%d", h.encryption_kdf_count, 1 << h.encryption_kdf_count)
+        xprint("  salt=%s", rf.tohex(h.encryption_salt))
+    else:
+        xprint("  - missing info -")
 
     if h.comment is not None:
         cm = repr(h.comment)
@@ -185,6 +345,7 @@ def show_item(h):
             cm = cm[1:]
         xprint("  comment=%s", cm)
 
+
 cf_show_comment = 0
 cf_verbose = 0
 cf_charset = None
@@ -193,36 +354,50 @@ cf_test_read = 0
 cf_test_unrar = 0
 cf_test_memory = 0
 
-def check_crc(f, inf):
-    ucrc = f.CRC
-    if ucrc < 0:
-        ucrc += (long(1) << 32)
-    if ucrc != inf.CRC:
-        print ('crc error')
+
+def check_crc(f, inf, desc):
+    """Compare result crc to expected value.
+    """
+    exp = inf._md_expect
+    if exp is None:
+        return
+    ucrc = f._md_context.digest()
+    if ucrc != exp:
+        print('crc error - %s - exp=%r got=%r' % (desc, exp, ucrc))
+
 
 def test_read_long(r, inf):
+    """Test read and readinto.
+    """
+    md_class = inf._md_class or rf.NoHashContext
+    bctx = md_class()
     f = r.open(inf.filename)
     total = 0
     while 1:
         data = f.read(8192)
         if not data:
             break
+        bctx.update(data)
         total += len(data)
     if total != inf.file_size:
         xprint("\n *** %s has corrupt file: %s ***", r.rarfile, inf.filename)
         xprint(" *** short read: got=%d, need=%d ***\n", total, inf.file_size)
-    check_crc(f, inf)
+    check_crc(f, inf, 'read')
+    bhash = bctx.hexdigest()
+    if cf_verbose > 1:
+        if f._md_context.digest() == inf._md_expect:
+            #xprint("  checkhash: %r", bhash)
+            pass
+        else:
+            xprint("  checkhash: %r  got=%r exp=%r cls=%r\n",
+                   bhash, f._md_context.digest(), inf._md_expect, inf._md_class)
 
     # test .seek() & .readinto()
     if cf_test_read > 1:
-        f.seek(0,0)
-
-        # hack: re-enable crc calc
-        f.crc_check = 1
-        f.CRC = 0
+        f.seek(0, 0)
 
         total = 0
-        buf = bytearray(rf.ZERO*4096)
+        buf = bytearray(rf.ZERO * 1024)
         while 1:
             res = f.readinto(buf)
             if not res:
@@ -230,14 +405,18 @@ def test_read_long(r, inf):
             total += res
         if inf.file_size != total:
             xprint(" *** readinto failed: got=%d, need=%d ***\n", total, inf.file_size)
-        check_crc(f, inf)
+        #check_crc(f, inf, 'readinto')
     f.close()
 
+
 def test_read(r, inf):
+    """Test file read."""
     test_read_long(r, inf)
 
 
 def test_real(fn, psw):
+    """Actual archive processing.
+    """
     xprint("Archive: %s", fn)
 
     cb = None
@@ -254,7 +433,7 @@ def test_real(fn, psw):
         return
 
     # open
-    r = rf.RarFile(rfarg, charset = cf_charset, info_callback = cb)
+    r = rf.RarFile(rfarg, charset=cf_charset, info_callback=cb)
     # set password
     if r.needs_password():
         if psw:
@@ -267,7 +446,7 @@ def test_real(fn, psw):
     if cf_show_comment and r.comment:
         for ln in r.comment.split('\n'):
             xprint("    %s", ln)
-    elif cf_verbose == 1 and r.comment:
+    elif cf_verbose > 0 and r.comment:
         cm = repr(r.comment)
         if cm[0] == 'u':
             cm = cm[1:]
@@ -291,7 +470,10 @@ def test_real(fn, psw):
     if cf_test_unrar:
         r.testrar()
 
+
 def test(fn, psw):
+    """Process one archive with error handling.
+    """
     try:
         test_real(fn, psw)
     except rf.NeedFirstVolume:
@@ -305,54 +487,67 @@ def test(fn, psw):
         xprint("\n *** %s: %s ***\n", exc.__name__, msg)
         del tb
 
+
 def main():
+    """Program entry point.
+    """
     global cf_verbose, cf_show_comment, cf_charset
     global cf_extract, cf_test_read, cf_test_unrar
     global cf_test_memory
 
-    # parse args
-    args = []
     psw = None
-    noswitch = False
-    for a in sys.argv[1:]:
-        if noswitch:
-            args.append(a)
-        elif a[0] == "@":
-            for ln in open(a[1:], 'r'):
-                fn = ln[:-1]
-                args.append(fn)
-        elif a[0] != '-':
-            args.append(a)
-        elif a[1] == 'p':
-            psw = a[2:]
-        elif a == '--':
-            noswitch = True
-        elif a == '-h':
+
+    # parse args
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'p:C:hvcxtRM')
+    except getopt.error as ex:
+        print(str(ex), file=sys.stderr)
+        sys.exit(1)
+
+    for o, v in opts:
+        if o == '-p':
+            psw = v
+        elif o == '-h':
             xprint(usage)
             return
-        elif a == '-v':
+        elif o == '-v':
             cf_verbose += 1
-        elif a == '-c':
+        elif o == '-c':
             cf_show_comment = 1
-        elif a == '-x':
+        elif o == '-x':
             cf_extract = 1
-        elif a == '-t':
+        elif o == '-t':
             cf_test_read += 1
-        elif a == '-T':
+        elif o == '-T':
             cf_test_unrar = 1
-        elif a == '-M':
+        elif o == '-M':
             cf_test_memory = 1
-        elif a[1] == 'C':
-            cf_charset = a[2:]
+        elif o == '-C':
+            cf_charset = v
+        else:
+            raise Exception("unhandled switch: " + o)
+
+    args2 = []
+    for a in args:
+        if a[0] == "@":
+            for ln in open(a[1:], 'r'):
+                fn = ln[:-1]
+                args2.append(fn)
         else:
-            raise Exception("unknown switch: "+a)
+            args2.append(a)
+    args = args2
+
     if not args:
         xprint(usage)
 
+    # pypy .readinto()+memoryview() is buggy
+    #if cf_test_read > 1 and hasattr(sys, 'pypy_version_info'):
+    #    cf_test_read = 1
+
     for fn in args:
         test(fn, psw)
 
-    
+
 if __name__ == '__main__':
     try:
         main()
diff --git a/PKG-INFO b/rarfile.egg-info/PKG-INFO
similarity index 88%
copy from PKG-INFO
copy to rarfile.egg-info/PKG-INFO
index 282b56d..3a6d9a7 100644
--- a/PKG-INFO
+++ b/rarfile.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: rarfile
-Version: 2.8
+Version: 3.0
 Summary: RAR archive reader for Python
 Home-page: https://github.com/markokr/rarfile
 Author: Marko Kreen
@@ -15,7 +15,7 @@ Description: rarfile - RAR archive reader for Python
         
         Features:
         
-        - Supports both RAR2 and RAR3 archives (WinRAR 2.x .. WinRAR 4.x).
+        - Supports both RAR3 and RAR5 format archives.
         - Supports multi volume archives.
         - Supports Unicode filenames.
         - Supports password-protected archives.
@@ -25,23 +25,18 @@ Description: rarfile - RAR archive reader for Python
           from RARLAB_ or ``bsdtar`` from libarchive_.
         - Works with both Python 2.7 and 3.x.
         
-        Notes:
-        
-        - Does not support the RAR5 format introduced in WinRAR 5.0.
-        - ``bsdtar`` does not support all RAR3 features.
-        
         Links:
         
         - `Documentation`_
         - `Downloads`_
         - `Git`_ repo
         
-        .. _RAR: https://en.wikipedia.org/wiki/RAR_%28file_format%29
-        .. _zipfile: https://docs.python.org/2/library/zipfile.html
-        .. _ISC: https://en.wikipedia.org/wiki/ISC_license
         .. _Git: https://github.com/markokr/rarfile
         .. _Downloads: https://pypi.python.org/pypi/rarfile
         .. _Documentation: https://rarfile.readthedocs.io/
+        .. _RAR: https://en.wikipedia.org/wiki/RAR_%28file_format%29
+        .. _zipfile: https://docs.python.org/2/library/zipfile.html
+        .. _ISC: https://en.wikipedia.org/wiki/ISC_license
         .. _libarchive: https://github.com/libarchive/libarchive
         .. _RARLAB: http://www.rarlab.com/
 Keywords: rar,unrar,archive
diff --git a/rarfile.egg-info/SOURCES.txt b/rarfile.egg-info/SOURCES.txt
new file mode 100644
index 0000000..89faaab
--- /dev/null
+++ b/rarfile.egg-info/SOURCES.txt
@@ -0,0 +1,95 @@
+LICENSE
+MANIFEST.in
+Makefile
+README.rst
+dumprar.py
+rarfile.py
+setup.py
+doc/Makefile
+doc/api.rst
+doc/conf.py
+doc/faq.rst
+doc/index.rst
+doc/make.bat
+doc/news.rst
+rarfile.egg-info/PKG-INFO
+rarfile.egg-info/SOURCES.txt
+rarfile.egg-info/dependency_links.txt
+rarfile.egg-info/top_level.txt
+test/run_dump.sh
+test/run_dump_all.sh
+test/test_api.py
+test/test_crypto.py
+test/test_format.py
+test/test_hashing.py
+test/test_korrupt.py
+test/test_reading.py
+test/test_seek.py
+test/files/ctime0.rar
+test/files/ctime0.rar.exp
+test/files/ctime1.rar
+test/files/ctime1.rar.exp
+test/files/ctime2.rar
+test/files/ctime2.rar.exp
+test/files/ctime3.rar
+test/files/ctime3.rar.exp
+test/files/ctime4.rar
... 5669 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-rarfile.git



More information about the Python-modules-commits mailing list