JFIF$        dd7 

Viewing File: /opt/imunify360/venv/lib/python3.11/site-packages/imav/wordpress/__pycache__/plugin.cpython-311.pyc

�

�?�����v�dZddlZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
ddlmZddl
mZddlZddlmZddlmZmZmZddlmZdd	lmZdd
lmZddlmZddlm Z dd
l!m"Z"ddl#m$Z$m%Z%m&Z&ddl'm(Z(ddl)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0ddl1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:ddl;m<Z<ej=e>��Z?ed��Z@dZAdZBd�ZCdeDdejEdeDfd�ZFdejEdefd�ZGdejHfd�ZIdFd eJfd!�ZKd"�ZLdeMfd#�ZNd$�ZOd%e"fd&�ZPd%e"deQfd'�ZRd(�ZSd)�ZT	dGd*eUe"fd+�ZVd,eJe"fd-�ZWd%e"d.eDfd/�ZXd0eDdeMfd1�ZYd2ed3eMdedzfd4�ZZd5edeDdzfd6�Z[d%e"dejEdefd7�Z\d2edeDdzfd8�Z]d2edeMfd9�Z^d%e"dejEd:eMd;eUd<eUddfd=�Z_d2ed>e`ddfd?�Zad@�ZbdA�Zcd%e"de`fdB�Zdd%e"dCeQde`fdD�ZedE�ZfdS)Hu

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 <https://www.gnu.org/licenses/>.

Copyright © 2019 Cloud Linux Software Inc.

This software is also available under ImunifyAV commercial license,
see <https://www.imunify360.com/legal/eula>
�N)�defaultdict)�LooseVersion)�Path)�
inactivity)�MalwareScanScheduleInterval�SystemConfig�ANTIVIRUS_MODE)�Index)�log_message)�	check_run)�files)�	Wordpress)�WPSite)�cli�	telemetry�PLUGIN_VERSION_FILE)�get_user_schedule_config)�build_command_for_user�calculate_next_scan_timestamp�$clear_get_cagefs_enabled_users_cache�
get_last_scan�get_malware_history�prepare_scan_data�!write_plugin_data_file_atomically)	�delete_site�get_outdated_sites�get_sites_for_user�get_sites_to_install�%get_sites_to_mark_as_manually_deleted�get_installed_sites�insert_installed_sites�mark_site_as_manually_deleted�update_site_version)�setup_site_authenticationzD/var/lib/cloudlinux-app-version-detector/components_versions.sqlite3zwp-rules.zip�VERSIONc�H�t��tj��dS)z#Clear all WordPress-related caches.N)rr�clear_get_content_dir_cache���J/opt/imunify360/venv/lib/python3.11/site-packages/imav/wordpress/plugin.py�clear_cachesr+Ts#��(�*�*�*��#�%�%�%�%�%r)�items�	user_info�returnc�����t|��}d�|D��}|D]D���fd�|D��}|r1t|t���}||�����E|S)Nc��i|]}|g��Sr(r()�.0�paths  r*�
<dictcomp>zsite_search.<locals>.<dictcomp>]s��
.�
.�
.�4�d�B�
.�
.�
.r)c�,��g|]}��|���|��Sr(r()r1r2�item�matchers  ��r*�
<listcomp>zsite_search.<locals>.<listcomp>`s*���M�M�M�4����t�9L�9L�M�$�M�M�Mr))�key)r�max�len�append)r,r-r6�
user_sites�result�matching_sites�most_specific_siter5s  `    @r*�site_searchr@Zs�����#�I�.�.�J�
.�
.�:�
.�
.�
.�F��4�4��M�M�M�M�M�:�M�M�M���	4�!$�^��!=�!=�!=���%�&�-�-�d�3�3�3���Mr)�admin_configc��:K�t||j���d{V��}|�dd��}t|j|��\}}}}d}	|tjkrt
||||��}	t|j��}
t|
|d���}||	|fS)N�	scan_datec�P�|ddko|d�|��S)N�
resource_type�file)�
startswith)r5r2s  r*�<lambda>z)_get_scan_data_for_user.<locals>.<lambda>�s-��4��0�F�:�*���L�#�#�D�)�)�r))	r�pw_name�getr�Interval�NONErrr@)�sinkr-rA�	last_scan�last_scan_time�interval�hour�day_of_month�day_of_week�next_scan_time�malware_history�malware_by_sites            r*�_get_scan_data_for_userrWjs�����$�D�)�*;�<�<�<�<�<�<�<�<�I��]�]�;��5�5�N�1I���<�1�1�-�H�d�L�+��N��8�=� � �6��d�L�+�
�
��
*�)�*;�<�<�O�"���	*�	*���O��>�?�:�:r)�	semaphorec���K�|4�d{V��	|�d{V��n4#t$r'}t�d|����Yd}~nd}~wwxYwddd���d{V��dS#1�d{V��swxYwYdS)NzTelemetry task failed: )�	Exception�logger�error)�cororX�es   r*�_send_telemetry_taskr_�s+�����8�8�8�8�8�8�8�8�	8��J�J�J�J�J�J�J�J���	8�	8�	8��L�L�6�1�6�6�7�7�7�7�7�7�7�7�����	8����8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8����8�8�8�8�8�8s5�A��A�
A�A�A�A�A�
A'�*A'�
�
coroutinesc����K�|sdStj|����fd�|D��}	tj|��d{V��dS#t$r(}t�d|����Yd}~dSd}~wwxYw)zK
    Process a list of telemetry coroutines with a concurrency limit.s
    Nc�T��g|]$}tjt|�������%Sr()�asyncio�create_taskr_)r1r]rXs  �r*r7z+process_telemetry_tasks.<locals>.<listcomp>�s?���
