[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