HEX
Server: LiteSpeed
System: Linux catuipe.dhs10.info 4.18.0-553.111.1.lve.el8.x86_64 #1 SMP Fri Mar 13 13:42:17 UTC 2026 x86_64
User: paradatacom (1125)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: //usr/share/cagefs/__pycache__/cagefslib.cpython-311.opt-1.pyc
�

��lj�4��P�ddlmZddlmZddlmZddlmZddlZddlmZmZm	Z	m
Z
ddlmZej
��ddlTddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z dd	l!m"Z"m#Z#m$Z$m%Z%m&Z&dd
l!m'Z'm(Z(m)Z)m*Z*ddl!m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1ddl2Z2ddl3m4Z4m5Z5m6Z6dd
l7m8Z8m9Z9ddl:m;Z;ddl<m=Z=m>Z>m?Z?m@Z@ddlAmBZBddlCmDZDddlEmFZFddlGmHZHmIZIddlJmKZKmLZLddlMmNZNddlOmPZPddlQZQddlRmSZSddlTmUZUmVZVmWZWddl2mXZXmYZYddlZm[Z[Gd�de\��Z]Gd�de]��Z^dZ_d e_zZ`d!Zad"Zbd#Zcd$Zdd%ZedZfd&agd'Zhdaid(Zjd)Zkd*Zld+Zmd,Znd-Zod.Zpd/Zqd0emzZrd1Zsd2Ztd3Zud4�Zv�dd6�Zw�dd7�Zx�dd8�Zyd9�Zzd5e{fd:�Z|d5e{fd;�Z}�dd<�Z~d5e{fd=�Zd5e{fd>�Z�d?�Z�d@�Z�dA�Z�dB�Z�ej�d&fdC�Z�dD�Z�e���pekZ�gZ�dE�Z�dF�Z�dG�Z�dH�Z�d&Z�dIZ�dIZ�dIZ�dJ�Z�dKe�d5e�fdL�Z�ia��ddM�Z�dN�Z�dKe�d5dfdO�Z�dP�Z�dQ�Z�gZ�dR�Z�dS�Z�dT�Z��ddU�Z�dV�Z�dW�Z�dKe�d5e{fdX�Z�ia�dY�Z�dZ�Z�d[�Z�d\�Z�d]�Z�ia�d^�Z�d_�Z��dda�Z�ia��ddb�Z�dc�Z��ddd�Z��dde�Z�Gdf�dge\��Z�dhe�die�d5e
e�fdj�Z�die�d5e	e�fdk�Z��ddl�Z��d dm�Z�dn�Z�do�Z�dp�Z�ia�dq�Z��d!ds�Z��d"dt�Z��d#du�Z�dddrdrdgdfdv�Z�dw�Z��d$dx�Z�dy�Z�dz�Z�d{�Z�d|�Z�d}�Z�d~Z�dZ�iZ�iZ�d�e	e�d5e�fd��Z�d��Z�d��Zΐd%d��Z�d�d�d�d�d�d��a�d�Z�d�Z�e5d zd�zZ�d��Z�d&a�d��Z�d��Z�d��Z�d��Z�d��Zڐd%d��Z�d��Z�d�Zݐdd��Z�d��Z�dddrdrddgdfd��Z�d��Z�d&d��Z�d&d��Z�d&d��Z�d&d��Z�d��Z�d�e�d�e�d5e�fd��Z�dKed5ej�dzfd��Z�					�d'd�e�d�e�d�e{d�e{d�e�e�dzd�e{d�e�e�dzd5e�fd��Z�		�d(d�e�d�e�d�e{d�e{d5e�f
d��Z�d��Z�d��Z�d��Z�d��Z�d��Z�d)d��Z�d��Z�d��Z�d��Z�d��Z�d��Z�d��Z�dedfd��Z�d��Z�d��Z�d��Z��d*d��Z�d��Z�d��Z�d���Z�d%d„�ZdÄ�ZdĄ�Zd�adń�Zd�adƄ�Zd�a�d+dȄ�Z	dɄ�Z
dʄ�Zd�e�fd̄�Zd̈́�Z
dΐZdϐez�ZdАZdѐZd҄�Zi�adӄ�ZdԄ�ZdՄ�Z�d,dք�Zd�ad&�a�d-d�e�dzfd؄�Z�d.d�e�dڐee�e�e�fd�e�d�e�d�e�d�e�d�e�dzd�e�dzd�e�dzfd��Z	�d/d�e�d�e�d�e�d�e�d�e�d�ee�e�e�fdڐee�e�e�fd�e{d�e�d�e{d�e{d�e�dzd�e�dzfd��Z�dd�e�d�e�d�e�d�e�dzfd��Zd��Zd�a d�a!d�a"d�a#d��Z$�d.d�e�dzfd��Z%�d0d��Z&�d%d��Z'i�a(d��Z)d�Z*d��Z+d�e�d�e�d5ee�e�ffd���Z,d�e�d�e�d5ee�e�ffd���Z-d�e�d�e�d5ee�e�ffd���Z.d�e	e�d�e�d�e�d�ee�e�fd5df
d���Z/d���Z0d��Z1d���Z2d���Z3�d��Z4�d��Z5�d��Z6d�a7�d��Z8�d��Z9�d��Z:�d��Z;�d��Z<�d��Z=�d	��Z>�d
�Z?�d��Z@�d��ZA�d
��ZB�d�d��ZC�d��ZD�d1�d��ZE�d��ZF�d��ZG�d��ZH�d��ZI�d�d��ZJ�d��ZKe �jLd�����d����ZMdS(2�)�print_function)�absolute_import)�division)�unicode_literalsN)�AnyStr�Dict�List�Optional)�standard_library)�*)�read_file_secure�write_file_secure�
set_user_perm�open_file_not_symlink�
set_root_perm)�create_dir_secure�closefd�set_owner_dir_secure�set_perm_dir_secure)�	root_flag�print_error�
get_groups�clpwd�SILENT_FLAG�logging�get_perm)�CL_ALT_NAME�ETC_CL_ALT_PATH�BASEDIR)�get_linksafe_gid�get_user_prefix)�UserNotFoundError)�home_owned_by_other_user�make_userdir�	read_file�read_file_cached��is_ea4_enabled)�get_alt_dirs)�get_website_id)�byteify�
unicodeify)�ClPwd�	clcaptain)�Feature)�is_panel_feature_supported)�
sigterm_check)�ExternalProgramFailed�is_socket_file�mod_makedirs��get_boolean_param�CL_CONFIG_FILE)�loggerc��eZdZd�ZdS)�CageFSExceptionc�0�tj|g|�Ri|��dS�N)�	Exception�__init__)�self�args�kwargss   �]/builddir/build/BUILDROOT/cagefs-7.6.44-1.el8.cloudlinux.x86_64/usr/share/cagefs/cagefslib.pyr>zCageFSException.__init__Es)����4�1�$�1�1�1�&�1�1�1�1�1�N)�__name__�
__module__�__qualname__r>�rCrBr:r:Ds#������2�2�2�2�2rCr:c��eZdZdZdS)�SymlinkErrorz-Raised when symlink creation or repair fails.N)rDrErF�__doc__rGrCrBrIrIIs������7�7��DrCrIz.etc.version�/z/etc/cagefs/cagefs.iniz/etc/cl.selector/php.confz/usr/share/cagefsz/usr/share/cagefs/etc.newz/var/run/cagefsFz!/var/log/cagefs-php-opt-check.logz/etc/psa/psa.conf�/var/www/vhostsz/run/systemd/journal/dev-logz"/usr/share/cagefs-skeleton/dev/logz/dev/logz>/opt/cloudlinux/flags/available-flags.d/cagefs-no-dev-log.flagz</opt/cloudlinux/flags/enabled-flags.d/cagefs-no-dev-log.flagz/etc/sysconfig/syslogz -a z/etc/rsyslog.confz(/etc/rsyslog.d/cagefs-syslog-socket.confz/etc/rsyslog.d/schroot.confc��	tj|d��dS#t$r&t|d�����YdSwxYw)z�
    /bin/touch analog - update timestamp of a file if it exists
    or create a file otherwise
    :param fname: file path
    :type fname: string
    N�a)�os�utime�OSError�open�close)�fnames rB�touchrUus_��!�
�����������!�!�!��U�C����� � � � � � �!���s��,A	�A	�returnc���d�}tt��}t|��D]�\}}||�d��r�||�t
��dkr_||ddks||ddkr|||t
d��}|||<n|||t
d��}|||<n��t
t|d���td	��d
S)z_
    Add syslog socket into CageFS, add it to syslog config and restart
    syslog service
    c�2�|d|�|z||d�zS)z5
        Inserts new inside original at pos.
        NrG)�original�new�poss   rB�_insertz2_add_syslog_socket_for_syslog_pkg.<locals>._insert�s$������~��#�h�s�t�t�n�4�4rC�SYSLOGD_OPTIONS�������"�'T��make_backup�*/bin/systemctl restart syslog &> /dev/nullN)r%�SYSCONFIG_SYSLOG�	enumerate�
startswith�find�
CAGEFS_SOCKET�
write_file�
ExecuteSimple)r\�lines�i�_�tmps     rB�!_add_syslog_socket_for_syslog_pkgrp�s��
5�5�5�
�&�'�'�E��%� � �
�
���1���8���0�1�1�		��Q�x�}�}�]�+�+�r�1�1���8�B�<�3�&�&�%��(�2�,�#�*=�*=�!�'�%��(�M�2�>�>�C�"�E�!�H�H�!�'�%��(�M�2�>�>�C�"�E�!�H��E�		����D�9�9�9�9��>�?�?�?�?�?rCc�Z�dt�d�}tt��}t|��D]9\}}||�d��}|dvr|||d�||<n�:t
j�t��r`ttd��5}|�
��}ddd��n#1swxYwY||krtjt��tt|d���tt|gd���td	��dS)
za
    Add syslog socket into CageFS, add it to rsyslog config and restart
    rsyslog service
    z$AddUnixListenSocket �
z$ModLoad imuxsock)r^rN�rTrb�+/bin/systemctl restart rsyslog &> /dev/null)�
LOG_SOCKETr%�RSYSLOG_CONFrfrhrO�path�isfile�CHROOT_OLD_CONFrR�read�unlinkrj�CHROOT_CONFrk)�chroot_conf_contentrlrmrnr[�f�old_contents       rB�"_add_syslog_socket_for_rsyslog_pkgr��s}��
A�*�@�@�@���l�#�#�E��%� � �����1��A�h�m�m�/�0�0���g����Q�x����~�E�!�H��E��
�w�~�~�o�&�&�'�
�/�3�
'�
'�	#�1��&�&�(�(�K�	#�	#�	#�	#�	#�	#�	#�	#�	#�	#�	#����	#�	#�	#�	#��-�-�-��I�o�&�&�&���
������
��	�������
�?�@�@�@�@�@s�"C�C�
Cc��t��rt��dSt��r/t��rt��t	d��dSdSt
j�t��rt��dSt
j�t��rt��dSdS)z�
    Add cagefs skeleton syslog socket to syslog config file.
    Create .conf file for rsyslog
    Restart syslog/rsyslog service
    When cagefs-no-dev-log flag is enabled (CLOS-3846), do not add the socket
    and remove it from config if present.
    Nz/usr/share/cagefs/need.remount)�is_cagefs_no_dev_log_enabled�remove_syslog_socket�is_new_syslog_socket_used�is_old_syslog_socket_in_cagerUrOrwrxrerprvr�rGrCrB�add_syslog_socketr��s���$�%�%�������� �"�"�-�'�)�)�	4�
!�"�"�"�
�2�3�3�3�3�3�	4�	4�
����(�	)�	)�-�)�+�+�+�+�+�	�����	%�	%�-�*�,�,�,�,�,�-�-rCc	��tj�t��r�t	t��}t|��D]H\}}||�d��r(||�td��}|||<n�Itt|d���td��tj�t��rg	tjt��n;#t$r.}tdtdt|����Yd}~nd}~wwxYwtd	��dSdS)
zl
    Remove syslog socket info for cagefs from system syslog configs
    Restart syslog/rsyslog service
    r]�Trbrd�removing�:Nrt)rOrwrxrer%rfrg�replacerirjrkr|r{rQr�str)rlrmrnro�es     rBr�r��sY��

�w�~�~�&�'�'�D��*�+�+���e�$�$�	�	�D�A�q��Q�x�"�"�#4�5�5�
��A�h�&�&�}�b�9�9����a����
�
	����	
�	
�	
�	
�
	�B�C�C�C�	�w�~�~�k�"�"�E�	>��I�k�"�"�"�"���	>�	>�	>��
�K��c�!�f�f�=�=�=�=�=�=�=�=�����	>����	�C�D�D�D�D�D�
E�Es�C6�6
D.�$D)�)D.c�J�tj�t��S)z]
    Return True if cagefs-no-dev-log feature is available on this platform (CLOS-3846).
    )rOrwrx� CAGEFS_NO_DEV_LOG_AVAILABLE_FLAGrGrCrB�&is_cagefs_no_dev_log_feature_availabler��s���7�>�>�:�;�;�;rCc�J�tj�t��S)z�
    Return True if cagefs-no-dev-log flag is enabled (CLOS-3846).
    When enabled, /dev/log is not created in CageFS user skeleton.
    )rOrw�lexists�CAGEFS_NO_DEV_LOG_FLAGrGrCrBr�r�s��
�7�?�?�1�2�2�2rCc�z�tj�t��rt	t��dSdS)zv
    Remove /dev/log from CageFS skeleton if present (e.g. after enabling
    cagefs-no-dev-log flag). CLOS-3846.
    N)rOrwr�rur{rGrCrB�remove_dev_log_from_skeletonr�s8��

�w���z�"�"���z�������rCc���tj�t��o@tj�t��t
kot
t
��S)z�
    File `/dev/log` is symlink to socket `/run/systemd/journal/dev-log` if
    server uses the newer version of syslog socket
    )rOrw�islink�DEV_LOG_SOCKET�realpath�SYSTEMD_JOURNAL_SOCKETr3rGrCrBr�r�sI��
�7�>�>�.�)�)�/�
�����(�(�,B�B�/��-�.�.�/rCc�*�tt��S)zB
    Return True if CageFS has into self an old syslog socket
    )r3rurGrCrBr�r�s���*�%�%�%rCc���	t|��}n#t$rd}YnwxYw	t|��}n#t$rd}YnwxYw|dks|dkr|dkr||kS||kS|dkr||kS||kS)Nr^r)�int�
ValueError)�txt1�txt2�op�i1�i2s     rB�getItemr�%s����
��Y�Y��������
���������
��Y�Y��������
��������	�R�x�x�2��8�8�
��7�7��$�;���$�;��
��7�7���7�N���7�Ns��!�!�5�A�Ac��|�d��}|�d��}t|��t|��krt|��}nt|��}t|��D]B}t||||d��rdSt||||d��rdS�Ct|��t|��krdSt|��t|��krdSdS)N�.r�r^)�split�len�ranger�)�base�test�lnrms    rB�
verComparer�<s����:�:�c�?�?�D��:�:�c�?�?�D��D�	�	�C��I�I���
��Y�Y���
��Y�Y��
�2�Y�Y�����4��7�D��G�Q�'�'�	��1�1��4��7�D��G�Q�'�'�	��2�2�	�
�4�y�y�C��I�I����q�	�T���S��Y�Y�	�	��q��rrCc�R�	tj|��dS#t$rYdSwxYwr<)rOr{rQ�rws rBr{r{Os:��
�
�	�$��������
�
�
����
���s��
&�&c���t}tst��\}}t��	t�>t	jd��}t
tdd��at	j|��t�tj	�
���d��dz|zdz��|r?t�d��|D]"}t�d|zdz���#|r?t�d	��|D]"}t�d|zdz���#|r?t�d
��|D]"}t�d|zdz���#nU#ttf$rA}	tdtt|	����t!jd��Yd}	~	nd}	~	wwxYw|st%||��dSdS)N�?rNr�z%Y.%m.%d %H:%M:%S�: rrz8 - The following options have been disabled as unknown:
z     * zF - The following options have been disabled as have incorrect values:
zI - The following options have been disabled as invalid (have no values):
zwriting to )rrr�php_log_optrO�umaskrR�PHP_OPTIONS_LOGFILE�write�datetime�now�strftimerQ�IOErrorrr��sys�exitr)
�msg�unknown_options_list�invalid_values_options_list�invalid_options_list�root_flag_saved�uid�gid�umask_saved�optionr�s
          rB�php_options_log_writer�Ws	���O����:�:���S���������(�4�.�.�K��2�C��;�;�K��H�[�!�!�!����(�+�/�/�1�1�:�:�;N�O�O�RV�V�Y\�\�_c�c�d�d�d��	=����Y�Z�Z�Z�.�
=�
=���!�!�)�f�"4�t�";�<�<�<�<�&�	=����g�h�h�h�5�
=�
=���!�!�)�f�"4�t�";�<�<�<�<��	=����j�k�k�k�.�
=�
=���!�!�)�f�"4�t�";�<�<�<�<����W������M�#6��A���?�?�?��������������������� ��c�3������ � s�EF
�
G�7G�Gc�z�tj��\}}}t|j��}t|��}|sO|�d|��}|�dd��}tj||��t
|tj���dS	ddl}|���}	n##t$rtj��}	YnwxYwtj|||d|	��|	�
���d��D]2}
tj||
��t
|
tj����3dS)Nr��Errno�Err code)�filerrr)r��exc_infor��	__class__r��syslog�print�stderr�StringIO�ImportError�io�	traceback�print_exception�getvaluer�)�level�includetraceback�exctype�	exception�exctraceback�excclass�messager�r��excfd�lines           rBr�r�wsL��'*�|�~�~�$�G�Y���9�&�'�'�H��)�n�n�G��)�"�(�(�G�G�,���k�k�'�:�.�.���
�e�S�!�!�!�
�c��
�#�#�#�#�#�#�	(��O�O�O��%�%�'�'�E�E���	"�	"�	"��K�M�M�E�E�E�	"����	�!�'�9�l�D�%�P�P�P��N�N�$�$�*�*�4�0�0�	)�	)�D��M�%��&�&�&��$�S�Z�(�(�(�(�(�	)�	)s�
B&�&C�Cc�L�	ttd��5}|���}ddd��n#1swxYwYn#t$rYdSwxYwt	jd|tj��}|sdS|���d�d��S)N�rtz^HTTPD_VHOSTS_D[ \t]+(\S+)$rrK)	rR�GLOBAL_PLESK_CFGrzr=�re�search�	MULTILINE�groups�rstrip)r~�data�matchs   rB�_read_vhosts_dirr��s����
�"�D�
)�
)�	�Q��6�6�8�8�D�	�	�	�	�	�	�	�	�	�	�	����	�	�	�	��������t�t������I�4�d�B�L�I�I�E����t��<�<�>�>�!��#�#�C�(�(�(s-�A�8�A�<�A�<�A�
A�Ac��t|��}t|��}tD])}t|��}|�|��rdS�*dS�NTF)�
strip_path�addslash�
black_listrg)�_file�rfilerws   rB�is_in_black_listr��s[���u���E��U�O�O�E�������~�~�����D�!�!�	��4�4�	��5rCc�<�tj��jjS)z*Returns the current line number in program)�inspect�currentframe�f_back�f_linenorGrCrB�linenor��s����!�!�(�1�1rCc�>�|dkr|ddkr
|dd�S|S)Nr�r^rKrG��_dirs rB�
stripslashr��s+���r�z�z���H��O�O�����9���KrCc�8�|dkrdS|ddkr|�d�S|S)Nr�rKr^rGr�s rBr�r��s.���r�z�z��s��R��C���������KrCr�c�2�t��tjd��}ttd��}|D]}|�d|z���|���tj|��tjtd��dS)N��wz%s
�)r1rOr�rR�FUSE_SAFE_LISTr�rS�chmod)�	safe_listr�r��filenames    rB�save_etc_safe_listr�s����O�O�O��(�4�.�.�K����%�%�E��'�'��
���F�X�%�&�&�&�&�	�K�K�M�M�M��H�[�����H�^�U�#�#�#�#�#rCrwc�>�|�t��}|pdS)zB
    Remove leading path to skeleton from the specified path.
    rK)�removeprefix�SKELETONr�s rBr�r��s!�����X�&�&�D��;�3�rCc�x�tj|��D]�}tj�||��}|}|dkr|t	|��d�}|dkr||z}d||<tj�|��r4|stj�|��st||||�����dS)Nr���cut_path�add_path)rO�listdirrw�joinr��isdirr��add_tree_to_list)�src�_list�follow_symlinksrr