�
�
��	��0��y�A�A�B�B�
�
�
r)zSome telemetry tasks failed: )rd�	Semaphore�gatherrZr[r\)ra�concurrency�tasksr^rXs    @r*�process_telemetry_tasksrj�s�����������!�+�.�.�I�
�
�
�
��
�
�
�E�
:��n�e�$�$�$�$�$�$�$�$�$�$���:�:�:����8�Q�8�8�9�9�9�9�9�9�9�9�9�����:���s�A�
A3�A.�.A3c��x
K�t�d��t��}t��}t��}t��}t��}g}tj�d��5	t
��t��}|s2	t|��t|���d{V��ddd��dSt��}	tjtj
d���}	|	����d{V��t|	��}
n4#t $r'}t�d|��d}
Yd}~nd}~wwxYw|
st�d��|
r$t%|	��}||
d�}
t'|
��}nd}t)t*��}|D]"}||j�|���#|���D�]�\}}	t3j|��}|j}n<#t $r/}t9d	t;|��||d
�ddd
���Yd}~�Wd}~wwxYwt=|||���d{V��\}}}|D�]}}t?||���d{V��r�	tAj!|���d{V��}|st9dd|iddd����NtE|||||��}tG||���d{V��tI||||���d{V��tAj%|���d{V��|rtM|||||���d{V��tAj'|���d{V��}|s|�(|��n(|�(tSj*||����|�tWj,|d||�������K#t $r'}t�-d||��Yd}~��wd}~wwxYw���t�dt;|����|r(t�dt;|����|r(t�dt;|����nf#t\j/$r+t�dt;|����Yn-t $r!}t�-d|���d}~wwxYwt|��t|���d{V��n)#t|��t|���d{V��wxYw	ddd��n#1swxYwY|S)zLInstall the imunify-security plugin for all sites where it is not installed.z%Installing imunify-security wp pluginzwp-plugin-installationNF)�integrity_checkz>Failed to load wp-rules index: %s, skipping rules installationz<valid WordPress rules not found, skipping rules installation��version�rulesz�Skipping 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}��count�user�reason�warning�	wordpresszwp-plugin-install-skip-user��format_args�level�	component�fingerprintz:WordPress site is not accessible using WP CLI. site={site}�sitezwp-plugin-cli-not-accessible�installed_by_imunify�rM�eventr{rnz,Failed to install plugin to site=%s error=%rz0Installed imunify-security wp plugin on %d siteszFailed to authenticate %d sitesz&Failed to install wp-rules on %d siteszXInstallation imunify-security wp plugin was cancelled. Plugin was installed for %d sitesz3Error occurred during plugin installation. error=%r)0r[�info�setr�track�taskr+rr!rjrr
r
�WP_RULES�update�get_updated_wp_rules_datarZrt�get_wp_ruleset_version�_format_php_with_embedded_jsonr�list�uidr;r,�pwd�getpwuidrIrr:rW�remove_site_if_missingr�is_wordpress_installedr�update_scan_data_file�update_site_auth�plugin_install�update_wp_rules_for_site�get_plugin_version�addr�build_with_versionr�
send_eventr\rd�CancelledError)rM�	installed�
authenticated�rules_installed�failed_rules_updates�failed�telemetry_coros�
to_installrA�wp_rules_index�
wp_rules_datar^�wp_rules_version�ruleset_dict�wp_rules_php�
sites_by_userr{r��sitesr-�usernamer\rOrTrVr��	scan_datarns                            r*�install_everywherer��s�����
�K�K�7�8�8�8����I��E�E�M��e�e�O��5�5��
�U�U�F��O�	�	�	�	�7�	8�	8�t;�t;�s	;��N�N�N�-�/�/�J��
��V
#�9�-�-�-�)�/�:�:�:�:�:�:�:�:�:�it;�t;�t;�t;�t;�t;�t;�t;�(�>�>�L�
%�!&���N�E�"�"�"��%�+�+�-�-�-�-�-�-�-�-�-� 9�.� I� I�
�
���
%�
%�
%����$�����
!%�
�
�
�
�
�
�����

%����!�
����$����
�	
$�#9�.�#I�#I� �/�*� � �� >�l�K�K���#��(��-�-�M�"�
5�
5���d�h�'�.�.�t�4�4�4�4�,�1�1�3�3�d
�d
�
��U�� #��S� 1� 1�I�(�0�H�H�� �����D�
&)��Z�Z�$'�&+�%�%�
(�"-�$A�
�
�
�
��H�H�H�H���������*2��)�\���������	�"�"�#�
"�G�G�D�3�D�$�?�?�?�?�?�?�?�?�!� �D�#&�"<�T�"B�"B�B�B�B�B�B�B�/� 6�	%�'�!4�-3�T�N�&/�*5�,J�
����%�%6�*�*�$� �+�%�%�	�4�D�)�D�D�D�D�D�D�D�D�D�.� �)�]�F����������
"�0��6�6�6�6�6�6�6�6�6�(��":� $� )� ,� /� 4�#�#��������),�(>�t�(D�(D�"D�"D�"D�"D�"D�"D��&��%�M�M�$�/�/�/�/�%�M�M� &� 9�$�� H� H����
(�.�.�%�0�%)�&<�%)�(/�	��������%�������J� �!�����������������EG�P
�K�K�B��I���
�
�
��
����5���K�K����$�
����<��,�-�-�������%�	�	�	��K�K�.��I���
�
�
�
�
�
�	�	�	��L�L�E�u�
�
�
�
�����		����
#�9�-�-�-�)�/�:�:�:�:�:�:�:�:�:�:��
#�9�-�-�-�)�/�:�:�:�:�:�:�:�:�:�:����:�it;�t;�t;�t;�t;�t;�t;�t;�t;�t;�t;����t;�t;�t;�t;�l�s��T/�Q.�%$T/�Q.�%A	D/�.Q.�/
E �9E�Q.�E � BQ.�;H�Q.�
I�!%I�Q.�I�:Q.�2N;�=Q.�>C;N;�9Q.�;
O,	�O'	�!Q.�'O,	�,BQ.�-S9�.7S�%S9�'	S�0S�S�S9�%T/�9&T�T/�/T3�6T3c��	tj��s"t�dt��dStj�����S#t$r&}t�d|��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)r�existsr[r\�	read_text�striprZ)r^s r*�get_latest_plugin_versionr�ls���	�"�)�+�+�	��L�L�8�:M�
�
�
��4�"�,�.�.�4�4�6�6�6���������=�q�A�A�A��t�t�t�t�t��������s�3A�$A�
B�&B�Bc���K�t��}|st�d��dSt�d|��t	��}g}t
j�d��5	t|��}t�dt|���d���|s#	t|���d{V��ddd��dSt��}tt��}|D]"}||j�|���#|���D�]�\}}		t#j|��}
|
j}n3#t($r&}t�d||��Yd}~�Nd}~wwxYwt+||
|���d{V��\}
}}|	D�]t}t-||���d{V��r�	t/j|���d{V��st�d|���Qt3|
||||��}t5||���d{V��t/j|���d{V��|�|��t/j|���d{V��}|r{|j}t?||��|� |��}tC|��tC|��k}|�tEj#||rd	nd
||�������B#t($r'}t�d||��Yd}~��nd}~wwxYw���t�d
t|����nf#tHj%$r+t�dt|����Yn-t($r!}t�d|���d}~wwxYwt|���d{V��n#t|���d{V��wxYw	ddd��dS#1swxYwYdS)zFUpdate the imunify-security plugin on all sites where it is installed.z)Could not determine latest plugin versionNz<Updating imunify-security wp plugin to the latest version %szwp-plugin-updatezFound z outdated sites�+Failed to get username for uid=%d. error=%sz#WordPress site no longer exists: %s�downgraded_by_imunify�updated_by_imunifyr}z+Failed to update plugin on site=%s error=%sz.Updated imunify-security wp plugin on %d siteszRUpdate of imunify-security wp plugin was cancelled. Plugin was updated on %d sitesz-Error occurred during plugin update. error=%s)&r�r[r\rr�rr�r�rr:rjrrr�r�r;r,r�r�rIrZrWr�rr�rr��
plugin_updater�r�rnr#r�rrr�rdr�)rM�latest_version�updatedr��outdated_sitesrAr�r{r�r�r-r�r\rOrTrVr�rn�original_version�is_downgrades                    r*�update_everywherer�zs�����.�0�0�N������@�A�A�A���
�K�K�F�����
�e�e�G��O�	�	�	�	�1�	2�	2�y;�y;�x	;�/��?�?�N��K�K�E��^�!4�!4�E�E�E�F�F�F�!�
��d*�/�:�:�:�:�:�:�:�:�:�sy;�y;�y;�y;�y;�y;�y;�y;�(�>�>�L�(��-�-�M�&�
5�
5���d�h�'�.�.�t�4�4�4�4�,�1�1�3�3�T
�T
�
��U�	� #��S� 1� 1�I�(�0�H�H�� �����L�L�E������
�H�H�H�H�����
����2��)�\���������	�"�"�#�
"�?�?�D�3�D�$�?�?�?�?�?�?�?�?�!� �<�%(�%?��%E�%E�E�E�E�E�E�E�%�"�K�K� E�t����%�%6�*�*�$� �+�%�%�	�4�D�)�D�D�D�D�D�D�D�D�D�"�/��5�5�5�5�5�5�5�5�5����D�)�)�)�),�(>�t�(D�(D�"D�"D�"D�"D�"D�"D��"��/3�|�,�0��g�>�>�>�$(�#:�#:�7�#C�#C�D�,8� '�,�,� ,�-=� >� >�,?�L�
,�2�2� )� 4�)-�,8�)B�(?�(?�-A�)-�,3�	!"�	!"�	!"������%�������I� �!�����������������u?�B
�K�K�@��G���
�
�
�
���%�	�	�	��K�K�+��G���
�
�
�
�
�
�	�	�	��L�L�?��
�
�
�
�����		����*�/�:�:�:�:�:�:�:�:�:�:��)�/�:�:�:�:�:�:�:�:�:�:����:�sy;�y;�y;�y;�y;�y;�y;�y;�y;�y;�y;�y;����y;�y;�y;�y;�y;�y;s��9O-�;<M	�8O-�A!M	�<E�M	�
F�"F�>M	�F�:M	�5K*�8M	�9C/K*�(M	�*
L	�4L	�M	�L	�-M	�O�	7N,�O�	N,�N'�'N,�,O�/O-�O�O-�-O1�4O1r{c��K�tj|���d{V��}|���r'tjt
j|���d{V��dSdS�N)r�get_data_dirr�rd�	to_thread�shutil�rmtree)r{�data_dirs  r*�delete_plugin_filesr�sq�����%�d�+�+�+�+�+�+�+�+�H������9����
�x�8�8�8�8�8�8�8�8�8�8�8�9�9r)c��K�	tj|���d{V��}|s+t|tj��||���d{V��dStj|���d{V��}tj|���d{V��t
|���d{V��t|��}|�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.
    Nr�uninstalled_by_imunifyr}z"Failed to remove plugin from %s %s)r�is_plugin_installed�process_manually_deleted_plugin�timer��plugin_uninstallr�rr;rr�rZr[r\)r{rMr��is_installedrn�affectedr\s       r*�remove_from_single_siter�
sz����#� �4�T�:�:�:�:�:�:�:�:���	�1��d�i�k�k�4����
�
�
�
�
�
�
��1��.�t�4�4�4�4�4�4�4�4���"�4�(�(�(�(�(�(�(�(�(�"�$�'�'�'�'�'�'�'�'�'��t�$�$��	���� ��.���	
�
�
�	
�	
�	
�����������9�4��G�G�G��q�q�q�q�q��������s�AC�BC�
D�C<�<Dc
��K�t�d��g}d}tj�d��5	t��t
��}|D]m}	|tjt|||�����d{V��z
}�0#tj
$r,t�d|t|����Y�jwxYwn.#t$r!}t�
d|���d}~wwxYw	t�d|��t|���d{V��n5#t�d|��t|���d{V��wxYw	ddd��dS#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[rrr�r�r+r rd�shieldr�r�r:rZr\rj)rMr�r��	to_remover{r\s      r*�remove_all_installedr�6s5����
�K�K�5�6�6�6��O��H�	�	�	�	�2�	3�	3�;�;�	;��N�N�N�+�-�-�I�!�
�
��
��g�n�/��d�O�L�L�'�'�!�!�!�!�!�!��H�H���-�����K�K�H� ��I���	���������
���	�	�	��L�L�D�e�L�L�L������	����
� 
�K�K�B��
�
�
�*�/�:�:�:�:�:�:�:�:�:�:��

�K�K�B��
�
�
�*�/�:�:�:�:�:�:�:�:�:�:����:�9;�;�;�;�;�;�;�;�;�;�;�;����;�;�;�;�;�;sl�E2� C�#,B�C�8C�C�
C�C�D/�
C:�C5�5C:�:D/�>1E2�/2E!�!E2�2E6�9E6c��K�	t||��t|���d{V��|�tj|d||j�����dS#t$r'}t�d||��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
    N�removed_by_userr}z>Failed to process manually deleted plugin for site=%s error=%s)	r"r�r;rr�rnrZr[r\)r{�nowrMr�r\s     r*r�r�[s�����
