v/ Pݬ dZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl mZddlmZddlmZmZmZddlmZdd lmZdd lmZdd lmZdd lmZmZdd l m!Z!m"Z"ddl#m$Z$ddl%m&Z&ddl'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ddl0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;ddle?Z@edZAdZBdZCdZDdeEdejFdeEfdZGdejFdefdZHdejIfdZJdId eKfd!ZLd"ZMd#ZNd$ZOdePfd%ZQd&ZRd'efd(ZSd'edeTfd)ZUd*ZVd+ZW dJd,eXefd-ZYd.eKefd/ZZd'ed0eEfd1Z[d2ed3ePdedzfd4Z\d5edeEdzfd6Z]d2edeEdzfd7Z^d2edePfd8Z_d'edejFd9ePd:eXd;eXddf d<Z`d2ed=eaddfd>Zbd?Zcd@Zdd'edeafdAZed'edBeTdeafdCZfdDZgGdEdFZhGdGdHehZidS)Ku  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.  If not, see . Copyright © 2019 Cloud Linux Software Inc. This software is also available under ImunifyAV commercial license, see N) defaultdict) LooseVersion)Path) inactivity)MalwareScanScheduleInterval SystemConfigANTIVIRUS_MODE)Index) log_message) Wordpress)files) WordpressSiteWPSite)cli telemetry)PLUGIN_VERSION_FILE)get_user_schedule_config)calculate_next_scan_timestamp$clear_get_cagefs_enabled_users_cacheensure_site_data_directoryformat_php_with_embedded_json get_last_scanget_malware_historyprepare_scan_data!write_plugin_data_file_atomically) clear_manually_deleted_flag delete_siteget_outdated_sitesget_sites_for_userget_sites_to_adoptget_sites_to_install%get_sites_to_mark_as_manually_deletedget_installed_sitesinsert_installed_sitesmark_site_as_manually_deletedupdate_site_version)setup_site_authenticationzD/var/lib/cloudlinux-app-version-detector/components_versions.sqlite3z wp-rules.zipVERSIONcHttjdS)z#Clear all WordPress-related caches.N)rrclear_get_content_dir_cacheJ/opt/imunify360/venv/lib/python3.11/site-packages/imav/wordpress/plugin.py clear_cachesr.Vs#(***#%%%%%r,items user_inforeturnct|}d|D}|D]Dfd|D}|r1t|t}||E|S)Nci|]}|gSr+r+).0paths r- zsite_search.._s . . .4dB . . .r,c,g|]}||Sr+r+)r4r5itemmatchers r- zsite_search..bs*MMM4t9L9LM$MMMr,)key)rmaxlenappend)r/r0r9 user_sitesresultmatching_sitesmost_specific_siter8s ` @r- site_searchrC\s#I..J . .: . . .F44MMMMM:MMM  4!$^!=!=!=  % & - -d 3 3 3 Mr, admin_configc:Kt||jd{V}|dd}t|j|\}}}}d} |tjkrt ||||} t|j} t| |d} || | fS)N scan_datecP|ddko|d|S)N resource_typefile) startswith)r8r5s r-z)_get_scan_data_for_user..s-40F:* L # #D ) )r,) rpw_namegetrIntervalNONErrrC) sinkr0rD last_scanlast_scan_timeintervalhour day_of_month day_of_weeknext_scan_timemalware_historymalware_by_sites r-_get_scan_data_for_userrZls$D)*;<<<<<<<? ::r, semaphorecK|4d{V |d{Vn4#t$r'}td|Yd}~nd}~wwxYwdddd{VdS#1d{VswxYwYdS)NzTelemetry task failed: ) Exceptionloggererror)coror[es r-_send_telemetry_taskrbs+88888888 8JJJJJJJJ 8 8 8 LL6166 7 7 7 7 7 7 7 7 8888888888888888888888888888888s5AA AAAAA A'*A' coroutinescK|sdStj|fd|D} tj|d{VdS#t$r(}td|Yd}~dSd}~wwxYw)zK Process a list of telemetry coroutines with a concurrency limit.s NcTg|]$}tjt|%Sr+)asyncio create_taskrb)r4r`r[s r-r:z+process_telemetry_tasks..s?     0yAABB   r,zSome telemetry tasks failed: )rg Semaphoregatherr]r^r_)rd concurrencytasksrar[s @r-process_telemetry_tasksrms !+..I       E :ne$$$$$$$$$$ ::: 8Q88999999999:sA A3 A..A3cK tjtjd}|d{Vt |}n3#t $r&}t d|Yd}~dSd}~wwxYw|st ddSt|}||d}t|S)z Load WordPress rules from the index and format them as PHP. Returns: str or None: PHP-formatted rules data, or None if rules could not be loaded. F)integrity_checkNz>Failed to load wp-rules index: %s, skipping rules installationzA99A>cvKt}t||}|d{VS)zLInstall the imunify-security plugin for all sites where it is not installed.N)r!WordPressSiteInstallerrun)rPsites installers r-install_everywherers@ " "E&tU33I  r,cvKt}t||}|d{VS)a Adopt WordPress sites where the plugin is installed but not tracked in our database or flagged as manually removed. This handles scenarios like: - Sites copied/migrated from another location - Sites migrated from another server - Sites where the manually_deleted flag was incorrectly set (past bugs) - Sites where the user installed the plugin from wordpress.org N)r WordPressSiteAdopterr)rPr processors r-adopt_found_sitesrsB  E$T511I  r,c tjs"tdtdStjS#t $r&}td|Yd}~dSd}~wwxYw)zLGet the latest version of the imunify-security plugin from the version file.z&Plugin version file does not exist: %sNz&Failed to read plugin version file: %s)rexistsr^r_ read_textstripr])ras r-get_latest_plugin_versionrs ")++  LL8:M   4",..44666  =qAAAttttts3A$A B &BB c Kt}|stddStd|t }g}t jd5 t|}tdt|d|s# t|d{VddddSt}tt}|D]"}||j|#|D]\}} t#j|} | j} n3#t($r&} td|| Yd} ~ Nd} ~ wwxYwt+|| |d{V\} }}| D]t}t-||d{Vr t/j|d{Vstd|Qt3| || ||}t5||d{Vt/j|d{V||t/j|d{V}|r{|j}t?||| |}tC|tC|k}|tEj#||rd nd || B#t($r'} td || Yd} ~ nd} ~ wwxYwtd t|nf#tHj%$r+tdt|Yn-t($r!} td| d} ~ wwxYwt|d{Vn#t|d{VwxYw ddddS#1swxYwYdS)zFUpdate the imunify-security plugin on all sites where it is installed.z)Could not determine latest plugin versionNzr/pwdgetpwuidrLr]rZremove_site_if_missingris_wordpress_installedrupdate_scan_data_file plugin_updateaddget_plugin_versionrqr&build_with_versionrr send_eventrgCancelledError)rPlatest_versionupdatedtelemetry_corosoutdated_sitesrD sites_by_userrrrr0usernamer_rRrWrY scan_datarqoriginal_version is_downgrades r-update_everywherers.00N  @AAA KKF eeGO    1 2 2y;y;x ;/??N KKE^!4!4EEE F F F! d*/:: : : : : : : :sy;y;y;y;y;y;y;y;(>>L(--M& 5 5dh'..t4444,1133T T  U  # S 1 1I(0HH LLE HHHH 2)\ ""# "??D3D$????????! <%(%?%E%EEEEEEE%"KK Et%%6**$ + %% 4D)DDDDDDDDD"/555555555 D)))),(>t(D(D"D"D"D"D"D"D"/3|,0g>>>$(#:#:7#C#CD,8 ',, ,-= > >,?L ,22 ) 4)-,8)B(?(?-A)-,3 !" !" !"   % I !u?B KK@G     %    KK+G           LL?      */:: : : : : : : : :)/:: : : : : : : : : :sy;y;y;y;y;y;y;y;y;y;y;y;y;y;y;y;y;y;s9O-;M F:M 5K*8M 9C/K*(M * L 4L M L -M O 7N,O N, N''N,,O/O-OO--O14O1rcKtj|d{V}|r'tjt j|d{VdSdSN)r get_data_dirrrg to_threadshutilrmtree)rdata_dirs r-delete_plugin_filesrzsq%d++++++++H9 x8888888888899r,cK tj|d{V}|s+t|tj||d{VdStj|d{V}tj|d{Vt |d{Vt|}|tj |d|||S#t$r'}t d||Yd}~dSd}~wwxYw)a7 Remove the imunify-security plugin from a single site, including all cleanup and telemetry. Returns the number of affected sites (should be 1 if deletion was successful). This function is intended to be protected with asyncio.shield to ensure it completes even if the parent task is cancelled. Nruninstalled_by_imunifyrz"Failed to remove plugin from %s %s)ris_plugin_installedprocess_manually_deleted_plugintimerplugin_uninstallrrr>rrr]r^r_)rrPr is_installedrqaffectedr_s r-remove_from_single_sitersz # 4T::::::::  1dikk4       1.t44444444"4((((((((("$'''''''''t$$   .         94GGGqqqqqsAC BC DC<<Dc Ktdg}d}tjd5 t t }|D]m} |tjt|||d{Vz }0#tj $r,td|t|YjwxYwn.#t$r!}t d|d}~wwxYw td|t|d{Vn5#td|t|d{VwxYw ddddS#1swxYwYdS)zHRemove the imunify-security plugin from all sites where it is installed.z#Deleting imunify-security wp pluginrzwp-plugin-removalNz_Deleting imunify-security wp plugin was cancelled. Plugin was deleted from %d sites (out of %d)z)Error occurred during plugin deleting. %sz0Removed imunify-security wp plugin from %s sites)r^rrrrr.r#rgshieldrrr=r]r_rm)rPrr to_removerr_s r-remove_all_installedrs5 KK5666OH    2 3 3;; ; NNN+--I!   gn/dOLL''!!!!!!HH-KKH I      LLDe L L L    KKB    */:: : : : : : : : : KKB    */:: : : : : : : : : :9;;;;;;;;;;;;;;;;;;slE2 C#,BC8C C C  CD/ C:C55C::D/>1E2/2E!!E22E69E6cK t||t|d{V|tj|d||jdS#t $r'}td||Yd}~dSd}~wwxYw)a Process the manually deleted plugin for a single site. Args: site: The site to process. now: The current time. sink: The telemetry/event sink. telemetry_coros: The list of telemetry coroutines to add the event to. The process includes: - marking the site as manually deleted in the database - removing plugin data files - sending telemetry for manual removal Nremoved_by_userrz>Failed to process manually deleted plugin for site=%s error=%s) r%rr>rrrqr]r^r_)rnowrPrr_s r-rrs %dC000"$'''''''''   '              L            sAA B %BB freshly_installed_sitescdKg} t|}|r0tj}|D]}t||||d{Vn2#t$r%}td|Yd}~nd}~wwxYw|rt |d{VdSdS#|rt |d{VwwxYw)a> Tidy up sites that have been manually deleted by the user. Args: sink: The telemetry/event sink. freshly_installed_sites: Optional set of sites that were just installed and should be excluded from being marked as manually deleted to avoid race conditions. Nz&Error occurred during site tidy up. %s)r"rrr]r^r_rm)rPrrto_mark_as_manually_removedrrr_s r-tidy_up_manually_deletedrs>O;&K #' ' # ' )++C3  5#t_ FFF =uEEEEEEEEF  ;)/:: : : : : : : : : : ; ;? ;)/:: : : : : : : : : ;s0AAB A7A2-B2A77BB/rc K|sdSt}tt}|D]"}||j|#|D]\}} t j|}|j}n3#t$r&}t d||Yd}~Md}~wwxYwt|||d{V\} } } |D]v}t||d{Vr t| | ||| } t|| d{VD#t$r&}t d||Yd}~od}~wwxYwdS)Nrz.Failed to update scan data on site=%s error=%s)rrrrr>r/rrrLr]r^r_rZrrr) rPrrDrrrr0rr_rRrWrYrs r-update_data_on_sitesrs  >>L %%M--dh&&t,,,,$))++&& U  S))I (HH    LL=    HHHH  *$ <HH H H H H H H      D+D$77777777  -""#  ,D)<<<<<<<<<<    D  %&&s0(B B4B//B4.)D E"EErcKtj|j}|j}t ||d{V}|dz }t |}t |||j|dS)N scan_data.phprgid)rrrpw_gidrrr)rrr0rrscan_data_path php_contents r-rrLs TX&&I  C0i@@@@@@@@H/N0 ::K% sr,indexfilenamec4|D]N}|d|kr@t||d}|r|cSOtd|||jdS)a Find a file path from the index by filename. Args: index: files.Index object filename: Name of the file to find (e.g., WP_RULES_ZIP_FILENAME, WP_RULES_VERSION_FILENAME) Returns: Path to the file or None if not found nameurlz%s not found in %sN)r/r localfilepathrr^r_ files_pathtype)rrr8 file_paths r-_find_file_in_indexr]s !! <8 # #U00e==>>I!! !     LL%x1A1A%*1M1MNNN 4r,zip_pathc tj|d5}|d5}tj|}dddn #1swxYwYdddn #1swxYwYnJ#tjt tjf$r&}t d|Yd}~dSd}~wwxYwt|tst d|dS|S)z Extract and parse wp-rules.yaml from the zip file. Args: zip_path: Path to wp-rules.zip file Returns: Parsed YAML data as dict or None if extraction/parsing fails rz wp-rules.yamlNz,Failed to extract or parse wp-rules.yaml: %sz Invalid wp-rules.yaml format: %s) zipfileZipFileopenyaml safe_load BadZipFileKeyError YAMLErrorr^r_ isinstancedict)rzip_file yaml_file rules_dataras r-_extract_wp_rules_yamlrrsb _Xs + + 7x// 79!^I66  7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7  $. 9 CQGGGttttt j$ ' ' 7DDDt s]A1A%A A%A A%A A% A1%A))A1,A)-A11!B8B33B8ct|t}|sdSt|}|sdStdt r|D] \}}d|d< |S)aJ Retrieve the latest WordPress rules and return them as a dictionary. Args: index (Index): The files.Index object used to locate the wp-rules.zip file. Returns: dict: The parsed wp-rules data as a dictionary. If the wp-rules archive or data cannot be found or parsed, returns None. Nz!Successfully parsed wp-rules.yamlpassmode)rWP_RULES_ZIP_FILENAMErr^rr r/)rrrcveparamss r-rurus#5*?@@H t(11J t KK3444$%++-- $ $KC#F6NN r,c"t|t}|sdS |}td||S#t $r&}td|Yd}~dSd}~wwxYw)a5 Retrieve the WordPress ruleset version string from the VERSION file. Args: index (Index): The files.Index object used to locate the VERSION file. Returns: str: The version string from the VERSION file. If the VERSION file cannot be found or read, returns "NA". NAz&Successfully read wp-rules version: %szFailed to read VERSION file: %sN)rWP_RULES_VERSION_FILENAMErrr^rr]r_)r version_pathversion_stringras r-rwrws'u.GHHL t%//117799 r/rrrr]r r=rrangergrjr)rrryrzr{rrrinstalled_sitesrrrlrrr0rr_max_concurrentibatchs r-update_wp_rules_on_sitesrs=  ,        ?@@@ KKABBB-e44M  CDDD.e44#L1>>LeeG UUF    4 5 5@@?  NNN233O"  =>>>@@@@@@@@(--M' 5 5dh'..t4444E+1133   U # S 1 1I %++7 )\7F   T**** + !4&)ZZ$'&+%% ("-$?    !&)) 4((((HHHH!& N1c%jj.99 E Ea!n"445neDtDDDDDDDDDD KKGG F      %    KKEG          LLEu      y@@@@@@@@@@@@@@@@@@su.L08J!6AJ! AG  J! H ?HJ!H  BJ! L!7LL L#K??LLLLc Ktdt}t}tjd5 t t}|s(td ddddStt}|D]"}||j  |#g}| D]\}} tj|}|D])}t||||} | | *G#t $r/} t#dt%||| dddd Yd} ~ {d} ~ wwxYwd } t'd t%|| D]&} || | | z} t)j| d did{V'tdt%|t%|nf#t(j$r+tdt%|Yn-t $r!} td| d} ~ wwxYwddddS#1swxYwYdS)z7Update auth.php files for all existing WordPress sites.z4Updating auth.php files for existing WordPress siteszwp-auth-updatez"No installed WordPress sites foundNzSkipping auth update for WordPress sites on {count} site(s) because they belong to user {user} and it is not possible to retrieve username for this user. Reason: {reason}rrvrzwp-plugin-auth-update-skip-userrrcrr Tz8Updated auth.php files for %d WordPress sites, %d failedzLAuth update for WordPress sites was cancelled. Auth was updated for %d sitesz+Error occurred during auth update. error=%s)r^rrrrrr.r#rrrr>r/rrupdate_site_authr]r r=r rgrjrr_)rrrrrrlrrr0rr_rrrs r-update_auth_everywhererNse KKFGGGeeG UUF    / 0 0@@?  NNN233O"  @AAA@@@@@@@@(--M' 5 5dh'..t4444E+1133   U # S 1 1I %++/ )Wf   T**** + !D &)ZZ$'&+%% ("-$E    HHHH& N1c%jj.99 E Ea!n"445neDtDDDDDDDDDD KKJG F      %    KK(G           LLF N N N  }@@@@@@@@@@@@@@@@@@suI#8G0 AG05AD65G06 E/%E*%G0*E//BG0/I#07I'I#) I2III##I'*I'cK t||d{V||dS#t$r<}||td||Yd}~dSd}~wwxYw)z/Process authentication setup for a single site.Nz*Failed to update auth for site=%s error=%s)r'rr]r^r_)rr0rrr_s r-rrs  'i888888888 D     4 8            s+1 A71A22A7c*Ktj|jrdSt |}|dkr$t j|d||jd{Vn1t d|tdd|id d d d S)a Checks if the site directory exists. If not, removes the site from the local database and sends a 'site_removed' telemetry event only if deletion is successful. Returns True if the site was removed (directory missing), False otherwise. Parameters: sink: The telemetry/event sink. site: The WPSite object to check and potentially remove. Side effect: If the site is missing and successfully deleted from database, a telemetry event will be sent. Fr site_removedrNz@Failed to delete missing site %s from database, no rows affectedz2Failed to delete missing site {site} from databaserrvrzwp-plugin-site-delete-failedrT) osr5isdirrrrrrqr^rvr )rPr rows_deleteds r-rrs w}}T\""ut$$La"^$              N     @!6      4r,file_permissionscK tj|d{V}|sdS|jdz}|dkr|ddD]R}||z }|r7|jdz}||kr||SdS#t $r'}td||Yd}~dSd}~wwxYw)a) Fix data file permissions for a single WordPress site. Args: site: The WordPress site to fix permissions for file_permissions: The file permissions to set (e.g., 0o440 or 0o400) Returns: bool: True if permissions were fixed successfully, False otherwise NFii)rzauth.phpTz.Failed to fix permissions for site=%s error=%s) rrrstatst_modechmodr]r^r_)rrrcurrent_dir_mode file_namercurrent_file_moder_s r-fix_site_data_file_permissionsr$s0)$////////   5$==??2U: u $ $ NN5 ! ! !6 6 6I 9,I!! 6$-NN$4$4$*!!%IIdOOOOJJt$$$$ KKE F     %    KK&E           LLCU         [000000000000000000sNF!D*,B=D*)F!*7F!F!# F,F F! FF!!F%(F%cTeZdZdZdZdZdZdZdddd d d d d ZdZ dZ dZ dZ dZ dS)r~z Handles installation of imunify-security plugin on WordPress sites. This class processes WordPress sites and installs the imunify-security plugin, including setting up authentication, scan data files, and rules. Tinstalled_by_imunifyzwp-plugin-installationzwp-plugin-install-skip-userz%Installing imunify-security wp pluginz5Installed imunify-security wp plugin on {count} sitesz&Found {count} site(s) for installationz5Failed to install plugin to site={site} error={error}z`Installation of imunify-security wp plugin was cancelled. Plugin was installed for {count} sitesz8Error occurred during plugin installation. error={error}zSkipping installation of WordPress plugin on {count} site(s) because they belong to user {user} and it is not possible to retrieve username for this user. Reason: {reason}startcompletefoundr_ cancelled exception skip_userc||_||_t|_t|_t|_t|_t|_g|_dSr) rPrr processed authenticatedrules_installedfailed_rules_updates failed_authr)selfrPrs r-__init__zWordPressSiteInstaller.__init__RsY   UU"uu$'EE!55!r,crKtj|d{V}|stdd|iddddSd S) a Check if site is ready for processing. Override in subclasses to implement different readiness checks. Args: site: The WordPress site to check. Returns: bool: True if the site is ready for processing, False otherwise. Nz:WordPress site is not accessible using WP CLI. site={site}rrvrzwp-plugin-cli-not-accessiblerFT)rrr )r>rrs r- is_site_readyz$WordPressSiteInstaller.is_site_ready\si(+'A$'G'G!G!G!G!G!G!G%  L#TN%:     5tr,c:|j|dS)a Record a successfully processed site. Override in subclasses to implement different recording logic. Args: site: The WordPress site that was processed. version: The plugin version installed on the site. N)r9rr>rrqs r-_record_processed_sitez-WordPressSiteInstaller._record_processed_sitets  4     r,c.t|jdS)z Execute post-processing after all sites have been processed. Override in subclasses to implement different database handling logic. By default, inserts all processed sites into the database. N)r$r9r>s r-run_post_processingz*WordPressSiteInstaller.run_post_processings t~.....r,c  Kt|jdtj|j5 t|jsA|j | t|j d{VcdddSt|jd t|jt}t!d{V}t#t$}|jD]"}||j|#|D]@\}} t-j|}|j}nL#t2$r?} t5|jdt||| ddd|j Yd} ~ gd} ~ wwxYwt9|j||d{V\} } } |D]}t=|j|d{Vr ||d{Vsr/rrrLr]r log_fingerprint_skip_userrZrPrrArrrr:r=rr;r<install_pluginrplugin_installrrrrDrrtelemetry_eventr_reprrvrgr)r>rDrrrrrr0rr_rRrWrYrrqs r-rzWordPressSiteInstaller.runs_  DM'*+++   " "4> 2 2N DN DM Dz*>L((***.d.BCCCCCCCCC]N DN DN DN DN DN DN DN D M'*11DJ1HH ,~~ &7%8%8888888 !,D 1 1  J99D!$(+2248888#0"5"5"7"7YYJC!$'L$5$5 #,#4$ ! ! !# M+6),U(+*/)) #,&1(,(F    ! !$6 9l &&' !&??!7 4!H!HHHHHHH%$;)-););D)A)A#A#A#A#A#A#A) (): . . ( $ / ))I#8i"H"HHHHHHHH"2 $ ) $ 2 $ 0 ## ,"&>$($-$0$($8$($= '"'"!"!"!"!"!"!"!" $2?&)&8&>&> > > > > > > >-0,B4,H,H&H&H&H&H&H&HG&P'-'@w'O'O!77gFFF!077 ) 4)-*.*>)-,3 !"!"!" )"LL $ g 6 = =)-T%[[!>!"!"u?@ M*-443t~;N;N4OO#NN9D,--,NN@D566)    M+.55!$.116     M+.55DKK5HH  ((***.d.BCCCCCCCCCC((***.d.BCCCCCCCCCCC]N DN DN DN DN DN DN DN DN DN DN DN DN DN DN D`~s U<Q).U<$CQ*FQ G5G Q GAQM/Q0DMQ N AN QN B8QT<AT 3T<5 T >ATT  T< /U<<0U,,U<<VVN)__name__ __module__ __qualname____doc__rMrOrJrLrIr?rArDrGrr+r,r-r~r~2sN,O(I =8K9H 5 G 7H("""0 ! ! !///YYYYYr,r~c\eZdZdZdZdZdZdZdddd d d d d ZfdZ dZ dZ fdZ xZ S)rz Handles adoption of existing WordPress sites with imunify-security plugin. Adoption is a special case of installation where the site already has the plugin installed but is not tracked in our database. F site_foundzwp-plugin-adoptionzwp-plugin-adopt-skip-userz#Adopting imunify-security wp pluginz3Adopted imunify-security wp plugin on {count} sitesz"Found {count} site(s) for adoptionz3Failed to adopt plugin to site={site} error={error}zZAdoption of imunify-security wp plugin was cancelled. Plugin was adopted for {count} sitesz4Error occurred during plugin adoption. error={error}zSkipping adoption of WordPress plugin on {count} site(s) because they belong to user {user} and it is not possible to retrieve username for this user. Reason: {reason}r1ct||dtjtjD|_t |_dS)Nch|] }|j Sr+)r)r4rs r- z0WordPressSiteAdopter.__init__..Fs'" " " AI" " " r,)superr?rselectrexisting_docrootsrsites_to_insert)r>rPr __class__s r-r?zWordPressSiteAdopter.__init__Cs` u%%%" " ,3M4IJJ" " "  #uur,c|j|jvr"t||rt||n|j||j|dS)ak Record a successfully adopted site. For adoption, sites that already exist in the database (flagged as manually deleted) have their flag cleared. New sites are tracked for batch insert. Args: site: The WordPress site that was processed. version: The plugin version installed on the site. N)rr\rr&r]rr9rCs r-rDz+WordPressSiteAdopter._record_processed_siteLsp <41 1 1 ' - - - 3#D'222  $ $T * * * 4     r,c.t|jdS)a  Execute post-processing after all sites have been processed. For adoption, only insert sites that are not already in the database. Sites that were already in the database had their flags cleared during _record_processed_site. N)r$r]rFs r-rGz(WordPressSiteAdopter.run_post_processingcs t344444r,cKt|d{VsdStj|d{V}|std|dSdS)z Check if site is ready for adoption. Args: site: The WordPress site to check. Returns: bool: True if the site is ready for adoption, False otherwise. NFz2Plugin not installed on site %s, skipping adoptionT)rZrArrr^rv)r>rrr^s r-rAz"WordPressSiteAdopter.is_site_readymsWW**400000000 5!4T::::::::   NND   5tr,)rQrRrSrTrMrOrJrLrIr?rDrGrA __classcell__)r^s@r-rr%sN"O$I ;6I5F 3L 7H$%%%%%!!!.555r,r)rcr)jrTrgloggingrrrrrr collectionsrdistutils.versionrpathlibrdefence360agent.apir defence360agent.contracts.configrrNrr defence360agent.filesr defence360agent.sentryr r imavr imav.model.wordpressrrimav.wordpressrrimav.wordpress.constantsr(imav.malwarelib.plugins.schedule_watcherrimav.wordpress.utilsrrrrrrrrimav.wordpress.site_repositoryrrrrr r!r"r#r$r%r&imav.wordpress.proxy_authr' getLoggerrQr^COMPONENTS_DB_PATHrrr.r struct_passwdrCrZrirbrrmr|rrstrrrrintrrrrrrrrrrurwrboolrrrrr$r.r~rr+r,r-rysv* ######************ ('''''......66666666666666))))))))888888MMMMMM                                              @?????  8 $ $TJ '%&&& t (9 t     ;& ;6B ; ; ; ;F80A8888::d::::&777B!!! ! ! ! 3    G;G;G;T9F9999 ))#))))X";";";J$ $ $ P26;;#&v;;;;;<3DL3333lf"ut *TdTk0Utd{<%C2! !  ! !  !  !  ! ! ! ! Hf%fTfdffffRGGGT    "V"""""J' '$'' ''''T:::zppppppppf^^^^^1^^^^^r,