def check_encrypted_rar(nzo, filepath): """ Check if file is rar and is encrypted """ encrypted = False if not nzo.password and cfg.pause_on_pwrar() and is_rarfile(filepath): try: zf = RarFile(filepath) encrypted = zf.encrypted if encrypted and int(nzo.encrypted) < 2: nzo.encrypted = 1 else: encrypted = False zf.close() del zf except: logging.debug('RAR file %s cannot be inspected', filepath) return encrypted
def check_encrypted_rar(nzo, filepath): """ Check if file is rar and is encrypted """ encrypted = False if not nzo.password and not nzo.meta.get('password') and cfg.pause_on_pwrar() and is_rarfile(filepath): try: zf = RarFile(filepath, all_names=True) encrypted = zf.encrypted or is_cloaked(filepath, zf.namelist()) if encrypted and int(nzo.encrypted) < 2 and not nzo.reuse: nzo.encrypted = 1 else: encrypted = False zf.close() del zf except: logging.debug('RAR file %s cannot be inspected', filepath) return encrypted
def check_encrypted_rar(nzo, filepath): """ Check if file is rar and is encrypted """ encrypted = False if not nzo.password and cfg.pause_on_pwrar() and is_rarfile(filepath): try: zf = RarFile(filepath, all_names=True) encrypted = zf.encrypted or is_cloaked(filepath, zf.namelist()) if encrypted and int(nzo.encrypted) < 2: nzo.encrypted = 1 else: encrypted = False zf.close() del zf except: logging.debug('RAR file %s cannot be inspected', filepath) return encrypted
def check_encrypted_rar(nzo, filepath): """ Check if file is rar and is encrypted """ encrypted = False if ( nzo.encrypted == 0 and not nzo.password and not nzo.meta.get("password") and cfg.pause_on_pwrar() and is_rarfile(filepath) ): try: zf = RarFile(filepath, all_names=True) encrypted = zf.encrypted or is_cloaked(filepath, zf.namelist()) if encrypted and not nzo.reuse: nzo.encrypted = 1 else: # Don't check other files nzo.encrypted = -1 encrypted = False zf.close() del zf except: logging.debug("RAR file %s cannot be inspected", filepath) return encrypted
class Assembler(Thread): do = None # Link to the instance of this method def __init__(self, queue=None): Thread.__init__(self) if queue: self.queue = queue else: self.queue = Queue.Queue() Assembler.do = self def stop(self): self.process(None) def process(self, job): self.queue.put(job) def run(self): while 1: job = self.queue.get() if not job: logging.info("Shutting down") break nzo, nzf = job if nzf: # Check if enough disk space is free, if not pause downloader and send email if diskspace(force=True)['download_dir'][1] < ( cfg.download_free.get_float() + nzf.bytes) / GIGI: # Only warn and email once if not sabnzbd.downloader.Downloader.do.paused: logging.warning( T('Too little diskspace forcing PAUSE')) # Pause downloader, but don't save, since the disk is almost full! sabnzbd.downloader.Downloader.do.pause() sabnzbd.emailer.diskfull() # Abort all direct unpackers, just to be sure sabnzbd.directunpacker.abort_all() # Place job back in queue and wait 30 seconds to hope it gets resolved self.process(job) sleep(30) continue # Prepare filename nzo.verify_nzf_filename(nzf) nzf.filename = sanitize_filename(nzf.filename) filepath = get_filepath(long_path(cfg.download_dir.get_path()), nzo, nzf.filename) nzf.filename = get_filename(filepath) if filepath: logging.info('Decoding %s %s', filepath, nzf.type) try: filepath = self.assemble(nzf, filepath) except IOError, (errno, strerror): # If job was deleted or in active post-processing, ignore error if not nzo.deleted and not nzo.is_gone( ) and not nzo.pp_active: # 28 == disk full => pause downloader if errno == 28: logging.error(T('Disk full! Forcing Pause')) else: logging.error( T('Disk error on creating file %s'), clip_path(filepath)) # Log traceback logging.info('Traceback: ', exc_info=True) # Pause without saving sabnzbd.downloader.Downloader.do.pause() continue except: logging.error(T('Fatal error in Assembler'), exc_info=True) break # Clean-up admin data nzf.remove_admin() # Do rar-related processing if rarfile.is_rarfile(filepath): # Encryption and unwanted extension detection rar_encrypted, unwanted_file = check_encrypted_and_unwanted_files( nzo, filepath) if rar_encrypted: if cfg.pause_on_pwrar() == 1: logging.warning( remove_warning_label( T('WARNING: Paused job "%s" because of encrypted RAR file (if supplied, all passwords were tried)' )), nzo.final_name) nzo.pause() else: logging.warning( remove_warning_label( T('WARNING: Aborted job "%s" because of encrypted RAR file (if supplied, all passwords were tried)' )), nzo.final_name) nzo.fail_msg = T( 'Aborted, encryption detected') sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo) if unwanted_file: logging.warning( remove_warning_label( T('WARNING: In "%s" unwanted extension in RAR file. Unwanted file is %s ' )), nzo.final_name, unwanted_file) logging.debug( T('Unwanted extension is in rar file %s'), filepath) if cfg.action_on_unwanted_extensions( ) == 1 and nzo.unwanted_ext == 0: logging.debug('Unwanted extension ... pausing') nzo.unwanted_ext = 1 nzo.pause() if cfg.action_on_unwanted_extensions() == 2: logging.debug( 'Unwanted extension ... aborting') nzo.fail_msg = T( 'Aborted, unwanted extension detected') sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo) # Add to direct unpack nzo.add_to_direct_unpacker(nzf) elif par2file.is_parfile(filepath): # Parse par2 files, cloaked or not nzo.handle_par2(nzf, filepath) filter, reason = nzo_filtered_by_rating(nzo) if filter == 1: logging.warning( remove_warning_label( T('WARNING: Paused job "%s" because of rating (%s)' )), nzo.final_name, reason) nzo.pause() elif filter == 2: logging.warning( remove_warning_label( T('WARNING: Aborted job "%s" because of rating (%s)' )), nzo.final_name, reason) nzo.fail_msg = T( 'Aborted, rating filter matched (%s)') % reason sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo)
def check_encrypted_and_unwanted_files(nzo, filepath): """ Combines check for unwanted and encrypted files to save on CPU and IO """ encrypted = False unwanted = None if (cfg.unwanted_extensions() and cfg.action_on_unwanted_extensions()) or ( nzo.encrypted == 0 and cfg.pause_on_pwrar()): # These checks should not break the assembler try: # Rarfile freezes on Windows special names, so don't try those! if sabnzbd.WIN32 and has_win_device(filepath): return encrypted, unwanted # Is it even a rarfile? if rarfile.is_rarfile(filepath): # Open the rar rarfile.UNRAR_TOOL = sabnzbd.newsunpack.RAR_COMMAND zf = rarfile.RarFile(filepath, all_names=True) # Check for encryption if nzo.encrypted == 0 and cfg.pause_on_pwrar() and ( zf.needs_password() or is_cloaked(nzo, filepath, zf.namelist())): # Load all passwords passwords = get_all_passwords(nzo) # Cloaked job? if is_cloaked(nzo, filepath, zf.namelist()): encrypted = True elif not sabnzbd.HAVE_CRYPTOGRAPHY and not passwords: # if no cryptography installed, only error when no password was set logging.info(T('%s missing'), 'Python Cryptography') nzo.encrypted = 1 encrypted = True elif sabnzbd.HAVE_CRYPTOGRAPHY: # Lets test if any of the password work password_hit = False for password in passwords: if password: logging.info( 'Trying password "%s" on job "%s"', password, nzo.final_name) try: zf.setpassword(password) except: # On weird passwords the setpassword() will fail # but the actual rartest() will work pass try: zf.testrar() password_hit = password break except rarfile.RarCRCError: # On CRC error we can continue! password_hit = password break except Exception as e: # Did we start from the right volume? if 'need to start extraction from a previous volume' in e[ 0]: return encrypted, unwanted # This one failed pass # Did any work? if password_hit: # We always trust the user's input if not nzo.password: nzo.password = password_hit # Don't check other files logging.info('Password "%s" matches for job "%s"', password_hit, nzo.final_name) nzo.encrypted = -1 encrypted = False else: # Encrypted and none of them worked nzo.encrypted = 1 encrypted = True else: # Don't check other files nzo.encrypted = -1 encrypted = False # Check for unwanted extensions if cfg.unwanted_extensions( ) and cfg.action_on_unwanted_extensions(): for somefile in zf.namelist(): logging.debug('File contains: %s', somefile) if get_ext(somefile).replace( '.', '').lower() in cfg.unwanted_extensions(): logging.debug('Unwanted file %s', somefile) unwanted = somefile zf.close() del zf except: logging.info('Error during inspection of RAR-file %s', filepath) logging.debug('Traceback: ', exc_info=True) return encrypted, unwanted
class Assembler(Thread): do = None # Link to the instance of this method def __init__(self, queue=None): Thread.__init__(self) if queue: self.queue = queue else: self.queue = Queue.Queue() Assembler.do = self def stop(self): self.process(None) def process(self, job): self.queue.put(job) def run(self): import sabnzbd.nzbqueue while 1: job = self.queue.get() if not job: logging.info("Shutting down") break nzo, nzf = job if nzf: sabnzbd.CheckFreeSpace() filename = sanitize_filename(nzf.filename) nzf.filename = filename dupe = nzo.check_for_dupe(nzf) filepath = get_filepath(cfg.download_dir.get_path(), nzo, filename) if filepath: logging.info('Decoding %s %s', filepath, nzf.type) try: filepath = _assemble(nzf, filepath, dupe) except IOError, (errno, strerror): if nzo.deleted: # Job was deleted, ignore error pass else: # 28 == disk full => pause downloader if errno == 28: logging.error(Ta('Disk full! Forcing Pause')) else: logging.error( Ta('Disk error on creating file %s'), latin1(filepath)) # Pause without saving sabnzbd.downloader.Downloader.do.pause(save=False) except: logging.error('Fatal error in Assembler', exc_info=True) break nzf.remove_admin() setname = nzf.setname if nzf.is_par2 and (nzo.md5packs.get(setname) is None): pack = GetMD5Hashes(filepath)[0] if pack: nzo.md5packs[setname] = pack logging.debug('Got md5pack for set %s', setname) if check_encrypted_rar(nzo, filepath): if cfg.pause_on_pwrar() == 1: logging.warning( Ta('WARNING: Paused job "%s" because of encrypted RAR file' ), latin1(nzo.final_name)) nzo.pause() else: logging.warning( Ta('WARNING: Aborted job "%s" because of encrypted RAR file' ), latin1(nzo.final_name)) nzo.fail_msg = T('Aborted, encryption detected') import sabnzbd.nzbqueue sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo) nzf.completed = True
def run(self): while 1: job = self.queue.get() if not job: logging.info("Shutting down") break nzo, nzf, file_done = job if nzf: # Check if enough disk space is free after each file is done # If not enough space left, pause downloader and send email if (file_done and diskspace(force=True)["download_dir"][1] < (cfg.download_free.get_float() + nzf.bytes) / GIGI): # Only warn and email once if not sabnzbd.downloader.Downloader.do.paused: logging.warning( T("Too little diskspace forcing PAUSE")) # Pause downloader, but don't save, since the disk is almost full! sabnzbd.downloader.Downloader.do.pause() sabnzbd.emailer.diskfull_mail() # Abort all direct unpackers, just to be sure sabnzbd.directunpacker.abort_all() # Prepare filepath filepath = nzf.prepare_filepath() if filepath: logging.debug("Decoding part of %s", filepath) try: self.assemble(nzf, file_done) except IOError as err: # If job was deleted or in active post-processing, ignore error if not nzo.deleted and not nzo.is_gone( ) and not nzo.pp_active: # 28 == disk full => pause downloader if err.errno == 28: logging.error(T("Disk full! Forcing Pause")) else: logging.error( T("Disk error on creating file %s"), clip_path(filepath)) # Log traceback logging.info("Traceback: ", exc_info=True) # Pause without saving sabnzbd.downloader.Downloader.do.pause() continue except: logging.error(T("Fatal error in Assembler"), exc_info=True) break # Continue after partly written data if not file_done: continue # Clean-up admin data logging.info("Decoding finished %s", filepath) nzf.remove_admin() # Do rar-related processing if rarfile.is_rarfile(filepath): # Encryption and unwanted extension detection rar_encrypted, unwanted_file = check_encrypted_and_unwanted_files( nzo, filepath) if rar_encrypted: if cfg.pause_on_pwrar() == 1: logging.warning( T('Paused job "%s" because of encrypted RAR file (if supplied, all passwords were tried)' ), nzo.final_name, ) nzo.pause() else: logging.warning( T('Aborted job "%s" because of encrypted RAR file (if supplied, all passwords were tried)' ), nzo.final_name, ) nzo.fail_msg = T( "Aborted, encryption detected") sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo) if unwanted_file: logging.warning( T('In "%s" unwanted extension in RAR file. Unwanted file is %s ' ), nzo.final_name, unwanted_file, ) logging.debug( T("Unwanted extension is in rar file %s"), filepath) if cfg.action_on_unwanted_extensions( ) == 1 and nzo.unwanted_ext == 0: logging.debug("Unwanted extension ... pausing") nzo.unwanted_ext = 1 nzo.pause() if cfg.action_on_unwanted_extensions() == 2: logging.debug( "Unwanted extension ... aborting") nzo.fail_msg = T( "Aborted, unwanted extension detected") sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo) # Add to direct unpack nzo.add_to_direct_unpacker(nzf) elif par2file.is_parfile(filepath): # Parse par2 files, cloaked or not nzo.handle_par2(nzf, filepath) filter_output, reason = nzo_filtered_by_rating(nzo) if filter_output == 1: logging.warning( T('Paused job "%s" because of rating (%s)'), nzo.final_name, reason, ) nzo.pause() elif filter_output == 2: logging.warning( T('Aborted job "%s" because of rating (%s)'), nzo.final_name, reason, ) nzo.fail_msg = T( "Aborted, rating filter matched (%s)") % reason sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo) else: sabnzbd.nzbqueue.NzbQueue.do.remove(nzo.nzo_id, add_to_history=False, cleanup=False) PostProcessor.do.process(nzo)
class Assembler(Thread): do = None # Link to the instance of this method def __init__(self, queue=None): Thread.__init__(self) if queue: self.queue = queue else: self.queue = Queue.Queue() Assembler.do = self def stop(self): self.process(None) def process(self, job): self.queue.put(job) def run(self): while 1: job = self.queue.get() if not job: logging.info("Shutting down") break nzo, nzf = job if nzf: sabnzbd.CheckFreeSpace() # We allow win_devices because otherwise par2cmdline fails to repair filename = sanitize_filename(nzf.filename, allow_win_devices=True) nzf.filename = filename dupe = nzo.check_for_dupe(nzf) filepath = get_filepath(long_path(cfg.download_dir.get_path()), nzo, filename) if filepath: logging.info('Decoding %s %s', filepath, nzf.type) try: filepath = _assemble(nzf, filepath, dupe) except IOError, (errno, strerror): # If job was deleted, ignore error if not nzo.is_gone(): # 28 == disk full => pause downloader if errno == 28: logging.error(T('Disk full! Forcing Pause')) else: logging.error( T('Disk error on creating file %s'), clip_path(filepath)) # Pause without saving sabnzbd.downloader.Downloader.do.pause(save=False) continue except: logging.error(T('Fatal error in Assembler'), exc_info=True) break nzf.remove_admin() setname = nzf.setname if nzf.is_par2 and (nzo.md5packs.get(setname) is None): pack = GetMD5Hashes(filepath)[0] if pack: nzo.md5packs[setname] = pack logging.debug('Got md5pack for set %s', setname) # Valid md5pack, so use this par2-file as main par2 file for the set if setname in nzo.partable: # First copy the set of extrapars, we need them later nzf.extrapars = nzo.partable[setname].extrapars nzo.partable[setname] = nzf rar_encrypted, unwanted_file = check_encrypted_and_unwanted_files( nzo, filepath) if rar_encrypted: if cfg.pause_on_pwrar() == 1: logging.warning( T('WARNING: Paused job "%s" because of encrypted RAR file (if supplied, all passwords were tried)' ), nzo.final_name) nzo.pause() else: logging.warning( T('WARNING: Aborted job "%s" because of encrypted RAR file (if supplied, all passwords were tried)' ), nzo.final_name) nzo.fail_msg = T('Aborted, encryption detected') sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo) if unwanted_file: logging.warning( T('WARNING: In "%s" unwanted extension in RAR file. Unwanted file is %s ' ), nzo.final_name, unwanted_file) logging.debug( T('Unwanted extension is in rar file %s'), filepath) if cfg.action_on_unwanted_extensions( ) == 1 and nzo.unwanted_ext == 0: logging.debug('Unwanted extension ... pausing') nzo.unwanted_ext = 1 nzo.pause() if cfg.action_on_unwanted_extensions() == 2: logging.debug('Unwanted extension ... aborting') nzo.fail_msg = T( 'Aborted, unwanted extension detected') sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo) filter, reason = nzo_filtered_by_rating(nzo) if filter == 1: logging.warning( Ta('WARNING: Paused job "%s" because of rating (%s)' ), nzo.final_name, reason) nzo.pause() elif filter == 2: logging.warning( Ta('WARNING: Aborted job "%s" because of rating (%s)' ), nzo.final_name, reason) nzo.fail_msg = T( 'Aborted, rating filter matched (%s)') % reason sabnzbd.nzbqueue.NzbQueue.do.end_job(nzo) nzf.completed = True
def run(self): while 1: # Set NzbObject and NzbFile objects to None so references # from this thread do not keep the objects alive (see #1628) nzo = nzf = None nzo, nzf, file_done = self.queue.get() if not nzo: logging.info("Shutting down") break if nzf: # Check if enough disk space is free after each file is done # If not enough space left, pause downloader and send email if file_done and not sabnzbd.Downloader.paused: freespace = diskspace(force=True) full_dir = None required_space = (cfg.download_free.get_float() + nzf.bytes) / GIGI if freespace["download_dir"][1] < required_space: full_dir = "download_dir" # Enough space in download_dir, check complete_dir complete_free = cfg.complete_free.get_float() if complete_free > 0 and not full_dir: required_space = 0 if cfg.direct_unpack(): required_space = (complete_free + nzo.bytes_downloaded) / GIGI else: # Continue downloading until 95% complete before checking if nzo.bytes_tried > (nzo.bytes - nzo.bytes_par2) * 0.95: required_space = (complete_free + nzo.bytes) / GIGI if required_space and freespace["complete_dir"][1] < required_space: full_dir = "complete_dir" if full_dir: logging.warning(T("Too little diskspace forcing PAUSE")) # Pause downloader, but don't save, since the disk is almost full! sabnzbd.Downloader.pause() if cfg.fulldisk_autoresume(): sabnzbd.Scheduler.plan_diskspace_resume(full_dir, required_space) sabnzbd.emailer.diskfull_mail() # Prepare filepath filepath = nzf.prepare_filepath() if filepath: logging.debug("Decoding part of %s", filepath) try: self.assemble(nzf, file_done) except IOError as err: # If job was deleted or in active post-processing, ignore error if not nzo.deleted and not nzo.is_gone() and not nzo.pp_active: # 28 == disk full => pause downloader if err.errno == 28: logging.error(T("Disk full! Forcing Pause")) else: logging.error(T("Disk error on creating file %s"), clip_path(filepath)) # Log traceback logging.info("Traceback: ", exc_info=True) # Pause without saving sabnzbd.Downloader.pause() continue except: logging.error(T("Fatal error in Assembler"), exc_info=True) break # Continue after partly written data if not file_done: continue # Clean-up admin data logging.info("Decoding finished %s", filepath) nzf.remove_admin() # Do rar-related processing if rarfile.is_rarfile(filepath): # Encryption and unwanted extension detection rar_encrypted, unwanted_file = check_encrypted_and_unwanted_files(nzo, filepath) if rar_encrypted: if cfg.pause_on_pwrar() == 1: logging.warning( T( 'Paused job "%s" because of encrypted RAR file (if supplied, all passwords were tried)' ), nzo.final_name, ) nzo.pause() else: logging.warning( T( 'Aborted job "%s" because of encrypted RAR file (if supplied, all passwords were tried)' ), nzo.final_name, ) nzo.fail_msg = T("Aborted, encryption detected") sabnzbd.NzbQueue.end_job(nzo) if unwanted_file: # Don't repeat the warning after a user override of an unwanted extension pause if nzo.unwanted_ext == 0: logging.warning( T('In "%s" unwanted extension in RAR file. Unwanted file is %s '), nzo.final_name, unwanted_file, ) logging.debug(T("Unwanted extension is in rar file %s"), filepath) if cfg.action_on_unwanted_extensions() == 1 and nzo.unwanted_ext == 0: logging.debug("Unwanted extension ... pausing") nzo.unwanted_ext = 1 nzo.pause() if cfg.action_on_unwanted_extensions() == 2: logging.debug("Unwanted extension ... aborting") nzo.fail_msg = T("Aborted, unwanted extension detected") sabnzbd.NzbQueue.end_job(nzo) # Add to direct unpack nzo.add_to_direct_unpacker(nzf) elif par2file.is_parfile(filepath): # Parse par2 files, cloaked or not nzo.handle_par2(nzf, filepath) filter_output, reason = nzo_filtered_by_rating(nzo) if filter_output == 1: logging.warning( T('Paused job "%s" because of rating (%s)'), nzo.final_name, reason, ) nzo.pause() elif filter_output == 2: logging.warning( T('Aborted job "%s" because of rating (%s)'), nzo.final_name, reason, ) nzo.fail_msg = T("Aborted, rating filter matched (%s)") % reason sabnzbd.NzbQueue.end_job(nzo) else: sabnzbd.NzbQueue.remove(nzo.nzo_id, cleanup=False) sabnzbd.PostProcessor.process(nzo)
def check_encrypted_and_unwanted_files(nzo: NzbObject, filepath: str) -> Tuple[bool, Optional[str]]: """ Combines check for unwanted and encrypted files to save on CPU and IO """ encrypted = False unwanted = None if (cfg.unwanted_extensions() and cfg.action_on_unwanted_extensions()) or ( nzo.encrypted == 0 and cfg.pause_on_pwrar() ): # These checks should not break the assembler try: # Rarfile freezes on Windows special names, so don't try those! if sabnzbd.WIN32 and has_win_device(filepath): return encrypted, unwanted # Is it even a rarfile? if rarfile.is_rarfile(filepath): # Open the rar rarfile.UNRAR_TOOL = sabnzbd.newsunpack.RAR_COMMAND zf = rarfile.RarFile(filepath, single_file_check=True) # Check for encryption if ( nzo.encrypted == 0 and cfg.pause_on_pwrar() and (zf.needs_password() or is_cloaked(nzo, filepath, zf.namelist())) ): # Load all passwords passwords = get_all_passwords(nzo) # Cloaked job? if is_cloaked(nzo, filepath, zf.namelist()): encrypted = True elif not passwords: # Only error when no password was set nzo.encrypted = 1 encrypted = True else: # Lets test if any of the password work password_hit = False for password in passwords: if password: logging.info('Trying password "%s" on job "%s"', password, nzo.final_name) try: zf.setpassword(password) except rarfile.Error: # On weird passwords the setpassword() will fail # but the actual testrar() will work pass try: zf.testrar() password_hit = password break except rarfile.RarWrongPassword: # This one really didn't work pass except rarfile.RarCRCError as e: # CRC errors can be thrown for wrong password or # missing the next volume (with correct password) if "cannot find volume" in str(e).lower(): # We assume this one worked! password_hit = password break # This one didn't work pass except: # All the other errors we skip, they might be fixable in post-proc. # For example starting from the wrong volume, or damaged files # This will cause the check to be performed again for the next rar, might # be disk-intensive! Could be removed later and just accept the password. return encrypted, unwanted # Did any work? if password_hit: # We always trust the user's input if not nzo.password: nzo.password = password_hit # Don't check other files logging.info('Password "%s" matches for job "%s"', password_hit, nzo.final_name) nzo.encrypted = -1 encrypted = False else: # Encrypted and none of them worked nzo.encrypted = 1 encrypted = True # Check for unwanted extensions if cfg.unwanted_extensions() and cfg.action_on_unwanted_extensions(): for somefile in zf.namelist(): logging.debug("File contains: %s", somefile) if get_ext(somefile).replace(".", "").lower() in cfg.unwanted_extensions(): logging.debug("Unwanted file %s", somefile) unwanted = somefile zf.close() del zf except: logging.info("Error during inspection of RAR-file %s", filepath) logging.debug("Traceback: ", exc_info=True) return encrypted, unwanted
def check_encrypted_and_unwanted_files(nzo, filepath): """ Combines check for unwanted and encrypted files to save on CPU and IO """ encrypted = False unwanted = None if (cfg.unwanted_extensions() and cfg.action_on_unwanted_extensions()) or (nzo.encrypted == 0 and cfg.pause_on_pwrar()): # These checks should not break the assembler try: # Rarfile freezes on Windows special names, so don't try those! if sabnzbd.WIN32 and has_win_device(filepath): return encrypted, unwanted # Is it even a rarfile? if rarfile.is_rarfile(filepath): # Open the rar rarfile.UNRAR_TOOL = sabnzbd.newsunpack.RAR_COMMAND zf = rarfile.RarFile(filepath, all_names=True) # Check for encryption if nzo.encrypted == 0 and cfg.pause_on_pwrar() and (zf.needs_password() or is_cloaked(nzo, filepath, zf.namelist())): # Load all passwords passwords = get_all_passwords(nzo) # Cloaked job? if is_cloaked(nzo, filepath, zf.namelist()): encrypted = True elif not sabnzbd.HAVE_CRYPTOGRAPHY and not passwords: # if no cryptography installed, only error when no password was set logging.info(T('%s missing'), 'Python Cryptography') nzo.encrypted = 1 encrypted = True elif sabnzbd.HAVE_CRYPTOGRAPHY: # Lets test if any of the password work password_hit = False for password in passwords: if password: logging.info('Trying password "%s" on job "%s"', password, nzo.final_name) try: zf.setpassword(password) except: # On weird passwords the setpassword() will fail # but the actual rartest() will work pass try: zf.testrar() password_hit = password break except rarfile.RarCRCError: # On CRC error we can continue! password_hit = password break except Exception as e: # Did we start from the right volume? if 'need to start extraction from a previous volume' in e[0]: return encrypted, unwanted # This one failed pass # Did any work? if password_hit: # Don't check other files logging.info('Password "%s" matches for job "%s"', password_hit, nzo.final_name) nzo.encrypted = -1 encrypted = False else: # Encrypted and none of them worked nzo.encrypted = 1 encrypted = True else: # Don't check other files nzo.encrypted = -1 encrypted = False # Check for unwanted extensions if cfg.unwanted_extensions() and cfg.action_on_unwanted_extensions(): for somefile in zf.namelist(): logging.debug('File contains: %s', somefile) if os.path.splitext(somefile)[1].replace('.', '').lower() in cfg.unwanted_extensions(): logging.debug('Unwanted file %s', somefile) unwanted = somefile zf.close() del zf except: logging.info('Error during inspection of RAR-file %s', filepath, exc_info=True) return encrypted, unwanted
def check_encrypted_and_unwanted_files(nzo, filepath): """ Combines check for unwanted and encrypted files to save on CPU and IO """ encrypted = False unwanted = None if cfg.unwanted_extensions() or (nzo.encrypted == 0 and cfg.pause_on_pwrar()): # Safe-format for Windows # RarFile requires de-unicoded filenames for zf.testrar() filepath_split = os.path.split(filepath) workdir_short = short_path(filepath_split[0]) filepath = deunicode(os.path.join(workdir_short, filepath_split[1])) # Is it even a rarfile? if rarfile.is_rarfile(filepath): try: zf = rarfile.RarFile(filepath, all_names=True) # Check for encryption if nzo.encrypted == 0 and cfg.pause_on_pwrar() and (zf.needs_password() or is_cloaked(filepath, zf.namelist())): # Load all passwords passwords = get_all_passwords(nzo) # if no cryptography installed, only error when no password was set if not sabnzbd.HAVE_CRYPTOGRAPHY and not passwords: logging.info(T('%s missing'), 'Python Cryptography') nzo.encrypted = 1 encrypted = True elif sabnzbd.HAVE_CRYPTOGRAPHY: # Lets test if any of the password work password_hit = False rarfile.UNRAR_TOOL = sabnzbd.newsunpack.RAR_COMMAND for password in passwords: if password: logging.info('Trying password "%s" on job "%s"', password, nzo.final_name) try: zf.setpassword(password) zf.testrar() password_hit = password break except rarfile.RarCRCError: # On CRC error we can continue! password_hit = password break except: pass # Did any work? if password_hit: # Don't check other files logging.info('Password "%s" matches for job "%s"', password_hit, nzo.final_name) nzo.encrypted = -1 encrypted = False else: # Encrypted and none of them worked nzo.encrypted = 1 encrypted = True else: # Don't check other files nzo.encrypted = -1 encrypted = False # Check for unwanted extensions if cfg.unwanted_extensions(): for somefile in zf.namelist(): logging.debug('File contains: %s', somefile) if os.path.splitext(somefile)[1].replace('.', '').lower() in cfg.unwanted_extensions(): logging.debug('Unwanted file %s', somefile) unwanted = somefile zf.close() zf.close() del zf except: logging.debug('RAR file %s cannot be inspected', filepath) return encrypted, unwanted