�%�d�C�0�0�0�"�$�'�'�'�'�'�'�'�'�'�	���� ��'����	
�
�
�	
�	
�	
�	
�	
���
�
�
����L���	
�	
�	
�	
�	
�	
�	
�	
�	
�����
���s�AA�
B�%B�B�freshly_installed_sitesc��dK�g}	t|��}|r0tj��}|D]}t||||���d{V���n2#t$r%}t�d|��Yd}~nd}~wwxYw|rt
|���d{V��dSdS#|rt
|���d{V��wwxYw)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)rr�r�rZr[r\rj)rMr�r��to_mark_as_manually_removedr�r{r\s       r*�tidy_up_manually_deletedr��s>�����O�;�&K�#�'
�'
�#�'�	��)�+�+�C�3�
�
��5��#�t�_��������������F�F�F����=�u�E�E�E�E�E�E�E�E�����F�����	;�)�/�:�:�:�:�:�:�:�:�:�:�:�	;�	;��?�	;�)�/�:�:�:�:�:�:�:�:�:�:�	;���s0�AA�B�
A7�A2�-B�2A7�7B�B/r�c	��K�|sdSt��}tt��}|D]"}||j�|���#|���D]�\}}	t
j|��}|j}n3#t$r&}t�d||��Yd}~�Md}~wwxYwt|||���d{V��\}	}
}|D]v}t||���d{V��r�	t|	|
|||��}t||���d{V���D#t$r&}t�d||��Yd}~�od}~wwxYw��dS)Nr�z.Failed to update scan data on site=%s error=%s)rrr�r�r;r,r�r�rIrZr[r\rWr�rr�)
rMr�rAr�r{r�r-r�r\rOrTrVr�s
             r*�update_data_on_sitesr��s��������� �>�>�L� ��%�%�M��-�-���d�h��&�&�t�,�,�,�,�$�)�)�+�+�&�&�
��U�		���S�)�)�I� �(�H�H���	�	�	��L�L�=���
�
�
�

�H�H�H�H�����
	����*�$�	�<�H�H�H�H�H�H�H�H�		
�����	�	�D�+�D�$�7�7�7�7�7�7�7�7�
��
�-�"�"���#���	�,�D�)�<�<�<�<�<�<�<�<�<�<���
�
�
����D���������������
����	�%&�&s0�(B�
B4�B/�/B4�.)D�
E�"E�Er�c���K�tj|j��}|j}t	||���d{V��}|dz}t|��}t
|||j|���dS)N�
scan_data.php�r��gid)r�r�r��pw_gid�_ensure_site_data_directoryr�r)r{r�r-r�r��scan_data_path�php_contents       r*r�r��s�������T�X�&�&�I�
�
�C�1��y�A�A�A�A�A�A�A�A�H���/�N�1��;�;�K�%�����s������r)�datac�^�dtj|���dd��zdzS)al
    Format a dictionary as a PHP file that returns JSON-decoded data.

    This creates a WordPress-safe PHP file that:
    1. Checks if it's being included from WordPress (WPINC defined)
    2. Returns the data as a decoded JSON string

    Args:
        data: Dictionary to embed in the PHP file

    Returns:
        Formatted PHP file content as a string
    zB<?php
