From dc6575dc76b4e2e1150566f72b2cbf8afccb647b Mon Sep 17 00:00:00 2001 From: evazion Date: Mon, 13 Apr 2020 14:05:21 -0500 Subject: [PATCH] uploads: fix corrupted image detection. * Fix corrupted image detection. We were shelling out to vips and trying to grep for error messages, but the error message for jpeg files changed. Now we load the file in ruby vips, which raises an error on failure. * Don't attempt to redownload corrupted images. If a download completes without any errors yet the downloaded file is corrupt, then something is wrong at the source and redownloading is unlikely to help. Let the upload fail and the user retry if necessary. * Validate that all uploads are uncorrupted, including files uploaded from a computer, not just files uploaded from a source. --- app/logical/danbooru_image_resizer.rb | 15 -------- app/logical/upload_service/utils.rb | 29 +++++--------- app/models/upload.rb | 7 ++++ test/files/test-corrupt.gif | Bin 0 -> 52645 bytes test/files/test-corrupt.png | Bin 0 -> 61 bytes test/test_helpers/upload_test_helper.rb | 4 ++ test/unit/upload_service_test.rb | 49 +++++++++++++----------- 7 files changed, 48 insertions(+), 56 deletions(-) create mode 100644 test/files/test-corrupt.gif create mode 100644 test/files/test-corrupt.png diff --git a/app/logical/danbooru_image_resizer.rb b/app/logical/danbooru_image_resizer.rb index 34db067b3..9321ccc2d 100644 --- a/app/logical/danbooru_image_resizer.rb +++ b/app/logical/danbooru_image_resizer.rb @@ -35,19 +35,4 @@ module DanbooruImageResizer output_file end - - def validate_shell(file) - temp = Tempfile.new("validate") - output, status = Open3.capture2e("vips stats #{file.path} #{temp.path}.v") - - # png | jpeg | gif - if output =~ /Read Error|Premature end of JPEG file|Failed to read from given file/m - return false - end - - return true - ensure - temp.close - temp.unlink - end end diff --git a/app/logical/upload_service/utils.rb b/app/logical/upload_service/utils.rb index f13a785a3..e8939122b 100644 --- a/app/logical/upload_service/utils.rb +++ b/app/logical/upload_service/utils.rb @@ -2,8 +2,6 @@ class UploadService module Utils module_function - class CorruptFileError < RuntimeError; end - def file_header_to_file_ext(file) case File.read(file.path, 16) when /^\xff\xd8/n @@ -25,6 +23,14 @@ class UploadService end end + def corrupt?(filename) + image = Vips::Image.new_from_file(filename, fail: true) + image.stats + false + rescue Vips::Error + true + end + def calculate_ugoira_dimensions(source_path) folder = Zip::File.new(source_path) Tempfile.open("ugoira-dim-") do |tempfile| @@ -180,23 +186,8 @@ class UploadService return file if file.present? raise "No file or source URL provided" if upload.source_url.blank? - attempts = 0 - - begin - download = Downloads::File.new(upload.source_url, upload.referer_url) - file, strategy = download.download! - - if !DanbooruImageResizer.validate_shell(file) - raise CorruptFileError.new("File is corrupted") - end - rescue StandardError - if attempts == 3 - raise - end - - attempts += 1 - retry - end + download = Downloads::File.new(upload.source_url, upload.referer_url) + file, strategy = download.download! if download.data[:ugoira_frame_data].present? upload.context = { diff --git a/app/models/upload.rb b/app/models/upload.rb index d5df336c4..a9d4e5fd4 100644 --- a/app/models/upload.rb +++ b/app/models/upload.rb @@ -6,6 +6,7 @@ class Upload < ApplicationRecord class FileValidator < ActiveModel::Validator def validate(record) validate_file_ext(record) + validate_integrity(record) validate_md5_uniqueness(record) validate_video_duration(record) validate_resolution(record) @@ -17,6 +18,12 @@ class Upload < ApplicationRecord end end + def validate_integrity(record) + if record.file_ext.in?(["jpg", "gif", "png"]) && UploadService::Utils.corrupt?(record.file.path) + record.errors[:file] << "File is corrupted" + end + end + def validate_md5_uniqueness(record) if record.md5.nil? return diff --git a/test/files/test-corrupt.gif b/test/files/test-corrupt.gif new file mode 100644 index 0000000000000000000000000000000000000000..e1ab46117b5746b05ec9555a937fc829df485932 GIT binary patch literal 52645 zcmZ?wbhEHbyv-QFw3&e+FE8)t(WBe9Z(qKA`Sj`2KYjZ2`t|G9*4BW4fX9y?-@bkO z;>C+Ue*92XRsHkl&;S4b6@RiYfPfB&0GYwS^8dq0&((V^UZ36lKS84}C39ZJs&zT9 z_Z8@zFUh@MvF?4%`~L?Pd^oBh!Rz7dv@k+v)|vFARS|yuoX(CjO+$8uJS*?iQP~#d zela3phit*|0>AaQ-#fS;WG>&_>&?i>&B)Z`$H?XB5uOv}Iw7YvH!H7h+O+!IY`4x9 zuCzdA<~HW$rnb(|$QeZy>o;uNWK~!@V_KFwdt^o=*YXv9p)K6rtE1d_)@{zOnmNm> zE9Q^~4}XEs>5V(PQ|mq5PjrWc1gCgMC;2BFi;YS>vHjDj>zlu6v)&Tj>Hg9uhT;EA z<822{uVP)u#3H2PAvjt4>YBTY8BaQFWct75!G*`VCxtY9|4SH&C?rf_U}Eu@D&l!5 zz}u0kEWbR1z3ZI@!m{Ib98oSfJ6`z^nA_=|z`_Y>9|7N#_z5E%oaP z^)&OJIme=A-lKyd%GcM=cZr@PbnQsA5qJE?tFJe%xfUK%$5Y^Rx!+fKo@%t1?O`@? zS<|Tog?CqLrazwJY9nPLc67qECchQ0awq$&i&)X$`=WU%i%`t@n|9p}yiL(t`h%9u z*)+#N;Dhx55tKPqGjO&T{p+R+%|SJZMq%c;RSRn&9$K_OIx)SzKKYx3#zG&)M>@(`d!QgG|g<4jy1q z@>nX~rEAe3P$tH5L5X|knnq_&6Sk8~%$zv}3=PhEel#*#&2nidby{@b0Ha5o00X0t z!GZ=h<^)M5ce4p1PiLsDSkcH3eePiclZsse10y@nf(Fz5OI*@gStJ%TGQ~-4P-bKJ zVb0_vq$Aj@S*~`IgA7Jy7KIP#tV=Ycn3je{O=y_TDxlyl{hMLI^97kk zl`9s^@_X`}k)1&ydrnT%g!Am&6_(92Wg8|rGH?h4JYlWkG00inEp#E1l{Mg}!+%C* ziwO)2$J00uY?4!9c-q~wE{$W8vxoXI@jMlShBXW_3&PfLu-wvJc~dT6+7c<2hPTYj z3Jj@xcQwsEIAwX#g9D5PPOBN1*7zkf>{0n*-pKHMQNxP;HY*$-l>26OA2`P1z2yAC zWxF;Q?6tp9eUNFHk(a^I|8dz%_p)*@G{~`=6ue}ae`s;|b{-Cei42U}71U2#W=LMD zja#$XfT2?B#Pql?DU}RNnd=TToHi->&9G36g)4Kvi@(9sO?+!qPB8kLO?bXmgrlLr z({Q2*LywF@jW2`B@`RilrXmw!4D$@QS2MoQY;G}|8aDUPRmZ~zwAmR={=H$WWcD(@ zFC^0N^}k($ZGa}zB<}B7rGA^_YuRFxBFnL{*>+20gjZE+KvKnu5E_TR`+@Yn% z*r>>HV8d&+oOzC$86vtG7mF@9vqI_oyVr;At=rxZ_~dFzLEh_|N_!6J?Ww-d!g^tQ z8N>GnS#ld$jvlr!)im}quw&(8P}s}Xw(3_C^P#ZwOp0k8F>GwhbVO7fDm5f-JWcwr zgE!&`(?p@hxiRM3MA!Dz7YTK`EP1pu_+X~zwTt(;4?MRQNnjBPUJv}D(p28Nb1%&Z&ygpv#P3C(Np%=Kt^)uqlL zUG$(~r}V+eo79}S{{Qf0eN`;`Uuj$WMaJxkBTNT&)@*N7&C+JGDtW|_^;nrV;3F$z z#sMbxf`;Fg@0exQ+&-(fVBM>mzRU(b4Y$k!jLq^6FkTZpvhafXaULBa{INUTd5jxB0p7dlT*98W@w3qD}!j3B6PcU5zHDd8D zaQI`?U}V4TK<=6+4I1*EN^;){t;BxzF_H!9yhV{m*W_m|}gg*_*i$Q@X2 zbM^eRTiuaHr=OgTPvdsGsq*YyS?Efk4q;X!ZibdMfh=~ClbQ3KqL&6REuYbIj4|Z# zvdwB=omos8GM9A-Tg+Opmida;e@BJ~PiJ1?Jf5}l@}vsqLu_}R1xhYB+a)A%lv87C z0MCOLuK#ON6uyMYRYWeBP$MnzYn|HmVpc8D1s+L{mx*4MQDyM;S@OjF^fL8$PM@^b zbG*4kR$g>ZTg7r#Y6Ws216PI3f-$8mv$S8aOf7$9rzA}~#i?Vwjmw(BE3pU(V)zcGg~bt5kL4M93;kHcutsLz)jBTey9$3M99b_a(X;=_ zC6W6g-aHJkUVJmQ^PhX<>)5=+QTvIhph$nFt?T5v$~6;y7F7fZSV=G*lWAs-vQP~S zUZ!oYptvsYK>|b9RWnuTDCK+3?!OwQwU|FW^smpXSX{aF|787ybv(Np>bvbW-*}{Q zchih>%*JUV8v=fB67dm;=e4-HAo%cM1(#*g{TJ8@H-B8lxFOQf?6da#%|{kR=y_gD zn`XjZkomB7M?;zXgFNZyl1$3qst#rvC0%W3Ys~!Wpw;N;trcU`HHAk>&Gkatw2x`p z?>#rHn2@9CP{`Z-;MJ`@&6&j;u3nuSzIw+Fi@eLWt_Is{Z%DCRc@*!x^XtuAAw^mH zz$0Qhi#zs&I&tpbShjWT*%l_(D97n+>-vLF-8et#H|w)$TUvY!4PTdWs$QKsWBTywZLB}PPK z{kGUwL7(2OV>+^gVUnF$_)+(&M+-|Aq*qpLxbW*-j34K2CtZfHCXIpvKD#WVjpdJC z;h3;4DDBE!qKm@k+I-E@>=ICXSsy7jr*8{P|4Z(Z(U{`+S~9CvWH`ITh{^gei| zIxh(N&+~u6(+|!1wc$dZTPovAbL78r=ReB4Y|gYQRG&kEz51(xg-iO)2VC49j5`nc zEEm>Yvz-6(q&lu5AzeqEG>4{*hb28Xi#$@`%(~9xmyj%9p!#2s_nJecghRt(Ws_ca zHD@-acY&_jr7k)OHeyLGi<{(l(wHtZX;v?1WO(LkX;if9io1%lN~0l%;}hZKB^>)1 zWezcl6d!8wQK~KwDwgsnUlZOaSD^a$VWUk(?diw<8VxNw(mfd#Sk->jSjYl{-VYxqRBGdW~ujLiYVQfCeZg!d*ja`hmjwPiVPO3`{)|U98 zxzM77)wO!-^zK6`&Q?NNycSG-YV9W1bU1dze>-fWy&%EzgaPlD%-C{YCIwdqr*KmS z?f4?qoGCSDmU%Lkw}1H@dzB-)?ozWzxJb|i{tFp8pRalQYq+0oU^({LL&Cr`I-%kJ zB*whOT{i<%w><7sS7d+s-I+UBWsy0v&t<7C(^GeDGLH%p;{4FOvs`O^MI{qQg!ob> zm5B`7D}1WeOP@Z~msr>q6`a)J)YsxsD$Y=Gy+QfjjB4Y_+8e&8G);;y+t4z<-K=^7 zD_4`yaweUt%b5gK{_EOYc9s3kta8x#=nY0Irj|$BY`!Ts%`a3}`r#eT|v7u~~h? z)E{Mvma%4&L(w(XdO6C_GxQYzgmR#;U-729Rq@9z@*4kvA)MU5cfpK0q zqe+Lqwxz~h!I_qe+KR55$T9y{_i0l5XE?L-QrAX?veQeawY;=^bxgfsiQW@a(|?Ld zA3gGa-0Xa?nbkYfuX(a+RiLSs(e!&?*k*;OWGe|OuM~B7te!4ppiyPSc9ZeX%L!J8 zv=ky+yNf0z9g8(mcI|ZVd%aw9i%N;(gf8(0p`ryU+{r%iotY6yfpaCYel*QgGp*Gy z)?xVM99^V$qma!VNo7Ncmh7#fdnLkom!|x+jZTG(Nxt)+E>T;s)_B5%0>)Vv zgi2zWRc%Cyzdly|W~^G8l`wNl`@JIxFQ2NrSeeI9QO(}AIPa0XiHUQVgI_?AUU0L~ zsY}MiOv?9@Ts%v3o-Hych^S4R(md%_r|1rYYLov40k0U38O`76)p}Mlx)~%2byq12|VrzEVI17sq@WdFvm-KXY^o{h>j zEy`yvsj*Mi?6I`mS?B98p)97|0!* z&)T?XXOf=NE#K=2*&Rg&H$HAPo}$OlWK^|i(!@{PEe$=tlm5?4FETipl@J>lr<;%A)?@salai25SuK)vZfkdg-3o-01U_TcS`UD@6O`bk(<( zCDj}HmzNuGo9Z48GG=X6+jwdHHr2IE$y^qhw*RXccQbom|1|GT_JQ+C+8K}3W5rbJ z!qmJaj9ISMB$q8%a=BK$nW0rk`1c|EnO28|e=(fgtQN6o(gvx8LDE}|CQo@Qlxm@3 ztkR_tyGZv#hzg&uX)u$2>M9n`OpZ^FLT8^~ShHBb*MVyaGgqpy&Xh_2b9681gev76 zm^3|n@=CV{>$kZ?USjp0&Bn}dnQ^*Wl2wuA0p`R%PlPX>&UR`t5}sxd6sW#aL)Dwx z@%9th<3?Pk1312J_FJ@ax^(r=1{S7o09T${ppu4m>Fr^j;@O^%;US5tC|k zp6m{LW1OX|vr)+=-C^S4M~9}U`uzGdx9{cdkWcH&q;xWZ%QkH4yJ;{fBKLxXc;>8T zS>`*TO`BYdwdWnR)-9Lio?;rRCTts?Fn`CKO|BxIbA>DpFcqm>xFEX7barNRsIzs3 zaIAkoQtOFnp)6biYjqFKp8W3iYKOzl8JoOfExE#_VkKQoHwaz3u!v{YpNaP$d1ijn z)ZDFly!*d#s3L3IY|B;5x*D5r%N^KtDkc7)`|X*F{bx;4d%Ln~xw&GdZwG^rmcZ6) zXNoe6mqhO~X`J`x<`J*_;;PBLpTpHA+H`Asd3EZ)+h{r~#I1%Y^55Kc}PTpiQzFXc1bki>iF z%#!1ipZ;Dmy{Y$Q=hByZOQwfBpC7wb`PboFK^xUx8mWrJu}Al@yY}j4@u)Vw49cy1 zX~3ZK;-jXjZMD|SNj-N~eEQ^;zQAA0^Qb_}+;HQI8!oYJWD_?od#ZYop=+Oze-KM3 zi|(^e4Q&e?dalGt)`oPN9%NF}d9;t|;Sa`pVaw+3P@b8(?)nFguO-L6{bcT|`fN18 zy>js+k42wnOPfbloHcLtv+6VANOoD)^@LQ2y z)?{ss$>%2~U(*b%@V)#%)M0D$)Y@m8$~A87(fbg__)ay%VNuhj)0b6(jBD3y&=V6s zqgy(`R7eEY~VtNCln*^SYibr+WLyiKwz3AX9VldYYS@^9Vo zOEV|&U+rWOnto>U>0j^WZTq59SNuqFhOTbV>&wO0E+_F`6xd(NuX;w!r>cqNsr&EE z-z0tbl$3Rf_B)+fe6i5FEXd@;oef_D#MZmtV^p75uIjpJs!xLK&!U{-mu8MW*0S>^ zpK3DTjuD!AUZszDID=z3!mb@f${{b|}HY!dH+b!y?*3-~!hPFN=RR+0G@AVO;Au7FfQp zU~t+PB;nwo;_{R!!eD_T1GA!>#tVT54ZLnsT?7m?PC7I@TK>Ohv%>uB5m{v>fe3?u zhHK5NY}{1=p^DQwrbr5Z$Xp(n*2BW<#uwe7;K&qa#OPAP!r;crcHsbnX%PeC5%07o z4tJKe9MB8aHCT7>>Vd`Q;(Wem^oBnavSQ^EySAyx<4&VC-?U`~44M9dn^RfkG$t$+ zSCVIw5!kWC&BsTOl|#TUA>@b?>wb>;90J^r&IrmBKUuorz=0DR*98P+Tztj6f92i} zL2h%C9{I*GZ8%rby@qASj1?Y#F0gPO%)6I!_@rOax+Zm;5n*7F zX`Z8)ZK~%H$j}_q9@_BOSjJ=fdIydGgQ+hLv`h0vuy>a1>1<}oS-fb+|HBDISrMN1 zTAkG9b8#^oV&{_B;kjh)4F(n72SLpfG_*`^F_|*QSsXMKlGyRSkt@_mi!Fq!;E|zf z&I3(3i+k3M(%Wuus51!k1-?)esxRnnTX=zCxnav12d7qkfsCh1XMM_e(AJ!5$`u&P~f#@y&YL?W|ama5~fB<6(c_FNq5;32`Z$X^(&5)y5*6?xo-&$Qsn# zXFE;$fkeTgDH|Ie>78-DEu6pMU?{`6+LTTE-~7yuZ18w>AkLuU%%_&W`(hW|5ayZ? z%JNRT^P?Q zcFXf=tlAmBgfo3+gz4QRuBghHI!2qnti8m|uiWJ>^Yj*rl73t84`tJ|ua6@aCrp0u zC_-V4!IKTooffIC+bmpgnUiVxr*j;?rp=8^-+buUO2!q|jg>9G{!B6I=qkM@;H}K{ zVc9&>H@xZp+ao;J9^kI6xtOr5%A$s$;jr%tf01^+4kf{A6XnkC^R_ECp5v=|P%RO` zV3)`^`@+WtzQZrFPxEq{S$MdcYkpweF2a}jUDNd657k{2bpa3FXP$F9D;&4sLV06- zvciX7OLI?Za5lz7>-{*vU3o*M_DV+OjQuh*-DM?LJ1F)wE!rg8Q5m4AJ+VRHCI5>< z&XQ@i34(t(Wxfj}Okg|vSh#|-C2dKo!2iGnaq}Y<7nB)3D~01%`5a(5Qkf#fW5{HdRAO+wB9XnZg<6c`> zyV$x9Oet;~WSzMUKqFL(hkzM_7AEiwH5EvoSM~ zLxDvH!n`~$se~q|^|Cy&*?K`>ve{1$xf$M7TO&>=#ayWQ&u?l@V2k`7^eA@ zq090`VxwL_Yud4p)(Hn1l32VXg*R-N&A7+iQN_qnI%NyHMS&q7ug4{8ch6(lKaYx4 zt(@cR`#?hY3}=j|MwiDn2ESzo4A>NV8JRUU`Dco#%T(TQ^jVaC;Qdu5zbh^?I5r4a z$5|Swo^fbNGuXh8qM+c(_R!CJnn-Z9y96HC)WsOB1N77x5#||bjNsRRu z&r5Aqh!Zx|4i~-3n6`UH9I*6G2n-Z0lDuZz zwkyKHQ2I}qkMaQ~{izG~%1qGH*IV$Kk!ewz-i#H-@3Lob=4_Dt-=e#xWarbUJO!cJ z2Zh?}HfCG=Tj0y89Z@;+5$Dk~vG`MGoP>oMyb3>XGfnYwU}gzokckMKWWHou5Rbr- zqI(C93;ms#G~3X@LvKTm(QhUtg$U15$B&W!J0fOq+c5rLVfJyF3D0)d_87*gZ@=-y zi7eoZBA%T-~S#2vaMOUNQGm8P0jHAJesroE>LQF1{VXI|_Eq^(=TN;P6_JK`nyir^W}4|Iz33>=Vmakfi|r1Nm5)wUa#eIEF1_`(;A}u^olO(Z zlRyXgLc@$z_D-h~9p)IZZ8}<{b@j-v9Sfw7xd;n?;F!?1|9~m$!k_9QO38C(typ$E z`r5IBD`n5T<&>^8m~yQ@&WmRwXUwhYwUK|W?Yz#gChD`SlS+7GV~gCX8to4Ewxu5g z#TTrauw@g|ECKO%ji*~)EI*NEZQXZJpoK;M#)l5Ob8A_A9Z$^n>Tte#_JO6R^k?Z< z2KFcZl5-cDEUH}N7%=0xJEK-7hf4H>!<$prhjp1e&p*l_pXd0LSMxq7E?ub$B0(1m0PznudF?wbj*sys$q$Xz)q71ZM!FM7EM|o z{Xwy@qI>CuuB@5OtV-<+i&>%$Dg{bSu-(NX*|}*^hi;-*+l~lsn?*ZkX|TlqkSS)^ zEBu3bK=CbM0)q4|L4#=7h^>rQJfyun*-xtR4-lLyy=o7N(4 z89AgE%qg*CE>2h(ccZ7Pp{e1Onc9_(?NM{e6j%xwRv9}?5;(yoUN9x#V*7C^0m}+y z>r)~T&1>(^lHe0ycbw6h`hdw;fW6du!JPmZ_ijT)Mn;q3mY!4H(k`8i-u&HxZJaxL zPfE9OPn`E(E@-RE3!QrfDvLHaO?O=HIZ?{&g53Uso)(A6Y%MHrFK`rl@N#}|?pAD6 zi?TI;)24NTt#Lued;CV_V&dcONpde1ta)v`V*-=dN#T%#o_kO3 z&lPOm(dV+f^GLH)p!lTGm%UI zua`Y^&?>MN+r!bCJB4L&L8E5O@t~PZA_<1Q8+c=N8e>*)oZ7r<3irg%FYFXKx6eP* zc-gt}g!dfT2jU8SUp!osJgRUcE;zTEP5H zMi1Kowl0QMXB3nVuh?snaaLr7z-ED#mMe_>r(C%wGPfEqJMFNHm~l=h!y;g1W77;Zn@y_xFl(*|LtbK=ozhUFXrTQObjYeD2SN#;zXmx3da3H-RG=W z?`Ac+Ka>u;;PGpPNO6Z};S)b&9i`7pE_4Qa3niF)c8JHUa<@`!(LTKV!0iboADNnZ z7z-KAJpv1k<#o7N1vfWTOnkIk?B{GwkAm}}9n6y|cCr*Rd1!Qp zt?3cal<9uh?xEr0K4W=@A$#+R&ZjFRj6RtB_c2uPacD@*;L2So_HfP)GY#%n3zu9q zoR{p_;bn9>c#n!n0~6OTvDYlCDyuzJIa=%u)TJ&o8J?JO`y)eN$mN48HH$iUT9rHP zCAus=G;TiVYf@lhx|H+BZdOUp=2|8xi%0BSQyV@C&#@IWVPs_ACctxZvVvPNqxp-y zyHs|(W1RSKMnn8zj@?}5=hNVj$ zRx>X?FjM!EAyyexA!wVW>E^z5bbR-{8cGx&~>RQ>T1g02c zrJEg{JlX8e_q0B6;kCaiqib;Nufmz{k&`E9I(im}RzDP2a)kH6M)40@*ri^vwkQZ% zG0!?aC7gf5oYJVUq^sB2zV73>c}pe3eQj}+uz}kt2jlFo4NE!ZSWUTx z9XS?kT}Ra&3{OTGL{yyE`OU^+du^M})eau#SP!mAm#dk79k}y<^6cLktZ5&W?!R2H z%CduRM@z}XX=x|a!lT*Tt}Iw~dT!<`u49IW|0cV0oQX=lanH6rkCsDsDJgOY4}m-0O3U0fy65jVrjj6wJH0p3GT z*MT!d4(*160iqpziTxeYH=2F6`Jd1`nJ7f^(j@0ljJz8Fj3%xpI2o2!xI}iHnt~KaEd9b259Im+OhPa zmFWI29O@b>?~a7U3GADBK>2)hyikFP_3X$vg}B69jU3m6X16Z+D!>x2;d-ip$>vx4 zf42p^{WeboPu$I#Bm8*l!8D1s%)P96$?i55d@;h3rR!`hta9L^okLm8RYy!JobvH2b^mX`eYdH5r zVp_~mhlmBggSre|d1Fs8r*06vbLh6V_x7M0jkbazUky^@64uNNc$(P2Y~}C z2*-CF$7cixJ7f#>1>82?(PZ(NVON(!(C^MEpOXqcFS^;%o-f=o8&L4|jBAG;0K2W#STF`-R&@VS?BJ?%6-Mg9C&mEtzv$J*IT@ zBpiMmXK;4$3Yo>ZO)8nJ9HMTMi#MFr^mAG*msxP$WzN;RvzmUdcqk-%c1Fw=IkCkR zC)>+9nQyu_D>AN4^qTa1&PBlm+I3SGaV@yuz2v#>ew)d&G-_GWuFkU> z*A8_gXFBNjALNMem|FQlo{x!1@o1B^py#W_;vp+k6k8LLIM|mec53`+m0c*&ns8Dk zf$8uymZb`_XDd9PCK6t;<3>nXQedM>ROYMAEc**zhH*5uEH^mA`!hrM#GIQAae3D` zB&&CG@8#=on7_2*S@*@|{{sTFzesfXJ1ukBpfK^ql1+vS&LlPe)?D12;Bj50LvES; zm%}-1Vat`cMK4M2d+QhB7viLBu{-^OfyBzz*=_B*d0Ki2es3FDcW!>jvQ71>Y>97(KG`-rY0_tc{ncIHMMRCUrEM?5eNQs~7fN^BzQE;&-RYZ?pK1GbJ(N@3_T!!L@y1nt zjXT$D67_HTZnetylHA)yNzIe((%&1x|B2q2(7dj!$tTgUU*Sl!m#o|isRf@I7^l3s z%*eE`xjpQL#I4=&D<3*Y-(&n$*uOH0!#7_ge7&a{XUg=67osM}gqVN7Im!Ff%+B_S zoDu!m@n<+MY}{m}*R=B}gRkV;GhY_1n!vo-Lp0|D-#3fq0^Kdll_Cpyr)~_8k6Q7u zr;K^PY=Nn8o3K~v)REZHkZ5(^sJkR*V3!|Mq zj2;ZxeM$ukPWRYWMl^l0@JsYbaawq}jEgPup}B9sdb8FC%Z!X=<;x5&G}lM5G(5Oz zD8j|abU2V9@L-d3;(`8y3QQb~j{J>>l08n#H5_J=k2`al(aD|R#Tmx~NsBHupK5s4 z%;@ld>A>NplbyoO%xZ_l=e*B9bMOFjTf{{_{SEny4xjQnpE@%fPntf($oKU;QT>o2 z#ZdDy_SL-^H-DUAulmI#F5P_8;E=<~g3$R5hx!j62yYN$Z?@uy2x#J9U=aDw^CSDf z(uoqR3|s;eJyb%vnK#?Gynevez|_pf!eJf2m9T($t-{-k0;TgzOp9+UUG16dz|H!7 zf`PO97IW&{B3dKI>f#tHgqQ zM`ktyTO*GJ3(q%uvaBq8d0gjgU+1M$c|HvZSsE-{TRM!`!met}G5N#Au=_;=11|&b zp9LzpVobseQ)B`rT+`0bSirO-agst#hLrU>#^OyXMnMvxjbdGaXQO(Y6V_>2mmG1F zT(qL`-$yQiKIW+`Vl_!0o_9C1L?+q&xOijg<(q*sv~yipCUG=LTi;RqpnCp#&*n{w z%KmSNT-4H=z+Nn%y7cDqGhEUV4hO8Z`tq459QQjektEt+DAMj*G<)ZTX88b#;K_{Q z7n2m3kG){)Hx8dNsX^$A%8JQ_?_(4Njky*qILKfxvfzLT6VKs;3|CS#9M!p|2t{b} zMKm->96C|pz&y<+h^?5{O5nWEs}Bs9v_o>r97{QC6U71<7EECGtoS%hL55S3Ma|6V z&-3nhhK2|HLE@GR4ou%CF~LV^%gl^fTw)>tk2?-01`A04ePJBP%%sBL8C(>S;1PY; zqP%5ctiS{=$GIPs0w*h+R0y6>e4)s}-a+nGih!%!$1aKbH!qYkw|ppI;?`Qpd8j2t zOIdg+&$4CzZ&*yundZRHBja&qu5rqXZo|e4VGBh)RF=5fvbG)5E=*^d7!x)@fk9`1 z9EZS72EIAdj|FD9h#U|wydvzy8MEh-PO<%)gv6N5C%!D=I?J}1#n|A^QCHipM}>#d z*bSPS)}FW-z`%9sl7RY*^(8;L9kaA9ct`KNYIQg#RHcVG^{$el@SKkvGapF#be?gU zwAAE#qgWQB%3^I50k<16@**pOO3QoN?}gX?Rc-F;nCZ$O$v^o?pt0eKo17~et}r_= zTSO`x;1sCeGn?1Nl4q9qzK98aij`9~70R5=lHJJm<(@$(XQs>a3Af``e*HTCC{to% z_0}JcSp>Uz3SKbf8eaInNS;TeV6HZ&>gwq(yfKTJtTs99$}RCayJ(^c`+~ba@+FT1 zaEsP)nl$ve%(~m;U6p^ z<0O}Pl39~V<&SI;=_qXNc2nUy*|5rl!}{$??inkJF1d0hT=Mv_DzNd32v=^D)ZzG& zV@?yLa@l`|gwFu*lXQQO@f}4k#3TLpJ z=$bzaJZifoh1>kaBYxjM5t1u7+9X951ibW65)w18Sth~4xJSFm;m))D+Rqf63N=rB zkXWF^Qgywm-@E(DH9XTCCod>$27gE&rAr z)DaVj-?h((>+}i_Z(a`ugFtZ~mZTuInJ<@Z%=$W6rK`Jaj!lRD6DBsTiJ#bJ*)%x@ zJl8rQp>Lv4G}lP#1k2QrAdz}SNnN2Lc3usJ|IF2gI;WHbHk-b9SZ(6q&%0fTN$v;7 z{39Qp7^Od$XCHNlah7C2Y1fqQKU+Vug?P_9wv$#*-Jm11OVd2pSy~4^1;_Xg0N9QT9 zJKtb5=TVp_#no!FL5r8WF5*Ny$dZ%>e?l|VX2o*1?g)`%YDZLT zJQfDUFa%wPjj^C7G#@@b)!LRGl zMX@>0m}f6MuHC}Sc5$cEWEPd6tNXroxSKE;>{Ps@QL@hdC!Y@f*2;}{1P-Vc zv9K~S+OV>pKeUy@=1$Yphcgvk|KQ3q$mdyijOl-a*#S1`H==HfxRk?m#WR02^b~o{ zI&&w;@siMVf&!-h7M>@0!q;5u zOlAzY-<2cWb|9m~CDG9~Y32hl$>j(Ab-oDX^h_(@Y(C=E!I`{PiBoz;fkB|gX=Rt= z0&=q)CI!g&O`jCjZ+iQIZ{o)@oS_>V?YMSrs4`57VN?m*!?j_m-MX*(`&5IMWNdGn zy(QGA=xp1jIU0h(j*L<IbCe{ypw@=In7v=BPTXt%!5V^*)@fkTBZ zK^%3f{;n07aH`+J!c3!cigdBL+Pc31I|O|i8k|=M`c3$`edDZYow+abb&fM#*c0$y zZ`)H54F=v5UFsiSzbMq<;1qQd{;-bsGEX2J%h zTVf_gS6r|5EAF)V&Bms1bJdQLCkNfX2(hw#UemKgV!7vmla6f(O-yZ~od>c$_1jOj zyj`*x^*`-&A=TR7Iz`aa6NzF!(y- z>PqPuQBxC`S`I&mGJhnnCFHS`DvL+EdEm{)OXaC?iG`D+93(#VY;}9p9J3_7X6lu1 zuZ_wdq3apI+~v=%Q1!3V}%0O$JK6}U9Wj6Zb~;8%>K$bRefsM zGt+@5BgE9Vn3=Iu$n;^P|P+u_aI&~a;N^IH|3XFJay6FeDn z(P55mSC)hS>BI*=ITd*K9Lmf%q@K~DB`Cn!(V=K5&($iWEfD#Bf%jcYcP_EWKQ=u- z-^BR7>3perLi(UW?v7(DVWIU;M1)h0+B)3zd3u_=i7hMkp!D2hlQe?-F8J18=)UyO z;Xx?7>x2vJs`uY?#BjTCeb^YFsO$FUE8FpiiNZ7cMW&rp;b6|=6%v~>r#R%oqZZjZ zRtJu#2|TM7^vO8&Zakp)e~IY2T>clVmxNCWG^}j(j=3q!b?f)lhAx9dmRrZ-wqDj= z@MuRY59i(n@q+FRf)kXP9J^93<+S>)KFir|s+2K7QQCp&GhQ?D~7h4kH?JhRbd!>vbGE@=N~ zcU+Rf^QQUHpGMtj;Sx_&{erG-54bR2*0GI&{YZzmM?-6t=QOt`jBGZCls+ubmhf?0 z>3wxYoTJJzp&W4;Q@1TMS{yPDmFXPd?olZUd@4M#MMb2+|3b^729A^&PemEqb#^>D zT%&3>!#_Ot!P=7x4eENDDqV}_C~MxCB%k4;`NKW=jhd!Io0RC0LLrZils2w{FfI;f zg+0rxr-V!HiH#0u({^C;?3fee>7-oYr^(>-@&BEt1}`R`&2^Kw@>JQx&0A1y`xN)g z%ua(V%*A$sW?L?JeHAhZ3a~!s8TmlPVZ*Y_Tc;l8NO}EA5Y3%yr1?ao<(y{=_bwGSIPUP|*rY9r{@1$B&TPos zdU{Pmt4xMav7n2Ti>Pi0FXP7W_76>tH4&wko?Dki99Wb3wsNuL9z~fd0oK?vO-hX$ zN;Ha2cH|sWX)bv1BBE3KMxxciWqcklJM%IG1LUL?crsO(BxhuLB}J9JJggLTfZOHZ z_709n&Ey$s0T)?SxhJ@k*fz=Bxa0Su`AEpr-d1(itBjfdC1V|LzBr^IaKu33a^U`4Q2Z>!7xP&wN#b^_KfQyEN_jUWqPPDS6^hYK5mCr{kq3Z8|*% z82>g(J&dc&z4?KM)6qM3TEY(aXq@wI@d&sVm&r8SeP&kN z&km6Xd@Y|^{)--*@rP;o4YpaStzoyOb_KLa?`&AZ#F%+OOZbMCbd_W4nUex*d=cgFm2^DCyf`% zddIi=G+%O&i@3Yc>cL{8M8%sXZW9i!l)Td@Dk5t3a)IxHRF1Fr1ofhK{+DF8wQ_eB zy3p~G{iy89Src5=M;-mpF^~Pi(??&XJ<&*+8mMV7qu+1N^uIgW)ZWfhZDo==(4_M& zfVrbvsNpq_huZSD44D?p4N{IL7Uo(9|6 zaekWCiJnzGuQMDD$EcPbt!nS)3uxhCJZ9OfO)ND7Y%}UAD zLndzb#t8x<-P3yfrXO@HtJ76I*bu3~vhtPksiLga8#OZwly+ZR%{PO!;*hSV!1L%J zN8N@l_Bl&@W!Qde^l8o1xOwoEs;s-fj9&Rw%~=Z%Oj*#ac_f2juV={~=dFz%ic4Nh z{GXM(^OK8gPI%_b14S>o&%N;OJ=h?yCg82CEXRp;?Wa1}?ld~OwCO}0xt<#Pze8`D z$dN5S`|h%xGJe%tx%Xs4(E-ITjQjbNv^ki#6E1Imuv&75TR?^@--O`fn)gjtv|fBG z!DY#K)n-nZ+ANm|X{+aQiGFF{IFrdR=(%I#F(nhWOcjHY17nGrt(;yqhF+D}qn;s5JM?_7aBoyeYZuNv|?n*gFzd zyr^U13N#G(AtW(rf_TuRxI=8O-Z)GTXq3NmP_U*$a!H`j`{+f7C{L04I9anJM|3C2t52A%S*)4n+adJg$isI= z87B^DX$fyQqdrF?SV@5^rp7CI3KQD{U5!rB%$Swz_B>)61su(Cs#XYVIDY=ld04Tv zNhUyBHS@mA+x|OhJ*feg%*zuerIu*cHfRewPfzJk`rwk_ z5@I*H#+Y#Wvp;@&^rZgv4z0C3GanpToqOcria;yrQ@`eUWXkZpt37#1px4{4@x_6_ zxZb%FH#Vk+Y<0I(6!uAC{}Rf3qrhzY1fdzS)5|{PrG9>4bEt)(-SFs9JFUYDOHz4% zWW>ZBc=+t~DV_j4ZhovA#^}8$BD@p6{rf7j+MO2+%I3Y#oDCAg1!foEA^@fNYau@MX= zXXbV_1Wrg)n^|T4aAr&1f2XESLq_Ku54%a<3fLT@#f}G_S)TD(Cabz|p~sP53`gqY z9W5okybzH5&LMUG#)0}qL&rbt{%^&MMZWypxXxCuC$4JE$!84C0?hoA%dX#KJ8gHo zQq%EKoM3T|`79Byub~VM9iOjO$(*)Hi1UrV)iq(CL+dUVi{L4thbCC0tmoZ-E%n>E z1$P>FGqZ&%=E~kblWzHYM>B)R8;Ocmww=LdL2Z!Tx{xXS9Af8=tyGvkDC&A`VE;+ePRcBu0kSV_D~bh*cJ zXwj8={ z4^8iRGFxMn;TemC&!b#x6TJStZCKD2J3Bhf*>Uaul_EAXLKjTuJj1v??*~Vj@m`3wVFrQ6MD^e^=#Abc=F&{(TOAbg_+yp!Yq~*|6sXbb6dXX z>6|?az4wG~Neub-^I*s^_DFk&7s>|ADhrO;R40Ts9-D1ooUtH*e(E5WcE7#`u`Q_ zhAT5#uLOi%zjxGa4|gs5DSt;%z1E)K5^LGcf_Rpi>HF?GADBEjth!JwCFQ?5n}J#) zW1xxRoYa6z5mH?yFZVs-kbA7)!rAQ{_J^ZPV$sDShXZmghZi19u#;hPe(Nj{!PGI` zh4Dd}Q19odwju&XcCVESc1TPUd9v$nzaqQeAFVYk1#FgcDjwBn834$nM@1?x)Z!2v}9Nm*x6c&CaWIG zi{R#w;8WvftD36LlQCJfJ?pJelgbLtys*i#pKe{a+{?uva7gMN;|-Pt0bDoa#rDM< z$^37l6Hx5i)}$_3;?tFs*~Hu+A|&JCG9i?~l%HMHVq;>Hc9*bF#_6NI6YMxyToM@+ zPB5%tEuB#N?gf?{f2(YvLsbT0o)Hp+t zK_KGuvAL$p!*$wxUaB`VvFuUV^2N(Q#dVTq$(_v%4k3)rOs8tET8H18`tvLBgxCaVm4scPYUO4DYwkJYry4Gp9%XC?i*{ z%1(oi%QmubHMQQ;esnu>qT!2WMzTtcu`K)|e~vj#PBiD*c5PGAg@{Azd6?VmCzL6! zKFOGDDrNnD*==W8Hoi4{Q4d)8ex@c*W^I^z$la9tVu!2arl$@i-=7QoXj`SNAz0Kgy?=I%VFB$nwZ#f(tb}|?hDlq5^87QoL_RpD*uiZ+c!AgW@&71wx zHG~rO*^4Yrm=imp;o({#PNNlvui6+mEN9}0@@B~}aqbrI6^Pi##40tz(B!7nA_dKJ zd<{=@Oju4hEeczrqAxXHY=iSrvlSe{`VyRzCi0%z^u|qTg@EG3<1up@-gk**X)HL& zT_)Jr$|+rSm|Hc_K;e|o-G|AI#_MuCwBvc0Uz+aHoAKq`E3ccI_!YHzd!4UeaXIL$ zrJB&dP{G6Fy3<#A=Kn{bW@T?U8ss|?66{1ZwOtz+lzdh@ey>S*K9SRI%9?9#e@?T7 zPS~XVaSfl+FOjLf{Y9^h)S9Xkxf$;nK3T(})H+qP`5cq3@?;)`gckk_*$hjqysoBP z{C{if0*e&gBT9afH5LbU*PT@U-q^7&W+AV<)P-Pkep$JvTOHeGvN!VHD>%??w9Rxo z|1LAeqGhZ#mu{SUUNoygnP0}?!ISk*Ry;V9$`SXCnQh(P1#X{inJOqLa#U>Dug$Z| z^u~IoipYs`f1g;?w%f|!n2xXQx5w;OPN_%Podqg&8~Sn!r^gFCNGy55Gihmq%vFbs zpWA)=(q3;~qUQO^LpfxsI>W@dr~Xe{kS@B@v8%cMtHJhFHxI0{D!pw`!J*w#=)~ZB zrPb@IrP?Qjt^Ze4t~nDPH0vibgGBg^y+%Bi(UaG_*~}R;ef78BQd6c>J{DuE3vFoJ zBACv!+w#%0#PXGXKQA$AL@y6$(%*gJ*2)RZSJE^a1h*E2UH=t*Gi-iR2B+xK|G%$p z?Qkp3Ad=$P^*K_J@CQ_NuwPHBE~QO_Ez4h;ToMHVb-a zBgdLlbDe|PHX}$(@M51r7CA=LaE4G+j*Kn_`Dm)>$`m$VIN~Y;<=aY4p8u{Wf8~dUv z+!(DMH+(+AAUk(vpO}cip_8J0Omcy3LYzt}H)PLqAKP)2ySw4&Vn#n!cBd59MiV*C zoIa+vQHK~;y9-Y4=~CkUu+Uk-vV(;sgZH>|w{^`UcTrz=*9sF3FB4-+)mH^vG6pRb z2^T#+iYzmbX=*j>;N)I-=hXE5lNN|EZD2Dz=hx`#9mM%mlx<;vA=`aH$-EzJYZwea z`0X@OU@N%XXa857@y?PNI@XH?GgfqTmLEw@uW37;ej(`p{O3QFC5i(Y{jOSdoVV}$Kh;`us z2K5yOT6TXs&Q^awwKBK(x>st^nr*xS%!0j1ZC1;s-!{m$`e>5n{+IK7#iPLf@{~ux zohe?EYD+BZt~{>1Hu1RKI_1T0GO~)oRN44spK6?|alho$ArWl%b>TawLq|(i9ywW? z!7gv&6!w1Sah`-1Qrt=&L17N!?F$x(TT45U(@Wiry(tH2^0%u6yq%c;M z-ZhC0#})cl9zN+QBD~x5w6{}-!iq0Joynpr!XI@8+>%OS4xVvnt;u5H+gZ=p_vv^` zmRy%ijp1$B(CuLwU^q)yF8<*ZGD3l=geHa~9ilur4d z=l`4I_pvaE%~u7A`kNk^6mOWd^TM*mNoo_ziZu4FTyt*q79X}BWuIg>1QcZyd=8Gb zsgkHa^x9bK*M*I0>77R(7Flu|yqLbBVnX59r{&uO=Ei=plzi}OOK?HiGwly0`ktq_ z#I7|9iQo7Zui$Vp>yn_z7Sq5qEdAW1zhJe% zvspV+4}NkFopP~PZsGOng*|J&H_4T3&%Y?Y^J;gy^SXq4AJ}(UGYRCH+*IWFSbgJI zPvj#8(MdB?x1=pB>TuchaFLpo=COTl+1CwOY?+FBWj>^GEHr%1zvBGE#SWS8L#}>Q z(#Z3Q_i)v}@Za!O{HsqJBxdk&luVuCZRdF`DWd%LuN9&8@Aj;ad&)kQ(@(|xV8-?n zoy&F$1zfSoYMpArI-c#@9qcKn+$r~LM#K3-=z+m*%cwbxvN>&!od zsF{jT>H-K*rauKGY@XrVRUw$ zwe9_7eOmhxgoAzMdh3&XYA47Fy)N(l^HP;FfGJ6Ag7($fY-{_j7`Xkia51{^>h;m% z8P8`gwGB_7rSMD4wA(h@QuhCKJ@Qa}wW0m7UtHrPSoZ6Mt zkL_VtYmu_`$ZJ0y7tveUTYkJ2nc>-?aq{Fp|E@*J-=ikjc_j+yv2mL*Fd9B!@LqXW z|0dk?+mG;Gw-W-H#X zY{v)XC+m1?Qn(5(JZS}(0fC(#>vNg)m+^E@Eu`H zdBeTty-v`<)Qm?87ha0(`@pn9(JD??{K|hn{d2y8=ln(O7R=?-s?cj!YVp;t=wazd z*z`ej!3Q0eX9Y{X_3#QX-!4<1E~g+`!C*e=ola5GUm+LAiV57#@0cNO*PPV@7Fo0~Ep$>@lJ<;Kcq7M~B-S<# zb(TcdH4YsyDqIy8{J(IEKkPH!6)0G;fJd7l=9y18Th{HSSFumnq`M3!c)ebDMQf)| zL&`O-g-g7)?t3qP@TtR@kFx6@K2=)F@FZ2p_8{w*7fEXla77&xTISBgvPf|CvyF8h zwR;LhcDMudl+*p3BzIp-`|{%dj*Yw*R%G(9G(-et&$y)N_UWOV8+YArzjos{$hZF@XbeJGZ%#080)z| z4E*A-`_Be-fd-a6#|p;lNc%aH`mJXN*@&bH|ej5{au zE?TJeiOI6he@Se3NGjFEp0gH+jS z##@}XX0WhFJ-cX?C>+(O@5-WRBWS9wAjVaq-@%lgkAixrGSmKyMkceE!eT`4MpHL(DrZ`z_9&3--@D^SFsotWL?YM>mbb$%*}c@{Xos z`&XS5m?RMJJ%!OAeXbERdzs?PZ;Hib?5B&8T(%zO+;Kp`>A}xAnwc{?N=`Vq>`^+b zm7*oWVU^Ywa3)Cb=w`utlY^EovY44*QpGG-x^c~uQ=S^k-pqPVW$N~S_+4CumDr|+ z3%d$fut^s=|BZU^i)C_5o$Ik*tCvn&pym8PFuft+(?ZdCIh?nWo{2nRIhVv&aF|Q$ zjoqIq9wG(pn~{ zvvux<2bmTQA)Z?peI8#kI~UHs%yfDpoAkqkf9x>^&0Z(IN=ROb+ihrkZ6fco1N_+z z#%BLNNB(sPT)v3ezvsaR1@@neVns<@Q`$HLPMS+!W0pyr{HxWupiyhtniroOS!%NR z+_ZJn6SxmHhANiIo3NNom}VWMG`B@P{J%-&Lea>L3q?d+<66Hm#(UIm`(&up#BkHQ z{TSb*UjmaXLUV-$AMmK~Hz~0Q`v)7sQohvJf^#eQ5ZWYF!v+2;Sy zsnp_ds<0u$^fozx6iz!m=9t{a1>b^AuJivYh`%r`X_ty0_emkAg}%#`W)(bVTj0bY zlei#=k!wMUYg5uW9VhLc-b$+`-J=hAq@DDI3rhkoZ8AybJH{IK?!|aw4i6&7a3LOCz~2O_DtZjQ=Sm@omnUJU7nNTmE(e|e1$i)INPuY zet!2yZXsuSg0*%+L6?H@olGVPQKh_3T8FolhIiI$FW`6AkX&bO_gqNuUKrb_1#Jfz zv{HV^a{Cn@Rj*{%darhnbrO?o%c4-}Ek61xQO*u2-3Q+O=%~K+z+FE5Zn6`s? zufv8TD&g@GxxEj2H~wGv_}Nx5K6lBI1>#>qkM(JamW8(FKhTxEqq~{2huqHG zFu!T%g_)xkRjDmk4Eg%UBZ0eWs#=`$gDQs8b*#rPHCV|!dh_8?#sZa>PQ5j$i;7DO zJ^run*`~%agICih;kUldq)R+0;pg=a5hi zqesj4T}9#gVjJh|tdQUHP0 za{`OwCyClcD-&~ACwX6Tj=eE0`u_#-`+;+(I;LwYY)Vqluw~$6;XNP}*zu%k`s(DQ zIoBHOSc)1L{!UozGpEd?=Tgi5>;9rU%jZmY&ui$qmE`%GKOpa&$SM<+p6&Yk0|I|N zReQ%+TIIk{rhcU$()tPW3fALhat`XNlos(nUVZ%MRg-0ENmc$c81(it85S#wY>23E zIbJ0=#o?E$Wurjcv`-5|moZ*i*dZP4@F$SnWg*{>gR)aH*cBo?Y#docCdB_%yP3na zVZGEdy_w$yBBq{NS2Q_sk$CA@yMz8gFT-|9r2k@_qcxkwFFT(jm6eBue-o2%jOm1T zO9db0bNGF z$ij}p2I8NVdO1##npN_^=j6kJXIs0c1Tl+5W-u;|Ym!K4i}o5k4zu$# z{vyi36%d$^eC+9IS&s+CJh4sXhcdo66|qk4_I$VDK5P2B-&zxy#ZpxA{`~(d74_Ke zm%@hpeHY`ml}kSiv}BcBBIPJ|h*P8~BzWPdL@< z8@d0n*lZI_@eo(NAaF%u=6y+>GYgf?TRHNC`?LjQ8`H0v9#M*Ek@PxX*WPk4`k2fn zN%^=g7N#A?co#j+OSn7j=Ckri2P56?N3ES+c3w~=bQ8mdH;Z51`Y5uX^`J`G9@f;w zr-F~JUy!0va;Q8|)@#BcSMvsr1u1q{Wc1#w75yp28t`ph(H)Hkrx&-1u!d9{TZ)$- zN;$-N=*iA)mqZ;s3y)P_cB+oLF%6XnP2mN0h^k1dWs1|K>-K>u9$#jDy(J#?|B1SMbdb~H8@J;ZvGh8A zIcm4S%=9MgyQ4a|l*YR=m^ryFu?oTS_kP{UH`#B7=Rq~L@5 zM;B3sL&t+Ih7<%`7oH$-eanQfLkSLt6GDD+{#vl$>fsM=j~x=ktTrF9Vs`kMm|)QG zA)&#bNUNFQ=p=^;-wnR9E;uloxhUb-#SK4yP2_nJus~stf`Ea*1c3_%4}N~AbuhYM z@a>_vK?V1P4PG+*|Ct(o8mpf(md)Md5EY~l+gtmG>(-Cs>lqj_t&bfRzY16`{7G>F!`T+bt^N`( zR_Zps%Z}scXtCNkRkxt*;MRcu4z3OMu8HXh9ZSs;C!XFBDUxtu$HOLuTa$g03pnFA zC-R-k+!ptX@xcpufs*+<8uZF~4>Wsq)P4{)TtC;~l&0$&wnT1bfp1+-$vsNFT*f{M z!u}a24Why|4NR``2{S#s6r!TK_yD8n$_59kgpUgX5=4G5o#K-YN%rFAoU+7$Y3_+F zah|&jiWwQVKfS;jE!8CyB|3-qqiCbf60wDK96FUuQtStoG6<`mQecVQab}t{SEQS; zoPE%W;6C2}Ck;f6j9YF_b>d-FztLoR#Hd3@Ltw#i^Y;@r3Gs(G9A>C1JYzE3u zZq|%DOS#NbB{#$|C`BCTognvha}a~|j{l!poz)kXJ#bjFcdNsiYSxcFysoX^&a?5? z7&bel*`07w&sul#)O5DF*H$cOVOn@{?pm=g9Wx6XT$WbqB?V5?ld(}}FHGw-KF@FU zrNW7kX^M&ubEM5i2PU>VD!zHAo{G0I+N7@H^<|m)+r@6;&I^KBl0OaFJyJCbCg-UN z9Cy~?__wK1%|UlsoHO@K2fdAgaWNNS`8yJv{8lWOkimVkWT{Z>0kg(~tlsw+*_fm4 z1m@J+@7d8Hz$MHh#_;urj|0QYw=!!?xi*yF5WUnE*y~xaGR3vFxb2~kX@yJIsa3`g z1jFZao33`VV<=c{xKZZw;dQ--tDa2oN)i5=12#TU(7sx-LA#9A*TpjxCZ2A8yVn1GFah~|c=El_- zYI|a~vM|5XE0OtJ>tMKZvXg~@d&6-DjvD=f8=MZ?HpttaWSP@Bn@31NNXthc_n{PP zYes>UK**b#SV5=9k0$UeysODAmLbfzH{oFT5kILNr)48%2-=kX_t6kLzOaRhJE+AZ z)rmpnVvE6?V6!g=)~TPH+{U5g*!0*o-Ii0y>8i_tcK$Y}Y}Exv`Qwg@3RST>3l?4E zIrX4{Wrd*-_Xpv?EfT$wa!-V3b%-!`tYEC-+`w)WIf2plAp6;c=j!>g&Ti*hGI5AORHH#g&%M7 z$_+xzV!W;SUuPV?;uqi=D&(WK_KLg4W5HwTVk)!#NL*mx;A+a-;*eHg=)m09)*w5> zTc)dp(<1VLYg6nSqnUSj?{Ot)g~T0VmM~fD6#K!WS!oXf;#%cuM%h8_lnQu0G|W{$Ux;I(mV3yp}y=V3c_q zbE%u{e%McO%@Ssdloe4yOE($`-*M1Zdl|K`$&F|0RR;-?jzrEToK37TAW zYxP%Oro?>N(H5nFcU_HfKu$#wV^Cth{;GeF`Q5D-@Tc2SvrBb5#Owq~y_dgZZ*fB>Hv0H5J{n21? z;>X&o(#rOwO-{yYAN*OLsUCjOq|{P=r6=};I}5jrIM@BwQ^nUBZb)s|q?5pz7Wejc z)RZ&Jcvh!u{I78LmW;-A24<#$>!xzInb_y8WKTWuDR9c1rP6a|u%_;Om&Pi2{P`v& z)~LwkQukY*N$ps4ewl`(!|j>EZ$rGb3^h1w!X1uGYLgVdA*|t$@I`38;|uOGH!Y4f zMLo;zRcr}2BWF(8DJxukO-wrHAb0hKeXFjtc>8f4iru7eJ0#&f=krVFRJl$~$-dHJ zo4BH3?sDla#@P;vbw?Tv%oq<&FLO-$xm4U%AuLQPrn#tE)MTT;A1;5_L(`+a&H1>C zH_pRj#rB}J2egH`E?obh#m8xJo}npN$oz&=)Q>h!$7MyvWltD%N)Bch9B62_o&MqY ziWg2N1FH6){Plvj;!lwW7v z54*Byqr16{QZs9(jl*V>*Afk#jVGpRKS|wpByNq{J66v=UtjkXj;HoCh-*wV6mYOG zd}zSGD*HfAs*O^GSc6=|lDyZ3Db2QL)HbeF)!Wn9A*$fbbX)n-#DLOW4V?d^k2~Gj zD>CE6HlalJrsZjjkNGPmu>IC+JQKKl!s5#>ZuZSTF8goi*QPJF=f0So)pzn@+vssP?gg z;ojTavPaV%c9!d=eTb~TASGlNQg8G|Gau+_v$)^9kY?W~$2+|u*u8M! z16POgEbZ%VcUvm2f9JgEu2xuTk@+F(?H6Ya!#d9dmV*K&XTI^BWaDXasGJ z{Q4KJwamizT7)((lV%f%vrAyTX26-S!@yvI*4GD&j1SwTw$(A5C|cc8!|lYqlQE5X znw(b)cjXlc)h2E^0ZGq`4BH#HbrxzbR4|@?g8zXz^So5Se;@f2)j}J>%+87PF8XH3 z5m>vxp!~LkjfG*s9Hr990agbVFsxVNu@B7Y+h)7*ftjene}>rwe!nExJf;d9RL%9>bhV&(i(!Kkle|`={7hD^XGV&lpLxY@)GiPZHBfWszar-P zuv6(tQP~95*qyHb8+uoIsBKPEd~6_+$lB$*VEW7r35&OO^&F@%dOjiK2IHw0mZys* zeN}SeeA4&Vp!G~qYT-u_TTf%2#=@tK+)Rx2QP0`l9O!FfYOhGMIjJ0vCeEUZ3|2)R zB_V8e52Soum=h~2#Xih3I@)(_lII)~u7lt5@35xFWcKxlhj0~k${Q}8<-nbjD&#=6;5niDQ*&h~m38rev83?N{DEwfaeD{dJw(EZN zO9Q<)#Q$Gfx>`}-Sx}n1Bh&j2Lb=-}n6D~b)ykgweYQPAbW9Ov`V%Gbgc)wX{)caK z)@hiyINe2|@jLTP2EK($d$SZ&^upzjR(OSnmOVej`|4}5&ngc6jdSe|3rI^EJrCku zJb|NjhA8hv)_g(9>MVWhf@!N$X8cZ_#|)f-J3mMI8}KIW}nIY)jn ztJ#7H%z->+?#$teT(RL&*2awb3mUs7gdQ&xFL_v%Ymk|}$ZAu#km1Lkz)r(UyAq~# zWzXPZ-ja}&a%ts7!*#zV&I@ETP&eVcwNNr@fk$dq^~FyL2OjaS{AI#r&VEj$TJY!` zHvy?wgNDZqJ*!>v&V63Ayh$#u#Ba7jec}h+Vnwd9RjsOq6J{M`=ibr!qM2LqMa2g< zYc1*jiVshPFgJ^aZ8c>%$+>Am!q%HzyC->TJp$yFNyrLH&@(Uet69MwzpK)B#blXib}lRK+>L%#LRK=Lq<+n)-!Xy1c8hi<3+v{h z7T#|hR=2|v4ulI|;Mn_V?Ii{~mW^yNlkCSrXOKX?`d>sARWebjcwD-!!3oMcMmL zd?K`jrGGQGco}D2m?sdyyy`c{x`*;>8s(a|dnIoO-I5@5ykXJqAb!`KOpZZsTaHtk06=@i&KIApiX8wH2q_9A* zX5$X2wnH~81=lZ=D%!U9)1&`-&$5bYdOBZmv8zY(t0nH0Kg=Sb5|z7zefkHz$AuyR z8|;#AG^|!(DhOP&XhQq050({=Ig2uQvs~iW2u?0P)4uoAtXIp~+{D$a9_h^%WPPYA ze^X4jW3%weuZK@t9WQKltX#uCuVlrI)AKAP70kEId^LFmbK-&Rg;o!KFuy&@&RE3y zTtvxlH>b-smZYt+%O6-zI=Io=fRp*9dZ1>zYRP0?>I5myl&>BT&}v(LZTmv-RP%neL-Q1ZEBaJmKPrsA~z$VaF4`%dc8+VO`1zwP%}BAN&5^ST=LYMPbGE zH47xZd^W87!gVGw&_1I|WWxSnL&h^~@~4G(R2mA}3f$#)^_9vp%~kB*TEU*f$XdH2 z%Hg2-w$;h`vp8jTO=i64cJNlJ;V0dj0o}}`l?=lK||sv;iXO@9vl9%@fz?2`!Y|Msp@W>%c(N` zyi_com(EIqoAw`08caO&YI8$qTK3CI-on|56Q*(;6IBkIz;WL|YPW(<#%~pAF}CHK zf=rw>sxFlCTXV7sUtqZCc0qUZ&I2{lsvDh|uJ1I|PSjQ@zmq@xVw&kh54JS|H~to$ z5x!-qb6k&sEk{RBQ|ju)2Zt|Q5z}9FPfCWp=N8k<)fpBW7F{ZyX}QQ!(nM&ZBgdY{ zZQe6Pg-aN-&UPg~;^$l<@pcnCn;%E@ip0f+Cp!Y!;%9Zvxm3Jbg)8c#a-<t+y19XQX$$w?O*&l9TW?R` zyZhT*`hwmYhCS}ddMU=wb_l4|1n@0<`RK@=<-QN@#y4g@OS3!XqqFf@q9_A@x#4QI zK>3w-nfYIrO4)2Ul)&~Y`ew z_`aN5czuCfF=rxE`=>U?t+(AgE-0SbsFO0m`21JZ!&c^V9-6TUDs+fWHNUx{ElOB< z#lfu&5eN3E$+p#2JP3L2w8xm?DZ|6-w>gp}G&xPbZ#>%?DelI)_vfMFzLnF+kNL{9Mdf{FCUMMpSG{H~cfP#rtFhQh^$BZ?pD}XUneCKh z-zJcBg;B&g(XC~Izo7v4GNu!c+=c5C^`BI-M<;3R{OIiHlwq`(JNKdC?I+H+gyn>j z^tUR^d2`2Pwt$qkpn2vM)-N$4fh#(XeN2>h@;%VQWUc(>mB804r)R26@mbTLJT)OO zD&$41$}a~2lamfETbGrrR$=+cyL4)T_^krITN8}+)bfK3*iwJ7bTVixNoOsT*Z!=) zDper2S?K@dYzF4%lAPrqnGPBrR86#=;NUsuWIm0+9 zah2xWCZ`FuJPn85Ki3do=XO$F$hC$?kBwntkP3S<--3)p1r8>*6OIC566`H6HYQly zYn5nlkW>(IZftJc+S<<0C^x5zVO#r(hGvF^4XrBdjr*INSeuwy`MO!!X0BJe3TnFFJWcDfRW^^s&e$2?E(ZaNamAOsgOQ^G_0;k|)MF(c4&@dT` zf`trB_8TP(R-`^Z`9r0`*~HqX56@7Pw!QMmD+*sajh&rbOan26y(-2xRf(ZsQR+v@~RVZ( zc}|PBNF>j)!&&jArOyD&Z$e3}UL7m}3 z!kmns>W=N5#h;R__q5+{j;i@9Waq{h#K@k^uXCflt%*UA+bSkgbrsWkl?BW^Cu&;@ z@1}7}J=w;<85)-4S)AYV-$i|9+!LPje(_Hp=QOfS+C8ha@xgV)SEkz-S1KqNboL%O z+^xM~7Q=(@zYd967W6(BRP6D7q43?)aRJY-hO>+UEt08>pA#4oj1S*<(ZX)GCVIiV z>q>_Fv$}+C?3ED22;ZyfVzZ`4aLV(9vH$3%A(!@mblCNp(JD+`DH`t)*ZPoI+@ zv&_ayBi9t653GD?bJkqAwD^ngaSg6L|5rIkIV$KfI>hYR(AO`e>uR)4#!$3>X`4WY z3uAcPOeWc5dW~!ieCIYMPUYuuT+qU5;njQ~;$MNnk~v!@EbR@uQ*eqyxq^2~V@J!+ z4i%vT4Z4i60wQUR(}gNBW@Re8I^rQUO)=R#xap^(cO~CtCCM_w8P~3+@dT{8AN}fN zd0VP~Qo}}Jjvs7l?y<2`<6o&{_=_(0;5sPaDwgwtGm-1nGAZsA8&x(1rq&)+oySwy z=+WU)*t7ZXSmpz@#L8B5uZE-}F=5?PA`WPM&Oy*j5y z_Goysltsh2D{CTV_vmkNV3=HF@^WGC;l8{sNuQX?-1*j;iykbS_g%4JzUV56r)*pn zKcnZ&cbJ{9c=cT;jx5I@_hk`VV)y$VJuf&Zhxf{kytc<*#Udg@?HLYy`|!;~)7YSG z-iGJG%TzKO&OGAVo^)S4ZpG4-cHa{hOfYh|_@RyU>yH+e1FVxBC#R;G`mLXB)A3}P zmWRfIskzr)9P0AA=c81ns<-eJYh0yPDZAsWo~#0iyGz%VY+CH7Z`H~iyQMvNT@(A_ zV{SZqEOPh{C7<%Jx+r*b#&foB7hFVg6j#fCX{gz7+rQf4K$rjj8Eo=GE6y|887*42 zgH>w6iclS!uPypAXH60wcqi(xnYe6eVc|9iH(BJ=@@gTcb4li&r@-!e z%tF>;$%XzC4{mGLD>#HFDQI>dJ|MWRZSvO@Elpg_hc`VC+-W4L$hNoQkVw@<&YilB z{LiXRGs<6|%a-z->sBSR%f3s-?mv`DGBcxWBp9VlIy%B;zhvCGVWPH^+r$3_9G8Q2 zjyg6i+i<##Go@Sdt|#-A$W~z&169L_=0*pR4NST_qD~zuW{LGFu!^r>V3K0saS2!? zuz>k&^`1vuH#nH=m~>B>gcUHQ&T|swcz8ln#%Z5&nA+8Z$sLNXcq&q-{ygc%9kzOby)=_s(gkfB ztAw`qw>0>IrG)e^GhM*Xv(ncA6V4S$RpuZ3A24Zg)VF)#M~SGC)b$vey> z?>Zc7;!8ZNexy&(&0}$>%;)A`_t^M+V*LeX7csr`)N@>aFs%OHHExe9>iah;%;c>% znC9%TMBv}AQ>%rJEA%=vhF55&C2icgYv~UqHonl4?pK25FZNIud7dg5ZSi2qY=fms z=Waci{**B&N~4uUcj8BFg99Aw3#Mhs>~)whJ267N@u6zLgiwzHqxdBbjB3>*~qb?<^M6RMOOO{+J;?n+rjiUP>%CP zpnRL#sl1zq9ON@vMbEk{la7zw@^w~6cV5P0H9dp8Nw<82_8v)gNuKJiHMvA<4bv^2 z$+{nTH#K+t_N$5uu{=G$zJT?r6|>Ms39c(!R^=3bIA(Kk&2e?Ejh?ltEjRzQIvJZS z65lkV`LuLoa;NV`x%f*D)z(dL`hV|%tzedLyuiA+d5UIYq7N1^J$)B6F}X!Qb$ME! z$VngLIk{0&dsIXh?`~O``(Nb42bniKIhzFqKPfV{Y+&Ij%9OC0vuMWQAKuQ+a~<_n zp1NCvly|pRmREdG;tJz9)~_Eau;kWd#?KDZ&$}KyvU~>b#%o+%8j%*AeACIU=&J!Cg1z zLvP-mixO`+TaI2lBq*A`aEa(S$MbsG?@AvhxTnm>3^irA{asZ1%->+cBTufm$~=GY zz`Mr3YtjXi{r4}+J~=pjNv49na*mnM)TD@+LaCz4iFe#m6*h(DXv|*2&tG?5*74pK z2fIEG2K|Vf#t-t3L?;<;n3(S2ThQyr^q*BFlzn!N64&zJ?7EkZC(b=6dOvl-l%q9I zSX3-_Pkt0rt#0_*OiR$k`d~m=>n#suo%12HuW$CeIi+`_;Q}X>wuO3W5fgYPNXRNO zwP$fnQ<%Z(-L|HfH8_z`c=sI1f)$G;SuG+C2ytw^tzmDZFi)yt&0$8NzDnDi zZQ|P~;kubQMzU?yt95U^jegx0v43#jQw5XDiS`U9mKh)Bt}tkCInkRLAto(lPuMF(0$>^5YvqLh6jW=+r@T`Vq6Q@ciEHW_jmG6n%U+l%^k+w|H7HGxUuE5 z!q$XG0v9$ox^+5;SuzFwn7HL8bH|IBF29<*UK~~wSY-65-6~jrONZLD2G_z5b6@Rj zZE;|Yh?ua^gX!VS!;ddCY$@EwxyGFB^kk_CQ#uLTO%WXf&@!c z2&a;;lE>yL%?BMqGz=4#@VRL;CkA#_Fg7bQ@EJrl))choemE-9wd_K%Y<>x|f`)TS zMiD33#);!cn3gow%dC+a;!jBv?`A*Do)ZUV&&{TCqpd?WK|CUDglor#fl4BJ| z+*K|#sVk@%Kj>{=-H`cHZk8gawQ`$9^3m!=f(i+3Y8vkHQOh!BH2jM26kBQIUC3^H zfm!Pfn}Os02(GT{7mu-PFPI)6(W>0l(0%ypgYIc1s*@@#Cv&hYyI|LB(!%+oQF(=k zh_hKog4gX}7G>!s8OJ`k0KFp?;)_!j?A$VCT@6EvMaSw-9tRg3TDFV3B***Wp+@tH zjocR|{YakpEs`l`gLl%7&chWQ{|_9w!?aP~a;M`Dr8y=}i6@--Y8Y>FY%{NN-LBzm zli2ZY)l#-OlIAB|bEI8VD^|9AS+%%oKlcTJUWQZ4E-k(OQ!iwL;Mf+$&mbE!ZwBGI}QSoF79#oT4NPQ z-z(O*A9~9yT-bJbhOF4OBVxkgoii*0`oA=_w8$(jek`tW!T!++rr*__DgxfYTP|q+ zYW3Y?Z@p=uf5I9=6V0T|m0}Z^x6kOl!0D(lgY`6{iF1L=(Ov8A9_aAp+LmU*;_KWP?NveDtLEbG~({7H+lwS{dhjvt%j(eaV}f<)tz3tOjEc}oA}=bJOX znR~88tcJ$ykQ)N4+dgr9ZE6zzFn4*u?0|>~lHQGaw>m7&u3Od-^nJn(pFkeZmO;Fi>n1;v|x7d;}&sd|EDb66CNMRSP>a%)a{(nlp%H4)_{Lolfaor>*{*1 z^ZYnGo#|T9UGEy-8@{XiRa>>>fA&`$*zd=4XY-6unUZd^84Gq5Dx_9(tZ{AgD6rXK z*%NIsiP`fk@6NM0aQR1*HplV&V%-C_+{Zkc z>sP6EX|I)<8m%gDGNDzS*lMYCayj`Q>Uuq0(UCU9o6PM zK_+P_)_TDkM?(|2MEgI4YQ0Y2+waN2morOdA^YJk(rh=k=J7?%H!5D2Ij~WD>v-mQEcP&{%fbV&MoSKo!N(FqCZ&G zG`4#KE5*oRcgPDG(}VptFiMZHmS$ z%e_2?4>rX7xXTm3YI{t4{R3_z!NfT-sW(2i-0g^Y{-^1m!{hq13Eq}W3RWx;92TMT zIN~{4{v9=Qb9ii;!2FeatN)o)?~2uG@18!^u(~9@xY+c0)TeYO<7Qz4sf3E4r5XZ{ zN;>4W?d|1cSMyjeWYIBM)?4A(x4frk$?E?@M@SG(t{Qb4OCd%yz!+^s7oEVZArOZ|JT zhs6s9-fW|~U;IbcGQP>+c-Y8k`=N_>r_iTV{$0`0hXeFWg|ekyFrRi__9vNb(u&OW ztnBU`uUeW{U1V$%EO0(_Gre6g{d!=gYKGKbQ`Q?V7`JK8Ij`H8$!KdBq2;4-sxLEh zbphAZ6Z-WNb&vj2KCH*qEXE_Vp*>gOLeCGjPro~o7QU@+y0Q2~`~Ta&8n!Su-aFONq=PGyU))kTdo-*lQK8ZPO0I%KoMhsf`CZ$O;>?0PEHXyn6tdIzglNaGpd>~l-`IL|k@+|P9D&%Zly z%HhHlXB#=A%&y;T7T331+L5&&qv^qqe;dDsnV;ZceZIQYE^vQFrDKdzIRRHer~ub zxa488pU=(8*`mKTFF2wkymZg8&&TK3g#LJIG(&2e_0g+an5|y0_wI0i__3h;Q4ZH8 z)`EDZir8Y$%}$;3b<0HOgpf`8MxJXLb?Zg< zG;^++f4h-^u`7W8*a2>3er5J$tXX>+Tc*1|zft|C%TDd|6Q6tfi+?tp<(x9Bi05z; zQ{aq_&K)ZqPPSf9|7&fyrf$WgOZ8TsOmnB@>pgB`HQ3dXx8wKT>l3Q>H*EAMus@Z> z;o02f*t|zYsP*M;{tcD?)ic-XtaaBan0jVO&FrZawi?oP2Ar+O^343J6fRVL=->5< z@qae^|DEsG#>V}37YHQh6uKHf= z5q5Hc$dOGN%^!HuAFws)%xLpq*n0Tm-v7*^?W`Mic&bQnDsK*wcr)vgW~q`31Ispt z1qO;dObyH{v_u8e*$(P4c1SU_oixtsvnu0bo2!yx!l0p0F|$-cDd>$34-dm14h0#3 zDL-`-K12#=xHPfIaP$buFerHR$@xs1#KbabQf7*pnw3PrxnrMhKD65S@t;{|W0fJ7 zPT-D81p$Wd76NB%4JN#82{aHX)A|3#%)iD=rb5R2=}WOExerQ$!<+h+S3)t_0J((^;k1QOMz&{ z1Vu4bQOjct5+6P|^W>O37fG;UJli779JFxKXN5=SmG~s)PPlpP!ik-CWllWU%)rpV zu*uA%<^qG%311lw17qcH2OE>s-h46;a9ABC%&xF|?uPVbCQD?5e6DJ3_gca`iPfg^ z#!OHQa`IQAzN&LLVHh5=Rs|zLk=9;fyx3^ucPmja_r}nSe9b?Glo%#^#{v> z156Bh4;|{`E~Gg!)hh&uRNY$fMM0RyL|sv!?2GvUjVTPzoh8+JJXoP?%HTA`SN3rO(^iH8 zwSavV1_ydhur?fFjMI41t0|PEoWRq&z{qof?4rdDF|YqCw#_oWl<~lUPjrDnv{?9?HRwwwU!RM2AfYliqq^A9Y&3sXlF2&p&4+k@6Gew3#t}EnXg2e(1s;jbYmLR>GRZ z-~JH_kbFid`&`EuSEM?#iWy8@YnFUs2om_jGhGd!CzS)XpzQ zA4{CzW!K6@xEe6gsv!8+j9%w>BWu8MLP z`(4P(nRnJ>?(W48Q#9Uu@JtqZd}vwP@xxL->^n3UJoh{yWt#Bj^%j#8(pPOX#Wx!S zF!?ReI+D}jp7?-?IhkP{%Q*)H-k2-BDj5!*smuN44@{YMWbrC?r8FT9mj!Jr$~W}< zzq3l0S<{J=X;a&p24;(YyI8mnIWp*8N#jqv?66(q!k+jYx%DDW54fKtHY`}UG)IPW z!S;3A?Rhg;MP3H6i|$fWkUe^!F+t)X?@j~$*b9#S600YD?yGQAxv`+UTPd+pYT-iZ za}RVHBp8LZxT>j}CAa!8M0@{uv`p2eU6}nxH&4|EeziOvaVHI_mvSn`yi1dWdLkwW z@h-GqdGKAQv_$Ix0Rw%t30_8vGtNqg-8fJ=N4Zt%_C5YZZdN%q{8i_?m(Jyw;N`oi zVQS(d_V^H`O{bQ!FdDs_ymndP&Sfc&t=%pNtKMonUBcs1dfio=>5Dp!_T|OM@ zT51AsQ(6A^+blS^RcX@6Xa~1BWgjO?@(I{yo_J<=p3zY)NTK&yq_X)6Nrr_10o!^s z8o6aQ995S|@lB4oqhny847Y_dg5BY(>im3tXIO)>AMIdDwXw6bcuSkfRjIq`*6 zhHEP;PaD&}q@F&xiPHKUBIdIuv~vBrGG)PCqmpGadkuNK8hO|DFUi;u?5fdXrZq*` zfE1#@t?EE3voZP{{EbVZCt7utc>yC-* z5*ad;st$>JZa5UE@t=WL?D~vp*R~vw;(9WX!zV zDFw?n?|RBI)8?AGyn~VN#l;hL&eV=&&$u4R@``&>;YwYV&n$Kyip{5VNUZP4VEXtb zf!9Q0vJ}skt=B3aw`C=2h--9rEK5=;GqN<;5{yl(hHMjB6&g3pJKfm7g>CzTjqm+Ct{!=Gjz#QeXr`%i!ER%h7j4-mC#QM1 zH8RgIm)&wCu5kXwvq~H;QuBpd{);a-Xl>?lQ~Ec@!6|>3+U6a2eAq`RH1EfTec~xj zoU=R+Xv|-ut@H255{rKaBWEdW{x_|GC$H{MXTuuCQkaR&uiiw&m0QsxM?66 z^g*=o-2}tOOAplj=v-6p(GXR}6=ovD(%tH_RPR{D>GKk&Ixl~0n$?!~bV+x^TI-c=)UZ&%qd*&sH!eho-;3vBTK4@%fhu_Qj9i$z3)T)5uw%a;N&=%g2e{c@`g4q?{PN z5~p!V*L;}%{z2_Vu}AVh&m5fQ%NBfxLqG6Vqv+|Pvy3Ma8-*k}-Y;lqXmGoedsT<^ zBrBWeRF{6nP*JJ5o}2-)MTz%Uan6)1@NiOyoSM+XKV^2=gr=)9eR3y5e>V!1DIB`7 z#O0EShjzw^D49!dAMkoSy?an$rpXL1HjxCUFRd&+AsQlwYS%C%#`+#_@w#Ri!Jg0@ zc6JW4Yk*8(KhwzuW?z2hjW@nm#(I1aI34T6X6nf0aw(z3(Ny)mNXAKv|0#Y~b_yBo z5aD%-{Ju0k%;9iFOxU@#uKo|Mu)Mj&_P}lGj~4cd8y{sQtv!z|b3H5^)8?@Ds_}v; zZN9;d2?@s%u7(NrPjNkSC*%Chz;jPZd!=LK;x@z!?s?!pb~+sEyp(|Ie8qY5OF>Jqm!lOkjxFX4wcrhsTW<7p49JA7LirfmzaO- zzisnP$tDSrgQ_3Srk40Bz2#ceI%V$GTe?-=$L6+ig?KeAxD>yG@%-NtGKMU3c^sEL z?VZ;nqAqeYD)oSR#96KYkBtVLvOP?BZ(Ng0eH1hfg~?t}`P27m>&4!Jg$`@NT~{`6 zO9bAz*yc8g^XA>N9Ae=sekZ3zo> zR6^4=L_dpMICF76_XP)ul4~xWQ$xSFa!4I=H<}WZaX?1ONy~@LQp|C#?@|_%)aW@e zaY<)Sn>LF6KiVMkV_OH-#_v&?4n0y>=>+`LRu#cREIg9qf{L&Njo- z)$FQnr-Mh_0oDfQuyf9#KSbFg?(T3=_BLZJcVoF6*=v2|uKJWmS}Ki;IS#4@^r_Vz za{JV9>O%CMzuZYFr|k`%eSavEyyk$ZpQCPvu$8FB16QqIg=LgBI?e{DXA`#{v1_(b8zkiCUciVLOBy9OpX|>$S_XnmO7)Mx8cRAqX$=b zHL8f*3^~%)w?tHBP8Pq4;!H8oBELrI4GzpU&O9tmE}w#}CkQJ%@pZ4fXnUgO_xBb8NY=Ml1s7T^YshP>A7@}`vtv!^|Y9*1dQ&^j+ z$=TMiwV!52m_Ze6Lt96s~n%bxv~j z-pB7bgLhtX4e&hZ@lx|0M~0wV$gU$fyHffRw=zuIr)k`BP%q|?j6$kT3&#)1BVuoy zV?MH~&y0U?;nbWvXP@5moqr{3_L}1rXPSdEbmUZT{Jy}ri?Qw0r-c$*Qjd$UWIth0 z5b@hG^FXQLJNp-RlYcgAFJpE+L~T6VImbg~uh-1=xKNXP z%Fp|PMVPM0g`z8OGYg-dx!Ciz?1a0AQ&#|EkYBUr7AA|BXSEMpFD+?!w~Dc>;-0R> zVzz>q;0fAOK4hshbU06VX{eLxx?^2Rr@mg>F`Yv~@1}@Zgm|gt9G8`F+_Q~!_D@c~ zmmL=#$*7*`Ia4ay!P4(AB`fj-Lry?|<^gq+8`*v(JQ0kCUY=`nyfo+DJ3f;+eg}<~ z=_)Q>J88+ZA3i5v^~{>uS~G3QCAL08-U}y^p4VMnoHn7$&~HY;|1GS%%1+m7v~8}Y zYz@dcHHSH`s{7B@17cnixE2T`Y4n9XklFq;V~VMvft_K~lNQ4*4HY|%a?J7j^6cdf z1Li2F)23!eCixv^JKlAW<3-IR{rv{7E4Q9;2~pDe>u_5v^lVC;lEEPj0q;vw4)K{Y zE$EZ6w3zB*bI|2s^Ivo=NzoaKSSMuMZI_(;JPP)qV%~Nx1Rn zcu73*HC>>*mm^B^{4LGJp06G{$$Vg3f9}}cKL2_nEQ{X2ccjSHFsYts4(yR~j99?fBs0JBPP^o4nWjdj zjw5fZ!uskXa)LfFB!n(0_KDW#mGm_~ELf>*8O@<{-YMC}*`k=?{4(dc4-fVG=DS~ z4)Xo~a#r%mk&i8l!)_#1Ex4dR=YW2U3)_tRHzyPfj?8VH6Y3@2E~VgToia(F;3V7E z*7a+hOJ*1vdmpk)=`&Mu&W!HRm6`s_lkv%>2CMcijq|-F^)neCU2@kJN|is`wDxdx zNp6Vf>0NVQ`(E)A>}b?%Ijy=Uc;gAl{eRkSgfcqu@ce1``d!MHJLk(k32$?jZKjR! z53aOXMl-5SiB~7C^{=SJfy3sb!%irjNHG)5UIALx%-HM4Kd0h=?2bTzJFlmuD~`zjVjCKU+07eQQoRx}s{1yF~A*6M^d=EIL$lpyI>x zJRJj{FP?!hKZMubX>mATFY@5@DV@;XOB>~~&j*~B=SizFVw`R2qW8REzuNkZb{kcA z-l@B^cL}rK_4wMYJ0)wmw%!5N!&ll?WNgcG^7gKAn02sIsCf0syB!VQCldD?MVxXt zpW@f-a>-~xm4eP;p|qn$D)}+eyFD#F)=fH?np?d^`E<&O#{5T<#7vw|G|gV9&Sbs# zWZaLBwi^v}G~Rq`B;3F-{r^yQE*VtG{%aX2p|IAw!at>WkQ{!%YSbEKE#nix%z>IMf`wxKV(Gjh#V? zQQ*p^+Wqn`*Xt`fT=)=Bz;$tH!m9-jcwYNIc+lwQo@=;-fk8FI5{ks?U1mL;UNP@i{o;6AXV=cxW3p(lc+?LE5;=H+Y``lfrk5y9MIom;Cy=DTJXdl8IxdIL9#o583-Ws{-7W zm}V+SS@wk*uye6aid$;Cb5TRn)}nA028VXvTN}khHlAs4oyHT+cVdspf8j$1nbck} zseJgGEbk*Y#mMID)kh}xd4)LkH2gI1nZdBy^Z#ne4N;|+N^h7k6a=4StzP{9spKgJ z2U+>Ho{)!S4S%|{dd;FXZb)eRmB0SWim63=yBCTa$YwDu+TplUOs0ch@D|r$ulZt8 zhf^C{*EgZZg}~G@y~}WQSi3tuq8LMoohdnP=&*+m|YfW3&K;DPe_UD(~a!s zi`b#LV8hHJkwjBzo&%Mo34Ut|J7SK`?qFq;deQlzB(BOO%J1{hl861C%VvuCyId<+ zaqpW@`hDIv2{s>Z9gk~i+_u=irEFVQZR)RAKF$AF4fRfn^SsX}R-N`Nr(vqIpxC9< zxLewP9NRl$7Pd%e`FJGgmS-&LtI$elu>PaKYClIYS$oF8hhNy)_C8#yq~XEf+|=G} zH_<20r;C$|FQx19f0OlGKX%3WU2(N7>iNLW5HZtX)g^tu4}OkZ6FOg}DOqn~anP;G zyup~d;E+TB6XU{*4hBUBdre{<1bAP%k{I+&)F`B(7rbWT^b;zWX!u3jt0*8Kltv3d&Z>y&6I1$uy@I;gP)L+kD*=aE?kzAd&CDNPKecRU0 zQ&zZampokMG(k?VOL%U<6&91ZQ`q%88y4C=?%?Guw6O8yiChsCY<>O9ap#yVhFm|U zu-6#!g-i&R@u)e;X_Ua4q}w8tr4ak|!Q^ebELJd1-Era2lNQG|SuPG9?E{=Ym3?Lh z_^>XQaBqG0oJ;c8A-32;H}=ef6Q<;>jgR|(dBVq6X>2ETK1tQFXz?&S>M!Oh@aCH2 za6aUan81$@Og}n11Hv2R_g~}N+8)qu@#aDYPfcl4{{g3k%UHQjpJd?pwdjb>4#wUk z6PuD-9yCgEY&g&RVxx)#YnzJS0j9hbk2 z6Kz5V((h=@3!Ug9>JxnEY~G^kHjVrf4+>Y8cNhj+C3Yu8u{2zrVB*}tapm8M3GpRI znC0v&JG3*LrrcAR$gH=pU5I7z#PkD?3$ij)jGu(x4nL#FFD~FN7Q5-X{D&zzyJm#V zUbSO!h{X=p#Ea5vW+k^;mNYe7b&i-~aZ57org`FP(}Vwgr?qmM)TGE&t$1#?r{knl zX!9Js6&%5d6J-Bw3!R{Iz~A!erwKc57_mrN99chM&J2Y*J?6~DgYFwXXv%zA&?Rc- zyZzH92H~^LZE_aP&)*z8aQ>-+oSH`4ta(Z7ybGSos4+R^+6e_KoOqKx&p5D*wNbv% zqCxt)P@D7#huHMqW@E2=uBCq)8ZU<|VtyrfqAu2eufWtor9X4t#JJh5j2oADWwIGe z=-IfgfGfqx`9-P6!;7;s{xaIDCA?Z6RNV!E{5w?E#r`X zr?KSlA@?g67(?P6+O!3mRhVY!dQCWY;L;=^w>u%MntM;Nh41lK%bIBL;vg$~AaliA z2DYrbG2aL$?>9up5#BVYMF@* zX>roX>XwbbrsEI#C*|&L)YMYVQIOFT`|q?zFqY%bl^MbX9f$bb3eF4nH)_1xk-Jyj zsVDN{+nx7$UV1x)@MhkTP+zwyVD_GSS#dnNe4(>;Db7%gzEvBYp?_nw{Sr5~|E~%b z&G}Z4e(U{iZk`M0e4V7qy16!92#|G^mDF<$ozlFp_lELI@kVCZV-IfWNwvxe2(tQn z&t6|VL%ZH|=11Rxj!f?w1>ua8wQ76JrV1R0uwHY{GbZ(8&NiK?o^jqPd<&hwEmVH8 zp4Ew&?Oblqy~fvF{j9GZs5vP&+by%KaB6+Flzq)JmM;yaOT1L?xvPep6ngidEJZ!y19NOGIMw|xG;Y)dDiE{d|YgyL0(fqhL_%tWBh9v*gctx z8xHWXES_JW_=3-|-$c>N&cWkXlgFmqpc`v`^d$?nC45__sQbYAXBXp6u7wgg4I(nm zoR|LhDeqBEd2qn`$pQ(MuwJHhux_+unpeVz?LeK)K-qd*TD`7mpbKGfpdcq8#=9jS<7_KMMqZ z=}o9{|31M@?1D1$8wTABr6+F=KQMT2cwvE>g(K6l29ag$B1WA&58iT5SQ7B%xl~$f z_aRKj7N5GO-_6o(687QW1_iM#%=d$wd{vU9R-Isb*HBQCiI)RQ{NHH-V!mx}@a^t7}VN*r0}RpX@FW~jd?A@QBllnV;g zS>1de7FW+}XW92(LD2GyM&%fkwsB06eQjbKb zI-~lo!%WNJY*dPJ%2QR(#agRgB;HfxsXX}RT{3^gg0))?`)BgR?503=7a~&4(TA5(7%pF(yyF?<~)*H;@~pVMdziWv`x~fn1)8XMLY)-l7k+eUA27X2O(~Q?4%@Zv1h7#mNEZ$cR=<@f=S6oUPC6^A0e!398`BXD*X{OxbkGql|`aQ z4;#7^_5EPJ_MkUyS;I^nMVp(8oKl3`#M=0FHFEiQ+RkO+`_vcP<*2RoH2g}F^@Y~i z6^c)0h}gTnep2D+|4=jRzXO*Lw`)S8n|Xp~>;bu7uG)64sxg{8kF;L5`EHFnq;Z8I zV7D9Jss@37LN~J3c{u3CE4T&PE@FA{mZ{5e-K=J{WB$QUO!Sr{c*QxGXnPu@aHMEF zeCf0$#Q15VAFF)Y#o806;#ePAWcB~+V+wer&?;o?ulT=I{DQLUOqN2vG?Yqaws1aYbI8}=Q1Yfj zF~168lOEPySt^*7aO}ust`p3jdy_@t`PcXyYJK-mZdR%L^M^~t7#a7!Q@AUvz^vqD zBgU~jX#W+KD-Dm|=cFe-U#fOQRKDOu^pgof9h$u6jz%p{-XA*PY1+W<;l{RMf&77k zY)5i=xf0*kJeCYQ$Y=Dh=2ByX!bc(ZLvj*Ik-rnpm?@}6mAd`&(_5mYZ@WmiW13Eg z==^I6S*EV@V;tBL4yq?6u-lk>ij`@oZs*^XD3@onZI&NvOTPY<{}1JkH11sEz?9|F zm~&0!#zFt&|Z?#-uEtT>6tcBRyF(BQ0BZAzSt~raMZt z=hg>peW-jQtZ5X_o|Ov zQ1^iKN8E$@)ycx=-#lK|C8MRpBR4_FZ(++jgA^-9xksyRA97gN!qu2{MK0rid1Z{L z+1HH*7K@^DUUGyj6WjOlk&!2_+avK^EL$%LRx%zx!*hkD@{IPK1oozIl}YOq8b4Jn zdnA(dFz-q3`)`MMcQBZ&p3Km>fS>7DUHAhzPiAH#Gwyr5GyW*V7dn@H&)3+q@?k<# zz&eFaf8iT!H>U9N+wIwr{KY|R%7R<>ilv%X+?%$9JLaX+vKLNAE^#nP798kSwOQ(w zcb3m-3oCCV(=_v{ni(3;%5!~=$hPY7&-mCdkF70Roo`m?l53m0ZYFi5w+XGWRjANv=aWeG*5O99wx}NyXvB2EO!EnF5_e#WixxGp!y9+RdEMWKhVG z5=`zbRIn&Zynblf4R&b{H*tr~!dA9+tDQmn-b&3$^i)wWk#Rn7M`7yL^oY^} znhL4wZwOAv5M3wBkzJAQd@Jc*#SNdmkDZ-Q`7NHjR&%M*>35nIQv`SDId&zzeY9O~ z(>nHJPV?NKabEwwq|0HEtL@D+%Oc|=8_TbDN&9yQUumj6lghC9+>))$C4vhD7gfg^ z?39UE{Bv2m?2Bg6+gsgP8GGHN#CKIPp1du8LAf-xMA+wy0M}#p%QrnQF~@A!CTc#h z;NIs}t*1<4KazSm%a2>z&3LBG_vA(rL*dl~*Z+}cZI1aiS+3q}cu3T*^~Utrh^9j) z&fbbxAebRKd5>`eYongVv_r8{ez)0gUb}t$$1DC-3MO-YzguzA`mhAX0}i@3K0FTje?U-3X~V)$gMAM-E^&zcGI`nI z_0w-V7L=<0U2yA=gRJfFT`h2D zi4bNJ&E?qFq;}$M-VTmTCD{U*4uk%^_y0E}{yV~Qib0fr{b_-DtnVD|b9dhQ+xQ@q zg;hl==l_ELr#fc(9j_NpQn|A;_|cni9=Y8riA^CnKUJKjtoWyWETO@#P`_ZsHsR+7 zwmb5Ds@d%J?r^!%8LOi;h_EI;t zY~f*FbKCOQ>K}jJ3Us{_&OAEh+C6?h*PHc`Uu*BZi8Q~q{cvW2lFNl5B^L$;tJ#`4K(*F>`=TIo*B#}pr&^wch0A$ofE{|Blp z4=3{+cjR$4&QWC+?`E1lxq*Q%!(b^Rllv0}v7<_E6KlTAn$wz9vYBB9$1)WM4K0Bd z2B!%s4089~m_i(K7*Yzq7X9euS>igaXzqq!QWqlWy0<#%{D*o`ubF3FAo-77xD*{LGiPxa?ZLZ$Aq!$MlykbMp(h?xcuxG{zjf1l>rW^TFfjg7H<`t zof;V`meoaEcp#-K>mq%~k?ZI)mhkD{6lH&}a%u>2VPTNCaP)wh*|B>Ie+T#nceltK z^6>aDEppN3_BD&R9yH~!vUPAMNSHSyu9;kX*orTZp}|q<-6{MVBijynp%|y!1QUA}Z*_&uiGF5fOi_{x+A8@4 z1cV#qMN+267Kk+Tr13lKxGKqIV!)@%c|iH0SfYtT42SjF1r0GGr3Otb7YbVr8B5$O?EM z-ovb0dC0-#%o{hxGLA(7DjeE(N+xG`)}3&4YAYYxOLVztn|oNO>l7GHaINH#lFCSVPdis z!}5u}Z(LrnuwD4l)cah~VYV)t)rE=7e>GSmv|?m7yqZYHR-CIy6n7u=$qWEukX^%>VhOWTsB- zHPBod*t_9?+7ypA9iMF+v;ArpRcRoN`CA+3bDQxzc_5WE zLve-GCM8wfjLio-97(0bzq@GJ-ai4R_DTc?3F4-X}NV7V~5;fvMH% zGhQ=_bAKsl%K86x+7;)_DOap7>N(dZ@E%cGyWkX~@8LN|&J{3eHfr(jdFmL^lj-HS zP$=OglV`-WlV@Bs_iQNUVozaUlTcP^_pIYe3{cWo@axXDsIs%dYb36U{cO#y^M7D$ zbfRs+CdJrAkESWJ>uhL9XAoL+YK59l;c}&gErFLyQ)|M0u+r?GDGN!EGlOzx^S zGgJPE9x|Bx%=(Ae=8}E!hf*Dni*T);F`b*M;KcUb%UJI?Emn2-A-pD!omJ|EpWMFJ zv)GLc>^c-OYma+fl310%tMFeZivC zmp(j^QOJx@?JMsTH)Ry$I?;N*CPYQ#kt4&)Syz4}v@H#O=#c9d;mW&Ug5&QMJ?ugo z+NMuoYN)u<&bg!O)|44WP8WI7U7z2a$G+dh#iM3%&X0u+0*jiQX0UpjStLwzDKnco z+hD1!2h&6L9T)7^_6C~He9&aPCvE!N5Pq&djzYyE9m_jwo7h4n9wr+xFmUG`cW`(k zV(fNk&bF-%CSC>?{L9i^R!gqs_?_{H)y#CG+uw~$@jsg0iX}E*o7ur~?L)I%xY0U= zk1waXDDcGkJ#k}@>@iW9aq{AmjlE%xj{l{W*EGm|NM`q{byro7aAfG3%2?3o;M2I- zQJU3kW)jZ|rpqnIU49w*wRYq(Sx@BUvM#p~P-D}oOHf&T=t8pygD{u+j_^w|%^g*Z z@43xxtFkUI;^fFXsIYjJi*Qx=Q6-PZ9M;-rUVacz>}>F#_2c6*_KOuUB!M7JLB zF1yIYT&O$i^M%9O3TlGlQ;tR3Y+<;bu*8!4#Q8SXOUq5lZ_Rg}_9a7RVRxYDMWN}> zj{AM;c9fNCSi#M+!NFc5xk+m=DfVRJLj9c|`V!R3CFUtVC^C{Sni|FpKpv*OmsU0<2&nS{7+bv3Iu zs7RDcioHCwt!>4cm#c2y2ojcfpgn(%w~?K-v&4~v`PI1&dUK`D+BYP$iR5Ic_tn19 zf1uFn7QtX@ZQ=f&FOgR?qtw`B!i|`m1?*xEj;AX6iBXLvZfu}H1T6b_zo>H3nO4NTL+B&;TxOk8iLGtYz7Q^jPH=juh5B$%R@ z<)qdq**JZ5-L*$)qE%^&qC?2tb5|zp*%itqZ1a2a?I&04WITD07-b^8`C zl@rX1^sT}>WlI-GUf6iiLxIgiP2|gB4nO%alM^|j3G95EEL}vc9x55G`pB`x)o?-S zY!!B!yeaMyDI7blxoQ1ul;&RWhC^r~Z&>0J+k5jOY=Tbnu5(O2ul2cAgzNto-U5MO z_9a25wpj~sOzfMc5GE;jciDtI!pN=F|2Ke?(WkGpm^0w1uVq44clLfW`N0s|wwNy%^?a zF&r=dD-`uILoo3RH(RvM`RHKQS+!ytZ|-T4iFEF+#Xq}Ux4%$y{y z;!$wa>xdAgxQ#P}QUtuUP3=ZsHQGBeTeC>w|LLc9zTv%DXc7gVV!lmpy zS2_RpU0G1>qrg*^=Mc$q(?G=bQqs~O2N~zc-42VLoTM+=GHQKhzIsS0*Iw(TW9*HU z^>xPHb=N1PJm6(mEB|Ukv()X*ln-U%%ii{w9^qg&h+52ks>Xq>;|uFS;YU5YtZw!? zez3Hj+Rx&cq_9`rz{E&k{sD%vMycr+lw=R2v^~mg4wjc^uRU~#Xg{l|C$7roAB0ps2xS(rePfb!{pRVfz^Z$tVYdO_U3bpt&CIg`W50#7xKC8^ZEqA2 zP&qO+#pQ#Y1d>Fq_!n0y`->520GTjZ8-NnK3HSo(wdx{ao9gW_9n zG~N_aOfFzEGz)Au>+-$OF22F&;@0xqWX?4!c$J@sZeb9ucu~m8BJLP2>iMBVbU}NqEGGMOfb+|sMy_Z+-jL&{9;3D zv3sAb3ZG0s#m+7NUHOB1T~DxPJZR2;D&e7GvL}Oa?jy#3OFWpIn2MZ)iWq}yjfHO~ zX!CTm7%iXhynuP?rxO1a6FeRKo3EPfbIOs)oLFd4=yYAccw@WW2gyoyR=$=NF(DbV zAjS8O0ytjOW)yI&RE^rfOIy z``T#gyxgJhw35SRaWMO%|DCs;mA9^pe(b?*&B#9~vpwO6%(@K5@J*4zt{qmb0_iM* z$qo~Prx`G@&5Zsy>)?%Grs7_a4?>*+TJt~f#(TPCnfpApurvj^8wW)V1^7bn1?z7BfTc<1>wKaK`O^K5>16+%r+**M}Pql(-c!vdLSf zCOlym*pjcdX=c;$mK7Ig?+RhLB*}5=xQEFij`W+2A;DdW*SmrWB>b{E4*&E|{mOXb zVs1u5cXDv(vjfvynPTmu6rVoyYgk;@wY^vC=}Ob(lkY8?mXg@|`aMGT* zwdsm0H|xf;$EWHa1V?st9iBi0d);bmuL6Sl3h81kOjegCKOWd~_ zr%vLiC}1+%$h*~4nEA!_ODC5Zybhb8>h?a!%cU{s<)=)`Y}3Tsn>wnPg%bH}1v;KB zXnDLrQ^rzSwzA)(DOlH&MR?(QD|WBqNp=RCq|dSV$5;OknJXaI{98;&(T6Wdv%+)L ziw%>qA8iOw2z;<~vW$WAs)NOLmqeo0>B4_0fH?qoT*l_N=G z)<^Xh+$@V0F|}P{71zqpVLp(W9O7OmcIMFfTdXV#xJ^71=8FlaELSv9TE)$&ZTa=q z)YsK}J(Ui;Jth3rP_x*0U(bw`fJTmWUCcojn7gaDYD%*nPd~6~qexlxVj1BE!77O-52u@0N`!ScUm_BQUU4aOb~ z?CV)&Z!l)b6|x=vpuKF>Ayf86G74QgHW*1c`Y$}NPTYF?p@~OU7xlWYW?s%MQ1&%L zkcp*pvs$1OhvMOo)!r^?6E>fCaD4F&rfr}2PJXG)I<9|u2N&z|Y5Hj!IUgA(Mi)Ob z3yRK4kTGUiySsn)Be|ko?jNFAqFyulH>oBXNcJ_TzB1wnJG0B(rkcCTdj8@yVpeCq zZP)0JvRwls@wEIqxO(aPAAVPng8uu zPKf_|J+V(f=FGUE zUap0gS6u$Txi_2f{RNTF4~hb7r5~`|^4WY?GRN|84Cn4+OdP*dHcsI7*Qi!J!1FWM zEP!{;nTGTWO|t2-%$XkCM{eKt_;~x^5mU$ZC7%N0ZrT>>{9PdOH;#GvkqNGscQ@y) zcerjiUDIPB^K{=;KUduN`Sz~w3v(5t1v{PhW>|7EzdHQ+LWd&D#DE9)xLf4B9NBJ7 z-Pd0bn^bd~dn@-B+aCF~y!o}4L)V@S{AjpgqPN56hX+hJH^(g3+*jWd%hVHKBs9V8 zrJ}Sl&mk}4bfvj0MU9UN?mpzbeE(lA7Xwr3r#Fmha=S7zwK;dE_p9DC|Dt_1fU$>x zW3Pgi^}p3?HV99B^oTR>e@uYDna$iRa}}TPzSOOMvMX_t(dspurY@;Yd$;57Wfrra z+r{RxL~PRP`Dmy=k>^R%K^;+p=&4d)GdYa-^47#2Zxv?KzMx}qay8$Ln7o#k1uo~9;@h`>-?Lkr zeOMV^et7vpmP3Be-F3^~yliZgEt0%&{P2Hf(+Bp`Tc)!na)+*Ezul3TD`&yCNwawK z%i<5Ls?0o-Hx!uNP@5Umy;bjB3gdF?K)2A?Bi3tffBd-U<{z(>cLca%BP^6yjM;^g zHw(?3p|W?w^iSW{$~2u}5mI=+!PYiFAT#Ou8|#B>R>T$`20h*r}3O&h~^BE;>hTmdLb=6u_@VvC-!0C&I4OFH9i!zuzUAg_{2M< zKlfT>y(a7Z&#r2D_TS~L)$!Dv3!Hidu|Wc&-lamnSkIMgxPL6>`7_0hYbvf>y7Kjx z!UUVMD$@7XvD(aG)c-u^f40=WJ0Zd;DgV|nsmX6RZ@-lBf5e2`u9>!8c6x6XymM5z z$QShFcDdcEY@@p#S&Kd#d9c6i@zlS*JH11jXXMfs^%c{afe)}H#1`8OKAfz9ECg$g_>`)=&_*V(??8%nhfLB20=07P%}lR|;l|FunvVlo(3 zBym_U*a-v}Nc=7+sF*m{Fd*7bmt#V-LxQfd!Ukc3ZMqH?728CwM|}9>;KX_U<4nyJ ze5A*It#l_6pa*Lj7ha}zUF9<-+QTCg4xV(QpzAki?D zEk;7)r6Viv3gywh-64eeD1P8$+p0@`55Nr*BHqYG&g6w3Wa3 z#$Rz;IlhQ*3P!>V66bUnFBmUs$jxI2Fy1ZWz`fdI19Qr3g;NiXGBGjzIBDR=5Ma>B zZuEj_+wFfFIvUsn?)2LqOq;+a#OXB4p+TGFhQWR@_CN;iyM7T57#^&$p16tm;0HCu zl(Hii8{+45@Jj7yDSF%+DwKJMf$`3azUdE^U3oB_an;0*4NN+-b63xwar@)?6c&b! z49q+qnwbByO|f3K*zDi|@8&rH3OSuCG(NxNX6Nx(aYF3#jb*FYHw0#Nv21XBF#C$o z#%zO&IvEKD`lbo)%xtGD^}FokGa4tK)7ZL_l~L(#@w_V*N)O#@7#d8ksV)c+Y2mEu zIJb(se1kf!{Z|pCa21-}=@%*>VuQlHvk~zn~a_?#=dwC4!H^wb-GKFDIzik!yRGgHS1x=4w!qaa! z&o=Lnr$XT&@ijuTdKsBQ8J_rkOc3^MWccI3FekEQ1H(*5$s0#k6zu1GeZltaq3|um z+b&5wsOjDnX7D5BM_%Or$vg=+T6jE;Xm4GAOk~*%rnZ=@_3mO(tgkdhI5MphqXcw? z<#DEH&FT_9`6h*DFJp2!zszUYu*U<9D8TEa7K&IUw%*Q1AT28KI3g6_&GX;#TC6R@?o%IbQAk8V;-S z=Zud899V)v1zPv-ihZX!_d?{3s?@3L{@-|1)VH92&a;wM7J0&W8X<)Fqv9M)z;hBOv8&}<5@SsWVr3cdl<3$Tn7uGyJEG*LhVVAIkzO}8$6Jfr~ zA`5jH8|niE7|RtHc0EkTWGP+ecgT!XcNnmxZ z*lU%;C2+rhSYi?%)PSo`5SVi+5ZUGMgsp zsU|dO<(D_-Bd>aKrkqhzj|!Z_CAM5R=TxE(?*VOwWe+ExcsphJqyJM@tFSkUtN3_v z%sinHcs(oVctgp?{;LN+#iVUXwn?x`dm0LQyiwgkao_9I` literal 0 HcmV?d00001 diff --git a/test/files/test-corrupt.png b/test/files/test-corrupt.png new file mode 100644 index 0000000000000000000000000000000000000000..1a81abef826f52b95708677c38c4b8e812e2f462 GIT binary patch literal 61 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;IMg|53hG<6jNCpN5mUKs7M+U~W1%@xC#e>8> MUHx3vIVCg!03C%3d;kCd literal 0 HcmV?d00001 diff --git a/test/test_helpers/upload_test_helper.rb b/test/test_helpers/upload_test_helper.rb index 66b404278..4f2d18dc9 100644 --- a/test/test_helpers/upload_test_helper.rb +++ b/test/test_helpers/upload_test_helper.rb @@ -1,4 +1,8 @@ module UploadTestHelper + def upload_from_file(filepath) + UploadService.new(file: upload_file(filepath)).start! + end + def upload_file(path) file = Tempfile.new(binmode: true) IO.copy_stream("#{Rails.root}/#{path}", file.path) diff --git a/test/unit/upload_service_test.rb b/test/unit/upload_service_test.rb index f8382dd86..d99360175 100644 --- a/test/unit/upload_service_test.rb +++ b/test/unit/upload_service_test.rb @@ -34,28 +34,6 @@ class UploadServiceTest < ActiveSupport::TestCase end end - context "for a corrupt jpeg" do - setup do - @source = "https://cdn.donmai.us/original/93/f4/93f4dd66ef1eb11a89e56d31f9adc8d0.jpg" - @mock_upload = mock("upload") - @mock_upload.stubs(:source_url).returns(@source) - @mock_upload.stubs(:referer_url).returns(nil) - @bad_file = File.open("#{Rails.root}/test/files/test-corrupt.jpg", "rb") - Downloads::File.any_instance.stubs(:download!).returns([@bad_file, nil]) - end - - teardown do - @bad_file.close - end - - should "retry three times" do - DanbooruImageResizer.expects(:validate_shell).times(4).returns(false) - assert_raise(UploadService::Utils::CorruptFileError) do - subject.get_file_for_upload(@mock_upload) - end - end - end - context "for a pixiv" do setup do @source = "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350" @@ -1133,6 +1111,33 @@ class UploadServiceTest < ActiveSupport::TestCase assert_equal("http://www.example.com", @upload.source) end end + + context "for a corrupted image" do + should "fail for a corrupted jpeg" do + @bad_jpeg_path = "test/files/test-corrupt.jpg" + + upload = upload_from_file(@bad_jpeg_path) + assert_match(/corrupt/, upload.status) + assert_equal(true, UploadService::Utils.corrupt?(@bad_jpeg_path)) + end + + should "fail for a corrupted gif" do + @bad_gif_path = "test/files/test-corrupt.gif" + + upload = upload_from_file(@bad_gif_path) + assert_match(/corrupt/, upload.status) + assert_equal(true, UploadService::Utils.corrupt?(@bad_gif_path)) + end + + # https://schaik.com/pngsuite/pngsuite_xxx_png.html + should "fail for a corrupted png" do + @bad_png_path = "test/files/test-corrupt.png" + + upload = upload_from_file(@bad_png_path) + assert_match(/corrupt/, upload.status) + assert_equal(true, UploadService::Utils.corrupt?(@bad_png_path)) + end + end end context "#create_post_from_upload" do