§ Rl¾jngãó`—dZddlZddlmZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl m Z mZddlmZmZddlmZddlmZmZddlmZmZdd lmZd d lmZd d lmZd d l m!Z!m"Z"ej#e$¦«Z%dZ&dZ'd Z(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1d„Z2d„Z3d„Z4e Gd„d¦«¦«Z5e Gd„d¦«¦«Z6e Gd „d!¦«¦«Z7ed"„¦«Z8d#„Z9d$„Z:d%„Z;d&„Zd)„Z?d*„Z@ejAd+„¦«ZBed,eCfd-„¦«ZDd.„ZEd/„ZFd0„ZGd1„ZHd2„ZIdS)4z9Per-user domain config persistence (~/.lve/domains.json).éN)Úcache)Ú dataclassÚfield)ÚListÚOptional)Ú disable_quota)ÚClPwdÚdrop_privileges)Ú userdomainsÚdocroot)ÚCPAPIExceptioné)Údomain_lve_sentry_extra)Ú id_registry)Ú ErrorCodeÚLvdErrorz.lvez domains.jsong$@gš™™™™™¹?iiˆ)ÚcpuÚpmemÚioÚnprocÚiopsÚepÚvmemi€iÿÿÿi)rrcól—|tvrttzttzfSttfS)zEReturn the inclusive (min, max) a stored *field_name* value may take.)Ú _BYTES_FIELDSÚ _INT32_MINÚ PAGE_SIZEÚ _INT32_MAX)Ú field_names úN/opt/cloudlinux/venv/lib64/python3.11/site-packages/websiteisolation/config.pyÚ _limit_boundsr!Is-€à•]Ð"Ð"Ý�IÑ%¥zµIÑ'=Ð=Ð=Ý •zÐ !Ð!óc ó^— t|¦«}nS#tttf$r9}t d|›dt |¦«j›�tj¬¦«d‚d}~wwxYwt|¦«\}}||cxkr|ks)nt d|›d|›d|›d|›�tj¬¦«‚|S)a2Coerce *value* to int and bound it to what *field_name* can carry. The single definition of "a usable limit value", shared by the reader and the writer. They disagreed once, and a value that could be written but not read back made the whole account's configuration unreadable (CLOS-7494). úlimit 'z' must be an integer, got ©ÚcodeNz' out of range [z, z], got ) ÚintÚ TypeErrorÚ ValueErrorÚ OverflowErrorrÚtypeÚ__name__rÚ INVALID_VALUEr!)rÚvalueÚivÚeÚlowÚhighs r Ú_validate_limitr3Psþ€ð 4Ý �‰ZŒZˆˆøÝ •z¥=Ð 1ð 4ð 4ð 4õð *�jð *ð *ݘ‘;”;Ô'ð *ð *åÔ(ð*ñ*ô*ð04ð 4øøøøð 4øøøõ˜jÑ)Ô)�I€CˆØ �"Ð Ð Ò Ð ˜Ò Ð Ð Ð ÝØ J�jÐ JÐ J°#Ð JÐ J¸Ð JÐ JÀbÐ JÐ JÝÔ(ð*ñ*ô*ð *ð €Is‚’A"©4AÁA"cóš—|tvr?d|cxkr tkr/ndStd|›dt›d|›�tj¬¦«‚dSdS)a_Refuse a memory limit smaller than one page, other than 0. The kernel takes memory limits in pages, so a value below PAGE_SIZE reaches it as 0 -- unlimited -- while the caller is told it was set (CLOS-7520). Checked on write only: a stored record with such a value still reads back, so the account's other records stay reachable. rr$z$' must be 0 (unlimited) or at least z bytes, got r%N)rrrrr-)rr.s r Ú_reject_sub_pager5ms‰€ð•]Ð"Ð" q¨5Ð'<Ð'<Ò'<Ð'<µ9Ò'<Ð'<Ð'<Ð'<Ð'<Ð'<Ýð .�jð .ð .Ýð .ð .Ø&+ð .ð .åÔ(ð*ñ*ô*ð *ð#Ð"Ð'<Ð'z(DomainLimits.to_dict..ˆs€ÐHÐHÐH™˜˜A¸!¸-��1¸-¸-¸-r")Ú__dict__Úitems©Úselfs r Úto_dictzDomainLimits.to_dict†s$€àHÐH ¤×!4Ò!4Ñ!6Ô!6ÐHÑHÔHÐHr"cóØ—|s |¦«St|t¦«s$tdt|¦«j›�¦«‚d„| ¦«D¦«}|di|¤ŽS)Nzlimits must be an object, got cóH—i|]\}}|tv¯|t||¦«“Œ Sr;©Ú LIMIT_FIELDSr3r<s r r@z*DomainLimits.from_dict..•s?€ðAðAðAÙ�a˜¨aµ<Ð.?Ð.?ð•_ Q¨Ñ*Ô*Ø.?Ð.?Ð.?r"r;)Ú isinstanceÚdictrr+r,rB)ÚclsÚdataÚvaluess r Ú from_dictzDomainLimits.from_dictŠs…€àð Ø�3‘5”5ˆLݘ$¥Ñ%Ô%ð SÝÐQ½DÀ¹J¼JÔ.¥s>€ð=ð=ð=±$°!°QØ�\Ð)Ð)¨a¨mð�¨¨1Ñ-Ô-Ø.;¨m¨mr"N)rBr5Úsetattr)rDÚkwargsÚ validatedr>r?s r ÚupdatezDomainLimits.update™s“€ð=ð=¸&¿,º,¹.¼.ð=ñ=ô=ˆ à—O’OÑ%Ô%ð #ð #‰DˆAˆqÝ ˜Q Ñ "Ô "Ð "Ð "Ø—O’OÑ%Ô%ð ð ‰DˆAˆqÝ �D˜!˜QÑ Ô Ð Ð ð ð r"cób—td„|j ¦«D¦«¦«S)Nc3óK—|]}|duV—Œ dSr:r;)r=r?s r ú z(DomainLimits.__bool__..­s&èè€ÐAÐA Q�1˜D�=ÐAÐAÐAÐAÐAÐAr")ÚanyrArNrCs r Ú__bool__zDomainLimits.__bool__¬s-€ÝÐAÐA¨$¬-×*>Ò*>Ñ*@Ô*@ÐAÑAÔAÑAÔAÐAr")r,Ú __module__Ú __qualname__rrr'Ú__annotations__rrrrrrrEÚ classmethodrOrUrZr;r"r r7r7|sò€€€€€€à€Cˆ�#ŒÐÐÑØ€Dˆ(�3Œ-ÐÐÑØ€Bˆ�Œ ÐÐÑØ€Eˆ8�CŒ=ÐÐÑØ€Dˆ(�3Œ-ÐÐÑØ€Bˆ�Œ ÐÐÑØ€Dˆ(�3Œ-ÐÐÑðIðIðIðð ð ñ„[ð ð ð ð ð&BðBðBðBðBr"r7có\—eZdZUdZeed<ee¬¦«Zeed<d„Z e d„¦«Z dS)Ú DomainEntryÚÚname©Údefault_factoryÚlimitscóD—|j|j ¦«dœS)N©rbre)rbrerErCs r rEzDomainEntry.to_dictµs'€à”IØ”k×)Ò)Ñ+Ô+ð ð ð r"có‚—t|t¦«s$tdt|¦«j›�¦«‚| dd¦«}t|t ¦«s$tdt|¦«j›�¦«‚||t | d¦«¦«¬¦«S)Nz$domain entry must be an object, got rbraz$domain 'name' must be a string, got rerg) rJrKrr+r,ÚgetÚstrr7rO)rLrMrbs r rOzDomainEntry.from_dict»s¶€å˜$¥Ñ%Ô%ð YÝÐWÅ$ÀtÁ*Ä*ÔBUÐWÐWÑXÔXÐ Xð�xŠx˜ Ñ#Ô#ˆÝ˜$¥Ñ$Ô$ð YÝÐWÅ$ÀtÁ*Ä*ÔBUÐWÐWÑXÔXÐ X؈sØÝ×)Ò)¨$¯(ª(°8Ñ*<Ô*<Ñ=Ô=ð ñ ô ð r"N) r,r[r\rbrjr]rr7rerEr^rOr;r"r r`r`°sj€€€€€€à€Dˆ#€N€N�NØ ˜5°Ð>Ñ>Ô>€FˆLÐ>Ð>Ñ>ð ð ð ð ð ð ñ„[ð ð ð r"r`cót—eZdZUeZeed<ee¬¦«Z e e ed<eddd¬¦«Z e eed<eddd¬¦«Zeed<ed „¦«Zd „Zd „Zd „Zd „Zd„Zedd„¦«Zedd„¦«Zdd„Zeejdd„¦«¦«Zed„¦«Zed„¦«Z d„Z!dS)Ú LvdConfigÚversionrcÚdomainsNF)ÚdefaultÚreprÚcompareÚ_lve_idÚ _degradedcó—|jS)a„True when this config stands in for a file that could not be read. It is empty like a fresh config, but the two mean opposite things: a fresh config says the account has no records, this one says its records could not be reached. Anything that would present it as the account's configuration, or write it back, has to tell them apart (CLOS-7494). )rsrCs r Ú unreadablezLvdConfig.unreadableØs €ðŒ~Ðr"có8—|jD]}|j|kr|cSŒdS)z5Find domain entry by name. Returns None if not found.N)rnrb)rDrbÚds r Ú find_domainzLvdConfig.find_domainãs1€à”ð ð ˆAØŒv˜Š~ˆ~Ø���ðàˆtr"có8‡—ˆfd„|jD¦«|_dS)zRemove domain entry by name.có*•—g|]}|j‰k¯ |‘ŒSr;©rb)r=rwrbs €r ú z+LvdConfig.remove_domain..ìs ø€ÐBÐBÐB˜a°1´6¸T²>°>˜°>°>°>r"N)rn)rDrbs `r Ú remove_domainzLvdConfig.remove_domainês$ø€àBÐBÐBÐB 4¤<ÐBÑBÔBˆŒ ˆ ˆ r"c ó˜— t|j|¦«}|rS| |¦«€@|j t |¬¦«¦«| ¦«dSdSdS#t$rO}t  d|j|dtdt|¦«j ¦«¬¦«Yd}~dSd}~wwxYw)zEResolve domain name from *docroot* and add it to the config. Nr{z(add_domain_by_docroot: uid=%s docroot=%sTzadd-domain-by-docroot©Úexc_infoÚextra) Ú_resolve_domain_for_docrootrrrxrnÚappendr`ÚsaverÚlogÚerrorrr+r,©rDr Ú domain_nameÚexcs r Úadd_domain_by_docrootzLvdConfig.add_domain_by_docrootîs€ð bÝ5°d´lÀGÑLÔLˆKØð ˜t×/Ò/° Ñ<Ô<ÐDØ” ×#Ò#¥K°[Ð$AÑ$AÔ$AÑBÔBÐBØ— ’ ‘ ” � � � ð ð ÐDÐDøõð bð bð bõ �IŠIÐ@Ø”l G°dÝ3Ð4KÍTÐRUÉYÌYÔM_Ñ`Ô`ð ñ bô bð bð bð bð bð bð bð bøøøøð  bøøøs‚A(A0Á0 C Á:ACÃC c ór— t|j|¦«}|r@| |¦«�-| |¦«| ¦«dSdSdS#t $rO}t  d|j|dtdt|¦«j ¦«¬¦«Yd}~dSd}~wwxYw)zJResolve domain name from *docroot* and remove it from the config. Nz+remove_domain_by_docroot: uid=%s docroot=%sTzremove-domain-by-docrootr) r‚rrrxr}r„rr…r†rr+r,r‡s r Úremove_domain_by_docrootz"LvdConfig.remove_domain_by_docrootsù€ð eÝ5°d´lÀGÑLÔLˆKØð ˜t×/Ò/° Ñ<Ô<ÐHØ×"Ò" ;Ñ/Ô/Ð/Ø— ’ ‘ ” � � � ð ð ÐHÐHøõð eð eð eõ �IŠIÐCØ”l G°dÝ3Ð4NÕPTÐUXÑPYÔPYÔPbÑcÔcð ñ eô eð eð eð eð eð eð eð eøøøøð eøøøs‚AAÁ B6Á'AB1Â1B6có4—|jd„|jD¦«dœS)Ncó6—g|]}| ¦«‘ŒSr;)rE©r=rws r r|z%LvdConfig.to_dict..s €Ð:Ð:Ð:¨˜Ÿ š ™ œ Ð:Ð:Ð:r"©rmrnr�rCs r rEzLvdConfig.to_dicts)€à”|Ø:Ð:¨T¬\Ð:Ñ:Ô:ð ð ð r"có*—t|t¦«s$tdt|¦«j›�¦«‚d|vrtd¦«‚|d}t|t ¦«s$tdt|¦«j›�¦«‚t |¦«tkr>t  d|t |¦«t¦«|dt…}||  dt¦«d„|D¦«|¬¦«S) Nzconfig must be an object, got rnzconfig has no 'domains' keyz'domains' must be a list, got z8domains.json for lve_id %s has %d domains; capping at %drmcóB—g|]}t |¦«‘ŒSr;)r`rOr�s r r|z'LvdConfig.from_dict..+s&€Ð?Ð?Ð?°!•[×*Ò*¨1Ñ-Ô-Ð?Ð?Ð?r")rmrnrr) rJrKrr+r,ÚlistÚlenÚ MAX_DOMAINSr…ÚwarningriÚLVD_CONFIG_VERSION)rLrMÚlve_idrns r rOzLvdConfig.from_dicts€õ˜$¥Ñ%Ô%ð HÝØFµ°d±´Ô1DÐFÐFñHôHð Hà ˜DÐ Ð ÝÐ8Ñ9Ô9Ð 9Ø�y”/ˆÝ˜'¥4Ñ(Ô(ð VÝÐT½DÀ¹M¼MÔÁ>có4—|j€td¦«‚|jr1tdt|j¦«›d�tj¬¦«‚| |j|¬¦«5| ¦«ddd¦«dS#1swxYwYdS)z™Write domains.json for this user (acquires flock for the write). *lock_timeout* overrides _LOCK_TIMEOUT for this call only. See _flock. Nz,cannot save: config has no associated lve_idzrefusing to overwrite zy: its current contents could not be read, so this write would discard every record in it. Repair or remove the file firstr%rš)rrrrsÚ config_pathrÚCONFIG_UNREADABLErœÚ_write)rDržs r r„zLvdConfig.save:sõ€ð Œ<Ð ÝÐIÑJÔJÐ JØ Œ>ð 2õ ðO­°T´\Ñ)BÔ)BðOðOðOõÔ0ð 2ñ2ô2ð 2ð �[Š[˜œ¨|ˆ[Ñ <Ô <ð ð Ø �KŠK‰MŒMˆMð ð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð sÁ+B  BÂBc #ó¬K—|€tn|}t|¦«5t|¦«}tj |d¦«}tj|tjtjzd¦«} tj ¦«|z} tj |tj tjz¦«n‹#t$r}}|jt jt jfvr‚tj ¦«|kr#t'd|›d|›d�t(j¬¦«|‚tjt.¦«Yd}~nd}~wwxYwŒ¹dV—tj |tj¦«tj|¦«n8#tj |tj¦«tj|¦«wxYw ddd¦«dS#1swxYwYdS) aExclusive flock on a per-user sidecar file. *timeout* defaults to _LOCK_TIMEOUT, which is sized for operations where skipping a tenant has a cost (`lvectl apply all` leaving its limits stale). A caller that only *reads* to count, and would rather skip this account than spend the budget, passes a shorter one: at the 10s default a handful of tenants holding their own lock can consume a whole batch's time budget and starve every account behind them (CLOS-7026). Nz .domains.locki€Tztimed out after zs acquiring domain lock z; another process holds itr%)Ú _LOCK_TIMEOUTÚ user_contextÚensure_config_dirÚosÚpathÚjoinÚopenÚO_CREATÚO_RDWRÚtimeÚ monotonicÚfcntlÚflockÚLOCK_EXÚLOCK_NBÚOSErrorÚerrnoÚEAGAINÚ EWOULDBLOCKrrÚBACKEND_UNAVAILABLEÚsleepÚ_LOCK_RETRY_INTERVALÚLOCK_UNÚclose)r˜r›ÚbudgetÚ config_dirÚ lock_pathÚfdÚdeadliner‰s r rœzLvdConfig._flockQsèè€ð#* /•�°wˆÝ ˜&Ñ !Ô !ð ð Ý*¨6Ñ2Ô2ˆJÝœŸ š  Z°ÑAÔAˆIÝ”˜¥B¤Jµ´Ñ$:¸EÑBÔBˆBð Ýœ>Ñ+Ô+¨fÑ4�ð 9ð 9Ýœ  B­¬ ½¼ Ñ(EÑFÔFÐFØøÝ"ð 9ð 9ð 9Øœ9­U¬\½5Ô;LÐ,MÐMÐMØ!Ýœ>Ñ+Ô+¨xÒ7Ð7Ý"*ð!U°6ð!Uð!UØ/8ð!Uð!Uð!Uå%.Ô%Bð#ñ#ô#ð$'ð 'õ œ Õ#7Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ð8øøøøð 9øøøð 9ð���å” ˜B¥¤ Ñ.Ô.Ð.Ý”˜‘ ” � � øõ” ˜B¥¤ Ñ.Ô.Ð.Ý”˜‘ ” � � øøø� ð/ ð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð sU�AG Á;FÂ,CÂ?Fà Eà A3EÄ=FÅEÅFÅ4G Æ5F8Æ8G Ç G ÇG có—||d¬¦«S)aThe safe default for a file that exists but could not be used. Empty so a root batch carries on for every other tenant, but flagged so it is never mistaken for "this account has no records" -- see LvdConfig.unreadable and save(). T)rrrsr;)rLr˜s r Ú _unreadablezLvdConfig._unreadablexs€ðˆs˜6¨TÐ2Ñ2Ô2Ð2r"cóB—t|¦«}tj |¦«s ||¬¦«S tj|tjtjztjz¦«} tj|¦«}tj |j ¦«sKt  d|¦«| |¦«|dkrtj|¦«SStj|d¦«5}d}| t$dz¦«}t'|¦«t$kr]t  d|t$¦«| |¦«cddd¦«|dkrtj|¦«SSt)j|¦«}ddd¦«n #1swxYwY|dkrtj|¦«n #|dkrtj|¦«wwxYwnU#t,t.t0f$r;}t  d||¦«| |¦«cYd}~Sd}~wwxYw | ||¬ ¦«S#t4t6t,t8t:f$r�}t=|t4¦«rt?|¦«ntA|¦«j!} t  d || ¦«t "d ||¦«| |¦«cYd}~Sd}~wwxYw) N)rrzignoring non-regular config %srÚrbéÿÿÿÿrz)ignoring oversized config %s (> %d bytes)zfailed to read config %s: %s©r˜z!malformed config %s, ignoring: %szmalformed config %s: %r)#r¡r¨r©Úexistsr«ÚO_RDONLYÚ O_NOFOLLOWÚ O_NONBLOCKÚfstatÚstatÚS_ISREGÚst_moder…r–rÃr¼ÚfdopenÚreadÚMAX_CONFIG_BYTESr”ÚjsonÚloadsr)r´ÚRecursionErrorrOrr(ÚAttributeErrorÚKeyErrorrJrjr+r,Údebug) rLr˜r©rÀÚstÚfÚrawrMr0Úreasons r r�zLvdConfig._read‚s:€å˜6Ñ"Ô"ˆÝŒw�~Š~˜dÑ#Ô#ð 'ð�3˜vÐ&Ñ&Ô&Ð &ð! +õ”˜�rœ{­R¬]Ñ:½R¼]ÑJÑKÔKˆBð !Ý”X˜b‘\”\�Ý”| B¤JÑ/Ô/ð3Ý—K’KÐ @À$ÑGÔGÐGØŸ?š?¨6Ñ2Ô2ð˜’7�7Ý”H˜R‘L”L�L�Lðõ”Y˜r 4Ñ(Ô(ð +¨AØ�Bð Ÿ&š&Õ!1°AÑ!5Ñ6Ô6�Cݘ3‘x”xÕ"2Ò2Ð2ÝŸ š Ð$OØ$(Õ*:ñ<ô<ð<à"Ÿš¨vÑ6Ô6ð +ð +ð +ð +ñ +ô +ð +ð˜’7�7Ý”H˜R‘L”L�L�Lðõ œ: c™?œ?�Dð +ð +ð +ñ +ô +ð +ð +ð +ð +ð +ð +øøøð +ð +ð +ð +ð˜’7�7Ý”H˜R‘L”L�Løøð˜’7�7Ý”H˜R‘L”L�L�Lðøøøøøå�G¥^Ð4ð +ð +ð +õ �KŠKÐ6¸¸aÑ @Ô @Ð @Ø—?’? 6Ñ*Ô*Ð *Ð *Ð *Ð *Ð *Ð *øøøøð  +øøøð +Ø—=’= ¨f�=Ñ5Ô5Ð 5øÝ�)¥ZµÅÐJð +ð +ð +õ *¨!­XÑ6Ô6ÐL•S˜‘V”V�V½DÀ¹G¼GÔÁ2 C+Á>BÂC+ÂBÂC+ÃCà C$Ã#C$Ã+"D5ÄD#Ä"D5Ä# D0Ä-D5Ä/D0Ä0D5c#óK—tj¦«dkrct|¦«}t|¦«5t ¦«5dV—ddd¦«n #1swxYwYddd¦«dS#1swxYwYdSdV—dS)uäDrop privileges to the target user if running as root. CLOS-4370: when invoked as root we pair drop_privileges with secureio.disable_quota — creating ~/.lve/ and the lockfile / writing domains.json must succeed even when the user is over disk quota, otherwise OSError(EDQUOT) inside this block aborts batch operations like `lvectl apply all` and leaves the rest of the users with stale limits. disable_quota raises CAP_SYS_RESOURCE in the effective set rN)r¨rÿrýr r)r˜røs r r¦r¦#sèè€õ „z�|„|�qÒÐÝ Ñ'Ô'ˆÝ ˜XÑ &Ô &ð ð ­ ©¬ð ð Ø ˆEˆEˆEð ð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð ð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð 𠈈ˆˆˆs5¸A0ÁAÁ A0ÁA ÁA0ÁA Á A0Á0A4Á7A4Úreturncó—tj}tj |¦«sdSg}tj|¦«D]5} | t|¦«¦«Œ&#t$rYŒ2wxYwt|¦«S)u@Cached scan of the LVD id-registry directory (CLOS-6868). A tuple, not a list, so the cached value cannot be mutated by a caller. `lvectl apply all` calls this roughly twice per account — 7,739 directory scans on a 3,868-account host — for a directory that cannot change while the command runs. r;) rÚ LVD_IDS_DIRr¨r©rÚlistdirrƒr'r)Útuple)Úids_dirÚresultrbs r Ú_isolated_lve_idsr"6s‘€õÔ%€GÝ Œ7�=Š=˜Ñ !Ô !ð؈rØ €FÝ” ˜7Ñ#Ô#ððˆð Ø �MŠM�#˜d™)œ)Ñ $Ô $Ð $Ð $øÝð ð ð Ø ˆHð øøøå �‰=Œ=ÐsÁ"A*Á* A7Á6A7có8—tt¦«¦«S)a‘Return list of LVE IDs (UIDs) that have domain isolation configured. Scans the id_registry directory for per-user registry files. Users only appear here after ``lvdctl set`` or ``lvdctl apply`` has been called at least once for one of their domains. Returns a fresh list each call, as before, so existing callers may mutate the result without disturbing the cache behind it. )r“r"r;r"r Úfind_all_lve_ids_with_configr$Ks€õ Õ!Ñ#Ô#Ñ $Ô $Ð$r"có8—t ¦«dS)zHDrop the cached isolated-uid list after a domain is enabled or disabled.N)r"rîr;r"r Úinvalidate_isolated_ids_cacher&Xs€å×!Ò!Ñ#Ô#Ð#Ð#Ð#r"có6—t |¦«S)z2Load the domain isolation config for a given user.)rlrŸrÇs r Ú load_configr(]s€å �>Š>˜&Ñ !Ô !Ð!r"có’— t|¦«dS#t$r%}td|›d�tj¬¦«|‚d}~wwxYw)z8Resolve domain name to document root path via panel API.rz&failed to resolve docroot for domain 'ú'r%N)Ú cpapi_docrootÚ Exceptionrrr¸)rˆr‰s r Úresolve_docrootr-bsm€ðDݘ[Ñ)Ô)¨!Ô,Ð,øÝ ðDðDðDÝÐNÀ ÐNÐNÐNÝ%Ô9ð;ñ;ô;Ø@Cð DøøøøðDøøøs‚— A¡ AÁAc ó0— t|¦«}t|¦«pgD]\}}||kr|cSŒnc#tttf$rI}t  d||dtdt|¦«j ¦«¬¦«Yd}~nd}~wwxYwdS)zBReturn domain name whose document root matches *docroot*, or None.z4Cannot resolve domain for docroot: uid=%s docroot=%sTzresolve-domain-for-docrootrN) rýr rr r´r…r†rr+r,)rôr rørˆÚdrr‰s r r‚r‚ksç€ð cÝ Ñ$Ô$ˆÝ +¨HÑ 5Ô 5Ð ;¸ð #ð #‰OˆK˜Ø�WŠ}ˆ}Ø"Ð"Ð"Ð"ðð #øõ •n¥gÐ .ðcðcðcõ � Š ÐHÈ#ÈwØÝ/Ð0LÍdÐSVÉiÌiÔN`ÑaÔað ñ cô cð cð cð cð cð cð cøøøøð cøøøð ˆ4s‚.3±3³BÁ ?BÂB)NN)JÚ__doc__rèÚ functoolsrrµr°rÓÚloggingr¨rÍrr®Ú dataclassesrrÚtypingrrÚsecureiorÚclcommon.clpwdr r Úclcommon.cpapir r r+Úclcommon.cpapi.cpapiexceptionsr rarrÚ exceptionsrrÚ getLoggerr,r…rrr—r¥rºrÒr•rIrrrrr!r3r5r7r`rlrìrïrõrùrýrr¡r§rârér¦rr"r$r&r(r-r‚r;r"r úr;s²ðð @Ð?àÐÐÐØÐÐÐÐÐØ € € € Ø € € € Ø € € € Ø€€€Ø € € € Ø € € € Ø€€€Ø € € € Ø(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ø!Ð!Ð!Ð!Ð!Ð!Ð!Ð!Ø"Ð"Ð"Ð"Ð"Ð"ð2Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ø@Ð@Ð@Ð@Ð@Ð@Ð@Ð@Ø9Ð9Ð9Ð9Ð9Ð9à%Ð%Ð%Ð%Ð%Ð%ØÐÐÐÐÐØ+Ð+Ð+Ð+Ð+Ð+Ð+Ð+à€gÔ˜Ñ!Ô!€à€Ø €ØÐð€ ØÐØÐØ€ àC€ ð€ Ø € ð € Ø € ð"ð"ð"ðððð: *ð *ð *ð ð0Bð0Bð0Bð0Bð0Bñ0Bô0Bñ „ð0Bðf ð ð ð ð ð ñ ô ñ „ð ð< ðnIðnIðnIðnIðnIñnIônIñ „ðnIðbð ð ñ„ð ððððBðBðBð@ð@ð@ðCðCðCð ð ð ð ðBðBðBð ðððððð$ ÔððñÔðð$ð˜5ðððñ„ðð( %ð %ð %ð$ð$ð$ð "ð"ð"ð DðDðDðððððr"