if ( ! defined( 'WPINC' ) ) {
	exit;
}
return json_decode( '�'z\'z
', true );)�json�dumps�replace)r�s r*r�r��s:��	 �
�*�T�
�
�
"�
"�3��
.�
.�	/��
	�r)�index�filenamec�4�|���D]N}|d|kr@t|�|d����}|���r|cS�Ot�d||�|j����dS)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
    �name�urlz%s not found in %sN)r,r�
localfilepathr�r[r\�
files_path�type)r�r�r5�	file_paths    r*�_find_file_in_indexr�s������
�
�!�!����<�8�#�#��U�0�0��e��=�=�>�>�I����!�!�
!� � � � ��
�L�L�%�x��1A�1A�%�*�1M�1M�N�N�N��4r)�zip_pathc���	tj|d��5}|�d��5}tj|��}ddd��n#1swxYwYddd��n#1swxYwYnJ#tjttjf$r&}t�	d|��Yd}~dSd}~wwxYwt|t��st�	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)�zipfile�ZipFile�open�yaml�	safe_load�
BadZipFile�KeyError�	YAMLErrorr[r\�
isinstance�dict)r��zip_file�	yaml_file�
rules_datar^s     r*�_extract_wp_rules_yamlr�sb���
�_�X�s�
+�
+�	7�x�����/�/�
7�9�!�^�I�6�6�
�
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�������C�Q�G�G�G��t�t�t�t�t����������j�$�'�'�����7��D�D�D��t��s]�A1�A%�A�A%�A	�A%�A	�A%�A1�%A)�)A1�,A)�-A1�1!B8�B3�3B8c���K�tj|���d{V��}tj�|��rtdt
|�����|���s�t|j	ddt
|��g��}t|���d{V��|���s#tdt
|��|j	���|�d��|S)a%
    Ensure the site's data directory exists with correct permissions.

    Args:
        site: WordPress site
        user_info: User information from pwd

    Returns:
        Path to data directory

    Raises:
        Exception: If the data directory is a symlink or cannot be created
    Nz)Data directory %s is a symlink, skipping.�mkdirz-pz)Failed to create directory %s for user %s��)rr��osr2�islinkrZ�strr�rrIr�chmod)r{r-r��commands    r*r�r�-s���� �%�d�+�+�+�+�+�+�+�+�H�	�w�~�~�h���
��7��X���
�
�	
��?�?����(���
�d�C��M�M�*�
�
���� � � � � � � � � ���� � �	��;��H�
�
��!���
�	���u�����Or)c���t|t��}|sdSt|��}|sdSt�d��t
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.yaml�pass�mode)r��WP_RULES_ZIP_FILENAMEr�r[rr	r,)r�r�r��cve�paramss     r*r�r�Xs���#�5�*?�@�@�H����t�(��1�1�J����t�
�K�K�3�4�4�4��$�%�+�+�-�-�	$�	$�K�C��#�F�6�N�N��r)c�"�t|t��}|sdS	|������}t�d|��|S#t$r&}t�d|��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)r��WP_RULES_VERSION_FILENAMEr�r�r[rrZr\)r��version_path�version_stringr^s    r*r�r�vs���'�u�.G�H�H�L����t��%�/�/�1�1�7�7�9�9�����<�n�M�M�M�����������6��:�:�:��t�t�t�t�t��������s�AA�
B�(B	�	Br�r�r�c��K�|j}	t||���d{V��}|dz}t|||j|���|�|��t
�d|j��dS#t$rA}|�|��t
�	d|j|��Yd}~dSd}~wwxYw)a=
    Deploy wp-rules to a single WordPress site and track the result.

    Args:
        site: WordPress site to deploy to
        user_info: User information from pwd
        wp_rules_php: Formatted PHP rules content
        updated: Set to add site to if successful
        failed: Set to add site to if failed
    Nz	rules.phpr�zUpdated wp-rules for site %sz)Failed to update wp-rules for site %s: %s)
