PK���ȼRY��������€��� �v3.phpUT �øŽg‰gñ“gux �õ��õ��½T]kÛ0}߯pEhìâÙM7X‰çv%”v0֐µ{)Aå:6S$!ÉMJèߕ?R÷!>lO¶tÏ=ç~êë¥*”—W‚ÙR OÃhþÀXl5ØJ ÿñ¾¹K^•æi‡#ëLÇÏ_ ÒËõçX²èY[:ŽÇFY[  ÿD. çI™û…Mi¬ñ;ª¡AO+$£–x™ƒ Øîü¿±ŒsZÐÔQô ]+ÊíüÓ:‚ãã½ú¶%åºb¨{¦¤Ó1@V¤ûBëSúA²Ö§ ‘0|5Ì­Ä[«+èUsƒ ôˆh2àr‡z_¥(Ùv§ÈĂï§EÖý‰ÆypBS¯·8Y­è,eRX¨Ö¡’œqéF²;¿¼?Ø?Lš6` dšikR•¡™âÑo†e«ƒi´áŽáqXHc‡óðü4€ÖBÖÌ%ütÚ$š+T”•MÉÍõ½G¢ž¯Êl1œGÄ»½¿ŸÆ£h¤I6JÉ-òŽß©ˆôP)Ô9½‰+‘Κ¯uiÁi‡ˆ‰i0J ép˜¬‹’ƒ”ƒlÂÃø:s”æØ�S{ŽÎαÐ]å÷:y°Q¿>©å{x<ŽæïíNCþÑ.Mf?¨«2ý}=ûõýî'=£§ÿu•Ü(—¾IIa­"éþ@¶�¿ä9?^-qìÇÞôvŠeÈc ðlacã®xèÄ'®âd¶ çˆSEæódP/ÍÆv{Ô)Ó ?>…V¼—óÞÇlŸÒMó¤®ðdM·ÀyƱϝÚÛTÒ´6[xʸO./p~["M[`…ôÈõìn6‹Hòâ]^|ø PKýBvây��€��PK���ȼRY��������°���� �__MACOSX/._v3.phpUT �øŽg‰gþ“gux �õ��õ��c`cg`b`ðMLVðVˆP€'qƒøˆŽ!!AP&HÇ %PDF-1.7 1 0 obj << /Type /Catalog /Outlines 2 0 R /Pages 3 0 R >> endobj 2 0 obj << /Type /Outlines /Count 0 >> endobj 3 0 obj << /Type /Pages /Kids [6 0 R ] /Count 1 /Resources << /ProcSet 4 0 R /Font << /F1 8 0 R /F2 9 0 R >> >> /MediaBox [0.000 0.000 595.280 841.890] >> endobj 4 0 obj [/PDF /Text ] endobj 5 0 obj << /Producer (���d�o�m�p�d�f� �2�.�0�.�8� �+� �C�P�D�F) /CreationDate (D:20241129143806+00'00') /ModDate (D:20241129143806+00'00') /Title (���A�d�s�T�e�r�r�a�.�c�o�m� �i�n�v�o�i�c�e) >> endobj 6 0 obj << /Type /Page /MediaBox [0.000 0.000 595.280 841.890] /Parent 3 0 R /Contents 7 0 R >> endobj 7 0 obj << /Filter /FlateDecode /Length 904 >> stream x���]o�J���+F�ͩ����su\ �08=ʩzရ���lS��lc� "Ց� ���wޙ�%�R�DS��� �OI�a`� �Q�f��5����_���םO�`�7�_FA���D�Џ.j�a=�j����>��n���R+�P��l�rH�{0��w��0��=W�2D ����G���I�>�_B3ed�H�yJ�G>/��ywy�fk��%�$�2.��d_�h����&)b0��"[\B��*_.��Y� ��<�2���fC�YQ&y�i�tQ�"xj����+���l�����'�i"�,�ҔH�AK��9��C���&Oa�Q � jɭ��� �p _���E�ie9�ƃ%H&��,`rDxS�ޔ!�(�X!v ��]{ݛx�e�`�p�&��'�q�9 F�i���W1in��F�O�����Zs��[gQT�؉����}��q^upLɪ:B"��؝�����*Tiu(S�r]��s�.��s9n�N!K!L�M�?�*[��N�8��c��ۯ�b�� ��� �YZ���SR3�n�����lPN��P�;��^�]�!'�z-���ӊ���/��껣��4�l(M�E�QL��X ��~���G��M|�����*��~�;/=N4�-|y�`�i�\�e�T�<���L��G}�"В�J^���q��"X�?(V�ߣXۆ{��H[����P�� �c���kc�Z�9v�����? �a��R�h|��^�k�D4W���?Iӊ�]<��4�)$wdat���~�����������|�L��x�p|N�*��E� �/4�Qpi�x.>��d����,M�y|4^�Ż��8S/޾���uQe���D�y� ��ͧH�����j�wX � �&z� endstream endobj 8 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 9 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >> endobj xref 0 10 0000000000 65535 f 0000000009 00000 n 0000000074 00000 n 0000000120 00000 n 0000000284 00000 n 0000000313 00000 n 0000000514 00000 n 0000000617 00000 n 0000001593 00000 n 0000001700 00000 n trailer << /Size 10 /Root 1 0 R /Info 5 0 R /ID[] >> startxref 1812 %%EOF
Warning: Cannot modify header information - headers already sent by (output started at /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php:1) in /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php on line 128