�name�srcnamerws        rBrr�s����
�3���	S�	S���'�,�,�s�D�)�)�����t�����H�
�
���'�D��t����d�?�D���d��
�7�=�=��!�!�	S��	S�r�w�~�~�g�?V�?V�	S��W�e�h��R�R�R�R��	S�	SrCc���tj�tj�tj�|����tj�|����Sr<)rOrwrr��dirname�basenamer�s rB�
get_real_pathr�sG��
�7�<�<���(�(������)>�)>�?�?���AQ�AQ�RV�AW�AW�X�X�XrCc�.�|�d��sdSt|d���rdS|�d��s|�d��rdS|dvrdStj�|��sdSt
|z}tj�|��sKtj�|��r>ttj�	|����rt||��dSt||d��dS)N�/etc/T)�etcz/etc/cl.php.d/�/etc/cl.selector/)�/etc/passwd�
/etc/group�/etc/shadowz
/etc/cl.php.dz/etc/cl.selector)rg�move_to_alternativesrOrw�exists�ETC_TEMPLATE_NEW_DIRrxr��is_path_read_only_mountedr��	copy_file�copytree)rw�destinations  rB�copy2etcr)�s���?�?�7�#�#�����D�d�+�+�+�������'�(�(��D�O�O�<O�,P�,P�����`�`�`���
�7�>�>�$������&��-�K�	�w�~�~�d���*�����t� 4� 4�*�$=�b�g�>N�>N�t�>T�>T�$U�$U�*��$��$�$�$�$�$���{�D�)�)�)�)�)rCc�\�t|��}t|��}t|��|�d��ri|tvr^t
j�|��r?dt|<t
j�|��rt|td��dSdS)Nrr�TF)
r�r�r)rg�
white_listrOrwr#rrr�s rB�add_to_white_listr,s����d���D��d���D��T�N�N�N����w�����
�"�"�����t�(<�(<�"� �J�t���w�}�}�T�"�"�
9� ��z�4�8�8�8��t��5rCc��|D]�}t|��}t|��}t|��t|��}||krt|��tj�|��}||kr||krt|��tj�|��r#t	j|��}t|����dSr<)	r�r�r)rrOrwr�r��readlink)�pathsrw�path2�path3�linktos     rB�copy_to_etcr3)s����
�
���$�����$����������d�#�#���D�=�=��U�O�O�O��� � ��&�&���D�=�=�U�e�^�^��U�O�O�O�
�7�>�>�$���	��[��&�&�F��V�����
�
rCc�,�|�|��Sr<�rg�rw�mounts  rB�$path_includes_mount_point_comparatorr8@s�����D�!�!�!rCc�,�|�|��Sr<r5r6s  rB�path_is_mounted_comparatorr:Cs���?�?�5�!�!�!rCc�B�t||��pt||��Sr<)r8r:r6s  rB�mounts_are_found_comparatorr<Fs$��/��e�<�<�g�@Z�[_�af�@g�@g�grCc�>�|�t}t|��}t|��}|�d��s|�d��rdS|D]F}|dkr>|ddkr2|���}t|��}|||��rdS�GdS)Nrz	/var/log/Tr�rrKF)�mountsr�r�rgr�)rw�
comparator�mounts_listr�s    rB�mounts_are_foundrAKs��������d���D��D�>�>�D����w����4�?�?�;�#?�#?���t������2�:�:�$�q�'�S�.�.��;�;�=�=�D��D�>�>�D��z�$��%�%�
��t�t���5rCc�,�t|t��Sr<)rAr:r�s rB�path_is_mountedrC_s���D�"<�=�=�=rCc�,�t|t��Sr<)rAr8r�s rB�path_includes_mount_pointrEes���D�"F�G�G�GrCc�Z�ddlm}|��j}t|t|���S)Nr��MountpointConfig)r@)�	cagefsctlrH�read_only_mountsrAr:)rwrHrJs   rBr%r%isE��*�*�*�*�*�*�'�'�)�)�:���D�6�(8�:�:�:�:rCc��|t|<dSr<)�	libs_list)�binary�libss  rB�add_libs_to_listrOws���I�f���rCc�@�	t|S#t$rYdSwxYwr<�rL�KeyError�rMs rB�get_libs_from_listrT|s4����� � �������t�t����s��
�c�:�	t|=dS#t$rYdSwxYwr<rQrSs rB�del_libs_from_listrV�s7��
��f������
�
�
����
������
�c��t��	tjd��}t|d��}t	jt
t��|d���|���tj|��tj	|d��dS#t$r}td|d|��Yd}~dSd}~wwxYw)Nr��wb�)�protocolrzwhile saving�-)r1rOr�rR�pickle�dumpr+rLrSrr=r)rr�r��errs    rB�	save_libsr`�s����O�O�O�8��h�t�n�n���X�t�$�$����G�I�&�&���:�:�:�:�
���
�
�
�
������
���5�!�!�!�!�!���8�8�8��N�H�c�3�7�7�7�7�7�7�7�7�7�����8���s�B
B�
C�&B>�>Cc�N�tj�|��r�	t|d��}t	tj|tj�������a	|�
��dS#t$r}td|d|��Yd}~dSd}~wwxYwdS)N�rb)�encoding�loadingr\)
rOrwrxrRr,r]�load�locale�getpreferredencodingrLrSr=r)rr�r_s   rB�	load_libsrh�s���	�w�~�~�h���7�	7���4�(�(�E�"�6�;�u�v�?Z�?\�?\�#]�#]�#]�^�^�I��K�K�M�M�M�M�M���	7�	7�	7��	�8�S�#�6�6�6�6�6�6�6�6�6�����	7����7�7s�AA;�;
B"�B�B"c�n�t|��}t|��}t|��}|tvSr<)r�r�r�
files_listr�s rB�path_is_in_listrk�s4���d���D��d���D�����D��:��rCc���trt|��rdSt|��}tj�|��r$t
|��std|d|d��dSdSdS)N�
Error in liner�zis not in list)�debug_optionrCr�rOrwr�rkr)rw�linenums  rB�check_errorrp�s�����_�T�2�2�����d���D�	�w���t���P��t�$�$�	P����$��>N�O�O�O�O�O�P�P�	P�	PrCTc�,�t|��}tr5t|��}||kr tdt	��d|d|��t
j�|��r�t|��}|tvrbdt|<|rXt
j�
|��r;t
j�|��st|td��dSdSdSdSdStr tdt	��d|��dSdS)Nrmr��!=r�Fr�zpath does not exist:)
r�rnrrr�rOrwr�r�rjrr�r)rw�add_tree�rpaths   rB�add_to_listru�s)���d���D��L��d�#�#���5�=�=������4��t�U�K�K�K�	�w���t���
H��$�����z�!�!� �J�t���
:�B�G�M�M�$�/�/�
:������9M�9M�
:� ��z�5�9�9�9�9�9�"�!�
:�
:�
:�
:�
:�
:��	H������*@�$�G�G�G�G�G�	H�	HrCc��|stj|��S	t|}n.#t$r!tj|��xt|<}YnwxYw|Sr<)rO�lstat�
stat_cacherR)rw�	use_cache�ress   rB�cached_lstatr{�sd�����x��~�~��0��������0�0�0�!#��$���/�
�4��3�3�3�0�����Js�
&�(A�Ac�:�	t|=dS#t$rYdSwxYwr<)rxrRr�s rB�clear_stat_cacher}�s7��
��t������
�
�
����
���rWc���|dkrt||���}|dkrt||���}tj|tj��tj|tj��krdStj|tj��rFt	j|��}t	j|��}|rt
||��}||kS||kS|tj}	|tj}
|	tjztjz}	|
tjztjz}
|	|
krdS|tj	|tj	ksr|tj
|tj
ksL|tj|tjks&|tj|tjkrdSdS)N�ryFT)
r{�stat�S_ISLNK�ST_MODErOr.�get_relative_path�S_ISUID�S_ISGID�ST_MTIME�ST_SIZE�ST_UID�ST_GID)�fileA�fileB�sbA�sbBry�relative_symlinks�	realfileA�	realfileB�
relative_path�modeA�modeBs           rB�is_same_metadatar��s����T�	�	��5�I�6�6�6���T�	�	��5�I�6�6�6����S���&�'�'�4�<��D�L�8I�+J�+J�J�J��u���S���&�'�'�&��K��&�&�	��K��&�&�	��	.�-�i��?�?�M��
�-�-��I�%�%�����E�����E��d�l�]�
"�t�|�m�3�E�
�d�l�]�
"�t�|�m�3�E�
��~�~��u�	�D�M��c�$�-�0�0�0�c�$�,�6G�3�t�|�K\�6\�6\��D�K�(�C���,<�<�<�#�d�k�BR�VY�Z^�Ze�Vf�Bf�Bf��u��4rCc�t�	t||||||���S#t$r}|jdkcYd}~Sd}~wwxYw)z�
    Returns: True if update of "injail" file is needed
             False if update is NOT needed (file in jail has same metadata)
    )r�r�ryr�rZN)r�rQ�errno)rY�injail�origstatbuf�
injailstatbufryr�r�s       rB�is_update_neededr�sp��
�#�H�f�+�=�.7�K\�^�^�^�^�	^��������1���������������s��
7�
2�7�7c��eZdZdS)�StaticallyLinkedErrorN)rDrErFrGrCrBr�r�s�������DrCr�r��
executablec��d|vrdS|���}|std|dd���dS|dd�ddgks|dd�|dd	�zgd
�krt���|ddvs#t|��d	kr|dd	�dd
gkrdSt|��dkrd}||vr|n|d}nHt|��dkr|dddkr	|d}ntd|dd���dStj�|��std|d|��dS|S)Nz no version information availablezfailed to parse ldd outputr^rrZ�
statically�linkedr��)�not�dynamicr�)zlinux-gate.so.1zlinux-vdso.so.1r��found�z/lib64/ld-linux-x86-64.so.2rKz ldd returns non existing library�for)r�rr�r�rOrwr#)r�r��splitted�dynamic_linker�lib_paths     rB�_parse_lib_pathr�s��)�T�1�1����z�z�|�|�H����0�$�s��s�)�<�<�<�����1��
�,��1�1�1���1��
���1��
�-�1Q�1Q�1Q�Q�Q�#�%�%�%���{�<�<�<��H�
�
��"�"�x��!��}���8H�'H�'H���
�8�}�}����7��%3�x�%?�%?�>�>�X�a�[���	�X���!�	�	����A��#� 5� 5��A�;����0�$�s��s�)�<�<�<���
�7�>�>�(�#�#���6��%��T�T�T����OrCc	��ddl}g}	t|d��}|�d|�d����d}|���n	#|cYSxYw|dkr|Sd}tj||gdt
jt
jt
jd	d	�
��}|j�	��D]<}	t||��}n#t$rYnwxYw|�|�|���=|S)z6
    Returns list of libraries for the executable
    rNrbz<Ir�iELFz/usr/bin/lddFT)�shell�stdin�stdoutr��	close_fds�text)
�structrR�unpackrzrS�
subprocess�Popen�PIPEr��	readlinesr�r��append)	r�r��retvalr~�	signature�ldd_path�pr�r�s	         rB�get_ldd_libsr�Bs,���M�M�M�
�F����T�"�"���M�M�$����q�	�	�2�2�1�5�	�	���	�	�	�	����
�
�
�����J����
��H�	��(�J�/�u�)��z�� *��4�d�	L�	L�	L�A���"�"�$�$�$�$��	�&�t�Z�8�8�H�H��$�	�	�	��E�E�	�������M�M�(�#�#�#���Ms�AA�A"�C�
C%�$C%c�&�|dkrdSt|��}d}|s|d}|dd�}d}d}|D�]=}tj�||��}t	|��}tj|j��r�|dz
}tj|��}	|	ddkr#tj�	||	z��}��tj�	tj�tj�
|��|	����}
t|��dkr;|
dt|���|kr td|
d��td���|
}��?tj�||��S)	NrKr�r^rr��symlink � points outside jail, ABORT�Symlink points outside jail)�
split_pathrOrwrr{r�r��st_moder.�normpathrr�rr=)rw�chroot�include_file�spathr�ret�
doscounter�entry�sbr�ros           rB�resolve_realpathr�qsj���c�	�	��s��t���E��H�����9���c�r�c�
��

�C��J������g�l�l�3�u�%�%��
�#�
�
���L���$�$�
	���M�J��{�3�'�'�H����S� � ��g�&�&�v�h��7�7����g�&�&�r�w�|�|�B�G�O�O�C�4H�4H��'R�'R�S�S����K�K��M�M�c�,�3�v�;�;�,�&7��&?�&?��
�C�1N�O�O�O�#�$A�B�B�B����
�7�<�<��H�%�%�%rCc�(�tj|��}tj|tj��}|sS|tjtjzzr7t
d|zt|��|tjztjz}tj||tj	|tj
f��|r6tj||tj|tj
��tj||��dS)Nz,removing setuid and setgid permissions from )rOr��S_IMODEr�r�r�rrrP�ST_ATIMEr��chownr�r�r)r�dst�
be_verbose�
allow_suid�copy_ownership�sbuf�modes       rB�copy_time_and_permissionsr��s���
�7�3�<�<�D��<��T�\�*�+�+�D��:��D�L�4�<�/�0�	:��B�3�F��U_�`�`�`��D�L�=�(�T�\�M�9�D��H�S�4��
�&��T�]�(;�<�=�=�=��<�
���d�4�;�'��d�k�):�;�;�;��H�S�$�����rCc��tj�|��}t|d��5}	tj|�����}n#t$rd}YnwxYw|�h|rf	tj|d���}n#t$rd}YnwxYw|�:|j|jkr*|j	|j	krtj|�d|�d����tjtj
ztjztjztjz}tj||d��}	tj|dd	�
��5}tj||��ddd��n#1swxYwYn7#t&$r*|s&	tj|��n#t$rYnwxYw�wxYwddd��dS#1swxYwYdS)a:
    F-04 (CLOS-5942) DiD: create the destination with restrictive mode
    (0o600) from birth, then stream source bytes into it via a private
    fd, so the file is never observable at a permissive mode. Skeleton
    rebuild paths (cagefsctl update_cagefs) run under umask(0), which
    used to let a plain shutil.copyfile expose the destination as 0666
    for the window between create and the later chmod. The final mode
    and ownership are applied by the caller through
    copy_time_and_permissions() after this returns, so the observable
    mode transitions 0o600 -> real-mode without ever passing through
    world-writable state.

    O_NOFOLLOW guards against a symlink swap between the pre-copy
    unlink and this create. O_CLOEXEC keeps the fd from leaking to any
    subprocess that runs concurrently with the rebuild.

    Ordering (post-review Bugbot HIGH on !203): open ``src`` first, so a
    missing / unreadable source raises before we touch ``dst``. Matches
    the legacy ``shutil.copyfile`` contract that a source open failure
    leaves an existing destination untouched. Failure cleanup only
    unlinks ``dst`` if we created it (i.e. it did not pre-exist) - an
    O_TRUNC of a previously good destination must not become a delete
    on mid-stream failure.

    Same-inode guard (post-review Bugbot HIGH on !203): shutil.copyfile
    raises SameFileError when src and dst point to the same inode. This
    helper is used by copy_with_permissions() after os.link() fails
    (see the hardlink-fallback branch at line 1107); if that link
    already exists as a hardlink between the two paths, opening dst
    with O_TRUNC would zero out the shared inode - which is also the
    host file - before we read a byte of src. Compare fstat on the
    resolved paths and skip the copy when they refer to the same
    inode.
    rbNF)rz and z are the same filerrYT)r)rOrwr�rR�fstat�filenorQr��st_dev�st_ino�shutil�
SameFileError�O_CREAT�O_WRONLY�O_TRUNC�
O_NOFOLLOW�	O_CLOEXEC�fdopen�copyfileobj�
BaseExceptionr{)	rr��dst_pre_existed�src_f�src_st�dst_st�flags�dst_fd�dst_fs	         rB�_atomic_copy_privater��ss��F�g�o�o�c�*�*�O�	
�c�4���)�E�	��X�e�l�l�n�n�-�-�F�F���	�	�	��F�F�F�	������/��
����e�<�<�<�����
�
�
�����
�����"��
���6�6��
���6�6��*�58�S�S�#�#�#�>�@�@�@��
�R�[�(�2�:�5��
�E���T�����e�U�+�+��	���6�4��6�6�6�
1�%��"�5�%�0�0�0�
1�
1�
1�
1�
1�
1�
1�
1�
1�
1�
1����
1�
1�
1�
1����	�	�	�#�
���I�c�N�N�N�N�������D������	����=)�)�)�)�)�)�)�)�)�)�)�)����)�)�)�)�)�)s��F5�&A�F5�A(�%F5�'A(�(F5�0B�F5�B�F5�B�BF5�,E1�E%�E1�%E)	�)E1�,E)	�-E1�0F5�1F%�>F�F%�
F �F%�F � F%�%F5�5F9�<F9c�l�|�d��}g}|D]}|r|�|���|S�NrK)r�r�)rwr�rz�items    rBr�r��sE���J�J�s�O�O�E�
�C������	��J�J�t������JrCc�N�t|��dkrdSd}|D]
}|d|zz
}�|S)NrrKr�)r�)r�r�r�s   rB�	join_pathr��s?���E�
�
�A�
�
��s�
�C������s�5�y�����JrCc�R�|dzt|��zdzt|��zS)Nrn)r�)rw�copy_permissionsr�s   rB�gen_path_keyr�s,���#�:�c�*�+�+�+�c�1�C��4G�4G�G�GrCr�c	�n
�t��t|��r||zSt|||��}|tvr
t|St	|��}|}d}	|	t|��k�rBt��t
|d|	dz���}
t|
||��}|tvr�tj�	|||	��}tj�
|��sn�t||d��}
tj�
|
��sn�|
}|rTt|��sE	t|
||||��n0#t$r#}td|
d|d|j��Yd}~nd}~wwxYw|t|<n
t|}|	dz
}	|	t|��k��B|	t|��k�rTt��t
|d|	dz���}
tj�	|||	��}	t#|
��}n3#t$r&}td|
zdz|j��Yd}~dSd}~wwxYwt%j|j���r#	t#|��}t%j|j��s#t+|��tj|��n#t$rYnwxYwt/d|zt0|��	tj|d	��t5|d
��n;#t$r.}t/d|zdz|jzt0|��Yd}~nd}~wwxYw|rG	t|
||||���n�#t$r$}td|
d|d|j��Yd}~�ntd}~wwxYw�njt%j|j���rPt9|
|��}t5|d
��|dd
kr1t;||||||��}t=|t?����n�tj� tj�	tj�!|��|����}
t|��dkr?|
dt|���|kr$td|
zdz��tEd���|
t|��d�}t;||||||��}t=|t?����|}|	dz
}	|	t|��k��Tt5|d
��|t|<|S)Nrr�z*failed to copy time/permissions/owner from�tor�zfailed to lstat(z):zCreate directory ��Fz$Warning: failed to create directory z -- rKr�r�r�)#r1r�r��handled_dirr�r�r�rOrwrr#r�rCr�rQr�strerrorr{r��S_ISDIRr�r}r{rr�mkdirrur��update_symlink_in_skeleton�create_parent_pathrpr�r�rr=)r�rwr�r�r�r��keyr��	existpathrm�origpath�origkey�tmp1ror��jailpathr��injailsb�realfiles                   rBr�r�s����O�O�O�������d�{���t�-�~�
>�
>�C�
�k����3���
�t���E��I��A��S��Z�Z�<�<������U�1�Q�q�S�5�\�*�*���x�)9�>�J�J���+�%�%��7�<�<�	�%��(�3�3�D��7�>�>�$�'�'�
��"�4��q�1�1�C��7�>�>�#�&�&�
���I��
z��	�(B�(B�
z�z�-�h�	�:�z�[i�j�j�j�j���z�z�z�� L�h�X\�^g�il�no�nx�y�y�y�y�y�y�y�y�����z����!*�K�� � �#�G�,�I�	�1���)
�S��Z�Z�<�<�0
�S��Z�Z�<�<������U�1�Q�q�S�5�\�*�*���7�<�<�	�%��(�3�3��	��h�'�'�B�B���	�	�	��*�8�3�D�8�!�*�E�E�E��4�4�4�4�4�����	����
�L���$�$�&	0�
�'��1�1���|�H�$4�5�5�(�$�X�.�.�.��I�h�'�'�'����
�
�
���
����
�'��0��Z�H�H�H�
z����5�)�)�)��H�e�,�,�,�,���
z�
z�
z��>��I�F�R�UV�U_�_�al�nx�y�y�y�y�y�y�y�y�����
z����!�
y�y�-�h��*�j�Zh�i�i�i�i���y�y�y�� L�h�X\�^f�hk�mn�mw�x�x�x�x�x�x�x�x�����y����
y�
�l�2�:�&�&�	0�1�(�H�E�E�H���%�(�(�(����S� � �-�f�h�
�.>�
�N�\�\���H�f�h�h�/�/�/�/��g�&�&�r�w�|�|�B�G�O�O�H�4M�4M�x�'X�'X�Y�Y����K�K��M�M�c�,�3�v�;�;�,�&7��&?�&?��
�3��/L� L�M�M�M�#�$A�B�B�B��s�6�{�{�|�|�,��-�f�h�.8�:J�J�Xf�h�h���H�f�h�h�/�/�/��	�	�1���e
�S��Z�Z�<�<�f�	�5�!�!�!��K����ss�>E�
E?�E:�:E?�H&�&
I�0I�I�4AK�
K
�K
�*%L�
M�$M�M�M#�#
N�-N�Nc	��t|��rdS	t|��}tj|j��r#t|��t
j|��n"#tttj
f$rYnwxYwd}|dkrJ	tj||��d}t|��n"#td|zdz|zdz��YnxYw|dkr{	t||��t|d���t!|||d|�	��dS#tttj
f$r$}td
|d|d|j��Yd}~dSd}~wwxYwdS)zKcopies/links the file and the permissions, except any setuid or setgid bitsNr�rzLinking � to z failed, will revert to copyingF�rs�r�r�z$ERROR: copying file and permissions r�)r�r{r�r�r�r}r��rmtreer�rQ�ErrorrO�linkrurr�r�r�)rr�r��try_hardlink�retain_ownerr�do_normal_copyr�s        rB�copy_with_permissionsrgs����������
���$�$���<��(�)�)�	��S�!�!�!��M�#�������W�f�l�+�
�
�
���
�����N��a���	��G�C������N��������	��
�3��v�-�c�1�2S�S�T�T�T��D�����!���	d�
!��c�*�*�*����.�.�.�.�%�c�3�
�q�Ye�f�f�f�f�f�f����&�,�/�	d�	d�	d��>��V�S�RV�XY�Xb�c�c�c�c�c�c�c�c�c�����	d����	�s6�AA�A>�=A>�
&B1�1C�5D�E�-E�Ec�F�t|��rdS	tj|��}n-#t$r t	d|zdzt
|��YdSwxYwt
|tj�|��|ddd���t||z|��}tj|j��rd}�nqtj
|j��rd}�nTtj|j���r8	tj|��}t	d|zd	z|zt
|��t!|d
���tj||��n/#t$r"t	d|zd	z|zt
d��YnwxYw|dd
krZtj�tj�tj�|��|����}|�d��s1tj�|��rt-||||��dSdSt/|jd��\}}		tj�|��sht	d|z|zt
|��tjtjdd|t9|��t9|��t9|	����nt	d|zdzt
|��t;||d|���dS#t$rt	d|zt
d��YdSwxYw)NzDevice z does NOT exist in real systemr�r�r�r�r��c�b�Creating symlink rT��check_mounts�Failed to create symlink rKz/proc/�zCreating device �mknodz does exist alreadyr
zFailed to create device )rCrOrwrQrrr�rwrr�r��S_ISCHRr��S_ISBLKr�r.�remove_file_or_dir�symlinkr�rrgr#�copy_device�divmod�st_rdevr��spawnlp�P_WAITr�r�)
r�rwr�rr��
chrootpathr�r�major�minors
          rBr r �s,���t�������
�X�d�^�^���������	�D� �"B�B�;�z�Z�Z�Z���������v�r�w���t�4�4�j�ST�ab�st�u�u�u�u�!�&��+�f�5�5�J���R�Z� � �����
�,�r�z�
"�
"�����
�,�r�z�
"�
"��	[��{�4�(�(�H��'�
�2�6�9�(�B�;�z�Z�Z�Z��z�$�?�?�?�?��J�x�
�+�+�+�+���	[�	[�	[��/�
�:�6�A�(�J�;�XY�Z�Z�Z�Z�Z�	[�����A�;�#����w�'�'�����R�W�_�_�T�5J�5J�H�(U�(U�V�V�H��"�"�8�,�,�	D������1I�1I�	D����*�l�C�C�C������"�*�c�*�*�L�E�5�F��w���z�*�*�	W��&�v�-�d�2�;�z�J�J�J��J�r�y�'�'�:�s�4�y�y�#�e�*�*�VY�Z_�V`�V`�a�a�a�a��I�j�(�)>�>�{�:�V�V�V�!�$�
�q�Q]�^�^�^�^�^�^���F�F�F��*�:�5�k�1�E�E�E�E�E�E�F���s5�(�&A�A�/AE	�	)E5�4E5�B6K9�9#L �L c	���t��t|��r|Sd}	tj|��D]�}
t��tj�||
��}	t
|��}tj|j	��rJt|||dd|���}
t|
t����t|||||||||��	�	}n$|	tj�||
��fz
}	��#t$r!}td|d|j��Yd}~��d}~wwxYwt#||	|||||||��	�	}t$r!|	D]}t|t�����|S)	zRcopies a directory and the permissions recursive, except any setuid or setgid bitsrGr�r)r�r�r�r���update�!failed to investigate source filer�N)r1r�rOrrwrr{r�r�r�r�rpr��copy_dir_recursiverQrr��copy_binaries_and_libsrn)r�r��force_overwriter��
check_libsrr�handledfilesr*�files2r�ror��epathr�r�s                rBr,r,�s����O�O�O��������
�F���D�!�!�
P�
P�������g�l�l�4��'�'��
	P���$�$�D���T�\�*�*�
5�*�6�3�:�`a�no�AM�N�N�N���E�6�8�8�,�,�,�1�&��_�j�Zd�fr�uA�CO�X^� _� _� _����"�'�,�,�t�U�3�3�4�4�����	P�	P�	P��;�C��A�J�O�O�O�O�O�O�O�O�����	P����)�&����U_�am�o{�~J�SY�Z�Z�Z�L��(��	(�	(�D���f�h�h�'�'�'�'��s�'BC>�>
D)�D$�$D)c��|�d��dkpA|�d��dkp(|tjtjztjzzS)N�/libr^�.so)rhr��S_IXUSR�S_IXGRP�S_IXOTH)r�r�s  rB�libs_check_is_neededr9�sS���J�J�v���"�$�
U��
�
�5�(9�(9�R�(?�
U� $���t�|�(C�d�l�(R� S�VrCc�x�t��	|r�	d�|��}tj||��t	j|t
jt	j|��j	����n"#tttjf$rYnwxYwt|d��5}|sdnd}|�|�|����ddd��dS#1swxYwYdS#ttf$r1t!d|zt"d��t%jd��YdSwxYw)z�
    Helper for write lines to file
    :param: filename `str` filename for write
    :param: lines `list` list with content lines
    :param: add_eol `bool` if True than add 
 to end each line
    z{}.bakrr�rrNzError: failed to write r�)r1�formatr��copyfilerOrr�r�rwr�r�rQrrRr�rrrr�r�)rrl�add_eolrc�backup_namer~�splitters       rBrjrj�s����O�O�O���	�
�&�o�o�h�7�7�����+�6�6�6����d�l�2�8�H�3E�3E�3M�&N�&N�O�O�O�O���W�f�l�3�
�
�
���
�����(�C�
 �
 �	*�A�!(�2�r�r�d�H�
�G�G�H�M�M�%�(�(�)�)�)�	*�	*�	*�	*�	*�	*�	*�	*�	*�	*�	*�	*����	*�	*�	*�	*�	*�	*��
�W������)�H�4�k�1�E�E�E�������������sY�C7�A(A<�;C7�<B�C7�B�C7�./C*�C7�*C.�.C7�1C.�2C7�7>D9�8D9c�
�|dvS)N)
�0�1�2�3�4�5�6�7�8�9rG)�ns rB�isdigitrL�s���B�B�BrCc�<�|sdS|D]}t|��sdS�dS)NFT)rL)�s�chars  rB�isdigitsrP�s=�����u������t�}�}�	��5�5�	��4rCc�,�t|��}|�|��}|dkri|||zd�}d}|t|��kr.t||��sn|dz
}|t|��k�.|d|�}t|��SdS)Nr^rr�)r�rhrLr��r��sign�lengthr[�end�pos2�vers       rB�get_versionrXs���
��Y�Y�F�
�)�)�D�/�/�C�
�b�y�y��3�v�:�;�;������S��X�X�o�o��3�t�9�%�%�
���A�I�D��S��X�X�o�o��%�4�%�j���3�x�x���1rCc��|dd�}tt|����D]#}||�d|��}|||<�$tj�|��rZ	tj|��nD#ttf$r0td|ztd��tjd��YnwxYwtj
d��}t||��tj
|��dS)N�ALIASzError: failed to delete r�r�)r�r�r�rOrwrxr{rQr�rrr�r�r�rj)�program�alias�command�scriptrmror�s       rB�update_wrapperr_s���
�Q�Q�Q�Z�F��3�v�;�;�
�
�����Q�i�����/�/����q�	�	�	�w�~�~�g����	��I�g��������!�	�	�	��.��8�+�q�I�I�I��H�Q�K�K�K�K�K�	�����(�4�.�.�K��w������H�[�����s�+B�>C�Cc��tj�|��sdSd}	tj|dd||gtjtjd���}|���\}}|jdkr'td|zdz|zd	z|ztd
��dS|jdkrdSn6#t$r)td|zdz|zd	z|ztd
��YdSwxYw|dkrt||��}||krd
SdS)NTz	/bin/grep�-mrB�r�r�r�rZ�Error while executing z -m 1 � r�r�Error: failed to run F)rOrwrxr�r�r��communicate�
returncoderrrQrX)r]�versionrS�GREPr��outrnrWs        rB�wrapper_not_installedrk)sE��
�7�>�>�'�"�"���t��D����d�D�#�t�W�=�?I��Wa�Wf�mq�
s�
s�
s���=�=�?�?���a��<�1����,�t�3�h�>��E��K�g�U�Wb�de�f�f�f��4�
�\�Q�
�
��4��������'�$�.��9�D�@�3�F��P�R]�_`�a�a�a��t�t�����
�d�{�{��#�t�$�$���'�>�>��5��4s�A8B-�B-�-/C �C z/usr/share/cagefs/safeprograms/z #CageFS proxyexec wrapper - ver rlc�N�|D]!}t|t��}|dkr|cS�"dS)zY
    Detect wrapper version from the file lines.
    If unable to detect, return -1.
    rr^)rX�	SIGNATURE)rlr�rhs   rB�get_proxy_versionrn[s>��
�����d�I�.�.���a�<�<��N�N�N��
�2rCc�,�t|��}tj�|��sdSt	t
t|z��}t|��}|dkstt|z|t��r$t|t|t|z��	t|t|zddd���dS#ttf$r9t!dtz|zt"d��t%jd��YdSwxYw)Nr^rr��r�r�r�z*Error: failed to set permissions/owner to )r�rOrwrxr%�
PROXY_PATH�wrappers_namesrnrkr	rmr_�wrappersr�rQr�rrr�r�)r��proxy�	proxy_vers   rB�install_wrapperrvgs���u���E�
�7�>�>�%� � ����
�j�>�%�#8�8�9�9�E�"�%�(�(�I��B���/����	�9�U�U���u�h�u�o�x��~�>�>�>��!�%��%��A�RS�de�f�f�f�f�f�f���W������<�x�G��M�{�\]�^�^�^�������������s�+C	�	AD�Dc��t��t|��}|tvr"t|d���t	|��dSdS)NFr	T)r1r�rsrurv)r�s rB�update_proxy_wrapperrx�sN���O�O�O��u���E������E�e�,�,�,�,�������t��5rCc�*�	tj|��n#ttf$rYnwxYwtj�|��rF|rt
|��stj|d��dStd|zdztd��dSdS)NTz"Error: failed to remove directory z because it includes mount pointsr�)rOr{rQr�rwrrEr�rrr)rwrs  rBrr�s���
�
�	�$�������W��
�
�
���
����
�w�}�}�T���v��	v�&?��&E�&E�	v��M�$��%�%�%�%�%��8�4�?�Bd�d�fq�st�u�u�u�u�u�	v�vs��+�+z/usr/bin/php-cgiz/usr/bin/phpz/etc/php.iniz/usr/local/bin/lsphpz/usr/local/sbin/php-fpm)�php�php-cli�php.ini�lsphpzphp-fpmz
/usr/selectorz/usr/selector.etcznative.confc�*�t��rdS|dvS)z�
    Returns True if php file for appropriate alias is mandatory
    for proper work of PHP Selector (i.e the file should exist
    and should be replaced with symlink successfully)
    :param alias: alias for php file
    :type alias: string
    F)rzr{r|r'�r\s rB�is_mandatoryr��s#�������u��1�1�1rCc��ts�tj�t��r�ttd��}|D]�}|�d��s�|���}|�dd��}t|��dkrG|d���}|d���}|tvr
|t|<��|���dadSdSdS)Nrs�#�=r�rZrT)�
config_loadedrOrwrx�NATIVE_CONFrRrg�stripr�r��
orig_binariesrS)r~r��arr\rws     rB�read_native_confr��s����
!�
�7�>�>�+�&�&�	!��[�#�&�&�A��
8�
8�����s�+�+�8��:�:�<�<�D����C��+�+�B��2�w�w�!�|�|� "�1����
�
��!�!�u�{�{�}�}�� �M�1�1�37�M�%�0��
�G�G�I�I�I� �M�M�M�
!�
!�	!�	!rCc���t��t���D]9}tj�|��}|�d��rdS�:dS)NrTF)r�r��valuesrOrwr�rg)rwr0s  rB�is_etc_in_native_confr��se�������$�$�&�&������ � ��&�&�����G�$�$�	��4�4�	��5rCc�B�|dkr
tdz|zStdz|zS)Nr|rK)�ALT_DEST_ETC_PATH�
ALT_DEST_PATHrs rB�get_usr_selector_pathr��s-���	��� ��$�U�*�*����U�"�"rCc�l�|dkr+|�d��stdd|gd���dSdSdS)Nr��.iniz/usr/bin/killallz-qF)�check_return_code)�endswith�Execute)�	file_names rB�kill_phpr��sI���B���	� 2� 2�6� :� :���#�T�9�5��O�O�O�O�O�O����rCc	��|dkrttz}nttz}tj�||��}tj�|��s�	tj�|��st|d��tj	d��}t|d�����tj	|��n>#ttf$r*}td|dt|����Yd}~dSd}~wwxYwt!��x}�tj|d	|��d
S)zW
    Create stub (empty file) for php file.
    Return True when error has occured
    r|r�r�rzFailed to write:r�NTr^F)r	r�r�rOrwrr�rr4r�rRrSrQr�rr�r r�)r\�selector_dir�	stub_pathr�r��linksafe_gids      rB�create_php_stubr��s0��

�	����"3�3����-�/������\�5�1�1�I�
�7�?�?�9�%�%�	�	��7�=�=��.�.�
2��\�5�1�1�1��(�4�.�.�K���C� � �&�&�(�(�(��H�[�!�!�!�!����!�	�	�	��*�I�s�C��F�F�C�C�C��4�4�4�4�4�����	����)�*�*�*��7�
���B��-�-�-��5s�&A9C � D�1D�Dc
��t��|r|�d��sdS|}nt|��}t��tD�]}t��t
j�t|��}||k�r=t
j�|���rt
j�	|���s�|dvr t��rt|��dS|}t|��}tdz|z}t|z}t
j�|��}	|rt |z}
n
t|z}
|	t
j�|
��fD]�}t
j�|��s�	t%|d���3#t&$rb}d|�dt)|���dd	����}
t-j|
|�
��t1|
t2d��Yd}~dSd}~wwxYw��t5||d�
��rtt7||d���rbt
j�|��}t;|��t7||d���r"t1d|zdz|zt2d��dSt=��x}�tj|d|��	t
j�	|
��rBtj |
��|kr)tj!|
��tj"||
��n$tG|
��tj"||
��nn#t&$ra}d|
�dt)|���dd	����}
t-j|
|�
��t1|
t2d��Yd}~dSd}~wwxYw|stI|
d���dS���dS)aN
    Move php file to /usr/selector* directory inside cagefs-skeleton and create symlink to it
    Return True if php binary has been moved successfully, False otherwise
    :param path: path to original php file
    :type path: string
    :param etc: True = /etc directory is being processed, False otherwise
    :type etc: bool
    rF)rzr{r}r|rKr��"Error: failed to create directory � : r�r��r�r�Nr)�create_parent_dirzError copying rr^� Error: failed to create symlink r	T)%r1rgr�r�r�rOrwr�rxr�r(r�r�rr	rr$rr4rQr�r�r8�errorrrr�r&rr�r r�r.r{rrru)rwrr�r\�	orig_pathr�	DEST_PATH�LINK_TO�	dest_file�dest_dir�	orig_file�parent_pathr�r�r�r�s                rBr"r"s����O�O�O�
�!����w�'�'�	��5�����4� � �������7�7�������G�$�$�]�5�%9�:�:�	��Y���B�G�N�N�9�$=�$=��r�w�~�~�V_�G`�G`���>�>�>�!�#�#�!�#�E�*�*�*� �5�5��H�-�e�4�4�I�%�c�)�(�2�G� �9�,�I��w���y�1�1�H��
1�0�9�<�	�	�$�y�0�	� (�"�'�/�/�)�*D�*D�E�
%�
%���w�}�}�[�1�1�%�%�$�[�%�8�8�8�8��"�%�%�%�x�;�x�x�SV�WX�SY�SY�Sa�Sa�bi�ku�Sv�Sv�x�x����S�1�5�5�5�5���[�!�4�4�4�$�u�u�u�u�u�u�u�����	%����%� �	�9��F�F�F�
%��Y�	�u�M�M�M�%� "�� 0� 0�� ;� ;�I��Y�'�'�'� ��I�5�Q�Q�Q�%�� 0�� :�6� A�)� K�[�Z[�\�\�\�$�u�u� 0� 2� 2�2��?����B��5�5�5�
��7�>�>�)�,�,�3��{�9�-�-��8�8��	�)�,�,�,��
�7�I�6�6�6��&�y�1�1�1��J�w�	�2�2�2����
�
�
�l��l�l�s�1�v�v�~�~�V]�_i�Gj�Gj�l�l����S�1�-�-�-�-���[�!�,�,�,��u�u�u�u�u�u�����	
�����
9��I�%�8�8�8�8��4�4���5s3�F'�'
H�1AH�H�BM
�

N5�AN0�0N5c�d�|dkrdSt|��}|ddddddd	d
ddd
dddddthvS)NrKTz/binz/bootz/devz/etcr4z/lost+foundz/mnt�/procz/rootz/sbinz/sys�/tmpz/usrz/varz/homerL)r��PLESK_VHOSTS_Dr�s rB�is_path_in_exclusionsr�Psd���s�{�{��t��d���D�����������������
��)��rCz(/var/www/cgi-bin/cgi_wrapper/cgi_wrapperc��td|zdz|ztd��tj||��|rt	||��dSt	||��dS)N�Copying rr�)rrr�r<r�)�A�B�Cs   rB�__copy_wrapperr�nsh���Z�!�^�f�
$�q�
(�+�q�9�9�9�
�O�A�q�����(�!�!�Q�'�'�'�'�'�!�!�Q�'�'�'�'�'rCc�L�t��	tj��r�d}d}ttdztfdttztf|t|ztf||tff}t
j�ttz��}t
j�|��st|d��|D]\}}}t|||���dSdS#ttf$r*}tdt|��z��Yd}~dSd}~wwxYw)Nz//var/www/cgi-bin/cgi_wrapper/cloudlinux_wrapperz9/usr/share/cagefs-plugins/plesk-cagefs/cloudlinux_wrapperz4/var/www/cgi-bin/cgi_wrapper/cgi_wrapper.orig.cagefsz2/usr/share/cagefs-plugins/plesk-cagefs/cgi_wrapperr�z!failed to install Plesk wrapper: )r1�cldetectlib�is_plesk�PLESK_ORIG_WRAPPER_FILENAMEr	rOrwrr�r4r�rQr�rr�)�CLOUDLINUX_WRAPPER�CLOUDLINUX_WRAPPER_PACKAGE�WRAPPERS�dirpathrr��permr�s        rB�install_plesk_wrapperr�wsU���O�O�O�B���!�!�	/�!R��)d�&�0�(�;q�2q�tO�P�I�8�To�Ko�rM�N�/��:L�1L�Ni�j�/�1C�E`�a�	�H��g�o�o�h�/J�&J�K�K�G��7�?�?�7�+�+�
-��W�e�,�,�,�"*�
/�
/���S�$��s�C��.�.�.�.�!	/�	/�
/�
/���W��B�B�B��7�#�a�&�&�@�A�A�A�A�A�A�A�A�A�����B���s�CC(�(D#�9D�D#c
��t��|ddkr
|dd�}|D�]�}
t��|
|vr�t|
��rTtj�|
��stj�|
��r|�|
���yt|
��rTtj�|
��stj�|
��r|�|
����	t|
��}n�#t$r�}|j
dkr�|dkr�tj|
��}
t|
��dkrBt||
|||||d||	��
�
}tr!|
D]}t|t!�����nQt#d|
zd	zt$|��n4t#d|
zd	zt$|��nt'd
|
d|j��Yd}~���d}~wwxYwt+|tj�|
��|dd|���	t/tj�|dz|
z��|��}n#t$rY��DwxYwt|��rUtj�|
��stj�|
��r|�|
�����t3|��r|�|
�����|
t4kr%t7��|�|
����t9|��r=t;|
��}t||||d|||	�
��}|�|
����Nt=|��rUtj�|
��stj�|
��r|�|
�����	t|��}d}t?|��n=#t$r0}|j
dkrd}nt'd||
d|j��Yd}~nd}~wwxYw|dkr[|	dkrU|rStAj!|j"��s:t#d|zdzt$|��t|t!������r|�r�|r�tAj#|j"��stAj$|j"��rbt#d|zdzt$|��	tj%|���n�#t$r"}t'd|d|j��Yd}~�nZd}~wwxYwtAj!|j"��rt#d|zdzt$|���n|	�r�tAj#|j"��stAj$|j"���rwtM|
|||d���rbt#d|zdzt$|��	tj%|���n�#t$r"}t'd|d|j��Yd}~�nwd}~wwxYwt#d|zdzt$|��t?|d���t|t!����|�|
��tAj$|j"��r�	tj'|
��}n#ttPf$rd}YnwxYw|dkr�tS|��s�|ddkrZtj�tj�*tj�|
��|����}t||g|||||||	��	�	}t|t!����tAj+|t@j,��}|r�t[|
|��rst]|
��}|dkrt;|
��}t_|
|��t||||d|||	�
��}tr!|D]}t|t!��������tAj!|j"��rt#d|zdzt$|��n8tAj!|j"��rnt#d|zdzt$|����]t+|tj�|
��|dd|���tAj$|j"��r�ta|
|��}t?|d���|�|
��tS|��s�|ddkrZtj�tj�*tj�|
��|����}t||g|||||||	��	�	}t|t!�����n�tAj!|j"��r�t+||
|dd|���}tc|��}tr&||kr t'dt!��d|d |��te||
|||||||	��	�	}t|t!����n�tAj#|j"��r�|r t#d!|
zd"z|zt$d��nt#d#|
zd"z|zt$d��tg|
||||�$��|�|
��t|t!����nDtAj4|j"��stAj5|j"��rtm||
||��tAj+|t@j,��}|r�t[|
|��r�tAj$|j"��stAj#|j"��r^t;|
��}t_|
|��t||||d|||	�
��}tr!|D]}t|t!��������|S)%z>copies a list of executables and their libraries to the chrootr^rKNrZr�r)rr�try_glob_matchingr0r*zSource file(s) z
 do not existr+r�r)r/rr0r*z'failed to investigate destination file r�z" already exists, will not touch itzDestination file z$ exists, will delete to force updatezERROR: failed to deletezDestination dir z existsT)r�z
 needs updatezfailed to deletez does NOT need updateFr	)r/rrr0r*r�r�rrzTrying to link rr�)rr)7r1r,rOrwrxr�r�rCr{rQr��globr�r-rnrpr�rrrr�r�rr�r�rxr�r�r"r�r�rur�r�r��S_ISREGr�r{r�r.r�r�rr�r�r9rTrOr�r�r,rrrr )r��binarieslistr.r�r/rrr�r0r*r�r�r�r�r��chrootrfile�php_libs�chrootsb�chrootfile_existsrr�rNr2s                       rBr-r-�s*
���O�O�O��r�
�c����������I8�I8�������L� � ���U�#�#�	��w�~�~�e�$�$�
+�����u�(=�(=�
+��#�#�E�*�*�*���5�!�!�	��w�~�~�e�$�$�
+�����u�(=�(=�
+��#�#�E�*�*�*��	��e�$�$�B�B���	�	�	���1���%��*�*��)�E�*�*�C��C����
�
�'=�f�c�?�\f�hr�KW�fr�PQ�`l�u{�(}�(}�(}��(�<�(+�<�<�� +�D�&�(�(� ;� ;� ;� ;��� 1�%� 7�� G��T^�_�_�_�_��-�e�3�O�C�K�PZ�[�[�[�[��?��c�!�*�U�U�U��H�H�H�H�����#	����(	�6�"�'�/�/�%�"8�"8�*�WX�ef�xD�	E�	E�	E�	E�	�*�2�7�+;�+;�F�3�J�u�<L�+M�+M�f�U�U�K�K���	�	�	��H�	����
�;�'�'�	��w�~�~�e�$�$�
+�����u�(=�(=�
+��#�#�E�*�*�*�� ��,�,�	�����&�&�&���/�/�/�!�#�#�#�����&�&�&�� ��,�,�	�#�E�*�*�H�1�&�(�O�U_�!"�<�P\�gm�o�o�o�L�����&�&�&���K�(�(�	��w�~�~�e�$�$�
+�����u�(=�(=�
+��#�#�E�*�*�*��	c�#�K�0�0�H� !����$�$�$�$���	c�	c�	c���1���$%�!�!��E�f�U�SV�WX�Wa�b�b�b����������		c������
!�
!��!���9J��SW�S_�`h�`p�Sq�Sq���B�{�N�#G�G��T^�_�_�_���V�X�X�.�.�.�.�!�=
!�#�<!���X�%5�6�6�a�$�,�x�GW�:X�:X�a�� 3�K� ?�@f� f�gr�s}�~�~�~�^��I�k�2�2�2�2��&�^�^�^�'�(A�+�c�RS�R\�]�]�]�]�]�]�]�]�����^�����,�x�'7�8�8�a�� 2�;� >�y� H��U_�`�`�`���3!��|�H�$4�5�5�*a���h�FV�9W�9W�*a�,�U�K��X�ae�f�f�f�'%�#�$7��$C�O�$S�T_�`j�k�k�k�[� "�	�+� 6� 6� 6� 6��#*�[�[�[� +�,>�{�3�q�z� Z� Z� Z� Z� Z� Z� Z� Z�����[����$�$7��$C�D[�$[�\g�hr�s�s�s�'���F�F�F�F�'��V�X�X�>�>�>�(�/�/��6�6�6�#�|�H�,<�=�=�
D�!4�/1�{�5�/A�/A�H�H��(/��'9�!4�!4�!4�/3�H�H�H�!4����#+�t�#3�#3�=R�S[�=\�=\�#3�(0���s�(:�(:�35�7�3C�3C�B�G�L�L�QS�QX�Q`�Q`�af�Qg�Qg�hp�Dq�Dq�3r�3r��3I�&�S[�R\�^m�oy�GQ�`l�|H�Wc�lr�4s�4s�4s�L�$/��&�(�(�$C�$C�$C�$(�<��4�<�0@�#A�#A�D� *�D�/C�E�4�/P�/P�D�'9�%�'@�'@��#'�4�<�<�+7��+>�+>�D�$4�U�D�$A�$A�$A�/E�f�d�Tc�eo�uv�FR�xD�MS�0T�0T�0T��$0�!D�04�%D�%D��(3�D�&�(�(�(C�(C�(C�(C�$��,�x�'7�8�8�a�� 2�;� >�y� H��U_�`�`�`����X�%5�6�6�!�� � 3�K� ?�	� I�+�V`�a�a�a� �
�v�b�g�o�o�e�&<�&<�j�[\�ij�|H�
I�
I�
I�
I���R�Z�(�(� 
E�5�e�[�I�I���K�E�:�:�:�:��#�#�E�*�*�*�,�X�6�6�4� ���s�*�*�#%�7�#3�#3�B�G�L�L�����QV�AW�AW�X`�4a�4a�#b�#b��#9�&�8�*�o�_i�ak�{G�co�co�x~�$@�$@�$@�L� ��&�(�(�3�3�3���,�r�z�*�*�
E�*�6�5�*�WX�ef�xD�E�E�E��"�5�)�)���R�U�k�%9�%9������$��t�[�Q�Q�Q�1�&���PZ�]g�wC�_k�_k�tz� |� |� |���K����2�2�2�2��,�r�z�*�*�	
E� �P��.�u�4�V�;�K�G��UV�W�W�W�W��Z��-�f�4�[�@��Q�O�O�O�%�e�K�
�Q]�lx�y�y�y�y��#�#�E�*�*�*��K����2�2�2�2��,�r�z�*�*�
E�d�l�2�:�.F�.F�
E��F�E�:�|�D�D�D��<��4�<� 0�1�1�D��	
8�3�E�4�@�@�	
8��<��
�+�+�8�t�|�B�J�/G�/G�8�'��.�.�D�$�U�D�1�1�1�#9�&�$��Yc�ij�zF�kw�AG�$H�$H�$H�L�$�8�$(�8�8�D�'��f�h�h�7�7�7�7���s��D�
G4�CG/�/G4�*3I�
I,�+I,� O;�;
P5�&P0�0P5�-T�
T/�
T*�*T/�W&�&
X�0X
�
X�
Z"�"Z8�7Z8c���g}|�||��rN|�||��}|�d��D]"}|���}|dkr||gz
}�#|S)z�retrieves a comma separated option from the configparser and splits it into a list, returning an empty list if it does not exist�,r�)�
has_option�getr�r�)�	cfgparser�sectionname�
optionnamer��inputstrror�s       rB�config_get_option_as_listr�jsu��
�F����[��4�4�!��=�=��Z�8�8���>�>�#�&�&�	!�	!�C��9�9�;�;�D��r�z�z��4�&� ����MrCc�`
�|ddkr
|dd�}tj�|��sF	t|d��n4#t$r'td|��t
jd��YnwxYwtj|d��g}|�	|��g}|�	|��tj
dd�dkr�t|d	zd
�����t|dzd
�����t|dzd
�����t|d
zd
������n�tj�
|d	z��st|d	zd��}�n5t|d	zd��}|���}t|��dkr�|�d��}t|��dkr�|d|vs
|d|vr�t#d|dzdz|zd	zt$|��	|�|d��n#t($rYnwxYw	|�|d��n#t($rYnwxYw|���}t|��dk��|�dd��t|��dk�rtdd��}	|	���}t|��dkr�|�d��}t|��dkrg|d|vs
|d|vrS|�|��t#d|dzdz|zd	zt$|��|d|vr||dgz
}|	���}t|��dk��|	���|���t/d|d	zddd���tj�
|dz��st|dzd��}�n5t|dzd��}|���}t|��dkr�|�d��}
t|
��dkr�|
d|vs
|
d|vr�t#d|
dzdz|zdzt$|��	|�|
d��n#t($rYnwxYw	|�|
d��n#t($rYnwxYw|���}t|��dk��|�dd��t|��dkr�tdd��}	|	���}t|��dkr�|�d��}
t|
��dkrQ|
d|vs
|
d|vr=|�|��t#d|
dzdz|zdzt$|��|	���}t|��dk��|	���|���t/d|dzddd���dS)Nr^rKr��creatingr�r���bsdz/passwdrNz/spwd.dbz/pwd.dbz/master.passwdr�r+rr�r�rZ�user � exists in rrs�
writing user rrpz/group�group r �writing group )rOrwrr4rQrr�r�r�extend�platformrRrSrx�readliner�r�rr�remover��seekr�r�)r��
users_list�groups_listr��usersr��fd2r��pwstruct�fd�groupstructs           rB�init_passwd_and_groupr�ws����������C�R�C�=��
�7�=�=��"�"��	���5�)�)�)�)���	�	�	��
�H�-�-�-��H�Q�K�K�K�K�K�	�����H�X�u�����E�	�L�L�����
�F�
�M�M�+������Q�q�S��U�"�"��X�i�
��$�$�*�*�,�,�,��X�j�
 ��%�%�+�+�-�-�-��X�i�
��$�$�*�*�,�,�,��X�&�
&�s�+�+�1�1�3�3�3�3�����x�	�1�2�2�	��x�	�)�#�.�.�C�C��x�	�)�$�/�/�C��<�<�>�>�D��t�9�9�Q�;�;��:�:�c�?�?����M�M�A�%�%�!�!���-�-�8�A�;�%�3G�3G������ 3�M� A�(� J�9� T�U`�ak�l�l�l�!�!�L�L��!��5�5�5�5��)�!�!�!� �D�!����!�!�L�L��!��5�5�5�5��)�!�!�!� �D�!�����|�|�~�~���t�9�9�Q�;�;�
�H�H�Q�q�M�M�M���J�J��N�N��m�C�(�(�B��;�;�=�=�D��t�9�9�Q�;�;��:�:�c�?�?����M�M�A�%�%�!�!���-�-�8�A�;�%�3G�3G��	�	�$��������� ;�F� B�8� K�I� U�Va�bl�m�m�m� (���v� 5� 5�"�x��{�m�3�F��{�{�}�}���t�9�9�Q�;�;�
�H�H�J�J�J��	�	�����m�X�i�-?�A�Z[�lm�n�n�n�n�
�G�N�N�8�H�,�-�-���8�H�$�S�)�)����8�H�$�T�*�*���|�|�~�~���4�y�y��{�{��*�*�S�/�/�K��K� � �1�$�$� ��^�v�-�-�;�q�>�V�3K�3K��H�[��^�3�M�A�(�J�8�S�T_�`j�k�k�k���
�
�k�!�n�5�5�5�5��%������������
�
�k�!�n�5�5�5�5��%�����������<�<�>�>�D��4�y�y��{�{�	����1�
�
�
��F���a���
�,�s�
#�
#���{�{�}�}���4�y�y��{�{��*�*�S�/�/�K��K� � �1�$�$� ��^�v�-�-�;�q�>�V�3K�3K��I�I�d�O�O�O��,�[��^�;�F�B�8�K�H�T�U`�ak�l�l�l��;�;�=�=�D�
�4�y�y��{�{�	���
�
�
��I�I�K�K�K��l�H�X�,=�!�XY�jk�l�l�l�l�l�lsY�A�.A9�8A9�I�
I,�+I,�0J�
J�J�/T�
T�T�T8�8
U�Uc��|ddkr
|dd�}tjd��}tj�|��sF	t	|d��n4#t
$r't
d|��tjd��YnwxYwtj	|d��g}|�
|��g}|�
|��tj�|dz��st|dzd��}n�t|dzd	��}|�
��}|���}t|��d
kr�||vrIt!d|zdz|zdzt"|��	|�|��n#t&$rYnwxYw|�
��}|���}t|��d
k��|�d
d
��t|��d
kr�tdd��}	|	�
��}t|��d
kr�|�d��}
t|
��dkrZ|
d
|vs
|
d
|vrF|�|
d
dz��t!d|
d
zdz|zdzt"|��|	�
��}t|��d
k��|	���|���	tj	|dzd��n3#t
t0f$rt!d|zdzt"d��YnwxYwtj�|dz��st|dzd��}n�t|dzd	��}|�
��}|���}t|��d
kr�||vrIt!d|zdz|zdzt"|��	|�|��n#t&$rYnwxYw|�
��}|���}t|��d
k��|�d
d
��t|��d
kr�tdd��}	|	�
��}t|��d
kr�|�d��}t|��d
krZ|d
|vs
|d
|vrF|�|d
dz��t!d|d
zdz|zdzt"|��|	�
��}t|��d
k��|	���|���	tj	|dzd��n3#t
t0f$rt!d|zdzt"d��YnwxYwtj|��dS)Nr^rKr�i�r�r�z/safe.usersrr�rr�r�rZrrsr�r�rrr�rr�$Error: failed to set permissions to z/safe.groupsr�r r�)rOr�rwrr4rQrr�r�rr�rxrRr�r�r�rrr�r�r�r�r�rSr�)r�r�r�r�r�r�r�r�r�r�r�r�s            rB�init_safe_users_and_groupsr��s����������C�R�C�=���(�4�.�.�K�
�7�=�=��"�"��	���5�)�)�)�)���	�	�	��
�H�-�-�-��H�Q�K�K�K�K�K�	�����H�X�u�����E�	�L�L�����
�F�
�M�M�+�����G�N�N�8�M�1�2�2���8�M�)�#�.�.����8�M�)�$�/�/���|�|�~�~���{�{�}�}���4�y�y��{�{��u�}�}�����]�2�8�;�M�I�+�V`�a�a�a���L�L��&�&�&�&��!�����D������<�<�>�>�D��;�;�=�=�D��4�y�y��{�{�	����1�
�
�
��E�
�
�Q���
�-��
$�
$���{�{�}�}���4�y�y��{�{��z�z�#���H��H�
�
��!�!��a�[�E�)�)�x��{�e�/C�/C��I�I�h�q�k�$�.�/�/�/��O�H�Q�K�7��>�x�G�
�U�Va�bl�m�m�m��;�;�=�=�D�
�4�y�y��{�{�	���
�
�
��I�I�K�K�K�^�
���-�'��/�/�/�/���W��^�^�^��6�x�?�
�M�k�[\�]�]�]�]�]�^����
�G�N�N�8�N�2�3�3���8�N�*�3�/�/����8�N�*�4�0�0���|�|�~�~���{�{�}�}���4�y�y��{�{��v�~�~����
�m�3�H�<�^�K�K�Xb�c�c�c���M�M�$�'�'�'�'��!�����D������<�<�>�>�D��;�;�=�=�D��4�y�y��{�{�	����1�
�
�
��F���a���
�,�s�
#�
#���{�{�}�}���4�y�y��{�{��*�*�S�/�/�K��K� � �1�$�$� ��^�v�-�-�;�q�>�V�3K�3K��I�I�k�!�n�T�1�2�2�2��,�[��^�;�F�B�8�K�N�Z�[f�gq�r�r�r��;�;�=�=�D�
�4�y�y��{�{�	���
�
�
��I�I�K�K�K�_�
���.�(�%�0�0�0�0���W��_�_�_��6�x�?��N�{�\]�^�^�^�^�^�_�����H�[�����sZ�A�.B
�B
�>F�
F!� F!�L*�*-M�M�P�
P+�*P+�V4�4-W$�#W$c�v�|ddkr
|dd�}tj�|��sF	t|d��n4#t$r'td|��t
jd��YnwxYwtj|d��g}|�	|��|dz}tj�
|��s�tj|tjtj
ztjztjztjzd��}tj|d��tj|d��}�nNtj|tjtjztjz��}tj|d��tj|d	��}|���}t+|��d
kr�|�d��}t+|��dkr_|d
|vrUt/d|d
zd
z|zdzt0|��	|�|d
��n#t4$rYnwxYw|���}t+|��d
k��|�d
d��t+|��d
kr�tdd��}	|	���}t+|��d
kr�|�d��}t+|��dkrG|d
|vr=|�|��t/d|d
zdz|zdzt0|��|	���}t+|��d
k��|	���|���t=d|dzd
d
d���dS)Nr^rKr�zError while creatingr��/shadowrrr�rr�r�r�rZr!rsr�rrp)rOrwrr4rQrr�r�rr�rxrRr�r�r�r�r��fchmodr��O_RDWRr�r�r�rrr�r�r�r�rSr�)
r�r�r�r��shadow_path�_fdr�r�r�r�s
          rB�init_shadowr�<so���������C�R�C�=��
�7�=�=��"�"��	���5�)�)�)�)���	�	�	��.��9�9�9��H�Q�K�K�K�K�K�	�����H�X�u�����E�	�L�L������Y�&�K��G�N�N�;�'�'���g���K�"�*�$�r�z�1�B�M�A�B�L�P��
�
��
	�	�#�u�����i��S�!�!����g���I��
�%���4�
�
��	�	�#�u�����i��T�"�"���|�|�~�~���4�y�y��{�{��z�z�#���H��H�
�
��!�!��A�;�%�'�'��G�H�Q�K�/�
�=�h�F�y�P�Q\�]g�h�h�h�����X�a�[�1�1�1�1��%�����������<�<�>�>�D��4�y�y��{�{�	����1�
�
�
��E�
�
�Q���
�-��
$�
$���{�{�}�}���4�y�y��{�{��z�z�#���H��H�
�
��!�!��A�;�%�'�'��I�I�d�O�O�O��O�H�Q�K�7��>�x�G�	�Q�R]�^h�i�i�i��;�;�=�=�D�
�4�y�y��{�{�	���
�
�
��I�I�K�K�K��m�X�i�-?�A�Z[�lm�n�n�n�n�n�ns#�A�.A9�8A9�1I
�
I�Ic�<�t|��}tj�|dz��st	d|zdzt
d��dStj�|dz��rt	d|zdzt
d��dStdd��}t|dzd��}|���}t|��d	kr�|�
d
d��}t|��dkrJ|d	|kr>|�|��t	d|d	zdz|zdzt
|��n'|���}t|��d	k��|���|���dS)
Nr�zError: z/shadow does not existr�z/shadow is a symlinkr!rsrNrr�z
Writing user r)
r�rOrwrxrrr�rRr�r�r�r�rS)r��userr�r��destr�r�s       rB�add_user_to_shadowr��sy���(�#�#�H�
�7�>�>�(�9�,�-�-���	�(�"�#;�;�[�!�L�L�L���	�w�~�~�h�y�(�)�)���	�(�"�#9�9�;��J�J�J���	
�m�S�	!�	!�B����"�C�(�(�D�
�;�;�=�=�D�

�d�)�)�a�-�-��:�:�c�1�%�%���x�=�=�A�����{�d�"�"��
�
�4� � � ������3�F�:�8�C�I�M�{�\f�g�g�g���{�{�}�}���d�)�)�a�-�-��H�H�J�J�J��J�J�L�L�L�L�LrCc� �t|��dkst|��dkrdStt|��t|����}d}||kr||||krn|dz}||k�|dkrdS||dzd�S)Nrr^r�)r��min)�s1�s2�min_lenr[s    rB�get_common_endr��s���
�2�w�w�!�|�|�s�2�w�w�!�|�|��t��#�b�'�'�3�r�7�7�#�#�G�
�C�

�'��/�/�
�c�7�b��g�����q����'��/�/��b�y�y��t�
�c�!�e�f�f�:�rCrr�c��tj�|��}tj�|��}t|��}t|��}|dks|dks|ddks|ddkr!t	d|zdz|zt
d��dSt
t|��t|����}|�+	t|d��n#ttf$rYnwxYwdSt|��}|dt|���}|dt|���}|D]�}|dz|z}|dz|z}	t|d��n#ttf$rYnwxYw	t||ddd�	���Q#ttf$r6}t	d
|zdz|zdz|jzt
d��Yd}~dSd}~wwxYwdS)
a
    Copy a path from a source to a destination.

    If there are shared ending directories between source and destination paths,
    iterates over the common ending directories,
    creating each corresponding directory in a destination path.
    Copies timestamp and permissions from source subdirectories.

    For example, if src = '/root/dir1/dir2' and dst = '/usr/share/cagefs-skeleton/dir1/dir2',
    running this function will result in creating directories 'dir1' and 'dir2'
    within the '/usr/share/cagefs-skeleton' path.
    r�rrKzError: invalid paths src = z dst = r�Nr�rp�!ERROR: while copying permissions rr�)rOrwr�r�rrr�r�r4r�rQr�r�r�r�)rr��common�
common_str�dst_path�src_pathr�r�s        rB�	copy_pathr�s3��
�'�
�
�3�
�
�C�
�'�
�
�3�
�
�C�
�S�/�/�C�
�S�/�/�C��r�	�	�s�b�y�y�c�!�f��m�m��Q��3����-�c�1�)�;�C�?��a�P�P�P��q�
�J�s�O�O�Z��_�_�
=�
=�F�
�~�	���e�$�$�$�$����!�	�	�	�
�D�		�����q��6�"�"�J��$�S��_�_�$�$�%�H��$�S��_�_�$�$�%�H������C�<��$���C�<��$��	���5�)�)�)�)����!�	�	�	�
�D�	����
	�%�h��Q�ST�ef�g�g�g�g�g����!�	�	�	��7��@��G��P�QU�U�VW�V`�`�bm�op�q�q�q��1�1�1�1�1�1�����	����

�1s<�C � C4�3C4�
E�E2�1E2�6F�G�*G
�
Gc�\�	tj|��S#ttf$rYdSwxYw)zq
    Securely get status of a file or a file descriptor.

    Returns None if unable to retrieve the status.
    N)rOrwr�rQr�s rB�oslstatr�s<����x��~�~����W������t�t����s��+�+�symlinks�	overwrite�
skip_src_dirsr*�skip_dst_filesc	�*�|�g}|�g}||vrdStj|��}	tj|��}tj|j��rd}	ni||vrdS	tj|��nK#ttf$r7}
td|zdzt|
��ztd��Yd}
~
dSd}
~
wwxYwd}	n#ttf$rd}	YnwxYwd}|	st||��dkrd}|D�]6}tj
�||��}
tj
�||��}	t|
��}t!|��}|du}|r�tj|j��r{|s|r��|r||vr��tj|
��}|rCtj|j��rt'j|d��ntj|��tj||��n�tj|j��rt-|
|||||��dkrd}n�|s|r��6|r||vr��>|r|rt/|
|||��s��V|r\tj|j��rtj|��n.tj|j��rt'j|d��t1|
|��t3|
|ddd������#ttt&jf$r?}td	|
zd
z|zdzt|��ztd��d}Yd}~��0d}~wwxYw	t3||ddd���nR#ttf$r>}td|zd
z|zdzt|��ztd��d}Yd}~nd}~wwxYw|S)
z�
    Recursively copy an entire directory tree.

    This function acts like shutil.copytree, but works
    if destination directory already exists and does not fail if symlink exists.
    Copies timestamp and permissions from source subdirectories.
    NrTzERROR: failed to delete file r�r�Frp�ERROR: while copying rr�r�)rOrrwr�r�r�r{r�rQrr�rrrwrr{rr�r.r�rrr'r�r�r�r)rr�rrrr*r	�names�dstbuf�
dst_existsr�r�rr�dstname�srcbuf�dstname_existsr2r_s                   rBr'r'�sU����������
�m����q��J�s�O�O�E����#�����<���'�'�
	��J�J��n�$�$��q�
��	�#�������W�%�
�
�
��7��;�E�A�#�a�&�&�H�+�WX�Y�Y�Y��q�q�q�q�q�����
�����J����W������
�
�
�����
�E����S�#���!�#�#��E��*�*���'�,�,�s�D�)�)���'�,�,�s�D�)�)��'	�!�'�*�*�F��W�%�%�F�#�4�/�N�� 
j�D�L���8�8� 
j�!��~���!��w�.�'@�'@����W�-�-��!�+��|�F�N�3�3�+��
�g�t�4�4�4�4��	�'�*�*�*��
�6�7�+�+�+�+���f�n�-�-�
j��G�W�h�	�=�RX�Y�Y�]^�^�^��E��!��~���!��w�.�'@�'@��!��f��6F�w�PW�Y_�ag�6h�6h���!�5��|�F�N�3�3�5��	�'�*�*�*�*���f�n�5�5�5��
�g�t�4�4�4�
%�W�g�6�6�6�)�'�7�q�UV�gh�i�i�i�i�����&�,�/�	�	�	��+�G�3�F�:�7�B�4�G��C���P�R]�_`�a�a�a��E�E�E�E�E�E�����	�����!�#�s�q�Q�WX�Y�Y�Y�Y�Y���W������3�C�7��>�s�B�4�G��C���P�R]�_`�a�a�a�����������������Ls��4B>�A0�/B>�0B8�,B3�-B>�3B8�8B>�>C�C�7AK
�9K
�B'K
�)K
�1K
�	BK
�
L(�)4L#�#L(�,M�N�4N�Nrrr�c��t��	t|��}tj|j��rdSt|��}|du}|sTtj�|��}|dkr/|r-ttj�|��|��tj
|j��rot
j|��}|rCtj|j��rtj
|d��nt
j|��t
j||��n�|r|rt!||||��sdS|rCtj|j��rtj
|d��nt
j|��t#||��t%||ddd���nT#t&t(tjf$r5}	t-d|zdz|zd	z|	jzt0d��Yd}	~	dSd}	~	wwxYwdS)
a�
    Copy a source file to a specified destination.

    The algorithm is as follows:
    - if the source is a directory - fail;
    - if the source is a symlink, remove the current destination
      and create a symlink in its place that points to the same location as the source symlink;
    - otherwise - remove current destination,
      and copy the source file copying its time and permissions as well.
    r�NrKTrrprrr�)r1r{r�r�r�rrOrwrrr�r.r�rr{rr�r�r�r�rQrrr�r)
rrr�r*rr
r�
parent_dirr2r�s
          rBr&r&Z	s���O�O�O�!��g�&�&���<���'�'�	��1���!�!���t�+���	@������1�1�J��S� � �%6� ��"�'�/�/�'�2�2�J�?�?�?��<���'�'�	f��[��)�)�F��
'��<���/�/�'��M�'�4�0�0�0�0��I�g�&�&�&��J�v�w�'�'�'�'��
�&�
�2B�7�G�U[�]c�2d�2d�
��q��
'��<���/�/�'��M�'�4�0�0�0�0��I�g�&�&�&�
!��'�2�2�2�%�g�w�1�QR�cd�e�e�e�e����W�f�l�+�����'��/��6�w�>�t�C�A�J�N�P[�]^�_�_�_��q�q�q�q�q���������

�1s$�(F-�DF-�A)F-�-G>�	*G9�9G>c�j�	t|d��}n#YdSxYw|���}t|��dkrq|�d��}t|��|kr"|||kr|���dS|���}t|��dk�qdS)Nrsrr�r�)rRr�r�r�rS)r��numrr�r�r�s      rB�test_numitem_existr�	s����
�(�3�
�
������q�q����
�;�;�=�=�D��t�9�9�Q�;�;��:�:�c�?�?����M�M�C���H�S�M�T�$9�$9��H�H�J�J�J��1��{�{�}�}���t�9�9�Q�;�;�
�1s��c�$�t|d|��S�Nr�r)r��
passwdfiles  rB�test_user_existr�	s���d�1�Z�0�0�0rCc�$�t|d|��Srr)�group�	groupfiles  rB�test_group_existr�	s���e�A�i�0�0�0rCc�*�tj|��Sr<)r�	get_names)r�s rB�get_all_users_with_uidr"�	s���?�3���rCc�~�tj|ddtjdd���}|���dS)NTz	/bin/bashr^)r�r�r�r��bufsizer)r�r�r�rf)r]�procs  rBrkrk�	sE����G�"&�'2�#-�?�!%�$&�(�(�(�D������a� � rCc��	|r-tj|tjtjd���}n,tj|tjtjd���}|���\}}|r7|jdkr,t
dd�|��ztd��nQ#t$rDt
dd�|��ztd��|rtjd���wxYw|S)NTrbrrcrdr�re)r�r�r��STDOUTrfrgrrrrQr�r�)r]r��merge_stderr�
exit_on_errorr�rjrns       rBr�r��	s�����	e�� �����IZ�ae�f�f�f�A�A�� ������_c�d�d�d�A��=�=�?�?���a��	V��|�q� � ��0�3�8�8�G�3D�3D�D�k�ST�U�U�U��������'�#�(�(�7�*;�*;�;�[�!�L�L�L��	��H�Q�K�K�K�
�	�����Js
�B+B.�.AC<c��t|��}|�|��}|dkr\|||zd�}d}|t|��kr.t||��sn|dz
}|t|��k�.|d|�}|SdS)Nr^rr�r�)r�rhrLrRs       rB�get_version_strr+�	s���
��Y�Y�F�
�)�)�D�/�/�C�
�b�y�y��3�v�:�;�;������S��X�X�o�o��3�t�9�%�%�
���A�I�D��S��X�X�o�o��%�4�%�j���
�
�2rCc�v�d}d}tj�|���rt|��}t	t|����D]�}||}|r�|ddkr�|�|��dkr�|�dd��}|d���}||kr�|d���}|�d��}	|	dkr
|d|	�}|���}|�d��}|�d	��}|}n��|S)
Nr�z#/var/lib/pgsql/data/postgresql.confrr�r^r�r�rar`)	rOrwrxr%r�r�rhr�r�)
r��value�	PSQL_CONF�	psql_confrmr��v�opt_name�valr[s
          rB�get_postgres_configr3�	s���E�5�I�	�w�~�~�i� � ���i�(�(�	��s�9�~�~�&�&�	�	�A��Q�<�D��
��Q��3���4�9�9�V�+<�+<��+B�+B��J�J�s�A�&�&���Q�4�:�:�<�<���v�%�%��A�$�*�*�,�,�C��(�(�3�-�-�C��b�y�y�!�$�3�$�i���)�)�+�+�C��)�)�C�.�.�C��)�)�C�.�.�C��E��E���LrCc�0�d}tj�|��r�t|��}|D]�}|���}tt
|����D]�}||}|�d��}|�d��}|dkrh	||dz}n+#td|��tj
d��YnxYw|�d��}|�d��}|ccS����td��S)Nz#/var/lib/pgsql/data/postmaster.optsrar`z-pr�zError while parsing�port)rOrwrxr%r�r�r�r�rr�r�r3)�OPTSrlr�r0rmrNr5s       rB�get_postgres_portr7�	s��0�D�	�w�~�~�d��� ��$�����	 �	 �D��
�
���A��3�q�6�6�]�]�
 �
 ���a�D���G�G�C�L�L���G�G�C�L�L����9�9�$� ��1��v����$�#�$9�4�@�@�@�������������:�:�c�?�?�D��:�:�c�?�?�D��K�K�K�K�K��	
 ��v�&�&�&s� B,�,&Cc��d}d}t��}|dkr$td�|����|}d|z}||krt||dzg��dStj�|��rC	t	j|��dS#ttf$rt||dzg��YdSwxYwdS)Nz#/usr/share/cagefs/pgsql.socket.name�5432r�zEWarning: Port of PostgreSQL server is not detected, using default: {}z/tmp/.s.PGSQL.rr)
