diff options
| -rw-r--r-- | module/plugins/hooks/UnRar.py | 2 | ||||
| -rw-r--r-- | module/pyunrar.py | 77 | 
2 files changed, 57 insertions, 22 deletions
| diff --git a/module/plugins/hooks/UnRar.py b/module/plugins/hooks/UnRar.py index 6bd650b4a..4f989e804 100644 --- a/module/plugins/hooks/UnRar.py +++ b/module/plugins/hooks/UnRar.py @@ -111,7 +111,7 @@ class UnRar(Hook):              else:                  folder = download_folder -            u = Unrar(join(folder, fname)) +            u = Unrar(join(folder, fname), tmpdir=join(folder, "tmp"))              try:                  success = u.crackPassword(passwords=self.passwords, statusFunction=s, overwrite=True, destination=folder, fullPath=self.getConfig("fullpath"))              except WrongPasswordError: diff --git a/module/pyunrar.py b/module/pyunrar.py index dfd488ce5..4db7e1775 100644 --- a/module/pyunrar.py +++ b/module/pyunrar.py @@ -20,7 +20,6 @@  from subprocess import Popen, PIPE  import re -import os  from time import sleep  from tempfile import mkdtemp  from shutil import rmtree, move @@ -73,7 +72,7 @@ class CommandError(Exception):          return EXITMAP[self.ret]  class Unrar(): -    def __init__(self, archive): +    def __init__(self, archive, tmpdir=None):          """              archive should be be first or only part          """ @@ -89,6 +88,11 @@ class Unrar():          self.headerEncrypted = None          self.smallestFiles = None          self.password = None +        if not tmpdir: +            self.tmpdir = mkdtemp() +        else: +            self.tmpdir = tmpdir +            makedirs(tmpdir)      def listContent(self, password=None):          """ @@ -110,7 +114,7 @@ class Unrar():          if ret == 3:              self.headerEncrypted = True              raise WrongPasswordError() -        elif ret == 0 and password: +        elif ret in (0,1) and password:              self.headerEncrypted = False          o = p.stdout.read()          inList = False @@ -201,13 +205,8 @@ class Unrar():              args.append(self.getSmallestFile(password)["name"])          except WrongPasswordError:              return False -        out = open(os.devnull, "w+") -        err = open(os.devnull, "w+") -        p = Popen(args, stdin=PIPE, stdout=out, stderr=err, bufsize=-1) -        ret = p.wait() -        out.close() -        err.close() -         +        p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE, bufsize=-1) +        (ret, out) = self.processOutput(p, statusFunction)          if ret == 3:              raise False          elif ret in (0,1): @@ -243,20 +242,14 @@ class Unrar():              args.extend(["-x%s" % e for e in exclude])          if destination:              args.append(destination) - -        out = open(os.devnull, "w+") -        err = open(os.devnull, "w+") -        p = Popen(args, stdin=PIPE, stdout=out, stderr=err, bufsize=-1) -        ret = p.wait() -        out.close() -        err.close() - +        p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE, bufsize=-1) +        (ret, out) = self.processOutput(p, statusFunction)          if ret == 3:              raise WrongPasswordError()          elif ret in (0,1):              return True          else: -            raise CommandError(ret=ret) +            raise CommandError(ret=ret, stdout=out, stderr=p.stderr.read())      def crackPassword(self, passwords=[], fullPath=True, destination=None, overwrite=False, statusFunction=None, exclude=[]):          """ @@ -271,7 +264,7 @@ class Unrar():                      sf.append(self.getSmallestFile(password)["name"])                  except WrongPasswordError:                      continue -                tdir = mkdtemp(prefix="rar") +                tdir = self.tmpdir                  try:                      self.extract(password=password, fullPath=fullPath, destination=tdir, overwrite=overwrite, statusFunction=statusFunction, files=sf)                  except WrongPasswordError: @@ -313,6 +306,49 @@ class Unrar():          except WrongPasswordError:              return False +    def processOutput(self, p, statusFunction=None): +        """ +            internal method +            parse the progress output of the rar/unrar command +            @return int: exitcode +                    string: command output +        """ +        ret = None +        out = "" +        tmp = None +        count = 0 +        perc = 0 +        tperc = "0" +        last = None +        digits = "1 2 3 4 5 6 7 8 9 0".split(" ") +        if not statusFunction: +            statusFunction = lambda p: None +        statusFunction(0) +        while ret is None or tmp: +            tmp = p.stdout.read(1) +            if tmp: +                out += tmp +                if tmp == chr(8): +                    if last == tmp: +                        count += 1 +                        tperc = "0" +                    else: +                        count = 0 +                        if perc < int(tperc): +                            perc = int(tperc) +                            statusFunction(perc) +                elif count >= 3: +                    if tmp == "\n": +                        count = 0 +                    elif tmp in digits: +                        tperc += tmp +                last = tmp +            else: +                sleep(0.01) +            ret = p.poll() +        statusFunction(100) +        return ret, out +          def getPassword(self):          """              return the correct password @@ -321,7 +357,6 @@ class Unrar():          """          return self.password -  if __name__ == "__main__":      from pprint import pprint      u = Unrar("archive.part1.rar", multi=True) | 