r�r�rr�r�r[r�docrootrZr\)	r{r-r�r�r�r�r��
rules_pathr\s	         r*r�r��s����"�
�C�
�4�T�9�E�E�E�E�E�E�E�E����+�
�)���$�(��	
�	
�	
�	
�	���D�������2�D�L�A�A�A�A�A���
�
�
��
�
�4�������7��L��	
�	
�	
�	
�	
�	
�	
�	
�	
�����
���s�A(A5�5
C�?6B;�;C�
is_updatedc
��BK�tjst�d��dS|st�d��dSt�d��t	|��}|st�d��dSt
|��}||d�}t|��}t��}t��}tj
�d��5	t��t��}|s(t�d��	ddd��dStt��}	|D]"}
|	|
j�|
���#g}|	���D]�\}}
	t'j|��}|
D]*}
t+|
||||��}|�|���+�H#t,$rI}t/d	t1|
��||d
�ddd
���|
D]}
|�|
���Yd}~��d}~wwxYwd}t5dt1|��|��D]&}||||z�}t7j|ddi��d{V���'t�dt1|��t1|����nf#t6j$r+t�dt1|����Yn-t,$r!}t�d|���d}~wwxYwddd��dS#1swxYwYdS)a
    Hook that runs when wp-rules files are updated.
    Extracts wp-rules.yaml from wp-rules.zip and deploys to all active WordPress sites.

    Args:
        index: files.Index object for wp-rules
        is_updated: Whether files were actually updated
    zCwordpress security plugin not enabled, skipping wp-rules deploymentNz)wp-rules not updated, skipping deploymentz/Starting wp-rules deployment to WordPress sitesz,No valid wp-rules found, skipping deploymentrmzwp-rules-deploymentzNo active WordPress sites foundzySkipping wp-rules update for {count} site(s) belonging to user {user} because username retrieval failed. Reason: {reason}rprtruzwp-rules-update-skip-userrvr`r�return_exceptionsTz5wp-rules deployment complete. Updated: %d, Failed: %dz3wp-rules deployment was cancelled. Updated %d sitesz3Error occurred during wp-rules deployment. error=%s)r�SECURITY_PLUGIN_ENABLEDr[rr�r\r�r�r�rr�r�r+r rr�r�r;r,r�r�r�rZrr:r��rangerdrgr�)r�rr�r�r�r�r�r��installed_sitesr�r{rir�r�r-r�r\�max_concurrent�i�batchs                    r*�update_wp_rules_on_sitesr�s=�����,�����
�	
�	
�	
�	�������?�@�@�@���
�K�K�A�B�B�B�-�e�4�4�M������C�D�D�D���.�e�4�4��#����L�2�,�?�?�L��e�e�G�
�U�U�F�	�	�	�	�4�	5�	5�@�@�?	��N�N�N�2�3�3�O�"�
����=�>�>�>��@�@�@�@�@�@�@�@�(��-�-�M�'�
5�
5���d�h�'�.�.�t�4�4�4�4��E�+�1�1�3�3�
�
�
��U�� #��S� 1� 1�I� %�+�+��7� �)�\�7�F� � �����T�*�*�*�*�	+��
!�����4�&)��Z�Z�$'�&+�%�%�
(�"-�$?�����!&�)�)���
�
�4�(�(�(�(��H�H�H�H�����!����& �N��1�c�%�j�j�.�9�9�
E�
E���a�!�n�"4�4�5���n�e�D�t�D�D�D�D�D�D�D�D�D�D��K�K�G��G����F���
�
�
�
���%�	�	�	��K�K�E��G���
�
�
�
�
��	�	�	��L�L�E�u�
�
�
�
�����		����y@�@�@�@�@�@�@�@�@�@�@�@����@�@�@�@�@�@su�.L�08J!�6AJ!�AG
�J!�
H �?H�J!�H � BJ!� L�!7L�L�	L�#K?�?L�L�L�Lc
���K�t�d��t��}t��}tj�d��5	t
��t��}|s(t�d��	ddd��dStt��}|D]"}||j
�|���#g}|���D]�\}}	tj|��}|D])}t||||��}	|�|	���*�G#t $r/}
t#dt%|��||
d�ddd	�
��Yd}
~
�{d}
~
wwxYwd}t'dt%|��|��D]&}||||z�}
t)j|
d
di��d{V���'t�dt%|��t%|����nf#t(j$r+t�dt%|����Yn-t $r!}
t�d|
���d}
~
wwxYwddd��dS#1swxYwYdS)z7Update auth.php files for all existing WordPress sites.z4Updating auth.php files for existing WordPress siteszwp-auth-updatez"No installed WordPress sites foundNz�Skipping 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}rprtruzwp-plugin-auth-update-skip-userrvr`rrTz8Updated 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[rr�rr�r�r+r rr�r�r;r,r�r�r�rZrr:rrdrgr�r\)r�r�rr�r{rir�r�r-r�r\rrrs              r*�update_auth_everywherer se����
�K�K�F�G�G�G��e�e�G�
�U�U�F�	�	�	�	�/�	0�	0�@�@�?	��N�N�N�2�3�3�O�"�
����@�A�A�A��@�@�@�@�@�@�@�@�(��-�-�M�'�
5�
5���d�h�'�.�.�t�4�4�4�4��E�+�1�1�3�3�
�
�
��U�� #��S� 1� 1�I� %�+�+��/� �)�W�f� � �����T�*�*�*�*�	+��
!�����D�
&)��Z�Z�$'�&+�%�%�
(�"-�$E�
�
�
�
��H�H�H�H���������& �N��1�c�%�j�j�.�9�9�
E�
E���a�!�n�"4�4�5���n�e�D�t�D�D�D�D�D�D�D�D�D�D��K�K�J��G����F���
�
�
�
���%�	�	�	��K�K�(��G���
�
�
�
�
�
�	�	�	��L�L�F��N�N�N������	����}@�@�@�@�@�@�@�@�@�@�@�@����@�@�@�@�@�@su�I#�8G0� AG0�5AD6�5G0�6
E/�%E*�%G0�*E/�/BG0�/I#�07I�'I#�)	I�2I�I�I#�#I'�*I'c���K�	t||���d{V��|�|��dS#t$r<}|�|��t�d||��Yd}~dSd}~wwxYw)z/Process authentication setup for a single site.Nz*Failed to update auth for site=%s error=%s)r$r�rZr[r\)r{r-r�r�r\s     r*r�r�fs�����	
�'��i�8�8�8�8�8�8�8�8�8����D��������
�
�
��
�
�4�������8���	
�	
�	
�	
�	
�	
�	
�	
�	
�����
���s�+1�
A7�1A2�2A7c��*K�tj�|j��rdSt	|��}|dkr$tj|d||j����d{V��n1t�	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_removedr}Nz@Failed to delete missing site %s from database, no rows affectedz2Failed to delete missing site {site} from databaser{rtruzwp-plugin-site-delete-failedrvT)rr2�isdirrrrr�rnr[rtr)rMr{�rows_deleteds   r*r�r�ts�����
�w�}�}�T�\�"�"���u��t�$�$�L��a����"��^�$���
�
�
�	
�	
�	
�	
�	
�	
�	
�	
�	���N��	
�	
�	
�
	�@�����!�6�	
