diff --git a/extractor/__init__.py b/extractor/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/extractor/bin/x64/7z.dll b/extractor/bin/x64/7z.dll new file mode 100644 index 00000000..cea996e4 Binary files /dev/null and b/extractor/bin/x64/7z.dll differ diff --git a/extractor/bin/x64/7z.exe b/extractor/bin/x64/7z.exe new file mode 100644 index 00000000..b55fefe6 Binary files /dev/null and b/extractor/bin/x64/7z.exe differ diff --git a/extractor/bin/x86/7z.dll b/extractor/bin/x86/7z.dll new file mode 100644 index 00000000..2bdaed6a Binary files /dev/null and b/extractor/bin/x86/7z.dll differ diff --git a/extractor/bin/x86/7z.exe b/extractor/bin/x86/7z.exe new file mode 100644 index 00000000..101884c3 Binary files /dev/null and b/extractor/bin/x86/7z.exe differ diff --git a/extractor/extractor.py b/extractor/extractor.py new file mode 100644 index 00000000..187cade1 --- /dev/null +++ b/extractor/extractor.py @@ -0,0 +1,130 @@ +import os +import sys +import logging + +Logger = logging.getLogger(__name__) + +# which() and os_platform() breaks when running in Transmission (has to do with os.environ) + +def os_platform(): + # Author Credit: Matthew Scouten @ http://stackoverflow.com/a/7260315 + true_platform = os.environ['PROCESSOR_ARCHITECTURE'] + try: + true_platform = os.environ["PROCESSOR_ARCHITEW6432"] + except KeyError: + pass + #true_platform not assigned to if this does not exist + return true_platform + +def which(program): + # Author Credit: Jay @ http://stackoverflow.com/a/377028 + def is_exe(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + for path in os.environ["PATH"].split(os.pathsep): + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + + return None + +def extract(dirpath, file, outputDestination): + # Using Windows + if os.name == 'nt': + if os_platform() == 'AMD64': + platform = 'x64' + else: + platform = 'x86' + + sevenzipLocation = os.path.normpath(os.path.join(os.path.dirname(sys.argv[0]), 'extractor/bin/' + platform + '/7z.exe')) + if not os.path.exists(sevenzipLocation): + Logger.error("EXTRACTOR: Couldnt find 7-zip, Exiting") + sys.exit(-1) + else: + cmd_7zip = [sevenzipLocation, 'x -y'] + ext_7zip = [".rar",".zip",".tar.gz","tgz",".tar.bz2",".tbz",".tar.lzma",".tlz",".7z",".xz"] + EXTRACT_COMMANDS = dict.fromkeys(ext_7zip, cmd_7zip) + # Using unix + else: + required_cmds=["unrar", "unzip", "tar", "unxz", "unlzma", "7zr", "bunzip2"] + ## Possible future suport: + # gunzip: gz (cmd will delete original archive) + ## the following do not extract to dest dir + # ".xz": ["xz", "-d --keep"], + # ".lzma": ["xz", "-d --format=lzma --keep"], + # ".bz2": ["bzip2", "-d --keep"], + + EXTRACT_COMMANDS = { + ".rar": ["unrar", "x -o+ -y"], + ".tar": ["tar", "-xf"], + ".zip": ["unzip", ""], + ".tar.gz": ["tar", "-xzf"], ".tgz": ["tar", "-xzf"], + ".tar.bz2": ["tar", "-xjf"], ".tbz": ["tar", "-xjf"], + ".tar.lzma": ["tar", "--lzma -xf"], ".tlz": ["tar", "--lzma -xf"], + ".tar.xz": ["tar", "--xz -xf"], ".txz": ["tar", "--xz -xf"], + ".7z": ["7zr", "x"], + } + # Test command exists and if not, remove + for cmd in required_cmds: + if not which(cmd): + for k,v in EXTRACT_COMMANDS.items(): + if cmd in v[0]: + log.error("EXTRACTOR: %s not found, disabling support for %s", cmd, k) + del EXTRACT_COMMANDS[k] + if not EXTRACT_COMMANDS: + Logger.warn("EXTRACTOR: No archive extracting programs found, plugin will be disabled") + + ext = os.path.splitext(file) + filePath = os.path.join(dirpath, file) + if ext[1] in (".gz", ".bz2", ".lzma"): + # Check if this is a tar + if os.path.splitext(ext[0])[1] == ".tar": + cmd = EXTRACT_COMMANDS[".tar" + ext[1]] + else: + if ext[1] in EXTRACT_COMMANDS: + cmd = EXTRACT_COMMANDS[ext[1]] + else: + Logger.debug("EXTRACTOR: Unknown file type: %s", ext[1]) + return False + + # Create outputDestination folder + if not os.path.exists(outputDestination): + try: + Logger.debug("EXTRACTOR: Creating destination folder: %s", outputDestination) + os.makedirs(outputDestination) + except Exception, e: + Logger.error("EXTRACTOR: Not possible to create destination folder: %s", e) + return False + Logger.info("Extracting %s to %s", filePath, outputDestination) + Logger.debug("Extracting %s %s %s %s", cmd[0], cmd[1], filePath, outputDestination) + pwd = os.getcwd() # Get our Present Working Directory + os.chdir(outputDestination) # Not all unpack commands accept full paths, so just extract into this directory + if os.name == 'nt': # Windows needs quotes around directory structure + try: + run = "\"" + cmd[0] + "\" " + cmd[1] + " \"" + filePath + "\"" # Windows needs quotes around directories + res = call(run) + if res == 0: + Logger.info("EXTRACTOR: Extraction was successful for %s to %s", filePath, outputDestination) + else: + Logger.info("EXTRACTOR: Extraction failed for %s. 7zip result was %s", filePath, res) + except: + Logger.error("EXTRACTOR: Extraction failed for %s. Could not call command %s %s", filePath, run) + else: + try: + if cmd[1] == "": # If calling unzip, we dont want to pass the "" + res = call([cmd[0], filePath]) + else: + res = call([cmd[0], cmd[1], filePath]) + if res == 0: + Logger.info("EXTRACTOR: Extraction was successful for %s to %s", filePath, outputDestination) + else: + Logger.error("EXTRACTOR: Extraction failed for %s. 7zip result was %s", filePath, res) + except: + Logger.error("EXTRACTOR: Extraction failed for %s. Could not call command %s %s %s %s", filePath, cmd[0], cmd[1], filePath) + os.chdir(pwd) # Go back to our Original Working Directory + return True \ No newline at end of file diff --git a/extractor/which.py b/extractor/which.py new file mode 100644 index 00000000..80090b66 --- /dev/null +++ b/extractor/which.py @@ -0,0 +1,17 @@ +def which(program): + # Author Credit: Jay @ http://stackoverflow.com/a/377028 + import os + def is_exe(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + for path in os.environ["PATH"].split(os.pathsep): + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + + return None