JFIF$        dd7 

Viewing File: /opt/cloudlinux/venv/lib/python3.11/site-packages/xray/reconfiguration/global_ini.py

# -*- coding: utf-8 -*-

# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT
import logging
import os
import re
import pwd
from contextlib import suppress
from glob import iglob
from typing import Tuple
from secureio import disable_quota

from xray.internal.utils import user_context

logger = logging.getLogger()

GLOBAL_INI_MARKER = '/opt/cloudlinux/flags/enabled-flags.d/xray-ini-global-mode.flag'

# directories that don't matter for us
# php is either outdated or just internal
_EXCLUDE_DIR_PATHS = (
    'php44', 'php51', 'php52', 'php53',
    'php\d+-imunify', 'php-internal'
)

# global set of ini locations where php
# usually loads configuration files from
# some of them may be missing, like /opt/plesk
# which only exists on plesk
_INI_LOCATIONS = (
    '/opt/alt/php[0-9][0-9]/link/conf',
    '/opt/cpanel/ea-php[0-9][0-9]/root/etc/php.d',
    '/opt/plesk/php/[0-9].[0-9]/etc/php.d',
    '/usr/local/php[0-9][0-9]/lib/php.conf.d',
    '/usr/share/cagefs/.cpanel.multiphp/opt/cpanel/ea-php[0-9][0-9]/root/etc/php.d',
    '/usr/share/cagefs-skeleton/usr/local/php[0-9][0-9]/lib/php.conf.d'
)

# same as above, but ini which are writeable by users
_INI_USER_LOCATIONS = (
    dict(path='/var/cagefs/*/*/etc/cl.php.d/alt-php[0-9][0-9]',
         user=lambda path: pwd.getpwnam(path.split('/')[4])),
)


def _is_excluded_path(dir_path: str) -> list:
    """
    Check if given path is in exclude list.
    """
    res = [substring for substring in _EXCLUDE_DIR_PATHS
           if re.search(substring, dir_path)]
    return res


def _iter_existing_ini_locations() -> Tuple[Tuple[int, int], str]:
    """
    Generator of existing paths (matching known wildcard locations)
    for additional ini files
    Returns tuple of (uid, gid) and path.
    """
    for location in _INI_LOCATIONS:
        for dir_path in iglob(location):
            if _is_excluded_path(dir_path):
                continue
            yield (0, 0), dir_path

    for location in _INI_USER_LOCATIONS:
        for dir_path in iglob(location['path']):
            if _is_excluded_path(dir_path):
                continue

            try:
                pw_record = location['user'](dir_path)
            except:
                logger.info('Unable to get information about user '
                            'owning %s directory (maybe he`s already terminated?), '
                            'skip updating', dir_path)
                continue
            else:
                yield (pw_record.pw_uid, pw_record.pw_gid), dir_path


def _create_single_ini(uid: int, gid: int, ini_path: str):
    # write counter of tasks so during mode switch
    # we can still safely cleanup ini files not
    # bound to any exiting tasks
    ini_content = ';xray.tasks=0\nextension=xray.so'

    path = os.path.join(ini_path, 'xray.ini')
    if os.path.exists(path):
        return

    with user_context(uid, gid), \
            disable_quota(), \
            open(path, 'w') as ini:
        logger.info('Generating %s file...', path)
        ini.write(ini_content)


def is_global_ini_mode():
    return os.path.exists(GLOBAL_INI_MARKER)


def create_global_ini_mode_marker():
    open(GLOBAL_INI_MARKER, 'w').close()


def remove_global_ini_mode_marker():
    with suppress(FileNotFoundError):
        os.remove(GLOBAL_INI_MARKER)


def create_ini_files() -> None:
    """
    Place xray.ini into each existing Additional ini path,
    including cagefs ones.
    """
    logger.info('Generating xray.ini files...')
    for (uid, gid), ini_path in _iter_existing_ini_locations():
        try:
            _create_single_ini(uid, gid, ini_path)
        except PermissionError:
            logger.warning('Unable to update file %s, '
                           'possible permission misconfiguration', ini_path)
            continue
        except Exception as e:
            logger.warning('Unexpected error happened during file processing: '
                           '"%s", error: "%s"', ini_path, str(e), exc_info=True)
            continue
    logger.info('Finished!')


