AlkantarClanX12

Your IP : 18.190.153.77


Current Path : /opt/cloudlinux/venv/lib/python3.11/site-packages/clselect/
Upload File :
Current File : //opt/cloudlinux/venv/lib/python3.11/site-packages/clselect/clselectstatistics.py

#!/opt/cloudlinux/venv/bin/python3 -bb
# coding=utf-8
#
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT


from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from collections import defaultdict
from future.utils import iteritems

from cldetectlib import get_suEXEC_status, get_suPHP_status
from cllimits import CageFs, CageFsException
from clcommon.cpapi import get_domains_php_info, get_system_php_info, getCPName

from .cluserselect import ClUserSelect
from .clselect import ClSelect as ClSelectPhp

from .clselectctl import interpreter_versions_short_summary, server_applications_summary
from typing import Optional, Dict  # NOQA


def _iter_versions(interpreter):
    """
    Return list of InterpreterSummary objects
    :rtype: list[clselectctl.InterpreterSummary]
    """
    return interpreter_versions_short_summary(interpreter)


def iter_server_applications(interpreter):
    """
    Return list of ApplicationSummary objects
    :rtype: list[clselectctl.ApplicationSummary]
    """
    return server_applications_summary(interpreter)


def get_versions_statistics(interpreter):
    # type: (str) -> Optional[Dict]
    interpreters_versions = _iter_versions(interpreter)
    if interpreters_versions is not None:
        return {
            it.version: {
                'full_version': it.version_full,
                'enabled': it.enabled,
                'installed': it.installed
            } for it in interpreters_versions
        }


def _is_acceptable_php_handler_cpanel(handler):
    """
    Handler is supported in the following cases:
    - handler is suphp or lsapi with suexec or suphp (check for last two is
      in the _get_php_selector_usage method)
    - handler is cgi or fcgi (only with suexec, otherwise scripts do not run in cagefs)
    - handler is None (possible when php package was removed and we can`t detect handler, it is set to None)
    """
    return handler in {'suphp', 'lsapi'} or \
        handler in {'cgi', 'fcgi'} and get_suEXEC_status() or handler is None


def _get_php_selector_domains_for_cpanel():
    """
    Return domains that are using php selector.

    1. Skip domains whose version is not system default (php selector
       replaces only system default version binary with symlink to alt-php)
    2. Take only domains that use supported handlers.
    """
    vhosts_php_info = get_domains_php_info()
    default_php_id = get_system_php_info()['default_version_id']
    phpselector_domains = defaultdict(set)
    for domain, domain_info in iteritems(vhosts_php_info):
        if domain_info['php_version_id'] != default_php_id:
            continue

        if _is_acceptable_php_handler_cpanel(domain_info['handler_type']):
            phpselector_domains[domain_info['username']].add(domain)
    return dict(phpselector_domains)


def _get_php_selector_domains_for_plesk():
    """
    Return domains that meet panel specific requirements which will allow php
    selector to work when the common requirements are met.
    """

    allowed_handlers = ('cgi', 'fastcgi')

    def is_allowed_version(handler_id):
        lsphp_vendor_version = 'x-httpd-lsphp-custom'
        if 'lsphp' in handler_id:
            return handler_id == lsphp_vendor_version
        return True

    domains_php_info = get_domains_php_info()

    result = defaultdict(set)
    for domain, info in iteritems(domains_php_info):
        if (info['handler_type'] in allowed_handlers and
                is_allowed_version(info['php_version_id'])):
            result[info['username']].add(domain)
    return dict(result)


def _get_php_selector_domains_for_da():
    """
    Return domains that meet panel specific requirements which will allow php
    selector to work when the common requirements are met.
    """
    allowed_handlers = ('fastcgi', 'suphp', 'cgi', 'lsphp')
    domains_php_info = get_domains_php_info()
    result = defaultdict(set)
    for domain, php_info in iteritems(domains_php_info):
        if php_info['handler_type'] in allowed_handlers:
            result[php_info['username']].add(domain)
    return dict(result)


def _get_php_vhosts_for_current_panel():
    """
    Detect current control panel and
    get list of php selector domains for it
    Return None if control panel is not supported
    """
    panel = getCPName()
    if panel == 'cPanel':
        return _get_php_selector_domains_for_cpanel()
    elif panel == 'DirectAdmin':
        return _get_php_selector_domains_for_da()
    elif panel == 'Plesk':
        return _get_php_selector_domains_for_plesk()
    else:
        # php selector is not officially
        # supported on another control panels
        return None


def get_php_selector_usage():
    """Get users and domains that use php selector"""
    cagefs = CageFs()
    if not cagefs.is_cagefs_present():
        return None

    # check if cagefs is initialized
    try:
        cagefs._load_info()
    except CageFsException:
        return None

    # either suexec or suphp is required to move user into cagefs
    if not any((get_suEXEC_status(), get_suPHP_status())):
        return None

    # ignore unsupported control panels
    php_vhosts = _get_php_vhosts_for_current_panel()
    if php_vhosts is None:
        return None

    php = ClUserSelect()
    domains_by_php_version = defaultdict(set)
    users_by_php_version = defaultdict(set)
    for user, user_domains in iteritems(php_vhosts):
        if not cagefs.get_user_status(user):
            continue

        version = php.get_version(user, show_native_version=False)[0]
        domains_by_php_version[version].update(user_domains)
        users_by_php_version[version].add(user)

    return {
        'domains_by_php_version': domains_by_php_version,
        'users_by_php_version': users_by_php_version
    }


def get_native_version_safe():
    """
    Safely get native version, or None if not set
    """
    php = ClSelectPhp()
    v = php.get_native_version(verbose=False)  # tuple[version, full_version] | None
    if v is None:
        return v
    return v[0]


def get_mode_of_php_selector():
    # type: () -> str
    """
    Get state of PHP selector: without CageFS or normal
    """

    return 'without_cagefs' if ClSelectPhp().work_without_cagefs() else 'normal'


def get_default_php_version():
    # type: () -> str
    """
    Get default version of PHP selector
    """

    # yep, get_version() returns default(!) version, don't ask me 'why'
    return ClSelectPhp().get_version()[0]