Python rarfile.UNRAR_TOOL Examples

The following are 30 code examples of rarfile.UNRAR_TOOL(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module rarfile , or try the search function .
Example #1
Source File: init.py    From bazarr with GNU General Public License v3.0 6 votes vote down vote up
def init_binaries():
    from utils import get_binary
    exe = get_binary("unrar")
    
    rarfile.UNRAR_TOOL = exe
    rarfile.ORIG_UNRAR_TOOL = exe
    try:
        rarfile.custom_check([rarfile.UNRAR_TOOL], True)
    except:
        logging.debug("custom check failed for: %s", exe)
    
    rarfile.OPEN_ARGS = rarfile.ORIG_OPEN_ARGS
    rarfile.EXTRACT_ARGS = rarfile.ORIG_EXTRACT_ARGS
    rarfile.TEST_ARGS = rarfile.ORIG_TEST_ARGS
    logging.debug("Using UnRAR from: %s", exe)
    unrar = exe
    
    return unrar 
Example #2
Source File: rarfile.py    From bazarr with GNU General Public License v3.0 6 votes vote down vote up
def _open_unrar(self, rarfile, inf, psw=None, tmpfile=None, force_file=False):
        cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
        add_password_arg(cmd, psw)
        cmd.append("--")
        cmd.append(rarfile)

        # not giving filename avoids encoding related problems
        if not tmpfile or force_file:
            fn = inf.filename
            if PATH_SEP != os.sep:
                fn = fn.replace(PATH_SEP, os.sep)
            cmd.append(fn)

        # read from unrar pipe
        return PipeReader(self, inf, cmd, tmpfile)

#
# RAR3 format
# 
Example #3
Source File: rarfile.py    From bazarr with GNU General Public License v3.0 6 votes vote down vote up
def custom_popen(cmd):
    """Disconnect cmd from parent fds, read only from stdout.
    """
    # needed for py2exe
    creationflags = 0
    if sys.platform == 'win32':
        creationflags = 0x08000000   # CREATE_NO_WINDOW

    # run command
    try:
        p = Popen(cmd, bufsize=0, stdout=PIPE, stdin=PIPE, stderr=STDOUT,
                  creationflags=creationflags)
    except OSError as ex:
        if ex.errno == errno.ENOENT:
            raise RarCannotExec("Unrar not installed? (rarfile.UNRAR_TOOL=%r)" % UNRAR_TOOL)
        raise
    return p 
Example #4
Source File: rarfile.py    From bazarr with GNU General Public License v3.0 6 votes vote down vote up
def _check_unrar_tool():
    global UNRAR_TOOL, OPEN_ARGS, EXTRACT_ARGS, TEST_ARGS
    try:
        # does UNRAR_TOOL work?
        custom_check([ORIG_UNRAR_TOOL], True)

        UNRAR_TOOL = ORIG_UNRAR_TOOL
        OPEN_ARGS = ORIG_OPEN_ARGS
        EXTRACT_ARGS = ORIG_EXTRACT_ARGS
        TEST_ARGS = ORIG_TEST_ARGS
    except RarCannotExec:
        try:
            # does ALT_TOOL work?
            custom_check([ALT_TOOL] + list(ALT_CHECK_ARGS), True)
            # replace config
            UNRAR_TOOL = ALT_TOOL
            OPEN_ARGS = ALT_OPEN_ARGS
            EXTRACT_ARGS = ALT_EXTRACT_ARGS
            TEST_ARGS = ALT_TEST_ARGS
        except RarCannotExec:
            # no usable tool, only uncompressed archives work
            pass 
Example #5
Source File: rarfile.py    From addon with GNU General Public License v3.0 6 votes vote down vote up
def _check_unrar_tool():
    global UNRAR_TOOL, OPEN_ARGS, EXTRACT_ARGS, TEST_ARGS
    try:
        # does UNRAR_TOOL work?
        custom_check([ORIG_UNRAR_TOOL], True)

        UNRAR_TOOL = ORIG_UNRAR_TOOL
        OPEN_ARGS = ORIG_OPEN_ARGS
        EXTRACT_ARGS = ORIG_EXTRACT_ARGS
        TEST_ARGS = ORIG_TEST_ARGS
    except RarCannotExec:
        try:
            # does ALT_TOOL work?
            custom_check([ALT_TOOL] + list(ALT_CHECK_ARGS), True)
            # replace config
            UNRAR_TOOL = ALT_TOOL
            OPEN_ARGS = ALT_OPEN_ARGS
            EXTRACT_ARGS = ALT_EXTRACT_ARGS
            TEST_ARGS = ALT_TEST_ARGS
        except RarCannotExec:
            # no usable tool, only uncompressed archives work
            return False
    return True 
Example #6
Source File: rarfile.py    From addon with GNU General Public License v3.0 6 votes vote down vote up
def custom_popen(cmd):
    """Disconnect cmd from parent fds, read only from stdout.
    """
    # needed for py2exe
    creationflags = 0
    if sys.platform == 'win32':
        creationflags = 0x08000000   # CREATE_NO_WINDOW

    # run command
    try:
        p = Popen(cmd, bufsize=0, stdout=PIPE, stdin=PIPE, stderr=STDOUT,
                  creationflags=creationflags)
    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 
Example #7
Source File: rar.py    From bazarr with GNU General Public License v3.0 6 votes vote down vote up
def read(self, fname, psw=None):
        """
        read specific content of rarfile without parsing
        :param fname:
        :param psw:
        :return:
        """
        cmd = [rarfile.UNRAR_TOOL] + list(rarfile.ORIG_OPEN_ARGS)

        with rarfile.XTempFile(self._rarfile) as rf:
            log.debug(u"RAR CMD: %s", cmd + [rf, fname])
            p = rarfile.custom_popen(cmd + [rf, fname])
            output = p.communicate()[0]
            rarfile.check_returncode(p, output)

            return output 
Example #8
Source File: rarfile.py    From addon with GNU General Public License v3.0 6 votes vote down vote up
def _open_unrar(self, rarfile, inf, psw=None, tmpfile=None, force_file=False):
        cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
        add_password_arg(cmd, psw)
        cmd.append("--")
        cmd.append(rarfile)

        # not giving filename avoids encoding related problems
        if not tmpfile or force_file:
            fn = inf.filename
            if PATH_SEP != os.sep:
                fn = fn.replace(PATH_SEP, os.sep)
            cmd.append(fn)

        # read from unrar pipe
        return PipeReader(self, inf, cmd, tmpfile)

#
# RAR3 format
# 
Example #9
Source File: rarfile.py    From arissploit with GNU General Public License v3.0 6 votes vote down vote up
def testrar(self):
        """Let 'unrar' test the archive.
        """
        cmd = [UNRAR_TOOL] + list(TEST_ARGS)
        add_password_arg(cmd, self._password)
        cmd.append('--')

        if is_filelike(self.rarfile):
            tmpname = membuf_tempfile(self.rarfile)
            cmd.append(tmpname)
        else:
            tmpname = None
            cmd.append(self.rarfile)

        try:
            p = custom_popen(cmd)
            output = p.communicate()[0]
            check_returncode(p, output)
        finally:
            if tmpname:
                os.unlink(tmpname) 
Example #10
Source File: rarfile.py    From arissploit with GNU General Public License v3.0 6 votes vote down vote up
def _open_unrar(self, rarfile, inf, psw = None, tmpfile = None):
        if is_filelike(rarfile):
            raise ValueError("Cannot use unrar directly on memory buffer")
        cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
        add_password_arg(cmd, psw)
        cmd.append("--")
        cmd.append(rarfile)

        # not giving filename avoids encoding related problems
        if not tmpfile:
            fn = inf.filename
            if PATH_SEP != os.sep:
                fn = fn.replace(PATH_SEP, os.sep)
            cmd.append(fn)

        # read from unrar pipe
        return PipeReader(self, inf, cmd, tmpfile) 
Example #11
Source File: rarfile.py    From Lector with GNU General Public License v3.0 6 votes vote down vote up
def _check_unrar_tool():
    global UNRAR_TOOL, OPEN_ARGS, EXTRACT_ARGS, TEST_ARGS
    try:
        # does UNRAR_TOOL work?
        custom_check([ORIG_UNRAR_TOOL], True)

        UNRAR_TOOL = ORIG_UNRAR_TOOL
        OPEN_ARGS = ORIG_OPEN_ARGS
        EXTRACT_ARGS = ORIG_EXTRACT_ARGS
        TEST_ARGS = ORIG_TEST_ARGS
    except RarCannotExec:
        try:
            # does ALT_TOOL work?
            custom_check([ALT_TOOL] + list(ALT_CHECK_ARGS), True)
            # replace config
            UNRAR_TOOL = ALT_TOOL
            OPEN_ARGS = ALT_OPEN_ARGS
            EXTRACT_ARGS = ALT_EXTRACT_ARGS
            TEST_ARGS = ALT_TEST_ARGS
        except RarCannotExec:
            # no usable tool, only uncompressed archives work
            return False
    return True 
Example #12
Source File: rarfile.py    From Lector with GNU General Public License v3.0 6 votes vote down vote up
def custom_popen(cmd):
    """Disconnect cmd from parent fds, read only from stdout.
    """
    # needed for py2exe
    creationflags = 0
    if sys.platform == 'win32':
        creationflags = 0x08000000   # CREATE_NO_WINDOW

    # run command
    try:
        p = Popen(cmd, bufsize=0, stdout=PIPE, stdin=PIPE, stderr=STDOUT,
                  creationflags=creationflags)
    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 
Example #13
Source File: rarfile.py    From arissploit with GNU General Public License v3.0 6 votes vote down vote up
def custom_popen(cmd):
    """Disconnect cmd from parent fds, read only from stdout."""

    # needed for py2exe
    creationflags = 0
    if sys.platform == 'win32':
        creationflags = 0x08000000 # CREATE_NO_WINDOW

    # run command
    try:
        p = Popen(cmd, bufsize = 0,
                  stdout = PIPE, stdin = PIPE, stderr = STDOUT,
                  creationflags = creationflags)
    except OSError as ex:
        if ex.errno == errno.ENOENT:
            raise RarCannotExec("Unrar not installed? (rarfile.UNRAR_TOOL=%r)" % UNRAR_TOOL)
        raise
    return p 
Example #14
Source File: rarfile.py    From Lector with GNU General Public License v3.0 6 votes vote down vote up
def _open_unrar(self, rarfile, inf, psw=None, tmpfile=None, force_file=False):
        cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
        add_password_arg(cmd, psw)
        cmd.append("--")
        cmd.append(rarfile)

        # not giving filename avoids encoding related problems
        if not tmpfile or force_file:
            fn = inf.filename
            if PATH_SEP != os.sep:
                fn = fn.replace(PATH_SEP, os.sep)
            cmd.append(fn)

        # read from unrar pipe
        return PipeReader(self, inf, cmd, tmpfile)

#
# RAR3 format
# 
Example #15
Source File: rarfile.py    From bazarr with GNU General Public License v3.0 5 votes vote down vote up
def testrar(self):
        """Let 'unrar' test the archive.
        """
        cmd = [UNRAR_TOOL] + list(TEST_ARGS)
        add_password_arg(cmd, self._password)
        cmd.append('--')
        with XTempFile(self._rarfile) as rarfile:
            cmd.append(rarfile)
            p = custom_popen(cmd)
            output = p.communicate()[0]
            check_returncode(p, output) 
Example #16
Source File: rarfile.py    From arissploit with GNU General Public License v3.0 5 votes vote down vote up
def _extract(self, fnlist, path=None, psw=None):
        cmd = [UNRAR_TOOL] + list(EXTRACT_ARGS)

        # pasoword
        psw = psw or self._password
        add_password_arg(cmd, psw)
        cmd.append('--')

        # rar file
        if is_filelike(self.rarfile):
            tmpname = membuf_tempfile(self.rarfile)
            cmd.append(tmpname)
        else:
            tmpname = None
            cmd.append(self.rarfile)

        # file list
        for fn in fnlist:
            if os.sep != PATH_SEP:
                fn = fn.replace(PATH_SEP, os.sep)
            cmd.append(fn)

        # destination path
        if path is not None:
            cmd.append(path + os.sep)

        # call
        try:
            p = custom_popen(cmd)
            output = p.communicate()[0]
            check_returncode(p, output)
        finally:
            if tmpname:
                os.unlink(tmpname)

##
## Utility classes
## 
Example #17
Source File: legendastv.py    From bazarr with GNU General Public License v3.0 5 votes vote down vote up
def __init__(self, username=None, password=None):

        # Provider needs UNRAR installed. If not available raise ConfigurationError
        try:
            rarfile.custom_check([rarfile.UNRAR_TOOL], True)
        except rarfile.RarExecError:
            raise ConfigurationError('UNRAR tool not available')

        if any((username, password)) and not all((username, password)):
            raise ConfigurationError('Username and password must be specified')

        self.username = username
        self.password = password
        self.logged_in = False
        self.session = None 
Example #18
Source File: rarfile.py    From bazarr with GNU General Public License v3.0 5 votes vote down vote up
def check_returncode(p, out):
    """Raise exception according to unrar exit code.
    """
    code = p.returncode
    if code == 0:
        return

    # map return code to exception class, codes from rar.txt
    errmap = [None,
              RarWarning, RarFatalError, RarCRCError, RarLockedArchiveError,    # 1..4
              RarWriteError, RarOpenError, RarUserError, RarMemoryError,        # 5..8
              RarCreateError, RarNoFilesError, RarWrongPassword]                # 9..11
    if UNRAR_TOOL == ALT_TOOL:
        errmap = [None]
    if code > 0 and code < len(errmap):
        exc = errmap[code]
    elif code == 255:
        exc = RarUserBreak
    elif code < 0:
        exc = RarSignalExit
    else:
        exc = RarUnknownError

    # format message
    if out:
        msg = "%s [%d]: %s" % (exc.__doc__, p.returncode, out)
    else:
        msg = "%s [%d]" % (exc.__doc__, p.returncode)

    raise exc(msg) 
Example #19
Source File: rarfile.py    From arissploit with GNU General Public License v3.0 5 votes vote down vote up
def check_returncode(p, out):
    """Raise exception according to unrar exit code"""

    code = p.returncode
    if code == 0:
        return

    # map return code to exception class
    errmap = [None,
        RarWarning, RarFatalError, RarCRCError, RarLockedArchiveError,
        RarWriteError, RarOpenError, RarUserError, RarMemoryError,
        RarCreateError, RarNoFilesError] # codes from rar.txt
    if UNRAR_TOOL == ALT_TOOL:
        errmap = [None]
    if code > 0 and code < len(errmap):
        exc = errmap[code]
    elif code == 255:
        exc = RarUserBreak
    elif code < 0:
        exc = RarSignalExit
    else:
        exc = RarUnknownError

    # format message
    if out:
        msg = "%s [%d]: %s" % (exc.__doc__, p.returncode, out)
    else:
        msg = "%s [%d]" % (exc.__doc__, p.returncode)

    raise exc(msg) 
Example #20
Source File: test_reuse.py    From Reusables with MIT License 5 votes vote down vote up
def test_extract_rar(self):
        if reusables.win_based:
            import rarfile
            rarfile.UNRAR_TOOL = os.path.abspath(os.path.join(test_root, "UnRAR.exe"))
        assert os.path.exists(test_structure_rar)
        reusables.extract(test_structure_rar, path=test_root, delete_on_success=False, enable_rar=True)
        assert os.path.exists(test_structure)
        assert os.path.isdir(test_structure)
        shutil.rmtree(test_structure) 
Example #21
Source File: rarfile.py    From bazarr with GNU General Public License v3.0 5 votes vote down vote up
def _extract(self, fnlist, path=None, psw=None):
        cmd = [UNRAR_TOOL] + list(EXTRACT_ARGS)

        # pasoword
        psw = psw or self._password
        add_password_arg(cmd, psw)
        cmd.append('--')

        # rar file
        with XTempFile(self._rarfile) as rarfn:
            cmd.append(rarfn)

            # file list
            for fn in fnlist:
                if os.sep != PATH_SEP:
                    fn = fn.replace(PATH_SEP, os.sep)
                cmd.append(fn)

            # destination path
            if path is not None:
                cmd.append(path + os.sep)

            # call
            p = custom_popen(cmd)
            output = p.communicate()[0]
            check_returncode(p, output)

#
# File format parsing
# 
Example #22
Source File: compressed_file.py    From subfinder with MIT License 5 votes vote down vote up
def __init__(self, file):
        self.file = file
        self._file = None
        _, ext = os.path.splitext(file)
        if ext == '.zip':
            import zipfile
            self._file = zipfile.ZipFile(self.file, 'r')
        elif ext == '.rar':
            import rarfile
            if sys.platform == 'win32':
                # if os system is windows,try to use built-in unrar
                rarfile.UNRAR_TOOL = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'unrar.exe')
            self._file = rarfile.RarFile(self.file, 'r')
        else:
            raise ValueError('CompressedFile doesnt support "{}"'.format(ext)) 
