From b5509536a4b04bfdc7f3c5b61b81e23c4ddfd2ca Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 23 Jul 2025 16:46:03 +0800 Subject: [PATCH] bugfix --- dapi/dapi.py | 234 +++++++++++++++++++++++++++++++------------ dapi/init.py | 13 ++- models/upapikey.xlsx | Bin 16789 -> 0 bytes models/upapp.xlsx | Bin 16581 -> 0 bytes 4 files changed, 176 insertions(+), 71 deletions(-) delete mode 100644 models/upapikey.xlsx delete mode 100644 models/upapp.xlsx diff --git a/dapi/dapi.py b/dapi/dapi.py index c217438..9665154 100644 --- a/dapi/dapi.py +++ b/dapi/dapi.py @@ -1,81 +1,183 @@ - -from time import time -from appPublic.aes import aes_encrypt_ecb, aes_decrypt_ecb +from traceback import format_exc +from appPublic.log import debug, exception, info from appPublic.timeUtils import curDateString +from uniqueID import getID +from time import time +from ahserver.serverenv import ServerEnv +from ahserver.auth_api import get_session_userinfo, user_login from sqlor.dbpools import DBPools -from ahserver.serverenv import get_serverenv -from ahserver.auth_api import get_session_userinfo +form rbac.check_perm improt create_org, create_user + +from appPublic.aes import aes_encrypt_ecb, aes_decrypt_ecb + +return_messages = { + -9: '用户同步:未知未知错误', + -4: '用户同步:添加用户apikey失败', + -3: '用户同步:添加用户失败', + -2: '用户同步:添加机构失败', + -1: '用户同步:用户已同步' +} def get_dbname(): - f = get_serverenv('get_module_dbname') - if f: - return f('dapi') + dbname = get_serverenv('get_module_dbname')('dapi') + return dbname + +async def get_secretkey(sor, appid): + recs = await sor.R('downapp', {'id':appid}) + if len(recs) < 1: + return None + secretkey = recs[0].secretkey + f = get_serverenv('password_decode') + return f(secret_key).encode('utf-8') + +async def get_apikey_user(sor, apikey): + f = get_serverenv('password_encode') + apikey = f(apikey) + sql = """select u.* from downapikey a, users u +where a.userid = b.id + and apikey=${apikey}$ + and expired_date > ${today}$""" + + recs = await sor.sqlExe(sql, {"apikey":apikey, 'today': curDateString()}) + if len(recs) < 1: + return None + return recs[0] + +async def bearer_auth(auth): + if not auth.startswith('Bearer '): + return None + apikey = auth[7:] + + if apikey is None: + return None + db = DBPools() + dbname = get_dbname() + async with db.sqlorContext(dbname) as sor: + user = await get_apikey_user(sor, apikey) + await user_login(user.id, username=user.username, userorgid=user.orgid) + return user.id return None -def build_manisdata(appid, apikey, secretkey): - """ - this appid is isusses by upapp we connect to, - secretkey is with the appid, is s fixed key from upapp - apikey is user's apikey assigned by upapp when the users is synchronous to upapp - """ - t = time() - txt = f'{t}:{apikey} - cyber = aes_encrypt_ecb(secretkey, txt) - return f'Manis {appid}-:-{cyber}' +async def deerer_auth(auth): + if not auth.startswith('Deerer '): + return None + deer_data = auth[7:] + appid, cyber = bear_data.split('-:-') + db = DBPools() + dbname = get_dbname() + async with db.sqlorContext(dbname) as sor: + secretkey = await get_secretkey(sor, appid) + txt = aes_decrypt_ecb(secretkey, cyber) + t, apikey = txt.split(':') + user = await get_apikey_user(apikey) + await user_login(user.id, username=user.username, userorgid=user.orgid) + return user.id -def build_dearerdata(apikey): - return f'Dearer {apikey}' - -async def get_apikeys(sor, appid, orgid, userid): - ns = { - 'appid':appid, - 'orgid':orgid, - 'userid':userid, - 'today':curDateString() + return None + +def return_error(code): + return { + 'status':'error', + 'errcode': code, + 'errmsg': return_messages.get(code, '未定义信息') } - sql = """select a.myid, b.apikey, b.secretkey from upapp a, upapikey b -where a.upappid = ${appid}$ - and b.userid = ${userid}$ - and b.orgid = ${orgid}$ - and b.expired_date > ${today}$ - and b.enabled_date <= ${today}$""" - recs = await sor.sqlExe(sql, ns) - if len(recs) > 0: - r = recs[0] - return r - return r -async def sync_users(request, upappid, orgid): - db = DBPools() - dbname = get_dbname() - async with db.sqlorContext(dbname) as sor: - upapp = await get_upapp(sor, upappid) +def return_success(data): + return { + 'status':'success', + 'data':data + } -async def dearer_header(request, appid): - db = DBPools() - dbname = get_dbname() - async with db.sqlorContext(dbname) as sor: - u = await get_session_userinfo(request) - r = await get_apikeys(sor, appid, u.userorgid, u.userid) - if r is None: - return None - dearer = build_dearerdata(r.apikey) - return { - "Authorization": dearer - } - return {} +async def get_orgid_by_dorgid(sor, dappid, dorgid): + d = { + 'dappid':dappid, + 'dorgid':dorgid + } + recs = await sor.R('downapikey', d) + if len(recs) < 1: + return None + return recs[0].orgid + +async def check_duserid_exists(sor, dappid, dorgid, duserid): + d = { + 'dappid': dappid, + 'duserid': duserid, + 'dorgid': dorgid + } + recs = await sor.R('kwdownapikey', d) + if len(recs): + return True + return False + +async def add_organzation(sor, dappid, org): + id = getID() + org['id'] = id + await create_org(sor, org) + return id + +async def add_user(sor, user): + id = getID() + user['id'] = id + await create_user(sor, user, roles=user['roles'] + return id -async def manis_header(request, appid): +async def add_apikey(sor, dappid, dorgid, duserid, orgid, userid): + apikey = getID() + d = { + 'id': getID, + 'dappid': dappid, + 'dorgid': dorgid, + 'duserid': duserid, + 'orgid': orgid, + 'userid': userid, + 'apikey': id, + 'enabled': '1', + 'created_at': curDateString(), + 'expires_at': '9999-12-31' + } + await sor.C('downapikey', d) + return apikey + +async def sync_user(request, params_kw, *args, **kw): + dappid = params_kw.dappid db = DBPools() dbname = get_dbname() + userinfo = await get_session_userinfo(request) async with db.sqlorContext(dbname) as sor: - u = await get_session_userinfo(request) - r = await get_apikeys(sor, appid, u.userorgid, u.userid) - if r is None: - return None - manis = build_manisdata(r.myid, r.apikey, r.secretkey) - return { - "Authorization": manis - } - return {} + ret_users = [] + roles = [{ + 'orgtypeid': 'customer', + 'roles': [ 'customer', 'syncuser' ] + }] + for o in params_kw.organizations: + for u in o['users']: + dorgid = o['id'] + duserid = u['id'] + orgid = await get_orgid_by_dorgid(sor, dappid, dorgid) + if orgid is None: + if o.get('parentid') is None: + o['parentid'] = userinfo.userorgid + else: + nparentid = await get_orgid_by_dorgid(sor, dappid, o.get('parentid')) + o['parentid'] = nparentid + orgid = await add_organzation(sor, dappid, o) + if orgid is None: + return return_error(-2) + u['orgid'] = o['id'] + u['roles'] = roles + exists = check_duserid_exists(sor, dappid, dorgid, duserid) + if exists: + return return_error(-1) + userid = await add_user(sor, u) + if userid is None: + return return_error(-3) + apikey = await add_apikey(sor, dappid, orgid, userid, u) + if apikey is None: + return return_error(-4) + ret_users.append({ + 'id': u['id'], + 'apikey': apikey + }) + return return_success(ret_users) + return return_error(-9) diff --git a/dapi/init.py b/dapi/init.py index 98f71f3..140678b 100644 --- a/dapi/init.py +++ b/dapi/init.py @@ -1,7 +1,10 @@ -from daap.dapi import dearer_header, manis_header +from dapi.dapi import sync_user, bearer_auth, deerer_auth from ahserver.serverenv import ServerEnv +from rbac.check_perm import register_auth_method + +def load_kyapikeyserver(): + env = ServerEnv() + env.sync_user = sysnc_user + register_auth_method('Bearer', bearer_auth) + register_auth_method('Deerer', deerer_auth) -def load_dapi(): - env = ServerEnv - env.dearer_header = dearer_header - env.manis_header = manis_header diff --git a/models/upapikey.xlsx b/models/upapikey.xlsx deleted file mode 100644 index 225cc93a199ed8f8c4ac59eb31361e657689033a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16789 zcmeHuWmFtp)-~?#E&&qUficogKzs-@b>^-Eg*2KE|tDu-LJPydqUO>KtgHwMY^B%~dEKR#BoMx>>Isu9mTylAt=dB39ulf6+N#5c2;Cy zOUf}GB{c_$e&Fk#+2iEFI`*fA0U!f&UkK?O%R+S*(-< zC<9W^x!)V{XglW$<-2K1I-x@;!xvzNlowsrl<2&cmpfrT$Lt0I_q0lv47Ze992_xXKl)-+>NO|ZvOzY#|)A=6CQ!w=fPksV{|8yAJ*bO6oazHfVIV_}u5G#hcZ z8OkT2iY^cwk5;>nUgAH#X3kO0&L{1v@)|x08Gd?a07~#d{U!78++s>zUYIN}6*PVS z;X506U0a@z1FH9Gim>MaeH$ZUp{h0AP|h7g^(TXIl?hgq@%5U=zjYY|bi*MGfXjG* z0|DUxK>@p3(*470Tx{$u^lfY`e$IaX@*rTq6bQKXfA`iFFJ<0Cj}&+pxXx#)GvbWG zN)uBH9cZa>2h>gQhNQumDyFf~(VZUw%D0AP1NPB>{fWu1amCw-<_Rb)Vk%aIZxH)% z6)mEI)O$jkpdpQzLaS)rG};qr_vz-<`VOZ2oeT6yfyllhlejkO?F7HBwm>00{U=ja ziilIR=4s^|l?O2;qHTJ~fOPYV8}T@N*rC&E+t;N@&V#plDK!>$JV~!J-WhmUU#7Y< zU}}X1kl5!!1UwSV##0rCWp5mhZX6$4FmD>P9m73;w=~qCRl+WCL+U z8ci%;0tDgj5I{hP0CNFY)nDx?Pf5$>D?Qrh%(^$9XKDC=Xov(wD}_4I6*Q|C*D^d? zKPB9cE4ufJ1sLlLX6mv(W7U(dkiZe{)xjBJkkHOIU6&dn;;3Vfj zPQ>M6PyFOb*bunry8Wt9tdR9@3EYr`Xrlws9VX+m<+u(B#)m5(r_49|U01wSn$ zd=--e?hUsyW`QTS7sQak$X7J%C;nc);W7_X0rlDeDKJ?9RuGpDHWEK;Z#@o#V>Xd7*8mM~ZW#N{ zjUJU&u;QG|JIj1Fd$y^47L%ZTXq<0~6^E}vgzP016&C$n$4}a}krzdA*NR`JSP_g9>hyl@?-n#ZAYJ^KluWTFMAIH4w4Y zve<_IQb{#e%_`bF7hH?W2Dt_rFY968e2ifb%@KYIS&_*DWTK(pdNi)h5Fd#A0)oxp z7O1mSCs^Xx8U=2|i8}AWGOtO)Se+PK2uDL$k=WVFJ;K^S_!S<9!2x`G=`})Rds0Ac zn^_U04lmvsX8R7^W|NPC9wOrBTnB`=EjW`AUl-TSHJ%@|i?+Nu55pkGS2^4cX0XF`hUa+WB*me!@f(L*XVEy(22U8;>M+drJZ%jYKYg*ip z^$I;;P6B^K06S-_XNx3LMQ8&b%O_8zH3`L03lNhdJ0hcbJi{NVNBM?H;sXX3yv_P% z>orCotsVoa`avpg#uQB+B!WKQvVr~O^^_r5ew)iiyh0L`{WGu#;XWbHXk`DHCj2He z3Qp3@@)L`}=ocI&7m^u%f6j#JR1eK%8i#Ul?H|E)`gT~-$@?|gCj7=WddVfRAoIfC znVDYUsF^_z;~Gq>2(+P6?0y&+D$ zIN*7$q_H10qeq#hpEIeum2mQA=n=Z-T+ykwjZjGME*aO#3bzcKA0!TH<+lS`D?$P( z3&Y4)!YRH^xW7F|+dA6lZ@XQ>!302-A;O#4I=}0sbV}Xr2ZVyEh`3% zzCraihsWc)I!{omrStadVgK4$#%jRy5FrUQqOAJ3;fBFTO$UlX-IUVEO`ob%lcw0c z?%GE?mYjo~CFs-!K<=vXBAIyN~|0B?q) zU`mN&n2Kaq&l{Ek1r~-f*o;L#oro4efg*H`g9;*e>4pS_F^24xA%e1ZAoZ6Yz%(ia z(@l@mcUc<1?t?D4%Cy#GPwX0K`hl?My4$eG)kA~0_0A*gP4#0yIhXbEyI$JbLQwW6 z@r{?9kA zW=$lfSUvvjbdkq87{?C^1Y`yMUmb<{UycI!wn66!j|hq9n_!3hg1j_JbL%A~BTHoc`l>sA5sCF;6QQzo9pHqchgYCd1afvbq0HzT;18%wFgzsOn2 zLq8!KVxG~&X(2N_LkpsjpxEpR&4)m3K!OZ~9Nkc<`N5frQMk$E5@xi9th^ACEJoJj z0-7%v_TA08Z0BR3lg%_Rrr}Q2-Nn&)H`8mbs5*>EJBL04I#97d=CGjIi2%EG%Nc=N~7 zY+>A(G9!Xz&R2unEld&P)t=cB8MOcyI@t9D5b+L0y>q;V4wY6f5cWzCFYN1Az;k;0 zhXpytZ-oLLM}Usd6$rCcJ*C;!56_r)-7oUheI73>gE4lAW1Sp?DdC)J1$zhXS`*hC zGDmK2Yg_|JJ;rXMjY65ypOdG_!gNY13{-FKEJC%+wH3^1-(;bFz;!~OVP!y{!CEp& zK+m@LDhg$FfxT;D_JtylB=QsCkv)KruLm<9OXsIgouTrmu)6#Vw{@Ohpsz8fv7b)@+9C*;iD|BhDzr6YVhi zrlWIPnXeKDE|y+(S8Oiko`2sSrbs@RZdo|NN)&q_s*sS$jR-1Cze!Y2t7XDj(mc7T z8I8WP{ju$_S!G4?dr!whCH)ODP2%1W^6W$DJwEOl7-cCdw=97lzD5C5w=uTOi$rXQ zM&sE(EEb?XL`<$o2HK0f=8J8V_QQGGNZ7GfS?RLiEe;2$Al&zI zp%4lxz*ymuAL6<`Hoe~KIn`MoSorWpPu}~@6W6gDXwT~gWG-XiXcm`!e79M+!nnbK zWb}bCHD8R;M7Ss@1G>32Sg%xE?A~&3ofmZ+2~r(wwX;&`1Tr<|ZZq7r^)qM8d|k*Q zd3m=6WPb19v(bv`2Ns+i?n_Bgd;9ym`*8@?wdaTrxp}qg%6g%O&g<7!_Yw_;{E>Mp z_vhUg;p}Wh$=_fpKW`-7_Y8{DRV{JqT_a;ejqG_SVcf_}H$tluv>L`5R=1jaAGs@0 zj@pKYvK7HRemT%_6<>0nL!XoZ7x89(UroR|f41EX`zVIA#pfTMzz3EJ%H=yB(_3BO zeWyqeV`-=z1^Mcr(zAiL1cfN0{3dTybXl{hMUjo-flnJZVt3a1$qT%`9P~9s=)<%* zslH5js0+M=WEzJDo{s|eM6BB*@0Zml-LcK$q|CtN6zLFWB;%PrYANGq9&t&5LP1XQ z2QAuK?T`jcvRnNq!$Zo(y=G}J#X|BP$Hv1lSPavFO zscgEoUW3fA3O=or$?*Ht3Z2@0BcvmM~}yt4e+S zlx#0pjA9oMuyCu<0x`;-P+=YTe5OeD6z z3?yr7!RzG2ef$j1NK?}=lHKxVAIkxEH(gi$rUyQzD2n8rnLrYp33lRUH`rj;-H@Pt zcfc9BpJxP6X+)Sz+4=1qK+|!dp;ubCqv15c0iVS4WuF1u!8B(t#J7QsfB9Zf6^BQE zlVVeOOnX*c|DyZp13d(tu0G?(#QS(C>o>_Rrn0MIpz=C9;qDF`JlZcqYo>FF_q|Zo zSBn+_*+Gpux^UWWy}QOUL^2J#v9;pIYFotpZ*Bg zE~?(V1OK6$$r;M^by6g)CJ&`B_dOrW>i!Oyl6(;)c-*4lN~Lh&9%8ykc0=!u@vxci zwK@fqxw$^uD^yeheBr`{@&K9RCI!|t(lN-;|cKt3u&@6;p!fqf_Z%b#@^Q|4$RG^=&i(s%& zAJpktb=Wdj9vK*p#4gf^EzrfFAC+_~MkFCRmt^wmG_7foq~~waxNy+p=1(Hr9ZDxFffZ?Y9?QLIH>hvS zfM7sW&8)+UYpd7R&zSdBLF3;X56|k|PncnC4s~>D+)A@MFtq*cUv9~sbtl2;)Lr3+ zFX4k_)GgLp0vEFIHZ;2%OElWuN4hO!CB-<@_*HPnZqM}V!3{?bBT?6_XCce$o3Bv7 zmt+l-QuRmWn<*Di9K$YwfzYDgiOI{1Gja(7=hd#+kjPQbF`0sr?0n`%3&|&D z&iw!)&A4>QGmK;zE`Jg>z|-dXJn3FumH~8`6lZ?}UetZ57@UD1H8h&Pb?|XVIL+oBb`I?-OGCPgKWJc+Pf|f6wFaU- zcS0}2wRM{6x6l2DEIZPW-%Fa|5D^Q_b~Dmsq*j>&5VRaz7R-+J@#Au2)0%N6xL0_FkQEL$je;Qn!EYT@mg*iY3NY`=SVQ8V$D1=ztBC-QZd4 z-LqmmTYpTzT^CbDjO2vH(>rUwL&lUqZdZ(#6Of9qA;9R2?MA=j`{e`{Iwq3dNSmjZ zzsaz|R<#oOMk@=^W%2Hax;jQP_KU;;f&QrAkHtLPTvCT+$?3&jFY@=%IfJdkd9WQ5 z-|=%Yh!M!Ou+MP8G`6_Yp(;QfQr{;)=d4RMlO!h5*WT@fM9|Ab?_@w*?RRyTN9YMp$yWh*34OFxZw=?@pcE-Zcdl^i7rVIj#?|D>GpwB z&Fz^0RUC0QeEUljR;hW;GMtZ6{@Oioq#y!Mrtil`NrlhggP@)(ykbC9;(s zGomhSu%PkZOR@AMjd82b=yU3^0?41^kll?;^o3UR`rPupkV}NnU{!p~gcLUecDtHO zc36+ySP`vIbJ!H^hH;;S9F=UxnWjtA#Kz!?y4U)-K!-&e6UwQQ3YC)zmn8(38M{SU zSD;AX4bZmToKqJFO|Va#vE@g&_Cout$;V97y-}-`N$ve`P0bm>rP^~NH#BX&p{w}R zMDhfk;d{Nu-i?&~pdm=o1PV(!!TNkcFVP?Pof!E5VIeQBmXDuwpMXqkKxKrk#YwU5@w4#q=&>t zu<#kj56z;^eAt&5*|tw%q#YZjDS0(OgB9{h)n%G!)X{Z$%Ys?k`Ts*sWtYf4A+I~!Fc47rh#v=*lo zBJm0fx+VmaIW;or;ubnNB)FO3A?lguoX<8mw|2EakY2A#y z2FwuQ|9y$~@o!Si6|vm@&|39;btgKdIqQ{=T{~FdT!38D>SwO0%}KR~QXcq#wdrP} ztGbq6t|wxvZJ==Bm}(0V(Jjx~>i6dAp6t0h3b_$_dIB&~sh< zsO}-4B%lxH7Hf~b#&a}mRBNx3(rC+xNE%j-u4h?kY6(1NIF9xf&RjHC+fEy{t0IAeV)C!T&LmQdxiNFQ zC<@l)v)`W?IeOAhw zy>*}v@8LX+FDFLtpg2zVV@ppQ5Dnt0xa-{@h4H^u)L9~6g9rhIyG zy)M9Mh#Al2b2pimtA3GQH2}3D0pyKPReAU#a{wvBQ7Zo^pSUpMS*;3wSwimr(8Gan zWmOH=V23?1%tdFs@>NCrQ5ZMrW{NAn{?4j9xzv2hmeowrsLS^z4h9E8zC@gULA@=o zH1HzAc!oY)Z4{>hZj5D-bjfbwyjl4$W-$ha!(Z2RYlctMVTe7avUk$^!R{`uSDjr3 zdI1L^aDSg6ADOHosHfbF)B8i3z}OpUWjXkhOHHF#;l+@4_YBOWOw@ZgelR@e1DnbZ zlF$uDOi@TJVus3H(kU-drO)Q6S!&jc(Za#8ZKY0~<iQqp+(G;gn?M^!bbz zMCb9h3F9i+B|;S7j0^%05ZXTyMh8yM|(4C6NjHcB2Q(+dWIKmjpPzB2D6M@ znwP(hR8J223qGtWaR7uzY`A$;#3x~zQYiA!tY}*DV(~1Z>>$<CHVbF@Hj z+>oC+dLVPc@=kFCTbdW!^SszE5th6ed2@)3(Mz2Q^Rql{4WkeX?QxmrZ0>|zII^)A z-vSBCm2s>pD1#-t(ii>y1T1RF(lQo4a)}%%%c5?kDr!fqMEz|T80s&5wwAaG`yZA* z?~@5^=AgBHDdU~S14j105{pF^kc=UXkLIAfs7IE@FRiH+3eHx&CsF4$p zx2_>Y)EI7i$4)lXmAW$|M6&5TyCmjFDxTv5k(3%BszQTa#+ZMhP=dx#xW}F7(Rz%m z5a`cPx3URKIa0de;o#|)~0fx@QH4rC%@Gn8Hk|zL7UnV z*xdUJ!MmmBd~7&PLO|1k)wAujd>vxn=GLUmF6!RX=4dFEGoV&njzCWnF}Pvyniv(H*OQw6}=D<%{(zi&|ff! zOzjz^;(OQ2#qB&@OA-H=bZ6`E!9hHgSe>$vhgwZj`}*4ruN=kH@+Z?%(yf3J8bT_( zPI)ZcPWQIxi4W(!k~x>s9Il<%>#up_pf=-yD>_-MeLP5SkVB}r77i8{=8XE9H}>ek zHL&m7oR)R{#BrS7<8yerGryc4NZl5|l_`&N_RL7S>9Q$mlK~Md=1w{vBQ0-!A~gQW z*!*pPhgDM?VmFoouak)an?3?BvRzC}@0$!x(3nM!)K}%fIti}tCWgqTpDv%R8*08q zqD3Gsu}vz@cZc*LWa{i(<41oikwE;&*LE52a`&n#NO97mvK|^J?3^*xL14V^^#Uf% zQyUVi(Mfn1&oy;uyo#@;@P*WHFGS8JMR;OJ&)^viQcRV1QTSdcm}5519G z7moFYsIU|LUE3i*^7wq#K-#BKj8M0F@{0n~avIm&N23nQ4>TWbaI$!E1wK)ql2p6w zSb9_m$@iq#?BkAy%wVFM%)`rpC%ofZPYI)bC!Zo$Ej<~vAi>G6oLxOgALmDEDgtw( z|Kr7FhW{L^c^N5(MwU1f%&Kl(8m~~4HDG63()x=JYqKJrMRG~Kf+c#FnjVYY{(S|f zGg|=&GtPUiPr}dx$6C$x3PX*mGw4Q&=jK|2+ef=|>Y{-va9PUQJ_@B*{lkrvbJ)cy z=Sy2mN;T2V+@S4|qYkODPqqdhoNbpaK*nTdb^{|%Hm=&`WoFUXLRV!42vemTC>-_j zYtT6OcAWKCXx24YlY!d_?2Ts>8H=gmsrjOh(S6y?NV#7go;JKc7v;04qVrnU+My-a zr!FhUDnQk#IfhU5JK9jN*bvBnHIQDam^$W>J}{U>91G7FN=IFED+&7$wF|yaB~<-o z^;5rk_lXGbIfcPf8m!cKSGOfhumUPsB7ODp<*hX=_J^!UCO3r<{Ag{ew(IAMd-y;@ zrjO+Fm_1yC#1aY)l&iJZY>@&JoGv1ANL`itR&${WF)^Wrw(iH_E)dqqiaZckCP=-X z{E(1(bIA#w>~@>^6kG33k<&7f`0!zLy~&gy)^bbPxdl7aQl+qmn0KRcP9ogQn*-kx zW^pLLTc*mjC4ziZ;A_F}NuPAe>LL}j$>MVqf=yCyU>;#O);NVUvVda_@XrCN6>yVn zu-n(uQ75a z7B%0@yu=+wVLE=BGT0R1lzBcl2wotn(NgJwga|KtLqz#J1(K$I&SvX0@le%(s!O+qN7Kdgtz^e=(2M)L`%Q@Y9KGbViY5QpNG0=p zx;ZAa12Pp7{D~JjIOo$Lej~>~N4Lg4Dkonix7YJQ)CL4srTFlsL*WqDjNTn5uZi;Q z=Rsyd<>l3+V}$xf5V5!zyd+7TbDj4^gm1iz>h_`+%EvVAF)hk5Szgb}bzU}>meJy! zv{^bmGnD93lXOYf*RFQWH>ZQ?BF^;hvhjnj1Mwj+ulw||TRS{1Pd4X&pu03Y#zI?7 zz`h6f|C(-|Zq=o8YXOZTiF1Ej_~9FYe$-3#6XT7h2fO_zPOP25$o||(?VyZKEXeB- zTWo}?V41d+=Ewu)MnO>SG}B?|+?<^f1JfoL(ykj=X*PURX>b3`7udg3O*yR?CAt7{ zgC8Ijk^Ccm{Hz`Lr)v6-;*?(pj6YL>U!^GlQC$Eb0!`=+^i{ysBW^wrPC$Y6U6axQ zsQ%+J#7a{19omaWEuPW0y*=BBJ(jOeT*bJ?2r<;NEg*rr2AHN*7aq$roqW}7$E#@2 zG+fboGqfG4pwiOfUk0L8(P66tJ>-9-<$n=pX>l7i09t-v6@(ev;NY=Vp)jmzzwvSvYKTqVIfS+PnZzz zPv%D(5nSgu&HApG(iz6`vmyDnX!RCb5<$+&4w;f|eb{8Vbe}t7$_Y)?HT`B*ty-Ml zm02TK$BG9X{M3#6dX`lORA8>xO%!Mc*SEgzxG)di{P;*l6Ii=GPt3>2+3T6{nl^@w zNpi&X7Dm4m&%QY9>hnSIwIRCZBqkwKSH&h^Ojvc5R>iS~@@V7cUb1RJKQ1Fx?<|lO zGocqXQVki>NsPy+PfL2qerjPNHy|BA%6pg1@qk5%Buvo%xO}sq=5?y;&(TtA{c?tg zB^k;=fEJ?49bnKHs3F_*e9b)na;}XXOgsgc!)t6?5G&Rs-w6Af$4I7S$_rXF-}vm70H z*tQ{VBAd?rcY=32Y0HwH0T240i>DfjaZxE6J27gpx>|~1Iu-I7B}PSga$3<*Du|jg z$@uSEalxpwTho;fSq*UXxIN^)H&d5G~WO}+q1_qefzdkx#ZbiC>9_}Rp>2f*0b;i8B zuAYe4w-@z1TVf%El=jO=DAHTx5eqGf=x$e}OxaG_j?#*cLQyH_gt@J2``CT*M^7`Q zetfjej08j+Jj{oZ1WqTa7wOh-;Ux?^m!?B03$6Q(BBqdz<4d4KexH;gVm0=7N+=4& zdcx;J>ZfawZEyTztOe{VdD*iOKW|4+|%c?{np1hD0b zfW^;$sTlbc_0r;OY?kSf`Zr{jU8Isy%7?gg0`K$!J$?D5R@kex=11ov5-K zs8)9}YC^qBr{)Lc1n`&in*}hEC<#U}S54^(9>->K^bFgyUz%Lx1ffYh4Q9G`2i4+3 zT-tNZJV2!;K=0&3jk+Vu1$OGhm1?bVM%|NHl=O4rGL4?%7SweO@|e88ha8`}=V_g0 z80fYv^Grq5;&K#z+Z_~lZEAcBrWA-Us!l?ote)FyV#mGXURfh4a>BnDqQ;0(CP7xw zS9})8LG0_ua>Z#SNS1NSAaiq<`m*|{J0@G4L>Qn(*UJX=aI+EHmZXbEdgM*Y+77lu zG(>A2l}pmnr9UlU!|*9H#K~rt?zew>#%oyrqu8Vx`1nIpcOs1Sw3Vt{o>#q+W&X;! z57kFFf!Ek(Oot%1(!CKC>4nPcqeBS*ObapO|fQ+dJos>5lNw*9lQ3;xo&iOEqYlr=n- z)>Dp_wn+*781ujmol&t*Ly5u5*TWBTbWkse37tKL=DGBE6_2&sFw5Ly7VE zfCY%hC>P7;e|Gr>R=Rop-C#)h);m)mwj`aUo^T)0rK2!zqy0ca2{AU;l%Q_Lx7X?` zawglo!ezK<5%25fGE{WHezCrX*Tjvs=nh<4Pq=Fsvt8Zd-2$gy>Qo3DCvU)|`fXah zW@bsW>icgNc5ZhuJ9&70XbVx>Nn}x9K-F!(z|njbMl+q2%-WL(NSC+Kcw<82*;es) zaDGq2c%`XyTN08}k6Sr1taWB>(6|^+<$|hWr;09wZGEO4;(!Nf7Mt5SDjHRUA}%#^ z9h1^Wjsp+Dp~*xqf5@E%ko~b`H^*NZv;ZGOu!OrQx-vzd#tS>xJS7J`n;Lp z2ck}wy2YeTSFUtHT=T^GUK0ys;bwD&H;m2rh>#nkdm6;P24R2R2(D@1s&_MmjbASW zkLXeOilLSJf@O!r`d-30nGzQ5LB~hOv(Gk18%&?D z+IA{s!!;GhG9{7Riuj~T&)K_6wLHpHGR0bt4rwZx1iUE$Ni9_(nUnd&=je;J1s*%$|mGbC57wZ5*vGCSoM0u`#0C zV!z7ZPs79)*$VqUsTI%TuuhW0`-{1I zr_!siMTUe-?#luYl2PoV9=`j_4Zhl4tWYIg=-AUgPmdEKmPR;P{P3^TRpdiJe?F{f zIAM$>ZlO|-kFDeD)2ikp{Sd%Xw}y$>Dg*W1D1|@E16{`3(=GHn{q^LiJx*k|kUR9A z;fALzGa0s!S!yrg`-dR;pi1nXPIU92%FNQvUxD^dG6Q3TD7^__H_?FU8tJdLqi1XT ze})6NW&hmL;<^AOtZ+f+pg$0T&LUQ=p@Mjo8R~G|RjYx-JPr&wFy2c94Pp&t7$xCD ze1~^lUMc%VU{DiLFrGSNP3j%`C@6nyztB|HBg%5mpEhA1lg*l4=cN$Rdizw%`i=xb z#}AeOwps)w>2VLXK0Lc`5Q9R3j0-)-*cwwlwzwKNm2BxlK1?;RwDszstkV3Z6a5Or zr;#wOOo>&7N0gD;AF{IH=$QC#HdBnr8Bu2oPb|O|w+&Y5%-@a@9_LfB$Q9Gp{HilR z=ayR2`3iTLq{zn6Q?2US7Mf!fRLbGl+Qd~3VeqnJWq_UhCmU^`Sz?v(={T71^o4&& zm~RFSas%rjDu*ECfKNbI$>64UIn&t9BJy;;z24qVG!lxx{~Qj#&*Wsjvf$25O1i^V zO-FA}x|M8ewM6{6ED`Ae?7|a)(P3PGQir+07c8lf3bEs%6vU>`!b=bQP8M>$29= zZK^XqwJXheN$yx>pUqG*42QNRz#EK&KWF0HOr7?0ESq)VL|4-w&=I_P-D>-&4fxO4D2a0775F92Nf2f#akN45nh zK#oTC3Pz5OKc%2Qj~Qt7&8)x2tib@wp#^s4QtZxyx`Gh%L~u@NhQ)^!i#>>8_sBNg z;AD)oR*lDBIgm8RIxL%<*4}ZK)-L=AS^Q`s;Y)xj9PZTL;&il0hDFt>7#P7rw}W*c zxeiS`P)9sMp)wZEkcV9$&+ow>c04jN0h%~P8@4~5fxW_XiCrb;)e+-OWJqIKJ$+WR zQa-A35JNBdn09owRy>`=185yZuTCbYWldNX8^02|BCuGWnk$rqS83%J^HMuRfx=}> zYI){;Ymyp~CQ(EblA<%b6moh~^al4*@um77hXn?q0SIG%-@E+VLjUpK-*hs|O8h&( zzxPc36<`Q3=l!LF^3Q?)-Z}QyfzN<6?7#Ps{fYBuuh4HKc>p{1N9WL=ga2%?_&rz^ z?tcdVN5jRRD1X+U|3>iz$lCw>3V%iURgL~9%AeJ=zfm4g{ubp|ZS9{Ze-_OBM$yFl zh4N?l+@An{R$BZ9FvS1cukowy;!l)6W!T>+5yZbx{zH`g6X8!C=r@8i**_5eM-}>W z=${nu@1c>b zKFt`r*`xQGy?gDNwQAL@l9L1lLj{5Wf&u~pA_Oui6aO3y3$}5rh zs)HHK#J6NNxQracY-SapnVA&CK+JAfq$&nfJ7QyRtdALZv8_|jHQg@ zZ|w(}cg|pWgsv(+c*@;t+qsGOv?CwJMypo|v@}sP<5`9ltXH}2wshmqXL&25=d{62 ziuG+sILD%d`g>#c8o7~iyS=9P(*p>$>|aZfbzd4W#D=lXCeD%gU-iBz0X++(S8sQM zKlQ8?_~pHFut#xgfjFFYImb85el;e5GSI=@NfWRg9mq31trz5aWZwI>(u*_5;yzuW z!x}xzzSo}xu))_?P$0Q~BQnb8c0&*Vk=Fq{g#{2<+s@F!o{sj{@qY>Y|1fL+_S4H^ zr6oZbkOEJAUkOLrxRxo2rYz`$_oNM;ff-Vsb=Xp(^P8VhavtE1WZ3Q?8Aw z^IYUNc2dZs#mq^MscD$n~cs zef7q06jkZ<{n+%$lwB>s4nyNg0wPOLn{W6=%48nVZK{Nnm z+`)l>uz;X|T`cJSVvV!4ow=U1wfV2r?|&Es3|ImI*Z#l#YK@mR>!wEvxD8n2H_;w; zLT00hseul#(7Xle!h1#1WK0#;TyO6xhydkZ#jplr@>_dk_H9`9a-?|#3X7PG73Ckm z+*?77_(tM2{u!@6osdGSc+Mo+1L)`D)r-|FOgWJ=^kJdsjuNxPXO!!40iDl+MfCI^ zP1qrvvS}_d7ki1!^8S8 z*PZ}VE7pU=J{2M05TiF7tJ*JlVYzok?ko+GGl|{-rYVjZ z`dL^#iBWYk#xYCUkW*K}!4&c{G{ULVPPxk_u{$+VWZqtjy%XFGy0UVG0(d1QyIW`OM)vkX~l|I;~YerY9Ae#A+GMtYm>w zEyVGAWj_k+r=gZb*`M*`dz-YQehZ|b!u5<+UeF70r$6|D72#WJRxT9XikJ(pVa0=& zF&^*}QFEV2C6QPCgp!mYc4Q$Hv4 zBR=uaSKYH523BEN{SHF#1G=M zCqxQ162k(5CW$8I{5&2f>g(4De92FDU;=AXOFa02h(``HCKhHazPp2WTtDyGGzI2z z>i4Y_Wj<*<$_nQaKU~?d!UZPH7kxfGxVkEwM+Ds?zhXVQ-giN|X|u(6Fs?ufN5~VZ z8Zv6}<=n%7lxriNMy$7@o(ZFjIWcW@X(`=3ffUqtcLZ*kyC%3BI+8psGiBXS5he`b@a(yPqpsH*yIzG!(sh1|JBZOi$hH>S5>UDu z$o5k#NNbhO$MB1&aJjAG_CyowM2Z$uISN8<(>eQ z!F;j9z@_`#_4{0}J8&Fy8_J{29P8S%PTurQi+vYJ+|$k+=RU*5b4T|EXr?m9<$N+- z#uT%kR*pQrIvevQ`5eU}UjN8}W}$wuG5`l;0G<`&4+rc`3=JLZ>3+X4|8lPBagtF0 zG6dWvJm5#)_Ha*0@kPrEFdkTxl#JKu({_g9&p6>t%fGtQ<%?4qqC|jovEFg*+Ej$~ z=f!s7m7$0vk>ClF0F6r1Tosb6cYF*`L}nj%7|oxQi$%BjX?ydcWlQgLr~!mez~2&E zyXMSM5ZREOjGcnO+-@4KJhC-oReVTY>9&whBAsg@@E#>K9jd7 zkDoE>MT?5lxsbvWQHG&q)sc{`M6gFgY*QP892#{zi)~4*J~8XAZuWRclMnB74l_~{^nnDWGFlWMhR!kSz(wM`ynog9im?lD#9 zoEp8oEPN1zlMdUnWsK{Dnsz1eP-%}8uLEqk7tP}|C(Dug^_OrXq8VEPpW9;;dXJ+V zkdUl#hK@%^1w4a&VP}<3{lpxrt$XJ*y$ez*d@1XRi-9F*! zM|J?7;Opz}Lp8;im^6*8IJJ0f4aE?hDtWasqmlwSt=I?^M0J@|!jVNRzi%Xgye26u zX#lcjfnK&rN=8*vgl9@dgeRj?2udL`6Eo?UTD)3z>JMMx5YiH4RVmUP2piG|KI`w# zdj7L?1oF|^SGu&K=r$tgHvGumYS~dx?0_%-pIcxak%sA_N9sK<_2=+@FSNqE+Gt1U z5@14xUwqkRQ0(HaN!W7h9`>rn2wJT?pyqvDc;%aXi5d{S?*%~`$N(}mg!Ge&7=k=sDU(+ z6dRqP1rR9pNRXkBBkQWwH(aS`MH|e{VTP;kROW+|#YwxJK?{V!j$EzEwwMAOt*3y| z4Yn$8&-PEdm|yb5G+>O|Xavy*Ez&M+?*&;6KGo)LJ;-+DgYM{%ZULXjw_PeoRA{JJ zBOYc!w^-?(J2zQSgr&cbyq5dfV+G~MU2WM+c<#F>iE(eLy|Dz$ z>7FT(RriOXgI!Aik!V-aJ;kYSS8eeG;iv%d#Jqd~Jg0xzuS5K1DByAUYYSh1uvpen znr_~B#1M5oD^&HmKQ9l&*d~s4aN?(gbFCI`@49J?UvkRsyS}b+_ak*1xsEglXUTj? zo+1s?F8QXfc6DnWs%7?B(Tw(04(bN31NsCb6Z!{!JrrAeHIJ*;!sFB473Qvl_ zSCm(77eb*9%xpA6fIgKEOcN!T074e!V3n_gDB4sQYDoo3MPsqaxg?a!k_wE$<$=n5 zUPXB!H{rIFBCE1{W6;UQQkkYc18`~X`|6L4^(9?%CoufA0`;Q5u1g*A*D0uOyjImT z#8{rXAe@jepL{kEOSG-8mY!U-9<<|FRyB(_p_E9pMeCi4&TC=0NbEmbe9>99KAU~| zGd;|a{4iZ|a6%Qxc0g3Y!4vBdROr4FC?1we_%kH=@{`k=y(c@PKSpO%l*sQq9QKs; z)=57R_6(Ef?8$8N^HjsANL#vQ3*Pt``cqxU*fcE=up=6d<=mLhLy<*HEK3F0iM|ww zub1}0d09)^vQ=9Ar0FO+r}5>C6N)tD$@v;&9C;dZ@YNF&R-PIEH|5`Mb6+SaE$G33 zfV$xSEALqU;+=HVGQn@&;UnFGZMo$2gw~YQYdKmg&svUyMd_o`(?&-r&%Um8R%M8B zFl!hvVLb74({~@78!&TtUkQe++UVhD*if*WZ)7quwon*a%KxF>%-D%fZI0t)i@^@IuFYAeS z-2)PIm5W@um+#P`hPU07(XM2t8lW}sS`1!R%Iz~3(^FOGb*qFIV`1<)3i8EXwR;_B z5eiXOIp|A@FxiwDiJokDs588zR63_Sj<+Ju zc&zIKU&zX%&gjP1q^yAC6q#TrB%|qGYH6b2(yXTeLH zpq;focO|>K;(ISZ-fa;JG=5nLt!o1V7(FAHk+sa4u9erITI&nVq z+xGC~aT69ab<#pXl@0Mhv9aa;`oL(|wvjsKH5EkPv=DB;RV=nh5ssQagT9EJ%r z*@2E7kZPL4?Mf(rn@c~FOa=P>yZ~Z|c@Dw?SI97zAHhC55CV<&^31Xn$$}`jqHrdz z0uuJH8EH@<)6IBdX!QaF{%QThnhQA;;PxiDTfqVKE&|OCl++Pf^iZfarA~BaGz>1A zFDMvc*z`;Rn34iAU=6%he9fsp>|5SvCw$uu?;R#(D!`6dijBtXly1M#*i`6VrK3k{ z@G_EUm>0f1upN-voU_1x_qWi&AVLzRiw_CBg7FGCTwVw&#k(&8wv(zSf7fsDYGRsl zZH)v;tI=IK%x&A-qN=Z5wxmE52_Cz6s6shhq??c~lEc8OeJpJHs7AYxGB3~j$1)X_ zApclKAPu>z=nPVE;hB(3W*2IBM6YD`Tu{Cn^VYLl9c1rXvmtEn;tAiXn15gZ4lC}3 zkp3FdAc#Jj`@8ix!T5vU&hM?42|Q~am$W>fj7v2doXJ|?`yF)Mq)<9E=|@^W-y!LX2E zN@k?d27MTc)Yg3nh5r>cj65c>47>vsSR1=DZB%Q zBesn+WDjuG??WNkj1f(U&Lf^kn;6olTPh<7&Tmi31)KSd871!BM%MB4aJ2mRvLoQ0 z)rI;M)r=tfiEqCzF}N=$2nWl!M*muTr+H#Zs={@ilk9Tggyj?+`w>uG2w0A?u} zR=!DKE*g7p{F4@+HB+mwuQgSx zYbPu_YM}A24tpncZig(e)_dC8)vl#E?P#Cv6htA=HWHroJn*-*v zan?U|HI!(!xea%j%SnlIstc%Mk6xeX)qxv~>_wuiSZk$?vw?1fZ$Y#`ShmCMtUnJ@_SEa<=+PbF4o#F8g@*(hZOzc*r&Wu;eG{1LS5o#o8}>Ul@Kxk4lj+4>SwR4F7#Lv2C}iq@*2 z`yyvoNqR00d7#-*EU4SkdX`0c_G1Y#)kBnEj-$bTFxq26<@zlmt z5+XTb@b=8uZILo3klTL6$@Nb~SQlh;!gQtI@(DSFg^r1&H~h@oBhYB@%|@-_-IZ20 zqVvM-K6O>hr`Qn5T|B)Jp__$#>^u_tC8?=}9#8TQ(YXUHL;0}n<43r;nS==BT9_x; zV49me8BpIq?NdJ_K4&s``|>#&E?Ic=LJ-*JehS^^q<~365GTv+??#OWpMe4@Cm;XZVkg zIkFodFmmkP{Hs`dFO??!)fk>*h>vKrKg5Pz(g&kL!V&f2JNMfP(+0&xltsISlfA#m zBObP+Wlfa3dz)5|ceNgt%_;?@#0BwH<5aMQ+U{W(L|WAk$&|=dxKE2Yx59$PAC+S0 zN*Q5SozUmjVfd3j#l3SgG}aSd*6npI@O)Pyj0&sjZ7Qs^;s3Li z$#w|)QP@G*W{i2NG+lfYuDENpj~jGItRbPCDyc{%sc1=3Xo;~)jBOc;7+xRshpSWS zJiamJp%bRUF!y$7uNC>INro3nl?sWSFSdypBe-;1UgY{G>+kPXy{jX615a>0KVbfh zlq1s=B5nkQB^hUXI;5BE3pgTtw~H{JA6LUKK(d2JD&DU;Ojqqwm?~InS;s=)-!Rw6 zIx)0tgafvUz=#)ROE6lAP5i(q0_weK|IMa-_D2PxN~{IUCQooTv9(aq6P7Qkd9B%y z58*qTUd7=yOytG{>fo}G4wL{>nUoSA=;IjpV$n3*kdbNQBx? zI=thso8$`MH`=PJ(~@-;>HMjNqqSj>`lR-^}S65s+uq zNoBq^)5#;jO%DxHPsjHTGncWu^O&VM1ww*!ql~`yq%!lLMyb%e=RYx+D*>ruS3R)I ze(j)t)z!(<eIGmwCak0F-Y!e0=)c(ZUm<>6B-!mYF)YFu=J1;il!UaPu=4)i!c@z&*x>tFeySYDT%PsLf}6 z#WROg8;FQ51-2I7R~NTrkDnuui}6!Bpx|B**X?gH|-Em;ZPBDF1P||u$#*8 zDi0L(6BAMaV?%s`4Jhr71jANwEJTvA0hJ1Dtz&>&P2RL-DhI|WeOf^YM{GjJ2aUls|b7c1h+R1iL@ z=t>w&K6>E3C{PC|5$|)pq|xtxVrM^a@j+L*VNIGsB&KTlZe;CGBcjGln}qM6e%3KK z%$CC%q0A^wj^4aRe;ZYyT2P1`DbE0@+<7|fQL~}fc5ty<6d30`c0){4QL( zPg@Tp72RBFiRK57l^2OI^3=HwU+tmp#Vk zQhm*RUB8_qT0v>q&~%ENSV$DwzHO7oz@qVNXUFV>OY+|&!-uD)l1*%&196nB%j0ORb|bO6qa{FRg`Ea ziqXF~B~4+HzBIk3V3G56MV_Oek2g$9JnhA8a5u!66nKaajC)V2a(sBXCdg%g9?$K4 zJCUBJah6fp549`_wYI6v%Br3QXpLhg6p&53YfSp`>bi#a~T zO=q;6rYi9uf}M0V$z4!)YuS}tYBp)ZW~yY^>2nnag9V{bB0)c|(Hc-1a28=SO&_j4 zg7pnIU(mv%$|@(=ZdVQ6Jz0z;K*)tt-f+pzHUUqmY`# z4OBX1Ql6tqpUhIT)vXqyMS@~mOC3APqt)L99OeiAxRztz>HBf}@GLuBksm2?GF&W* zk@7|AV-}G^RxVQTS2Y)9!eg-8aB2!a`z}5k z*bv7b1Qhzn!L1kNeDalG5OCs=J8{7i zPT&9mZy%$OfWj2#i>(Rh4SlDxwlO0Y#TPkGC&Bs=KuFoh>)&fYgXq5`B+lA1)eOR6 z+S%D^8YV5ca;#IGx5pRH*9rLv1DPaW50jdU^jvWdb;`Jh1I?Jrm{==t%iKh5(vR9# zjnB9WT8K$Xm9@B;8;+%2QjL|AVNvRQP^h_9vus6Yd-i0AgKJf{<^AiU%&rUX&~QDE zW76T;d~QSgbB&f>jcD0|(QeJ^C|c=U*YxmcYRApD29WgrQhYZmcN|A`w_zT(#g(#w zrn!FQ$fxZk;i{n&x=`(fCmeHhaEC866E1PzkK!99jgG4)l63ClKFW*lXZ)-e_2z%HY;xID{!^?j~cW-KeU2pDr+FM=W0v?J21;{#34*dFr*? zQV7ebWaXf-Z1I((Ew**2UR4X7`r8~Q*(qtp1*Pb!1QU#?kk!4I-kqzS!Bejd5nj}e zztq~3kByDm?RvV{()S@!uh;PL!du9mb^h3hgpaTv8}g|nH{lZSOg_B3d3+GAy?Bx@ z6m!?>ul|q|<@gd$*#<66)sxOF{%WW?v#u@sqW>|7roxG+G0g& zN8jUuYNbLp9E^b*4s*l-g|!F+j|FL)LN-Jx5KGDhaSdC$nbXJ5ZOFWxYFGrnVc?vJ zDtKacYF)gFPR4;ZZol6YwRMVUFQp-_0~=fRgzg#iqgp z#<7Xd=h608D~&zeB2{dOI`9ud@A4w%mP58s2LpHV+2b@RHzYqO%P>pLE>YBn#@5n@ z*`2t2<8rd=0yCqQy7-Af%pu=-gBY|1`U<>3IeK6D!*n;lUQNgHXUM=B`}`!{E*8;J~)L1)x9-9ir& z*3tZlfP?{sJq+-29afq(O*Vf)R|Y$yX(79>)bPr_B(uo;c1tE6FON~OuTSdcmcf+S zjiX&L)&`EInxpCbxe*f#GT8HNMFSqL0~R87ea;cer>3k~zMgwVR|1>dep!lw+{uH@ zV&F<4ww^8geDrBuGE+(+q*7&09&O74?obO?(lO>AYo6X6*Aa0Yf%nsqlNf(Boxbj^ zq!1mL8mX;xcfu2v_dajpf_X-IIUuRfaQvX4G07~l)%-DoAES^i%I66mDi@C*2r5?| zBchGG=Ntaq<`;Lc-SOaT8E_>pQe_yW^>_Y|Db_+Y6h$e4G^Gn}`kr+wU9Sl_i*P!7*zGfF z)4#{FwyGOOkLGmrJx)})#~POoWddym4{#e?$LO-ZYCNJXTHTLT27a|?N}K;^v?EHo z0d@Kv;x*5?_?mbvi&x_{Ah&m8&jw|k;yTK(J=aWKd;fEOPe-D{v~#FY*@5O!8Z*vS zBL_X+!hrKKuG5QZzg6t3-5Q+s$DhY*DksZLiz5|W5G~keB9u3H$PC%Fpd^sBtUB|W zE6uxn!z&p2SNB`}bY5RDCPqpOaA?7#Ek`hGwSifuON`CtKYgridYQ**zXgF7GZm5e zR&k53KNIDZO+jUE;-hki+Y-~v`YzA&X$~jS#lmAkqJw5b$WOaeiCUyXYivBPcYCTv z&>3&(B^bg9bp+jMLwf{0%;$+60f2f#{Fj^frNaM9f&8n?U zuci5Sk%xa&CqNrO6}|<15p;2nn+t#wRAeJ+RNe*Edsu>4PKv%oeRi+GG5o&0Z8N^j zn)b;37260QhI*zMB;cn$x=H1k`w~qDe--<|3Mw=WceL&_ZF?%HjEqD`f3(_r*s1_| zl4p!=&z{AqNa(N8JUffxA+Gd;_hHx*WhG{o7ut}ubTW0P)IYzd`f+|#P=7g!{DRMI zmDe#Qb}{ZR&JnG{lPktCAbfn`t;c`pe3NPZ1p%zka%A}O2CzH%&pL!Ao^hr=fTOH~ z{I8kv--)dBxIwGsUkVlY0|MA78fmY*d8ggP2dGp@c?a<^W|nFwdwFp;@vv6+plVV` z8$=PXko>^((=5WE%d|EX1K2T1bIMdw3Q`^a@&a|`tNHQAK~V{hjl!KFtl~W;7q=Rh zSF83Kt7A<-s$9oIcp0fVmVr)VVuh?8)Q>5`F%|O3k!ptvvh^gRR?jsRP0HSM&quCV z5~JQU-;$PQULtT8Pa*_uyL(8jKMCe? z%~+9kU~MyP%b8{1>V}DwCZJ}Gm5`s2tH&erC43YEop_)7HH>~So?~Ii#hXm&r9Qg) zFeV{ON7dT@Ju$Ua5*1tZx4reNJE_WXy|~O&-ID;?ow^>BNcDG+(!#uk+gdVU=mgp@c+y`M?L>M7z{I06yE*kPrFHPT@ zUstKNkPH`#AKkcnY}S+R*+dgpy33Vis}X3{$XaDsm_72k2HCMK*N;zN2b8gGwwXhr zN~42mCK*4AmI<__;5*(o&CVwfk1RWz|-$eii5nfEnU4LrhV9MQaYGZ%OU0-TrxTI;wX3!H1;<8BK zkR?iW0**nD(a&T6$+pl$29(mreQ*SB)boqbcL2ryXD1adzbw;D5BHpabiP#3GHq5~ zTSq|X(}QxFBRL;TLK`w1iu4+}&q|9d_OmlmwrneXOL^H_vAC3L+|0(MZS*dg$-`8+ z4;OVKGXW6`2mQVzfyf`Sj}zT5{e>m z?;>9py!`7~44>ppes2v}3z zOv6@w3q?YKS#qlGfrBAIZ!FRGYQT==RHOoj`{+6HFy-&!*ky!>%4Q;WsfffIkhj~I zQyD1`%6!LS=r6X|gJ+(MBM+!p&gfo@cr`2>_{Q=XD%Uag@q$cqe4gvfxmuM8qj$45 z3T`(#{Mux>q^aB^qR4W&@1f3B+1uK14d*s2jejN!E!U1wEtoZManX&FQ3NbXz|oUd z{}i=$xhNSM7S|X<6PyQTcX(l@dxeMdpZbPqyU@7c=Y@k7+W}zse{x@qL$ezkkiSm- z?<(1Ezn32OyBI0(l`HE9z2&ozZBR+=r0NOV=ThIJF=Ak@c(8U5uD2l zIgTK4Jewba4^d{&+I+MI)%NfXp7q-1m4h|^L`5Hk4&Vt^P+(B5u4z6zz+ldxo$zlR z;*;IsKbbLgB2DWE;uYCuO$#pHXyd5EAl|CHDhU@)pfXWpqhjMmhE3}pm#%*F)lddr zAIS}=#R_3Z&iip1qD67T(c8A@_bsc z%?atg7YSPi*zV_8t$4it7n4!F32|!%?uy_#?VoginCh=|Y~@D}=aE237kz=r37$_H ze#|1LY}!%(HT&cmoy@XQE9}{?g^5QS=jg(5ohCGqgexrBVCvfaMUz6NO=nO_lOx#!}_DVHdt z(zKA3XdXb~?|;}rBRd81h{M?#-yO`f# zUV%dLzQt0!I_=Z&Xs=c>UIOPQ3lGAs2LBG=>N{GPWmg>^uN2JS_*(WHX;iQIvJ4`e7`f^9!v+{bZ4o>^!2fzHlu!8db#^Tr$2FfeBIc%1aeTmmbZ4=r)QLvjK}t@;Ri>IoZnM# z-8%wk8pd9yr^Nk?=srxBAdYi1svjm*hjdu%WTt^9>gL<;DyBkjtk;yu)_86j; zuNWxLo?L8l+73IuZ#m4D>1w7fwfS->mEO%R7Kis_DB~uSpkTI?88t#JGHFIXv6&kX zBQPJ5sF+t<;GQEtC5_qOzHw$t>6I>gs;JK z8?}Dwxi(G^p5O-$dQ|E&*zf9C81yVs0&U&I;G|18C}KWQ5eJzeBTAapdTC#d7};n4 z@zvyW+b+{6!WBFGNJD;qEtSRsOw*&2vKIJP7SHHO4(p8BpVC$LUtLvaJfr7yF~%K> zX1?B(d%jLz4XYD*rz-@GfJi|ieFuy|K(M1tj6RO zMus2B zDPNL;UeC_6y6aEPK*DT3V`+6V6Cy#4juKpd^{oi{I7E1sGcU-CNkiEPgV=C=4DasL z2ZNq}Mu5DedWPdm!*KINt#lfPahM$5_m!t-GNTexbWqs%uFM}H8QCuC{>V>$-~~_x zN0oG@ZAbq!HHME^8sTVu<5!`h#EXE<-~{`R%Dm38}zopx`z!5DWUowg$J3Vje#IIx>< zEbA6yy%R_uw~NVP%c=EL3~sr8tYIS}hS2tf#e=O9MNWFyhOG8rj~nV_?aEgAepKbfUT$KIz}*0#j1Pt&1>msTIBjkdQLs!aTXLLHz*v=sG zcD%k^UynE7OMLhe4!^_fXtq4>#zR7~#a=~6Z%4A3Y-71d_@yin=^pIN1BRPEypb5e zG7aK~CyWbUIdyZaj07&bCc+jwMG<(|^7eqAPO#>2u|h4+?$b`CxS>&OyDL%lwBkuY%`olX)xIhR{s_(nLY)^Vu?%GG zrEC@Sag>5qF$Kru^c5a{dZ65f-(LD2HVKbG)(MfBPrWT2=rqQHsz2;3$As+~bfNcE zdNdt>6pbzXbP>%)U;t!(BUvYM69I#j_+3V{Z`8ofw9-dD8@Tr~+3CHus9X3Ipo+`9 z=x&BT$_ltx+ovf`;%V*(B2WAh@~SMCi!-hnJYFz5DzZL5mgFd{ma}JbzfZRV9WjkN zU1sf#YiiNz1qAy{Nyt6V4BC=bwX+4VnZpWpP^@TDp4N>C#&<;yk@OP!9B$xoB`J&e z70^}jpZlGTfy;n(z=WRxDg(&??|`JR4M2BsFtk%Nba413z`Q+Ypw%C;9IH|K4NxcYr~_iubpU!?y$fz0>ON1D^oT z6Y#YDOW)O7oVUF-e~=UaIWPdu-#cyI4u0E|@Mo|J-2WZ?A1w-RQQj7Q|3P5~Z}