From d7284ccfe40f7028e880328566bb825ea31ad619 Mon Sep 17 00:00:00 2001 From: Anna Miroshnik Date: Thu, 12 Mar 2015 18:56:10 +0300 Subject: [PATCH] Format UTF-8 filenames correctly for download (#16556) The code is the same for both FileDownloader and DownloadStream except that FileDownloader forces the content-type to be an "attachment". Change-Id: I50abf3b0f019b773bc0a44b16536a9479f9f472f --- .../src/com/vaadin/server/DownloadStream.java | 44 ++++++++++++++---- .../src/com/vaadin/server/FileDownloader.java | 14 ++++-- .../com/vaadin/server/DownloadStreamTest.java | 39 ++++++++++++++++ .../tests/components/FileDownloaderTest.java | 37 ++++----------- ...-\346\227\245\346\234\254\350\252\236.pdf" | Bin 0 -> 22522 bytes 5 files changed, 93 insertions(+), 41 deletions(-) create mode 100644 server/tests/src/com/vaadin/server/DownloadStreamTest.java create mode 100644 "uitest/src/com/vaadin/tests/components/embedded/\303\245\303\244\303\266-\346\227\245\346\234\254\350\252\236.pdf" diff --git a/server/src/com/vaadin/server/DownloadStream.java b/server/src/com/vaadin/server/DownloadStream.java index 681c438967..0dfd9e42c3 100644 --- a/server/src/com/vaadin/server/DownloadStream.java +++ b/server/src/com/vaadin/server/DownloadStream.java @@ -20,9 +20,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.logging.Logger; import javax.servlet.http.HttpServletResponse; @@ -40,6 +43,8 @@ import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class DownloadStream implements Serializable { + public static final String CONTENT_DISPOSITION = "Content-Disposition"; + /** * Maximum cache time. */ @@ -280,17 +285,14 @@ public class DownloadStream implements Serializable { } } - // suggest local filename from DownloadStream if - // Content-Disposition - // not explicitly set - String contentDispositionValue = getParameter("Content-Disposition"); - if (contentDispositionValue == null) { - contentDispositionValue = "filename=\"" + getFileName() - + "\""; - response.setHeader("Content-Disposition", - contentDispositionValue); + // Content-Disposition: attachment generally forces download + String contentDisposition = getParameter(CONTENT_DISPOSITION); + if (contentDisposition == null) { + contentDisposition = getContentDispositionFilename(getFileName()); } + response.setHeader(CONTENT_DISPOSITION, contentDisposition); + int bufferSize = getBufferSize(); if (bufferSize <= 0 || bufferSize > Constants.MAX_BUFFER_SIZE) { bufferSize = Constants.DEFAULT_BUFFER_SIZE; @@ -317,6 +319,30 @@ public class DownloadStream implements Serializable { } } + /** + * Returns the filename formatted for inclusion in a Content-Disposition + * header. Includes both a plain version of the name and a UTF-8 version + * + * @since + * @param filename + * The filename to include + * @return A value for inclusion in a Content-Disposition header + */ + public static String getContentDispositionFilename(String filename) { + try { + String encodedFilename = URLEncoder.encode(filename, "UTF-8"); + return String.format("filename=\"%s\"; filename*=utf-8''%s", + encodedFilename, encodedFilename); + } catch (UnsupportedEncodingException e) { + return null; + } + + } + + public static Logger getLogger() { + return Logger.getLogger(DownloadStream.class.getName()); + } + /** * Helper method that tries to close an output stream and ignores any * exceptions. diff --git a/server/src/com/vaadin/server/FileDownloader.java b/server/src/com/vaadin/server/FileDownloader.java index 42c2f76e1a..b0c3bb1120 100644 --- a/server/src/com/vaadin/server/FileDownloader.java +++ b/server/src/com/vaadin/server/FileDownloader.java @@ -141,12 +141,17 @@ public class FileDownloader extends AbstractExtension { } stream = ((ConnectorResource) resource).getStream(); - if (stream.getParameter("Content-Disposition") == null) { - // Content-Disposition: attachment generally forces download - stream.setParameter("Content-Disposition", - "attachment; filename=\"" + stream.getFileName() + "\""); + String contentDisposition = stream + .getParameter(DownloadStream.CONTENT_DISPOSITION); + if (contentDisposition == null) { + contentDisposition = "attachment; " + + DownloadStream.getContentDispositionFilename(stream + .getFileName()); } + stream.setParameter(DownloadStream.CONTENT_DISPOSITION, + contentDisposition); + // Content-Type to block eager browser plug-ins from hijacking // the file if (isOverrideContentType()) { @@ -158,4 +163,5 @@ public class FileDownloader extends AbstractExtension { stream.writeResponse(request, response); return true; } + } diff --git a/server/tests/src/com/vaadin/server/DownloadStreamTest.java b/server/tests/src/com/vaadin/server/DownloadStreamTest.java new file mode 100644 index 0000000000..180b2e348b --- /dev/null +++ b/server/tests/src/com/vaadin/server/DownloadStreamTest.java @@ -0,0 +1,39 @@ +package com.vaadin.server; + +import static org.mockito.Matchers.contains; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; + +import org.junit.Before; +import org.junit.Test; + +public class DownloadStreamTest { + private String filename = "日本語.png"; + private DownloadStream stream; + + @Before + public void setup() { + stream = new DownloadStream(mock(InputStream.class), "", filename); + } + + @Test + public void contentDispositionFilenameIsUtf8Encoded() throws IOException { + VaadinResponse response = mock(VaadinResponse.class); + + stream.writeResponse(mock(VaadinRequest.class), response); + + String encodedFileName = URLEncoder.encode(filename, "utf-8"); + verify(response).setHeader(eq(DownloadStream.CONTENT_DISPOSITION), + contains(String.format("filename=\"%s\";", encodedFileName))); + verify(response) + .setHeader( + eq(DownloadStream.CONTENT_DISPOSITION), + contains(String.format("filename*=utf-8''%s", + encodedFileName))); + } +} diff --git a/uitest/src/com/vaadin/tests/components/FileDownloaderTest.java b/uitest/src/com/vaadin/tests/components/FileDownloaderTest.java index 6e0616b115..9eb6806d13 100644 --- a/uitest/src/com/vaadin/tests/components/FileDownloaderTest.java +++ b/uitest/src/com/vaadin/tests/components/FileDownloaderTest.java @@ -37,7 +37,6 @@ import com.vaadin.server.StreamResource; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinResponse; import com.vaadin.tests.components.embedded.EmbeddedPdf; -import com.vaadin.tests.util.Log; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; @@ -49,27 +48,18 @@ import com.vaadin.ui.Label; import com.vaadin.ui.Layout; import com.vaadin.ui.NativeButton; -public class FileDownloaderTest extends AbstractTestUI { +public class FileDownloaderTest extends AbstractTestUIWithLog { private AbstractComponent firstDownloadComponent; - private Log log = new Log(5); @Override protected void setup(VaadinRequest request) { - addComponent(log); - List> components = new ArrayList>(); components.add(Button.class); components.add(NativeButton.class); components.add(CssLayout.class); components.add(Label.class); - // Resource resource = new ExternalResource( - // "https://vaadin.com/download/prerelease/7.0/7.0.0/7.0.0.beta1/vaadin-all-7.0.0.beta1.zip"); - // addComponents(resource, components); - // resource = new ExternalResource( - // "https://vaadin.com/download/book-of-vaadin/current/pdf/book-of-vaadin.pdf"); - // addComponents(resource, components); ConnectorResource resource; resource = new StreamResource(new StreamResource.StreamSource() { @@ -105,13 +95,16 @@ public class FileDownloaderTest extends AbstractTestUI { } catch (IOException e) { e.printStackTrace(); } - // resource = new DynamicConnectorResource(this, "requestImage.png"); - // addComponents(resource, components); - // resource = new ThemeResource("favicon.ico"); - // addComponents(resource, components); resource = new ClassResource(new EmbeddedPdf().getClass(), "test.pdf"); addComponents("Class resource pdf", resource, components); + Button downloadUtf8File = new Button("Download UTF-8 named file"); + FileDownloader fd = new FileDownloader(new ClassResource( + new EmbeddedPdf().getClass(), "åäö-日本語.pdf")); + fd.setOverrideContentType(false); + fd.extend(downloadUtf8File); + addComponent(downloadUtf8File); + addComponent(new Button("Remove first download button", new ClickListener() { @@ -131,7 +124,7 @@ public class FileDownloaderTest extends AbstractTestUI { FileDownloader e = (FileDownloader) firstDownloadComponent .getExtensions().iterator().next(); e.remove(); - log.log("FileDownload detached"); + log("FileDownload detached"); } })); } @@ -213,16 +206,4 @@ public class FileDownloaderTest extends AbstractTestUI { return bi; } - @Override - protected String getTestDescription() { - // TODO Auto-generated method stub - return null; - } - - @Override - protected Integer getTicketNumber() { - // TODO Auto-generated method stub - return null; - } - } diff --git "a/uitest/src/com/vaadin/tests/components/embedded/\303\245\303\244\303\266-\346\227\245\346\234\254\350\252\236.pdf" "b/uitest/src/com/vaadin/tests/components/embedded/\303\245\303\244\303\266-\346\227\245\346\234\254\350\252\236.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..e44a87e9adaa3d4e3d95d0c38506739df3ce7df1 GIT binary patch literal 22522 zcmeFYRa9I-)Gmm-2KUAxI0S24f&>jN!QBZo?(P;`8VT+eAO!bdjk`MpZy-2a^2@Bb zv+l$HIJ4Hgbe&UGXUkW%*Y5i0Ri$OvxY&8n===Aed&i|$`IG&FXdeKa04GyhG+|)? zhoXg}704RE`&Oj};E=Jg2U)nhmG&ke3uy~8Cvyvcs3@8%$i>3M0nHPZMFT~HNn;XQ zj_s2&8xynA*k`5@1Tn8OjjN$=fkr4d-Fx3TyxpA}M0 zj-a=8SHM4y-pp6BFt;(0bn*n~bG}vZaPtDVxdaT*-aPm(J^#M@Z_ia-oXpfMKmh$W zWzsSL4ta++m6HEeO8r+U4=@05=%|?5T9|5`K19E+PmvVA&c5?jJ`X=lD zFsT0^`M(DB)Bs&WL*AR=e28JG-4zNM7FwDTW)K_}9Jb`#%E(zGkW_3CirzP0uo$!S zOFZFr=lf-9sWE@k6Ca69+$3uvgMdtei0n)}37dHqBty9j&lVgwDUKdzSTqGO(!BkA ztLbM$NqV*6ialHXxL~AdH0N<#+x2HXUWVw8wT+E@q+69?hj&54!m)_Y-xEf$`(d4d zD8EWzcm0f_4~Mk8M%@QK zUAI1FCEVyw{VGq=Qc@um$ndVxn@0s#%?>ML;}jlawXYAg9&T=eu%&f%lkDjmug@FE zn6$LCVh@F4wv2^?ug6_4EO`c>K1F+vlHWxH+#wt4kiS4YI?d+u2fN`X+3$^>28_x~ z_q%V77Yc3ypo{_2zN7LO0AW#4EZu|seg6dyzw~6fG;XoiD>1PTAI!B8WAg~$R8YY! z_DiNq^R7{E-#>k1jAdtHsvF&V?0S8q67f#S%(P+b9wIw@@(8%~cruXk9Ec`>WFP5o zJfu+z2Hb~;-G#VUyli5>1g3uojfsx--?#D~#1X7iNFUWSGI|x+xDsjnWI?E`tlV4) zH#mV7R2l?PR@8N+a(;K!*7ewSd$xuLPm|AM{`CMt5wWxI`ZV!+K@xQ&Tsh?xbokUL z_SmS*iU0d)68m|Q;}yz*j*znf_3jY%CXUArVpO)`yf?-HO`jQGzAWWEFIkCRWfm0` zZ9I){fUGzDw$P1mXlYBXAYdVI3Z^**g_`2Qj~^etmfy9ZOIt(Jd;6zv>!;sVHhh-)1LeC@netfU0ECOe4PJ>>h+Q;;Gr}CX!#fn^K+k4)Rzec)=5yJ8x;)x5TUalMr4Q*CbW>Y%!1efw&!4|4RhBlfbh=^t>r z=E3s*eLR(z|HY=nMKm%TtYJ1O;f&Y$dPjx%SaV$jIY-G=)vvSQ>HAb|LoTA+g!|=%PKLp>wdcPrUE`(P5&u?< zLKX5V{=Nn=4+{ce9Aq*jyqe;8p_Ztn))Qh^#-KQZu-r{YNleU1XOfO}B)qbQWeS|A zutk?W$a^TygDYHqN67mwHZP-uyNW_ZMWs@n6~4|FJJ(r)?D;m}wZ%d*78Kw8eToFd z;==7|n&bIf{#TQ^Mb4}k7EOJ9mPw=*V?C?#9#rsnF1v!JZ&3zByXMPQ*uYj;;Z=!J zcE4_8+h{rmkr}!n2cvhl(ECYvb^*pusxpE9WC}0(ayhR3qPN!l$;-0AVU5&C?ppx| zwp*y#L(dNfPkL#EFwd}-xZ2rO>IG&5g%!G5SXhj$N*FKH7{D2C5sqc&94@su<%wfY zFQJB;W)2ka*pvSP9lbO9w!LjCG1|-K?0p4Q?tQ&hd8L~icDK*E=`Z5R$l_vCYkZr- zR=k)-0ANUmx%=;I7C5eLrJc`A> zeszx_Z)({4EiJzVhJ~&AHUso>T`ESwW7im%0ZAKmx1?vad|T9ZU4QM|1xdFDz`Gv) z2Obzu_jG>8Rh$nv(@R+V2bbGvrkk%fMz1%mOH>zfwdLhU$H$GVV_nZHU8s75j!MeP zdJOo|Xoe-mUP0PJIl>I!u7|nWEcJm{+!@_EEXVnFaZvcU+kQK%nYWJ*VjSXQ46Ax3 zZAef4KP+Mw?agu~z52p28#T$){pTt)gVVyAAQ_}%a7651a1KND`JL83lt#;2=@{{q zMw8Iy^XRm4C11h4?HC7SNhkQW*<(~H01|6Q5$6$rnfj}CQI(3{5GIQKWUvU1( zQJAzOI0}VerBhp`)_P_V|0RTcBEt(O`IX<&&E~n*SH;Hw7NJZK)Epy*1sBkTKOdMn z{Ilt}{X(<>MrVp=!IP_i-5fM0J@cDjkYa`6ASL58BmBcq4+K_%!6H|3 zQTN|+idLRceGQyxNs|+ZH+l%buG@8=U^wE=6=PjQ!uzcVDzs|=7;#dt{hx^HY?g+imc*TM%!gObEN4o&T#e26I5Q+^ zP`0-TWfBbVKk~#qWPN#<;qSUva;;}G>nDSE1~nr%XeB8hvU;{TYk84`n)zGWYLR7| z`R8+piEXIDxHD6NyUrgwC%84oYH_d^6}9rJ56cKLY%m{|+{AOuB!2j_ z;?(uFNHrTfvlE;H_u4w$Sanj6BkCSWmOh{UZSV0g$m?4t z=HK8hdjAiC0k=x+jYLOdW|T&YsNmD}kI@{myaXru;VQK;Z7jaHkc%)yUP1J3eS$h< z%_@Ym&Xoj88eG&H37oE-A280xxxEO#44pOB*jACP;ehxSt^ z4=Yny6CrZHPedZb^g3tNP4eI%*9Q_+Az;3VjBona%lJBpR+e=`H}Dkm;`u&{5N>?)=lW>o!cIWdIKoDP^$ng4<%^+!r=eh| z!0R}zb1%x<#M(Kw@qNz-dPx?$#}geE4mZI>5p86)HoYOd_F5#vsQJt}wc&L@K|I^N zfZ+dLQyj;+Z7rC4sOYMS&m2l3Se2E(tL!+SWOawg()lB}ZZR@=f&+aT+G1R-s!ChL zlc4Eq!UziIO}|SKlIP{tNpLY&^@95_iv zb+uwr?eQ(Faqsi{@9-nsNCNeP`6}fuUqp~P_xRncQe$*<+M_;C!kVrJH`Q%znS4Ft zI(pjdfv-nuYs16CGo|Tg6~hZuxebx9VKPjNW=W6~LtAV@#A ze}+z=qv%DiaX-!4khk_LLjQ#+Trphwuy>%0J#~Cw&j4Izi=GAGZ2Pf`+#!Oj` z%LB$F7Ky(he`V|s;m>pOPE^FaE<9@_zVUk7x_H`2j!s0;`sQXnroc@*g9}#!cY6GD zEH`DU%d@5NZ2lF3ZX6E(_CTXqKtlRg0AQUCXCu8~n+b_7DB&3Rq{IY^zL^QLk?r=f zj?m6Y?_56a7s4XU`4(8e8mJn#=_fWlI5>OmES~8ydP*RzyEUj|U4|!cp=Bw4dEv2w zpuCM%z5&9Xjicj!7#BGe++<#llYJDAz5F|l$HDYM0Kpx2(@c~rplGn+$K+PeDCrPC ze2<`UIS$R1t5xtcunSRNk>aI})f|m#2A--@qIFNUqF^MrmZiI8YIA6ntrAIpn{D9* zBeOxlvwq4Em)suyphmK5!|4{${~&vjO(8N#7_JT$`Y-CmJjF^|_jR)ru%V1sNUdC8S%Z3Qt^cY_Psnm&ee~}6SiXrw2cXo=fn4T^KEwVK@-(RN4EjL!e-b{poj#E_PM_xH}Ef zc}K5`6EO}9I%mnyv?^tLY!u8>D3$LJQYQwI3~75e)1o)7`kXMDxKy8Pw{bdRI||H3 zA8aX!{Vy29?jbZ|bS7U8rZYDaDQXj)2rD?IjbCmo<}KnB7-eV{;XS1Oji@DaM@L7S zQ;1fyPlozqwO%2WkrNuUplqH; zH3!L)5vWkL^C23{TBGSD*JcYnhHIj*ow*y`+=PMH@;RKySc&-^ucO+HZNbApS~ON3AbwF6$trT^_l5!F3eOKQ01<{ppNa_`l`b@E#I zkA)*W>Swtir<~cP{WDF8gh*P{1a^mQ_)8B#X6%Zc`5T;yb@to|pU&QygTFXvRttaY zsRg+OLAENe{W(zd!NVi<%*mF4lstXZ;lgRCE*n<{y+hCy+wfaj~DGs{C`brG8*+39N!8?DQp%2enP`nb`Ix}5r&zl|kOm^rMp zB*I6?2u{Yn3R9v9(?cRKX9gFR<}2M+lhRH1PI0%`_|Q0mVxoN0A9%jY#;H?9KJHD# z{Z5VVjQi#uG7m{r%hZ!xC%3K5zmBdNjmLBU@Oe5b-&i=f^{L)G$#~dW>XL!>hl7H1 zcoZ4>PH7z^5`J4x1c}%qu#UAYrZhEOCb=|5gDTUETDOxgRrUS0=X7wa$2U0*(UvP7UqYf%u8{s zBJ@OQMA&si;g2Mi54g#YY9=#9S8J|PxU*{0!h&;zEZg5vNt~Kjm^wQqKa0q_;Nzl! z)Py-fY<%7b^Oxiu`Wf<yrMh22sS_whT}knc2L9iWnm7kcR3d-K0AECIGy0M$GRD!cyt z=;Ev5r*K!IN}I-cb)Zh4LY_tu2GGlIrscyIxS+diamzeQa5(beVU9fdAk2gl86_1J zG1~9}lLMVC!DxuUhWTIl**}rgsd;%wat_`A;m;qR3!X&s1fL@1L2S3T+j}a2|t11%2#L=_is7m<1hkk>~LqT{qFnjbXQF z1+x@>UtoePp~yAEW}d%ge>n~gz>-{OlZNZUeL9eeZr2rK^9p(bWRd*#FV>(O(RImK zY^E~EP07$)-xh2|gL8U7N)_4-_*qB@MU2<*dbV1f{qeg>`xMPk4QuG56<50{6Sw(o zm<9}XW!xMFp`QIxJ2H@QuW5L|Or=z0J;BCxvFA}OY7Bf9qq@iAp#HgS-)!6@En?`$ z^0liy9B}}NUm)(R1}!M?0@3oDjfbxAqrMWA1W&=#OE2f|h=qtt%qc|TS*T85r71;|JX@rsmC!TY>8{-A zfHx6XBN%EA#4Q14ZX4bb8efJF{td4x>ff^od+)X7Zf>ckMh1suw?VHayeD7D{8+-6!u3?GNuC z-kffpi`p5aeW~b%;6^ZIuKmV7;)w~H-p@Y+qo2>VI zU zslxO~&`IU=Blq7P`P{$B8loK+V@*vQM0XSm_w4x|T@D~hJBKiG8&i`E+xbg;E32nF<8)$~DD?eHO zEgIDc{3>A^%v5oGfldL>FXTJRCR1rfSJJSXJxbGqoMIJYL=Ow`Q%s$C0E}jLCsTsr?tR?F&wthLi*kr z`jLR3dNTJPfF_W8aUj1bCS&((*eC^Fur zRCGv&&Ay|72bKGT=@;_Ze7m-w1-XwDh#@E6QX(x5Uoc5+1O~qSMdVucN(W zt|28nEtdx1TZf47%z}cz)a$U>bEl;ZCn|mg#tW+~7TSoNZKa(^I^xnWxZ(&nu>Z5d zlL0p}6dC>nM&!v)!XZYxY9#zo=Q~VM!!iYPX#yJqqR-w_l%$=*R?i}LJzDH7Zjcpa z5Q-lMvEln7t3N&YeWVd0c5nY2^ryB`u1I6``wsmsMfy4OC4AE#9LOoV@_iFidQ(>x zu-afak)rn3rZ(dyO^-Vz^f;kuFG3g z0hFVcZUoW*3svsAFj+E1B7&3OjcR5G)L9mr&Q*qoX3>5oK-Jo}tZ1y4f5Pc5gb zUMUs82ICvD(1hc_>Ld6L%`>lYFB!OMWlK8=PGB>1d-D{egcc2Py9na*q{|dEj^U;) zJS0PXg;gQeWnGn!dHUBgja*(m&%GM7uqo=6c-<@ve9_8pT+304KWZ&GjJ`_Ujk{+S zCG`MrbgdFi((h0DcH_~UkTA?}V0qwRp+@!>TJCUSjOF&_ zCC3D~91E3#xHLreXdDE({1g5|@sharJ}uDj}2!H7>S)<}$rqXik|_;kUASK+=8 zd-gDzP*M$VO9FylvvBI$7nzpi>V%^-LC=5M0nZ4+X}zM=CA#zt$!v-hdF}6XWLWm3 z8Q$BR1vd@hTY+cuw`s-9gWa;Yl7DG`l}1=29}0qCp*uwp%h14iBit33q&^KK*2$7J zPVaJPTvbhITlwb4WKT=-yEBz=g!m3j3C`@)e!g$(Ec2^Vc58RKxNago9BbW6#!j96 zQd3@5RrT|WcA+kX{IRgfT_>nuM1WMz{S>I9H-kewtBAwMUGx*z1&3dUbCKx6=g)g+ zOC=tm*L05<2^O!86)ebI$5Wx7^BwLabvF+`GZ*cxwWy#Qgl0b$3f5>l2Ih`WIfnp| zV8Im8M{_wL?kySM#mX#e?gV8vQ7jh@GS%8LrHZ+cpnk~N==kXO;SyT; z2RZYABTezA0WUWG^YAghjjNSb1*fc4%QiVJ!9lEZ{*^tN6Drvo+8D4gsb7i%pwBt1 z;#VbRqFsT-{LK{6x_p80kWI4v{n1b5k>mF3NxdQ|S_Vj;Wazwc?1*Dcyh8)a>KKJ_ z0{5UjIQKN=ABe5XS%JTOuJR3)&4V$s^nFfi8iN4(it|rqmcZII?NY5weOWmKpb%?& z7CC%mAU#|X%=y}~mZ3Vly0W`rjo?IWT5xrlzW+42klMZb07ePACe{G!s9BM##{0c? znb0Zwt+5|HifB2Scey`BTOYNjhQXMjN^%_B3l?C=M>4ReFbu?4*KKqAr>YcxW}fNMPJYIr9On+ z?GL7C5Y2V~me*#wBYq_c~{~OC25w#4Giu%S?~Aih|i5>fB2N>pY8( zx{zX;A1|8TpQyRpGZ&a}-FVysrCVt18g!@|kM&cRzOETauxiR^mNzF-$TIBIj~~DvklY+`D>{)>5Gf3z>Xg zdNCvoyMqmw(O1IX(@geiNLv%h!EWc)q0f$vO_8|csXkh-KCV3@W-E%6N4r&KZy~+f zhvu>TQdI+4GZKpvp)!X6C86IdK#8u>ABTqpem>X~LSL6=Si*jIOcGZhAj^jF!-S_t zb_)Y=!WW1(;ohoNFbXQ(a>&cb(_A2gBATEp`gvs)x59OF)BS zs{&3L@Aes-S-UAycVkzPn%+OLB8~a*<|2?27^cH7Oa^^|8Xld z4BL^z<=WlPwzdQJ+v=644R&w&mkQX#&nku)#THy59SxKp3rb`O3W1vA(zzvJ#Dde? z4K3NWmdoO~h`V&{`;@v-RncwqrD4SEYUQ|xr31!c1rKq$*Vh$GB&m%*R*iJUr%HBd zta{FDxj$vfQe73UBJ8>dslGC`rG*neAbY8KY3nO2_E$k=bj1P6=-1d3X{<(?Bw}3xJWDuM zLDWWd=DKf5Re4&;!%TYx-=t&rKBAY~Xt8@eYm{Q3Bo}d2xtByUk%EA!?Q)XEWvu96 z;&OEL%G6BM#84M93Gwon;DT?_1KH6(4i`z=XbmSYVe@$~kSCD`&lLy{;BCH$mJU)K zLZXn>2i3E(5=(la_nfRY2SwM;E}uNs^SnI+Z1qH`ls5tdp1VPxuxY1%xGO8kf~@GE zoZMytrL;UVJb&()xC_OoM52YgKNJd4O$d8GMS|Zhs7&W2#K~TN)et=h2bRbn5F)@z z9_Y82061NAX}LM|WX*qmc$Ya~{RK(wxYb_jKz`7g1*m{s`VkZ_UBcQ*9s}`ahi`H? zvM=Ipl>u_dF-jL-g~3dcl-L-DFc;PV$r}Tce#b5of(Wt4y@4|Yy8J+W%yAVmaN&FK z0lM#O2+9}-Tvk0Bb`POhy$Ps!lRFk-3PfjhAkJ5^pxXS>$ zXAEMjGoWUIDR2zbZ#35#}8{8-e7nW18f{yztu%FaPYt1ITp3+KxZSC0fo+1`B z;%6$ACOsV6{&CcQo;*LfcBXLpKBPah_z?}4#IEi$Bq}@j??>(^c93+xt3CXqMPF)p z6!bhh{YQ)orq5;z1l#N92A|cm2{zq^Q#{epH}y0pqg2i91h$`?@5UAxYU;LrsW9r0 z=LJ+d;)k1Mx1rX~A01VBb@%o>bTv$-C)PC@UfHZ*jnDK9J|{lRvGfswnxP>6co~g5Onw4Jig!U;afdkhbuCqrzxIo;A5Uz zb9~5j=LY()%A78`C9W$feDPAe!-%S;^G9_!6P~|V3Jq21(&KqBcCkKLpX~2gS;G|S zgkgJ<9Pge*XlrY7F}5%AFjf_b=zH467yBTF5kV@Jo_L|H&vL#_*1_YcEh5V($e6(f zrtL|Pc%`Mb-1ZUUHSed{0IP9_XiH2EQF1SoKKIdN*AUTw! z!W}G>I@n>z(7oQ@lplY3h9;za@*_A_Z*db>Do(q(@F`ij{dJg-Q=_{q1_B}hMmvH=wMp(hX3>Nd49IX`?wfx(0 zY@}a*=K1-I$QVUQPABQe@wm0w4YAeJabU0_7xf~93)oe6xkpq!7Q=Dip~$pew{?un z&ybvgsxW^l<`Ge&1DihN_+>F8N6u8+iTW1L0vO?FsIkLeJn1QOkQ6VqOB!E%ggkQg z9{#!`frYOaX6{{Djk`nm<0$JP`H|C@a{7!Tgqf^ljhFjGlXj+YG(3}nt?8EVS8$!X3GA1?+)u&R=JNZ3!&_a-&!HqVw#l7hTa#{r?TmM~x9stKeFm#bqvAbA zOJ3le@7`^H->LYMCZ%L|8b+4+>EFV=J;pDy(gBSk7?+&3>i6r<(g3g5;oc{M&~}#F zxv405fI_^Ok-rNgwcGMkKECt$G7{=rmTU#=&dUl#dCYT`vN70 zKbxfsO8#RkI-JW3^fJ2;qxb8X&4FUqK4ON7&TgDmkfWQ}-+3|`GGRg3wEpn3sW1e* zAS6l|hI_xxOZ;=|ZhQS{ft!R2FIT_i_^#e*8e@$*3<9_+_H#jg7-_3~vXGp~46!puXXBRX6?(#Cs=MN+Q_Y>LbAJG{ID>`)B_rsIUNrbXZO@B7zS z@3P%V)oebJ)=*;y79W+e*hXWwMRs$4pZ6iQ?fN0Z;Edf`-)b7)UBMG&AZZZSnzb z@b7Z6%Hm?Un^peRfjk*;JiSn~pSg5%XSOpl3MdyX;yeQ5OGzOQ*PN2rK3_fk`@C$`A7v~jVlB9Ej82O6&&DDL&D|FA zx3f3=k=@z+rH3_jo1&YX6yVw}iMJHVE47#8bt z7)>1#lQ=S;=jTMFKnw-bs#I>7XGB3A;J%JJPyyc>efmM#4K>xhy*b7Tx9()-^6d>~TCYkwy{Bi^w`?wZP&phwG=ng{O=Y?UOmQwvqaKKG zd-yx{4JQDBqR^&>#^D7)X<4g_Z>N{>Q){$lvW9YZl^qL<%HK*tIOtdf@ih*=ERtA? zo(|Wv>Wv7sIYyaM$k&fe*Jk5hr z$S${y=6q+z<5H&22eDgYKY-%SE!O+;%_&xSlc>7K;TaM>uijh-nS+VWlCgLvZ8e!% zfIlY?*hk-5xiV}sVX??Bc~k`fyTz#A*5Cs9vEI&}!KwSckZ#d92%`q@wjG`V;qYXX zvGC%T)7g5P-7UnR?UwSrfal?)&suT{Bx11YNU_=uXry(tswF;{eqD6}-`411WkvPd zM}&jp{8=BH3A|*!lnXJxR@5Feu~rly2J0f1jF0J5P3vA7edZe;WINp_1@FOr_UG0q zoBk?$svrZ@r_->Y&L;>Q%sNv1J_J-b_<49uD*owr4Ot0D%VFO-C2L+7%m`G$`wVdW zv>e|z)Cfz>cZl~VWUui@NhQGxoBE(f*1hjb0lot3jVtz2>yvL_^O3s z@_z0%eCg2ln1b6+)Jx<<5TWqTw-J;3y_iRScJt2m?8(g7W(9W4hFcEGjz)RD<|C%| z-L*DoHW87Ia4f_N(DlPMv@_uH?y@g|rTJ$AD%gnea!x9A)LA2NYdF>cQmu44S4{Bi z;$%M-zQx~xaS{}2F+zv?Ae3pm?-^CEBxA(`J|a)^YR;@5AJ(aCDB&rM$imdJ*z}ab zbcxIO5e(g-Pl|_#5D41Tn9i#g=W-LP4%?FYS^rD{s)sY+d&t`+wa?0HVHgT~CkE*h z@F--9gYAs-TrDyejLU*Z`-UGCY=KWNSlDBQ7G~LAb=r<%Tj&UXVt#|(vTAL;f7AI9 z9-fM4mr^yCDqDLqeAsxexQnjm%yEsDAfileb@ASHEpsi%Pq|m-gP07!a?FA&=nscI z-dx58^f0gH;X_4Kg+s*_k2FAm9c#l_ESL|D8y2XoP5?S-;OUaaSb^*IYz`{0}K zqR(@U)n9cBc<2OuuZcyju&KshAw8>o^i**P$x};;R?gOBGFF@BQ%z(P+R&b*w2R&s ziA51^)sGk_^w}fX@Dxf1*09*sMVC=4wFr&|ULlHQ7TOu)d2ToJ)s>~z!meR! z)g|71M%QalpOL^mRMbj+N@4#G8cK=-7P^=%j=VX+m!ZUQ{fqmD(?B6YFe%0j8 zXZ1<1YvLW%=A+7+TdjSi>BdkH0?Ix{ouc}m4%XnjC96Tr>cuXyD)34P=GsW2uvfZl zD^rUzGoE@ifcogBR-Sr&KB}6dqjMWp25frntJI7_rzIOFZS5T!JwNV7)tFiNgU2O; z>b^b^f`}+2N6~lX08t?bKCo_@YBP{J99!jn)3~0Gdl+T zGPsGq%WRqUX_)d~7|DJgDihUZFbdBqFO7iUYT+9!D6jDw%0CRFr1c?LR03386D^b| ziDLY5fVYX-oD7nb&S6}xdKRFcE#K+{s2gc_?`cpo;t4hn>KI8X^j!LE~c_};j&NA^bWF0|g6X~d2fgs+5sG0I(_XHR(OWUfM19UKc8Zh*ebuy;}p^cT|4WYSR&aTD?I|DcKU z$|TEKMU*a^ArE&-+X>}I{?4DyHrcMLEyhfahJ_?$va{ccvWoI`RNI%vJ3-msrfL_q zf>MpJ*_e-jK_0U%#5`0cd&g@ohBWO+*j>fxBai;_#lj&}4Qvd}#{gMM@4x&h8QVl? zT;i8>ck5jl*WwV^AS0tBN5f6lZ>e{+1qpb12!M>be9XNqU6=&kWzC+?Gc@i$_9P`u z`YrA5ugBzc@&kd~z!z0rke0ih7%>F}ML;*J<2bgAR{0Mp(h#%Y?5ZSv+)6pNIBEn@ z{AwbSvvHYJ!-Qn+#9p#d2mydbNfma0uY?cDYctXF;bJ><4xnWAwWTyxQIB-kb<0Mq zNIWhE>oQfve9zPIqHM4k6YRijzsoIak~%xc%(K@p{-|DWSin84n=3@d7oywgPVIfw z>+i#8#{FE`^5X#M?saZ91+o;4-0j6yluN1&)a_Mp))Y{=L7*=d|0weiF11J5XZCL9#IZ;mSTL#dEub+dN<8bK2V@>R{_~JY?}em>LD?pAJv179exC zb7g(YctE)P8R+O23DUGmh$kSGbW>ja(?9GTsJp#PQ*!9x{;V#EYhD&-{BAse`eKeZ z`Z7;%O;+9YSfa8;)568X!H|J_2nO%a+ls;OmTXJL#!htOMq@-j^j+(cWF7QHkE4!*6ky{@U^em4_VAq z3BDBQp3meC5sGU@cDGZ*fGqP~ViI~?cNzvJt6T#cN{iiOhhwW?DV5Lk zV@j**OS;-duLVQLm;SqL{vCx^NPpM-S+mZm~U^n zas!w0SvkVMF56f^yH-NQuJ`3>M#I{b=`^UQn&YAM}1?niw*GH7oZ7Yp5vL*(Kl7TK{}_U@9INKcG-6WY;S! zjYOT0{*0l7F=4yea9e1Zu(0CYaayuL^>Ys1%43u8=@e}>xG@_^j!sZs_$gI|X0SIg zdR6VLf}0g4V3_U3JY9oYzRX%Hbrc#6lT={iR3F@9Qx;{TM!y_zgYW<~eFWJ_v3^%3y7D7?B zz|&JuTJ|oS0ZILIIfBaYeiPm)rWO+k@zAQn&-w55nn?h4cV5fGAsckzp?z&Zc0#D- z@zAT33a-QBVaptr5PPkurPfIFXsuJ|nb0aAfJ)^28e1IZ#rB|E{IwhKrJ;+pGw;i^ zt253vGE$t?D?kwA@&n{y;*H0)h4fSm3+TuB@_T`GercnifEp*XD?H>Q6!_=(c+17y zoUY`F0wCw%;p5}u>U!1PEzU{&;X}<9RKDqE@7A`U02wJ_^ZXTVh&guhA1C*JCmjEy z;{Idja`AHV3j8-^m+K!#`2WG#<>Gp)dm|Dnzfq1kB>r)s9p4zZ01jyjcN;ScHQ6_M z@c)5L`@d17=XBk42n}Y$d>Gwk!2D}#fHm+pv{jHt>03f#njVG8U_=T92@o7jQx+H& z92p3p&JXQvImA2ndE*Uk+)lJCG+6}*yj@C)RDwH<0N3WfN5)mtw+%11HxQabQS=h%0}2;jO|NzYn&MhJy=^zW~G{etG?v zu+U`;*K^|pMhITmxVvra7TF4F^6L$LM&;^qeBsE3c}2PNdj^(mrLj(KT>s|3zGyvE zp5zOzt-A2SIe8tms>A3%!S!54E1@t+64zF56sxbWDyyN7-ReyAa{jrG8@@rZOG57G z_{=E6HLpL4KWNS=GC}*63lP!vMGcn~rHwe^m!xG)=*vJJ^fO7)0&<4aqCF5FJ2*U+ zj-|Cl{LKR)^v=jGY_?zoFEg%gTC?gc9(?hakdfuyS%di;WoV_(&kkHwgNbv=0XJii#wQvU2|zzs;a_xT_! zyl({b3lxfd{f@WE74IoKA13&i^I|pDMHhel+#vJ)v#I>{kP%ZVJOE#Nuc* z1W$aCXp+e9=Bj8+m?@;6NcNfG3@&izPj1rVWFO!iJ!J?H2bh*T`&J9BJf36F?fvB+ zpZs2_2x0Q3QfpGXSYZIGw4^UsFq3F#@u)YKP^=-lZljtAly$(Qk|F{JJvH;!{+9q( z@^Rg+xV0ZoyhIXj^umJsp0Dp;DdUHx1FR|MU_cb`fdWTVr03-1%~Y_S;-`eTr1$z% ze-49@=mO#5RT;Xmeg?rjs{&KtQ^iwNML-n4P;aEL3%(u_d_ZTDFe(s1cqb8_|FMqx z4rdz$F%+p6#UxH3>OwLUV2W#nLxlS=^1U?Pcf6?tVhKfnCC+H11D*Icnxmu~xz9y# zYUnoMAaQRRsidgiAIxDJ(3XNvB(P}nXsr@iejDH;eGKU>l-?4UlckVtEs#`=D#Oq~ zt-zX#B9#`A9sfT68QGdVi-0XwOOh=AbkgvU=~@s3`wM9;s52o~e4?<+gp=4CLrjLU zFrj|v&UBlTBx5u~OOeWwoF`&w(6nAr$D|5v9z&r!+-$-mre0~WZP9Ac>jVpz85cPT zKZ!jF{xe|8<~!VXr0+t~6On|Gf1{YAyrNPg$0OIG%pw~jYv0}Ch|%XVt}_h_$#~Uhre9(nl$Jc?%f=@l=U9@tZ{3BvOTO*=ng% zWxw!WSr3#q?;@&yk1_&k*aAFcROs1sOm^ zf5r5SUl}EtpT{J}2**B;?Ty`LYU^0*rs%HfOzSw-wOf9yL#x+o7_8T76t!HlG_#s9 zL$_qHY#VCsRi3DUoQ>uV`A7Igg@j9`_C?Sp?64162~!xtpC@qiVs9@9>I&Wn(h9H$ z$_n1L-nGWNg7ln-)D>)S-!0i7l$-ljUa$F;@+EOv(0qR*Ny=Ew0;XGI>!7A(-Jw=zzfwz+nV0_CeiC@1BIwns z+Dh0;??vfFbkBXyjHrj`8io;u9ButkX@G7(Kf3Lc%creR{3-J(A5))G$Wn+BE~%~r z+;0|h(9+Q)iq+nRyY|m_?~iUWaq4mTTE%}Q!1`+j9Ws6rQmTF0h4N;a>XJMfjZ#-_ zY2UPhwetAX^i}>>A?F>{)b{Lg6a;}Qh;*bWQWZ#op*QJ8dM^pm5+M+JxiqCoQ##Uv z6afK21f+*v1)?A=NN>_RNC~{?{rT?o-S^hp>-=%{cg@**&Ybz@%ap#;kUP56)kzk)-5BWdah}s@-fH>~v-pHlwll%jp5A!s@y?~tWz6%7OP^PU z%q`!!uMs^7XWY43((YECyIyr04`&}bBfTEfkJa6;Ib% zUpBvtB-SN4xk5o)PNGQif`ptTiyTF&L)JrSLJ1~&OB&p&`OG71s5QNeEnmA5n#i6|ilxMpUmM6uV09p>ZOPi}h4Nf;w@S;%%RAdN56 zG{Yx$33bQ=x!uT)Q+{UFnftJ(FQ>093PrD6vGBgP0yrKxo{;=SV0ck`v3;p;F>S$f zX?AaL_rq@H9vfXZjXq60jS|fO4I{k={T>aR{(@&mAeCqMo+H0CzdHYEz&LKV!u4SH zCE16_{m90<(ne6jRRd4M9Rpf@>mrU~8Aw&FxSz(XssA-M4WE7twi%l${;{sb=lJA= zc;s1$l7h9uyzWp$emQJoX_M~r%U;8ik$vG$be|88>pmXz+*A@F#?oTV&S!ABCBgX| zZ>d+Gub6M`ZlP+wwMYeR2amgH8%4 zJFmU894Ks( zAdpW4d#rzMca$<`jQL)^BZ2vXI*=I+klt^d>F5qwY5%^k)03>noezW7HJSS@Uf9oj zEUe)~3Z`NH?UqrJJ2I9PV_TrE1k^T_I;C zKZw$es($I7+$k*)fU=-~PFaW@g|4cP7d5Z4AyyGFqZ=d3B61=WO)v+L;|Q|H;hICb zQ`0Hkw&R5_mSRYAvb1$`8?`aj8t{d3JtikBNXD1qImHw!F*7SMwH#^F;boN?MQ@+W z+f{S}x7KIBTK+*0kDeCm5F{0a1U_P9s0gIFN(tup<9b$HvbOkRq7!j0GK50A;`2Mu zTPAlhIm}vcd5>Nv7P#i1Rfd%7+Hji~ZY`1Do>pYAl43_C!=}N*(b_jLU_fisd z6TJy#2w@C`EA%R|bTG6-!o60?(16Zv0C+=@xg(ks+;H?%VFd2Q~u zo<~;Q8@b9~rM?=#^epX$X$jUwTo!KRrR-#JQP7f2W%K<0gVdbOr?bM}IpmB&-@9Vif5Whw+%!X?j7hBs=-4aHcah z6>#D_AHL9iSlII|$=HTjy}>U?!^%N-@eOwm3GX2M3^S5t*3g{Dmkx{D%!*4h@pa)r ztlTh(cHiu2_;R)x)Ny-pZa{bTeY~qe=tR;KpLrE-xEHZkb=d=b(0}ddCU+WL+LKC9 zWsijy+NIpThH%1e#9*Xxien1l_i^6yEHlbW@M!qJg6&(~sD$@&z{MxrtTH7^#_#;G zP2Q=?EcLWb>gSCD4QtK$h51HIe3k@SJ8K4|pf#X1>1(pXw^`MHv!~j|iM}AKVeQW+ zj$8=gx!{eAGi7W{@t%B^fMAFqlOU-d*Ga=W$x2<^;+LZNv_5epZe9s9TGHRlALf|g zR5$J6_0W^$DCiJ#QFuQ71mNcVz2L$m+b@J5hr}-Q>=~b;*`vq6+%fapY*rjMTy*I` zuFSMzv{z8NX}#gtD6SVD5|F6CAe~^|*xHcSSssCzA;BbN-FEG^Z5!S5&4@O5Ul|`e z-?r*ISrxr+QO@Pz(cRC!*#Zg6HFjJ{)OhvYKvoc-mmrDvw5}(vh}}@KRkEna zakWS_pCuqS#$6Q<;!YIz=e=f>S9DOcNr$H$!UAaxw&vebm-3D zmyW(M^Up!k@hxPCDnz5JUni{9v%QoJN@B`&-Jr=3y$Bc#ypAm;)NqcOu3Y#Mnngsr-W|Z1B&sUeo0#R zFhs~JIB*Yz`xA83t0T(j|Z4t`39BnbDDEAoX6D+{fqhWD;dvBaxBB6%& zOg+M=sO;J_^OH5u#-6~gf9J!Y^|7$Y7{9#_S%dT^^i5CbAfAw(3lO@qA^>LXKjekL znGI6lkQ3;ZnAG4{i}QluiVBZzTCA)$$4Fd(wnL$CB`tBpG2u=5&Gv2iZ33+iTFN8Y=I+gtEg8-Qv{4U4 z&GOGtFRd+#%s%11e&;GtMQBY3He@)oOTm05Mde0Y1Z@;~xR=^D70G1xq_45!oEp54 zTO7CClt=UrGtFOpMW0={BJPd4ZnSOy(oWO%)PqXU70Bhqm-W8ImgX0HcpYFcU&9r* zp|nkvC#NV9^-O^Tc;it(dxu?+&@Of2uA zfUAiVb5}dBY(4Y)gXP-VAA&Dbo=Y;mX4ar@WZDxwgqi!E9fW*nKg>hv9VKvU3g$Cs z*h+HyPOZwR*uzX6PcomwQ{CuC-=l4}AXvP5eXh1r7X{KN_J)x@=n?#+~St1Ztalj#Z{^*PV&%#nJF zlTc#GErV;ClsbPDOI`IhK7G6iyhzyo%xxV%pM){7Fi%a)@HsB})*rfpVr&zu(4x+2 zDp_;@Z<4YcUwApLJl1ILzT~XIKwwtGYBfwITP04=kVl|Rbm>tvVY4X}yMEB6{qMl1 z_bbk!GOrd*%1^+*&*54dT}y-s}_oI_!yGbb)8 zQp7>axxp#KmEIDXK%J1Rr=q>DXR3`Z*e$?jORLMP>dAdnpU^B&6nU`KM!*osXv=5; z2o(|nOv7B@9p%F1EAJZNG0TsZzI8~r_&t!8nrc6UY(UsGaidZL9zjoF;R;hUh{ zUg+@daBW&`-Qu%G*sfvATHOYeWfsyR(&no*Ezl_OsR_&@MziKigoWl??J0u;KmPXG4L+(;kKBZP^1{2?{ zp`alVXaR>vZ{P3>?Pd>9AuqjpN6uDTaG&@jVn+6H%icq}oSQqBRHOAD5Z}HVr^lm~ z2;^fqAkql-RG4nPYNhs$W{g~cAxB?SPk@u^cCEZm#=e9Jqb7Z|B2<0$VUL=ahJnV0 z7Khqi+TrC)$;r$9w}LOVQFaP*QNj$DNMEX#kBG?rtQd+XGh?I!P@VIdPNJ`Z&DyW3rm%{OJiM9zGNfQYchAD>3Ms;Oh zeb=9<1=}Z?rut+nMZ-{r<%hJHK9e#t_uyY1VV#E=Qa+`SrMyWoGx=`fV=QJe!B$;S zUM*#}3}c(QKJR_5@VQ5+pngEm{3V16>9;w;%8S~7viX1W^T6etAqew>KD7+q8pvjJ z_S^=>OY}^vA)E=(u1^V`2=i z3g4MdhH)fcy>WDzx1Ncv{~VK1zZ%3z9+qGh<$4o$(0>SLF@dN}s!Jt1jZbAaoqlNA zg!cJYSZ0TfDM!U@y~vMdl$4ig5~33BICY)#=rwz@LbvrVc1ht4`9Ne(z>yD}=9I-`~VGKcIEkiH_Q4D5PD)ha6) zE4*+iGmPn#&SUD9KYXPLbb`FY$K)g14ASp*AMt1=(ytOTy?XnJkb%EXzT}!`1W#y6 zx_8K(H2oC!h!RG6)l&5qxt+{i+F=5Zn;L|U)DRM!|Fi1nr+pdsxJu$2sMcqhXTLiS zTrE}Ee2fyE8uGI{Q@q?CbQCg0<`fklMH-G!5mi%Cu~ir8dESfct>F2_r^GYN+oYFm zRHa>CC|#sl`Z|ZDQ19)jY1T;dAYk-yZ^-1AiITR3O2r2A6yaG2QvDLZ8osAP!%nyJE8S{7gJ?%b72f)~L`i=g%9 zZraL)Z1yycy$I>Y2X^TV*^^UKEt9DeFVKt=d-#(}8yGL#$p~={arUW6+d3td)h?#N zCw@E8X?>-lkiLYvy1>CgppnA20?hIq3G4JeJYhcQdUZT|rAV>(^**NYqo5(Islmd( z#;}RCG5dY_=>ax>aS1ze>=?b#>7+aDgD&>lnu?pU8(+lsPsnd6ZuD=YuX|n0oWvbk zZxjq;HVH?9+k?Hrio$4>&nfp3Uy7Sb5h&!7CbLbmup)OaJ?+0V!_CZgY7iDCGkd~$ z5{Kz2cOI~zAV9P|g8 z6u;g-Sf9Xu(@Nzn-7OuQ;D2FD-TuQX{hJO7{N)9YhNU&TmL9t?-cJEx0WiCcho!5# z4?7+}`jchq?auqlao{gXE02OW2mk~CK|%l!5GVu?HU$8<@z>v$|9C|_)YQhq8jo=O zxh1}nA&)1wy4yJ+6@K(Fey;h0lj>yi&-veudb`@f$N=m>Fd5*#2fHvBECgnUvHzuk zfMTNf!2cNR$p2^n08kj;WBE-30Y!xIf%;9uPeA|H@LidI*?~m`-NzGOe?9B&YH8-v+Y zt7qqfk29X;s_W#0Pop2Hf)BVV66S=@slV