r7r�r;rjrOrwrxr{rQr�)�PGSQL_SOCKET_CFG�default_pg_portr5�socket_names    rB�detect_postgresr=
s��<���O����D��r�z�z�
�U�\�\�]l�m�m�n�n�n���"�4�'�K������#�k�$�&6�%7�8�8�8�8�8�
�7�>�>�*�+�+�	A�
A��	�*�+�+�+�+�+���W�%�
A�
A�
A��+�k�$�.>�-?�@�@�@�@�@�@�
A����	A�	As�>B�%B=�<B=c�"�t|��dkrdSt|��}tj|��D]�}tj�||��}	tj|��j}n #t$rtd|��Y�YwxYwtj|��r�rtj|��rt|����|tjtjzzr#|rt!d|����t!d|����dS)Nr�zlstat() failed for pathzMounted to skeleton:zCopied  to skeleton:)r�rCrOrrwrrwr�rQrr�r�r��print_suidsr�r�r�)r�mountedrrr�s     rBr?r?$
s#���#���'�!�!����c�"�"�G��
�3���7�7���'�,�,�s�D�)�)��	��8�G�$�$�,�D�D���	�	�	��1�7�;�;�;��H�	�����<����	���<����	7��� � � � ��d�l�T�\�1�2�	7��
7��,�g�6�6�6�6��,�g�6�6�6��7�7s�A6�6B�Bc���i}tj�|��rIt|d��}|D]"}|�d��d}d||<�#|���|S)Nrsr�rr�)rOrwrxrRr�rS)rwr��pfr�r�s     rB�get_users_from_passwdrC;
sj���E�	�w�~�~�d����
�$��_�_���	�	�D��:�:�c�?�?�1�%�D��E�$�K�K�
���
�
�
��LrCc��t��|dz}tj�|��sdSt	|��}|dkrt|dz��}d}t
t|����D]�}||�d��}t|��dkr�|ddvr�|ddd��d	��}g}d}	|D]}
|
|vr|�	|
���d
}	�|	r;|ddz|d
zdz}d	�
|��}||dzz
}|||<d
}��|rKt||��	tj
d|��dS#tttjf$rYdSwxYwdS)Nr rFr�r�r�)r�rrr^r�Trz:x:rZrr)r1rOrwrxr%rCr�r�r�r�rrjr��copystatrQr�r)
r�rw�
group_filerl�file_changedrmr��group_users�new_group_users�changedr�ro�tmp2s
             rB�!remove_unwanted_users_from_groupsrLG
s����O�O�O���$�J�
�7�>�>�*�%�%�����j�!�!�E���}�}�%�d�=�&8�9�9���L�
�3�u�:�:�
�
�$�$����8�>�>�#�&�&����M�M�Q���X�a�[�
�%B�%B�"�1�+�c�r�c�*�0�0��5�5�K� �O��G�#�
#�
#���5�=�=�#�*�*�4�0�0�0�0�"�G�G��
$��q�k�%�'����3�C�7���x�x��0�0���t�D�y� ����a��#������:�u�%�%�%�	��O�L�*�5�5�5�5�5����&�,�/�	�	�	��D�D�	����	�s�
E$�$F�Fc�&�i}tj�|��rotj|��D]Z}tj�||��}tj�|��rtj|��}|||<�[|Sr<)rOrwrrrr�r.)�
cl_alt_dir�linksr�rw�link_tos     rB�
read_symlinksrQp
s���E�	�w�}�}�Z� � �&��Z�
�+�+�	&�	&�E��7�<�<�
�E�2�2�D��w�~�~�d�#�#�
&��+�d�+�+��%��d����LrCc	���d}|D�]\}	||}tj�|��r|tj|��kr�Dn tj�|��r�e	tj|��n^#t$rQ}|jtjkrtj
d|�d���ntjd|��|���Yd}~nd}~wwxYwtj||����#t$rb}d|�dt|���dd	����}tj||���t|t d
��d}Yd}~��Vd}~wwxYw|S)NFzPath z does not existzError: Unable to remove path r�r�r�r�r�r�T)rOrwr�r.rr{rQr��ENOENTr8�infor�rr�r�rr)rOr�rwrPr�r�s      rB�write_symlinksrU|
s����E�����	��D�k�G��w�~�~�d�#�#�
��b�k�$�/�/�/�/��0�����t�$�$�
��
U��	�$�������
U�
U�
U��7�e�l�*�*��K� =�� =� =� =�>�>�>�>��L�!G��!G�!G�RS�T�T�T�T����������	
U����
�J�w��%�%�%�%���	�	�	�c�T�c�c�c�!�f�f�n�n�W�V`�>a�>a�c�c�C��L��q�)�)�)�)��C��a�(�(�(��E�E�E�E�E�E�����		����
�LsI�?C4�	 C4�+B�?C4�
C�
AC�C4�C�C4�4
E �>AE�E c��t||��}|j}|j|kr|tjzS|tjzr	|j|vp|tjzSr<)rr��st_uidr��S_IWUSR�S_IWGRP�st_gid�S_IWOTH)r�r�r�r�r�s     rB�is_writabler\�
sY��
��S�
!�
!�F��<�D��{�c����t�|�#�$��d�l�"�?����)>�
Y�T�D�L�EX�[rCc��d}	tj|��}n#t$rd}YnwxYw|r�tj|j��s!|r3tj�|��r|rt||��SdS	tj	|��nR#ttf$r>tj�|��rtd|ztd��YdSYnwxYw	t||��n�#t$r�}tj�|��s[d|�dt|���dd����}t#j||�	��t|td��Yd
}~dSYd
}~nd
}~wwxYwdS)a�
    Create directory if it does not exist. Check for symlink (race conditions are not handled).
    Returns True if error has occured
    :param path: path to directory
    :type path: string
    :param perm: Linux permissions
    :type perm: int
    :param allow_symlink: True = allow path to be symlink, False = delete symlink and create directory
    :type allow_symlink: bool
    :param update_perm: True = set permissions when path exists
    :type update_perm: bool
    TFzError: failed to remove r�r�r�r�r�r�N)rOrwrQr�r�r�rwr�set_permr{r�r�rrr4r�r�r8r�)rwr��
allow_symlink�update_perm�path_existsr�r�r�s        rB�make_dirrb�
s����K���x��~�~����������������� ��<���%�%�
	 �-�
	 �B�G�M�M�$�<O�<O�
	 ��
,���d�+�+�+��5�
 ��	�$�������W�%�
 �
 �
 ��7�?�?�4�(�(� ��6��=�{�A�N�N�N��4�4� � �
 ����
��T�4� � � � �������w�}�}�T�"�"�	�e�t�e�e��A�����w�Xb�@c�@c�e�e�C��L��q�)�)�)�)��C��a�(�(�(��4�4�4�4�4�		�	�	�	�	����������5s8��(�(�<B�A	C �C �$C5�5
F�?A4E>�>Fc��	tj||��dS#ttf$rt	d|zt
d��YdSwxYw)NFr�r�T)rOrrQr�rr)rwr�s  rBr^r^�
s]���
���t�����u���W������6��=�{�A�N�N�N��t�t����s��*A�Ac��	tj|||��dS#ttf$rt	d|zt
d��YdSwxYw)NFz"Error: failed to set ownership to r�T)rOr�rQr�rr)rwr�r�s   rB�	set_ownerre�
s_���
���s�C� � � ��u���W������4�t�;�[�!�L�L�L��t�t����s��*A�Ac��|D]}}t|��}d}|D]g}tj�||��}tj�||��}	t	|	|||��}
|
�nt|
���h�~dS)Nr�)r�rOrwrrr)�basepath�
real_homepathr�r��personal_mountsr7rrwrr�r�s           rB�fix_owner_of_personal_mountsrj�
s��� �����5�!�!�����	�	�D��7�<�<��d�+�+�D��g�l�l�8�T�2�2�G�%�g�s�C��G�G�B��z����B�K�K�K�K���rCc�&�|sdSg}|rddlm}|dd���}|j}|D�]j}	tj|��}n#t
j$rY�*wxYwtj�	|j
��}tj�|j
d��}	tj�|	d��}
t||j
��r#td|zdz|zd	ztd
����t!|	|j
|j|��}|���t%|	d||���}|���t'|��t)|j
|j��t+|
��t-��|rt/|	||j
|j|����ldS)
NrrGT��skip_errors�skip_cpanel_checkz.cagefsz.cagefs.enabledz)Warning: skipping .cagefs chown for user z: home z is owned by another userr�i�)r�)rIrHrir�get_pw_by_namer-�NoSuchUserExceptionrOrwr��pw_dirrr#�pw_uidrrr�pw_gidrrrrrrj)r��is_user_enabled�	fix_ownerrirH�	mp_configr��pwrhrw�status_flagr�s            rB�
update_statusry�
s��������O��4�.�.�.�.�.�.�$�$���N�N�N�	�#�3���$e�$e��	��%�d�+�+�B�B���(�	�	�	��H�	������(�(���3�3�
��w�|�|�B�I�y�1�1���g�l�l�4�):�;�;��$�M�2�9�=�=�	��?�$�F�� �"/�0�2M�N���
$�
$�
$�
�"�$��	�2�9�m�
L�
L��
�:��
 ��u�m��
C�
C�
C��
�:��������b�i���+�+�+��;�'�'�'������	e�(��}�b�i���Tc�d�d�d��I$e�$es�>�A�Ac�\�td}td}t|d|dg��S)Nr{r|�-cz-i)r�r�)�php_path�php_ini_paths  rB�get_php_infor~+s-���Y�'�H� ��+�L��H�d�L�$�7�8�8�8rCc���td}td}	t��rt|dgdd���}nt|d|dgdd���}n#t$rd	}YnwxYw|S)
Nr{r|raTF)r(r)r{z-qmr�)r�r(r�rQ)r|r}�results   rB�get_list_of_php_modulesr�1s����Y�'�H� ��+�L�����	l��h��-�D�PU�V�V�V�F�F��h��l�E�B�QU�ej�k�k�k�F����������������Ms�9A�A%�$A%c�>�tdkrt��t���d��}ia|D]K}|rG|�d��s2|�dd�����}dt|<�Ltt��S)Nrr�[rdrnr�)�php_modulesr�r�r�rgr��lower�list)rlr��module_names   rB�get_php_modulesr�Cs����d�������'�)�)�/�/��5�5�����	-�	-�D��
-�T�_�_�S�1�1�
-�"�l�l�3��4�4�:�:�<�<��+,��K�(������rCc�V�t��d}iatj�|��ryt	|��}|D]g}|���}|dkrK|���}t|��dkr$|ddkr|d}|dt|<�htS)N�/etc/cl.selector/selector.confr�r�rrzr�rZ)�alt_versionsrOrwrxr&r�r�r�)�CL_ALT_CONFrlr�r��verss     rB�get_alt_versionsr�Ts�����6����
�7�>�>�+�&�&�		3�$�[�1�1�E��
3�
3���{�{�}�}���2�:�:������B��2�w�w�!�|�|��1�����!�!�u��-/��U��T�*���rCrzc�>�tdkr�d}iatj�|��r�t	|��}|D]�}|���}|dkrg|���}t|��dkr@|d}|d}|d}	|tvrt|}
ni}
|	|
|<|
t|<��|tvrP|r,tt|�	����S|t|vrt||SdS)Nr�r�r�rr�r�)
�alt_confrOrwrxr&r�r�r�r��keys)r�r\�get_aliasesr�rlr�r��	cur_alias�cur_vers�cur_path�temps           rB�get_alt_confr�ls���4���6����
�7�>�>�+�&�&�	2�$�[�1�1�E��
2�
2���{�{�}�}���2�:�:������B��2�w�w�!�|�|�$&�q�E�	�#%�a�5��#%�a�5��#�x�/�/�#+�H�#5�D�D�#%�D�*2��Y��-1���*���x����	)�����+�+�-�-�.�.�.�
�h�t�n�
$�
$��D�>�%�(�(��4rCc�l�|dkrtt��St|d���}|dkrgS|S)N�nativeT)r�)r�r�r�)r��aliasess  rB�get_alt_aliasesr��s@���x����M�"�"�"��t�4�8�8�8���d�?�?��I��rCc��	||z}tj�|��sdSt||��S#tt
f$rYdSwxYw)z�
    Check if .so file has changed by comparing with its copy in skeleton.
    Returns True if file needs ldd re-scan (changed or not in skeleton).
    T)rOrwr#r�rQr�)rw�
skeleton_path�
skeleton_files   rB�_is_so_file_changedr��sc��
�%��,�
��w�~�~�m�,�,�	��4���m�4�4�4���W������t�t����s�$8�8�A
�A
�skeletonc��d}g}g}t��D]�}d|z}|dz}|dz}tj�|��r|�|��n�Gtj�|��r|�|��tj�|��r|�|����g}|rEgd�}	|�t
|g|z|	zgd�z���d����|r>|�t
|g|zdd	gz���d����t��}
|D]o}|rkt|��}|�t||��r5t|��}|
�|��t||���Z|
�|���pt|
��S)
Nz
/usr/bin/findz	/opt/alt/z/usr/binz	/usr/sbin)	�(�-pathz
*/usr/include�-or�z*/usr/share�)z-pruner�)z-namez*.soz-printrrz-typer~)r)rOrwrr�r�r�r��setrTr�r�r*rOr�)
r��FIND�altpaths�binpaths�altdirrw�binpath�sbinpathr/�prunerN�cached_libs�result_libss
             rB�get_alt_php_libsr��s���D��H��H��.�.�&�&���V�#����#���+�%��
�7�=�=����	��O�O�D�!�!�!�!��
�7�=�=��!�!�	%��O�O�G�$�$�$�
�7�=�=��"�"�	&��O�O�H�%�%�%���E��
�

�
�
��	���W�
�F�X���%�(C�(C�(C�C�
�
�
�%��+�+�	�	�	��N�
���W�d�V�h�.�'�3��?�@�@�F�F�t�L�L�M�M�M��5�5�D��
)�
)���		)�,�T�2�2�K��"�&9�$��&I�&I�"�*�4�0�0�����K�(�(�(� ��{�3�3�3�3����K�(�(�(����:�:�rCc���	tdzt|��zdz|zdz}n#t$rYdSwxYw|dz}tj�|��s&|dz}tj�|��sdStj|��}|�d��rdS|�d��r5|�dd��}|d|�	d���}|SdS)	NrKrrzr}z/usr/selector/r�z/opt/alt/phpr�)
rr!r"rOrwr�r.rgr�rh)�usernamerw�
user_php_filerP�php_vers     rB�get_php_version_for_userr��s��
���}��x�8�8�8�3�>��I�L_�_���������t�t������5�L�M�
�7�>�>�-�(�(���w��
��w�~�~�m�,�,�	��4��k�-�(�(�G����*�+�+���x����.�)�)���/�/�.�"�5�5���,�7�<�<��,�,�,�-�����4s�#&�
4�4zcl.php.drz.cl.selectorzdefaults.cfgc	��||D]�}|dz}tj�||��}tj�d|dd|��}tj�|��s�t	|��	tj||����#t$r_}d|�dt|���dd����}	tj
|	|�	��t|	td
��Yd}~��d}~wwxYw��dS)Nr��/opt/altr�	php.d.allr�r�r�r�r�r�)
rOrwrr�rrrQr�r�r8r�rr)
�php_versr�r�r�mod�	link_name�	link_pathrPr�r�s
          rB�enable_extensions_symlinksr�s���8�$�-�-���&�L�	��G�L�L��)�4�4�	��'�,�,�z�7�E�;�	�R�R���w�~�~�i�(�(�	-��y�)�)�)�
-��
�7�I�.�.�.�.���
-�
-�
-�l��l�l�s�1�v�v�~�~�V]�_i�Gj�Gj�l�l����S�1�-�-�-�-���[�!�,�,�,�,�,�,�,�,�����
-����		-�	-�-s�B�
D�"AC<�<Dc�0�|tv�ri}tj�|���r�tj|��D�]�}|dz|z}|�d���r�tj�|���r}|dtd���}g||<t|��}|D�]M}|�	��}|�
d��s|�
d���r|�d��r|�dd��}n+|�d��r|�dd��}|�d	d
��}t|��dkr�|d
�d��rptj�
|d
�����}|dtd���}||kr||�|����O���|t|<t|S)
al
    Return dependencies of php modules (extensions), determined by parsing of ini files in specified directory
    :param alt_dir: path to directory where ini files are (something like '/opt/alt/php54/etc/php.d.all')
    :type alt_dir: string
    :return: something like { 'mailparse' : ['mbstring'], 'xsl' : ['dom'], 'xmlreader' : ['dom'] }
    :rtype: dict
    rKr�N�	extension�zend_extensionr`r�rar�r�rZr5)�
deps_cacherOrwrrr�rxr�r&r�rgr�r�r�lstripr�)�alt_dir�deps�ini_file�ini_path�extnamer�r��exts        rB�get_dependenciesr�s����j� � ���
�7�=�=��!�!�	>��J�w�/�/�
>�
>��"�S�=�8�3���$�$�V�,�,�>������1I�1I�>�&�}��V����}�5�G�$&�D��M�/��9�9�H� (�>�>��#�{�{�}�}���?�?�;�7�7�
>�4�?�?�K[�;\�;\�
>�#�}�}�S�1�1�=�'+�|�|�C��'<�'<���!%���s�!3�!3�=�'+�|�|�C��'<�'<��!%���C��!3�!3�B� #�B���1���"�Q�%�.�.��2G�2G��&(�g�&6�&6�r�!�u�|�|�~�~�&F�&F��&)�,�C��J�J�;�,�&7��#*�c�>�>�$(��M�$8�$8��$=�$=�$=���"�
�7���g��rCc��||vr7||D]}t|||���||vr|�|��dSdSdSr<)�get_load_orderr���
load_orderr�r��deps    rBr�r�:sg��
�d�{�{���9�	2�	2�C��:�t�S�1�1�1�1��j� � ����c�"�"�"�"�"�	�{�!� rCc��||vrC||D]}||vr||vr|�|��� ||vr|�|��dSdSdSr<)r�r�s    rB�get_load_order_not_recursiver�Dsz��
�d�{�{���9�	'�	'�C��*�$�$������!�!�#�&�&�&���j� � ����c�"�"�"�"�"��{�!� rCc�8�|�t|��}ttfD]y}g}	d||vr|||d��nd||vr
|||d��||D]}|dvr
||||���n(#t$r|st	dt
d��Y�vwxYw|S)aG

    :param php_vers: something like 'php5.4'
    :type php_vers: string
    :param php_modules: { 'php5.3' : ['dom', 'xmlreader'], 'php5.4' : ['dom', 'xsl'] }
    :type php_modules: dict
    :param ini_path: path to directory where ini files are (something like '/opt/alt/php54/etc/php.d.all')
    :type ini_path: string
    N�ioncube_loader�ioncube_loader_4)r�r�z^Error: cyclic dependencies of PHP modules detected. Depth of dependencies will be limited to 1r�)r�r�r��RuntimeErrorrr)r�r�r�r��quiet�funcr�r�s        rB�build_load_orderr�Ns���|���)�)���!=�>�J�J���
�	J��;�x�#8�8�8���Z��'7�8�8�8�8�#�{�8�'<�<�<���Z��'9�:�:�:�"�8�,�
0�
0���D�D�D��D��T�3�/�/�/���E���	J�	J�	J��
J��x�{F�HI�J�J�J���	J�����s�AA2�2"B�B�
document_rootc�f�|�dS|�'tj�|t|��}n6t	|��}	tj�|t|	|��}tj�|��sdSt
|||d���}
t�rts<t�5	tjt���a	n#ttf$rdaYnwxYwtr|
S|stj|��}t!��}t�|
||���}tjstjstjrX|rd|z}
nd}
|
d	|zd
z|zz
}
|r	|
d|zz
}
n|
dz
}
t+|
tjtjtj��n|
}|S)
a�
    Read custom PHP settings from user's backup directory
    :param homepath: User's home directory path
    :param filename: Configuration filename (e.g., 'alt_php54.cfg')
    :param uid: User ID
    :param gid: Group ID
    :param php_vers: PHP version
    :param user_name: Username
    :param alt_php_ini_file: Path to alternative PHP INI file
    :param document_root: Optional document root for per-domain configuration
    :return: PHP settings lines or None
    NF)r))�phpconf_pathT)�input_phpini_linesr�zUser: z
User: Unknownz; PHP version: z#
                     Backup file: z(
                     Destination file: z/
                     Destination file: Unknown)rOrwr�CL_ALT_BACKUP_DIRr*rxr
�validate_alt_php_ini�$bad_try_init_phpinivalidator_trigger�php_ini_validator�phpinivalidator�PHPINIvalidator�PHP_CONFrQr��get_php_verr��validate�unknown_options�invalid_values_options�invalid_optionsr�)�homepathrr�r�r��	user_name�alt_php_ini_filer��backup_path�
website_id�
php_ini_lines�alt_vers�output_lines_list�log_messages              rB�read_custom_php_settingsr�ps��� ���t����g�l�l�8�->��I�I���$�M�2�2�
��g�l�l�8�->�
�H�U�U��
�7�>�>�+�&�&���t�$�[�#�s�E�R�R�R�M��*�3�	<�8I�8Q�
<�$3�$C�QY�$Z�$Z�$Z�!�!���W�%�
<�
<�
<�7;�4�4�4�
<����/�	!� � ��	@�&�2�;�?�?�H�#�%�%��-�6�6�-�ai�jr�as�6�t�t���,�
	_�0A�0X�
	_�\m�\}�
	_��
.�&��2���-���,�x�7�:`�`�cn�n�n�K��
R��J�M]�]�]����Q�Q��!�+�/@�/P�Rc�Rz�}N�}^�
_�
_�
_��*���s�/C
�
C �C r�r�r�rr�r�r�r�c	
���tj�d|dd��}	t|||	��}
g}|
D]�}|�d|zdz��|	dz|zdz}
t|
��}|D]K}|���}|r3|�d��s|d	z
}||vr|�|���L|�d	����tj�|d
��}	t|d|zdz|||d
d�|||���}n#ttf$rd}YnwxYw|�*|�|��|�d	��t||||��dS)a�
    Enable specified extensions for specific php version and user
    :param php_vers: PHP version, something like 'php5.4'
    :param php_modules: Extensions enabled for different PHP versions for the user, e.g. {'php5.3': ['dom', 'xmlreader'], 'php5.4': ['dom', 'xsl']}
    :param dirpath: Path where generated alt_php.ini file is written to (e.g. '/var/cagefs/prefix/user/etc/cl.php.d/alt-php54')
    :param dirname: Name of directory for specified PHP version inside /opt/alt directory (e.g. 'php54')
    :param uid: User ID
    :param gid: Group ID
    :param homepath: Path to home directory of user (e.g. '/home/user')
    :param user_name: Name of user
    :param document_root: Optional document root for per-domain configuration
    r�rr�z;---z---
rKr��;rr�alt_php.ini�alt_z.cfgr�N)r�r�r�r�)
rOrwrr�r�r&r�rgr�rQr�r�r)r�r�r�rr�r�r�r�r�r�r��alt_php_ini�module�module_ini_path�
module_inir��
user_ini_path�custom_php_settingss                  rB�enable_extensionsr��s����w�|�|�J����D�D�H�"�(�K��B�B�J��K��!�!�����6�&�=��0�1�1�1�#�S�.�6�1�F�:��&�o�6�6�
��	-�	-�D��;�;�=�=�D��
-�D�O�O�C�0�0�
-������{�*�*��&�&�t�,�,�,�����4� � � � ��G�L�L��-�8�8�M�
#�7�x�7=�g�~�f�7L�7:�7:�@H�����AJ�HU�ER�T�T�T����
�W��#�#�#�"����#�����&����.�/�/�/����4� � � ��k�=�#�s�;�;�;�;�;s�4%D�D0�/D0�userpath�def_vers�cl_alt_def_modules�vers_changed�def_vers_old�force�rebuildc
��t��}
|dkrd}|dkrd}|dkri}|dkri}tj�|��}d}|
D]�}d|z}d|�dd��z}d|z}tj�||��}tj�|d��}tj�|��r|	s|
rWt|d|||��r��||vs|	r%||vr||||<nt��}|||<d	}t|||||||||�
�	�	��|r|}n|}|s|rt||||||���dSdS)Nr�Frzr�r�zalt-r�r�T)r�r�r�)r�)r�rOrwr�r�rr�r$r�r��write_cl_alt_to_backup)r�r�r�r�r�r�r�rrrrr�r�r��
real_userpath�modules_changedr�r�rr�r�r��modules�new_verss                        rB�select_default_php_modulesr
�s����!�!�H��4������t������d������T�!�!����G�$�$�X�.�.�M��O��;�;���4�<���$�,�,�s�B�/�/�/���'�!���'�,�,�x��0�0������W�m�<�<�
�����
�.�.�	;�5�	;�G�	;��G�U�C��m�D�D�
����+�+��+��1�1�1�,>�x�,H�K��)�)�-�/�/�G�,3�K��)�"&��
�h�)�%�%�!�!�'/�(1�,9�
;�
;�
;�
;��"� �������g��g��x��;��S�Xe�f�f�f�f�f�f�g�grCc�2�|�,tj�|tt��}n;t|��}tj�|t|t��}t
||��t|��}t��|S)z�
    Read CloudLinux alternatives backup file for a user
    :param homepath: User's home directory path
    :param document_root: Optional document root for per-domain configuration
    :return: Tuple of (version, modules, state, other)
    )	rOrwrr��CL_ALT_DEFAULTSr*r�read_cl_alt_backupr)r�r�r�r�r�r�r�s       rB�read_cl_alt_backup_as_userr8
sx�����g�l�l�8�->��P�P���$�M�2�2�
��g�l�l�8�->�
�O�\�\���#�s����
��
,�
,�F��O�O�O��MrCc�b�	t|��}n#ttf$rYdSwxYwtjdd���}	|�|��n#tj$rYdSwxYw	t|dd��d}n#t$rYdSwxYwi}i}i}|�	��D�] }|�
dd��}|�d��r�t|td��d���r�t||d	��||<|�|d
��rg|�|d
���������d��rd||td��d�<��|dvr8i}	|�|��D]}
|�||
��|	|
<�|	||<��"d
|vrTd
|d
vrJ|d
d
�������d��rd|d<||||fS)N�NNNNF��
interpolation�strict�versionsrzrr�r�r�state�disable)r�	phpnativer�)rrQr��configparser�ConfigParser�readfprr��
IndexError�sectionsr�rgrPr�r�r�r�r��options)r��backup_file�cfgr�r�	php_state�other�sectionrrr�s           rBr
r
M
s���&�+�K�8�8�����W��&�&�&�%�%�%�&�����
#�$�u�
E�
E�
E�C�&��
�
�;��������&�&�&�%�%�%�&����&�,�S�*�e�D�D�Q�G�����&�&�&�%�%�%�&�����G��I��E��<�<�>�>�
%�
%���/�/�#�r�*�*�����e�$�$�	%��'�#�e�*�*�+�+�2F�)G�)G�	%�8��g�y�Q�Q�G�G���~�~�g�w�/�/�
8�S�W�W�W�g�5N�5N�5T�5T�5V�5V�5\�5\�5^�5^�5i�5i�js�5t�5t�
8�27�	�'�#�e�*�*�+�+�.�/��
�M�
)�
)��G��+�+�g�.�.�
;�
;��"%�'�'�'�6�":�":�����$�E�'�N���u���7�e�K�.@�#@�#@�u�[�GY�Za�Gb�Gh�Gh�Gj�Gj�Gp�Gp�Gr�Gr�G}�G}�H�HI�HI�#@�#�	�(���W�i��.�.s0��'�'�A�A*�)A*�.B�
B�Bc�:�tdkr;tdkr0tdkr%tdkrttttfSt	t
j�tt����\aaaattttfSr<)
�cl_alt_def_versr��cl_alt_def_php_state�cl_alt_def_otherr
rOrwrrrrGrCrB�read_cl_alt_defaultsr'|
s����$���#5��#=�#=�BV�Z^�B^�B^�cs�w{�c{�c{�� 2�4H�JZ�Z�Z�Rd�eg�el�eq�eq�sB�DS�fT�fT�SU�SU�O�O�'�)=�?O��.�0D�FV�V�VrCc�P�|dkr-tj�tt��}d}	n�|�&tj�|t
��}
n5t
|��}tj�|t
|��}
tj�|��}t|
d|||��rdStj�|
t��}d}	g}
|
�	d��|
�	d|zdz��|dkri}|D]�}|
�	d|zd	z��|
�	d
d�||��zdz��|dkr8|td��d�}||vr||s|
�	d
����|dkrU|D]R}|
�	d|zd	z��||D],}|
�	|dz|||zdz���-�St|
||||	��dS)z3
    Write CloudLinux alternatives backup file
    NFr�Tz[versions]
zphp=rrz
[z]
zmodules=r�rzzstate=disabled
r�)rOrwrrrr�r*r�r$r�r�r)r�r�rr�r�rr!r�r��	drop_perm�
backup_dirr�rh�backupr"r�r�s                 rBrr�
s3���4����g�l�l�?�O�D�D���	�	�� �����h�0A�B�B�J�J�(�
�6�6�J�����h�0A�:�N�N�J���(�(��2�2�
��
�E�3��]�C�C�	��F��g�l�l�:��?�?���	��F�
�M�M�.�!�!�!�
�M�M�&��/�$�&�'�'�'��$������2�2���
�
�e�G�m�E�)�*�*�*��
�
�j����'�'�*:�!;�!;�;�D�@�A�A�A��D�=�=��3�u�:�:�;�;�'�D���
�
��d��
��
�
�0�1�1�1����}�}��	F�	F�G��M�M�%��-��-�.�.�.���.�
F�
F���
�
�f�S�j��w���)?�?��D�E�E�E�E�
F��f�k�3��Y�?�?�?�?�?rCc�j�g}tdd��5}|D�]}|s2|�d��dkr�|�d��dkr�|���}|d}|d�d��}	|rd	|	vr�u|rd
|	vr�||sU|�tdz��dks4|rb|�d��dks|�d
��dkr0|�||�d��d�����	ddd��n#1swxYwY|S)a:
    Return list of mounts points
    :param all_cagefs_mounts: return CageFS mounts points only
    :param without_nosuid: return mount points without 'nosuid' attribute
    :param rw_mounts_only: return rw mount points only (i.e. mounts without 'ro' attribute)
    :param all_mounts: return all mount points
    z/proc/mountsrszcagefs-etcfsr^zcagefs-varfsr�r�r��nosuid�rorKz/var/cagefs/z	/.cagefs/N)rRrhr�r	r�)
�all_cagefs_mounts�without_nosuid�rw_mounts_only�
all_mountsr@r>r�r��
mountpoint�optss
          rB�get_mounted_dirsr5�
s����K�	
�n�c�	"�	"�J�f��	J�	J�D��

J�T�Y�Y�~�6�6�"�<�<����>�AZ�AZ�^`�A`�A`��J�J�L�L���q�T�
���t�z�z�#����!��h�$�&6�&6��!��d�d�l�l���J�����#��!>�!>�"�!D�!D�)�"E�/9���~�/N�/N�RT�/T�/T�Xb�Xg�Xg�hs�Xt�Xt�xz�Xz�Xz��&�&�z�*�/�/�#�2F�2F�2G�2G�'H�I�I�I��	J�J�J�J�J�J�J�J�J�J�J�J����J�J�J�J��s�DD(�(D,�/D,c��tjd��}t��}|r�tjd��D]m}|�t|����}|rGtj�|��r(|�	|�
d�����nndtj��}|D]N}||j
}|�|��}|r(|�	|�
d�����O|S)zh
    Returns set of base home directories like {"/home0", "/home1", .., "/home9"} including "/home"
    z(/home\d?)/z/home*r�)r��compiler�r�r�r�rOrwr�addrr�
get_user_dictrq)�use_glob�pattern�dirsrw�mrwr�r�s        rB�get_homeN_dirsr>�
s����j��(�(�G��5�5�D��%��I�h�'�'�	%�	%�D��
�
�h�t�n�n�-�-�A��
%�R�W�]�]�4�(�(�
%����������$�$�$��	%�
�
 �
"�
"���	%�	%�D��d�8�?�D��
�
�d�#�#�A��
%����������$�$�$���KrCc�@�t|��}|tvrx	t|��}tj|j��rt
j|��x}t|<ngx}t|<n0#ttf$rgx}t|<YnwxYwt|}|Sr<)
r��
listdir_cacher{r�r�r�rOrrQr�)rwr�rzs   rB�cached_listdirrA�
s����d���D��=� � �	+���%�%�D��|�D�L�)�)�
/�,.�J�t�,<�,<�<��m�D�)�)�,.�.��m�D�)�����!�	+�	+�	+�(*�*�C�-��%�%�%�	+�����D�!���Js�AA.�.B�
Bz/etc/cagefs/custom.etc/c�*�tt��Sr<)rA�
CUSTOM_ETCrGrCrB�get_custom_etc_listrDs���*�%�%�%rCr��
user_etc_pathc�F�it||���t||���S)ag
    Get additional files for a user
    to be placed within their '/etc' directory.

    This includes retrieving files added
    by the 'custom.etc' directory mechanism
    and mount points defined in the 'cagefs.mp' file.

    Args:
        username: The user's name
        user_etc_path: The user etc path, like '/var/cagefs/<prefix>/<username>/etc'
    )�get_custom_etc_files_for_user�!get_etc_dirs_from_mounts_for_user)r�rEs  rB�!get_additional_etc_files_for_userrIs0���
'��-�
@�
@��
+�H�m�
D�
D��rCc���i}|t��vr`t|z}	t|��}n#ttf$r|cYSwxYwtj|j��rt||||���|S)a&
    Get a list of additional files for a user,
    which have been added to the user's '/etc' directory
    by utilizing the 'custom.etc' directory mechanism.

    Args:
        username: The user's name
        user_etc_path: The user etc path, like '/var/cagefs/<prefix>/<username>/etc'
    r)	rDrCr{rQr�r�r�r�r)r�rE�etc_listrwr�s     rBrGrGs����H��&�(�(�(�(��H�$��	���%�%�D�D����!�	�	�	��O�O�O�	�����<���%�%�	X��T�8���W�W�W�W��Os�.�A�Ac��ddl}i}|�dd���}|j}|j}t	||||��	tt
j|����}n#tj$r|cYSwxYwt	||||��|S)a�
    Get a list of additional directories for a user,
    which have been added to the user's '/etc' by defining
    additional mount points within the 'cagefs.mp' file.

    Process only the mount points splitted by username or UID,
    as only these are mounted to the user's '/var/cagefs/.../etc',
    which is subsequently mounted to the skeleton's '/etc'.

    Args:
        username: The user's name
        user_etc_path: The user etc path, like '/var/cagefs/<prefix>/<username>/etc'
    rNTrl)	rIrH�splitted_by_username_mounts�splitted_by_uid_mounts�_process_etc_mountsr�r�get_uidrp)r�rErIrKrvrMrN�user_uids        rBrHrH2s��������H��*�*�t�t�*�T�T�I�"+�"G��&�=���3�X�}�h�W�W�W���u�}�X�.�.�/�/�����$�������������.��-��R�R�R��Os�!A!�!A5�4A5r>�user_identifierrKc�8�|D]�}|�d��r|t|��vr�)|�ddd��}|�d��}|�|��|}|D]'}t
j�||��}d||<�(��dS)aq
    Process mount points and construct a list of '/etc' ones
    and their respective user subdirectories.

    Retrieve a list of contents within the mount point,
    and if it contains the user's identifier
    (UID for mount points splitted by UIDs,
    or username for mount points splitted by usernames),
    add all the subdirectories to the resulting list.
    rr�r�rKN)rgrAr�r�r�rOrwr)r>rRrErKrw�parts�current_path�parts        rBrOrOTs����
'�
'�����w�'�'�	�?�.�QU�BV�BV�+V�+V���|�|�G�R��+�+���
�
�3����
���_�%�%�%�$���	'�	'�D��7�<�<��d�;�;�L�%&�H�\�"�"�	'�
'�
'rCc�t�|t��v�r"t|z}	t|��}n#ttf$rYdSwxYwtj|j��r�tj	|��D]�}|tttfvr�|dz|z}|dz|z}	t|��}nJ#ttf$r6}td|zdzt|��ztd��Yd}~�{d}~wwxYwtj|j��rt!||d�����t#||d�����dSdSdS)NrKzError: lstat() failed file r�r�Tr))rDrCr{rQr�r�r�r�rOrr�CL_PHP_DIR_NAME�ETC_VERSION_NAMErr�rr'r&)r�rEr�r�rrr�r�s        rB� update_custom_etc_files_for_userrZns����"�$�$�$�$��D� ��	���%�%�D�D����!�	�	�	��F�F�	�����<���%�%�
	<��J�t�,�,�
<�
<���[�/�CS�#U�U�U���*�x�/�C�(�#�-��8�D�!�+�C�0�0����#�W�-�!�!�!�� =�� C�e� K�c�RS�f�f� T�Va�cd�e�e�e� ���������!�����|�D�L�1�1�<� ��d�T�:�:�:�:�:�!�#�t�d�;�;�;�;��'%�$�
	<�
	<�
<�
<s'�-�A�A�B+�+C2�<,C-�-C2z/usr/share/cagefs/custom.etc/c�2�tt��rdSdSr�)rA�CUSTOM_ETC_LOGrGrCrB�custom_etc_presentr]�s���n�%�%���t��5rCc��	tt��}nY#ttf$rEt	jd��}t	jtd��t	j|��YnwxYw|rtt|z|d���dS	t	jt|z��dS#ttf$rYdSwxYw)Nr�T�r=)	r{r\rQr�rOr�r�rjr{)r��
list_of_filesrnr�s    rB�save_custom_etc_logrb�s������(�(�����W������h�q�k�k��
����'�'�'�
���������������>�$�&�
��F�F�F�F�F�F�	��I�n�T�)�*�*�*�*�*����!�	�	�	��D�D�	���s"��AA-�,A-�B-�-C�Cc��g}|tt��vr�tt|z��}|D]�}|���}||vri|�dt
z��sL|�dtz��s/|�t��s|�|����|�	��|Sr�)
rAr\r%r�rgrrX�ETC_VERSIONr��sort)r�rarz�old_listrws     rB�get_custom_etc_files_to_deleterg�s���
�C��~�n�-�-�-�-��^�D�0�1�1���	%�	%�D��;�;�=�=�D��=�(�(�����K��8�8�%�D�O�O�C�P_�L_�<`�<`�%�dh�ds�ds�t�eA�eA�%��J�J�t�$�$�$�����
�
�
��JrCc��t|��}t��}|D]}|�||d���� |Sr<)r�r�r8)rrw�plenrzr�s     rBrr�sG���t�9�9�D�

�%�%�C�
��������$�%�%�������JrCc���	tj|��}n#t$rYdSwxYwtj|j��sdS|jdkp|jdkp|jtjzS)NFr)	rOrwrQr�r�r�rWrZr[)rwr�s  rB�is_path_securerk�s}����x��~�~���������u�u������<���%�%���u��+��"�Z���q�(8�Z�d�l�T�\�>Y�\�\s��
%�%c�,�t�dStj�t��rtt��sdadSt
jdd���a	t�t��dS#tj	$rdaYdSwxYw)NFr)
�cagefs_ini_cfgrOrwrx�
CAGEFS_INIrkrrrzrrGrCrB�read_cagefs_iniro�s����!����G�N�N�:�&�&���z�0J�0J������!�.�T�%�P�P�P�N�����J�'�'�'�'�'���������������s�A>�>B�Bc���d}t��t�|Sttdd��}	t|d��}|dkrd}n#tt
f$rd}YnwxYw||zS)Ni�Qr��update_period_daysrr�)rormr�r�r�r)�seconds_in_24hrz�dayss   rB�get_update_periodrt�s����N���������
#�N�H�>R�
S�
S�C���3�q�6�{�{���!�8�8��D����
�#�������������D� � s�A�A%�$A%c���t��t�tjdd���at�|��st�|��t�|||��ttd��}t�	|��|�
��ttdd��ttd��dS)NFrrrr)
rormrr�has_section�add_sectionr�rRrnr�rSrer^)r"r�r-r�s    rB�set_cagefs_ini_optionrx�s���������%�2��e�T�T�T���%�%�g�.�.�,��"�"�7�+�+�+����w���.�.�.��J��$�$�H�����"�"�"��N�N����
�j�!�Q�����Z������rCc�B�tddt|����dS)Nr�rq)rxr�)rss rB�set_update_periodrzs!���(�$8�#�d�)�)�D�D�D�D�DrCc���tj�d��}|rdnd}t��t�|St�dd��rt�dd��S|S)Nz%/opt/alt/tmpreaper/usr/sbin/tmpreaperz)/opt/alt/tmpreaper/usr/sbin/tmpreaper 720z/usr/sbin/tmpwatch -umclq 720r��tmpwatch)rOrwrxrormr�r�)�	is_ubuntu�TMPWATCHs  rB�get_tmpwatch_paramsrsq������F�G�G�I�>G�l�:�:�Ml�H���������� � ��:�6�6�8��!�!�(�J�7�7�7��OrCc�(�tdd|��dS)Nr�r|)rx)�
params_strs rB�set_tmpwatch_paramsr�s���(�J�
�;�;�;�;�;rCc�\�t��t�gSttdd��S)Nr��
tmpwatch_dirs)rormr�rGrCrB�get_tmpwatch_dirsr�s+���������	�$�^�X��O�O�OrCz&/usr/share/cagefs/last_update_time.txtc	��ttttt	j������gd���tjtd��dS)NTr`i�)rj�LAST_UPDATE_TIMEr�r��timerOrrGrCrB�save_last_update_timer�$sJ����#�c�$�)�+�+�&6�&6�"7�"7�!8�D�I�I�I�I��H�
�u�%�%�%�%�%rCc���tj�t��rSt	t��}	t|d�����S#ttf$rYnwxYwdSr)	rOrwrxr�r%r�r�r�r)�contents rB�read_last_update_timer�)st��	�w�~�~�&�'�'���,�-�-��	��w�q�z�'�'�)�)�*�*�*���J�'�	�	�	��D�	�����1s�&A!�!A5�4A5c��t��}|dkrdSt��}ttj����}|||zkS)NrT)rtr�r�r�)�
update_period�last_update�current_times   rB�#update_of_cagefs_skeleton_is_neededr�4sK��%�'�'�M������t�'�)�)�K��t�y�{�{�#�#�L��K�-�7�8�8rCc��t|��}|sdSt|��}|sdStj|j��r�tj|j��sdSt	j|��}|���t	j|��}|���||krdS|D]&}|dz|z}|dz|z}	t||	|��sdS�'dStj|j��rdS|s2tj|j��stj|j��rt||||���Stj||d���S)NFrKT)r�r�)�shallow)rr�r�r�rOrre�are_dirs_equalr�r��filecmp�cmp)
�dir1�dir2r��sbuf1�sbuf2�listdir1�listdir2r�path1r0s
          rBr�r�Dsn���D�M�M�E����u��D�M�M�E����u��|�E�M�"�"���|�E�M�*�*�	��5��:�d�#�#���
