Unrar cleanup

This commit is contained in:
mano3m
2014-03-29 21:39:38 +01:00
parent f99a94d685
commit 6152ddbd5f
+35 -35
View File
@@ -41,36 +41,36 @@ def call_unrar(params):
if rar_executable_cached is None: if rar_executable_cached is None:
for command in ('unrar', 'rar'): for command in ('unrar', 'rar'):
try: try:
subprocess.Popen([command], stdout=subprocess.PIPE) subprocess.Popen([command], stdout = subprocess.PIPE)
rar_executable_cached = command rar_executable_cached = command
break break
except OSError: except OSError:
pass pass
if rar_executable_cached is None: if rar_executable_cached is None:
raise UnpackerNotInstalled("No suitable RAR unpacker installed") raise UnpackerNotInstalled("No suitable RAR unpacker installed")
assert type(params) == list, "params must be list" assert type(params) == list, "params must be list"
args = [rar_executable_cached] + params args = [rar_executable_cached] + params
try: try:
gc.disable() # See http://bugs.python.org/issue1336 gc.disable() # See http://bugs.python.org/issue1336
return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
finally: finally:
gc.enable() gc.enable()
class RarFileImplementation(object): class RarFileImplementation(object):
def init(self, password=None): def init(self, password = None):
global rar_executable_version global rar_executable_version
self.password = password self.password = password
stdoutdata, stderrdata = self.call('v', []).communicate() stdoutdata, stderrdata = self.call('v', []).communicate()
for line in stderrdata.splitlines(): for line in stderrdata.splitlines():
if line.strip().startswith("Cannot open"): if line.strip().startswith("Cannot open"):
raise FileOpenError raise FileOpenError
if line.find("CRC failed")>=0: if line.find("CRC failed") >= 0:
raise IncorrectRARPassword raise IncorrectRARPassword
accum = [] accum = []
source = iter(stdoutdata.splitlines()) source = iter(stdoutdata.splitlines())
line = '' line = ''
@@ -107,28 +107,28 @@ class RarFileImplementation(object):
else: else:
self.comment = None self.comment = None
else: else:
raise UnpackerNotInstalled("Unsupported RAR version, expected 4.x or 5.x, found: " raise UnpackerNotInstalled("Unsupported RAR version, expected 4.x or 5.x, found: "
+ signature.split(" ")[1]) + signature.split(" ")[1])
def escaped_password(self): def escaped_password(self):
return '-' if self.password == None else self.password return '-' if self.password == None else self.password
def call(self, cmd, options=[], files=[]): def call(self, cmd, options = [], files = []):
options2 = options + ['p'+self.escaped_password()] options2 = options + ['p' + self.escaped_password()]
soptions = ['-'+x for x in options2] soptions = ['-' + x for x in options2]
return call_unrar([cmd]+soptions+['--',self.archiveName]+files) return call_unrar([cmd] + soptions + ['--', self.archiveName] + files)
def infoiter(self): def infoiter(self):
command = "v" if rar_executable_version == 4 else "l" command = "v" if rar_executable_version == 4 else "l"
stdoutdata, stderrdata = self.call(command, ['c-']).communicate() stdoutdata, stderrdata = self.call(command, ['c-']).communicate()
for line in stderrdata.splitlines(): for line in stderrdata.splitlines():
if line.strip().startswith("Cannot open"): if line.strip().startswith("Cannot open"):
raise FileOpenError raise FileOpenError
accum = [] accum = []
source = iter(stdoutdata.splitlines()) source = iter(stdoutdata.splitlines())
line = '' line = ''
@@ -136,7 +136,7 @@ class RarFileImplementation(object):
if line.strip().endswith('is not RAR archive'): if line.strip().endswith('is not RAR archive'):
raise InvalidRARArchive raise InvalidRARArchive
if line.startswith("CRC failed") or line.startswith("Checksum error"): if line.startswith("CRC failed") or line.startswith("Checksum error"):
raise IncorrectRARPassword raise IncorrectRARPassword
line = source.next() line = source.next()
line = source.next() line = source.next()
i = 0 i = 0
@@ -144,7 +144,7 @@ class RarFileImplementation(object):
if rar_executable_version == 4: if rar_executable_version == 4:
while not line.startswith('-----------'): while not line.startswith('-----------'):
accum.append(line) accum.append(line)
if len(accum)==2: if len(accum) == 2:
data = {} data = {}
data['index'] = i data['index'] = i
# asterisks mark password-encrypted files # asterisks mark password-encrypted files
@@ -153,7 +153,7 @@ class RarFileImplementation(object):
data['size'] = int(fields[0]) data['size'] = int(fields[0])
attr = fields[5] attr = fields[5]
data['isdir'] = 'd' in attr.lower() data['isdir'] = 'd' in attr.lower()
data['datetime'] = time.strptime(fields[3]+" "+fields[4], '%d-%m-%y %H:%M') data['datetime'] = time.strptime(fields[3] + " " + fields[4], '%d-%m-%y %H:%M')
data['comment'] = None data['comment'] = None
yield data yield data
accum = [] accum = []
@@ -168,23 +168,23 @@ class RarFileImplementation(object):
data['size'] = int(fields[1]) data['size'] = int(fields[1])
attr = fields[0] attr = fields[0]
data['isdir'] = 'd' in attr.lower() data['isdir'] = 'd' in attr.lower()
data['datetime'] = time.strptime(fields[2]+" "+fields[3], '%d-%m-%y %H:%M') data['datetime'] = time.strptime(fields[2] + " " + fields[3], '%d-%m-%y %H:%M')
data['comment'] = None data['comment'] = None
yield data yield data
i += 1 i += 1
line = source.next() line = source.next()
def read_files(self, checker): def read_files(self, checker):
res = [] res = []
for info in self.infoiter(): for info in self.infoiter():
checkres = checker(info) checkres = checker(info)
if checkres==True and not info.isdir: if checkres == True and not info.isdir:
pipe = self.call('p', ['inul'], [info.filename]).stdout pipe = self.call('p', ['inul'], [info.filename]).stdout
res.append((info, pipe.read())) res.append((info, pipe.read()))
return res return res
def extract(self, checker, path, withSubpath, overwrite): def extract(self, checker, path, withSubpath, overwrite):
res = [] res = []
command = 'x' command = 'x'
@@ -202,17 +202,17 @@ class RarFileImplementation(object):
checkres = checker(info) checkres = checker(info)
if type(checkres) in [str, unicode]: if type(checkres) in [str, unicode]:
raise NotImplementedError("Condition callbacks returning strings are deprecated and only supported in Windows") raise NotImplementedError("Condition callbacks returning strings are deprecated and only supported in Windows")
if checkres==True and not info.isdir: if checkres == True and not info.isdir:
names.append(info.filename) names.append(info.filename)
res.append(info) res.append(info)
names.append(path) names.append(path)
proc = self.call(command, options, names) proc = self.call(command, options, names)
stdoutdata, stderrdata = proc.communicate() stdoutdata, stderrdata = proc.communicate()
if stderrdata.find("CRC failed")>=0 or stderrdata.find("Checksum error")>=0: if stderrdata.find("CRC failed") >= 0 or stderrdata.find("Checksum error") >= 0:
raise IncorrectRARPassword raise IncorrectRARPassword
return res return res
def destruct(self): def destruct(self):
pass pass