MOON
Server: Apache
System: Linux kvm.asjudinet.com 5.14.0-611.54.6.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Fri May 15 04:23:18 EDT 2026 x86_64
User: asjudine (1001)
PHP: 8.0.30
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //opt/cloudlinux/venv/lib64/python3.11/site-packages/clwpos/wpos_hooks.py
#!/opt/cloudlinux/venv/bin/python3 -bb

#
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENCE.TXT

import subprocess
import sys
from distutils.sysconfig import get_python_lib
from functools import partial
from pathlib import Path

from clwpos.constants import (
    ALT_PHP_REDIS_ENABLE_UTILITY,
    INSTALL_CACHING_HOOKS_UTILITY,
    PHP_REDIS_ENABLE_UTILITY,
)
from clwpos.feature_suites import any_suite_allowed_on_server, is_module_allowed_for_user
from clwpos.optimization_features import OBJECT_CACHE_FEATURE
from clwpos.utils import is_wpos_supported

UNIVERSAL_HOOK_PATH_DNF = '/etc/dnf/universal-hooks/multi_pkgs/transaction'
UNIVERSAL_HOOK_PATH_YUM = '/etc/yum/universal-hooks/multi_pkgs/posttrans'
UNIVERSAL_HOOK_PATH_APT = '/etc/apt/universal-hooks/multi_pkgs/Post-Invoke'
# Matches the alt-phpXY-pecl-ext meta package AND the individual
# alt-phpXY-pecl-<ext> packages (the universal-hooks regex is anchored:
# ^alt-php.*-pecl-.*$). The individual packages ship php.d.std/<NN>-<ext>.ini
# (ALTPHP-2352), so their updates must re-run enable_redis_for_alt_php.py
# to keep php.ini the single active declaration (CLOS-6959).
ALT_HOOK_DIRNAME = 'alt-php__WILDCARD__-pecl-__WILDCARD__'
# Hook directories used by previous versions, cleaned up on (re)install
LEGACY_ALT_HOOK_DIRNAMES = ('alt-php__WILDCARD__-pecl-ext',)
EA_HOOK_DIRNAME = 'ea-php__WILDCARD__'
PLESK_HOOK_DIRNAME = 'plesk-php__WILDCARD__'
HOOKS_LISTENERS_DIR = '/usr/share/cloudlinux/hooks/listeners'
MODIFY_USER_HOOK = 'wpos_modify_user_hook.py'
USER_DIRS_HOOK = 'wpos_user_dirs_hook.py'
# Hooks that depend on AccelerateWP activation state
DYNAMIC_WPOS_HOOKS = (MODIFY_USER_HOOK,)
# Default hooks that should be always installed
DEFAULT_WPOS_HOOKS = (USER_DIRS_HOOK,)


def _install_universal_hook(path_provider, target_binary: str) -> None:
    """
    Create hook dir and symlink the target binary if it doesn't exist yet.
    """
    hook_dir_path = path_provider()
    hook_dir_path.mkdir(parents=True, exist_ok=True)
    hook_name = Path(target_binary).name
    hook_full_path = Path(hook_dir_path, hook_name)
    if not hook_full_path.exists():
        hook_full_path.symlink_to(target_binary)


def _uninstall_universal_hook(path_provider, target_binary: str) -> None:
    """
    Remove hook symlink if present (even if broken).
    """
    hook_dir_path = path_provider()
    hook_name = Path(target_binary).name
    hook_full_path = Path(hook_dir_path, hook_name)
    if hook_full_path.is_symlink():
        hook_full_path.unlink()


def _universal_hook_path(dir_name: str) -> Path:
    """
    Get path to the package manager universal hooks directory
    with the given (wildcard) name.
    """
    if Path('/etc/apt/').exists():
        return Path(UNIVERSAL_HOOK_PATH_APT, dir_name)
    elif Path('/etc/dnf/').exists():
        return Path(UNIVERSAL_HOOK_PATH_DNF, dir_name)
    return Path(UNIVERSAL_HOOK_PATH_YUM, dir_name)


def get_universal_hook_alt_php_path() -> Path:
    """
    Get path to yum universal hooks directory
    with alt-php* hooks.
    """
    return _universal_hook_path(ALT_HOOK_DIRNAME)


def _uninstall_legacy_universal_hooks_alt_php() -> None:
    """
    Remove the alt-php hook from the directories used by previous versions
    (and the directory itself when we emptied it), so the utility is not
    run twice per transaction after the hook directory was renamed.
    """
    for legacy_dir_name in LEGACY_ALT_HOOK_DIRNAMES:
        legacy_path_provider = partial(_universal_hook_path, legacy_dir_name)
        _uninstall_universal_hook(legacy_path_provider, ALT_PHP_REDIS_ENABLE_UTILITY)
        legacy_dir = legacy_path_provider()
        try:
            if legacy_dir.is_dir() and not any(legacy_dir.iterdir()):
                legacy_dir.rmdir()
        except OSError:
            pass


