݈~>dZddlZddlZddlZddlmZmZddlmZddl m Z m Z m Z m Z ddlmZddlmZddlmZdd lmZdd lmZdd lmZdd lmZdd lmZddl m!Z!ddl"m#Z#ddl$m%Z%m&Z&ddl'm(Z(m)Z)ddl*m+Z+m,Z,ddl-m.Z.ddl/m0Z0m1Z1m2Z2m3Z3mZm4Z4m5Z5m6Z6m7Z7m8Z8m9Z9ddl:m;Z;mZ>m?Z?ddl@mAZAddlBmCZCmDZDddlEmFZFmGZGmHZHddlImJZJddlKmLZLmMZMddlNmOZOmPZPmQZQmRZRmSZSmTZTmUZUmVZVmWZWmXZXmYZYmZZZddl[m\Z\m]Z]m^Z^m_Z_m`Z`ddlambZbe+ecZde0e1fZee>dd e?!Zfd"ZgeVsefhd#dd$eg%n&efhd#eZeiejj&Gd'd(ekZleGd)d*ZmGd+d,ZndS)-z+ Implementation of clwpos-user CLI utility N) dataclassasdict)chain)DictListOptionalTuple)drop_user_privileges)Feature)is_panel_feature_supported)WP_BROKEN_CORE_REPAIR_TIP)parse) constants)gettext) WposError WposDaemon) get_user_info)get_allowed_modulesget_allowed_features_dict)get_visible_modulesget_visible_features_dict) setup_loggingUSER_LOGFILE_PATH) reload_redis) OBJECT_CACHE_FEATURE CDN_FEATUREALL_OPTIMIZATION_FEATURESCompatibilityIssuer UniqueId!convert_feature_list_to_interface disable_without_config_affectingenable_without_config_affecting DomainName DocRootPath)get_subscriptions_by_pwis_feature_hidden_server_wide)ArgumentParserCustomFormatter)enable_caching) UserConfigLicenseApproveStatus)CommandProgresstrack_command_progressupdate_command_progress) RedisLibUser)post_site_checkRollbackException) USER_WPOS_DIRcheck_license_decorator print_data catch_errorerror_and_exitdaemon_communicate check_domainis_run_under_user_run_clwpos_as_user_in_cagefsis_redis_configuration_runningget_server_wide_optionsget_pw)php_info%update_redis_disable_banners_constantWordpressError wordpressobtain_wp_cli_env)redis_socket_health_checkz/usr/bin/clwpos-userz.Utility for control CL AccelerateWP under user)formatter_classcn t|S#t$rtjd|zwxYw)NusernamezUser '%s' does not exist)r>KeyErrorargparseArgumentTypeErrorrGs py/clwpos/user/wpos_user.pyget_userrMcsOPx(((( PPP()Ch)NOOOPs"4z--userT)defaultrequiredtype)rNrPhelpc"eZdZdZfdZxZS)MaxCacheMemoryzM Class to validate format and values of cache memory setted by user. c tt|j|g|Ri|}n"#t$rt jdwxYwt j}t j}||cxkr|ksnt jd|d|d|S)Nz#invalid value type, must be integerzvalue must be in range: [, ]) superrS__new__ ValueErrorrJrKrMINIMUM_MAX_CACHE_MEMORYMAXIMUM_MAX_CACHE_MEMORY)clsargskwargsinstance min_memory max_memory __class__s rLrXzMaxCacheMemory.__new__us T9u^S119#OOOOOOHH T T T,-RSS S T7 7 X33333333,GJGG*GGGII Is $(A)__name__ __module__ __qualname____doc__rX __classcell__)rbs@rLrSrSpsB         rSc2eZdZUdZeed<eed<eed<dS)ManagedFeaturezI To track (docroot, website, feature) which was enabled/disabled docrootwebsite feature_nameN)rcrdrerfstr__annotations__rhrLrjrjs<LLL LLLrhrjc eZdZdZddiZdZedefdZe dZ dZ d Z d Z d]d ed edefdZedededefdZdefdZededededefdZdZededededefdZeddd !ed"d d#$ed%d d#$ed&d 'ed(d d d)ed*ed d#+ed,Z ed-d.d/d0ed1d2d34ed5d6d74ed8Z!d9Z"e#d:Z$d;Z%d<Z&d eded#zfd=Z'ed>ed?d @edAZ(dBZ)d^defdCZ*dedDededEefdFZ+dGedHededefdIZ,edJdKe-e.j/Lee0dMZ1dNZ2e#dOZ3ed&edPe4e5QedRedSd @edTZ6dUZ7e0e#dVZ8d]dWZ9edXZ:dYZ;dZed[edHedGefd\ZCloudlinuxWposUser._check_redis_configuration_process_and_exitsg * * */M/O/O *  a!abb      + * * *rhF user_configrc |jj}|tkrdSddg}||g}t j}t |}||vo|o|dk} |dko| } |o |dko|dk} tdt||t|t|t|| s| s| r*tdt|dSdS) aD Determine if it is needed to send reload command to Wpos redis daemon. Such reload should be done: 1. Enabling object cache and redis is not alive for user 2. Enabling object cache, but there are no successful sites (failed enabling) 2. Disabling object cache for last site Fdisablez disable-allrenablezCheck whether to reload redis for user=%s, command=%s, is_redis_alive=%s, before config modified status=%s,sites_with_enabled_cache_left=%sz*Redis is needed to be reloaded for user=%sT) rwrsr"get_enabled_sites_count_by_modulesr~geteuidrDrrrn) rzrrbefore_config_modifiedrsdisable_commandssites_count_with_enabled_moduleuidis_redis_aliveturn_off_upon_disable_last_siteturn_on_upon_enablingturn_off_upon_failed_enablings rL_is_redis_daemon_reload_neededz1CloudlinuxWposUser._is_redis_daemon_reload_neededsV*$ * * *5    +6*X*XZaYb*c*c'jll2377,36F+F,P+9,P+Ja+O ( ")H!4"4%3!3 *@*N)0H)<*N)HA)M &  7 HH''.//788 : : : ! $A Ed  KKDc#hh O O O4urhdomains_per_docrootphp_datactt}}|D]E}|d}||vr||d||dF||fS)zb Returns pair (all_php_versions, all_php_handlers) for domains in docroot vhostversionhandler)setadd)rrversionshandlersitemdomains rL+_get_php_versions_handlers_pair_for_docrootz>CloudlinuxWposUser._get_php_versions_handlers_pair_for_docrootsv !UUCEE( * *D']F000 LLi ) ) ) LLi ) ) ) )!!rh module_namec g}|S)z Collects general (not depending on worpress/docroot setup) server misconfigurations/incompatibilities with WPOS rp)rzrissuess rLcollect_general_issuesz)CloudlinuxWposUser.collect_general_issues s  rhmodule doc_root_infor?visible_featuresc X|dJtdtdtdtdt|gSg}||||||| }|||S) z\ Collects incompatibilities related to docroot (non-supported handler, etc) php_versionNPHP_MISCONFIGUREDz"Unable to detect php configurationzWe were unable to detect php configuration for this website. This might happen if there is a misconfiguration in control panel.zKPlease try again later and contact your administratorif the issue persists.) debug_data) unique_idheader descriptionfix_tip telemetry)r)rrdictextend_check_ambiguous_php_configcollect_docroot_issues)rzrrr?rradditional_issuess rLrz)CloudlinuxWposUser.collect_docroot_issues(s  ' /"1ABB !#g!h!h788"m<<<   d66}hOOPPP"99 ,<:>> '((( rhc g}|d}|||\}}t|dkr}|tt dt dt ddd|it jtd| t|dkr}|tt d t d t d dd|it jtd | |S)z Checks whether docroot has multiple php configs for the same path. This usually happens on cPanel when user or admin selects different php versions for primary domain and alias which points at the same location. domainsz"Different PHP versions for domainszOThose domains: %(domains)s are in same docroot, but using different PHP versionzMSet or ask your system administrator to set same PHP version on those domainsrUPHP_VERSION_BADLY_CONFIGURED)reasonrrrrrrrz"Different PHP handlers for domainszPThose domains: %(domains)s are in same docroot, but using different PHP handlerszMSet or ask your system administrator to set same PHP handler on those domainsPHP_HANDLER_BADLY_CONFIGURED) rlenappendrrrr PHP_MISCONFIGURATIONr)rzrr?rrrrs rLrz.CloudlinuxWposUser._check_ambiguous_php_configCsx+I6!MM ++( x==1   MM"ABB !#D!E!Emnn!499-@#A#A';"= 3      " x==1   MM"ABB !#E!F!Fmnn!499-@#A#A';"= 3      " rhwordpress_inforkmodule_is_enabledcPg}t|}|d}|s|t t dt dt t||ddtj tt|n||kr|t t d t d t d tt|t| tj tt|t| | | ||||S) zi Collects incompatibilities related to wordpress setup (conflicting plugin enabled, etc) rz%Failed to determine WordPress versionzOptimization feature couldn't be applied because WordPress installation at %(wp_path)s seems to be damaged or misconfigured. Details: %(error_details)sversion_missing_reasonz&wp-include/version.php file is invalid)r error_details)minimum_supported_wp_versionrzUnsupported WordPress versionzVOptimization feature is incompatible with WordPress version %(wp_version)s being used.zThe minimal supported WordPress version is %(minimum_supported_wp_version)s. Upgrade your WordPress installation or reinstall it from the scratch.)r wp_version) parse_versionrgetrrrr rr MISCONFIGURED_WORDPRESSrnUNCOMPATIBLE_WORDPRESS_VERSIONrcollect_wordpress_issues)rzrrrkrrrrs rLrz+CloudlinuxWposUser.collect_wordpress_issuesvs(5[5]5]5_5_'`'`$#'' 22 +  MM"DEE !5!! 6 '&4&8&84 E ''   '>"D`@a@abbb+    26 6 6 MM"<== !#Q!R!Rfgg 589U5V5V#&z??'E"589U5V5V#&z??   $  k::>7Teffggg rhz--listen store_trueT)actionrOz--domainN)rOrNz --wp-pathz --feature)rOz--ignore-errors)rOrNrz --advice-id)rPrOrNc t|jj|jjdufr>t |jj|jjdufst |jddi|jjd}|D],}|dtDvrt |jddi-ttj |jj|jj|jj|jj |jjdiS)NrzDBoth domain and wp_path arguments are requited if one of them is set,c6g|]}|Srp)to_interface_name).0rs rL z3CloudlinuxWposUser.subscription..s$^^^2244^^^rhzUnsupported feature passed)rsrrr ignore_errors advice_id)anyrwrrallr7rvrsplitrr8rDAEMON_REGISTER_UPGRADE_ATTEMPTrr)rzfeaturesfs rL subscriptionzCloudlinuxWposUser.subscriptions%  !4:#5T#AB C C \TZ. 0B$0NOPP \ 4=86Z+[ \ \ \:%++C00 X XA^^D]^^^^^t}x9U.VWWW!Aj'z)z)!Z5-      rhz--statusz-szStatus of license agreements)rQrz --approvez-azApprove license agreement)rQz--textz-tz"Read and approve license agreementc,|jjrKt|jj}i}tD]$}||j||j<%d|iS|jjrKt|jj}t|jj}| |ddiS|jj rLt|jj }|j sddiSdt|jiSt!d)NlicensesstatuszLicense agreement acceptedrNO_LICENSE_TERMStextUnknown command)rwrr+rrget_license_approve_statusnameNAMEapprover approve_license_agreementrHAS_LICENSE_TERMSopenLICENSE_TERMS_PATHreadr)rzucrrs rL agreementzCloudlinuxWposUser.agreements* :  9DJO,,BF4 S S')'D'DW'M'M'Rw|$$' ' Z  9dj011GDJO,,B  ( ( 1 1 16 Z_ 9djo..G, 0 W788==?? &&788 8rhcg}g}t|jdo |jj}d} |dD]I} |r0| d|jjkr|| d} n4|| J|r | s|d}|D]} i} tD]} | t jvrtd| 3| |dd| d| } | | |vd }|d g}n| | | || }g|| ||| |}|r!| d d|Di|| | <|| d| dpd| dgz }|S)a Function to get information about features and wp for a domain. :return: list of dictionaries "wps_out": [ { "features": { "accelerate_wp": { "enabled": false, "visible": true }, "cdn": { "enabled": false, "visible": false }, ... }, "path": "", "version": "x.x.x" } ] rFwpsrTKOptimization feature "%s" is skipped, because it is hidden by administratorrrenabledvisiblerNrrcg|] }|j Srp dict_reprrissues rLrz6CloudlinuxWposUser._get_for_domain..4s'333,1333rhrUNKNOWN)rrr) hasattrrwrrrr=hidden_featuresrwarning _is_enabledrupdater)rzrkrvisible_modulesgeneral_feat_issuesdocroots_features_issueswps_outwps_to_processwp_path_specified wp_path_foundwpfeatsfeat is_enabled module_infowordpress_issuesrs rL_get_for_domainz"CloudlinuxWposUser._get_for_domainsB,$DJ ::Qtz?Q & * *B  *f:!333"))"---$(ME4 %%b))))  2] 2*51N " " BE1 > >244DDDNN#prvwww!--mI.Fq.I2f:W[\\ *4AXYY  /7')$$'+'D'Db'Z(E(($(.-g6t<& &&335;333(3>d,,..// vJ!)}9 % GGrhc Jtjjj}t jjj}t t |ttj fd| D}fd| D}t5 tn%#t$rrg||dcYcdddSwxYwj}t%jjj}j|jit(D]K}|tj vrt*d|3||<Lfd| D}g} | } t1jdrmjjrafd| D} | s=t5d} | djjiz} t| djji | } | D]@\}}||||}| i|||d r |d jndd gz } A dddn #1swxYwY| ||dS) NcNi|]!\}}|tfd|D"S)cg|]}|v| Srprprrhidden_features_sets rLrz6CloudlinuxWposUser._get...M+<<<#7BU3U3U3U3U3Urhr!r feature_setrr4s rL z+CloudlinuxWposUser._get..Lb& & & & X :<<<<'/<<<& & & rhcNi|]!\}}|tfd|D"S)cg|]}|v| Srprpr3s rLrz6CloudlinuxWposUser._get...Tr5rhr6r7s rLr9z+CloudlinuxWposUser._get..Sr:rh)docrootsallowed_featuresrrc`i|])\}|fdD*S)c Bi|]}||Srp)r)rr+rphpinforzrs rLr9z6CloudlinuxWposUser._get...xsI $55%( rh)keys)rrkrr#rArzrs @rLr9z+CloudlinuxWposUser._get..wss ( ( (+G]!4 8 8 : : ( ( (rhrcFg|]\}}jj|dv||fS)r)rwr)rrkrrzs rLrz+CloudlinuxWposUser._get..sD%V%V%VBX'='+z'8M)=#?#J#J9=  wD D D D D D D D D D D D D D D N! : :  &&((  $$&&   s7K,C)(K,)D <K, D  GK,,K03K0ctjj}|fdtjt jhDdS)Nci|]<}||=Srp)lower_get_upgrade_urlrrrzs rLr9z:CloudlinuxWposUser._get_billing_status..sI !6!6w}}!G!Grh)r upgrade_url)r&rwrrrr)rz subscriptionss` rLrMz&CloudlinuxWposUser._get_billing_statussY/ @@ * 4 9;;KL   rhct|jt|jjdtjdS)Nmax_cache_memory) used_memoryra) r0rget_redis_used_memoryr+rwr get_configrDEFAULT_MAX_CACHE_MEMORYrys rLrNz$CloudlinuxWposUser._get_redis_statuss^'(>??UUWW *4:? ; ; F F H H L L"J$G!!   rhcr ttj|dd}n#t$rd}YnwxYw|S)Nrsrr^)r8rDAEMON_GET_UPGRADE_LINK_COMMANDr)rzrr^s rLr\z#CloudlinuxWposUser._get_upgrade_urlsa ,%E"..KK   KKK s "% 44z --websitezWebsite to scan)rPrQrOc |jjj}t|t |}} t }n#t $r|rd}YnwxYw|}i}tD];| }|vrf| ttdtdtdtjtdt!rf| ttdtd td tjtd |D].\}} |jj| d vr|vr|| ||} | d D]} || d d| d} g} | rO|| dg tjtjdn5|vr-| dg}n|| || }g|| |} ng|} || dgfd| D0=|D]}|ds |dj|d<d|iS)zd ATTENTION: --website = actually domain, -> pass domain name instead of website !!! NzFeature was not made visiblez1Optimization feature was not made visible to userz9Contact Administrator to allow using optimization featureFEATURE_NOT_MADE_VISIBLE)r)rrrrrzFeature is hidden server widez6Optimization feature is hidden in server wide settingsz(Contact Administrator to make non-hiddenFEATURE_HIDDEN_SERVER_WIDErrrrrPr advice_typerrcdg|],}t|t|j|jjd-S)rl) isinstancerrrr)rrrs rLrz+CloudlinuxWposUser.scan..sR;;; "*UL^:_:_ ;$)O',+6+;;;;rhr)rwrrFrrr?rrJrrrrrr rjrr'rkrIrlrr  setdefault!CLOUDLINUX_MODULE_ALREADY_ENABLEDrrrrHrL)rzu_idallowed_modulesr"rArSrgeneral_issuesrkrdocroot_issuesr)r,incompatibilitiesr. document_rootrs @rLscanzCloudlinuxWposUser.scans z%+>t+D+DFYZ^F_F_ jjGG    GGG  '')) 4> > K!88EEN/11%%& !?@@$%&Y$Z$Z !"] ^ ^"*"C"&.H"I"I"I -[99 %%& !@AA$%&^$_$_ !"L M M"*"E"&.J"K"K"K +4//*;*;% % &:%]9-EEE/11%)%@%@#]G_&N&NN(.B!%!1!1- 2J12MrRXz[f!g!gJ(*%!>r&z266==$,$N'+vv+6+;?? %77(7?/1,,/3/L/L +RJ0M0X0X,-bn,a~,aP`,a)),=n,=)NN2f:r2299;;;; &7 ;;;-% P'--// S SM / +8+G+RM- ( ( c  sAAAc t|jddrdnd}|dkrdnd}t|jddt|jjdr |jjn t }|j}|gdgd gd gi}|}t}|D]\}} | d pg} | r| d nd} r| vr0| d gD]} | dpd d} | p|}| pd}|d|d|}| r tj || n|}tj tj |ds|d | t!|dd||}nH#t"$r;t$d|||d|YwxYwt)|t*ra|jd|j}d|vr|d |s|d||||rNt3fd|Ds!|d |dd|S)NrFrmaxcache_enabledmaxcache_disabledrrerror(accelerate_wp_plugin_needs_to_be_updated"accelerate_wp_plugin_not_installedrrrrr/:z"wp-content/plugins/clsop/clsop.phpz accelerate-wpmaxcache)envzMAx Cache %s failed for %s znot a registeredc3*K|] }|D]}|vV dSrrp)rsublistr domain_filters rL z/CloudlinuxWposUser._maxcache..Ts7$o$owgn$o$o_c]d%:$o$o$o$o$o$o$orhz:/)rrwrrr>rrJrCrIrstripr~rrisfilerrB Exceptionr exceptionrorArErr[rrH)rzr success_keyuser_pwrHsummaryrS wp_cli_envrkrrrr)r label_domain label_path site_label abs_wp_pathrerr_textrs @rL _maxcachezCloudlinuxWposUser._maxcache"sP$TZ5AAPy,2h,>,>((DW  Hd;; %,TZ_i%H%HV$*//fhh?  R 6 0"  '')) &(( &__.. < >/R66s;;%1 $^ (FF<FF*FF @GTbgll7G<<CCH)X^^-=-=== JKRRS]^^^^(// ;;;;K(// ;;;;3 <6  b$o$o$o$o'..JZJZ$o$o$o!o!o b 8 9 @ @HA`A`}A`A`A` a a as:GAHHcd}|1t}|D] }||nt|}|||S)Nc|di}|d|d<|d|d<dS)rphprrr php_handlerN)popr)rrs rLreformat_php_dataz.reformat_php_data[sG((5"%%C"%'')"4"4D "%'')"4"4D   rh)rrH)rzrkrrSrs rLrJz!CloudlinuxWposUser._get_user_infoZs| 5 5 5 ?%I!*!1!1!3!3 1 1 !!-0000 1&0I  i ( ( (rhwordpress_pathis_module_enabledcjg}t|jjj}||}t }||} ||| ||} | dD](} | d|kr||| ||})dg|| |RDS)zB Obtains issues for special docroot and wordpress rrrcg|] }|j Srprrs rLrzDCloudlinuxWposUser.get_current_issues_by_docroot..}scccEcccrh) rrwrrFrr?rJrr) rzrrrkrr.rsrtrAuser_info_by_docrootrur)s rLget_current_issues_by_docrootz0CloudlinuxWposUser.get_current_issues_by_docrootls -djo.DEE44[AA**#227;;44[BVX_apqq&u- b bB&z^++#<<["gO` = b b  cc-b~-b-bQa-b-bccccrhrrct|jj}||||o|t |jjjvSr)r+rwrrrrF)rzrrrrs rLr zCloudlinuxWposUser._is_enabledsH   ( (##FGV<<vK^_c_i_n_uKvKvAvvrhz--max_cache_memoryz!Maximum cache memory to use in MB)rQrPrNct|jj}d|jjdi}||t |j|S)Nramb)r+rwrra set_paramsr8COMMAND_RELOAD_DICT)rzrparamss rLrzCloudlinuxWposUser.setsU   ( ($)D&H&H&HI f43444 rhc <fd}t|jj}g}|D]\}} ||||t ||n;#t $r.tdt||fYqwxYw| t|r< td#t $rtdYwxYwdd |DiS) Nctt||}|rtdd|id|||dS)Nrz:Error(s) "%(errors)s" during disabling plugin in WordPresserrors)r)rrrrelative_docroot)r"r%rdisable_module)rksiterm last_errordoc_rootrs rL_disable_singlez8CloudlinuxWposUser._disable_all.._disable_singlesx9H%%tLJ P%z2   T4 _f  g g g g grh)rkrlrmzCannot disable feature for: %sryesskip_last_reload_timezFailed to reload redisdisabledc,g|]}t|Srp)r)rrs rLrz3CloudlinuxWposUser._disable_all..sJJJdVD\\JJJrh) r+rwrenabled_modulesrrjrrrrnrr r)rzrall_enabled_featuresdeactivated_objectsrrmrrs @@rL _disable_allzCloudlinuxWposUser._disable_alls h h h h h h  ( (!1133 ,@ ? ? (HdL $ ===#**"8TP\]]]     !A3RVXdGeCfCfggg 222w|?T?T2UU ?? u===== ???$$%=>>>>>? ? JJ6IJJJKKs$2A445B,+B,C%%$D  D c : t|jj\}}|jjd}d|dvrt |jdditj tj ||}| tj |dzs:|tj |krt |jddit|jj}g}|jj}||jj||s)t%d|jj|jjddS|| |jt-t/|jj|| }|r=t0|j|jz||ni ||jj||nF#t<$r9} t0d || Yd} ~ nd} ~ wwxYw|j| || r tCd n#tD$rO} | j#| jz} t0d| j| || Yd} ~ nId} ~ wt<$r9} t0d|| Yd} ~ nd} ~ wwxYw|j|$|jj||} |tK|jjj&v} |'d}n#tP$rd}YnwxYw| r|rYtEt%d|jdtSj*|jjj+itY|dit |jdt%didS| | dt[|j./d} |rJ| t%ddtSj*|jjj+idn%|0|||| }|r || dd<| S)Nr..r1Invalid wp_path: must not contain '..' components;Invalid wp_path: resolved path is outside the document rootzbOptimization feature %(feature)s is already disabled on the domain %(domain)s. Nothing to be done.rrrrrrz"unable to disable module in configrrz(CLWPOS daemon error: '%s'; details: '%s'zunable to reload cache backendaOptimization feature disabling failed because one or more steps reported error. Caching is still active, but may work unstable. Try disabling it again. Contact your system administrator if this issue persists. Detailed information you can find in log file '%(log_path)s'log_path)homedirr)rEdetailsrzWordPress caching module is still enabled, but no errors happened. Try again and contact your system administrator if this issue persists.rrrbzOptimization feature disabled, but one or more steps reported error. Detailed information you can find in log file '%(log_path)s'rr)1r9rwrrrrr7rvr~rrealpathr startswithr+rroptimization_featurerrrrxr!r"r$rr|rErrrrrrrrrr rrFr IndexErrorrformatrrr0rrcr)rzrHrrrrrrmre s_detailsris_module_visibleresponsers rL_disablezCloudlinuxWposUser._disables)$**;<<(*$**3// 7==%% % %  NO    g&&rw||Hg'F'FGG %%bg&6&6x&@&@3&FGG 27#3#3H#=#===  XY      ( (z)>>@@ ##DJ$5w MM ] "7 8 8*.**; HZ[[]] ] ..|.DDD $$&&&5 tz( ) )7<III   ! LL+j.@@ A A A MM* % % % % !!!$*"3WlKKKK ! ! !  !EFFF a         ! $$&&&  . .r< . H H ! !599999 ! ! !I 1   !KQYXabbb a         ! ! !  !ABBB a         ! $$&&& ,,TZ->VV(,? @V,W,WW BJJ   JJJ  *  ]^^'."$5$.jF!C!C!C%,"&!1!1$*2CWg!V!V!C!C!CrhzeThe %(feature)s optimization feature is already enabled on the domain %(domain)s. Nothing to be done.rrz