�
�����:�d�#�#���
�
�����x����5��	�	�D��3�J��%�E��3�J��%�E�!�%���8�8�
��u�u�
��t�	
��e�m�	$�	$���u��8�$�,�u�}�-�-�8���e�m�1L�1L�8���d�%�u�E�E�E�E��{�4���7�7�7�7rCc�,�tjtj�|d����}t	j��}|D]K}	tj|��}|j}||z
|krtj|���<#t$rY�HwxYwdS)z�
    Clean directories from old files
    :param dir_path: Dir path to clean
    :param max_lifetime: Max lifetime for clean
    :return: None
    zsess_[a-z0-9]*N)	r�rOrwrr�r��st_ctimer{rQ)�dir_path�max_lifetime�sessions�cur_time�sessrN�ctimes       rB� clean_dir_from_old_session_filesr�fs����y�����h�0@�A�A�B�B�H��y�{�{�H�����	����
�
�A��J�E��%��,�.�.��	�$�������	�	�	��D�	����
�s�8B�
B�Br�c�R�	t|d��5}|���D]�}|���}|�d��r�,|�d��r2d|vr.|�d��d���}�s|�d��r,d|vr(t|�d��d��}��	ddd��n#1swxYwYn#tttf$rYnwxYw|�d��|fS)	au
    Read php.ini and returns session.save_path and session.gc_maxlifitime options
    :param str path: Path to ini file
    :param int default_time: Return that time when can not get value from config
    :param str default_path: Return that path when can not get value from config
    :return: Tuple (session.save_path, session.gc_maxlifitime)
    :rtype: (str, int)
    rsr�zsession.save_pathr�r�zsession.gc_maxlifetimeNz"')	rRr�r�rgr�r�rr�r�)rw�default_time�default_path�configr��ls      rB�get_opts_from_php_inir�yse��
�
�$��_�_�	8���(�(�*�*�
8�
8���J�J�L�L���<�<��$�$�8���\�\�"5�6�6�8�3�!�8�8�$%�G�G�C�L�L��O�#:�#:�#<�#<�L�L��\�\�":�;�;�8��q���#&�q�w�w�s�|�|�A��#7�#7�L��
8�	8�	8�	8�	8�	8�	8�	8�	8�	8�	8�	8����	8�	8�	8�	8���
�
�G�,�
�
�
���
�������e�$�$�l�2�2s5�C5�C
C)�C5�)C-�-C5�0C-�1C5�5D�Dc���|�d��rWtj�t	|��t	tj�|������S|S)z�
    Convert symlink value (path) from absolute to relative
    :param original: path to original file
    :param dest: path where symlink will be created
    rK)rgrOrw�relpathr�r)rYr�s  rBr�r��sU�����3���X��w���z�(�3�3�Z�����PT�@U�@U�5V�5V�W�W�W��OrCc�P�t||��}tj||��dS)z�
    Create relative symlink instead of absolute
    :param original: path to original file
    :param dest: path where symlink will be created
    N)r�rOr)rYr�r�s   rB�relative_symlinkr��s+��&�h��5�5�M��J�}�d�#�#�#�#�#rCc�2�tj|��}	t||��}tj�|��r-tj|��|krtj|��nt
|d���tj�|��s1td|�d|��td��tj	||��nC#t$r6}td|�d|�dt|����td��Yd}~nd}~wwxYw|S)	z�
    Create symlink or update if changed. Return value of original symlink (destination it points to)
    :param origpath: path to symlink in real file system
    :param jailpath: path to symlink in cagefs-skeleton
    Trrrr�rr�N)rOr.r�rwr�r{rrrrrQr�)rrrr�r�s     rBr�r��s.���{�8�$�$�H�e�)�(�H�=�=�
�
�7�>�>�(�#�#�	<��{�8�$�$�
�5�5��	�(�#�#�#���x�d�;�;�;�;��w�~�~�h�'�'�	0��E��E�E�m�E�E�{�TU�V�V�V��J�}�h�/�/�/����e�e�e��S�H�S�S�-�S�S�3�q�6�6�S�S�U`�bc�d�d�d�d�d�d�d�d�����e�����Os�B=C�
D�,D�Dc��tj�t��sdStdz}ttz}tdz}	tj�|��st|d��nC#t$r6}td|zdzt|��ztd��Yd}~nd}~wwxYw	tj�
|��stj||��dSdS#t$r=}td|zd	z|zdzt|��ztd��Yd}~dSd}~wwxYw)
z�
    Create symlink /usr/share/cagefs-skeleton/var/run/utmp -> /var/run/cagefs/utmp
    needed for emulation of /var/run/utmp inside CageFS
    For details see CAG-706
    N�/utmpz
/var/run/utmpr�r�r�r�r�z -> )rOrwrr	�VAR_RUN_CAGEFSr4rQrr�rr�r)�utmp_cagefs�skel_cagefs_dir�	skel_utmpr�s    rB�create_utmp_in_skeletonr��sv���7�=�=��"�"���� �7�*�K���/�O��?�*�I�i��w�}�}�_�-�-�	1���%�0�0�0����i�i�i��4��F��N�QT�UV�QW�QW�W�Yd�fg�h�h�h�h�h�h�h�h�����i����x��w�~�~�i�(�(�	/��J�{�I�.�.�.�.�.�	/�	/���x�x�x��2�Y�>��G�+�U�X]�]�`c�de�`f�`f�f�hs�uv�w�w�w�w�w�w�w�w�w�����x���s0�/A;�;
B;�,B6�6B;�?4C7�7
D>�2D9�9D>c�:�	tj|��}n#tj$rYdSwxYw|jdzt
z}|dz}tj�|��s�t|j
|j��	tj�|��stj|dd���tj|d��nA#t t"t$f$r't'��|rt)jd��YnwxYwt-��dSdS)	a
    Create user's personal /home/user/.cagefs/var/run/cagefs/utmp file
    For details see CAG-706
    :param user: user name
    :type user: string
    :param exit_on_error: True == execute sys.exit(1) when error has occured
    :type exit_on_error: bool
    Nz/.cagefsr�r_T)�	recursiver�r�)rror-rprqr�rOrwr�rrrrsrr.r�r�rQr�r2r�r�r�r)r�r)rw�utmp_dir�	utmp_files     rB�create_utmp_for_userr��s*���
�
!�$�
'�
'�����$������������y�:�%��6�H��7�"�I�
�7�?�?�9�%�%�
��b�i���+�+�+�	��7�=�=��*�*�
A����%�4�@�@�@�@��O�I�r�*�*�*�*����"7�8�	�	�	������
���������	����	������
�
s��*�*�>AC
�
;D�Dc�8�ttdd���sdSdS)zf
    Check clean_php_sessions parameter in config file
    By default sessions cleanup is enabled
    �clean_user_php_sessionsT)�default_valFr5rGrCrB�"is_clean_user_php_sessions_enabledr��s'��
�^�-F�TX�Y�Y�Y���u��4rC)�maxsizec�6�ttj��Sr<)r0r/�LVErGrCrB�is_running_without_lver��s��)�'�+�6�6�6�6rC)rVN)FNNr<)T)NNTF)r�r)rrr)rr�rr)rr�r)r�r�)FF)F)r)TTNFN)TF)TFT)FT)rzF)NFr)NNN)NN)FFFF)r�(N�
__future__rrrrrf�typingrrr	r
�futurer�install_aliases�builtinsr�r�r�r�r�r�r�r]rr�r�r�r�r�r�r�rO�	functools�secureior
rrrrrrrrrrrrrrrr��clcagefslib.constrrr�clcagefslib.fsr r!�clcagefslib.exceptionsr"�clcagefslib.ior#r$r%r&�clcagefslib.selector.configurer(�clcagefslib.selector.pathsr)�#clcagefslib.webisolation.jail_utilsr*�clcommon.clfuncr+r,�clcommonr-r.�clcommon.constr/�clcommon.cpapir0r��signals_handlersr1�clcommon.utilsr2r3r4r6r7�logsr8r=r:rIrYrdrnr��ETC_TEMPLATE_DIRr$r��VERBOSE_FLAGr�r�r�r��FALLBACK_PLESK_VHOSTS_Dr�rur�r�r�rerirvr|ryrUrpr�r�r��boolr�r�r�r�r�r�r�r{r��LOG_ERRr�r�r�r�r�r�r�r�rnr	�FUSE_WHITE_LISTrrr�r�r+rrr)r,r3r>r8r:r<rArCrEr%rLrOrTrVr`rhrjrkrprurxr{r}r�r�r�r�r�r�r�r�r�r�r�r�r�rr r,r9rjrLrPrXr_rkrqrmrsrrr�rnrvrxrr�r�r�r�r�r�r�r�r�r�r�r"r�r�r�r�r-r�r�r�r�r�r�r�stat_resultrr�r'r&rrrr"rkr�r+r3r7r=r?rCrLrQrUr\rbr^rerjryr~r�r�r�r�r�r�r�r�r�r�r�rX�ETC_CL_PHP_PATHr�rr�r�r�r�r�r�r�r�r��dictr�r
rr
r$r�r%r&r'rr5r>r@rArCrDrIrGrHrOrZr\r]rbrgrrkrmrortrxrzrr�r�r�r�r�r�r�r�r�r�r�r�r�r�r��	lru_cacher�rGrCrB�<module>r�s���&�%�%�%�%�%�&�&�&�&�&�&�������'�'�'�'�'�'�
�
�
�
�/�/�/�/�/�/�/�/�/�/�/�/�#�#�#�#�#�#� �� �"�"�"���������	�	�	�	�
�
�
�
�
�
�
�
�������������
�
�
�
�������������
�
�
�
�����	�	�	�	���������	�	�	�	�����n�m�m�m�m�m�m�m�m�m�m�m�m�m�Z�Z�Z�Z�Z�Z�Z�Z�Z�Z�Z�Z�^�^�^�^�^�^�^�^�^�^�^�^�^�^�^�^�^�^�����C�C�C�C�C�C�C�C�C�C�<�<�<�<�<�<�<�<�4�4�4�4�4�4�^�^�^�^�^�^�^�^�^�^�^�^�9�9�9�9�9�9�3�3�3�3�3�3�>�>�>�>�>�>�/�/�/�/�/�/�/�/�%�%�%�%�%�%�%�%�"�"�"�"�"�"�5�5�5�5�5�5�����*�*�*�*�*�*�����������
:�9�9�9�9�9�9�9�������2�2�2�2�2�i�2�2�2�
	�	�	�	�	�?�	�	�	�"���$�$��&�
�&��&��2��"������9����&��+��7��
1�
���$d� �W��*����#�
�"��8��/��
!�
!�
!�@�@�@�@�8A�A�A�A�D-�-�-�-�<E�E�E�<<��<�<�<�<�3�d�3�3�3�3�����/�4�/�/�/�/�&�d�&�&�&�&����.���&
�
�
� � � �@#�N�u�)�)�)�)�2	)�	)�	)�"�!�#�#�>�'>���
����2�2�2�
��������������$�$�$��S��S������
�
S�
S�
S�
S�Y�Y�Y�
*�3�*�4�*�*�*�*�6
�
�
�&���(
��"�"�"�"�"�"�h�h�h�
����(>�>�>�H�H�H�:�C�:�D�:�:�:�:�
�	����
���
�
�
�
8�
8�
8�7�7�7��
����P�P�P�H�H�H�H�*�
�����
�
�
�!�!�!�!�J
�
�
�
�	�	�	�	�	�I�	�	�	� �#� �3� �8�C�=� � � � �F)�S�)�T�#�Y�)�)�)�)�^&�&�&�&�@����M�M�M�b��������H�H�H�]�]�]�]�Bd�d�d�d�D(F�(F�(F�(F�X45��q�_`�op�@B�KL�����<V�V�V�
����2C�C�C�
���
�
�
�"���0!�!�!�L/�
�
/�	�����	�T�#�Y�	�3�	�	�	�	����4
�
�
�
v�
v�
v�
v�$#���"�%���� �
�(����#�m�3��
2�
2�
2��
�!�!�!�$���#�#�#�P�P�P�
���2L�L�L�L�^���8I��(�(�(�(�B�B�B�:BC�q�]^�mn�}~�ST�ce�no�R�R�R�R�l	�	�	�bm�bm�bm�bm�NY�Y�Y�Y�|Co�Co�Co�Co�P����6���7
�3�7
�S�7
�S�7
�7
�7
�7
�t	�&�	�R�^�d�2�	�	�	�	�#�#�/3�!�04�
d�d�#�d��d��d��d�!��I��,�	d�
�d�"�#�Y��-�
d�:=�
d�d�d�d�R)-�"�3
�3
�s�3
��3
�!%�3
��3
�(+�3
�3
�3
�3
�n
�
�
�1�1�1�1�1�1� � � �
!�!�!�����,��� ���2'�'�'�.A�A�A�27�7�7�.���/3�;O�%�%�%�%�R������:\�\�\�)�)�)�)�\���������$.e�.e�.e�.e�b9�9�9�
�
�
���
�
�
������(�� � � � �H������/�s�/�/�/�/�f���8���/�)��#�� ��-�-�-��
� � � �J#�#�#�#�#�#�����<��',�$�8�8�AD�GK�AK�8�8�8�8�vA<�A<��A<�$�s�D��I�~�2F�A<�QT�A<�_b�A<�il�A<�sv�A<�CF�IM�CM�A<�ad�gk�ak�A<�CF�IM�CM�A<�A<�A<�A<�\]a�=g�=g��=g��=g�#�=g�C�=g�[^�=g�tx�y|�C�DG�H�zH�uI�=g�X\�]`�bf�gj�bk�]k�Xl�=g�-1�=g�AD�=g�MQ�=g�\`�=g�mp�sw�mw�=g�PS�VZ�PZ�=g�=g�=g�=g�@����3��S��QT�W[�Q[�����*$/�$/�$/�R��������W�W�W�.@�.@�mp�sw�mw�.@�.@�.@�.@�d����2����,�
����&'�
�&�&�&����58��=A�#�s�(�^�����(�C��14��9=�c�3�h������.���58��=A�#�s�(�^�����D'��S�	�'�C�'�'*�'�6:�3��8�n�'�IM�'�'�'�'�4<�<�<�21�����
�
�
�&
�
�
����	]�	]�	]���
�
�
�"!�!�!�$ � � � E�E�E�
�
�
�<�<�<�
P�P�P�<��&�&�&�

�
�
�9�9�9� 8�8�8�8�D���&3�3�3�3�0���$�$�$����,x�x�x�.����8������T�"�"�"�7�7�#�"�7�7�7rC