X7ROOT File Manager
Current Path:
/opt/cloudlinux/venv/lib/python3.11/site-packages/clselect
opt
/
cloudlinux
/
venv
/
lib
/
python3.11
/
site-packages
/
clselect
/
??
..
??
__init__.py
(536 B)
??
__pycache__
??
baseclselect
??
clextselect.py
(19.71 KB)
??
clpassenger.py
(26.53 KB)
??
clselect.py
(21.77 KB)
??
clselectctl.py
(9.15 KB)
??
clselectctlnodejsuser.py
(20.66 KB)
??
clselectctlphp.py
(43.82 KB)
??
clselectctlpython.py
(44.75 KB)
??
clselectctlruby.py
(18.59 KB)
??
clselectexcept.py
(10.22 KB)
??
clselectnodejs
??
clselectnodejsuser
??
clselectphp
??
clselectphpuser
??
clselectprint.py
(5.39 KB)
??
clselectpython
??
clselectpythonuser
??
clselectruby
??
clselectstatistics.py
(6.51 KB)
??
cluserextselect.py
(15.19 KB)
??
cluseroptselect.py
(23.65 KB)
??
cluserselect.py
(28.22 KB)
??
locked_extensions.ini
(1.2 KB)
??
utils.py
(16.22 KB)
Editing: clextselect.py
# -*- 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 absolute_import from __future__ import print_function from __future__ import division import collections import configparser import os import operator from clcommon import clcagefs from .clselect import ClSelect from .clselectexcept import ClSelectExcept from .clselectprint import clprint from . import utils # dependencies modulse dict. Example { 'ext_name': 'ext1' } - ext1 depends from ext_name depend_modules_dict = dict() class ClExtSelect(ClSelect): CONFLICTS_PATH = ( '/etc/cl.selector.conf.d/php.extensions.conflicts' if clcagefs.in_cagefs() else '/etc/cl.selector/php.extensions.conflicts' ) SYSTEM_ALT_PATH = '/opt/alt' def __init__(self, item='php'): ClSelect.__init__(self, item) self._conflicts = [] # Sets in _get_enabled_extensions method # True - extension list was read from native php built-ins # False - extension list was read from /etc/cl.selector/defaults.cfg self._use_default_exts_from_native_php = False def _is_disabled_extention(self, ext_name): return ext_name in self._hidden_extensions def enable_extensions(self, version, ext_list): """ Adds extensions to default list of extensions for a version """ alternatives = self.get_all_alternatives_data() self._check_alternative(version, alternatives) defaults_contents = self._process_ini_file( self.DEFAULTS_PATH, (self._item, version), self._add_extensions, ext_list, action = 'enable_extentions') self._write_to_file( '\n'.join(defaults_contents), ClExtSelect.DEFAULTS_PATH) def replace_extensions(self, version, ext_list): """ Replaces extensions to default list of extensions for a version. Writes/updates /etc/cl.selector/defaults.cfg file :param version: alt-php version to process :param ext_list: list extensions to set as defaults for the version """ alternatives = self.get_all_alternatives_data() self._check_alternative(version, alternatives) defaults_contents = self._process_ini_file( self.DEFAULTS_PATH, (self._item, version), self._replace_extensions, ext_list) self._write_to_file( '\n'.join(defaults_contents), self.DEFAULTS_PATH) def disable_extensions(self, version, ext_list): """ Removes extensions from default list of extensions for a version :param version: alt-php version to process :param ext_list: comma separated extensions list to delete """ alternatives = self.get_all_alternatives_data() self._check_alternative(version, alternatives) defaults_contents = self._process_ini_file( self.DEFAULTS_PATH, (self._item, version), self._del_extensions, ext_list, action = 'disable_extentions') self._write_to_file('\n'.join(defaults_contents), self.DEFAULTS_PATH) def list_extensions(self, version): """ Returns list of extensions marking built-ins and enabled ones Also replaces mysqli->nd_mysqli in defaults.cfg for new installations according to LVEMAN-1399 :param version: php version :return Tuple: (extension_name, extension_state) extension_state: None -- built-in extension False/True -- disabled/enabled extension """ ext_mysqli_name = 'mysqli' ext_nd_mysqli_name = 'nd_mysqli' ext_list_to_write = list() is_need_to_write_defaults = False alternatives = self.get_all_alternatives_data() self._check_alternative(version, alternatives) # Get extensions list from /etc/cl.selector/defaults.cfg for supplied verson or # list of built-in extesions for native if version does not present in defaults.cfg enabled_extensions = self._get_enabled_extensions(version) # Get extension list for version as_built_in = self._get_builtins(version) try: # Get extensions list for version - list of files # /opt/alt/phpXX/etc/php.d.all/*.ini without .ini extension # Without dependencies analysis as_extensions = self._load_extensions_list(version) except ClSelectExcept.UnableToGetExtensions: as_extensions = [] # ['bz2', 'calendar'] -> ('bz2', None), ('calendar', None) all_extensions = list(map((lambda i: (i, None)), as_built_in)) for ext in as_extensions: status = False if (ext in enabled_extensions) and (ext not in as_built_in): status = True ext_set = set([(ext, True), (ext, False), (ext, None)]) if not set(all_extensions).intersection(ext_set): # add ext and its status to result list # LVEMAN-1399: # If defaults modules was taken from native php built-ins # replace mysqli to nd_mysqli (if it exist) and set status True to it if ext == ext_mysqli_name and self._use_default_exts_from_native_php\ and ext_nd_mysqli_name in as_extensions: all_extensions.append((ext_mysqli_name, False)) all_extensions.append((ext_nd_mysqli_name, True)) # After module replacement we need to write new list as defaults is_need_to_write_defaults = True # add nd_mysqli to list for write ext_list_to_write.append(ext_nd_mysqli_name) else: all_extensions.append((ext, status)) if status: # if module enabled, add it to list for write ext_list_to_write.append(ext) # all_extensions example: [('bz2', None), ('calendar', None), (u'zip', True), (u'zmq', False)] # If module replacement occures, write list to defaults.cfg if is_need_to_write_defaults: self.replace_extensions(version, ext_list_to_write) return tuple(sorted(all_extensions, key=operator.itemgetter(0))) def _get_enabled_extensions(self, version): """ Returns list of enabled extensions for a version """ try: # reads extensions list from /etc/cl.selector/defaults.cfg data = self._dh.get( "%s%s" % (self._item, version), 'modules') self._use_default_exts_from_native_php = False return list(map((lambda i: i.strip()), data.split(','))) except (configparser.NoSectionError, configparser.NoOptionError): self._use_default_exts_from_native_php = True return self._get_builtins('native') def _add_extensions(self, section_info, section, data, trace=True): """ Adds 'modules' option to section or extends it @param section_info: tuple (item and version) @param section: list @param data: list @return: list """ section_header = self._make_section_header(section_info) if len(section) == 0 or section_header != section[0]: return section midx = None modules = [] alt_path = self._compose_alt_path(section_info[1]) for idx in range(len(section)): if section[idx].startswith('modules'): midx = idx break if midx: modules_string = section[midx][section[midx].find('=')+1:].strip() modules.extend( list(map((lambda i: i.strip()), modules_string.split(',')))) modules.extend(data) modules = self._check_for_conflicts(modules) resolved_modules = self._include_dependencies(modules, alt_path) modules_string = 'modules = %s' % (','.join(sorted(resolved_modules))) if midx: section[midx] = modules_string else: section.append(modules_string) return self._smooth_data(section) def _replace_extensions(self, section_info, section, data, trace=True): """ Adds 'modules' option to section or extends it @param section_info: tuple (item and version). Example: ('php', '5.2') @param section: list. Modules from /etc/cl.selecto/defaults.cfg for supplied php version Example: ['[php5.2]', 'modules = bcmath,dom,gd,imap,json,mcrypt,mysql,mysqli,phar,posix,sockets,uuid,wddx,xmlreader,zip', '', ''] @param data: list: Modules list to set from command line @:param trace: ????, Currently not using, always True @return: list """ global depend_modules_dict section_header = self._make_section_header(section_info) if len(section) == 0 or section_header != section[0]: return section midx = None alt_path = self._compose_alt_path(section_info[1]) for idx in range(len(section)): if section[idx].startswith('modules'): midx = idx break modules = data[:] if trace: resolved_modules = set() modules = self._check_for_conflicts(modules) for mod in modules: include_dep = self._include_dependencies([mod], alt_path) if len(include_dep) != 1: # Dependencies found, add them to depend_modules_dict # Add deps to dict depend_modules_dict.update({dep_module: mod for dep_module in include_dep if dep_module != mod}) resolved_modules.update(include_dep) modules_string = 'modules = %s' % (','.join(sorted(resolved_modules))) else: modules_string = 'modules = %s' % (','.join(sorted(data))) if midx: section[midx] = modules_string else: section.append(modules_string) # Cleanup dependency list - remove from dependencies all modules, present in command line modules = depend_modules_dict.copy() for dep_module in modules.keys(): if dep_module in data: del depend_modules_dict[dep_module] return self._smooth_data(section) def _del_extensions(self, section_info, section, data, trace=True): """ Deletes items in data list from section list @param section_info: tuple (item and version) @param section: list @param data: list of extension names to delete @return: list """ section_header = self._make_section_header(section_info) if len(section) == 0 or section_header != section[0]: return section midx = None alt_path = self._compose_alt_path(section_info[1]) for idx in range(len(section)): if section[idx].startswith('modules'): midx = idx break if not midx: return section modules_string = section[midx][section[midx].find('=')+1:].strip() modules = set(map((lambda i: i.strip()), modules_string.split(','))) resolved_modules = modules.copy() for item in set(data): if item not in modules: continue rest_of_modules = modules.difference([item]) if self._is_dependency(item, rest_of_modules, alt_path): continue resolved_modules.discard(item) resolved_modules = self._include_dependencies(resolved_modules, alt_path) modules_string = 'modules = %s' % (','.join(sorted(resolved_modules))) section[midx] = modules_string return self._smooth_data(section) def _is_dependency(cls, ext, modules, alt_path): """ Checks if module in modules dependent on ext and returns true or false @param ext: Module to check @param modules: set of names of installed modules @param alt_path: Path to alt-php ini dir: /opt/alt/phpXX/etc/php.d.all @return: bool. True if ext present in dependencies of any module in modules list """ global depend_modules_dict for mod in modules: dependencies = cls._get_dependencies(mod, alt_path) if ext in dependencies: depend_modules_dict[ext] = mod return True return False _is_dependency = classmethod(_is_dependency) def _compose_alt_path(self, version): """ Composes and returns path for alternatives """ return os.path.join( self.SYSTEM_ALT_PATH, "%s%s" % (self._item, version.replace('.', '')), "etc", "%s.d.all" % (self._item,)) def _include_dependencies(cls, ext_list, alt_path, data=None): """ Includes dependencies into extensions list and update data dict if present @param ext_list: list @param alt_path: string @param data: dict @return: list """ in_section = False result_ext_list = [] handled = set() q = collections.deque(ext_list) while q: ext = q.popleft() if ext in handled: continue handled.add(ext) ext_path = os.path.join(alt_path, f'{ext}.ini') try: f = open(ext_path) file_contents = [] pending_contents = [] for line in f: if line.startswith('extension') or line.startswith('zend_extension'): ext_name = cls._single_out_extension(ext, line) if ext_name != ext and ext_name not in handled: q.appendleft(ext_name) continue file_contents.append(f';---{ext}---') in_section = True file_contents.extend(pending_contents) pending_contents = [] if not (line.startswith(';') or line.startswith('\n')): if in_section: file_contents.append(line.rstrip()) else: pending_contents.append(line.rstrip()) f.close() if data is not None and ext not in data: data[ext] = file_contents # Adding to the beggining of the result list due to LVEMAN-504 result_ext_list.insert(0, ext) except (OSError, IOError): continue return result_ext_list _include_dependencies = classmethod(_include_dependencies) def _get_dependencies(cls, ext, alt_path): """ Checks if an extension has dependencies and if so returns them Otherwise returns None @param ext: string @return: set """ dependencies = set() ext_path = os.path.join(alt_path, "%s.ini" % (ext,)) try: f = open(ext_path) for line in f: if line.startswith('extension'): ext_name = cls._single_out_extension(ext, line) if ext_name != ext: dependencies.add(ext_name) return dependencies except (OSError, IOError): return dependencies _get_dependencies = classmethod(_get_dependencies) def _single_out_extension(ext, line): """ Singles out and returns extension from line """ quirks = {'ixed': 'sourceguardian'} if '/' in line: ext_name = line[line.rfind('/')+1:].strip() else: ext_name = line[line.find('=')+1:].strip(' "') if '.' in ext_name: ext_name = ext_name[:ext_name.find('.')] if '-' in ext_name: ext_name = ext_name[:ext_name.rfind('-')] if ext_name in quirks: ext_name = quirks[ext_name] elif ext in ext_name: ext_name = ext elif ('_' in ext and ''.join(map((lambda i: i.capitalize()), ext.split('_'))) == ext_name): ext_name = ext return ext_name _single_out_extension = staticmethod(_single_out_extension) def _check_for_conflicts(self, ext_list): """ Removes from extensions list conflicting ones """ if not self._conflicts: self._load_conflicting_extensions() clean_set = set() for ext in ext_list: if self._is_not_conflicting(ext, clean_set) and \ not self._is_disabled_extention(ext): clean_set.add(ext) #else: #clprint.print_diag( # 'text', # {'status': 'WARN', # 'message': '%s skipped as conflicting (%s)' % (ext, str(clean_set))}) return clean_set def _is_not_conflicting(self, ext, clean_set): """ Checks extension against conflicting sets """ for conflict in self._conflicts: if ext in conflict: if len(clean_set.copy().intersection(conflict)) != 0: return False return True def _load_conflicting_extensions(self): """ Loads conflicting extensions from file and saves'em as list of sets """ conflicts = utils.read_file_as_string(self.CONFLICTS_PATH) for line in conflicts.splitlines(): if ',' not in line: continue conflict_set = set(map((lambda i: i.strip()), line.split(','))) if len(conflict_set) < 2: continue self._conflicts.append(conflict_set) def _load_extensions_list(self, version): """ Loads alternative extensions list for a version @param version: string """ alt_path = self._compose_alt_path(version) try: alt_extensions = [] for filename in os.listdir(alt_path): if not filename.endswith('.ini'): continue extension = filename[:filename.find('.ini')] if extension in self._hidden_extensions: continue alt_extensions.append(extension) return sorted(alt_extensions) except OSError: raise ClSelectExcept.UnableToGetExtensions(version) @staticmethod def _print_dependencies_info(dependens_info): """ Prints info @param ext: string @param data: list """ for (i, ext) in dependens_info: clprint.print_diag( 'text', {'status': 'WARN', 'message': '%s enabled as dependency (%s)' % (i, ext)}) @staticmethod def get_dependencies_list(ext, data, ext_list): """ Get array of dependenses [(ext, depending ext)] @param ext: string @param data: list """ if not data: return [] diff = set(data).difference([ext]) return [(i, ext) for i in diff if i not in ext_list] @staticmethod def get_conflicts_info(init_list, processed_set): return list(set(init_list).difference(processed_set)) @staticmethod def _print_conflicts_info(diff): """ Prepares data for printing conflicts if any @param init_list: list @param processed_set: set """ if diff: for i in diff: clprint.print_diag( 'text', {'status': 'WARN', 'message': '%s skipped as conflicting' % (i,)})
Upload File
Create Folder