????
Current Path : /usr/local/ssl/share/cagefs/ |
Current File : //usr/local/ssl/share/cagefs/phpinivalidator.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 """ Module to validate the configuration file alt_phpXX.cfg """ from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals from future import standard_library standard_library.install_aliases() from builtins import * import re import os ALTPHPVER_PATTERN = re.compile(r'alt_php(\d)(\d)\.cfg') def get_php_ver(input_phpini_path): """ function to get the version of the php file name alt_phpXX.cfg for example: 'alt_php55.cfg' => '5.5' """ php_ver_searched = ALTPHPVER_PATTERN.search(os.path.basename(input_phpini_path)) if php_ver_searched: return '.'.join(php_ver_searched.group(1, 2)) class PHPINIvalidator(object): DIRECTIVE_PATTERN = re.compile(r'(^Directive|Type|Range|Remark)\s*=\s*(.*\S)\s*$') CUSTOM_OPTIONS_DIRECTIVE_PATTERN = re.compile(r'^([a-zA-Z0-9_.]+)\s*=\s*([^;="]+[^;=" \t]|".+"|[^;="])\s*(;.*)?$') BOOLEAN_VARIANTS = ('On', 'Off', '0', '1', 'True', 'False') def __init__(self, phpconf_path='/etc/cl.selector/php.conf'): self.phpconf_path = phpconf_path self._phpconf_data = self._load_phpconf(self.phpconf_path) # List with unknown options: self.unknown_options = [] # List options: self.invalid_values_options = [] # List of invalid options (for example, options without values) self.invalid_options = [] def _load_phpconf(self, phpconf_path): """ Load reference data. Gets a dictionary of the form; example: {'upload_max_filesize': {'Default':'2M', 'Type':'list', 'Range'; '2M,4M,8M,16M,32M,64M,128M,256M,512M,1G'} """ phpconf_dict = {} directive_title = None phpconf = open(phpconf_path) for phpconf_line in phpconf: if phpconf_line.startswith('#'): continue searched = self.DIRECTIVE_PATTERN.search(phpconf_line.rstrip()) if not searched: continue directive_name, directive_val = searched.group(1, 2) if directive_name == 'Directive': directive_title = directive_val phpconf_dict[directive_title] = dict() else: phpconf_dict[directive_title][directive_name] = directive_val phpconf.close() return phpconf_dict # Use only full php_ver (e.g 5.4.11 instead of 5.4) def validate(self, input_phpini_lines, php_ver): output_phpini_lines = [] # Clear lists of bad options self.unknown_options = [] self.invalid_values_options = [] self.invalid_options = [] for input_phpini_line in input_phpini_lines: output_phpini_line = input_phpini_line if input_phpini_line.startswith(';'): output_phpini_lines.append(output_phpini_line) continue try: input_phpini_line1 = input_phpini_line.strip() if input_phpini_line1.endswith('='): input_phpini_line1 += '0' directive_name, directive_val = self.CUSTOM_OPTIONS_DIRECTIVE_PATTERN.search(input_phpini_line1).group(1, 2) is_valid_directive, is_valid_value = self._validate_directive_val(directive_name=directive_name, directive_val=directive_val, php_ver=php_ver) if not is_valid_directive: self.unknown_options.append(input_phpini_line.strip()) else: # Directive is valid, check value if not is_valid_value: self.invalid_values_options.append(input_phpini_line.strip()) except AttributeError: is_valid_directive = False is_valid_value = False self.invalid_options.append(input_phpini_line.strip()) if not (is_valid_directive and is_valid_value): output_phpini_line = ';' + input_phpini_line output_phpini_lines.append(output_phpini_line) return output_phpini_lines def _validate_directive_val(self, directive_name, directive_val, php_ver): """ Validates directive for supplied PHP version :param directive_name: Directive name :param directive_val: Directive name :param php_ver: PHP version (3 digits) to check directive :return: Tuple (is_valid_directive, is_valid_value) - boolean flags validity of directive and value """ directive_data_dict = self._phpconf_data.get(directive_name) if not directive_data_dict: return False, False directive_data_type = directive_data_dict['Type'] remark = directive_data_dict.get('Remark') if remark: # Remark present if remark.startswith('>') or remark.startswith('<'): remark_znak = remark[0] remark_ver = remark[1:] if remark_znak == '<': if php_ver.split('.') > remark_ver.split('.'): # version mismatch return False, False elif remark_znak == '>': # return php_ver.split('.') > remark_ver.split('.'), False if php_ver.split('.') < remark_ver.split('.'): # version mismatch return False, False else: # Remark: = xx.yy.zzz or Remark: = xx.yy # Form 2-digit versions from remark and checking alt-php version remark_ver_parts = remark.split('.') remark_ver_2digit = '%s.%s' % (remark_ver_parts[0], remark_ver_parts[1]) php_ver_parts = php_ver.split('.') php_ver_2digit = '%s.%s' % (php_ver_parts[0], php_ver_parts[1]) if remark_ver_2digit != php_ver_2digit: # Invalid directive for supplied PHP version return False, False if directive_name not in self._phpconf_data: # No such directive return False, False if directive_data_type == 'bool': if directive_val not in self.BOOLEAN_VARIANTS: # directive value is boolean (by php.conf), but directive_val not boolean return True, False elif directive_data_type == 'list': if directive_val not in directive_data_dict['Range'].split(','): # directive value is not from php.conf list return True, False return True, True