Exemplo n.º 1
0
def convert_state_file_to_conf_74(filename, refactoring_tool=None):
    """
    Converts .pstate file (pre-7.4.0) to .conf file.
    :param filename: .pstate file
    :param refactoring_tool: RefactoringTool instance if using Python3
    :return: None
    """
    def _fix_state_config(config):
        for section, option in [('state', 'metainfo'), ('state', 'engineresumedata')]:
            value = config.get(section, option, literal_eval=False)
            try:
                value = str(refactoring_tool.refactor_string(value + '\n', option + '_2to3'))
                ungarbled_dict = recursive_ungarble_metainfo(ast.literal_eval(value))
                value = ungarbled_dict or ast.literal_eval(value)
                config.set(section, option, base64.b64encode(lt.bencode(value)).decode('utf-8'))
            except (ValueError, SyntaxError, ParseError) as ex:
                logger.error("Config could not be fixed, probably corrupted. Exception: %s %s", type(ex), str(ex))
                return None
        return config

    old_config = CallbackConfigParser()
    try:
        old_config.read_file(str(filename))
    except MissingSectionHeaderError:
        logger.error("Removing download state file %s since it appears to be corrupt", filename)
        os.remove(filename)

    # We first need to fix the .state file such that it has the correct metainfo/resumedata.
    # If the config cannot be fixed, it is likely corrupted in which case we simply remove the file.
    fixed_config = _fix_state_config(old_config)
    if not fixed_config:
        logger.error("Removing download state file %s since it could not be fixed", filename)
        os.remove(filename)
        return

    # Remove dlstate since the same information is already stored in the resumedata
    if old_config.has_option('state', 'dlstate'):
        old_config.remove_option('state', 'dlstate')

        new_config = ConfigObj(infile=str(filename)[:-6] + '.conf', encoding='utf8')
        for section in old_config.sections():
            for key, _ in old_config.items(section):
                val = old_config.get(section, key)
                if section not in new_config:
                    new_config[section] = {}
                new_config[section][key] = val
        new_config.write()
        os.remove(filename)
Exemplo n.º 2
0
def cleanup_noncompliant_channel_torrents(state_dir):
    logger = logging.getLogger(__name__)
    channels_dir = state_dir / "channels"
    # Remove torrents contents
    if channels_dir.exists():
        for d in channels_dir.iterdir():
            if len(d.stem) != CHANNEL_DIR_NAME_LENGTH:
                dir_path = channels_dir / d
                # We remove both malformed channel dirs and .torrent and .mdblob files for personal channel
                if dir_path.is_dir():
                    shutil.rmtree(str(dir_path), ignore_errors=True)
                elif dir_path.is_file():
                    os.unlink(str(dir_path))

    # Remove .state torrent resume files
    resume_dir = state_dir / "dlcheckpoints"
    if resume_dir.exists():
        for f in resume_dir.iterdir():
            if not str(f).endswith('.state'):
                continue
            file_path = resume_dir / f
            pstate = CallbackConfigParser()
            try:
                pstate.read_file(file_path)
            except (ParsingError, MissingSectionHeaderError):
                logger.warning(
                    "Parsing channel torrent resume file %s failed, deleting",
                    file_path)
                os.unlink(file_path)
                continue

            if pstate and pstate.has_option('download_defaults', 'channel_download') and \
                    pstate.get('download_defaults', 'channel_download'):
                try:
                    name = pstate.get('state', 'metainfo')['info']['name']
                    if name and len(name) != CHANNEL_DIR_NAME_LENGTH:
                        os.unlink(file_path)
                except (TypeError, KeyError, ValueError):
                    logger.debug(
                        "Malfored .pstate file %s found during cleanup of non-compliant channel torrents.",
                        file_path)