Example #23
Source File: rarfile.py    From addon with GNU General Public License v3.0 5 votes vote down vote up
def check_returncode(p, out):
    """Raise exception according to unrar exit code.
    """
    code = p.returncode
    if code == 0:
        return

    # map return code to exception class, codes from rar.txt
    errmap = [None,
              RarWarning, RarFatalError, RarCRCError, RarLockedArchiveError,    # 1..4
              RarWriteError, RarOpenError, RarUserError, RarMemoryError,        # 5..8
              RarCreateError, RarNoFilesError, RarWrongPassword]                # 9..11
    if UNRAR_TOOL == ALT_TOOL:
        errmap = [None]
    if code > 0 and code < len(errmap):
        exc = errmap[code]
    elif code == 255:
        exc = RarUserBreak
    elif code < 0:
        exc = RarSignalExit
    else:
        exc = RarUnknownError

    # format message
    if out:
        msg = "%s [%d]: %s" % (exc.__doc__, p.returncode, out)
    else:
        msg = "%s [%d]" % (exc.__doc__, p.returncode)

    raise exc(msg) 
Example #24
Source File: rarfile.py    From addon with GNU General Public License v3.0 5 votes vote down vote up
def _extract(self, fnlist, path=None, psw=None):
        cmd = [UNRAR_TOOL] + list(EXTRACT_ARGS)

        # pasoword
        psw = psw or self._password
        add_password_arg(cmd, psw)
        cmd.append('--')

        # rar file
        with XTempFile(self._rarfile) as rarfn:
            cmd.append(rarfn)

            # file list
            for fn in fnlist:
                if os.sep != PATH_SEP:
                    fn = fn.replace(PATH_SEP, os.sep)
                cmd.append(fn)

            # destination path
            if path is not None:
                if _have_pathlib and isinstance(path, Path):
                    path = str(path)
                #cmd.append(path + os.sep)
                cmd.append(path)

            # call
            p = custom_popen(cmd)
            output = p.communicate()[0]
            check_returncode(p, output)

