From 70c4c5709585305757e7ab3ac3270f0f0446d1f0 Mon Sep 17 00:00:00 2001 From: DirtyJerz Date: Wed, 8 Apr 2015 12:55:01 -0400 Subject: [PATCH] Self-signed SSL support Create a new trust manager using memorizing-trust-manager. (https://github.com/ge0rg/MemorizingTrustManager) Set the SSLSocketFactory for volley's OkHttpClient as well as HttpsURLConnection. HttpURLConn uses the application's singleton SSLSocketFactory, so setting that will take care of all other https calls elsewhere in the app. --- android/android.iml | 1 + .../android/VolleyHttpClient.java | 58 +++++++++++++----- lib/memorizing-trust-manager-0.9.jar | Bin 0 -> 15455 bytes 3 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 lib/memorizing-trust-manager-0.9.jar diff --git a/android/android.iml b/android/android.iml index 75a704f..dc79907 100644 --- a/android/android.iml +++ b/android/android.iml @@ -16,5 +16,6 @@ + \ No newline at end of file diff --git a/android/src/mediabrowser/apiinteraction/android/VolleyHttpClient.java b/android/src/mediabrowser/apiinteraction/android/VolleyHttpClient.java index b505770..9636a3a 100644 --- a/android/src/mediabrowser/apiinteraction/android/VolleyHttpClient.java +++ b/android/src/mediabrowser/apiinteraction/android/VolleyHttpClient.java @@ -1,15 +1,25 @@ package mediabrowser.apiinteraction.android; -import mediabrowser.apiinteraction.android.images.ImageCacheManager; -import mediabrowser.apiinteraction.http.HttpRequest; -import mediabrowser.apiinteraction.http.IAsyncHttpClient; -import mediabrowser.apiinteraction.Response; -import mediabrowser.model.logging.ILogger; import android.content.Context; -import com.android.volley.*; +import com.android.volley.DefaultRetryPolicy; +import com.android.volley.Request; +import com.android.volley.RequestQueue; import com.android.volley.toolbox.ImageLoader; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; +import com.squareup.okhttp.OkHttpClient; +import de.duenndns.ssl.MemorizingTrustManager; +import mediabrowser.apiinteraction.Response; +import mediabrowser.apiinteraction.android.images.ImageCacheManager; +import mediabrowser.apiinteraction.http.HttpRequest; +import mediabrowser.apiinteraction.http.IAsyncHttpClient; +import mediabrowser.model.logging.ILogger; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.X509TrustManager; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; public class VolleyHttpClient implements IAsyncHttpClient { @@ -41,10 +51,30 @@ public RequestQueue getRequestQueue() { // lazy initialize the request queue, the queue instance will be // created when it is accessed for the first time if (mRequestQueue == null) { - - mRequestQueue = Volley.newRequestQueue(context, new OkHttpStack()); - //mRequestQueue = Volley.newRequestQueue(context, new HttpClientStack(new DefaultHttpClient())); - //mRequestQueue = Volley.newRequestQueue(context); + // register MemorizingTrustManager for HTTPS + try { + SSLContext sc; + sc = SSLContext.getInstance("TLS"); + MemorizingTrustManager mtm = new MemorizingTrustManager(context); + sc.init(null, new X509TrustManager[]{mtm}, new java.security.SecureRandom()); + + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HttpsURLConnection.setDefaultHostnameVerifier( + mtm.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier())); + + OkHttpClient okClient = new OkHttpClient(); + okClient.setSslSocketFactory(sc.getSocketFactory()); + OkHttpStack okStack = new OkHttpStack(okClient); + + mRequestQueue = Volley.newRequestQueue(context, okStack); + //mRequestQueue = Volley.newRequestQueue(context, new HttpClientStack(new DefaultHttpClient())); + //mRequestQueue = Volley.newRequestQueue(context); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + mRequestQueue = Volley.newRequestQueue(context, new OkHttpStack()); + } catch (KeyManagementException e) { + e.printStackTrace(); + } } return mRequestQueue; @@ -86,14 +116,12 @@ public void cancelPendingRequests(Object tag) { } } - public void Send(final HttpRequest request, final Response response) - { + public void Send(final HttpRequest request, final Response response) { int method = Request.Method.GET; - if (request.getMethod() == "POST"){ + if (request.getMethod() == "POST") { method = Request.Method.POST; - } - else if (request.getMethod() == "DELETE"){ + } else if (request.getMethod() == "DELETE") { method = Request.Method.DELETE; } diff --git a/lib/memorizing-trust-manager-0.9.jar b/lib/memorizing-trust-manager-0.9.jar new file mode 100644 index 0000000000000000000000000000000000000000..28c11b833a57aab6b3e199001d46c2910c2cc874 GIT binary patch literal 15455 zcma)j1CV9SmUY>-(Pg{3Y}>YNv&*(^+jf_2+qU)h7w?~W^S*gAG5bcIn>S*uwa>Yk zvGZg^E;&hH5GViu2nc|O$Y^1JKLPaDzm~e?W|!jcsgCu|*3e4d(a}3@R05bEA^4lIg5m1DJ99x0?6wqQHPMd&k`(Slm?Mp~ITAN@@cE9| z?FP_`yv}1|Z&0%D*>zD@vZt%36Nv4%3?N12VQuyR7@=Z?D(y6clQc#RoD&8lZd-qh zad-oNDtU`Wv^I_Fg~|Rwg$&}p# zz?0dtPLRZpdePX6-7r2fD3G|0f)$dycnINX!QvgDc9W{7nC>bF?+Q@t*b$;D~>4DA?(hTIDO$hw7D> z5_5ZJ|8!dif~R@|=@sw&sl=4Ma|!&?7&%Suh9qk*l#_JJj+v8k+ZgEPv-fg4tBBNm zNM`}9(R`AjvgBZ5BIQY%K}Na34;fDAG|z;~X(|@$;50$c5+7g7QnMO-o+_e}ku!}~ z7kC~6Qgfp85o@0D6&pC@bQBr5QfmkSd469^GZf)C-_Knot=X6`#@TL?HLI17Q!tsz zYw3a1ejhx7C9J<5d}+)*Jr*6tKFoqo@*REB-KO`ZI;zxP7owf_>Qu|E?J{~>FB;LT zAI9IDbJqx}e_%DeY^9Cz!PjmLy34mov5R^v#>YrvMFD*peF?ojeFP*BUvK-Ctfywc zF*wx+!lr?>t9qmDkWhs4Ua0aQw#iXnp^G(tR6wsRyD}seNJ}Apys{W5zm-=okX)u4 zKa)^xPZXG*Wlv|;jsXLAt)VO>FyDxO5N~hDOfBHy{OD&H;`C=;DAc-tFqv{SUD@W=n4MO^S!g?w8+Xz0;6}9ImZ1OU4WKtcF z4!u(ylI?3!c1K;8y5Yh}oK$)ek3~e9DsheHbDo7e>?wKSPs^jYl3tt5Hp1*mn5k2S zO^p}xu9xkBzvPAE?+#CV2Hpu(pRn)K^Xfq3vFLJ&IYhYW3_`ck77*`Nb8OCOHxs3> zvzV^;<2Ex-BjXLY2@XnkmhO>kDBLRIDBUu3R_+~7eEPTPGCors`9y7(zR>uT7$Afw zePlCy0e_Y5p&kwKuS%kp-jVlDk=VhzjJ+g;^X}78euWca`YPHZ*(T34c|ec7bcFlv zw1@ld=_0YxLNmq3#cCJzwv+X1OlRPAnZPV9UtH)0MCayHiLx%(SnKGogn`-wtkiA1 zkWV*pAT4ldo=HojJN3z3$S!khbK7?)1&#Y*X_3hE-$C$S&Y5`7DsculcenzI@=> z=L&@=ggs9s($OXp&~TdG2*=d57vi{x{AHf4&K2gE=CN$yI;b8b6A3vzZ*nrB$AU1> zkgkakBNy*(R>QB1ee7utCuP25d`aoIB>^VGku82n6^-VdQ&TYNWYc81H$|(H0A4lD zWjA7frdiKR8?FSn6#u&5AXtEiu$3vzVpt;aDu1dR@kADcd1DjX!Tilgdm(+EIDRvn_#^HZ5wWzH~retwn9=~fzYW2%Ls>ieSJ-JxJ_j5}7)w8b2WJnL)J7_BcY$N1- zHq`oqAK*)L*^TcsJD&wGtOwo9o15D>OhPEb!u>;R{h0!6T#B;MN$+8GF(U0A3B}vHhVZry7+T9D-#$pAM#>b@Exx|+bOh}H-zXIcaFxN6}G(mCmGPl**r zTu<@YEu^`mlP3c4^Us4*;NRS#QGt�v#c>JhEoIGKf6lzw8&f^tt30#JPfTw!~(y zegka@nPQzJ26zEjME2nSASNwDs)FSuPUtJ zuIEG?k*pFr86aZRpOcpnH(`%rsTd_xehlu`y0?J#ow<4R|EM%0Hpkkj& zbj<9d2#+J8*l{v?Qjg!A2ll4>AvyofzUSI-wBBO-opK_R-x6jM1Uas0| zSa1o9)-ca((SfGiNlNQfQsHADCfh;IP#1X|+y~1C`MVpQx7XJow|I*`OAW&muVGKb zwf^}x;J>~Sy3vG%HGu#Cy#0A`r2StPXC((`M<;208+}t_2V#c*zeKBesv?V`d`}|P z6IKfZK#@0>nhE}ZTnn+T>vn6b5SQaexU^is9XPAcxRODr^zP9--B*0D^(6K2U4B_wn^d1+b_`l^#iELt*#2=*dR5 zu{}Yr!hniV0dVRS$WY?yf=U%MXEqL-lh)B#wWF(@xpH$R`UHJVW>o!=aeqSP*1i;C1Uh8maCBj?p6wbGSp`9E;CiMS^nF+89*8i2R! z?vt;@cSk!h5#w!hk~iAb50W6X6Oj`fhGH|HD*Q-Daf94#9f{eS$Z);-8?<#Nh-K*+57x1oEwSDm!z>2F-OE!FKeHsCWDr(WvW6?sgvxQiew;2n3lJhdC>$SOko25Ck~`18 z_L@rPr-N4ClMM7R^(b8pLOxCkzqx==3TU0p*9kOQsflewBP;Bw6Dq~qe+-<^g)6mP zr{aQuoX;!vqti-MGge!K@mZo`El3 zM?5RuC!1nie4>OI5=*t#wC@l@AHY`EL(y0qmM0Qje86QEEQJ;)KA~AG7wO~0F1D4A z2m)+%&N(HBz+}Ozu~^&~Ur}tg6n${Jb$i z8Ef)@PkJJ~woyrN=h$NCb@&Y-tx=p3m&ZJjZRvnQgvb_v^R-G5ZBz7kv$c7lYyq zoTvi4*_OQkV8&ed0^BlS_8O6b{G9|ty9h{PtOocZ{%rH14Q}#7lKs?+zvMHa^IzEYRq{lOq+HwT%{(Ex?(K+Htx!u zwm^GkUY@ilv0iR?FxTOKU|8@>k!mSOA&eJuq{%u?PHNV|&pMcIHq>FMnkY?h?JBf6 zO^ctjpJ(hsh8e(S^}vWb!4TB$$vQ$2>2G`y^YQTKEO--2R?$Fi&NCf$8b-N39OU57 z)IYupuE=5}7fc?^`l`HY&#e8#Hd?RimJQd*wtvuyPS|+_t>YNZ75;c>th6z1OgxU= zJquMV6AJIBHrMo?h5o&@6Fod5U+>r!=PG3@gIuxpO4K#{W-fq@)jn)4DROI5wPv8V zw8Jj@VgR8-sffZ+rO)rQIoC|Q_?C!~u8?gbMe>+QM^}`eqsE+8C}jvybkS*e!>=gT zQ_*Z?zpK;dgCjTN7YT%V$w*5r0K5+0P%N&1S$OwJr$F{l5E_DYllYJU? zVx=d()&P~2gy?v!cUPhzgpkmzt4$=8aqi4yk;3J2JsQO9rjWCy(iS&MIY+xmS!Q=W5_bpEQ}T$0p00Y7My5Ed zhF+-X5{XIx^k@tFKvzSi$A&|*TmdISm`>%Qx{6Cucs_VgehKTwSV09B{C!*E$VImV z(96MRvUHaKM@sv4YB>)=>udw^6O8<_cE7X8l7WTAii)Reut|JAC13EsdCqo#QQ5KT zokz0LhK98+B~XuRi1he=w2fQIwdMymRLV6~rYW95q?MhTPG z=^~t*eW6MNZt%TJxH)3#2rSVcR0c7A&LH&@aT|@;?8jASn9&$GB5H=OcmQWnaW^Wn zZm1lZkQjM_))%BBpXW7YK@)KcU%*kzIf;AucR1;%599j6yu9HEBcI;0uNBedit8Gv zy+MheT1HB4?}R_l@FaH+bUtvS72(^dz9CA^0e!{#+&ObaN@ENYd)UWz(#&REA!vgP z+HZ8!TyhKG5=swVkY^L%$B79g|7%s1QgAoO`2hfME(riY{eP~i|0tbV8jxN}i;KL+Q^dB6To5oI5Fi+6 zghqrH5^5*{v3yA6VP<@T;*5TAqf(h^1WpZAo)uNjq8$pF7Qzt(fJOeTdX|<=p4OM; zF7s;^i_MgGpVQv9I$Khtu{FEHp3j?y8x3^NQ%v|=4uPRZZbK+D%sy&(F)tK@A)jX6 zqIfY9+lcNsNyCO<`1kkwAAvbgFXE@}W5dHm$L0Y&RNLE3FPH&6*Chboy*s9#%mQ1y z54Vm!SfkV9iTJPP7~d;9IT#;`yh$TABp(exSmV4YOLRt4bVZN;_}(6)H6SUv*dO_Q zJ#k02Mfa{gU)U>-xhxGYL8C8FBquTf#9E6<#34dB)=^%=9I@3jeD0bm8iTd zv@zDsm7IB5Bq4P2HS22Uo+$$-in2&-W4&sfE8@pLbEt0-SDB>QWmoFbon-ThY3FKy zmBCsRaM3a^2nU?tIoIW}zAlgiL%k|hbuw6mca>HKh?&RgY2R8gqKQw zK3F#`*5sEfvWAYDb^^rE!rwaUJ}Bn3Psl;?a_3j^lfWk3%@>qor`I&UE*$bSX$v(0 zKjrgSmBzd*h1x;T z&_F$4=Ct>f*f1}cGE9Y}4KW9D?uU(p5Y{bXr6Pxn5%mm+$PtkhCe1rFPuNYw2)+Hka72K2RjzfvOB zK#j89iu|lNyM-hBHAD|C;Hd5BUA1+GhA`V&+-4)JJvnCr>&1?|e7Yq)c|K)nvDMg! z$O+io*4|uH=04fJCOv+B!@lyWC9kRrjl&^0npj)b%7bDl`|xIVYlt#?19^ z;m6C}@~101>Lol$6_SM6^5CQ32Q=suh&VJd6(9knTD;xfaI%UE9Vw=kU{~g%-Wb$4 zau*zfFj}OVc-u&Lps0#V3aNssU8B}2PCzu}BGEwA%iU->SLVgc6PaQh9neSrOXWH{ z2}Ae3&NS!^rrKHrP9xeeU6e3k1<6#jq$jGu`M#{~>`_f*TkyG{$2hgtx{d~xOf$G9 zs3gBPH%;<(p2X0Rmd#UX>o7jHB5(F{HAA$cjZvjJ-f%3?yueXltWA!x$I1#Si*r~# z_cfwiFFQrbh2|#0g(75E4Filx<%WLEP? zqN-XPn};eEhMQTtLh0@}XcZGx=}qhF{n{RQb6~||U%k|45m~9Tu~I^*M@Ix!9!p!+ zYI27fplt4WX2c+j!A&6ryGm@pM)I_=JCWOcxX_|n*$~c;u;Ako4aC{pgCbWb$i3F< zE}nfR>(^MXVM{8DT z?t^g?4s8BNtc=Y)$lg6gC{fB}sG(h2%<|6;6wH!4dyY%`LBg_d34tfRDwh~xuG53I z(vxkGvRIq~E?YA{Uw>G29BS2|FM~NEWXFOVIdyI!3NKJnqQsdK?KUS)Wkp(fD$~}Q z3r3_Q91mpUOzq=t)jML%#~ey*+2SgUw5u~jG}qR)+)0Aiqs3L9t()i=Xl}NiY`3oB zSN$kCqpQ|#PoVaIx&TJ_?qowEC@whD*V#;y2NBC_$k)-o8{Dp_neOTob{$2W(H~}Q zFw_Zn2)<$vha5%F%LbzST>}EijV5G?4Q>EnV`QFzfMio6N!l?GRtRDH1|W{H1_mk? zl+rO*r5BBGB@tarRAVHC?K-Aj8!(0Id|3)E$J1Ba9N40nNT5x<*=prc4U<8n2094K zkAt1E8yCq&kzjdLe-#bKMyX_`*Ad&qn7Gm3Xu$`yZhJE-B}NTc^Egj zTX@jdAXB1S*X+i*)AmS>Jv!v3=(?US8*rYK@1C}usJczB|YDC-pLv}ZdQODP^wp8g|Cd)Dr{bqW1f86s0%Ti?Rl z_v|SkhM|n#K~qqB!pI4&f6BVQ-dd>MnchxQJf7=nbMfPxT?T>VoGS@!JS1&m zVRuUfElHY`mT0e$m_l$|^=!HuGt{qSBa`glf_gbctU3Car z$^@8lE;6(ThY4+_=qGtl5=dz%(?$Yi+p?hXgG}6zAEd#7YSwE=E+Bb~{TFI2txZM1 z1y&N@!-@X;c&*~QSmmUOn>Bd93@U6hENVOu))EWm7#DaHFID0D^o^90i)#H&gE{od z@tkLrLI}tKyjIdrDElQ!GR_d4*=Sz67vpmuaTAfn9;6;iISk4R`a5>n!w2hm7k>0u*>o|N=-9N=iTva z8Qy_z0J*NU5cnH7rgBPognU`gtv{5PWvlWEG{N69H^zburj>u?2>X}$RCGf=v(<7CUYCCNCxYQ>l3$u6uZ_Z0H9aEpCjHpW zHk=o6;YZ*w1&@tq?7@Xsb2_?Tlb-DrqwnFB zyQ#PXm|IsuJ|Mj{K^`RujuC4z>JlIobBYP`on?Ri!wtR~LI*G0%rfMl*KQhNUXffV zn%CI@wqRnDyApU+#{pVN8~|F$4xHlj6#a>Go*|<|o$j`gTyU5_`XFSpL z)1%0xD)E%Ydb)V}1-$GylPef{SCKdWXmbZ&L8gsm&HcA5<1AtsPMSn4?ZVuVQ`cg} znaGJO4hCtiOGI0dwOyPI{^qtbMWc0ZNlR7#Oyv>&ww-3|9iFrOnT|l5vu73Wk>#qZ zp!WXr^{R1V05gGFNY}Mj8ZWbNSJ<==5Wz~VqMzEX%bDJE8FvicZ5uzOr_^mswgHcT zfh;uJxK2CVx98zF$CEoIj4;wo?5ppX8;xoni}uWGSo4{WS@oMWB0 z6|g14fGY9qid@$;QT;C4(+xQqbb(}DZ|R%AJrf?i8}w&5^BSjxb(e5QN^zQO-83;q zy?qof-`1R)rm_UK*`epz&7$Wp_0e&qSc*QYc@DdDi|vH0Q`W`fc!H`idJoepj-JM7 zBDK06bZT0wMOc?c@CGE97S*9?QAJB-SKwx#ZI(tLwVAUM2U^>QP%R%Y=X)toat9JH ze+D%VNppO%gJ(9S`m{8c97ZMIn$T)SXs`Xy&MPHa>lV!Iol+WpiqEu{G+;1tJBm6| zIM;EonLac8u|MS+2c$fz9OwOlH3 zB;4$<3Zb7~A?-0$p9dV1V46BKR_jy^$&#cU$*gmPc4w+m4T=Ns}{aX5c6k}!AC zl{o`f&rNnYL3X)(a?<}XmX6RWWkOs48Mz}+Ekpgo&yv2K1{d4ueyaLa^2sf{30d* z&baT`ngXLDS&?oMhlLB+^Z04I^P`wte4X&RS+o7LRylLLqUIt#Sk0^G<7^?WsstR4 zaRotFLIO50L|MDRV$75+%e^M3bH8CC(7x9}7UQ&Bb}8kz_I#%2Xp+vk)wR~Y;q}hm zx-dp2Lh7f_A{dd$$ts|G%a+IC>RX`P7IxFRkbn~$Xk4>&!Y!3->>7fidW8uyA+^K^$NWe z^Gc(fC+bJb!Naw<#l11Dw4n~jex0y}^%h~p^;ZHLk+;4Oa<}khbS1@2oNQ-3-6Q|z zxe6tnW0pW1?Ye679h+xv{Ky-m0KZoK?V#Vj&)H;X6jYybF- z`srJsnsqIR;XBFV1O0kHjBTBhDVp%{8SquMZ99|k_DSafE!&d`aQe*oU|abeqw}rH zwO#b=^zO}(w~ap|?mmv{??d&;1Du2Rw3ilA1L1xXV`jC=f0vl_9NSV^c|o{`H^#~L zYK#g#;wDEoHS9<{8c%ySXRO2rNtsVPB2nkJl?xi|t(6;xJMNP^-A)2Q-gQafxz0MF z;wC%NWu3No((qVP`;aPutY>7H?@R3r#Y@2-bA>p*M)BAnw*4Bpu4J1 zY1UW$6~KG~kXGMBN8cI}%q0>8Zf5q%fYqD;mc%PEfaNkz?FHsChu{U~VaDb`nrj-k z$dn%vKEw1vA7up@$stw{qjFJTAPXO5{+rZL6HZZloF7YdRdD}#HV_Z$svykmX{IoM z`4vE#g6cev2@V0e2v6Fa1-9?rW9Qx6Y~R!j$~$@N)R8&FrhnzQEZL^m<7E8Ri7M#C zr9JVg_e6&4dTv8a9BdM#vX2YIOZ})ZJqxXM=jKc%LzR$Y9Ke6G_n8NZ6~`WueVd;vN3@Sxs7ZvgHr+~1kYM`saQj#0YOr~oOX$+9 zsh+`hN#6r7`UWA~1|gc3bZ3YgeJJe_!xLE3Zx0XtRUb;)ZCPZ`+a|qlB#9@Wo$oQw zj$gxTVA{PTYX@n=w{Dflu~p3^Ak>d^>zcl)lp1633WxHOOu#c^OgFxe+;jsFUk4ZR z03*n3rN`jZ63kz*y%GUr8npgo`rD&igQP|CtRK7ebW-|5TVSiL{i`eBwQ1Pj(A>6R z+x9S9wzkwDFs^EBnbQc2^W+PVP!o#o>Cz5aG{t>SOUku=Y3i9q_>gP~pR_V?F3lKL zw({YuT9^pN*;B@>*64Y%M=`X%8q|&|l6p`4>5dQdlhzc#rpK3)3lO=-psv9;D9btp zSzRKI?5YnIAeD;Mrq(@-=$fPXl0f(HvuUuX1jm)(cp5Wm?nd3qOuRMZH6tC+Pr8Xe zJ2-mSzA>aX#X$#OV`dk+R1a^j5_~tL6|tY<)fg@-{0qrE+YD6s1 zXaaX9iyI!+f8@a^5M;vzkQeZ4$teD^0#%)}YMkD4Z;Uma`?2HBFuiad{95=E@9d3}kokl;q zY^1faEDgF?>O!z6qvsW|=y5U0ch$(@~li<|3>z`S**#Nq^|am=@0F!KW0J1eMb_m(|Z#Wd?d zwh6A8Uao0yjlR-udlN#v2_6*Tj#;X-28CrlL;2G2Y!0#TNt_fbhhviclpz;1w8=~(>9@r9hN`}HpL?h~ zST<0=A>-Z2M%xWQ`yueMiuSSqt2BshPO2;9_-ZiO&S=G!N@}?z4v~7C`o%R4e7-~p zG4x}bKpFmy%(C;`x^ucoP%Dqv!xFz3zEAggroB>anlQ9<@z4)Cs|%`5FhJ%6D-Q{) z6sd)#=sonvW0G`TI#bmrGrPC?+;!d+>#d%8+>Nqva+9$(>=#ZQK?@wp zoxccmx-|`D%~Q6Eavl0OWeg9*SF$21P_KkgwRs~VsV9rVAoj&I@XoNvTcHoHfanRv z8@yc1SF_O;|KN@R_yI0pOUoQa^c?e5zJmzcCLc8Gkh@&r%W1h%x(!>?K3WDuH+cm9OR}?SM>v2hoMo{>Q$Nn`^>y zLrGu5@R+2zno0Qpeu4gn{egliTbT?1{e0OJgea4!T6&p14T0<~yH~Ukr-VcINH+-fT~0)AH%w7520d51=pP~g{% zZrMm)yNC?A1UGDAaPBpM{otrgN>Uwpp9AOr!a4aEB-gtVGWn+7vXK^D{hcEUXU_yQ zMbnsU8=$fsqjcg@Nb4#`c3o)gh0gq8^M>M!xb{iX9?%mB&=}D@pl+)Y>0`caUwF_Pslz09Lj~y`T@sd?Y zJO0{3Yz5mh`^XE9krx^xCTHXEMqh?uNJ!lP(f0tHek;K^hXrxbP{+tp5V;dS@i%>- zpl3rfr~krUX+<`5eT(89Cm{BYAOQLGoHvT4xtACIAbNo^(Biegy631*xGGOw#>e8; z7+J1Ai6;Pij)WP|l2q>Ko3;52MpiOUSm_3u!aLF!R4|L8WH~MH1+-MQbuB2Z| z&d@+Zw}t3$ib5Hn(!-+s9n}&y3b$%6PL@z85}(()DC8qpSoc%?c9`Of(r0Q~3eNh7 z@-bj>l=U(+S@qFO!G%qy(B{XP!(+pl_3ns|L%+*A_ap)JTcVkcf|iLofzO86L3sH< zUhtG}u8q$aGoEhrTUo8g4J)=s)g}kp!||PsA~>yH@m81dZ5YyN$UE$f$-`^^X`k1m zsHkV}=A0}wpHQ9+IlsbvBJKzI*7O+M{FrNNzJ27kSBi>cOnzafAfFiF5r_R($+3O( z*ys-^pf8rjZ{Y*Ao;;+lsv$?(=1E}Gb$9TcUfcc)o=BB28*ib3?9xrf(^}SomYubv53u3tT`xY($j9~pCu7N-@&G4iL-!r5-6CRjmHzymiz$f*opr%wb?;?P z?;Mvm9zzgPi95bCWG^{RG(Ee8cDa-C^XJs&XG;)v;(m1a$Fg@N z#F7d4RV!MnVb1k?YQlyl#BG?n0#gl@vHDaL6Oi(kY&5Z|hC67THkWzpE^{LWHJR0y z1?!$CaCtUAVQG^`UB^W0mVdN8TT5@5%Zhw!Uww64`Y7=Yx{Dqidmdp6i^zY`Vrgfp z8ckF`5yGLq!_A>rGwOl*CeIu&2B3!C|F-p;XwfgY?uGf1W_sb(JN6`(*eY@U0A$Qg zSg20TmzWhz3aM7mX;(g+{iMu++woR=W!9tval8uQhlKWa0+$F=w{vqRCm}syMpl)yw491p;Cb)?w6Ck$Te!j|vb`d%oaDEOB-AJ%y z>5OgjLiT)7EMD&pzp0A3VmR45{E6lRuSUn+!l(#qbwI_Glv`Pk6JNdXBe~(-GnPD8 zWG-K(7eAJ9v?O>2L|II6k-l6GFuf>Pu?dTRTp6*cEN-DpM7{+JRvvvG)&gcTe`rpd zoVL4sXr9{w>QV*yLz` z#RH-kwrsfMl}Robj3ejx4puG}YHjN0ovFU|^Bfz*m*X0bEE|-=5ABOw=L8uPuTmFb z8ZI&8N~;-vPo^D>8Jjxg;=nuE8HbaIzLsuTo&a0Vm~=UjA2F@kXV083GVAI@fb;5m zuOX-FG=5!ZhWH?c@Uz_kjXfIc86_Kzp?LnRCv*#lUGtPApJx{)#Q-P6(Ko#A{T)6&_>Yi?An^HoMyDb-EW=VKCdbvi~7Dm}A)@g%E^YnlJH zTaKfES|MZsyW@@5yZfa>XN`8RBGw5J`0%w)aucL9tWVE_z%9{TlC{9T`~H!^!Hxc)g>7O=Vn zdsru#U$`@~8=d4-!c@Q(3Gmn}4ZBho{AyE@%as!x$Jkik>GfrSsmICt^QrbU!esro zEK**)mQLQxNgn=1F&9NVlLci{l7upuav9sCO3JKOl9RCTv%Sa~&9vj(z55!!=Y^w{ zt$DYBDw?DhFRvceR+CFM7dC_{PNC`ZEIe)?SqDP)2>~_u;CZK~7OEZ}y+R7`Ixe%I zcc4jmOxxVVDqL{`?l=AV9XwVK*InWf!`Ykdy^f|Oup0RX%C-k3tMir(<>I`ESYF*zSA>4|~gT(zoW;|$DjvBQ1@?m0osK0(nn6@PXW zW~>tt3rUGJ)%p5o7H+>RcL1wF{g!8OoVkT=F*zhR0b=ZkXq0n`z#iGr`=Xv$$TUhj z5B8ieXqGUWg>SUjZScTB_a`#bg}XwbWDUAieILp-zU1(EN8YXSlFUd2GIKRIfIDoe zR1A)Md`7a>jo*{F*!f4gcQj7#h~2&TBu9t2PXj0|X5vHk;7ZK79})x~=06L8c-LhI z{c^5L!thXtLr&4@uXL|URs!JgmV!))0DcC<-`{irYHf#B!CQd9&DJ!!KK??UKLL&J zVEimOTg+L|Eq(d^o4KivDS}%1j}7hqPy2T^G-)MiA!9>xM{`@7f1Gadj-8b0=R*ma zo&i!Ak9mO>>sL@;3BpE>f<%)_Ph>?@*dIelH51PwZG7y~!azpn`2}y>sR-+GXkc>n zdbGjmdUd?~4*pBgiKWy`IX72Zq$E->c*xF319{x}ie?ylWhvHA9Y&c6$$l^5_x(U3 zRU&Ng+8Sr8gKcp_;ZB6!r{9b`egN*h#c{e2xs1tl2DLjc?e>n$G;2_}3Pa0%WuKckT^h_1>hpChgpFgZy;AQa&L*$MgQ-#@_k$6_^&ARqxf_E zPuhQRN&a2oFZ6#{F#j?`{v-ZM?DD7k#~S&+5&p79{v-Y(r2XmsA^fLN@_%FgWt99! z{KXvn)BUf^zig9#XaC(c`5*j3zsG;W{%GyZl zznc>Nsmk?dtp8`#e`itnyY}DD`~Fj#`;R~I|ET@X2l@A>fB&BJ@5kZ(nKa>#5BL9; p^dIHp@5+C#KmSzr`uT5^|6YycBtgOcqCo%o@c)^(5bS^b`hQSK1`q%M literal 0 HcmV?d00001