update path, add python unrar
This commit is contained in:
parent
642ba49f68
commit
00165d302e
862 changed files with 804 additions and 6 deletions
22
Shared/lib/python3.7/site-packages/unrar/__init__.py
Normal file
22
Shared/lib/python3.7/site-packages/unrar/__init__.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2012 Matias Bordese
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = 'Matias Bordese'
|
||||
__email__ = 'mbordese@gmail.com'
|
||||
__version__ = '0.3'
|
||||
|
||||
VERSION = __version__
|
||||
107
Shared/lib/python3.7/site-packages/unrar/constants.py
Normal file
107
Shared/lib/python3.7/site-packages/unrar/constants.py
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2012 Matias Bordese
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# Success result
|
||||
SUCCESS = 0
|
||||
|
||||
#
|
||||
# Open Modes
|
||||
#
|
||||
|
||||
# headers only
|
||||
RAR_OM_LIST = 0
|
||||
# testing and extracting
|
||||
RAR_OM_EXTRACT = 1
|
||||
# headers only, include splitted volumes
|
||||
RAR_OM_LIST_INCSPLIT = 2
|
||||
|
||||
#
|
||||
# Process file operations
|
||||
#
|
||||
|
||||
RAR_SKIP = 0
|
||||
RAR_TEST = 1
|
||||
RAR_EXTRACT = 2
|
||||
RAR_CANCEL_EXTRACT = -1
|
||||
|
||||
#
|
||||
# Errors
|
||||
#
|
||||
|
||||
# End of archive
|
||||
ERAR_END_ARCHIVE = 10
|
||||
# Not enough memory to initialize data structures
|
||||
ERAR_NO_MEMORY = 11
|
||||
# Archive header broken
|
||||
ERAR_BAD_DATA = 12
|
||||
# File is not valid RAR archive
|
||||
ERAR_BAD_ARCHIVE = 13
|
||||
# Unknown encryption used for archive headers
|
||||
ERAR_UNKNOWN_FORMAT = 14
|
||||
# Archive/Volume open error
|
||||
ERAR_EOPEN = 15
|
||||
# File create error
|
||||
ERAR_ECREATE = 16
|
||||
# Archive/File close error
|
||||
ERAR_ECLOSE = 17
|
||||
# Read error
|
||||
ERAR_EREAD = 18
|
||||
# Write error
|
||||
ERAR_EWRITE = 19
|
||||
# Buffer too small, comments not completely read
|
||||
ERAR_SMALL_BUF = 20
|
||||
# Unknown error
|
||||
ERAR_UNKNOWN = 21
|
||||
# Missing password error
|
||||
ERAR_MISSING_PASSWORD = 22
|
||||
|
||||
#
|
||||
# Comments state
|
||||
#
|
||||
|
||||
# comments not present
|
||||
RAR_NO_COMMENTS = 0
|
||||
# Comments read completely
|
||||
RAR_COMMENTS_SUCCESS = 1
|
||||
|
||||
|
||||
#
|
||||
# Host OS
|
||||
#
|
||||
|
||||
RAR_DOS = 0
|
||||
RAR_OS2 = 1
|
||||
RAR_WIN = 2
|
||||
RAR_UNIX = 3
|
||||
|
||||
|
||||
#
|
||||
# Callback messages
|
||||
#
|
||||
|
||||
UCM_CHANGEVOLUME = 0
|
||||
UCM_PROCESSDATA = 1
|
||||
UCM_NEEDPASSWORD = 2
|
||||
UCM_CHANGEVOLUMEW = 3
|
||||
UCM_NEEDPASSWORDW = 4
|
||||
|
||||
#
|
||||
# Change volume callback message
|
||||
#
|
||||
RAR_VOL_ASK = 0
|
||||
RAR_VOL_NOTIFY = 1
|
||||
362
Shared/lib/python3.7/site-packages/unrar/rarfile.py
Normal file
362
Shared/lib/python3.7/site-packages/unrar/rarfile.py
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2012 Matias Bordese
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import ctypes
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
|
||||
from unrar import constants
|
||||
from unrar import unrarlib
|
||||
|
||||
|
||||
__all__ = ["BadRarFile", "is_rarfile", "RarFile", "RarInfo"]
|
||||
|
||||
|
||||
if sys.version < '3':
|
||||
def b(x):
|
||||
return x
|
||||
else:
|
||||
def b(x):
|
||||
if x is not None:
|
||||
# encode using DOS OEM standard
|
||||
return x.encode('cp437')
|
||||
|
||||
|
||||
class BadRarFile(Exception):
|
||||
"""RAR file error."""
|
||||
|
||||
|
||||
def is_rarfile(filename):
|
||||
"""Return true if file is a valid RAR file."""
|
||||
mode = constants.RAR_OM_LIST_INCSPLIT
|
||||
archive = unrarlib.RAROpenArchiveDataEx(filename, mode=mode)
|
||||
try:
|
||||
handle = unrarlib.RAROpenArchiveEx(ctypes.byref(archive))
|
||||
except unrarlib.UnrarException:
|
||||
return False
|
||||
unrarlib.RARCloseArchive(handle)
|
||||
return (archive.OpenResult == constants.SUCCESS)
|
||||
|
||||
|
||||
class RarInfo(object):
|
||||
"""Class with attributes describing each member in the RAR archive."""
|
||||
|
||||
__slots__ = (
|
||||
'filename',
|
||||
'date_time',
|
||||
'compress_type',
|
||||
'comment',
|
||||
'create_system',
|
||||
'extract_version',
|
||||
'flag_bits',
|
||||
'CRC',
|
||||
'compress_size',
|
||||
'file_size',
|
||||
'_raw_time',
|
||||
)
|
||||
|
||||
def __init__(self, header):
|
||||
"""Initialize a RarInfo object with a member header data."""
|
||||
self.filename = header.FileNameW
|
||||
self._raw_time = header.FileTime
|
||||
self.date_time = unrarlib.dostime_to_timetuple(header.FileTime)
|
||||
self.compress_size = header.PackSize + (header.PackSizeHigh << 32)
|
||||
self.file_size = header.UnpSize + (header.UnpSizeHigh << 32)
|
||||
self.create_system = header.HostOS
|
||||
self.extract_version = header.UnpVer
|
||||
self.CRC = header.FileCRC
|
||||
self.flag_bits = header.Flags
|
||||
if header.CmtState == constants.RAR_COMMENTS_SUCCESS:
|
||||
self.comment = header.CmtBuf.value
|
||||
else:
|
||||
self.comment = None
|
||||
|
||||
|
||||
class _ReadIntoMemory(object):
|
||||
"""Internal class to handle in-memory extraction."""
|
||||
|
||||
def __init__(self):
|
||||
super(_ReadIntoMemory, self).__init__()
|
||||
self._data = None
|
||||
|
||||
def _callback(self, msg, user_data, p1, p2):
|
||||
if msg == constants.UCM_PROCESSDATA:
|
||||
if self._data is None:
|
||||
self._data = b('')
|
||||
chunk = (ctypes.c_char * p2).from_address(p1).raw
|
||||
self._data += chunk
|
||||
return 1
|
||||
|
||||
def get_bytes(self):
|
||||
return io.BytesIO(self._data)
|
||||
|
||||
|
||||
class RarFile(object):
|
||||
"""RAR archive file."""
|
||||
|
||||
def __init__(self, filename, mode='r', pwd=None):
|
||||
"""Load RAR archive file with mode read only "r"."""
|
||||
self.filename = filename
|
||||
mode = constants.RAR_OM_LIST_INCSPLIT
|
||||
|
||||
archive = unrarlib.RAROpenArchiveDataEx(filename, mode=mode)
|
||||
handle = self._open(archive)
|
||||
|
||||
# assert(archive.OpenResult == constants.SUCCESS)
|
||||
self.pwd = pwd
|
||||
self.filelist = []
|
||||
self.NameToInfo = {}
|
||||
if archive.CmtState == constants.RAR_COMMENTS_SUCCESS:
|
||||
self.comment = archive.CmtBuf.value
|
||||
else:
|
||||
self.comment = None
|
||||
self._load_metadata(handle)
|
||||
self._close(handle)
|
||||
|
||||
def _read_header(self, handle):
|
||||
"""Read current member header into a RarInfo object."""
|
||||
rarinfo = None
|
||||
header_data = unrarlib.RARHeaderDataEx()
|
||||
res = unrarlib.RARReadHeaderEx(handle, ctypes.byref(header_data))
|
||||
if res != constants.ERAR_END_ARCHIVE:
|
||||
rarinfo = RarInfo(header=header_data)
|
||||
return rarinfo
|
||||
|
||||
def _process_current(self, handle, op, dest_path=None, dest_name=None):
|
||||
"""Process current member with 'op' operation."""
|
||||
unrarlib.RARProcessFileW(handle, op, dest_path, dest_name)
|
||||
|
||||
def _load_metadata(self, handle):
|
||||
"""Load archive members metadata."""
|
||||
rarinfo = self._read_header(handle)
|
||||
while rarinfo:
|
||||
self.filelist.append(rarinfo)
|
||||
self.NameToInfo[rarinfo.filename] = rarinfo
|
||||
self._process_current(handle, constants.RAR_SKIP)
|
||||
rarinfo = self._read_header(handle)
|
||||
|
||||
def _open(self, archive):
|
||||
"""Open RAR archive file."""
|
||||
try:
|
||||
handle = unrarlib.RAROpenArchiveEx(ctypes.byref(archive))
|
||||
except unrarlib.UnrarException:
|
||||
raise BadRarFile("Invalid RAR file.")
|
||||
return handle
|
||||
|
||||
def _close(self, handle):
|
||||
"""Close RAR archive file."""
|
||||
try:
|
||||
unrarlib.RARCloseArchive(handle)
|
||||
except unrarlib.UnrarException:
|
||||
raise BadRarFile("RAR archive close error.")
|
||||
|
||||
def open(self, member, pwd=None):
|
||||
"""Return file-like object for 'member'.
|
||||
|
||||
'member' may be a filename or a RarInfo object.
|
||||
"""
|
||||
if isinstance(member, RarInfo):
|
||||
member = member.filename
|
||||
|
||||
archive = unrarlib.RAROpenArchiveDataEx(
|
||||
self.filename, mode=constants.RAR_OM_EXTRACT)
|
||||
handle = self._open(archive)
|
||||
|
||||
password = pwd or self.pwd
|
||||
if password is not None:
|
||||
unrarlib.RARSetPassword(handle, b(password))
|
||||
|
||||
# based on BrutuZ (https://github.com/matiasb/python-unrar/pull/4)
|
||||
# and Cubixmeister work
|
||||
data = _ReadIntoMemory()
|
||||
c_callback = unrarlib.UNRARCALLBACK(data._callback)
|
||||
unrarlib.RARSetCallback(handle, c_callback, 0)
|
||||
|
||||
try:
|
||||
rarinfo = self._read_header(handle)
|
||||
while rarinfo is not None:
|
||||
if rarinfo.filename == member:
|
||||
self._process_current(handle, constants.RAR_TEST)
|
||||
break
|
||||
else:
|
||||
self._process_current(handle, constants.RAR_SKIP)
|
||||
rarinfo = self._read_header(handle)
|
||||
|
||||
if rarinfo is None:
|
||||
data = None
|
||||
|
||||
except unrarlib.UnrarException:
|
||||
raise BadRarFile("Bad RAR archive data.")
|
||||
finally:
|
||||
self._close(handle)
|
||||
|
||||
if data is None:
|
||||
raise KeyError('There is no item named %r in the archive' % member)
|
||||
|
||||
# return file-like object
|
||||
return data.get_bytes()
|
||||
|
||||
def read(self, member, pwd=None):
|
||||
"""Return file bytes (as a string) for name."""
|
||||
return self.open(member, pwd).read()
|
||||
|
||||
def namelist(self):
|
||||
"""Return a list of file names in the archive."""
|
||||
names = []
|
||||
for member in self.filelist:
|
||||
names.append(member.filename)
|
||||
return names
|
||||
|
||||
def setpassword(self, pwd):
|
||||
"""Set default password for encrypted files."""
|
||||
self.pwd = pwd
|
||||
|
||||
def getinfo(self, name):
|
||||
"""Return the instance of RarInfo given 'name'."""
|
||||
rarinfo = self.NameToInfo.get(name)
|
||||
if rarinfo is None:
|
||||
raise KeyError('There is no item named %r in the archive' % name)
|
||||
return rarinfo
|
||||
|
||||
def infolist(self):
|
||||
"""Return a list of class RarInfo instances for files in the
|
||||
archive."""
|
||||
return self.filelist
|
||||
|
||||
def printdir(self):
|
||||
"""Print a table of contents for the RAR file."""
|
||||
print("%-46s %19s %12s" % ("File Name", "Modified ", "Size"))
|
||||
for rarinfo in self.filelist:
|
||||
date = "%d-%02d-%02d %02d:%02d:%02d" % rarinfo.date_time[:6]
|
||||
print("%-46s %s %12d" % (
|
||||
rarinfo.filename, date, rarinfo.file_size))
|
||||
|
||||
def testrar(self):
|
||||
"""Read all the files and check the CRC."""
|
||||
error = None
|
||||
rarinfo = None
|
||||
archive = unrarlib.RAROpenArchiveDataEx(
|
||||
self.filename, mode=constants.RAR_OM_EXTRACT)
|
||||
handle = self._open(archive)
|
||||
|
||||
if self.pwd:
|
||||
unrarlib.RARSetPassword(handle, b(self.pwd))
|
||||
|
||||
try:
|
||||
rarinfo = self._read_header(handle)
|
||||
while rarinfo is not None:
|
||||
self._process_current(handle, constants.RAR_TEST)
|
||||
rarinfo = self._read_header(handle)
|
||||
except unrarlib.UnrarException:
|
||||
error = rarinfo.filename if rarinfo else self.filename
|
||||
finally:
|
||||
self._close(handle)
|
||||
return error
|
||||
|
||||
def extract(self, member, path=None, pwd=None):
|
||||
"""Extract a member from the archive to the current working directory,
|
||||
using its full name. Its file information is extracted as accurately
|
||||
as possible. `member' may be a filename or a RarInfo object. You can
|
||||
specify a different directory using `path'.
|
||||
"""
|
||||
if isinstance(member, RarInfo):
|
||||
member = member.filename
|
||||
|
||||
if path is None:
|
||||
path = os.getcwd()
|
||||
|
||||
self._extract_members([member], path, pwd)
|
||||
return os.path.join(path, member)
|
||||
|
||||
def extractall(self, path=None, members=None, pwd=None):
|
||||
"""Extract all members from the archive to the current working
|
||||
directory. `path' specifies a different directory to extract to.
|
||||
`members' is optional and must be a subset of the list returned
|
||||
by namelist().
|
||||
"""
|
||||
if members is None:
|
||||
members = self.namelist()
|
||||
self._extract_members(members, path, pwd)
|
||||
|
||||
def _extract_members(self, members, targetpath, pwd):
|
||||
"""Extract the RarInfo objects 'members' to a physical
|
||||
file on the path targetpath.
|
||||
"""
|
||||
archive = unrarlib.RAROpenArchiveDataEx(
|
||||
self.filename, mode=constants.RAR_OM_EXTRACT)
|
||||
handle = self._open(archive)
|
||||
|
||||
password = pwd or self.pwd
|
||||
if password is not None:
|
||||
unrarlib.RARSetPassword(handle, b(password))
|
||||
|
||||
try:
|
||||
rarinfo = self._read_header(handle)
|
||||
while rarinfo is not None:
|
||||
if rarinfo.filename in members:
|
||||
self._process_current(
|
||||
handle, constants.RAR_EXTRACT, targetpath)
|
||||
else:
|
||||
self._process_current(handle, constants.RAR_SKIP)
|
||||
rarinfo = self._read_header(handle)
|
||||
except unrarlib.UnrarException:
|
||||
raise BadRarFile("Bad RAR archive data.")
|
||||
finally:
|
||||
self._close(handle)
|
||||
|
||||
|
||||
def main(args=None):
|
||||
import textwrap
|
||||
USAGE = textwrap.dedent("""\
|
||||
Usage:
|
||||
rarfile.py -l rarfile.rar # Show listing of a rarfile
|
||||
rarfile.py -t rarfile.rar # Test if a rarfile is valid
|
||||
rarfile.py -e rarfile.rar target # Extract rarfile into target dir
|
||||
""")
|
||||
|
||||
valid_args = {'-l': 2, '-e': 3, '-t': 2}
|
||||
if args is None:
|
||||
args = sys.argv[1:]
|
||||
|
||||
cmd = args and args[0] or None
|
||||
if not cmd or cmd not in valid_args or len(args) != valid_args[cmd]:
|
||||
print(USAGE)
|
||||
sys.exit(1)
|
||||
|
||||
if cmd == '-l':
|
||||
# list
|
||||
rf = RarFile(args[1], 'r')
|
||||
rf.printdir()
|
||||
elif cmd == '-t':
|
||||
# test
|
||||
rf = RarFile(args[1], 'r')
|
||||
err = rf.testrar()
|
||||
if err:
|
||||
print("The following enclosed file is corrupted: {!r}".format(err))
|
||||
print("Done testing")
|
||||
elif cmd == '-e':
|
||||
# extract
|
||||
rf = RarFile(args[1], 'r')
|
||||
dest = args[2]
|
||||
rf.extractall(path=dest)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
254
Shared/lib/python3.7/site-packages/unrar/unrarlib.py
Normal file
254
Shared/lib/python3.7/site-packages/unrar/unrarlib.py
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2012 Matias Bordese
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ctypes
|
||||
import os
|
||||
import platform
|
||||
|
||||
from ctypes.util import find_library
|
||||
|
||||
from unrar import constants
|
||||
|
||||
|
||||
__all__ = ["RAROpenArchiveDataEx", "RARHeaderDataEx", "RAROpenArchiveEx",
|
||||
"RARCloseArchive", "RARReadHeaderEx", "RARProcessFile",
|
||||
"RARSetPassword", "RARGetDllVersion", "RARSetCallback",
|
||||
"dostime_to_timetuple"]
|
||||
|
||||
|
||||
lib_path = os.environ.get('UNRAR_LIB_PATH', None)
|
||||
|
||||
# find and load unrar library
|
||||
unrarlib = None
|
||||
if platform.system() == 'Windows':
|
||||
from ctypes.wintypes import HANDLE as WIN_HANDLE
|
||||
HANDLE = WIN_HANDLE
|
||||
UNRARCALLBACK = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_uint,
|
||||
ctypes.c_long, ctypes.c_long,
|
||||
ctypes.c_long)
|
||||
lib_path = lib_path or find_library("unrar.dll")
|
||||
if lib_path:
|
||||
unrarlib = ctypes.WinDLL(lib_path)
|
||||
else:
|
||||
# assume unix
|
||||
HANDLE = ctypes.c_void_p
|
||||
UNRARCALLBACK = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_uint,
|
||||
ctypes.c_long, ctypes.c_long,
|
||||
ctypes.c_long)
|
||||
lib_path = lib_path or find_library("unrar")
|
||||
if lib_path:
|
||||
unrarlib = ctypes.cdll.LoadLibrary(lib_path)
|
||||
|
||||
if unrarlib is None:
|
||||
raise LookupError("Couldn't find path to unrar library.")
|
||||
|
||||
|
||||
def dostime_to_timetuple(dostime):
|
||||
"""Convert a RAR archive member DOS time to a Python time tuple."""
|
||||
dostime = dostime >> 16
|
||||
dostime = dostime & 0xffff
|
||||
day = dostime & 0x1f
|
||||
month = (dostime >> 5) & 0xf
|
||||
year = 1980 + (dostime >> 9)
|
||||
second = 2 * (dostime & 0x1f)
|
||||
minute = (dostime >> 5) & 0x3f
|
||||
hour = dostime >> 11
|
||||
return (year, month, day, hour, minute, second)
|
||||
|
||||
|
||||
class UnrarException(Exception):
|
||||
"""Lib errors exception."""
|
||||
|
||||
|
||||
class _Structure(ctypes.Structure):
|
||||
"""Customized ctypes Structure base class."""
|
||||
|
||||
def __repr__(self):
|
||||
"""Print the structure fields."""
|
||||
res = []
|
||||
for field in self._fields_:
|
||||
field_value = repr(getattr(self, field[0]))
|
||||
res.append('%s=%s' % (field[0], field_value))
|
||||
return self.__class__.__name__ + '(' + ','.join(res) + ')'
|
||||
|
||||
|
||||
class RAROpenArchiveDataEx(_Structure):
|
||||
"""Rar compressed file structure."""
|
||||
_fields_ = [
|
||||
('ArcName', ctypes.c_char_p),
|
||||
('ArcNameW', ctypes.c_wchar_p),
|
||||
('OpenMode', ctypes.c_uint),
|
||||
('OpenResult', ctypes.c_uint),
|
||||
('_CmtBuf', ctypes.c_void_p),
|
||||
('CmtBufSize', ctypes.c_uint),
|
||||
('CmtSize', ctypes.c_uint),
|
||||
('CmtState', ctypes.c_uint),
|
||||
('Flags', ctypes.c_uint),
|
||||
('Reserved', ctypes.c_uint * 32),
|
||||
]
|
||||
|
||||
def __init__(self, filename, mode=constants.RAR_OM_LIST):
|
||||
# comments buffer, max 64kb
|
||||
self.CmtBuf = ctypes.create_string_buffer(b'', 64 * 1024)
|
||||
super(RAROpenArchiveDataEx, self).__init__(
|
||||
ArcName=None,
|
||||
ArcNameW=filename, OpenMode=mode,
|
||||
_CmtBuf=ctypes.addressof(self.CmtBuf),
|
||||
CmtBufSize=ctypes.sizeof(self.CmtBuf))
|
||||
|
||||
def __str__(self):
|
||||
return self.ArcNameW
|
||||
|
||||
|
||||
class RARHeaderDataEx(_Structure):
|
||||
"""Rar file header structure."""
|
||||
_fields_ = [
|
||||
('ArcName', ctypes.c_char * 1024),
|
||||
('ArcNameW', ctypes.c_wchar * 1024),
|
||||
('FileName', ctypes.c_char * 1024),
|
||||
('FileNameW', ctypes.c_wchar * 1024),
|
||||
('Flags', ctypes.c_uint),
|
||||
('PackSize', ctypes.c_uint),
|
||||
('PackSizeHigh', ctypes.c_uint),
|
||||
('UnpSize', ctypes.c_uint),
|
||||
('UnpSizeHigh', ctypes.c_uint),
|
||||
('HostOS', ctypes.c_uint),
|
||||
('FileCRC', ctypes.c_uint),
|
||||
('FileTime', ctypes.c_uint),
|
||||
('UnpVer', ctypes.c_uint),
|
||||
('Method', ctypes.c_uint),
|
||||
('FileAttr', ctypes.c_uint),
|
||||
('_CmtBuf', ctypes.c_void_p),
|
||||
('CmtBufSize', ctypes.c_uint),
|
||||
('CmtSize', ctypes.c_uint),
|
||||
('CmtState', ctypes.c_uint),
|
||||
('Reserved', ctypes.c_uint * 1024),
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
# comments buffer, max 64kb
|
||||
self.CmtBuf = ctypes.create_string_buffer(b'', 64 * 1024)
|
||||
super(RARHeaderDataEx, self).__init__(
|
||||
_CmtBuf=ctypes.addressof(self.CmtBuf),
|
||||
CmtBufSize=ctypes.sizeof(self.CmtBuf))
|
||||
|
||||
def __str__(self):
|
||||
return self.FileNameW
|
||||
|
||||
|
||||
def _c_func(func, restype, argtypes, errcheck=None):
|
||||
"""Wrap c function setting prototype."""
|
||||
func.restype = restype
|
||||
func.argtypes = argtypes
|
||||
if errcheck is not None:
|
||||
func.errcheck = errcheck
|
||||
return func
|
||||
|
||||
|
||||
def _check_open_result(res, func, args):
|
||||
if res is None:
|
||||
raise UnrarException("Archive open error")
|
||||
# res is the archive handle
|
||||
return res
|
||||
|
||||
|
||||
def _check_readheader_result(res, func, args):
|
||||
if res == constants.ERAR_BAD_DATA:
|
||||
raise UnrarException("Bad header data.")
|
||||
# res == SUCCESS | res == ERAR_END_ARCHIVE
|
||||
return res
|
||||
|
||||
|
||||
def _check_process_result(res, func, args):
|
||||
if res == constants.ERAR_ECLOSE:
|
||||
raise UnrarException("File close error")
|
||||
elif res == constants.ERAR_BAD_DATA:
|
||||
raise UnrarException("File CRC error")
|
||||
elif res == constants.ERAR_BAD_ARCHIVE:
|
||||
raise UnrarException("Not valid RAR archive")
|
||||
elif res == constants.ERAR_UNKNOWN_FORMAT:
|
||||
raise UnrarException("Unknown archive format")
|
||||
elif res == constants.ERAR_EOPEN:
|
||||
raise UnrarException("Volume open error")
|
||||
elif res == constants.ERAR_ECREATE:
|
||||
raise UnrarException("File create error")
|
||||
elif res == constants.ERAR_EREAD:
|
||||
raise UnrarException("Read error")
|
||||
elif res == constants.ERAR_EWRITE:
|
||||
raise UnrarException("Write error")
|
||||
# res == SUCCESS | res == ERAR_END_ARCHIVE
|
||||
return res
|
||||
|
||||
|
||||
def _check_close_result(res, func, args):
|
||||
if res == constants.ERAR_ECLOSE:
|
||||
raise UnrarException("Archive close error")
|
||||
# res == SUCCESS
|
||||
return res
|
||||
|
||||
|
||||
# Return library API version.
|
||||
RARGetDllVersion = _c_func(unrarlib.RARGetDllVersion, ctypes.c_int, [])
|
||||
|
||||
|
||||
# Open RAR archive and allocate memory structures (unicode)
|
||||
RAROpenArchiveEx = _c_func(unrarlib.RAROpenArchiveEx, HANDLE,
|
||||
[ctypes.POINTER(RAROpenArchiveDataEx)],
|
||||
_check_open_result)
|
||||
|
||||
|
||||
# Set a password to decrypt files.
|
||||
RARSetPassword = _c_func(unrarlib.RARSetPassword, ctypes.c_int,
|
||||
[HANDLE, ctypes.c_char_p])
|
||||
|
||||
|
||||
# Read header of file in archive (unicode).
|
||||
RARReadHeaderEx = _c_func(unrarlib.RARReadHeaderEx, ctypes.c_int,
|
||||
[HANDLE, ctypes.POINTER(RARHeaderDataEx)],
|
||||
_check_readheader_result)
|
||||
|
||||
|
||||
# Performs action and moves the current position in the archive to
|
||||
# the next file. Extract or test the current file from the archive
|
||||
# opened in RAR_OM_EXTRACT mode. If the mode RAR_OM_LIST is set,
|
||||
# then a call to this function will simply skip the archive position
|
||||
# to the next file.
|
||||
RARProcessFile = _c_func(unrarlib.RARProcessFile, ctypes.c_int,
|
||||
[HANDLE, ctypes.c_int, ctypes.c_char_p,
|
||||
ctypes.c_char_p], _check_process_result)
|
||||
|
||||
|
||||
# Performs action and moves the current position in the archive to
|
||||
# the next file. Extract or test the current file from the archive
|
||||
# opened in RAR_OM_EXTRACT mode. If the mode RAR_OM_LIST is set,
|
||||
# then a call to this function will simply skip the archive position
|
||||
# to the next file. (unicode version)
|
||||
RARProcessFileW = _c_func(unrarlib.RARProcessFileW, ctypes.c_int,
|
||||
[HANDLE, ctypes.c_int, ctypes.c_wchar_p,
|
||||
ctypes.c_wchar_p], _check_process_result)
|
||||
|
||||
|
||||
# Close RAR archive and release allocated memory. It must be called when
|
||||
# archive processing is finished, even if the archive processing was stopped
|
||||
# due to an error.
|
||||
RARCloseArchive = _c_func(unrarlib.RARCloseArchive, ctypes.c_int, [HANDLE],
|
||||
_check_close_result)
|
||||
|
||||
|
||||
# Set a user-defined callback function to process Unrar events.
|
||||
RARSetCallback = _c_func(unrarlib.RARSetCallback, None,
|
||||
[HANDLE, UNRARCALLBACK, ctypes.c_long])
|
||||
Loading…
Add table
Add a link
Reference in a new issue