def install_yum_universal_hook_alt_php() -> None:
    """
    Install yum universal hook for configuring PHP redis
    after alt-php*-pecl-* package is installed/updated.
    """
    _uninstall_legacy_universal_hooks_alt_php()
    _install_universal_hook(get_universal_hook_alt_php_path, ALT_PHP_REDIS_ENABLE_UTILITY)


def uninstall_yum_universal_hook_alt_php() -> None:
    """
    Remove yum universal hook for configuring PHP redis ext.
    """
    _uninstall_legacy_universal_hooks_alt_php()
    _uninstall_universal_hook(get_universal_hook_alt_php_path, ALT_PHP_REDIS_ENABLE_UTILITY)


def get_universal_hook_ea_php_path() -> Path:
    """
    Get path to yum universal hooks directory
    with ea-php* hooks.
    """
    return _universal_hook_path(EA_HOOK_DIRNAME)


def install_yum_universal_hook_ea_php() -> None:
    """
    Install yum universal hook for configuring PHP redis
    after ea-php* package is installed/updated.
    """
    _install_universal_hook(get_universal_hook_ea_php_path, PHP_REDIS_ENABLE_UTILITY)


def uninstall_yum_universal_hook_ea_php() -> None:
    """
    Remove yum universal hook for configuring PHP redis ext.
    """
    _uninstall_universal_hook(get_universal_hook_ea_php_path, PHP_REDIS_ENABLE_UTILITY)


def get_universal_hook_plesk_php_path() -> Path:
    """
    Get path to yum universal hooks directory
    with plesk-php* hooks.
    """
    return _universal_hook_path(PLESK_HOOK_DIRNAME)


def install_yum_universal_hook_plesk_php() -> None:
    """
    Install yum universal hook for configuring PHP redis
    after plesk-php* package is installed/updated.
    """
    _install_universal_hook(get_universal_hook_plesk_php_path, PHP_REDIS_ENABLE_UTILITY)


def uninstall_yum_universal_hook_plesk_php() -> None:
    """
    Remove yum universal hook for configuring PHP redis ext.
    """
    _uninstall_universal_hook(get_universal_hook_plesk_php_path, PHP_REDIS_ENABLE_UTILITY)


def install_single_hook(hook) -> None:
    """
    Install single hook
    """
    lve_utils_hooks_dir = Path(get_python_lib(), 'clwpos', 'hooks')
    listeners_hook_path = Path(HOOKS_LISTENERS_DIR, hook)
    lve_utils_hook_path = Path(lve_utils_hooks_dir, hook)
    # remove old hook pointing to symlink to lve_utils
    if 'lve_utils' in str(listeners_hook_path.resolve()) or 'python3.7' in str(listeners_hook_path.resolve()):
        listeners_hook_path.unlink()
    if not listeners_hook_path.exists() and lve_utils_hook_path.exists():
        listeners_hook_path.symlink_to(lve_utils_hook_path)


def uninstall_single_hook(hook):
    """
    Uninstall single hook
    """
    listeners_hook_path = Path(HOOKS_LISTENERS_DIR, hook)
    if listeners_hook_path.is_symlink():
        listeners_hook_path.unlink()


def install_default_panel_hooks() -> None:
    """
    Install wpos_user_dirs_hook.py hook
    """
    for hook in DEFAULT_WPOS_HOOKS:
        install_single_hook(hook)


def uninstall_default_panel_hooks() -> None:
    """
    Uninstall wpos_user_dirs_hook.py hook
    """
    for hook in DEFAULT_WPOS_HOOKS:
        uninstall_single_hook(hook)


def install_dynamic_panel_hooks() -> None:
    """
    Install panel WPOS hooks.
    """
    subprocess.run([INSTALL_CACHING_HOOKS_UTILITY, '-i'], check=False, capture_output=True)
    for hook in DYNAMIC_WPOS_HOOKS:
        install_single_hook(hook)


def uninstall_dynamic_panel_hooks() -> None:
    """
    Remove panel WPOS hooks.
    """
    subprocess.run([INSTALL_CACHING_HOOKS_UTILITY, '-d'], check=False, capture_output=True)

    for hook in DYNAMIC_WPOS_HOOKS:
        uninstall_single_hook(hook)


def _install_hooks():
    """
    Install all hooks
    """
    install_default_panel_hooks()

    if is_wpos_supported() and any_suite_allowed_on_server():
        if is_module_allowed_for_user(OBJECT_CACHE_FEATURE):
            install_yum_universal_hook_alt_php()
            install_yum_universal_hook_ea_php()
            install_yum_universal_hook_plesk_php()
        install_dynamic_panel_hooks()


def _uninstall_hooks():
    """
    Uninstall all hooks
    """
    uninstall_yum_universal_hook_alt_php()
    uninstall_yum_universal_hook_ea_php()
    uninstall_yum_universal_hook_plesk_php()
    uninstall_dynamic_panel_hooks()
    uninstall_default_panel_hooks()


def main():
    """
    Install or uninstall panel and yum/dnf universal hooks.
    """
    if '--install' in sys.argv:
        _install_hooks()
    elif '--uninstall' in sys.argv:
        _uninstall_hooks()


if __name__ == "__main__":
    main()