<commit_before># -*- coding: utf-8 -*-
"""
    latexonhttp.workspaces.filesystem
    ~~~~~~~~~~~~~~~~~~~~~
    Filesystem driver / management for build workspaces.

    :copyright: (c) 2019 <NAME>.
    :license: AGPL, see LICENSE for more details.
"""
import logging
import os.path
import shutil

logger = logging.getLogger(__name__)

CHECK_DATA_SPEC_SIZE_ESTIMATE = True
WORKSPACE_DIRECTORY = "./tmp/loh_workspaces"

# TODO Clean workspace directory on start/init?
# --> if there was an application error, the workspace is orphaned and not removed.


def is_safe_path(basedir, path, follow_symlinks=False):
    # https://security.openstack.org/guidelines/dg_using-file-paths.html
    # resolves symbolic links
    if follow_symlinks:
        return os.path.realpath(path).startswith(basedir)
    return os.path.abspath(path).startswith(basedir)


def get_workspace_root_path(workspace_id):
    return os.path.abspath("{}/{}".format(WORKSPACE_DIRECTORY, workspace_id))


def get_resource_fullpath(workspace_id, resource):
    return os.path.abspath(
        "{}/{}".format(get_workspace_root_path(workspace_id), resource["build_path"])
    )


def persist_resource_to_workspace(workspace_id, resource, data):
    resource_full_path = get_resource_fullpath(workspace_id, resource)
    if not is_safe_path(get_workspace_root_path(workspace_id), resource_full_path):
        return "INVALID_PATH"
    # TODO Id for identifying input resources.
    logger.info("Writing to %s ...", resource_full_path)<commit_msg>Support again "deep" path in workspaces<commit_after># -*- coding: utf-8 -*-
"""
    latexonhttp.workspaces.filesystem
    ~~~~~~~~~~~~~~~~~~~~~
    Filesystem driver / management for build workspaces.

    :copyright: (c) 2019 <NAME>.
    :license: AGPL, see LICENSE for more details.
"""
import logging
import os.path
import shutil

logger = logging.getLogger(__name__)

CHECK_DATA_SPEC_SIZE_ESTIMATE = True
WORKSPACE_DIRECTORY = "./tmp/loh_workspaces"

# TODO Clean workspace directory on start/init?
# --> if there was an application error, the workspace is orphaned and not removed.


def is_safe_path(basedir, path, follow_symlinks=False):
    # https://security.openstack.org/guidelines/dg_using-file-paths.html
    # resolves symbolic links
    if follow_symlinks:
        return os.path.realpath(path).startswith(basedir)
    return os.path.abspath(path).startswith(basedir)


def get_workspace_root_path(workspace_id):
    return os.path.abspath("{}/{}".format(WORKSPACE_DIRECTORY, workspace_id))


def get_resource_fullpath(workspace_id, resource):
    return os.path.abspath(
        "{}/{}".format(get_workspace_root_path(workspace_id), resource["build_path"])
    )


def persist_resource_to_workspace(workspace_id, resource, data):
    resource_full_path = get_resource_fullpath(workspace_id, resource)
    if not is_safe_path(get_workspace_root_path(workspace_id), resource_full_path):
        return "INVALID_PATH"
    # TODO Id for identifying input resources.
    logger.info("Writing to %s ...", resource_full_path)
    os.makedirs(os.path.dirname(resource_full_path), exist_ok=True)
{'fraction_non_alphanumeric': 0.1192159383033419, 'fraction_numerical': 0.003213367609254499, 'mean_word_length': 4.691042047531993, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5378504', 'n_tokens_mistral': 1016, 'n_tokens_neox': 979, 'n_words': 208}