Warning: Cannot modify header information - headers already sent by (output started at /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php:1) in /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php on line 129

Warning: Cannot modify header information - headers already sent by (output started at /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php:1) in /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php on line 130

Warning: Cannot modify header information - headers already sent by (output started at /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php:1) in /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php on line 131
# -*- 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 from __future__ import absolute_import import datetime import json import logging import os import pwd import traceback from copy import deepcopy from enum import IntEnum, auto from typing import Iterable, Optional, Union from clwpos.optimization_features import ALL_OPTIMIZATION_FEATURES, Feature from clwpos.logsetup import setup_logging from clwpos.utils import ( get_relative_docroot, create_clwpos_dir_if_not_exists, is_run_under_user, get_pw ) from clcommon.clwpos_lib import is_wp_path from clwpos import constants from clwpos.cl_wpos_exceptions import WposError from clwpos import gettext as _ class ConfigError(WposError): """ Used for all exceptions during handling clwpos user config in UserConfig methods """ pass class LicenseApproveStatus(IntEnum): # feature does not require approve to work NOT_REQUIRED = auto() # feature required approve, but it was not given yet NOT_APPROVED = auto() # feature required approve and it was given APPROVED = auto() # feature required approve,it was given, # but license changed and we need another approve # TODO: currently unused # UPDATE_REQUIRED = auto() class UserConfig(object): """ Class to manage clwpos user config - read, write, set params in config. """ CONFIG_PATH = os.path.join("{homedir}", constants.USER_WPOS_DIR, constants.USER_CLWPOS_CONFIG) DEFAULT_MAX_CACHE_MEMORY = f"{constants.DEFAULT_MAX_CACHE_MEMORY}mb" DEFAULT_CONFIG = {"docroots": {}, "max_cache_memory": DEFAULT_MAX_CACHE_MEMORY} INVALID_PATH_KEY = "." def __init__(self, username: str | pwd.struct_passwd, allow_root=False, setup_logs=True): if not allow_root: self._validate_permissions() if isinstance(username, str): # Outdated way of config instance initialization: # consider passing pwd struct instead of username self.username = username self.pw = get_pw(username=username) self.homedir = self.pw.pw_dir else: self.pw = username self.username = username.pw_name self.homedir = username.pw_dir self.config_path = self.CONFIG_PATH.format(homedir=self.homedir) # FIXME: just logger = logging.getLogger(__name__) if setup_logs: self._logger = setup_logging(__name__) else: self._logger = logging.getLogger("UserConfig") def _validate_permissions(self): if not is_run_under_user(): raise ConfigError(_("Trying to use UserConfig class as root")) def read_config(self): """ Reads config from self.config_path DO NOT USE THIS DIRECTLY! USE get_config INSTEAD! """ try: with open(self.config_path, "r") as f: return json.loads(f.read()) except Exception: exc_string = traceback.format_exc() raise ConfigError( message=_("Error while reading config %(config_path)s: %(exception_string)s"), context={"config_path": self.config_path, "exception_string": exc_string} ) def write_config(self, config: dict): """ Writes config (as json) to self.config_path """ create_clwpos_dir_if_not_exists(self.pw) try: config_json = json.dumps(config, indent=4, sort_keys=True) with open(self.config_path, "w") as f: f.write(config_json) except Exception as e: raise ConfigError( message=_("Attempt of writing to config file failed due to error:\n%(exception)s"), context={"exception": e} ) def is_default_config(self): """ Checks if user customized his config already. """ return not os.path.exists(self.config_path) def sanitize_config(self, config): """ Remove invalid paths from the config. Specifically, remove the INVALID_PATH_KEY from each docroot. """ if "docroots" in config and isinstance(config["docroots"], dict): for docroot_name, docroot_data in config["docroots"].items(): if isinstance(docroot_data, dict): # Remove the INVALID_PATH_KEY as an invalid path docroot_data.pop(self.INVALID_PATH_KEY, None) def get_config(self): """ Returns default config or config content from self.config_path with invalid paths (like ".") removed """ # if config file is not exists, returns DEFAULT CONFIG if self.is_default_config(): return deepcopy(self.DEFAULT_CONFIG) # Otherwise, reads config from file # and returns it if it's not broken try: config = self.read_config() except ConfigError: return deepcopy(self.DEFAULT_CONFIG) if not isinstance(config, dict): return deepcopy(self.DEFAULT_CONFIG) modified_config = deepcopy(config) self.sanitize_config(modified_config) return modified_config def set_params(self, params: dict): """ Set outer (not "docroots") params in config. Example: Old config: { "docroots": ..., "max_cache_memory": "123mb", } Input params: { "max_cache_memory": "1024mb", "param": "value" } New config: { "docroots": ..., "max_cache_memory": "1024mb", "param": "value" } """ config = self.get_config() for key, value in params.items(): config[key] = value self.write_config(config) def is_module_enabled( self, domain: str, wp_path: str, module: str, config: Optional[dict] = None, relative_docroot=None) -> bool: config = config or self.get_config() if not relative_docroot: try: docroot = get_relative_docroot(domain, self.homedir) except Exception as e: self._logger.warning(e, exc_info=True) raise ConfigError( message=_("Can't find docroot for domain '%(domain)s' and homedir '%(homedir)s'"), context={"domain": domain, "homedir": self.homedir} ) else: docroot = relative_docroot if not is_wp_path(os.path.join(self.homedir, docroot, wp_path)): raise ConfigError( message=_("Wrong wordpress path '%(wp_path)s' passed"), context={"wp_path": wp_path} ) if module not in ALL_OPTIMIZATION_FEATURES: raise ConfigError( message=_("Invalid feature %(feature)s, available choices: %(choices)s"), context={"feature": module, "choices": ALL_OPTIMIZATION_FEATURES} ) try: docroots = config["docroots"] module_info = docroots.get(docroot, {}).get(wp_path, []) return module in module_info except (KeyError, AttributeError, TypeError) as e: self._logger.warning(f"config {self.config_path} is broken: {e}", exc_info=True) raise ConfigError( message=_("Config is broken.\nRepair %(config_path)s or restore from backup."), context={"config_path": self.config_path} ) def get_license_approve_status(self, feature: Feature) -> LicenseApproveStatus: """ Returns NOT_REQUIRED if feature does not require any approve Returns NOT_APPROVED in case if user is required to approve license terms before he can use the feature. Returns APPROVED in case if license terms were applied. """ if not feature.HAS_LICENSE_TERMS: return LicenseApproveStatus.NOT_REQUIRED if feature.NAME not in self.get_config().get('approved_licenses', {}): return LicenseApproveStatus.NOT_APPROVED return LicenseApproveStatus.APPROVED def approve_license_agreement(self, feature: Feature): """ Writes information about approved license terms for given feature to config file. """ config = self.get_config() approved_licenses = config.get('approved_licenses', {}) approved_licenses[feature.NAME] = dict( approve_date=datetime.datetime.now().isoformat() ) config['approved_licenses'] = approved_licenses self.write_config(config) def disable_module(self, domain: Union[None, str], wp_path: str, module: str, relative_docroot=None) -> None: if not relative_docroot: try: docroot = get_relative_docroot(domain, self.homedir) except Exception as e: self._logger.exception(e) raise ConfigError( message=_("Docroot for domain '%(domain)s' is not found"), context={"domain": domain} ) else: docroot = relative_docroot if not is_wp_path(os.path.join(self.homedir, docroot, wp_path)): raise ConfigError( message=_("Wrong wordpress path '%(wp_path)s' passed"), context={"wp_path": wp_path} ) if module not in ALL_OPTIMIZATION_FEATURES: raise ConfigError( message=_("Invalid feature %(feature)s, available choices: %(choices)s"), context={"feature": module, "choices": ALL_OPTIMIZATION_FEATURES} ) config = self.get_config() # check here as well that config has expected structure if not self.is_module_enabled(domain, wp_path, module, config, relative_docroot=relative_docroot): return # remove module from the list config["docroots"][docroot][wp_path].remove(module) # delete wp_path if all modules are disabled if not config["docroots"][docroot][wp_path]: del config["docroots"][docroot][wp_path] # delete docroot in it doesn't have wordpresses if not config["docroots"][docroot]: del config["docroots"][docroot] self.write_config(config) def enable_module(self, domain: str, wp_path: str, feature: str) -> None: try: docroot = get_relative_docroot(domain, self.homedir) except Exception as e: self._logger.exception(e) raise ConfigError( message=_("Docroot for domain '%(domain)s' is not found"), context={"domain": domain} ) if not is_wp_path(os.path.join(self.homedir, docroot, wp_path)): raise ConfigError( message=_("Wrong wordpress path '%(wp_path)s' passed"), context={"wp_path": wp_path} ) if feature not in ALL_OPTIMIZATION_FEATURES: raise ConfigError( message=_("Invalid feature %(feature)s, available choices: %(choices)s"), context={"feature": feature, "choices": ALL_OPTIMIZATION_FEATURES} ) config = self.get_config() # check here as well that config has expected structure if self.is_module_enabled(domain, wp_path, feature, config): return if "docroots" not in config: config["docroots"] = {} if docroot not in config["docroots"]: config["docroots"][docroot] = {} if wp_path not in config["docroots"][docroot]: config["docroots"][docroot][wp_path] = [] config["docroots"][docroot][wp_path].append(feature) self.write_config(config) def enabled_modules(self): for doc_root, doc_root_info in self.get_config()["docroots"].items(): for wp_path, module_names in doc_root_info.items(): for name in module_names: yield doc_root, wp_path, name def wp_paths_with_enabled_module(self, module_name: str) -> Iterable[str]: """ Return absolute WP paths with specified module enabled. """ for doc_root, wp_path, name in self.enabled_modules(): if name == module_name: yield os.path.join(self.homedir, doc_root, wp_path) def wp_paths_with_active_suite_features(self, features_set: set): """ Unique set of sites with active features from feature set SET is used here, because one site may have several features activated from one set e.g: site1 with activated object_cache, shortcodes = 1 path """ sites = set() for feature in features_set: sites_with_enabled_feature = self.wp_paths_with_enabled_module(feature) for site in sites_with_enabled_feature: sites.add(site) return sites def get_enabled_sites_count_by_modules(self, checked_module_names): """ Returns count of sites with enabled module """ sites_count = 0 for _, doc_root_info in self.get_config().get('docroots', {}).items(): for _, module_names in doc_root_info.items(): sites_count += any(checked_module_name in module_names for checked_module_name in checked_module_names) return sites_count