#
# File format parsing
# 
Example #25
Source File: rarfile.py    From addon with GNU General Public License v3.0 5 votes vote down vote up
def testrar(self):
        """Let 'unrar' test the archive.
        """
        cmd = [UNRAR_TOOL] + list(TEST_ARGS)
        add_password_arg(cmd, self._password)
        cmd.append('--')
        with XTempFile(self._rarfile) as rarfile:
            cmd.append(rarfile)
            p = custom_popen(cmd)
            output = p.communicate()[0]
            check_returncode(p, output) 
Example #26
Source File: comicfilehandler.py    From Tenma with MIT License 5 votes vote down vote up
def __init__(self):
		# Set the unrar tool based on filesystem
		if os.getenv('TENMA_UNRAR_PATH'):
			rarfile.UNRAR_TOOL = os.getenv('TENMA_UNRAR_PATH')
		elif sys.platform == 'win32':		# Windows
			rarfile.UNRAR_TOOL = os.path.dirname(comics.__file__) + "/utils/unrar/unrar.exe"
		elif sys.platform == 'darwin':	# Mac
			rarfile.UNRAR_TOOL = os.path.dirname(comics.__file__) + "/utils/unrar/unrar_mac"
		elif sys.platform == 'linux':	# Linux
			rarfile.UNRAR_TOOL = os.path.dirname(comics.__file__) + "/utils/unrar/unrar-nonfree_ubuntu"

	#================================================================================================== 
