diff options
author | RaNaN <Mast3rRaNaN@hotmail.de> | 2011-10-14 18:10:40 +0200 |
---|---|---|
committer | RaNaN <Mast3rRaNaN@hotmail.de> | 2011-10-14 18:10:40 +0200 |
commit | e4077960822e24f3041e16e7e818c105e372152d (patch) | |
tree | 12580f141668f4eb0edf4b90fbf3417e8dcc3a3a /module/plugins/internal/UnRar.py | |
parent | fixes syntax error on old python versions (diff) | |
download | pyload-e4077960822e24f3041e16e7e818c105e372152d.tar.xz |
first version of new extract plugin
Diffstat (limited to 'module/plugins/internal/UnRar.py')
-rw-r--r-- | module/plugins/internal/UnRar.py | 279 |
1 files changed, 152 insertions, 127 deletions
diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py index d22e54b61..67f95b018 100644 --- a/module/plugins/internal/UnRar.py +++ b/module/plugins/internal/UnRar.py @@ -14,145 +14,170 @@ 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: mkaay + @author: RaNaN """ -from __future__ import with_statement -import sys import os -from os.path import exists, join, isabs, isdir -from os import remove, makedirs, rmdir, listdir, chmod -from traceback import print_exc +from os.path import join -from module.plugins.hooks.ExtractArchive import AbtractExtractor -from module.lib.pyunrar import Unrar, WrongPasswordError, CommandError, UnknownError, LowRamError +from subprocess import Popen, PIPE +from module.plugins.hooks.ExtractArchive import AbtractExtractor from module.utils import save_join - +try: + import pexpect #used for progress + PEXPECT = True +except ImportError: + PEXPECT = False import re class UnRar(AbtractExtractor): + __name__ = "UnRar" + __version__ = "0.1" - def removeFiles(self, pack, fname): - if not self.getConfig("deletearchive"): - return - m = self.re_splitfile.search(fname) + re_splitfile = re.compile("(.*)\.part(\d+)\.rar$") - download_folder = self.core.config['general']['download_folder'] - if self.core.config['general']['folder_per_package']: - folder = join(download_folder, pack.folder.decode(sys.getfilesystemencoding())) - else: - folder = download_folder - if m: - nre = re.compile("%s\.part\d+\.rar" % m.group(1)) - for fid, data in pack.getChildren().iteritems(): - if nre.match(data["name"]): - remove(join(folder, data["name"])) - elif not m and fname.endswith(".rar"): - nre = re.compile("^%s\.r..$" % fname.replace(".rar", "")) - for fid, data in pack.getChildren().iteritems(): - if nre.match(data["name"]): - remove(join(folder, data["name"])) - - def packageFinished(self, pack): - if pack.password and pack.password.strip() and pack.password.strip() != "None": - self.addPassword(pack.password.splitlines()) - files = [] - - for fid, data in pack.getChildren().iteritems(): - m = self.re_splitfile.search(data["name"]) - if m and int(m.group(2)) == 1: - files.append((fid, m.group(0))) - elif not m and data["name"].endswith(".rar"): - files.append((fid, data["name"])) - - for fid, fname in files: - self.core.log.info(_("starting Unrar of %s") % fname) - pyfile = self.core.files.getFile(fid) - pyfile.setStatus("processing") - - def s(p): - pyfile.setProgress(p) - - download_folder = self.core.config['general']['download_folder'] - self.core.log.debug(_("download folder %s") % download_folder) - - folder = save_join(download_folder, pack.folder, "") - - - destination = folder - if self.getConfig("unrar_destination") and not self.getConfig("unrar_destination").lower() == "none": - destination = self.getConfig("unrar_destination") - sub = "." - if self.core.config['general']['folder_per_package']: - sub = pack.folder.decode(sys.getfilesystemencoding()) - if isabs(destination): - destination = join(destination, sub, "") - else: - destination = join(folder, destination, sub, "") - - self.core.log.debug(_("Destination folder %s") % destination) - if not exists(destination): - self.core.log.info(_("Creating destination folder %s") % destination) - makedirs(destination) - - u = Unrar(join(folder, fname), tmpdir=join(folder, "tmp"), - ramSize=(self.ram if self.getConfig("ramwarning") else 0), cpu=self.getConfig("renice")) - try: - success = u.crackPassword(passwords=self.passwords, statusFunction=s, overwrite=True, - destination=destination, fullPath=self.getConfig("fullpath")) - except WrongPasswordError: - self.core.log.info(_("Unrar of %s failed (wrong password)") % fname) - continue - except CommandError, e: - if self.core.debug: - print_exc() - if re.search("Cannot find volume", e.stderr): - self.core.log.info(_("Unrar of %s failed (missing volume)") % fname) - continue - try: - if e.getExitCode() == 1 and len(u.listContent(u.getPassword())) == 1: - self.core.log.info(_("Unrar of %s ok") % fname) - self.removeFiles(pack, fname) - except: - if self.core.debug: - print_exc() - self.core.log.info(_("Unrar of %s failed") % fname) - continue - except LowRamError: - self.log.warning(_( - "Your ram amount of %s MB seems not sufficient to unrar this file. You can deactivate this warning and risk instability") % self.ram) - continue - except UnknownError: - if self.core.debug: - print_exc() - self.core.log.info(_("Unrar of %s failed") % fname) - continue + @staticmethod + def checkDeps(): + return True #TODO + + @staticmethod + def getTargets(files_ids): + result = [] + + for file, id in files_ids: + if not file.endswith(".rar"): continue + + match = UnRar.re_splitfile.findall(file) + if match: + #only add first parts + if int(match[0][1]) == 1: + result.append((file, id)) else: - if success: - self.core.log.info(_("Unrar of %s ok") % fname) - self.removeFiles(pack, fname) - - if os.name != "nt" and self.core.config['permission']['change_dl'] and\ - self.core.config['permission']['change_file']: - ownerUser = self.core.config['permission']['user'] - fileMode = int(self.core.config['permission']['file'], 8) - - self.core.log.debug("Setting destination file/directory owner / mode to %s / %s" - % (ownerUser, fileMode)) - - uinfo = getpwnam(ownerUser) - self.core.log.debug("Uid/Gid is %s/%s." % (uinfo.pw_uid, uinfo.pw_gid)) - self.setOwner(destination, uinfo.pw_uid, uinfo.pw_gid, fileMode) - self.core.log.debug("The owner/rights have been successfully changed.") - - self.core.hookManager.unrarFinished(folder, fname) - else: - self.core.log.info(_("Unrar of %s failed (wrong password or bad parts)") % fname) - finally: - pyfile.setProgress(100) - pyfile.setStatus("finished") - pyfile.release() + result.append((file, id)) + + return result + + + def init(self): + self.passwordProtected = False + self.headerProtected = False #list files will not work without password + self.smallestFile = None #small file to test passwords + self.password = "" #save the correct password + + def checkArchive(self): + p = self.call_unrar("l", "-v", self.file) + out, err = p.communicate() + if "Corrupt file or wrong password." in err: + self.passwordProtected = True + self.headerProtected = True + return True + + self.listContent() + if not self.files: + self.m.archiveError("Empty Archive") + + return False + + def checkPassword(self, password): + if not self.passwordProtected: return True + + if self.headerProtected: + p = self.call_unrar("l", "-v", self.file, password=password) + out, err = p.communicate() + if "Corrupt file or wrong password." in err: + return False + + return True + + + def extract(self, progress, password=None): + command = "x" if self.fullpath else "e" + + if PEXPECT: + p = self.call_unrar(command, self.file, self.out, password=password, pexpect=True) + #renice(p.pid, self.renice) + + cpl = p.compile_pattern_list([pexpect.EOF, "(\d+)\s?%"]) + while True: + i = p.expect_list(cpl, timeout=None) + if i == 0: # EOF + break #exited + elif i == 1: + perc = p.match.group(1) + progress(int(perc)) + # pexpect thinks process is still alive (just like popen) - very strange behavior + p.terminated = True + + else: + #subprocess - no progress + p = self.call_unrar(command, self.file, self.out, password=password) + renice(p.pid, self.renice) + + progress(0) + out, err = p.communicate() #wait for process + progress(100) + + #TODO, check for errors + + + def getDeleteFiles(self): + #TODO + return [] + + def listContent(self): + command = "vb" if self.fullpath else "lb" + p = self.call_unrar(command, "-v", self.file, password=self.password) + out, err = p.communicate() + + result = set() + + for f in out.splitlines(): + f = f.strip() + result.add(save_join(self.out, f)) + + self.files = result + + + def call_unrar(self, command, *xargs, **kwargs): + if os.name == "nt": + cmd = join(pypath, "UnRAR.exe") + else: + cmd = "unrar" + + args = [] + + #overwrite flag + args.append("-o+") if self.overwrite else args.append("-o-") + + # assume yes on all queries + args.append("-y") + + #set a password + if "password" in kwargs and kwargs["password"]: + args.append("-p%s" % kwargs["password"]) + else: + args.append("-p-") + + + #NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue + call = [cmd, command] + args + list(xargs) + self.m.logDebug(" ".join(call)) + + if PEXPECT and "pexpect" in kwargs: + #use pexpect if available + p = pexpect.spawn(" ".join(call)) + else: + p = Popen(call, stdout=PIPE, stderr=PIPE) + + return p + +def renice(pid, value): + if os.name != "nt" and value: + try: + Popen(["renice", str(value), str(pid)], stdout=PIPE, stderr=PIPE, bufsize=-1) + except: + print "Renice failed"
\ No newline at end of file |