HEX
Server: LiteSpeed
System: Linux php-prod-1.spaceapp.ru 5.15.0-157-generic #167-Ubuntu SMP Wed Sep 17 21:35:53 UTC 2025 x86_64
User: xnsbb3110 (1041)
PHP: 8.1.33
Disabled: NONE
Upload Files
File: //proc/self/root/usr/lib/python3/dist-packages/apparmor/__pycache__/easyprof.cpython-310.pyc
o

%`b���@s�ddlmZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZGdd�de
�ZdadDdd	�Zd
d�Zejfdd
�Zdd�Zdd�Zdd�Zdd�ZdEdd�Zdd�Zdd�Zdd�ZdEdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Z d(d)�Z!dFd*d+�Z"Gd,d-�d-�Z#d.d/�Z$d0d1�Z%d2d3�Z&d4d5�Z'd6d7�Z(d8d9�Z)dFd:d;�Z*d<d=�Z+d>d?�Z,dEd@dA�Z-dGdBdC�Z.dS)H�)�with_statementNc@s eZdZdZdd�Zdd�ZdS)�AppArmorExceptionz)This class represents AppArmor exceptionscCs
||_dS�N)�value)�selfr�r�3/usr/lib/python3/dist-packages/apparmor/easyprof.py�__init__�
zAppArmorException.__init__cCs
t|j�Sr)�reprr�rrrr�__str__"r
zAppArmorException.__str__N)�__name__�
__module__�__qualname__�__doc__r	r
rrrrrsrF�TcCs>z
tj�d|�Wn	tyYnw|rt�|�dSdS)zPrint error message and exitz
ERROR: %s
N)�sys�stderr�write�IOError�exit)�out�	exit_code�do_exitrrr�error-s��rcC�,ztj�d|�WdStyYdSw)zPrint warning messagez	WARN: %s
N)rrrr�rrrr�warn8�
�rcCr)z
Print message�%s
N)r�stdoutrr)r�outputrrr�msg@rr#c
Csht|�ztj|tjtjd�}Wnty(}zdt|�gWYd}~Sd}~ww|��d}|j|gS)z!Try to execute the given command.)r!r�Nr)	�debug�
subprocess�Popen�PIPE�STDOUT�OSError�str�communicate�
returncode)�command�sp�exrrrr�cmdHs

���
r1cCs4trztj�d|�WdStyYdSwdS)zPrint debug messagez
DEBUG: %s
N)�	DEBUGGINGrrrrrrrrr%Us��r%cCsvztj�|�}Wntytd�YdSw||kr!td�dStj�|�s)dStj�|�}||kr9td�dSdS)z
Validate namez'Could not find absolute path for binaryFz,Binary should use a normalized absolute pathTzBinary should not be a symlink)�os�path�abspath�	Exceptionr%�exists�realpath)r4�a_path�r_pathrrr�valid_binary_path^s �r;cCs~td|�z	|�d�\}}Wn
tyYdSwt�d|�s"dSd|vr7d}|�d�s/d}t||d�s7dSd|vr=dSdS)	zValidate variable namez
Checking '%s'�=Fz^@\{[a-zA-Z0-9_]+\}$�/T)�relative_ok�")r%�splitr6�re�search�
startswith�
valid_path)�v�keyr�rel_okrrr�valid_variableus"�
rHcCs�d|}|s|�d�std|�dSd|vrtd|�dSd|vr+td|�dSztj�|�}WntyCtd	|�YdSw||krStd
|||f�dSdS)z
Valid pathzInvalid path: %sr=z
%s (relative)Fr?z
%s (quote)�../z%s (../ path escape)z%s (could not normalize)z'%s (normalized path != path (%s != %s))T)rCr%r3r4�normpathr6)r4r>�m�prrrrD�s(�rDcCst�d|�rdSdS)zKnown safe regexz^[a-zA-Z_0-9\-\.]+$TF)rArB��srrr�_is_safe�srOcC�t|�S)zVerify the policy vendor�rOrMrrr�valid_policy_vendor��rRcCs6zt|�Wn
tyYdSwt|�dkrdSdS)zVerify the policy versionFrT)�float�
ValueError)rErrr�valid_policy_version�s�rVcCs&|s|�d�rt|�s
dSdSt|�S)�Verify the template namer=FT)rCrDrO)rN�strictrrr�valid_template_name�s
rYcCrP)rWrQrMrrr�valid_abstraction_name�rSrZcCs.|�d�r
t|�sdSdSt�d|�rdSdS)zVerify the profile namer=FTz"^[a-zA-Z0-9][a-zA-Z0-9_\+\-\.:~]+$)rCrDrArBrMrrr�valid_profile_name�s
r[cCrP)zVerify policy group namerQrMrrr�valid_policy_group_name�rSr\cCs:t|�sdSg}t�|d�D]}|�|�q|��|S)z$Find contents of the given directoryN�/*)rD�glob�append�sort)r4�files�frrr�get_directory_contents�srccCs&z
t�|dd�}W|Sty�w)zOpen specified file read-only�rzUTF-8)�codecs�openr6)r4�origrrr�open_file_read�s��rhc	Cs�|std�dSd}t|���dkrt|�r|}ntjdd�\}}t|t�s+|�d�}t	�
||�t	�|�|dg}|rC|�d	|g�|rL|�d
|g�|�
|�t|�\}}t	�|�|dkrbdSdS)
zVerify policy compilesz/Could not find apparmor_parser. Skipping verifyT�r�aa-easyprof��prefix�utf-8z-QTK�-b�-IrF)r�len�
splitlinesrD�tempfile�mkstemp�
isinstance�bytes�encoder3r�close�extendr_r1�unlink)	�policy�exe�base�include�fnrbr.�rcrrrr�
verify_policy�s,




r�c@s�eZdZdZdd�Zdd�Zdd�Zdd	�Zd$dd�Zd
d�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zddgddggddddfdd�Zd%d d!�Zd"d#�ZdS)&�AppArmorEasyProfilezEasy profile classcCs�t|�|�dd�tj�|j�|_td|j�t�|_tj�	|j�r(|�
�d|_|jr3|j|_ntj�|j�sJt
ddg�\}|_|dkrJd|_d|_|jrT|j|_d|_|jr^|j|_|jrstj�|j�rstj�|j�|jd	<n |js�|jr�tj�	|j�r�t|j�r�tj�tj�|j��|jd	<|jr�tj�|j�r�tj�|j�|jd
<|jr�tj�|j�r�tj�|j�|jd<|jr�tj�|j�r�tj�|j�|jd<d|_d|_|jr�|jr�|jr�|js�td
��|j�r|j�r|j|_t|j�|_dD]#}tj�|j||j|j�}tj�|��std||f��||j|<q�d	|jv�r'td��d|jv�r1td��||_|�rBt|��sBtd|��|j�rO|j |jdd�n|� |j�|�!|j"�|j#�rf|�$|j#�n|jdk�rr|�$|j�g|_%t&|jd	�D]}tj�	|��r�|j%�'|��q|d
|jv�r�t&|jd
�D]}tj�	|��r�||j%v�r�|j%�'|��q�g|_"t&|jd�D]}tj�	|��r�|j"�'|��q�d|jv�r�t&|jd�D]}tj�	|��r�||j"v�r�|j"�'|��q�dSdS)N�conffilez/etc/apparmor/easyprof.confzExamining confile=%sz/sbin/apparmor_parser�which�apparmor_parserrz/etc/apparmor.d�	templates�templates_include�policygroups�policygroups_includez+Must specify both policy version and vendor)r�r�z Could not find %s directory '%s'z"Could not find templates directoryz%Could not find policygroups directory�Invalid path for binary: '%s'F)�allow_abs_path)(�verify_options�ensure_valuer3r4r5r�r%�dict�dirs�isfile�
_get_defaults�parser_pathr7r1�parser_base�parser_include�
templates_dir�isdir�templaterD�dirname�include_templates_dir�policy_groups_dir�include_policy_groups_dir�policy_version�
policy_vendorrr+�join�binaryr;�manifest�set_template�set_policygroup�
policy_groups�name�set_namer�rcr_)rr��optr�i�drbrrrr	s�
��������
�
�����zAppArmorEasyProfile.__init__cCstj�|j�std|j��t|j�}t�d�}|D]7}|�|�s"q|�	d�r:t�
d|���d�d�}||jd<q|�	d�rQt�
d|���d�d�}||jd	<q|�
�|j��}d	|vrftd
|j��d|vrqtd|j��|j��D]}tj�|j|�s�td|j|��qvdS)
z#Read in defaults from configurationzCould not find '%s'z
^\w+=".*"?zPOLICYGROUPS_DIR=r<rz["']r�zTEMPLATES_DIR=r�z$Could not find TEMPLATES_DIR in '%s'z'Could not find POLICYGROUPS_DIR in '%s'N)r3r4r7r�rrhrA�compilerBrCr@�stripr�rw�keysr�)rrb�pat�liner�r��krrrr��s2





�
��z!AppArmorEasyProfile._get_defaultscCs
||_dS)zSet name of policyN)r�)rr�rrrr��s
zAppArmorEasyProfile.set_namecCst|j���S)z Get contents of current template)rfr��readrrrr�get_template�sz AppArmorEasyProfile.get_templateTcCs�d|vr
td|��|�d�r|std|��|�d�r-tj�|�s(td|��||_dStj�|jd|�}d}d|jvrHtj�|jd|�}tj�|�rS||_dS|durbtj�|�rb||_dStd|��)	zSet current templaterIz(template "%s" contains "../" escape pathr=z)Cannot use an absolute path template '%s'�%s does not existNr�r�)rrCr3r4r7r�r�r�)rr�r��sys_t�inc_trrrr��s$



z AppArmorEasyProfile.set_templatecC�|jS)z/Get list of all available templates by filename)r�rrrr�
get_templates��z!AppArmorEasyProfile.get_templatescCs�|}|�d�s7tj�|jd|�}d}d|jvr"tj�|jd|�}tj�|�r+|}n|dur7tj�|�r7|}|jdksA||jvrGtd|��t|��	�S)z$Get contents of specific policygroupr=r�Nr�z Policy group '%s' does not exist)
rCr3r4r�r�r7r�rrfr�)r�policygrouprL�sys_p�inc_prrr�get_policygroup�s

z#AppArmorEasyProfile.get_policygroupcCs�g|_|dkre|�d�D]Z}|�d�r&tj�|�std|��|j�|�qtj�|j	d|�}d}d|j	vrAtj�|j	d|�}tj�|�rN|j�|�q|dur_tj�|�r_|j�|�qtd|��dSdS)zSet policygroupsN�,r=r�r�r�)
r�r@rCr3r4r7rr_r�r�)rr�rLr�r�rrrr��s&

�z#AppArmorEasyProfile.set_policygroupcCr�)z)Get list of all policy groups by filename)r�rrrr�get_policy_groups�r�z%AppArmorEasyProfile.get_policy_groupscCsftj�|jd|�}tj�|�s/|jstd|��tj�|jd|�}tj�|�s/td||f��d|S)zGenerate an abstraction rule�abstractionsr�zNeither %s nor %s existz#include <abstractions/%s>)r3r4r�r�r7r�r)r�abstractionr|r}rrr�gen_abstraction_rulesz(AppArmorEasyProfile.gen_abstraction_rulecCs.t|�s
td|��|�d�\}}d||fS)zGenerate a variable declarationz!Invalid variable declaration '%s'r<z%s="%s")rHrr@)r�decr�rErrr�gen_variable_declarationsz,AppArmorEasyProfile.gen_variable_declarationcCs�g}|�d�s|�d�std|��d}|�d�s|�d�r d}|�d�r:|�d||f�|�d	|||f�|S|�d
�sD|�d�r]|�dtj�|�|f�|�d|||f�|S|�d|||f�|S)
Nr=�@z '%s' should not be relative pathriz/home/z@{HOMEzowner z%s %s,z
%s%s** %s,z/**r]z%s%s %s,)rCr�endswithr_r3r4r�)rr4�access�rule�ownerrrr�
gen_path_rules 
��z!AppArmorEasyProfile.gen_path_ruleNFc
Cs�dd�}
|��}d|vr)d}d}|��D]}|s |�d�rd}q||d7}q|}d}|rEt|�s7td|��|r@d	||f}nd
|}n|rLd|}ntd��t�d
||�}t�d||�}|
dkrkt�dd|
|�}|	dkrxt�dd|	|�}|dkr�t�dd||�}d}|
||�}d|}|dkr�d|}|�d�}|��|D]
}|d||�	|�f7}q�t�d|||�}d}|
||�}d|}|dkr�d|}|�d�}|��|D]!}|�
|���D]
}|d||f7}q�||�d�dkr�|d7}q�t�d|||�}d}|
||�}d |}t|�d!k�r.d"|}|��|D]}|d||�|�f7}�qt�d|||�}d#}|
||�}d$|}t|�d!k�rid%|}|��|D]}|�
|d&�D]}|d||f7}�q[�qSt�d|||�}d'}|
||�}d(|}t|�d!k�r�d)|}|��|D]}|�
|d*�D]}|d||f7}�q��q�t�d|||�}|�r�td+�|St||j|j|j��s�td|�td,��|S)-NcSsLt�d|�}d}|��D]}|�|�r#dt|�t|���}|Sq
|S)z9Calculate whitespace prefix based on occurrence of s in tz^ *%sri� )rAr�rq�matchrp�lstrip)�trNr�rLr�rrr�find_prefix7s
�z3AppArmorEasyProfile.gen_policy.<locals>.find_prefixz###ENDUSAGE###FriT�
r�zprofile "%s" "%s"z"%s"zprofile "%s"�'Must specify binary and/or profile namez###PROFILEATTACH###z
###NAME###z
###COMMENT###zComment: %sz###AUTHOR###z
Author: %sz###COPYRIGHT###z
Copyright: %sz###ABSTRACTIONS###z%s# No abstractions specifiedz%s# Specified abstractionsr�z
%s%sz *%sz###POLICYGROUPS###z%s# No policy groups specifiedz%%s# Rules specified via policy groups���z	###VAR###z#%s# No template variables specifiedrz%s# Specified profile variablesz###READS###z%s# No read paths specifiedz%s# Specified read permissions�rkz###WRITES###z%s# No write paths specifiedz%s# Specified write permissions�rwkzSkipping policy verificationzInvalid policy)r�rqrCr;rrA�subr@r`r�r�rpr�r�r%r�r�r�r�r#)rr�r��profile_name�template_varr�r��	read_path�
write_path�author�comment�	copyright�	no_verifyr�rz�found�tmpr��
attachmentrBrlrNr�r�rdrrr�
gen_policy+s�

�





�

�
��zAppArmorEasyProfile.gen_policyrc
Cs|jdi|��}|s|rtj�d|�tj�d|�dSd}d|vr)|d}n
d|vr2|d}ntd��tj�|t�	dd|�
d���}tj�|�rQtd	|��tj�|�s\t�|�tj�
|�shtd
|��tjdd�\}}t|t�sz|�d
�}t�||�t�|�t�||�dS)z
Output policyz ### aa-easyprof profile #%d ###
r rir�r�z#Could not determine output filenamer=�.z'%s' already existsz'%s' is not a directoryrjrkrmNr)r�rr!rrr3r4r�rAr�r�r7�mkdirr�rrrsrtrurvrw�shutil�move)r�params�count�dirrz�out_fnrbr~rrr�
output_policy�s0





z!AppArmorEasyProfile.output_policyc
Cs�t�}t�|d<t�|dd<d}d|vr|d}n
d|vr#|d}ntd��t�|dd|<tj�|j�}|dkrE||dd|d<|jrUt|j�|dd|d	<|jrc|j|dd|d
<|D]�}|dkss|dkrtd|vrtqe|dkr}||s}qe|dkr�t�|dd|d<||D]+}|�	|�s�td
|��|�
d�\}}|�d��d��d�}||dd|d|<q�qe|dks�|dkr�||�
d�|dd||<|dd||�
�qe|||dd||<qetj|dddd�}	|	S)z'Take params list and output a JSON file�security�profilesrir�r�z"Must supply binary or profile name�defaultr�r�r�r��template_variableszMalformed template_var '%s'r<r��{�}r�r�r�T�)r�z: )�	sort_keys�indent�
separators)r�rr3r4�basenamer�r�rTr�r�r@r��rstripr`�json�dumps)
rr�r��pkeyr�rF�tvarr�rE�json_strrrr�gen_manifest�sT



��z AppArmorEasyProfile.gen_manifest)T)rN)rrrrr	r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrrr�s8n


�
#r�cCs&|D]}tj�dtj�|��qdS)Nr )rr!rr3r4r�)rar�rrr�print_basefilenamess�r�c	CsJ|D] }t|��}tj�|��d�Wd�n1swYqdS)Nr�)rfrr!rr�)rar�rbrrr�print_filess
���r�cCsBgd�}|D]}t|j|d�rt�d|��qt|j|j|�dS)�-Check for -m/--manifest with conflicting args)r�r�r�r�r�r�r�r�r�r�r�r�F�'can't use --%s with --manifest argumentN)�getattr�values�optparse�OptionValueError�setattr�dest)�option�opt_strr�parser�
conflict_args�conflictrrr�check_manifest_conflict_args
s��rcCs0|jjrt�d|�d���t|j|j|�dS)r�r��-N)r�r�r�rr�rr�rrrrrrr�check_for_manifest_arg#s
�rcCs6|jjrt�d|�d���|j�|jg��|�dS)z;Check for -m/--manifest with conflicting args (with append)r�r	N)r�r�r�rr�r�rr_r
rrr�check_for_manifest_arg_append*s
�rc
CsF|jddddd�|jdddttd	d
dd�|jd
ddddd�|jdddddd�|jddttdddd�|jddttdddd�|jddddd d!d"�|jd#d$d%dd�|jd&d'd(dd�|jd)d*dttd+d,d-�|jd.d/d0dd�|jd1d2d3dd�|jd4dttd5d6d7d�|jd8dttd9d:d;d�|jd<dttd=d>d?d�d@S)AzAdd parser argumentsz--parserr�z4The path to the profile parser used for verification�PATH�r�help�metavarz-az--abstractions�callbackr�z$Comma-separated list of abstractions�ABSTRACTIONS��actionr�typerrrrnz--baser�z1Set the base directory for resolving abstractions�DIRroz	--Includer�z>Add a directory to the search path when resolving abstractionsz--read-pathr�zPath allowing owner readsz--write-pathr�zPath allowing owner writesz-tz
--templater�zUse non-default policy template�TEMPLATEr�)rrrr�z--templates-dirr�z#Use non-default templates directoryz--include-templates-dirr�zAlso search DIR for templatesz-pz--policy-groupsz%Comma-separated list of policy groups�POLICYGROUPS)rrrrrz--policy-groups-dirr�z'Use non-default policy-groups directoryz--include-policy-groups-dirr�z!Also search DIR for policy groupsz--policy-versionr�z/Specify version for templates and policy groups�VERSIONz--policy-vendorr�z.Specify vendor for templates and policy groups�VENDORz--profile-namer�zAppArmor profile name�PROFILENAMEN)�
add_optionrr+r)rrrr�add_parser_policy_args1s���������������
�rc
Cs�|dkrt��}|jdddddd�|jdd	d
ddd
�|jddddd
�|jddddd
�|jddddd
�|jddddd
�|jddddd
�|jdddttdddd�|jddttd d!dd�|jd"dttd#d$dd�|jd%dttd&d'dd�|jd(dttd)d*d+d�|jd,d-d.d/d0d1d2�|jd3d-d4d5d6d7�|jd8d9dttd:d;dd�|jd<ddd=d>d?�t|�|�|�\}}|j	r�d@a
||fS)AzParse argumentsNz-cz
--config-filer�z Use alternate configuration file�FILErz-dz--debugzShow debugging output�
store_trueF)rrr�z--no-verifyz.Don't verify policy using 'apparmor_parser -p'z--list-templateszList available templatesz--show-templatezShow specified templatez--list-policy-groupszList available policy groupsz--show-policy-groupzShow specified policy groupsz-nz--namerr�z*Name of policy (not AppArmor profile name)�COMMENTrz	--commentr�zComment for policyz--authorr�zAuthor of policyz--copyrightr�zCopyright for policyz--template-varr�zDeclare AppArmor variablez@{VARIABLE}=VALUEz--output-format�store�
output_formatz/Specify output format as text (default) or json�FORMAT�text)rrrrr�z--output-directory�output_directoryzOutput policy to this directoryr)rrrrz-mz
--manifestr�zJSON manifest filez--verify-manifest�verify_manifestzVerify JSON manifest file)rr�rrT)r��OptionParserrrr+rrr�
parse_argsr%r2)�argsr�my_opt�my_argsrrrr(�s�����������������r(cCst|d�}|s|jstd��|jr|j|d<|jr|j|d<n|jr(|j|d<n
|r2tj�|�|d<|jr:|j|d<|jrB|j|d<|j	rJ|j	|d<|j
rR|j
|d<|jrZ|j|d	<|jrb|j|d
<|j
rj|j
|d<|jrr|j|d<|jr|jd
kr|j|d<|jr�|jd
kr�|j|d<|S)z"Generate parameters for gen_policy)r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�)r�r�rr�r3r4r�r�r�r�r�r�r�r�r�r�r"r�)r�r�r�rrr�gen_policy_params�s@












r,c	Cs�zt�|�}Wntytd��wd|vr|d}n|}d|vr&td��|d}gd�}g}|D]�}t||t�s?td��t�|�}d}	|�d�rXd	||vrUtd
��|}	nt	|d|�d	||vrp||d	}	t	|d	|	�||D][}
|
|vr�td|
��|
d	kr�qt|
d
ks�|
dkr�t	||
d�
|||
��qt|
dkr�||d}g}|��D]}
|�d|
||
f�t	|d|�q�qtt
||
�r�t	||
|||
�qt|�|	|f�q2|S)z�Take a JSON manifest as a string and updates options, returning an
       updated binary. Note that a JSON file may contain multiple profiles.zCould not parse manifestr�r�z4Could not parse manifest (could not find 'profiles'))r�r�r�r�r�r�r�r�r�r�r�r�r�r�zWrong JSON structureNr=r��0Profile name should not specify path with binaryr�zInvalid key '%s'r�r�r�r�z@{%s}=%sr�)r��loadsrUrrtr��copy�deepcopyrCrr�r�r_�hasattr)r��opt_origrK�	top_table�table�
valid_keysr�r�r�r�rFr��vlistrErrr�parse_manifestsZ�


�
�r7cCst|d�r|jrt|j�std|j��t|d�r*|jdkr*t|j�s*td|j��t|d�rF|jrFt|d�rF|jdkrF|j�d�rFtd��t|d�rZ|jrZt|j�sZtd	|j��t|d
�rn|j	rnt
|j	�sntd|j	��t|d�r�|jr�t|j|�s�td
|j��t|d�r�|j
r�|j
D]}t|�s�td|��q�t|d�r�|jr�|j�d�D]}t|�s�td|��q�t|d�r�|jr�|j�d�D]}t|�s�td|��q�t|d�r�|jr�|jD]}t|�s�td|��q�t|d��r|j�r|jD]}t|��std|��q�dSdSdS)zMake sure our options are validr�zInvalid binary '%s'r�NzInvalid profile name '%s'r=r-r�zInvalid policy vendor '%s'r�zInvalid policy version '%s'r�zInvalid template '%s'r�zInvalid variable '%s'r�r�zInvalid policy group '%s'r�zInvalid abstraction '%s'�
read_pathszInvalid read path '%s'�write_pathszInvalid write path '%s')r1r�rDrr�r[rCr�rRr�rVr�rYr�rHr�r@r\r�rZr8r9)r�rXr�rrrr�nsp��

�����
�
���
�

��r�cCsJd}t|�\}}td|�}ddg}dg}|D]�}td|||f�||vr-|d|7}q|dkrG|d�d	�s>d
|dvrF|d|d7}q|dkr`|d�d
�D]}||vr^|d|7}qRq|dkr�t�d�}	|dD]*}
|�|
�s{|d|
7}qm|
�d�d}td|�d|vs�|	�|�r�|d|
7}qmq|r�t	d|�dSdS)z+Verify manifest for safe and unsafe optionsriNr�r�r|zExamining %s=%sz
found %s keyr�r=�*z
profile_name '%s'r�r�z
found '%s' abstractionr�z[*/\{\}\[\]]z
%sr<rzExamining %sz..z+Manifest definition is potentially unsafe%sFT)
r(r�r%rCr@rAr�r�rBr)r�r)�err_strr��
fake_easyp�unsafe_keys�safe_abstractionsr��ar��tv�tv_valrrrr&�sF
���

�r&)rT)F)NNr)/�
__future__rrer/r^r�r�r3rAr�r&rrrr6rr2rrr!r#r1r%r;rHrDrOrRrVrYrZr[r\rcrhr�r�r�r�rrrrr(r,r7r�r&rrrr�<module>s^


	

	

#j
Tj)
V,