�	
�	
�	
��4r)�file_permissionsc���K�	tj|���d{V��}|���sdS|���jdz}|dkr|�d��dD]R}||z}|���r7|���jdz}||kr|�|���SdS#t$r'}t�d||��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
    NFi�r)r�zauth.phpTz.Failed to fix permissions for site=%s error=%s)	rr�r��stat�st_moderrZr[r\)r{r&r��current_dir_mode�	file_namer��current_file_moder\s        r*�fix_site_data_file_permissionsr-�s0������)�$�/�/�/�/�/�/�/�/����� � �	��5�$�=�=�?�?�2�U�:���u�$�$��N�N�5�!�!�!�6�	6�	6�I� �9�,�I����!�!�
6�$-�N�N�$4�$4�$<�u�$D�!�$�(8�8�8��O�O�$4�5�5�5���t���������<���	
�	
�	
�
�u�u�u�u�u�����
���s�.C�BC�
C3�C.�.C3c��\K�t��}t��}tj�d��5	t	��t��}|s	ddd��dSddlm}ddlm	}|��j
|j
krdnd}|D]\}t||���d{V��r�t||���d{V��}|r|�
|���G|�
|���]t�dt!|��t!|����nj#t"j$r+t�d	t!|����Yn1t&$r%}	t�d
|	��Yd}	~	nd}	~	wwxYwddd��dS#1swxYwYdS)z�
    Fix data file permissions for all WordPress sites with imunify-security plugin installed.

    Args:
        sink: The telemetry/event sink
    zwp-plugin-fix-permissionsNr)�HostingPanel)�Pleski �z=Fixed data file permissions for %d WordPress sites, %d failedzOFixing data file permissions was cancelled. Permissions were fixed for %d sitesz1Error occurred during permission fixing. error=%s)r�rr�r�r+r �+defence360agent.subsys.panels.hosting_panelr/�#defence360agent.subsys.panels.pleskr0�NAMEr�r-r�r[rr:rdr�rZr\)
