Example #1
0
    def open(self, member):
        #print "opening %s..." % member
        # based on https://github.com/matiasb/python-unrar/pull/4/files
        if isinstance(member, rarfile.RarInfo):
            member = member.filename
        archive = unrarlib.RAROpenArchiveDataEx(self.filename,
                                                mode=constants.RAR_OM_EXTRACT)
        handle = self._open(archive)
        found, buf = False, []

        def _callback(msg, UserData, P1, P2):
            if msg == constants.UCM_PROCESSDATA:
                data = (ctypes.c_char * P2).from_address(P1).raw
                buf.append(data)
            return 1

        c_callback = unrarlib.UNRARCALLBACK(_callback)
        unrarlib.RARSetCallback(handle, c_callback, 1)
        try:
            rarinfo = self._read_header(handle)
            while rarinfo is not None:
                #print "checking rar archive %s against %s" % (rarinfo.filename, member)
                if rarinfo.filename == member:
                    self._process_current(handle, constants.RAR_TEST)
                    found = True
                else:
                    self._process_current(handle, constants.RAR_SKIP)
                rarinfo = self._read_header(handle)
        except unrarlib.UnrarException:
            raise rarfile.BadRarFile("Bad RAR archive data.")
        finally:
            self._close(handle)
        if not found:
            raise KeyError('There is no item named %r in the archive' % member)
        return b''.join(buf)
Example #2
0
    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.MissingPassword:
            raise RuntimeError("File is encrypted, password required")
        except unrarlib.BadPassword:
            raise RuntimeError("Bad password for File")
        except unrarlib.BadDataError:
            if password is not None:
                raise RuntimeError("File CRC error or incorrect password")
            else:
                raise RuntimeError("File CRC error")
        except unrarlib.UnrarException as e:
            raise BadRarFile("Bad RAR archive data: %s" % str(e))
        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_files(self, member):
     res = []
     if isinstance(member, RarInfo):
         member = member.filename
     archive = unrarlib.RAROpenArchiveDataEx(self.filename, mode=constants.RAR_OM_EXTRACT)
     handle = self._open(archive)
     reader = PassiveReader()
     c_callback = unrarlib.UNRARCALLBACK(reader._callback)
     unrarlib.RARSetCallback(handle, c_callback, 1)
     try:
         rarinfo = self._read_header(handle)
         while rarinfo is not None:
             if rarinfo.filename in member:
                 self._process_current(handle, constants.RAR_TEST)
             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)
     res.append((member, reader.get_result()))
     return res