Example #27
Source File: rarfile.py    From Lector with GNU General Public License v3.0 5 votes vote down vote up
def check_returncode(p, out):
    """Raise exception according to unrar exit code.
    """
    code = p.returncode
    if code == 0:
        return

    # map return code to exception class, codes from rar.txt
    errmap = [None,
              RarWarning, RarFatalError, RarCRCError, RarLockedArchiveError,    # 1..4
              RarWriteError, RarOpenError, RarUserError, RarMemoryError,        # 5..8
              RarCreateError, RarNoFilesError, RarWrongPassword]                # 9..11
    if UNRAR_TOOL == ALT_TOOL:
        errmap = [None]
    if code > 0 and code < len(errmap):
        exc = errmap[code]
    elif code == 255:
        exc = RarUserBreak
    elif code < 0:
        exc = RarSignalExit
    else:
        exc = RarUnknownError

    # format message
    if out:
        msg = "%s [%d]: %s" % (exc.__doc__, p.returncode, out)
    else:
        msg = "%s [%d]" % (exc.__doc__, p.returncode)

    raise exc(msg) 
Example #28
Source File: rarfile.py    From Lector with GNU General Public License v3.0 5 votes vote down vote up
def _extract(self, fnlist, path=None, psw=None):
        cmd = [UNRAR_TOOL] + list(EXTRACT_ARGS)

        # pasoword
        psw = psw or self._password
        add_password_arg(cmd, psw)
        cmd.append('--')

        # rar file
        with XTempFile(self._rarfile) as rarfn:
            cmd.append(rarfn)

            # file list
            for fn in fnlist:
                if os.sep != PATH_SEP:
                    fn = fn.replace(PATH_SEP, os.sep)
                cmd.append(fn)

            # destination path
            if path is not None:
                cmd.append(path + os.sep)

            # call
            p = custom_popen(cmd)
            output = p.communicate()[0]
            check_returncode(p, output)