def remove_ini_files() -> None:
    """
    Remove all gathered clos_ssa.ini files
    """
    logger.info('Removing clos_ssa.ini files...')
    for (uid, gid), clos_ini_dir in _iter_existing_ini_locations():
        ini_file = os.path.join(clos_ini_dir, 'xray.ini')
        try:
            with user_context(uid, gid), open(ini_file) as f:
                contents = f.read()

                # unlink file only if there are no linked tasks
                # case with minus sign covers negative values
                if "xray.tasks=0" in contents or \
                        "xray.tasks=-" in contents:
                    os.unlink(ini_file)
        except FileNotFoundError:
            continue
        except Exception as e:
            logger.warning('Unable to remove file: "%s", error: "%s"', ini_file, str(e))
            continue

    logger.info('Finished!')
Back to Directory  nL+D550H?Mx ,D"v]qv;6*Zqn)ZP0!1 A "#a$2Qr D8 a Ri[f\mIykIw0cuFcRı?lO7к_f˓[C$殷WF<_W ԣsKcëIzyQy/_LKℂ;C",pFA:/]=H  ~,ls/9ć:[=/#f;)x{ٛEQ )~ =𘙲r*2~ a _V=' kumFD}KYYC)({ *g&f`툪ry`=^cJ.I](*`wq1dđ#̩͑0;H]u搂@:~וKL Nsh}OIR*8:2 !lDJVo(3=M(zȰ+i*NAr6KnSl)!JJӁ* %݉?|D}d5:eP0R;{$X'xF@.ÊB {,WJuQɲRI;9QE琯62fT.DUJ;*cP A\ILNj!J۱+O\͔]ޒS߼Jȧc%ANolՎprULZԛerE2=XDXgVQeӓk yP7U*omQIs,K`)6\G3t?pgjrmۛجwluGtfh9uyP0D;Uڽ"OXlif$)&|ML0Zrm1[HXPlPR0'G=i2N+0e2]]9VTPO׮7h(F*癈'=QVZDF,d߬~TX G[`le69CR(!S2!P <0x<!1AQ "Raq02Br#SCTb ?Ζ"]mH5WR7k.ۛ!}Q~+yԏz|@T20S~Kek *zFf^2X*(@8r?CIuI|֓>^ExLgNUY+{.RѪ τV׸YTD I62'8Y27'\TP.6d&˦@Vqi|8-OΕ]ʔ U=TL8=;6c| !qfF3aů&~$l}'NWUs$Uk^SV:U# 6w++s&r+nڐ{@29 gL u"TÙM=6(^"7r}=6YݾlCuhquympǦ GjhsǜNlɻ}o7#S6aw4!OSrD57%|?x>L |/nD6?/8w#[)L7+6〼T ATg!%5MmZ/c-{1_Je"|^$'O&ޱմTrb$w)R$& N1EtdU3Uȉ1pM"N*(DNyd96.(jQ)X 5cQɎMyW?Q*!R>6=7)Xj5`J]e8%t!+'!1Q5 !1 AQaqё#2"0BRb?Gt^## .llQT $v,,m㵜5ubV =sY+@d{N! dnO<.-B;_wJt6;QJd.Qc%p{ 1,sNDdFHI0ГoXшe黅XۢF:)[FGXƹ/w_cMeD,ʡcc.WDtA$j@:) -# u c1<@ۗ9F)KJ-hpP]_x[qBlbpʖw q"LFGdƶ*s+ډ_Zc"?%t[IP 6J]#=ɺVvvCGsGh1 >)6|ey?Lӣm,4GWUi`]uJVoVDG< SB6ϏQ@ TiUlyOU0kfV~~}SZ@*WUUi##; s/[=!7}"WN]'(L! ~y5g9T̅JkbM' +s:S +B)v@Mj e Cf jE 0Y\QnzG1д~Wo{T9?`Rmyhsy3!HAD]mc1~2LSu7xT;j$`}4->L#vzŏILS ֭T{rjGKC;bpU=-`BsK.SFw4Mq]ZdHS0)tLg