rM�fixedr�rr/r0r&r{�successr\s
          r*�$fix_data_file_permissions_everywherer7�s�����
�E�E�E�
�U�U�F�	�	�	�	�:�	;�	;�0�0�/	��N�N�N�2�3�3�O�"�
��0�0�0�0�0�0�0�0�
�
�
�
�
�
�
B�A�A�A�A�A�&����,��
�:�:����
�
(�

%�

%��/��d�;�;�;�;�;�;�;�;��� >��*�!�!���������%��I�I�d�O�O�O�O��J�J�t�$�$�$�$��K�K���E�
�
��F���	
�
�
�
���%�	�	�	��K�K�&��E�
�
�
�
�
�
�
�
�	�	�	��L�L�C�U�
�
�
�
�
�
�
�
�����	����[0�0�0�0�0�0�0�0�0�0�0�0����0�0�0�0�0�0sN�F!�D*�,B=D*�)F!�*7F�!F!�#	F�,F�F!�F�F!�!F%�(F%)r`r�)g�__doc__rdr��loggingrr�r�r�r��collectionsr�distutils.versionr�pathlibrr��defence360agent.apir� defence360agent.contracts.configrrKrr	�defence360agent.filesr
�defence360agent.sentryr�defence360agent.utilsr�imavr
�imav.contracts.configr�imav.model.wordpressr�imav.wordpressrrr�(imav.malwarelib.plugins.schedule_watcherr�imav.wordpress.utilsrrrrrrr�imav.wordpress.site_repositoryrrrrrr r!r"r#�imav.wordpress.proxy_authr$�	getLogger�__name__r[�COMPONENTS_DB_PATHr
rr+r��
struct_passwdr@rWrfr_r�rjr�rr�r�r��intr�r�r�r�r�r�r�r�r�r�r�r�r�r��boolrr r�r�r-r7r(r)r*�<module>rPs1����*������������	�	�	�	�
�
�
�
�
�
�
�
���������#�#�#�#�#�#�*�*�*�*�*�*�����������*�*�*�*�*�*�����������
(�'�'�'�'�'�.�.�.�.�.�.�+�+�+�+�+�+�������+�+�+�+�+�+�'�'�'�'�'�'�>�>�>�>�>�>�>�>�>�>�M�M�M�M�M�M�������������������
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�@�?�?�?�?�?�	��	�8�	$�	$���T�J����
'��%��&�&�&�
�t�
��(9�
�t�
�
�
�
�  ;��&� ;�6B� ;� ;� ;� ;�F8��0A�8�8�8�8�:�:�d�:�:�:�:�&A�A�A�H�3�����G;�G;�G;�T9�F�9�9�9�9�)��)�#�)�)�)�)�X";�";�";�J$
�$
�$
�P26�;�;�#&�v�;�;�;�;�;�<3�D��L�3�3�3�3�l�f�������"���#�����2�u�����t������*�T��d�T�k�����0(�
�(� �.�(�	�(�(�(�(�V�U��t�d�{�����<�%��C�����2!
�
�!
�� �!
��!
��	!
�

�!
�
�
!
�!
�!
�!
�Hf�%�f�T�f�d�f�f�f�f�RG�G�G�T
�
�
�"�V�"��"�"�"�"�J'�
�'�$'�'�	�'�'�'�'�T:�:�:�:�:r)
Back to Directory  nL+D550H?Mx ,D"v]qv;6*Zqn)ZP0!1 A "#a$2Qr D8 a Ri[f\mIykIw0cuFcRı?lO7к_f˓[C$殷WF<_W ԣsKcëIzyQy/_LKℂ;C",pFA:/]=H  ~,ls/9ć:[=/#f;)x{ٛEQ )~ =𘙲r*2~ a _V=' kumFD}KYYC)({ *g&f`툪ry`=^cJ.I](*`wq1dđ#̩͑0;H]u搂@:~וKL Nsh}OIR*8:2 !lDJVo(3=M(zȰ+i*NAr6KnSl)!JJӁ* %݉?|D}d5:eP0R;{$X'xF@.ÊB {,WJuQɲRI;9QE琯62fT.DUJ;*cP A\ILNj!J۱+O\͔]ޒS߼Jȧc%ANolՎprULZԛerE2=XDXgVQeӓk yP7U*omQIs,K`)6\G3t?pgjrmۛجwluGtfh9uyP0D;Uڽ"OXlif$)&|ML0Zrm1[HXPlPR0'G=i2N+0e2]]9VTPO׮7h(F*癈'=QVZDF,d߬~TX G[`le69CR(!S2!P <0x<!1AQ "Raq02Br#SCTb ?Ζ"]mH5WR7k.ۛ!}Q~+yԏz|@T20S~Kek *zFf^2X*(@8r?CIuI|֓>^ExLgNUY+{.RѪ τV׸YTD I62'8Y27'\TP.6d&˦@Vqi|8-OΕ]ʔ U=TL8=;6c| !qfF3aů&~$l}'NWUs$Uk^SV:U# 6w++s&r+nڐ{@29 gL u"TÙM=6(^"7r}=6YݾlCuhquympǦ GjhsǜNlɻ}o7#S6aw4!OSrD57%|?x>L |/nD6?/8w#[)L7+6〼T ATg!%5MmZ/c-{1_Je"|^$'O&ޱմTrb$w)R$& N1EtdU3Uȉ1pM"N*(DNyd96.(jQ)X 5cQɎMyW?Q*!R>6=7)Xj5`J]e8%t!+'!1Q5 !1 AQaqё#2"0BRb?Gt^## .llQT $v,,m㵜5ubV =sY+@d{N! dnO<.-B;_wJt6;QJd.Qc%p{ 1,sNDdFHI0ГoXшe黅XۢF:)[FGXƹ/w_cMeD,ʡcc.WDtA$j@:) -# u c1<@ۗ9F)KJ-hpP]_x[qBlbpʖw q"LFGdƶ*s+ډ_Zc"?%t[IP 6J]#=ɺVvvCGsGh1 >)6|ey?Lӣm,4GWUi`]uJVoVDG< SB6ϏQ@ TiUlyOU0kfV~~}SZ@*WUUi##; s/[=!7}"WN]'(L! ~y5g9T̅JkbM' +s:S +B)v@Mj e Cf jE 0Y\QnzG1д~Wo{T9?`Rmyhsy3!HAD]mc1~2LSu7xT;j$`}4->L#vzŏILS ֭T{rjGKC;bpU=-`BsK.SFw4Mq]ZdHS0)tLg