§ À•¿jPãóΗddlmZddlmZddlmZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl m Z mZmZddlmZmZmZmZddlmZddlmZmZdd lmZdd lmZdd lmZm Z m!Z!dd l"m#Z#dd l$m%Z%ddl&m'Z'ddl(m)Z)ddl*m+Z+dZ,dZ-d>d„Z.d?d„Z/d„Z0d„Z1d„Z2d„Z3d„Z4d„Z5d„Z6d@d„Z7d>d„Z8ej9ej:zej;zej9ej:zej;zej9ej:zej<zej9ej:zej<zd œZ=d>d!„Z>dAd#„Z?dAd$„Z@d%„ZAd&„ZBd'„ZCd(„ZDd)„ZEd*„ZFd+„ZGdBd.„ZHd/„ZId0„ZJd1„ZKdCd3„ZLd4„ZMd5„ZN dDd6„ZOd7ePd8eQfd9„ZRd:ePfd;„ZSd<„ZTd=„ZUdS)Eé)Úprint_function)Úabsolute_import)ÚdivisionN)ÚtimeÚ monotonicÚsleep)ÚAnyStrÚListÚDictÚOptional)ÚPath)ÚurlparseÚ urlunparse)Úresolve_username_and_doc_root)ÚCP_NAME)ÚNoDomainÚ NotSupportedÚ IncorrectData)Ú mod_makedirs)Úinit_sentry_client)Úget_pkg_versioné)Úclprint)ÚClSelectExceptz/sbin/cagefs_enter_userzehttps://9713d1296f804031b058b8f2d789d7ac:8ddacae32d8246cf8b25cf826bf3fc0a@cl.sentry.cloudlinux.com/12c ó¦— tj|td¦«tjtjd|d¬¦«}| ¦«\}}nA#t tf$r-}tj |dt|¦«¦«‚d}~wwxYw|j dkr/tj |pdd  |¦«›d|›�¦«‚|S) z‰ Runs external process and returns output :param cmd: command and arguments as a list :param env_data :return string ú /dev/nullT)ÚstdinÚstdoutÚstderrÚ close_fdsÚenvÚtextrNzoutput of the command: ú ú )Ú subprocessÚPopenÚopenÚPIPEÚSTDOUTÚ communicateÚOSErrorÚIOErrorrÚFileProcessErrorÚstrÚ returncodeÚExternalProgramFailedÚjoin)ÚcmdÚenv_dataÚoutputÚstd_outÚstd_errÚes úE/opt/cloudlinux/venv/lib64/python3.11/site-packages/clselect/utils.pyÚ run_commandr9)så€ð >ÝÔ!Ø Ý�{Ñ#Ô#Ý”?ÝÔ$ØØØð ñ ô ˆð"×-Ò-Ñ/Ô/ш��øÝ •WÐ ð>ð>ð>ÝÔ-¨c°!¬fµc¸!±f´fÑ=Ô=Ð=øøøøð>øøøà Ô˜AÒÐÝÔ2Ø Ð QÐ Q¸#¿(º(À3¹-¼-¸-¸-ÈÈÐQñ ô ð ð €Ns‚AAÁBÁ'(BÂBc óD— tj|td¦«tjtj|d||¬¦«}| ¦«\}}nA#t t f$r-}tj|dt|¦«¦«‚d}~wwxYw|j ||fS)a³ Runs external process and returns output. Differs from subprocess.check_output, run_command above, and check_output below in that it does not throw an exception if process's return code != 0 :param cmd: command and arguments as a list :param env_data :param preexec_fn: Pre-exec function. None if don't need :param cwd: Directory name to set as current :return Cortege: (ret_code, stdout, stderr) rT)rrrÚ preexec_fnr Úcwdr!rN) r%r&r'r(r*r+r,rr-r.r/)r2r3r;r<Úprocessr5r6r7s r8Úrun_command_fullr>Ds­€ð >ÝÔ"Ø Ý�{Ñ#Ô#Ý”?Ý”?Ø!ØØØð  ñ  ô  ˆð#×.Ò.Ñ0Ô0ш��øÝ •WÐ ð>ð>ð>ÝÔ-¨c°!¬fµc¸!±f´fÑ=Ô=Ð=øøøøð>øøøà Ô ˜w¨Ð /Ð/s‚AAÁBÁ((BÂBcóª—d} t|¦«}| ¦«}| ¦«n#ttf$rYnwxYw|S)z8 Reads file contents and returns it as a string Ú)r'ÚreadÚcloser+r,)ÚfilenameÚdefaults_contentsÚfs r8Úread_file_as_stringrF`sb€ðÐð Ý �‰NŒNˆØŸFšF™HœHÐØ �Љ Œ ˆ ˆ øÝ •WÐ ð ð ð Ø ˆð øøøà Ðs„7<¼AÁAcó—t|i|¤ŽdS©N)Ú check_output)ÚargsÚkwargss r8Ú check_callrLns€Ý�$Ð!˜&Ð!Ð!Ð!Ð!Ð!ócó�—| dd¦«}| d¦«}| dd¦«}| dd¦«}|r||z }|d= tjd |tjtjddœ|¤Ž}nA#t t f$r-}tj|dt|¦«¦«‚d}~wwxYw|  ¦«\}} |r)|  |¦«|  ¦«|�|  ¦«|jrtj|p| p|¦«‚|S) av check_output(val1, val2, val3, arg4=val4) equivalent check_output(args=(val1, val2, val3), arg4=val4) or equivalent check_output(val1, args=(val2, val3), arg4=val4) DON'T USE check_output((val1, val2, val3), arg4=val4) :param tuple *args: arguments for command line :param dict **kwargs: parameters for subprocess.Popen :return str: ÚerrorNrJr4ÚwaitT)rJrrr"r©)ÚpopÚgetr%r&r(r+r,rr-r.r*ÚwriterBrPr/r0) rJrKrOÚargs_from_kwargsr4rPÚpr7rrs r8rIrIrsN€ð �JŠJ�w Ñ %Ô %€EØ—z’z &Ñ)Ô)ÐØ �ZŠZ˜ $Ñ 'Ô '€FØ �:Š:�f˜dÑ #Ô #€DØðØ Ð Ñ ˆØ �6ˆNð?Ý Ô Ð l $­z¬ÅzÄÐ]aÐ lÐ lÐekÐ lÐ lˆˆøÝ •WÐ ð?ð?ð?ÝÔ-¨d°1¬gµs¸1±v´vÑ>Ô>Ð>øøøøð?øøøà—]’]‘_”_�N€FˆFØ ðØ� Š �VÑÔÐØ� Š ‰ŒˆØ ÐØ �ЉŒˆØ„|ðNÝÔ2°5Ð3L¸FÐ3LÀfÑMÔMÐMØ €MsÁ#*BÂC Â(CÃC cóD‡—ˆfd„tj‰¦«D¦«S)NcóŽ•—g|]A}tj tj ‰|¦«¦«¯?|‘ŒBSrQ)ÚosÚpathÚisdirr1)Ú.0ÚdrZs €r8ú zlist_dirs..•s<ø€Ð PÐ PÐ P�!­2¬7¯=ª=½¼¿ºÀdÈAÑ9NÔ9NÑ+OÔ+OÐ PˆAÐ PÐ PÐ PrM)rYÚlistdir©rZs`r8Ú list_dirsra”s'ø€Ø PÐ PÐ PÐ P•r”z $Ñ'Ô'Ð PÑ PÔ PÐPrMc #ó²K—|V—|D]M\}}|t|¦«zV—|D]1}|d tt||f¦«¦«zV—Œ2ŒNdS)Nú.)r.r1Úmap)rZÚversionsÚmajorÚminorsÚminors r8Ú versioningri˜s…èè€Ø €J€J€JØ!ð<ð<‰ ˆˆvØ•S˜‘Z”ZÑÐÐÐØð <ð <ˆEؘŸš¥#¥c¨E°5¨>Ñ":Ô":Ñ;Ô;Ñ;Ð ;Ð ;Ð ;Ð ;ð <ð<ð¾A)ÚwÚwbÚaÚabc ó— t|}n6#t$r)td|›dtt¦«›d�¦«‚wxYwt j||tjztjzd¦«}t j|||¬¦«S)zqOpen `path` for writing with O_NOFOLLOW on the leaf so a symlinked target is refused instead of dereferenced.z-file_write/file_writelines: unsupported mode z (expected one of ú)i¤r‡) Ú_MODE_TO_OS_FLAGSÚKeyErrorÚ ValueErrorÚsortedrYr'Ú O_NOFOLLOWÚ O_CLOEXECÚfdopen)rZr�r‚ÚflagsÚfds r8Ú_open_no_follow_writer™æs¢€ðHÝ! $Ô'ˆˆøÝ ðHðHðH݈jà&* d d­FÕ3DÑ,EÔ,EÐ,EÐ,Eð GñHôHð HðHøøøõ Œ��u�rœ}Ñ,­r¬|Ñ;¸UÑ CÔ C€BÝ Œ9�R˜ fÐ -Ñ -Ô -Ð-s ‚ �3ArŠcó°—t|||¬¦«} | |¦«| ¦«dS#| ¦«wxYw©zN write litle data to file and close :param path: :return str: r‡N)r™rTrB)rZÚliner�r‚r„s r8Ú file_writer�ósR€õ # 4¨°fÐ =Ñ =Ô =€FðØ� Š �TÑÔÐà� Š ‰Œˆˆˆøˆ� Š ‰Œˆˆøøøó ”?¿Acó°—t|||¬¦«} | |¦«| ¦«dS#| ¦«wxYwr›)r™Ú writelinesrB)rZÚlinesr�r‚r„s r8Úfile_writelinesr¢sT€õ # 4¨°fÐ =Ñ =Ô =€FðØ×Ò˜%Ñ Ô Ð à� Š ‰Œˆˆˆøˆ� Š ‰Œˆˆøøøržcó—tjddkr+tjddkr| |¦«S| |d¦«}t |¦«dkr|d||df}n |dddf}|S)z¸ str.partition for all python versions :param s: string to parse :param sep: separator to split by :return: cortege - see str.partition function for python 2.5+ rérér@)ÚsysÚ version_infoÚ partitionÚsplitrx)ÚsrvÚs_partsÚ ret_corteges r8Ú s_partitionr­ s‰€õ Ô˜Ô˜aÒÐ¥CÔ$4°QÔ$7¸1Ò$<Ð$<Ø�{Š{˜3ÑÔÐà�gŠg�c˜1‰oŒo€GÝ ˆ7�|„|�qÒÐØ˜q”z 3¨°¬ Ð3ˆ ˆ à˜q”z 2 rÐ*ˆ Ø ÐrMcóÞ— t|d¦«}n#t$rYdSwxYwd}tj|¦«}|D]}| |¦«r|dz }Œ| ¦«|S)z" find regex count in file rNrr)r'r,ÚreÚcompileÚsearchrB)ÚpatternrZrEÚcounterÚregexrœs r8Úgreprµs�€ðÝ ��s‰OŒOˆˆøÝ ððð؈tˆtðøøøð€GÝ ŒJ�wÑ Ô €EØððˆØ �<Š<˜Ñ Ô ð Ø �q‰LˆGøà‡G‚G�I„I€IØ €Ns ‚“ ! !có$—ddlm}||¦«S)z¢ Determines is user should be skipped in selectorctl work :param username: user name to check :return: True - user should be skipped, False - not r)Úis_admin)Úclcommon.cpapir·)Úusernamer·s r8Úuser_should_be_skippedrº2s(€ð (Ð'Ð'Ð'Ð'Ð'ð ˆ8�HÑ Ô ÐrMc ó—tj |¦«se t|d¦«dS#tt f$r>}t d|dt|¦«¦«tj d¦«Yd}~dSd}~wwxYwdS)NiízError: failed to createú:r) rYrZr[rr,r+Úprintr.r¦Úexit)Údest_dirr7s r8Úmake_dirrÀ>s•€Ý Œ7�=Š=˜Ñ "Ô "ðð Ý ˜ 5Ñ )Ô )Ð )Ð )Ð )øÝ�Ð!ð ð ð Ý Ð+¨X°s½CÀ¹F¼FÑ CÔ CÐ CÝ ŒH�Q‰KŒKˆKˆKˆKˆKˆKˆKˆKøøøøð øøøððs¡3³BÁ3A=Á=Bcó¾— tj|¦«n#t$rYnwxYwtj |¦«rt j|d¦«dSdS)NT)rYÚunlinkr+rZr[ÚshutilÚrmtreer`s r8Úremove_file_or_dirrÅGsn€ð Ý Œ �$‰ŒˆˆøÝ ð ð ð Ø ˆð øøøå „w‡}‚}�TÑÔð"ÝŒ �d˜DÑ!Ô!Ð!Ð!Ð!ð"ð"s ‚— $£$c ó²— tj |¦«rEtj|¦«|kr+tj|¦«tj||¦«dSdSt |¦«tj||¦«dS#t$r@}td|d|dt|¦«¦«tj d¦«Yd}~dSd}~wwxYw)NzError: failed to create symlinkz->r¼r) rYrZÚislinkÚreadlinkrÂÚsymlinkrÅr+r½r.r¦r¾)ÚsrcÚdstr7s r8Ú make_symlinkrÌPsÞ€ð Ý Œ7�>Š>˜#Ñ Ô ð !ÝŒ{˜3ÑÔ 3Ò&Ð&Ý” ˜#‘”�Ý” ˜3 Ñ$Ô$Ð$Ð$Ð$ð'Ð&õ ˜sÑ #Ô #Ð #Ý ŒJ�s˜CÑ Ô Ð Ð Ð øÝ ðððÝ Ð/°°d¸CÀÅcÈ!ÁfÄfÑMÔMÐMÝ Œ�‰ Œ ˆ ˆ ˆ ˆ ˆ ˆ ˆ øøøøðøøøs‚A B Á&$B  CÂ5CÃCcó2—tj|ddd¬¦«S)Né)ú,z: T)ÚindentÚ separatorsÚ sort_keys)ÚjsonÚdumps)rƒs r8Ú pretty_jsonrÕ^s€Ý Œ:�d 1°ÈÐ MÑ MÔ MÐMrMr"Fc óÜ—|}d} t||¬¦«\}}nÏ#t$rCtj|dd ||¦«dœ¦«t jd¦«Ynƒt$r:|rn4tj|ddtzdœ¦«t jd¦«YnAt$r5tj|dd|›d |›�dœ¦«t jd¦«YnwxYw||fS) a¨ Safely resolve username and doc_root by domain, or resolve document root by username, or resolve document root and username by effective uid :param pass_not_supported_panel: pass not supported panel for php selector :param msg_format: error messages' format (json or text) :param user: str -> name of unix user :param domain: str -> domain of panel user :return: tuple -> user, doc_root N)ryÚdomainÚERRORz(No domain found for user: {}, domain: {})ÚstatusÚmessagerz6NodeJs/Ruby/Python selector not supported for %s panelzDomain z is not owned by the user ) rrrÚ print_diagÚformatr¦r¾rrr)ryr×Ú msg_formatÚpass_not_supported_panelÚ result_userÚresult_doc_roots r8Ú$safely_resolve_username_and_doc_rootrácsW€ð€KØ€OðÝ'DØØð( ñ( ô( Ñ$ˆ �_�_øõ ðððÝÔØ  7Ð7a×7hÒ7hÐimÐouÑ7vÔ7vÐwÐwñ ô ð õ Œ�‰ Œ ˆ ˆ ˆ Ý ðððØ #ð Ø å Ô ØØ"Ð/gÕjqÑ/qÐrÐrñ ô ð õ ŒH�Q‰KŒKˆKøøÝ ðððÝÔØ  7 7ÐbhÐbhÐbhÐjnÐjnÐ7oÐpÐpñ ô ð õ Œ�‰ Œ ˆ ˆ ˆ ð øøøð ˜Ð 'Ð's†›A C'Á'AC'Â);C'Ã&C'cóÈ—t||¦«d}|D](}t||¦«d}||kr ||cSŒ)td |¦«¦«‚)a Transform all directories to realpath, compare and return config value :param user: str -> unix user - owner of the config :param directory: str -> wanted directory key :param config: dict -> config to get value from, should have directories as keys rú%Config does not contain directory: {})r~r‘rÜ)ryrzÚconfigÚ abs_directoryÚconf_dirÚ abs_conf_dirs r8Úget_using_realpath_keysrè�s{€õ   iÑ0Ô0°Ô3€MØð$ð$ˆÝ" 4¨Ñ2Ô2°1Ô5ˆ Ø ˜LÒ (Ð (ؘ(Ô#Ð #Ð #Ð #ð )õ Ð:×AÒAÀ)ÑLÔLÑ MÔ MÐMrMcó —t||¦«d}d}t| ¦«¦«}|D]#}t||¦«d}||kr||=d}Œ$|s"td |¦«¦«‚dS)a Transform all directories to realpath, compare and remove directory key :param user: str -> unix user - owner of the config :param directory: str -> wanted directory key :param config: dict -> config to remove key from, should have directories as keys rFTrãN)r~ÚlistÚkeysr‘rÜ)ryrzräråÚremoved_at_least_oneÚ config_keysrærçs r8Údelete_using_realpath_keysrîžs¢€õ   iÑ0Ô0°Ô3€MØ ÐÝ�v—{’{‘}”}Ñ%Ô%€KØð(ð(ˆÝ" 4¨Ñ2Ô2°1Ô5ˆ Ø ˜LÒ (Ð (Ø�xÐ Ø#'Ð øØ ðRÝÐ>×EÒEÀiÑPÔPÑQÔQÐQðRðRrMcó^—t||¦«dt||¦«dkS)a# Checks that two paths in user home directory are the same after stripping symlinks :param user: Unix user whose home directory contains both paths :type path1: str :type path2: str :return: True if paths are canonically the same otherwise False :rtype: bool r)r~)ryÚpath1Úpath2s r8Úrealpaths_are_equalrò²s-€õ �t˜UÑ #Ô # AÔ &­+°d¸EÑ*BÔ*BÀ1Ô*EÒ EÐErMç@có—t¦«|z} tj|d¦«n3#t$r&}|jtjkrYd}~dSYd}~dSd}~wwxYwt¦«|krdSt d¦«Œn)z;Wait until a killed session can no longer run account code.TrNFgš™™™™™©?)rrYÚkillpgr+rlÚESRCHr)ÚpidÚtimeoutÚdeadlinerns r8Ú_wait_for_process_group_exitrúÃs�€å‰{Œ{˜WÑ$€Hð ð Ý ŒI�c˜1Ñ Ô Ð Ð øÝð ð ð ØŒy�EœKÒ'Ð'Ø�t�t�t�t�tØ�5�5�5�5�5øøøøð øøøõ ‰;Œ;˜(Ò "Ð "Ø�5Ý ˆd‰ Œ ˆ ð s”*ª A´AÁAcóÖ— tj|d¦«n#t$rYdSwxYw tj|tj¦«n#t$rYnwxYwt |¦«dS)zBKill descendants left in the session after its direct child exits.rN)rYrõr+ÚsignalÚSIGKILLrú)r÷s r8Ú_kill_remaining_process_grouprþÒsŽ€ðÝ Œ �#�qÑÔÐÐøÝ ðððØˆˆðøøøð Ý Œ �#•v”~Ñ&Ô&Ð&Ð&øÝ ð ð ð Ø ˆð øøøå  Ñ%Ô%Ð%Ð%Ð%s‚˜ &¥&ªA Á AÁAcóz— tj|jtj¦«n#t $rYnwxYw | d¬¦«}t|j¦«nX#tj $rFt|j¦« | d¬¦«}n#tj $rd}YnwxYwYnwxYw|S)z>Stop a timed-out child and every process still in its session.r¥©rø)r@r@) rYrõr÷rüÚSIGTERMr+r*rþr%ÚTimeoutExpired)r=r4s r8Ú_terminate_process_grouprßsí€ð Ý Œ �'”+�vœ~Ñ.Ô.Ð.Ð.øÝ ð ð ð Ø ˆð øøøð 3Ø×$Ò$¨QÐ$Ñ/Ô/ˆõ & g¤kÑ2Ô2Ð2Ð2øõ Ô $ðððÝ% g¤kÑ2Ô2Ð2ð Ø×(Ò(°Ð(Ñ3Ô3ˆFˆFøÝÔ(ð ð ð ØˆFˆFˆFð øøøøøð øøøð €MsA‚$'§ 4³4¸A#Á##B8ÂBÂB8ÂB2Â/B8Â1B2Â2B8Â7B8có,—i}|si}t||g|z}t|tjtjd¬¦«}|�d|d<tj|fi|¤Ž}d} |€| ¦«\} } n| |¬¦«\} } n)#tj$rd} t|¦«\} } YnwxYw| rdn|j} | s,| dkr&d   |¦«d t¦«d œ} n|   ¦«} | |d <| |d <| rdnd|d<|S)z= Run any process using the utility cagefs_enter_user T)r!rrr"NÚstart_new_sessionFré|é€zËUser's process "{}" failed and didn't return anything. It could mean that user has too small limit of PMEM for running of cloudlinux-selector. Please, increase the limit to user and try run process againrO)ÚdetailsÚresultÚ timestampr4r/Úfailed) ÚCAGEFS_ENTER_USER_BINÚdictr%r(r&r*rrr/rÜrÚstrip) ryÚpath_to_utilityÚargs_for_utilityÚenv_varsrør r2Ú popen_argsr=Ú timed_outrÚ_Úretcodes r8Úrun_process_in_cagefsrôsz€ð €Fð ðØˆÝ  $¨Ð 8Ð;KÑ K€Cݘ(­:¬?Ý'œ_°4ð9ñ9ô9€JàÐð+/ˆ Ð&Ñ'ÝÔ˜sÐ1Ð1 jÐ1Ð1€GØ€Ið6Ø ˆ?Ø×+Ò+Ñ-Ô-‰IˆF�A�Aà×+Ò+°GÐ+Ñ<Ô<‰IˆF�AøøÝ Ô $ð6ð6ð6؈ Ý,¨WÑ5Ô5‰ ˆ���ð6øøøðÐ6ˆcˆc GÔ$6€Gð ð  �g ’m�mðCçCIÂ6È/ÑCZÔCZØÝ™œð  𠈈𗒑”ˆØ€Fˆ8ÑØ"€Fˆ<ÑØ&Ð1�t�t¨E€Fˆ8ÑØ €MsÁ3B  #B1Â0B1ÚversionÚreturncóš—tdtd¦«td¬¦«}d| dd¦«›�}d}t d¦«}| ¦«sdS t |¦«5}| ¦«}d d d ¦«n #1swxYwY| d ¦«std |›d �¦«‚||vrd S||vr[t |  d ¦«  ¦«¦«}|  ¦«}|t|¦«vrd Sn#| ¦«YnxYwdS)ar Check if python version is used by imunify packages The algorithm is as follows: - Verify if imunify services are installed - Check if shebang contains the path to the specified Python version being checked - If shebang contains the path to the imunify virtual environment, determine the Python version it is based on by reading a symlink Ú lvemanagerF)ÚreleaseÚdsnÚhandlez/opt/alt/pythonrcr@z/opt/imunify360/venvz/usr/bin/imunify-serviceNz#!zERROR: "z" doesn't have a shebangT)rrÚ LVEMANDSNÚreplacer Úis_filer'ÚreadlineruÚ ExceptionÚlstriprrÈr.ÚcaptureException) rÚ sentry_clientÚalt_pathÚimunify_venv_pathÚimunify_servicerEÚ first_lineÚvenv_python_binÚ python_bins r8Úis_imunify_using_pythonr,'s¡€õ' |½_È\Ñ=ZÔ=ZÕ`iÐrwÐxÑxÔx€Mà; §¢°°bÑ!9Ô!9Ð;Ð;€HØ.ÐÝÐ5Ñ6Ô6€OØ × "Ò "Ñ $Ô $ð؈uð)Ý �/Ñ "Ô "ð & aØŸš™œˆJð &ð &ð &ñ &ô &ð &ð &ð &ð &ð &ð &øøøð &ð &ð &ð &ð×$Ò$ TÑ*Ô*ð SÝÐQ ÐQÐQÐQÑRÔRÐ Rà �zÐ !Ð !Ø�4à   Ð *Ð *Ý" :×#4Ò#4°TÑ#:Ô#:×#@Ò#@Ñ#BÔ#BÑCÔCˆOØ(×1Ò1Ñ3Ô3ˆJØ�3˜z™?œ?Ð*Ð*Ø�tøøð)Ø×&Ò&Ñ(Ô(Ð(Ð(Ð(øøøà ˆ5s7Á'D0Á6B D0ÂBÂD0ÂBÂ/D0ÃAD0Ä0Erycó>‡‡—tj‰¦«Šˆˆfd„}|S)z Drops to user có•—tj¦«dkrtjg¦«tj‰j¦«tj‰j¦«‰tjd<‰jtjd<dS)NrÚUSERÚHOME) rYÚgeteuidÚ setgroupsÚsetgidÚpw_gidÚsetuidÚpw_uidÚenvironrt)ryÚuser_pwds€€r8Úfunczdemote..funcTsjø€õ Œ:‰<Œ<˜1Ò Ð Ý ŒL˜Ñ Ô Ð Ý Œ �(”/Ñ"Ô"Ð"Ý Œ �(”/Ñ"Ô"Ð"Ø!�Œ �6ÑØ%œ_�Œ �6ÑÐÐrM)rrrs)ryr9r8s` @r8Údemoter:Ns:øø€õŒ|˜DÑ!Ô!€Hð -ð -ð -ð -ð -ð -ð €KrMcól—d}d}|D](} ||g|¢Ri|¤Ž}|dz}Œ#|$r } | }Yd} ~ Œ!d} ~ wwxYw|s|‚|S)NFTrQ) r9ÚusersÚexception_typerJrKÚcaught_exceptionÚ is_handledÚ user_aliasr r7s r8Úapply_for_at_least_one_userrAfs™€ØÐØ€Jàððˆ ð Ø�T˜*Ð6 tÐ6Ð6Ð6¨vÐ6Ð6ˆFð ˜$Ñ ˆJˆJøðð !ð !ð !Ø Ð Ð Ð Ð Ð Ð øøøøð !øøøð ðØÐà €MsŠ œ-¡(¨-có²—t|¦«}d|jvr1|j dd¦«}| |¬¦«}t |¦«S)aÎ Transforms a URL containing a wildcard ('*') in the netloc. If the netloc of the URL contains a '*', it replaces the '*' with 'any'. This is necessary because URLs with wildcards are not valid for HTTP requests. Replacing '*' with 'any' ensures compatibility with systems or libraries that do not support wildcards in URLs. :param url: str - The URL to transform. :return: str - The transformed URL with the wildcard replaced. Ú*Úany)Únetloc)rrErÚ_replacer)ÚurlÚparsedrEs r8Útransform_wildcard_urlrIxsT€õ�c‰]Œ]€FØ ˆfŒmÐÐØ”×&Ò& s¨EÑ2Ô2ˆØ—’¨�Ñ/Ô/ˆÝ �fÑ Ô ÐrMrH)NNN)rN)rŠN)NNr"F)ró)NN)VÚ __future__rrrrlrYrrr¯r%r¦rÓrÃrürrrÚtypingr r r r Úpathlibr Ú urllib.parserrÚclcommon.clpwdrr¸rÚclcommon.cpapi.cpapiexceptionsrrrÚclcommon.utilsrÚclsentryrÚclsentry.utilsrÚ clselectprintrÚclselectexceptrr rr9r>rFrLrIrariror~r…r‰ÚO_WRONLYÚO_CREATÚO_TRUNCÚO_APPENDr�r™r�r¢r­rµrºrÀrÅrÌrÕrárèrîròrúrþrrr.Úboolr,r:rArIrQrMr8úrZshðð&Ð%Ð%Ð%Ð%Ð%Ø&Ð&Ð&Ð&Ð&Ð&ØÐÐÐÐÐØ € € € Ø € € € Ø € € € Ø € € € ØÐÐÐØ € € € Ø € € € Ø € € € Ø € € € à'Ð'Ð'Ð'Ð'Ð'Ð'Ð'Ð'Ð'Ø/Ð/Ð/Ð/Ð/Ð/Ð/Ð/Ð/Ð/Ð/Ð/ØÐÐÐÐÐØ-Ð-Ð-Ð-Ð-Ð-Ð-Ð-à8Ð8Ð8Ð8Ð8Ð8Ø"Ð"Ð"Ð"Ð"Ð"ØPÐPÐPÐPÐPÐPÐPÐPÐPÐPØ'Ð'Ð'Ð'Ð'Ð'Ø'Ð'Ð'Ð'Ð'Ð'Ø*Ð*Ð*Ð*Ð*Ð*à"Ð"Ð"Ð"Ð"Ð"Ø*Ð*Ð*Ð*Ð*Ð*ð2ÐØ s€ ððððð60ð0ð0ð0ð8 ð ð ð"ð"ð"ððððDQðQðQð<ð<ð<ððððððð* ð ð ð ð ð ð ð ð Œ�r”zÑ ! B¤JÑ .Ø Œ+˜œ Ñ " R¤ZÑ /Ø Œ�r”zÑ ! B¤KÑ /Ø Œ+˜œ Ñ " R¤[Ñ 0ð ðÐð .ð .ð .ð .ð ð ð ð ð ð ð ð ðððð$ððð& ð ð ðððð"ð"ð"ð ð ð ðNðNðNð '(ð'(ð'(ð'(ðTNðNðNð"RðRðRð( Fð Fð Fð" ð ð ð ð &ð &ð &ðððð*MQØ"&ð0ð0ð0ð0ðf$ Sð$¨Tð$ð$ð$ð$ðN�ððððð0ððð$ððððrM