#
# File format parsing
# 
Example #29
Source File: rarfile.py    From Lector with GNU General Public License v3.0 5 votes vote down vote up
def testrar(self):
        """Let 'unrar' test the archive.
        """
        cmd = [UNRAR_TOOL] + list(TEST_ARGS)
        add_password_arg(cmd, self._password)
        cmd.append('--')
        with XTempFile(self._rarfile) as rarfile:
            cmd.append(rarfile)
            p = custom_popen(cmd)
            output = p.communicate()[0]
            check_returncode(p, output) 
Example #30
Source File: rarfile.py    From bazarr with GNU General Public License v3.0 4 votes vote down vote up
def rar3_decompress(vers, meth, data, declen=0, flags=0, crc=0, psw=None, salt=None):
    """Decompress blob of compressed data.

    Used for data with non-standard header - eg. comments.
    """
    # already uncompressed?
    if meth == RAR_M0 and (flags & RAR_FILE_PASSWORD) == 0:
        return data

    # take only necessary flags
    flags = flags & (RAR_FILE_PASSWORD | RAR_FILE_SALT | RAR_FILE_DICTMASK)
    flags |= RAR_LONG_BLOCK

    # file header
    fname = b'data'
    date = 0
    mode = 0x20
    fhdr = S_FILE_HDR.pack(len(data), declen, RAR_OS_MSDOS, crc,
                           date, vers, meth, len(fname), mode)
    fhdr += fname
    if flags & RAR_FILE_SALT:
        if not salt:
            return EMPTY
        fhdr += salt

    # full header
    hlen = S_BLK_HDR.size + len(fhdr)
    hdr = S_BLK_HDR.pack(0, RAR_BLOCK_FILE, flags, hlen) + fhdr
    hcrc = rar_crc32(hdr[2:]) & 0xFFFF
    hdr = S_BLK_HDR.pack(hcrc, RAR_BLOCK_FILE, flags, hlen) + fhdr

    # archive main header
    mh = S_BLK_HDR.pack(0x90CF, RAR_BLOCK_MAIN, 0, 13) + ZERO * (2 + 4)

    # decompress via temp rar
    tmpfd, tmpname = mkstemp(suffix='.rar')
    tmpf = os.fdopen(tmpfd, "wb")
    try:
        tmpf.write(RAR_ID + mh + hdr + data)
        tmpf.close()

        cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
        add_password_arg(cmd, psw, (flags & RAR_FILE_PASSWORD))
        cmd.append(tmpname)

        p = custom_popen(cmd)
        return p.communicate()[0]
    finally:
        tmpf.close()
        os.unlink(tmpname)