From 4d3040d1ac14008244e4de657878ce8f5424ada0 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 18 Apr 2023 19:43:45 +0200 Subject: [PATCH] Sorts files during unzip Ensures that related content are unpacked accordingly in a mixed content case --- geonode/storage/data_retriever.py | 3 +- geonode/storage/tests.py | 27 ++++++++++++++++++ .../storage/tests/data/data_collection.zip | Bin 0 -> 14261 bytes 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 geonode/storage/tests/data/data_collection.zip diff --git a/geonode/storage/data_retriever.py b/geonode/storage/data_retriever.py index 9e467c66341..68a14c2e864 100644 --- a/geonode/storage/data_retriever.py +++ b/geonode/storage/data_retriever.py @@ -211,7 +211,8 @@ def _unzip(self, zip_name: str) -> Mapping: available_choices = get_allowed_extensions() not_main_files = ["xml", "sld", "zip", "kmz"] base_file_choices = [x for x in available_choices if x not in not_main_files] - for _file in Path(self.temporary_folder).iterdir(): + sorted_files = sorted(Path(self.temporary_folder).iterdir()) + for _file in sorted_files: if not zipfile.is_zipfile(str(_file)): if any([_file.name.endswith(_ext) for _ext in base_file_choices]): self.file_paths["base_file"] = Path(str(_file)) diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index 89eea61d4ad..d1affec2353 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -608,3 +608,30 @@ def test_zip_file_should_correctly_recognize_main_extension_with_shp(self): self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) _files = storage_manager.get_retrieved_paths() self.assertTrue("single_point.shp" in _files.get("base_file")) + + def test_zip_file_should_correctly_relate_mixed_content(self): + zip_file = os.path.join(f"{self.project_root}", "tests/data/data_collection.zip") + storage_manager = self.sut( + remote_files={"base_file": zip_file} + ) + storage_manager.clone_remote_files() + self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) + _files = storage_manager.get_retrieved_paths() + base_file = _files.get("base_file") + + def strip_extension(filename): + return filename.split(".")[0] if filename else filename + + base_name = strip_extension(base_file) + available_files = [ + _files.get("shp_file"), + _files.get("prj_file"), + _files.get("shx_file"), + _files.get("dbf_file") + ] + + def assert_same_base_name(base_name, file_name): + self.assertEqual(base_name, strip_extension(file_name)) + + for file in available_files: + assert_same_base_name(base_name, file) diff --git a/geonode/storage/tests/data/data_collection.zip b/geonode/storage/tests/data/data_collection.zip new file mode 100644 index 0000000000000000000000000000000000000000..0702327be361a2bfda7c9c2a6eb13bd08ca5a9b4 GIT binary patch literal 14261 zcma)@1yEaUx9@2wZY^4h7He?|#qBMHqD70B;7~lc6I!grU5XVi?he7BcyT8LEt)`( z1W7LMz4y%bo%fzI_hipAdv@me|1)bnD|?>3lAoq3_9IHHhgkSn4=gqG)H4iEUSMHi z{q+C~>+${B-Okz8(b^Q~V(09^XJuhyxofj!X=P>xv_eh>lWenb6z%?%KEb@n^j)f2 zE=bG9&nBlA9|ueGKbdY;joOUen`!)4ra(7)r#MrhF9MVUT_cP2ztCcPj75X1Z#kW{ zpG(Wfl5^!n|5*`@VfoeUFTUpu6Ia=_x3O>0#$|g#+%45O*9%*_n8n&@8@xDXOy8^Y zwhbQm^GbnZ^y4I`CjIP@4r4yn;uXD z1s{_Ao(Gb8dY+tpx>CeolPq8|Fy&Bz90WjI^913EzLCdEV@bQ z0Rln-0==zVq)59CEGuFfk@|n6u#G%3nD*Yp@xM0m`M*YE|8CTc|F!l1+F;!;FP~ka zUSvLpKJLB6qx(T}KiplMtWB-VJzzGi)p@mcIq& z&Zg$hR&LhrroN^?Hy1BED{E&AvasCe? z{JUIZrHOh4C>1b~R;28{D8_;C*Kgn3>B!5u{?6wk(3qSw4MloLylD|r7kdmcbMD0U)|lHGfYZqQb+kpL%V{)_sPrb7s)R_$XjVzUBg&n zI^Hsock*ztG+h&#?i6Y=olMJQ6W1?=|5^?A^@Z(}baxEo1E}CDxf7)O@Us5TD=ttR zCe^3zX01(ncltFK6e(qr@Ca;gLr`DZyVbcf=<=YCEh8Uc*E^6So3U< z1R3D8Zl@c7Ogw*1M-JImxEzRrs{kN%axKmgZXcv7HmCd>u+(E}>oZtR-%l{IohH#p zCHUjO&hbf~@9SQDfbe_)$y+%j+;DQOBXiU`K$Tl2J`3anWO?vCn!TGkGa~=mnm)K| zGh*2e82?&y#ucf5W1T??mbf=BG1!e7Ziik(^eLWVm;nAONXj&a) zi@NKyIPWTIZpurOZPMpOlRq3ijPm82^=zIjCG4pl*h>itUgCsuBcWdp=?;96FK6jC z_ceT>1kP`qg%(!=wmD8$tX1(Qd+N&a7L>0`hXUU2!gYS)k=4}-bTh)7NtwPB-R{sS zqiFR2b$wm~R8fvUDb&mbC`%!q z?TYVDl(5R@0SxVhO5zH=JKtWgJGOkuTqYRe545!rjgXTz^K~mDan_RDGr@8Qa; z<@b4I)QYe3b8UjAs-atX^rcH|4<3itP7<=+Vc<~39G%X)VJV7c(Dv0faw4M)<@b%mflfI5eYi&CRbx@|ZHBY7#E^IdmM(8BVt$7Wox8epB zIkWZSwL21jWkwATPZ<;umOHjptKMF(@0k<{lsmxbwE+ux9k)qckv__VG*Tk=m$RJct?0ra+#}IS^dm@WTp2GbO4ssdO>)0a zYyPgsJB#ooYiQ;H)~u zG?tLl*LwNw*q6eFwMT*-Q_Pr1oFm}`ZiS4v>klZ2MpBXYYm3grioOgpb7B1Rg|>{L z)#>Y{B5Ygw7^i*T#nFMA-goIB!Q=ct4?|7ev{<1@wIAXx;0O*`6N(lV-bvo4mt_(Q zZ#N+j_B;t({g@M!@-zgT0Sz9MBlJu%iho8WGT#u8L2}rdEdMF-I{nyL??GA>lfw&W z>AWrX4YZ~;VMGGhLO4`57xi*hGDNbkQOPf{Cun6uU@g;F3CXQ-kx&jl#V@ya>qMi* zsm6h`NwfHFn0Z`)Mvx)l+~pnW&jq}8w6E{btTz5He z7N~;oes>G%7uhCid8G8*xoL?)7S#c(EwwWXAa7=x%!O zimF3h$1H=>QPklue-DV-Nu?tIu7q_SXlx*E9Mb{4E}mt()V(CpigO{UKRPvRb=N<$ zAMvgJ3NOJSVyNzYe*m?yP0jD%WYp2$IEa`wj)dv}BqJvJP}m3sx()P!-uNfvxVq|v zolmY0kN2aF=bz%3b6LW^11FSN=)vRyHI5{=13YDj#{qY5&h98`+>y0bOvpYQZiHQn zjIz-9lM_&}jQ^D&q37_gA&PmR-G#}_L*zElI7WQ6)mo_?`y^1Nap9@DZR_f^S@~IooHqz>p z{<98~jYe(Xq%5N+VR*B5R-{d^v=mqJUiVp?_YL~8=4VUV9orGX2|v%XPhzAl<|e7` zkHKRe)86>0F?Wmy*a%5Q@s7}PFdYYPu&z`RGPmz2bL?T{LTx1C_|KDh0N^w z|#xro>G=q;|Ko)_q!4S{Mw0_$%PBNWfPTPn1%C|;2`Y!1kW37j?ndUL_ z^?w{2;-*fRzxf$}y&7Aj>G^51Ka!X#dmFRkDk9k!ctUddywfWbKw=*#%QcC+I+GB> z3_*u`d!|^bZ43l0k0#YyEz(Jh=|=nUy7$1Reyd+J{^$ZA4;{EuuK^*M8ephq1h*_D zYAF83y%3Z5nW?Caj3JbUop8-I#Q&OW@ODFxKPVyYPc`RoJ^ArQza#{k(2RHKRKKa_ zwYN$j_ECmTa}Vxr1=Z{F&#e@WvhhIGklb(-5DQO_ZP9MZ$3QBeQe?M-^A=F)TPYpT zE$$Nad>FL7^!WWE;Iw~AxKR4~JJV_3UQ@Q)?=Ob^)tSIPx?B38574FZOEquHfHI(2 zVc$bXbDOyuZ@Z*5i)k516>e%z0`2JyO^@_oGgsuskI?!fa^S2{$n~SeQ1_KT^kV#i zCYNlEGEcWgaSj(Ww~nA`^UayIeW$U~%f0aW`A}{(HrZl9y^wU-PyRcfc^w8Od&_*`%mAzg)-Q^; zDDk?L(E@;b^@rBeLFNl%k9fj5JXyQ5HNZ>eH-a0_zAL z63{XYz(&2>x>flxN^0zPE-{Y9;$tF1`<4<}r3~pmi4ey~Ha8j>K@Oz^RusglQkU?i z@_6xvgwCg0U*F8MU0ZUctm8sk7|)LpU<<6 zTj&wj;<%JGM-QEn($n;OMU9IL`pk3qv?g^wP1+l~zE&7ux4=5pVX8=5iM&W_ z9}a1cioO!1j@#|I5@oV|j!0OWeRJhk0o!{Q;*pbp8g*a$yaL}y=o@B}9Zk#rLlC?q zyQ?_Y0~QR?kF3r8DwE?GvOUSuP$rHSt6QCY^f?1N+s^_z=XTZ9^+oq)Yf%U4$^F9i zBI(-Ta!iylNNBzBgdt1wd=UAVCvl4Pk`aIz2AgBQqMLEv+^hcJ@W{Np(tAXvp`>BO6q=@E+Pu>@$suWzfVzA8!U4cq!5}ny8Zx%GUqTZY zA?wkQnRsEQSTKSmIlWSGd(JLo=pw>Zf6zVd`uv(6XkmPs{Ho%KNm~@rJi2uYj4jpB zCmf9jmfh8CqMg6+$AniXT1lD_;4$o&a~$f1H}o;;FK%{krKxUY+c4Op;GTOLbb8(T z3KVta=3T7&76&ydPBG)|K5Z;RDpWa`{crs*#Ja3D!lgbY&Iejz#liw@WteiTy}j%h zK6V5)#8#v^@O!6t_KlR6zh9EFJ&?3{JE};X-kISNC@r<(>yt%69siOm2=4{N{5{K# zuWaqRfalBpu^L;=0|FUfM3LvgAGXG|Ln~nkY^+#RC$+DU0vVM++#8ohPfyhQJ>&aBlg@Hi zUNu>hc)rk@!;~6-`D}J{2SDIph#*L~o6Inl8XPsJ$vk~Iz0Tuw*SQL(o_SEpd49h? zOR<$!(g2q)#UI7RqWC>0gQ;S6NfJF#U1TyKpfdg#Tr{tRN#|3ZR0Y&q z5I6aJST}ftH>-QhvX1GmWK;JmM$@sG7{vA!CGk#K1??Y7y2{`IsI~Idu4lH+U1L>z zFgB^rIen^US!$(_Noq-)w385;Z>QAVtEZ-qh6Aje%aVNwY$ib8i-^5jP8q*O%!O>y zB;28#D*s%+G_cxQB%>SpZm26!49%AU3!aNZf$tRcrG+3tcji@3)&+6^s;pKbg0 z!dru1Wr+kC#H(-x5355XFccwhqMRZ12dF-eB^E1=41kKWZNOD?w$5$5vaWP_+mi);MXEBIJk6nSahdqTG|#}O z$tM}g{3q*QZUFFiB}>mbfX8mf@>&L6idL+mr4Y>laB-^-*yrx@F*hfKXvfzTzW#jT z3bflby@W{FC@Jo3|ElOY*#Y8L%bOQ_$-u#w@O3YmJST(SSa-Cn0vapN#5)Z@eAjqX z)_=PApGA-kAT(-DKh}OWP0BJl=A92W3oG03{&j^f$Z&{{^#$TY(KZ0i?#3{>q zhM%MsSp^1Gl`IitR>Zv4VcXgQRC){1`+gbMBv7|bJqRS^K8bc@-4Z_zkT=BshzPjy zuS4%ce!mYQCc_nLNxG0+2Wu5SB4v^(dNbGzRo*(IgC7XxmJ1JGoAx`olLD-lDdh$& zJ+bSz8IfPI>B6EHj0UF--WzP@_o>vas}B0Q7-Ai+jQCRwr934%>oe(%e`m1Yb7()!!Nenx*wO` z?p}$Wns%6V@?MTVunKZ;p*4DtStZseo<5P_sbKdUez?jp^3aDJ^kq!B#Ty>bD?k%g zw&iAc9KAQ@JD$+Wm~9Ic|8lpvEfsd-Za9x4h;Akc4eKeZZI-W2xL~tJXfkI#bFrq^ zIPfmjYUNrDP-l-Z*gv+UP!MBn=y^#XbEaeoar9y42>e5Rn`(`&S5Y5RB(h`?-1ua< zm19mi7SXd#o&gWutvdEzs_oJd&+w+99z!H1eJ(i{%^G1vw67zKCmekM$pK55WaXLV zPcLdWuZJa-x9@VC%0mJk-acDt)7H*W=y^x^bkylo+UIII*^Mjsvjm#AEzHyG<)vf9@c5{MAF2fS)?!!j;PLv7dZ+ zAt+&dv-$NHu%5Ruqk@JkXl2phz$YtwRcZqJr z;j5#e5VzS(wIWN)LKz+3&M)SDfjCoLW+1jn;!II1HlcU~Schz3^?PbT4&Ng8n96#! zs^I(Muy(g2>eFt)DI8OpzPt8^a*uxbZm03&RB?(QkfGP?wgVA)TWj8=z1b^Q87jRG zOw6&%&Etv`5k_EA#lH-{qw-0GwwlYScvam2{91&6I@XhtF!b!O+ zj_seshV4v;Jz+(XTPaX|4SOHa?uFtD+LE9Vtzn7!jI1~%d7H*=J$2%hruZw^h>lmp zhU^S?K#Pt;*9DoleT7AQr|d8Y-5OlxDt^G+72_mODtiza77o8HDALK>zLU})Z{mmS z{4_r4NFs=+Ha*Ul3J%+zMCFEHv*H-c_pxU9j_5-pINy{QN1|6`KP%AvOboIXnzC0DVa%r__IJKkX~{c|IOA%a#{5UlJw~vqO=i1 zgX0e~%|aX_z!3N!yuD1A`7&zPy0}Q;%}?2(MY{2iHDkZtDO1mO6)4JcxJKf0J*@&~ zLx&&0Rv&wEzm7fLExiDz&eRjzWIGhYY=LHpgB4X;8Y6a^NoH(v3KM5X9Ty|;dsnvBh zT7}Q16=izocj4fj62%|RIfY0J{LZCYnOLUaSFT&OA=VHG2vR!R%DS_;B4}wt1ij|e z80hJ)&W6uhbd5U#tD9pw9uJbW7xbc+fPtmXrK~*Q19b!svKeXjnH%`Uxu=;^aGg+f z@Ni?wx9D(43DneZ_cQcVMG^wOk^b=)6JN`ozKHw;CK4sW5J9mz?SBnr9p=zKG(Y(? z@aKV>OvMUJh!o_z7kG#B5vT=RCPyd)U9u122^_A8t%Rh>12UHs6wz!!r?C_^C# zMTeeW=M*EgiKh@sq$7*Hg@YELnYx_x{+fc(!GB}3AS`p(=c}~i$Vd$8HZOWh=&UnT z>z#kOuo@i`?IoauHQn|M)T|lUC_ay;-dq9PJo7tEIjxyM-C6cWb@AHn2d`-Kzf10B z^3HHh?(@@`q^u7M;7>@Otq>#Tr)oP*$?77ETIKZ}lt{w7u_L0etB6?AG0fk-i8Xq0 z=oN@``t%Xo^(4;Fsbm9(M>1O3_h|+Dtns4li2v?jL0xVQS=t(!P3)Uuk`wm4DY!=9 z?b+SemWKHsIJaJ|nopHsZC9ZV#95V^r3&;2q2&U45ff)2`RODs{@dS5G|p5$`{!h_ z889t3nQL}TXy7}-)I^x>w9|m;i1{7n%AXn+7x%1)C?$ZVuSVWoHX~|9))Uc`*qO%? zQT=qx{ct^78I1u)nWJuAjki33X%MuvU;yn_`(Iuuw>j9^;RJMbUq3)&K2CNE5OvkF z1zJ)s#kb-U@iy|g_XtfdjMm-OL)UIXN5>Q}qj)e#z-vvS*N z{lfYBI~SM|1laZ&GP@Roq>t8Ehu+_BYE@aMh+~g;NcQqa4-L`p108Dy^PD)ZYaEA~ zc&$36i`jlO$$Jz#dPxpwODGvC#yEbZp&q&X7>eO#iX4lEkZNn_$`-28KCxj&6@#R6 zobaAz>L=8HY|6h3$3~#bUtD%we4r8$RGGiyfb=c<;nOiBJz=R@2RSz~sHsMIIidJ> zm%8?+6J_R$-d#RX&!f}5-M9@lC84Nc(9itE*XBPnofa!eF1RnA)C_`Qnz?D?K~A~X zHQ%Hx>x@krchUxP1dv*+z8rxLB1e_Xcc$Vt7+yTyBL)57BC+1so34FmNqg$0)QLa) zZL7eo%W_|VsWbj`(VdGQ$i;eG&bwN_7$$n5to4(?B>Ktr+5jvK;hB!!jXHJ#%gMw9 z?iLXhbc%`#iT@IOE{s?&^!tPSV%OF%w)7s7bfvTkGmS~SVti1&liC@9*8venOs{38 zru8UFu7*QFun3--P4Cd{%*)uqLge)=``7ZeEd_jWimzt^uodnLQ*bM0*Z)M`j>s4D z!+m$k@GL0Oi!pmo$i$Xg7y;h72DtUwjk*LY>aDxdpwNZ3HQuzokb3h} zuQqJgh9Y84(c`;hdu|8O;ZYLq@mJVw9pc#+(tm+ne3$QXV#4@fImVA9hHv8SwtjO` zwXEbEQYz7M+{xvk-oU2f5bxe7Lzban*cSHvkLx5jnI%20J-4qM<+3Qad=9oCgM z@<;CM{UIGws{Y8x4>dk(4dG$Qh4*Ac?j7h|W3&s{Vf=-HZNgsPBD=EpldHYrQh-~| zpqwwTlxltbaw!ry>5kj60yd88uMUa_r3YXTvyHE#WhGp>tc@QeVTc90WF96LFThAoWibN!4O(;${6%fH_GamYr&UX@gQF8CfXK>O#wX?F7h z=PU?dojL5xKn^~JVsGl%>Pd3%XIx#u;%3WQdP|6HIMrw71~!c5^Ob#^?>nBN$X~_b z<=X+ZX@T`WdF_VgZ{+$L`w|>T%xc4{P!xMj)bfizn6VSv3r;;mIJh=r(IDr z9c4S{rX}E;8)+RkX{V2SA8xsx!|Ls}^kDlTEwJsoPPO?)K`{l(^FJ?9K|jo9*%@}Z zV7a%rTXyCW@u3S+iLB5DbcMCSru=$I35K}6{Q*E%i%EdEI?Iy0Cbo*dqEO{qWoU+= zIGZvuVJMo%t!B4Q+=4C82-4b_*qpN+Ap#cpE{0P_sC$^I^inFA=~FoEqwP^Qv#g9M}%;Wib@7UtKv zQShX+Z#&b3Zuf2+?+_Be_Q|^}?swSK<{A9s1tnYYR}M^V8=fq;$<5Ssaib`r2t_^S zas0j=4LNsJF8Q=cD_YJvE^_{b?Lv0$)r!wI4D5DpMSFZviRN9D zq`@{*A1(~~%@X4t+kiwt50ws2G9rq3J?v~hg>T2Zv-wXR?6=p*jqCv2VlOr$?gGR= zYK#)`-hp6O-pZ&X7lK%VlECduLYxamn)~12oHl2kcux<>WH5{*-$4R|$VQIO|4Ijh zuh^bR|D|XD7aG!k3yz4@0r z8M3b!-Unkknd-VjOi6~XRP&UXghR7G0MTymaNNx?`H(Nb9n^{cMHyzt80iAGbCqV} z(rtSzx_y3$#|8W0_WTs%tTU#?yzCZ2}iN!KN9Uy77^0hy9I z5odmici351`l3lqX1{~(gfVd>L-kzGbqE~D<1EK)=!_EzJPbRh}$CB5C~ET^Yd z4^b5r?=BCy!DH$c9h<}5O>plk4EBLaQDN&)A>ppY|E*5$K4(X$np{ z3s>#CKr%Aen0N#a`wsE!^z!!yOv>W7naPOy<7Hu(xe>r?vE{q##yX`Tj5XiGSG?(W zn>Ie5tVg2p)7?x4@8AF!rIf9USv)v|4GjF%}p ztQ*BsPBODGu|piY09`5nvY7;p*E3IPhs%gZ#j_bOD|KzLn5^s3rw8~&im`{Ea?mf` zrMfcR+5@&PjB6Geo%}2IPnvh%A4tEA$KxAGjXBiL2qQw zziL^ofI=gk@Y_** zo$oPuQgeB#rtprrF-U&ApZcxwq)KdcEI#YWet;K)Lx0TN8H7j0o7dg&>yM{d;y#{m z0h1PEO-Bv#tXXMHhM42JkB1Kbtu144<%}~2F}X2aCri-Sw$Ok!yGF`WCP?FB(r195 zTzDW%*$*Bv#4WO@fx3zgklRHW#3*J?O$tGm)+*5k8F};X@njADl+h=du<&a@OMM)) z^N=Hw(cUpgBQ(x#*fqqiAB}U<>n2?#^>Z+1T{C%WY8E>hTYw9vGo<5%+WVIMEVC#g z_$WyxM99-R7H=t3flTdM!D^a3U$!DxNhPgZ!*+1gtZ$0ozu8;x?QLk=RaeFDz~Uc2 z6?4K-J?6!r9tVAN{3w4^Oz(q|JWa%YIA54+kc_9vG^~?7NQ*)j&TVD>EW5)gbFy zM^mh~VETNAicpk^=4V35_2dONGt?hjh|?Ze_j?^X-0EW()o^RC58>wQ^E;Ke!+buT zT1;>|?h!CAaqbEDbO4auFjR*epx581=5v@I>G|lel0(z?+2ol>VJG&rNxdRevaD)F@FJ{@Jnv?<@A!Hc6qD3L~*RRUT{de@*4yXx1~0aYj{k``&$O}NH7 zC07W>J99{lze#bZLnNU^^?$t~moZ{*3dcK{IM6Y{n$!jAY!<7^dV(j-y^yyjcuvpY zISz^kiyPEcqc??6G1T1KF}TUnv@i>tMP~c4Wp!4fc`X4za#Zk&ZcN|zgD7EYZoXPa z1WhfzepWn_<-2q(*DM4$^-*Unjh9{g9qvgS_lJY7+U|3)u`k4Oq0DtcoPxY010!~{k}@E!AuG}kTL+jQG~u$lWuL_B|Wk$vmAX<*|{jNc`Kgw>dXvc@%h}yM0s= zc!S`45RS>T>kAYHab*dAVB8AS%NhZhgRj3WS^v-tHY6Ql>Je?KvLyA9a_^ktw=W~5 zw}ThvB&Ugh45E&W)UHE1T4Do)chgF#w7Is?+wHq8ib6YvtzW%2*~U80=0p<#*6U4p zdNo5P(v@6`0KU$5IOv4Zj@bU(@=>}moWoU_5tV7Cttcc936m;?DBJO=eA~`9{98{R z(}V`djAJ&rZn}m%Z_N2n@J^LsWSq_Q-d+j6)E>EMO18!k#He-W#qK1PEtS4i@BJMh z!|(}sJHAzTKhE|cXqY!b1J?nd{DtlX_$&XH@h+Dmjl%Zzz)$D}Rk)R6nI26*tyA+D zPI`!xnf_!&3J)K#oN&#Ivv6?~d;;bjai-Mrt?LDWMoE)n2d=20pDKXkc+R<5;K@9? z5DH2;e^DB{RbrOsq&V&pf9c}6=Nci40dW0w<}GRkW6)pp>o+{5=J7+s_q82loF-JI zNgI2=`{f5w-O__b6L+hG+bQKRsszuH{&!aSTmTf0=L#69rmzK$UH)1fJG zfwR!J+-~s}Ppm<=EcsQdPv;f1XiqDIxLfBh--Vq4pir6~Z7FP@VxPkrK3>3Qvs81F zkox|c0BgkM6miRt8XM~2>V%DSX7s}93)6ZH-SLLp#qD^&<0IA|RVux4T*Q|xdookvJ?<>FKj9$#nQ$g zS8Ay%#L#POuh=lFAPv5|KU&xe*O{^?eE!l;wMr2oI3IYsl1?`zMsA+QPRKfoD4(QB z?`aYo`Pi-4;8yUPlMTFA3OF<9#vcWmjC>1UA`{iE?S96RO2fM0St-0QeEnhfwF3+J z#K$7Ge&zY*x!f4JjSyoa%Ws^62kuRM5Qk*Fgo{_E<}szOZei%h#_t~7J{*=oygMP~ zt@Do8ZpjgSp_}s^>9I5GmJZVn);2r<-KbS{-HgdXp0n_bn>R1;g|-U2%s#&%Ka(ye zQUk+gLM~i7nU;w#kOp2p+x6lo4b^tw9#p*!hA0q}X~jZ_Jrk`C#<_5VF&2)hx*YD; z%K(`Ny1c09pB->S6zw}@AhSH4k0EtGDa2? z!fm3x#?c*XzWG|XlM>Y%%$nDxt=4Gj6{zOaqH$Zx`ytr6pT^$OHkpT6y)M{|t7bBT z$2HMQ$lE@e;r8fLU)r0+$V2A=6LR#`I$7NXKS_`Jn@WfE9_}G4DoParStP_1f|pCY z`Jp~I3cPc0)mvOkIui^0X*<`-*pg-a;DY?)<<9<+zJPBIn3&%c6O^*;eH7nw!e!ul zK3@7@@g^Eo#RRv2@zpPQSO<0;#!x83h8Do`0E1tr!-wiVqX`H+(DNWYi2DLfp;UE> zPW#tRX9PLjp-5A5H;;>pcth`!zR=!ak28N+8bz18r^h-TBHZY_x$koTO>0wc(jn;b zb+2bv@s5Xixo0)|q1l_j;Uv|K_1iRiGU&%O>T0c74P%yiPjQpGsbv)}hbImK0hZRo zG#2W-dL*JPIxuZD98`NCLjOq8JmJ89vfO+{n%n5Ad&*`fg+yRZ-0bBK9}ZAhG?SoL zcV0D^G~wEe+K90R7u|d}#U2XhX1V(_9#tF67g`F~!B~7?(`Z!VtQrkjczW&OMR~Un z7mB`QHA+`@mbDb>Evt7AiQ34Got#+Z{LV>ZoTL>bQIVrx50j}#61qMW>^RZNAHX&! z=)4=DUG#Z7n4t(nhHiwj!mn(_%avOJ)D z!K?Go(rk+i;pGiF48C|+RGDu^UEZWUUF8&Z!F19acTzu^`(%KWeW1T zi^!aT^8uZHPh*)Ai8BbMDtSey9<@E2A7%Ul7#2h5B2(j;AJ_6rT9q#K+$F0o_`W?? z(oxf#MHFS7OZXfL0;h$BSyvCmpRa$)9rgTzUAQ$M{O9ET=&0tFS&Mi@?v|uNuam>0 ziJyIeqJsXyyco2JaI1{_WXK$_=X(BafB@#=NS@rZMtIDR5OpJpc{%-2&@<5wzhuye z@9pANiiX?Imefnkh?tL|yvU)8G!R`G@%xt~z7F>7Xod1-xlMA3d#QIU0%Nr59hw5?f!YXEwocA7a21#`T$$jC&BwxjiKo8 zl_OQV&gniy7p7v9-u>$S`uR-__SdTiOMhL+sr}{mFg^#jkRte;pZU0_oB0U0kTv+6 zg?X*Jn>imB8uj{>fPjsFz*lg{9~$iMLyxfvSD4Q%;+Pv+7~*B_=l9^eGPPigU%#JD z`{?}J1MCobr9d3)5UJlm?{IK&apF;u!LOCN?%&C$?*}Nv-{BAwt5`65Ke#7H9z2xA z{_kn2`$YWjSK;TsPyb}6{;B>a7WIF$SXhOhb^ocpr%wK<{wG@WFZJJ;)qnczdz#~) z>VNV?|5B&_ziOZVQ2%!r(ZAG?zt#T^75%&PzXFQ>C4Kzxe}WhN)9;`7&cFQ5{{Mde zme&6cl=+w6;ynWO|G}UBEz$qs_s=iLzx)JV{}24`Q;+jEu!Ti%f4JXA#3TIo)&Bw$ Cq!$1H literal 0 HcmV?d00001