libdigidoc-3.10.5/0000775000372000037200000000000013560273530013277 5ustar travistravislibdigidoc-3.10.5/README.md0000664000372000037200000000522013560273131014552 0ustar travistravis# libdigidoc * License: LGPL 2.1 * © Estonian Information System Authority Dependencies --------------------------- You need the following dependent librarys to build libdigidoc: - openssl - https://www.openssl.org/ - Apache style license - libxml2 - http://xmlsoft.org/ - MIT license - zlib - http://www.zlib.net/ - zlib license - iconv - https://www.gnu.org/software/libiconv/ - LGPL license - doxygen - http://www.stack.nl/~dimitri/doxygen/ - doxygen license Full documentation ---------------------------- For documentation please see in doc folder SK-CDD-PRG-GUIDE Contact our support via www.id.ee for assistance. ## Building [![Build Status](https://travis-ci.org/open-eid/libdigidoc.svg?branch=master)](https://travis-ci.org/open-eid/libdigidoc) [![Coverity Scan Build Status](https://scan.coverity.com/projects/724/badge.svg)](https://scan.coverity.com/projects/724) ### Ubuntu 1. Install dependencies sudo apt-get install cmake libxml2-dev libssl-dev 2. Fetch the source git clone --recursive https://github.com/open-eid/libdigidoc cd libdigidoc 3. Configure mkdir build cd build cmake .. 4. Build make 5. Install sudo make install 6. Execute /usr/local/bin/cdigidoc ### OSX 1. Install dependencies from [http://www.cmake.org](http://www.cmake.org) 2. Fetch the source git clone --recursive https://github.com/open-eid/libdigidoc cd libdigidoc 3. Configure mkdir build cd build cmake .. 4. Build make 5. Install sudo make install 6. Execute /usr/local/bin/cdigidoc ### Windows 1. Install dependencies from * [Visual Studio Express 2013 for Windows Desktop](http://www.visualstudio.com/en-us/products/visual-studio-express-vs.aspx) * [Libxml2](http://xmlsoft.org/downloads.html) * [OpenSSL Win32 binaries](https://slproweb.com/products/Win32OpenSSL.html) or [OpenSSL source](https://www.openssl.org/source/) * [ZLib source](http://zlib.net/zlib128.zip) 2. Fetch the source git clone --recursive https://github.com/open-eid/libdigidoc cd libdigidoc 3. Configure mkdir build cd build cmake .. 4. Build make 5. Execute libdigidoc/cdigidoc.exe ## Support Official builds are provided through official distribution point [installer.id.ee](https://installer.id.ee). If you want support, you need to be using official builds. Contact our support via [www.id.ee](http://www.id.ee) for assistance. Source code is provided on "as is" terms with no warranty (see license for more information). Do not file Github issues with generic support requests. libdigidoc-3.10.5/doc/0000775000372000037200000000000013560273131014041 5ustar travistravislibdigidoc-3.10.5/doc/sample_files_CDD.zip0000664000372000037200000011222113560273131017701 0ustar travistravisPKy%C&]5#datafile_xmlns_missing.ddocZg6ί|$4L.nb ï\277+inyІ:)G!,2Hй?||%QL?K6Oȋ̎ m?* ʢ~zE>}(D T7WP/6.d]MX4z_OD 2?Q@cLJKA>>4+%y< o ZenR<>h%gkSSkIgs}Qwj3P+/3)aM]!2̶'9,83Qlv6MkR M3>ٖ p)NsWP3Zj-ulbu xBFs~@{<;B18uuq 8k _up8+=HѨ=8'R b .FtB+kģ9WkYY7ht % emQmM#'Ϟ7/`\5HƲ!ENn="ҿz$=o[8qrc.#&7݃Z gK+)tL8SgV699t|'cxޔY]<Xijp6ȀOɶRn'<ǃPmζUoIWR :OwA\/hkؗ`ԑߔ%0 C ;u}P8men n!,M\ K GUǧף#٨֏3|R_ױߧ ^>ߙm*4nv ޳j&mS {{z f|6ur7W9ޖg/e^$_Va_nM٢_3:CH]=!n~~Ʈ\?~fRSΚȍ~sMn9{nV$Ap.AH漜,f{msi/QM]btmNM54 wZsȎoHԬN4E.^^s7tj:P.zJF8Hb]!cZCNNt J[m]Xn+c{!X4cu3Cf>VS[Z`qn*_dN9BcD vTk"yu&G̰Z?pq$Qd:M9N@$*$\Xn/,ݛoR0NbpN،(<ۭ9Ug< :G1 9 ̃c^D Q}躝jʆjd֔"#v0 >N+EkL?\`,FLbLw(zI7f[F^K{5BRˎ[N0uL&*8LmbХŗ}Mj,Y9lO.]5n^nTp1)'qDx[?-L 'iJ)8v!Y?*5kMc%Z&&U-+f,{xxb̆4\S͜'Gl1^}?Pc祡|r{6gD(lI;'[^R޵%P/mx=akq|~s"Nn7 HeY/^K,a0Qehj͓֧k|mhISuJ~WCiċU& /.\8 _%6_LXaнb6 ~dܪ_/:<&ՋAXPϯ*K`ϷmsF>ci (2d%\C؄vG0 ޟ=-U)Pc? %'Ͳ(~!;iGk)"j̰ANgıŔMw|N  1Xb7ȼ;0~kK^uPɸ||yzK-EaVfjȱ"2> -~ dC{q~ ~Z0QVqb.$Pu9_:;ok7U9sU}͠,|7oDH[f%̃U5or4ʎ %.%~G0"u%?q6|W DUe89etayT@ܴn1'%}ffsm-{b^6f]*r5k ,h9o՟P)Q:avW#+ە{[2P.BwivWʵ񞾙 :P;׻an^.;b!rF+Sێql̕u)w"@SzNN3 {:'S'<3E,b +|ڗЏn<H8P3Iy:9BAE\L>q^H0:XRU(GoxU쎚zڭ;[|:b-~j5!{*_n1-r2li WJ1r^1)An"iqr"5F^gjX,b#MBc \w\6)[ Q,6I=Wd=O]q[ gt[ _'L},MD/Vrh5?J`NY9Z@u~^P9[?(49(7xm' Ͱ2&Lr>m* RR.kPEn!-Ѹ¬a&ǕlIܘ\TF-ؒVb苢Twl̟3Tg*,̖t0!hy %HjHJpx*g]p"+"E^(u_ lEtOa^?*|?<ܫߕ@,VKW,t,9c?sDNđ Wpx9 5|xX~7˺f "*͹M7e@\r Igڨ)%'/2МFy+ SlѸbm<.-ndc[kq4S,IcnzH/Tu0^ǬMPO lUB9 Kʅ ]iUE-KZ~Z7OzY/D4vUsgڍ=|U^ xn&vZ߿+*GE@%rq}96x߿͢@\ٞ3~49BD' 9NWqoN3[gʾj1Q[`.ۏ `72趥d4Ɍ!l&;IU$w_yufj<$!ӏXWn&w1/ڱ2P uM%@PƢU#@eg+-MD9DDGnebN%uX\5 3rtVKvz˽fzƇn ?evj0#{idTNJO(ehWK5px,(jNP"k{{NWQ䘆Mg_Cʕ/gv`?F!ZroylsٺyuUD?v%^9"ԕ٬uX3݀QЇIBJoDQ1" i 0ݦP,^"`fERn/\:‹(XW. Kz#ؓohހ̝"bW7'b#/΢;I|Z6 ߣ|cqH27*%-3kG Y,PЉT(mj?͠kjdӿMԘ%ˆ`xUTb`|P2@m@V /Fdb2Ay01OH@C%y}TIL>r#K'?Tx2DWVxUd1Nb+0$XlTd y5&&lM^.a-P|0'{%}v@m"ΕZJ^g$" v'~BKw'aWZ+5f/$P Yn5mdzVO;,`bD#cXY^`/Z蕉 _A#?V}^,e&K"Ȉ(ZptvֶֽX+Uz*5%cUKy=kD*"̀< x|'YZ E2&ec@]H*TP;C !VN5Q~BY'jg A^:w!_3^ m*ֻ@De&lcWgyvDv#La7S!MlG^%ІWQp [R~up'\Q+4%Rȍ6p2'I2䅇0+)WB$zae/rsAwƞh_t#q&~41kĽ}6xƘ3k{.{rS[OHݥew8-QLc*? *|Kڋ#( πo#@A(#ŧOPD&w+UCX%?,)OԗsG 7-2& E fsx),šD/oNjܤlN1(98e=hUƮǀ'RrE zuabm@aA0R[#Ϥm5 R-''A6e/$5}' Pa du2()¥QXL14X"8=ރː <ŷ>NJqf$W K(d岒!:u% aS T>)Tm'$vZiu&0|I#zAlrh^uh]!UI3"Gj=}j>J/9 n`H]NT Egd0KCl]|X_@XƳD f]k,a,!fd $}HXt`h,>z0U+(0yH<w^[+Y#BBԭ+ wOz}uڪxS23[D$>'2B}lRԔ L Κ mj*b/Iq_!l]n6a+eQ;sMA )eTiJNX:1FlGt(@TO=]c5b D@(z.Չ07Nb 'b-8b؇yJ/EVv@T]e/$uAcP)KDw|`۬dAwi.^f?k?3y+l\[\z\j$H ڡͲA5uP|Q_89Ƞ~xy+}̡ =^ː,EK MyB%Fj 2C>gUo,*Wt(4rq^kmQU{&:1UJYrl!5v$Nwl9#)A~&]V`8U*XR+ؤo1*Hstq2/BRCV»]ƹ[CH H:ʮ C.Yl"x(H22biI:BZ`XU=Z3(y,p‘"x0,#n X5)rzPh d >5`L.8Vu8~4Fyި:}Ρ30Ի;Lc$j:-1D_dc?v =꺋>8A||tJ?T+pEJ@ ՠc CiL+?ik>8,B`x*FLbU /.;A[Wȣ5F+@bVA@* UARUl mp.F@иA+!YD0TdӃ% q*QY@U A),cj>]Z7?4h+SFWL*{UFVIu\ےP?,)d2)Y+="l=f p0hmH@EWj;K=u(F~:I$z?'֎(LURXwDiCu)^Pf%T~Cuw= B븠ȏhбcDY$_ Ɂe!mb#HFnm)::NSk* _y$.ԓ۠) C '}x A{`$Upk;wЙ>O_F:mMMC11zrG;DڿW̕=-i!d c.ҿ37Z>ܻ g$+ASO맚/ᙢrY -'K~lD U <"ٕw쀪K:Li4 78[4e3D]%xdĀ}\D:=ijp- ѠbSe XlI:42r0(˜y`ǭw/Vs8vq``e``[S-h!&]uԆ@ٿA>UOOXO;3f1Dђc(;ӻV~1JO'{dv~QcʯÚ\O_]>/Kt7?}ߴW_'}y8p_]ý!:W \iXJ#ti㢍W}#|<\1d+ެ+7P~|݀:?;ݷz^⾢Ou]:1rh7s=uTM\N;bwrNchO77ߕ ~=3v#FXu]%]o~va=_-QdXP^M;f1)g,VOgoMhD| g$4.;aߘHjҊzIW.7T{_7l螼/*xpw>:V]MFi;եY{V=,k|V"`rm%/_N˦j6m&z9XŷY֔eVBkCO^ׇopۋaCNLj"_¯H㼳x +:yb v:|i_OšIǝ9n8+4f7uS7qLw1,]~uv eHkgk7"qgyWeqV=QpžȽз%引  Y8:|la$G`ɘ4Dv4|'wSv|+ԨS?S/ EnՃYNKc^ce8ǓlJ71uNˆA]YqDQ&LU)GU|H^k=[Ujj1S c~テ3Qoz{4^>f_ #*EOsA:r M/yYwhqIٶ8vo.=s)q~Gz^=t]dH8cLQ G$8u c TyLbjXi8 u\n񼻠 aV&\]9RA_-kc ԫ:7<^fTSٯ*Gd5/d8t lI=E9%5 IәH첀E&kqӶ^m:P.@UEbHU8($kg]79s.TXbUV,@<|R(qT (`ۿ2R4gqߓgQ2l1g}rۺ:H_K'ʶʁ'7boWSs (_h7qncKr⛧WkQL=6.>1 [zz`_T.oVM7Nc}ஓyM0at=g٩=JeFz'\/ꪩ:sp[8!.F8FC fyٰOiw.8~'ok73F7 lpgS%pƘRŠ0{2.la @0Uග, ϬUA!#)\X ;*Naͩ ޵W(:y0mE\@&[=c$ (.bqFG-Q tS&NséV^k{nrxD9t~vɍU.@;܆,6SEt72k]O˛rxKse';7"P;%_5p݀RC=wB]&vu_2nJ?6s= )4kF9m 4%SA<j1[jη 򙔞}nzٺud e;}gzmgnc׸PEMi_6z,<˰qz츜GrܜŠ)318ۅw̪ o4dnÂd0k ]wHqmB.eл6j6)>½Ax4Eo .mǁm4iwqE W0&ng NtIZV|7)t1=55cn?'(6W~ ^@oRcwxX=Xah2s'rxzC@8ߪSXTuwzh{h9/p;|YI$_o(?ɏ*4\Ufש62ވ?]WO;ݟa a{.v&ͥ>3xH{oVQ1Άza_QרuĖ ^So8akfs=*hk֋v0xc[n֒5K6Jِ޳ ]̒d#'-nWPPކ,eVD/l~OبαmKmr|=ˌvGV6FxJ5o٭:\lc\\w 6_oH`#ꐜ~Ltpud߷9)[+-|.ֱq۳w8|zXN LG<=^SWh Mmm;_6ώ>k9~R!]!Pڮò-JE8_?]-THg8Z:d!zU硂9])VsC}{n9,8irt.*8-)p܂9yV1*lNu .(S88r +2UK'=ܣ2ld2;@s0|YRuLu:S?*Qy>ޡs\L(y V'vjo U˙s[WuOgȸlI`;YKful_IoBOӉ3{C_PŮh챫n'/l_Mf67MƛwPJ^_\.<;-Dy"~!L՗w/SF9N<7K  Pcgk0Xq|@ c>Մ1PjB s=@&`įUq\%<#UjNx;,iX;-oҗvQ_0>˅|WJN <6t K3@7l=+$5C(⚋7m*vFuTQ9.o`73{p-P?Jto,aʯ :[qKggە Ω5K8>NnEXj1;?k"USsus=ko> }N"Qyj0;ΦKpsWOQomnl+"c}64?5fKVNNZ٠KkڪS˞ήZ;V^fr7 c^OȂƦgxrqFJխX)tAW[o[=na"ʼʗ?{gl<>%sͪwe/비 (zg~;PKy%CLH old_digidoc_format_1.0.ddoc]Ys~ׯH%ĀS9JB0,^R[_kI^Q9ЮtFr2|8}oH7Ͻi^oOa7?w~3Nt0O{o VN"ll6E 0xtߐԪTAz~17gOJ.]=?+`$Uɻ[ki걫Zq;wKh,|yR.|3F]-Q/KH6ղTlyoO)D*呣v `vAü'G/+i5QH6]z]~`s AK_˶u?A`X $UC;BMOQV5tA=Rx~?+6hRX$%.S u;h=! R 3o4s!͸\5CɧJFݽ 6o {lZaCo^~FH>Zf\W`<90Se>b> BWTٴת:Ucuքjә2 ;KH6ࠬ> jLszR}#z8MXDgU'ePh Y7 ^`3.Z\fFԐֽ֫H) (fa SU+G*hzٸwx֛4=~rJ7}Z ꬛yܻ㎕{Z7x`[U{;?3)}5e[A|kF́y#-n|̺{RX)~+[92]쎺Ewֶ̠mAo-? [kN}i f; Ǽ L/~Mޤ 2GAr{~3d p}n~[b[U JVnx"n&=9G,`߀?ڍyUٮLA::LPqoB.~5/QYq? 'PZqߺuvin+܅ߚ @׵H/ wZF$[{rog]ktQ$~P&mUYnm= uAn6n|BFQ&bX 3|kL[O:Vm{by_I2Tۙ嬭g ~AjE6)Z^]l`.2& ԓ~u?(P[1r_u$g]]t՜]Z^GtI JsRO[e~a8'9QйpSoAPmt`#U ]x[W|ʺDawW2\)]H)Et'7s z v1rʽ:M3 Q"fJu#߱0fEsXq@pr[ vl1'`%L'VɆ4 U+ˌ,Z?}RW6}XW؋zz&_ +2"L5gHih-CXe0&ҰY5]B -Xh%=Y(C=`S0 ehPhc@nj"D&mbc#L9bRm:i /`c~&r (wyM[4Z Ձ)7"Q@f @(Frg0w3dDc>80l2HM鰓#Si?r'DI*B+'Eo舲$(ʳfHkͻ)#Vڐ֐ޢ[[J'B?~R|PxӓqOd޻jdn&wqi&7'[tZ4e=Ƿ=SzLh |ckŪ}|8,m^e;x,z9NJ31xL$eCs mqw{Ѡz*KT(;,>Ύ0́si=}ÎgK,սw"O>hdFOhߚw4~Qۤ'S>jz|/PߡEזC(J ff=^tkɅ8d^b6l8bPpI>*~cov؃*ʌqY0ݫ-gk܋jE-f hJ[4XYQ K􍨹^X:NL卬)T Ji71f.+fVhH8#hCf tS <4[Ѵ殤Z3DΩ|PzW+I3&;5S͝EvzʮDž=?ڢIY|D呰l'5Zk_gJQYʓ1Uł"*@N.{i B4m6EzBkZZiToԜT$PH;hIT`24K+ Wκ6/[5)TM1 E8fewhHFn/1R6BIXY;S)^nFi辽Q j<♛dn}0#z*WB+)Þ{S\#M iDi/܈l$[6U#h%*\dJ9ijZ(bόVD&VYf,cxE_E#:Z2z. z+N*oz+FHa|i; 7q%y'Z9I`}%'lТr{Xb7kgsP+Tp %Ɩ,b?0'~{]l*$<K؅~}|IoFd:z0nf ugTҝqa;H.HW:f_#rwv$E(NYWࡽCK0Ct CE2]=/Dwi8ڽյ%i3S٘wΥ!4  ?hC@)S]AHbXoH)l츴f/r&\wŜcOMblJ@IE-@ft); XE đ]fS􉗵OH mݠ.6qhL8{. w&`$U6LR}ؾߔ'J@ifkS#UY9HP 񬋑)wP&F*+ l`Ҕ2J% -TuIol[V %c!n? fQZ0f4C4#2q it~P(3'UJ2\q }_˒Pt88#Q1/N%X E8e)0 /h;K4 1\mSo`PjilH9Bdо;wg#1'X靮0$jt6[ Ф7==wJ֗p^1 Z;4IWkҩCyk\X63RiƨYa?Z"uع*=C68Mz!O9k\*YMx?~uOx7AخQnvԶW;yjշ@-'o^Aڀ#ע.,L\>M귐^DB8pzuݭd_|:#9IM[UTmQWGv/t(C^0Vb.9wB~|ၽp@bN$JQmq'13 jaݎL9K7GR_ ef M'4ӯw/GV#PgC 6ʁz5 u?ujK7'YsdmCԨ5is#Uv~c`U@Qͷ߫q shcX¨=~=c͂,w}3NU~=DY)" BU{]UˠрEVsCm 4V<>ٶhg ï6W# PcrdS[zTkcA=&D Xj^@A3!J%Śm\<]^+UL&QJZ:(y}"J$ Ϯh∘S!q,Ix]ȉg\!#kDlwzɲ=؈KzF6?G6cF-RH)O55QIST>S:#8#8#8#8#8#8#8#8#8#8#8#8#8#8#8#P d"yZ+:"XsedXG[ah/M) AsAv=<gtgry4efGVz͊,SX b7UQ h88ǨK [TRrdp9T,(qGqD̊%ocQn<-YU,gReTM^[K,1LC5*qP"k]u<4c 2Ò:W5)N$wM 5+9X9^lllWl({5vXo5,+5K ufH&+-lf3H[$==om4)hBScE)hZUTV|dM*Y+iBHtO45[_X3źވEbK JۮB d -A$ĭ㸏L?eE\\S)IWkҹmKB|HVq ,hi¶ʲ=cuym98WNG0!2/F=%Օ00WV5AcĤE4i#< iȀl# k"Pyۊ tnm'h$m'+ké z s킪jɠ9`<PIc/yH%h{OG͉wDl 4K8C=Q} 3#ǚ:RvMS+:ݚ@r^LKU6◠= ~d1BS˘XF9 7 OWAMf >rjY5Y*63QE6k݈pM#}T>yHAUS ABɼCjݠ<)4B%`sXkn-Fw`5Lx<9W/e"Ul^a%>rI855J =.=,\ ] !8 w.hfЕΘ`h6(@06٬,aǔg|u-Ͱ銞ǃ4Lx gTao8=i,y7qWiʀ =|ej#&5Z JB%<ߎ:<¡;"d7LC4x 䏥kVrp@p<Oҝ,Oy?]9矦+-b3 g,*}EvA9gJq! h¯"R V85K#w $麤'>i>Iaܐs_pp#/`F<;Iy[7?Ivӕ0WsPSkb N`7]Y5?aAϷÚ5G(aʦO Q~Z:[g?] /o|~q?Q?GΖOCy ˗*u&t9\R=+^ĂL~rX)1O;á+u‹zTk <.?BJtT$B9"^PڴF1Y02{3!3l.>^HMkd8fo1%`SdK%J] &2ƛIp% W7E9;%: #up!%<L2A{ 'piNpA X2bB " X yلs@ @!hR_ ( a+ńw&< ,KG_ `ҭDŽ7&̙,2!<N#A* 65W;hj X _C/GO }NN% d.{9tY#5Pu+פ^U. LhK6Jeb *O5&0*گAֆK83 <'*~0C-`B ڒ6m'[yB}· |MX[ʨAQkL 'KFC؄/ m!U&_ Gsui&ܩ i](lWߗ+YF pbT{i{߁~\^){*dKB>X/x}kk4-B?T@3& w1fr Ц~6e0Z7|!c$)W¶'H+Y"oLh="D=zi6tqsu:"Δ#->9-s| &sáS2(1Ǡ'u#Y!n X¾#J?6J*Dg"^~WLuuC84%M(녨z! $ªI! Lʄh^ZL*/ w)4(r5">lz!JDG$. SHpk Ѥ۸ Pikpk)QPAw3hLp<^l8Ԧ|t#~cB~X.@trE(U%{| X6>z >N.%ۭqY./z4O=nx ؙkw.'(X;|CcQw}Ξ'9_vU&!7iXIFO#YDEIj}dhw ބrF= XG[ H %e2j NӁ"nD<2S͹.Kc{7|myV c>[ǎΛb~7Ϸ$4c 8m.i0ks.B:'\@Yћ@ЎϹ6P"6Z{ t:AA;ޑA[A&[ #f/q(p"D+qY'L/HuYԳu-DKS!l0*\S>n>U' e,j BXMն IG,+G1Đ40iMqEHjGwT'{6.17wШ|&<.g1 YMuq 6"³fp1XT#lo|~pl ) Lb{f`: q1bŊqCX=y^Alm Jo ʾZqFƁJ5TV({G,\I/1K4kaDj<634g4i,M%JKhI3<KYK !+Q4[ l(/S(V3D8zńK#׬)1oU#`<6X~z/dM1>-f%pu]26Z4.UE6TU#ZͭVS~^+XvyOطhͮvc6K]\%p?"A RS8H†$umC8M8luM"D+2lT #d^V0C Mqre[[v$oMqs+7 |Ae*Yg;%˓{C;Z,5:Ew!*6hz}e6Nl{L3q^gbx=Fh 8aX/U] ^& S\SidZ  :F5RsьD(5 e2I-kV9*GH@G3+̰^J8&'5 Ax4R~ӅYZ ~0잡;cݿu+;&LW(tL;B些 mBےQk;@BlΥnKtb4Ki ]dA1-_SXjh>_h7/83ܪmi'$ 0t `M5Ï;rmL Dx ^9#\5*"\UBC#_7'uFGpNS}:~Fe9Kdl<Eo{6صH)z*sF=&d|AˑU>~y?S<=\mɐbQ//o~В ڡ7jJ5Sz!"5UOI/# *nZ[V"j$bsYnhesr }#y[$',T-AАu3]&NpW~0n1/cbfÂLvZZ 4My!*uFpFpFpFpFpFpFpFpFpFpFpFpFpFpFpF|y~\V8]Oʳ횥{_˵ɛ+V<;\QE'x5]R)~ŏ$P-0׭, 9>oȏON|lc%?S36/ i]kœ~ .dr/Vӽu1I+p_Q~uH:&jWޜf3ݦkFѬv[ Խ\QANOx{wv"2!LPlb7y0nPXHF!%긆"vYe'Gc%Q: 9G?Q ^5.B6TO" 9&/n9[vNnu ;63;2Z#:Ec:; Xҩʳ(K9^CM ONYX8FGˁ=2A#y5"N=?tSIC&JF֩f}:}CLJ&;Xq"Mlޠi`uuk/{ȵnDtYMݏ]fn׳Y<?_3(gstitpOaY>o`*0} .3T2us 0o}q @a|΍g=ƫ$c*p p5^~!Yrx5U%qQN>Sca<|{iZA',._<_*ݿ%VeLфlAy--2qc,ój$x]#F/X!)`Y2|ٲ氌g1#ˌ;C#k-~ KPr Τt } cbແ gt䅠ZXp[BjzWGb ffʹ;ԁhzs/# * n.UEl.jT| ArF3HU~6fe:L .KU\{rFmGDɞaR;kc{< o'D89)éy:'^%&5Q᭮9/*H@nc:[G%06&$tW=l)Bf&7aOGr2 @tPZd~lc47T:+q]ҽ' G.wdi)ڡ?udzH VΤoaD^- x]O,p%f3 sl~VY+Kvw $ )Won`^=, WX12*z,tђ\1p^ҟY0AJ%+殦YL:dz[> !Hxuqohe`*Ͻ^]TY*%ӈ#7ȖTE~-Z2'ӁnGje)rW52`uO"] (F vuot[%t|S##[A$\yͫ7Mwg崾-Xe&(J/—դCJIx fr n Tqo:/䩨Ti"{M 8vM;"5#'ZE{ 0鴟F1&o[:,.?oYAg[8v^HVvS,|}o>0 5o4W yeKEg7:cJN]z[ _1q=ƌ,(i&k|񽂗FA i*p:.uƯ/PlF]802/,2 fb]ͨp9%oyq fk~1.~M;}IZgs\vi>ꏕmTe X/ЩGz\4?9u&L0ۮkZ0-qoi6+KZL3hCh۴`U~k-lxgD+"xt\ea ;`Vav}s=O<( {qlT,7($Kl_N74wWDN =^꽓B~z^y =6^1 zgM$)t\-y$yBח <\yɻnK*8(b.jxIʂg5ئ"Cok^2Uː'۾g|RoHx͖Gi$Ŕ>Z^XmQË[’Ȑ|7쏍s3QGalj/?"?"?" B2٪+CkA+zرQ)^t/6c|\sۅ(XMۮdw>KiFȲj/wp=!b Hd]J9ihQK/JCsJ<#UbdkT:iAJj"GC_:D")@`ck:;rk؆4_ɆbD4^eu҂J7ߡE7 Xsz4 v'>܁}@qa/K2A"B]i jZ'~h%sZC͇g䁁2 ,͟1l^rouHszc7OC29QvLUTQ$`4r^$=]X$1ke@4&쾵 㦜 Aa[EO''2GplZe`$>% #>ZFsbϺ|,kb"(>,4WrF"O/Q2 d~x>d(![ EۋANuP0UUUNIp?{mHQ.2~=)5!t{>DQgߊjql~}_-Hl6]3ϡH}o\Bl4D iEcխy} ~^-N'4Z$;V01Nɯb"օ鯂#G٭KNM qő%o&)6u kO!!H.mE}M-8lm mr-o!{D?{H-" 11*,*T.T֭H•n}ٺ6,WQ|v<"Q*?*'Bߏ ?R Sڄ|D"& TP!ߌ i/uPaTRɟFRѺNdc4NTJWd*u7qȶ"D*nSY2'=zҕC9)(E҃RZYK{N<B>؆ G h_rKW6$X' !Ɗ_3a:M|ּ^&O7Aϫ՜J :D A q~2L%̊n.{^6I oÞ<^ 2h'r(FƵon{B:JޘL>xThCh6%NpS|]semw®,7xʬ6+5Zk{'YT=_ȉe |Oԓ2ϖiy5qB.Byr7늭ۙS-0(JzDBKZvF粸AI:e;N86yfǻյOR] ;V]XUЎ.S &r7_7E4M{ ՛Ŭ[fz* T>Ew73O;POe>>,c2 ztw;9y ,~H}a9h ,h_]>#?oU; U@,_"ž"L6Nll 6X /.-^^m0c*B#hL[2r74 U8*jt ;P>nO-]Ҫedw\r ||B?-~Xe$jJ$ކnUS0 3hߠ.o;izo-"N 1,r&bvIS8l)+s016VЄ5Ld_Md%j"c/W{' 9[N*KD NgU5 1rv肨>Ø?@CU;Ywes!m F$D ~/PزxXH9ќ@et e¸J`;)gSl9&WU;p;# Gwk J.KzA\yYRh{7:ۙ mgJ YqK~j/ R,}+]^Xz *("2rҤק%1OBdͳh{Ld|o xXxQd,9'[/7q>/vv9ڑ̳f2aܡb F9'Ć<`םsMld_"n\5Dt<5%eeMZKX8B 5¡sЌ@^4,^?ܬ4*,$YrF5(/~Z;4cl\$S'oŖ%*/)UM$is`ƊE^}JG7lyt!qվQ2=`+[>ZVY2嵜oWͧtog.WasþAK oZ_;o۫>sr4~`7<=oSMb"=Gu}p^g! VV!uY7^Ɩ~umT7nf߯mxɤ(C9 t6B} ;vQIo\v.lw1,b ѧw"#2pmg< #r+\lJxcps/@Ta]?O&?$5g 1 zF|2haO?p8`ێόav))[Fu ̽}&Ϥe^ V;ȽY̚] *Qx}sC{DZ|16I]W u-pt:al4:w s6:mYdrT GDzyfeɜܡ*r`dfu~naeGzQWU z*ȝ́PYPPK!l7GvFM+ [eeȫbiڝ܃سe^y|R)VeRZIJveTHOhx"g1ׅt.Q$/L}G4DZ]䎂[cX{Ռl+eEhu>L)d4'7w-Jޤb;6<ז&M?o pȒj=F+uy؝q\e7ݡSV_/ 0sLߺ4s0vugnιY~>OΟB".Z;|ƑԢc 8 avN%&&ApKmEp)삌,dvc&W֫_(@YH-v'% P}->_g!{{cP>>L^Sŧ_PK?y%C&]5#$ datafile_xmlns_missing.ddoc Ԑ9+Y ?+Y ?PK?gaA #Dj%9O$ nissuerserial_xmlns_missing.ddoc &)>C ?C ?PK?y%CLH $ 8old_digidoc_format_1.0.ddoc ;9"c"cPK?kCF"ms$ ՀREADME Dtظ?۲?X?PK?k]>>> endobj 2 0 obj <> endobj 3 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 4 0 R/Group<>/Tabs/S/StructParents 0>> endobj 4 0 obj <> stream xVMo0 `Y߲"@>CuX4͌!qrY4ؑD>IUq/*89IU/~.o*72W&r3d6Á  =(k ; ;,7~p~1a~(3ɤ=0_V:"o`i8/!Dgy{([P Zy^!IgNj`V“w6DHf]MO3Jz@Ǒʊ)pF3/A $)ݻ].Z,0E*.vlIYUk9ń 9} Uss\E8Xp$lawh"*{n8kL~vk}/b9)\[D%L:B^ ܠ{( 9q÷8Ĩq#}Ki=Ӣk2a@zI1=O &9O˽,m:<=şbV.,/KL#J2ߎ8U/:6CTw ^Xbis87fdi$zR^ {f&'Z#rS)`5aSeOT$m"{%}݇/Do[1{ @:A?_\, endstream endobj 5 0 obj <> endobj 6 0 obj <> endobj 7 0 obj <> stream xY UU> 3pY,#<.wP@@@4@\*S<ȕ$#S,aXJZ.Y%)-U@dy\f̞=go}j¯>_*{?s{I;{0(>,<¿x>I᳧I_#Y)D|co{Fwh#z9x՝ʿˁ)eNʃ'i++R =)^MQG)!C%\9 uT\OkΞ`+.nC9GULF,$c0Fc Wt\/'i6؎V rzriBJrB["zt!Ys7C9` „̽ QnmrJF^rpDv4(RCчذFj?T/& ]t> I3s].mqky[Cҳ%v!U|ʍE$2]!`#)Oim0@ Cb\P`-d3B ]1PO8y,MbO%0$T<?;-&4wm3l_l?'Ϲ/# 魿Jq7ǺScj6;w[-Ү5Uyi4uF`m ~DVք)wylY`yUspAt;)pprqx0$ 7Ģ0XOi\f+>BP*%iD/rC-ۼ2*/De߳E*\^ٹ)5Cz5Rtm\.KUe!N0HcUwެ<ʽ;a닅=F8jzve^ݬ\$kq5EDfFEu%I&S+he@ŪX՗T|b瑞(Rl8cs%[raFH{ýM,0$CPIXuZ|{ 嬄!6؞ȢV"ɥg.UzgC}:DWF[|.  VuEρx`D Vil^lٵ Tr0k"bi(2r>oP.\mjPKmmx,!!K>o HDiNZؤ[ҪY`f\3P:# i^?q4Xk?0̆0&A3<Y|(I@#%r S~O_r3`7X'm'dNdL? # L.1 ]^{)YɈp+2|Ri ʖQZHgQ]@L -Ib&x6ܼ!R"\-H!NXrsM 7љ `Z e{ӑG^BpWBzLїoiWKŒ/>̃q=z} mâwGe*) &6Jl_ˇH 7-<`f @'IM ˚}= pJl(HSx}?zIIFJ1F3r1W12}f 9cn녵 Kmzm)R]Њ{QSd<L+A}=e-.hA=jeư`ۆeqeQ!_|E;LfK-1ON2)7O]f7}dGwLQUyWp&c!& xT/ַ+"S:L(0 J ?J 3tx˺#]O 2l4ٚ^֞piϫ$iH{Y>aK=+JZv۫ebl 1;w@M~*VS>_bRxe&1&ػ}Jmˉ#IHxm#F)is3ӏ>OQh PyG>ʌȆȲ"+) ehhQS@i1oCy-hҖr `Jye ewn|޻;G]{5O$ !/ !ZRKV(uhmZ8_kgeU-4Z~t@!25@n{_v6~LW%Y>w>&> endobj 9 0 obj <> endobj 10 0 obj <> endobj 11 0 obj [ 12 0 R] endobj 12 0 obj <> endobj 13 0 obj <> endobj 14 0 obj <> endobj 15 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 16 0 R/Group<>/Tabs/S/StructParents 3>> endobj 16 0 obj <> stream x[o8AM ( K8&NodIԸݶ8g~3˳xfyY*>.ow_Xup7jU_^PJZZWU>=O3N8:mhߞ,iaJ"ZA?ZJ ]U%+nOOH==8+8=5Y+(틣Lm  \g7tU2VUH9Yb~J]BIY3Ў=Ť.MKJI h>0oY /K빘=AP r'yPCz?7N+GiqMMRJ3Fۤ@*~zm{z ;3jmG%~} LQ@8R]%T&m6\h4kVأ!͊%Jm߇0#Xy,/1mUloqzs,ۢ l/]ds`=/ehz>D1-3\u_֍t;p=m >{y\ol 7sN"`S"yWbv16h9 cYAM޻-YƋȡatsvnRi^nl}V-ݥA|oؒU`UʦK`ucja9-a`-(qͱo:1*]kl!mkx[a,l/DI8a)KKpKi,u$9,0u`iCMK2hRvN`]Y XFxm_߰zYP5cpZ vN`gi%.̶m"u0\:[ZM)pTң:eaU?GhTĦ: 9=R NkU!DaMJ_m<q?ΒЪLp#!4ָ吇 *5l|Ou811`-x-mW u&"/]X3T4dvwb/-~XU2=0ϛ#KWP4!L wU'v$*Bؗ'xCj1mJeSQҪbrD|WpV%8fԍR+rSq4BAm$7CA#h]O"IP+$:4x/UXW&V V)&^[Fkν]a x]U"%r 6.Ex%)Wn>^E75֝ͺl]F * mN|vH]ӎu d+C3̘ p%:i|UvR+n\xU ;N0A6bJ-wh%f"}cJܶ v\[7;{0媲?5L&ſT2qdPWv> endobj 18 0 obj [ 19 0 R] endobj 19 0 obj <> endobj 20 0 obj <> endobj 21 0 obj <> endobj 22 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 24 0 R 27 0 R 28 0 R 30 0 R 32 0 R 33 0 R 35 0 R 38 0 R 40 0 R 42 0 R 44 0 R 45 0 R 46 0 R 48 0 R 49 0 R 51 0 R 53 0 R 55 0 R 56 0 R 59 0 R 60 0 R 62 0 R 66 0 R 67 0 R 72 0 R 74 0 R 76 0 R 79 0 R 81 0 R 84 0 R 86 0 R 88 0 R 89 0 R 91 0 R 92 0 R 94 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 23 0 R/Group<>/Tabs/S/StructParents 6>> endobj 23 0 obj <> stream x]s6~(miA^\$޻'-;f5rvsR&I1[˲_h4iϾz_=~/_~eڿl7WWٻ7?޾RάQy2U\Sy\>\{;Uy'pd.u.o37lsvouh2 'ul%Nಋ}Z~q+B/.27fi[^Z@ŴH>Џ?~??kVۊ* k=<Ϳ/Y|Wv~T>8<( ֽ~nBaͺ=Wv>l(1?Y:J(xV^>RWޒqY ˬEUZ&gK}ym۬telt68h 2JrKW8_N\tH#Ve)V7eOno?uᩏe \,5xqؼJ]Z*xʼnc/U@_/zs//OWˋg/_v_qOp'}NKY i\Y?8Voۍx/mڿxѽË=˴`BQ[s?ahln*iZHHlJWUhV8ecW羥l߷s p"Gn>ϊ˿6bݲQXKו}Z^/P){X^v սtt?d J,"~Ym~թ>]te7Ԯjn _{!]Ok|O{u{VX:Ev/&t iKǽ>ŪD&+R~<Y*2zs-ТsF ;uL L$_"*:ٙ1 bU@ 2 ^TZHD 6L,v MGP* B)_ d!Hhdl3z~[V -*׵vyQ/6_)| \dAPֺliNj~. nVPש⠼u@yq0j7wáL,0V8(4A\Qb@kD$URU!ճ$VgA0.#"7Lw 0D*"cĄQ'>H:u\Vc.}Cǩa|!vV ;VƴF50pǨc!j9`Pg]WJ]!]%b/ xc e 2Tu&Ai[T>5'_]Ym? e'q U{h$Aӽl+ cZ$r["fMk$M9ċTE8W/~_j\CJ"u,Zi /91[,c2U^sqPq]( eԣ"u cFjqZ>zfS`~De\]~eY-Z~ q? 6~WS+6AxJ}mrek. w٢a(CT!GCD/D:ʑf'> k!؟4nuEq'Ο# !?/!-t0[:nšTb0sHU I0 \]!Brh_A,{ @_Сn~3Mv iT ?c|ol#qIH?~H:0!i`ׁ ԁ3BjPkH*`enS4!_]f?l`Q8_?=Lb?RCM/, Jg]"y,Q:Kוw?(J 20*iW0戵JyLU SBlBBZR$t1*R$fov>w @p`8Xe=n~=nXBLa;YXs"K Bgasb?b2kޭÇ3Sp[ .Y|q}?}A~OB 7eM,p\l&Yy{&6D ;D&_;τo5C8f[C`;6+d {ѼFdiaϸ  e`&2/ 2J;֐"QXU!%f՝'r`dzXO"yIzK7݌ |O1ؒp# +Vc[:e>`I~6`&@Ԕ=hZ|gӎg{"-6WDQubtHu"}%/|!bq:=W>_1s)DK8'w = >9~@Sߚ|U$E4.d%ODžb|;с 2ub= S-O bpcSYs3aB>mGnܣmMf<䫑u 50,K[4iNӵ'Oi?mӭ!&i uSoU-X霬cp CщliN!}F _v=?Ycwt;[™4'񑀆us;d]sH~h#;)3bnq)wS?^`mK7=ϳ%;[<ϕ)&]ئ?p,e@OS+Ȭ@8WFzr(^B!w%)cID(zw1 8Ի6? ɻZAK-x]MܢKF]oQG4>x]Ʀ gչqH|"7I~G@X/_O]Q? )pQ.~/|W4&+5qsDnllif[}t@ eQh^å{RaDu^׿߲;P)H]ی_ycp Cu5A 7.}>JGI:Gy,\ mJX' 0Bt&90L\V#zEh''iD"=f$ap C8>jF߅\ %tQyBwjD#ܘ_c4>A>qr6A3TQH0' W*.i}³J:'M"L]FګEE\e@ښvJM+ܶf]8(VYqPBvigׇm=Trxu֪xoI`dr-L[2+W5[" fal>[YZ>A;@ӤK ]zYt[鳩8hݐP3!H8JLhE!LK%-)֓Bi.q P#0} P#G<ïwݷ4ie(Ej!,BESv@o!Mr*MH5ql R TH!Aq&4zFqzx5 bFkD,Y5Fq" nakD9>*η푞(ONGhgD$@BA 1y} t4s+ƪV)z7}2m!T-10A)"ۍRTI/Kap&ظ;_HP  &]|-?۽CJ0H?rZ . EeM 1͢y\`L aV1IuD5]쌎[nFGd8Y[G%W_oeb BuJ lWPwlƒfa)-ar@h6Vܺ>/Jk7櫫.i?sB9-MKUVo&k&Mh($` 8#}4ݣ6䢂_IH wةġd4;6a us8ƷСsz8E NJXXЗrAk!ᖆ(87l8ړP YPUBɪ=8 MzB8 NN2sdV2F("fiJ:(p(nI C %ri "~np \ֻXyOH]BӴ5 8]epcqs6T@hz?CzLi}S dzLwRGsl>B&*q`yeQ7kjm돇~v/xb7FtPbꑢf5(( rlԎ%(4Db|C3=DR9r#-A{ endstream endobj 24 0 obj <>/F 4/Dest[ 3 0 R/XYZ 125 746 0] /StructParent 7>> endobj 25 0 obj <> endobj 26 0 obj <> endobj 27 0 obj <>/F 4/Dest[ 15 0 R/XYZ 125 736 0] /StructParent 8>> endobj 28 0 obj <>/F 4/Dest[ 29 0 R/XYZ 125 736 0] /StructParent 9>> endobj 29 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 96 0 R/Group<>/Tabs/S/StructParents 43>> endobj 30 0 obj <>/F 4/Dest[ 31 0 R/XYZ 125 736 0] /StructParent 10>> endobj 31 0 obj <>/ExtGState<>/XObject<>/Pattern<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 105 0 R/Group<>/Tabs/S/StructParents 1>> endobj 32 0 obj <>/F 4/Dest[ 31 0 R/XYZ 125 317 0] /StructParent 11>> endobj 33 0 obj <>/F 4/Dest[ 34 0 R/XYZ 125 343 0] /StructParent 12>> endobj 34 0 obj <>/XObject<>/Pattern<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 173 0 R/Group<>/Tabs/S/StructParents 2>> endobj 35 0 obj <>/F 4/Dest[ 37 0 R/XYZ 125 736 0] /StructParent 13>> endobj 36 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 241 0 R/Group<>/Tabs/S/StructParents 4>> endobj 37 0 obj <>/XObject<>/Pattern<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 262 0 R/Group<>/Tabs/S/StructParents 5>> endobj 38 0 obj <>/F 4/Dest[ 39 0 R/XYZ 125 247 0] /StructParent 14>> endobj 39 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 365 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 364 0 R/Group<>/Tabs/S/StructParents 44>> endobj 40 0 obj <>/F 4/Dest[ 41 0 R/XYZ 125 384 0] /StructParent 15>> endobj 41 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 367 0 R 368 0 R 369 0 R 370 0 R 371 0 R 372 0 R 373 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 366 0 R/Group<>/Tabs/S/StructParents 46>> endobj 42 0 obj <>/F 4/Dest[ 43 0 R/XYZ 125 468 0] /StructParent 16>> endobj 43 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 374 0 R/Group<>/Tabs/S/StructParents 54>> endobj 44 0 obj <>/F 4/Dest[ 43 0 R/XYZ 125 359 0] /StructParent 17>> endobj 45 0 obj <>/F 4/Dest[ 43 0 R/XYZ 125 112 0] /StructParent 18>> endobj 46 0 obj <>/F 4/Dest[ 47 0 R/XYZ 125 545 0] /StructParent 19>> endobj 47 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 375 0 R/Group<>/Tabs/S/StructParents 55>> endobj 48 0 obj <>/F 4/Dest[ 47 0 R/XYZ 125 249 0] /StructParent 20>> endobj 49 0 obj <>/F 4/Dest[ 50 0 R/XYZ 125 156 0] /StructParent 21>> endobj 50 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 383 0 R/Group<>/Tabs/S/StructParents 56>> endobj 51 0 obj <>/F 4/Dest[ 52 0 R/XYZ 125 389 0] /StructParent 22>> endobj 52 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 391 0 R/Group<>/Tabs/S/StructParents 57>> endobj 53 0 obj <>/F 4/Dest[ 54 0 R/XYZ 125 736 0] /StructParent 23>> endobj 54 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 392 0 R/Group<>/Tabs/S/StructParents 58>> endobj 55 0 obj <>/F 4/Dest[ 54 0 R/XYZ 125 239 0] /StructParent 24>> endobj 56 0 obj <>/F 4/Dest[ 58 0 R/XYZ 125 736 0] /StructParent 25>> endobj 57 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 393 0 R/Group<>/Tabs/S/StructParents 59>> endobj 58 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 394 0 R/Group<>/Tabs/S/StructParents 60>> endobj 59 0 obj <>/F 4/Dest[ 58 0 R/XYZ 125 481 0] /StructParent 26>> endobj 60 0 obj <>/F 4/Dest[ 61 0 R/XYZ 125 218 0] /StructParent 27>> endobj 61 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 395 0 R/Group<>/Tabs/S/StructParents 61>> endobj 62 0 obj <>/F 4/Dest[ 65 0 R/XYZ 125 736 0] /StructParent 28>> endobj 63 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 398 0 R/Group<>/Tabs/S/StructParents 62>> endobj 64 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 399 0 R/Group<>/Tabs/S/StructParents 63>> endobj 65 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 405 0 R/Group<>/Tabs/S/StructParents 64>> endobj 66 0 obj <>/F 4/Dest[ 65 0 R/XYZ 125 694 0] /StructParent 29>> endobj 67 0 obj <>/F 4/Dest[ 71 0 R/XYZ 125 117 0] /StructParent 30>> endobj 68 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 406 0 R/Group<>/Tabs/S/StructParents 65>> endobj 69 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 408 0 R/Group<>/Tabs/S/StructParents 66>> endobj 70 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 409 0 R/Group<>/Tabs/S/StructParents 67>> endobj 71 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 410 0 R/Group<>/Tabs/S/StructParents 68>> endobj 72 0 obj <>/F 4/Dest[ 73 0 R/XYZ 125 298 0] /StructParent 31>> endobj 73 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 411 0 R/Group<>/Tabs/S/StructParents 69>> endobj 74 0 obj <>/F 4/Dest[ 75 0 R/XYZ 125 736 0] /StructParent 32>> endobj 75 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 412 0 R/Group<>/Tabs/S/StructParents 70>> endobj 76 0 obj <>/F 4/Dest[ 78 0 R/XYZ 125 327 0] /StructParent 33>> endobj 77 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 413 0 R/Group<>/Tabs/S/StructParents 71>> endobj 78 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 414 0 R/Group<>/Tabs/S/StructParents 72>> endobj 79 0 obj <>/F 4/Dest[ 80 0 R/XYZ 125 376 0] /StructParent 34>> endobj 80 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 415 0 R/Group<>/Tabs/S/StructParents 73>> endobj 81 0 obj <>/F 4/Dest[ 83 0 R/XYZ 125 531 0] /StructParent 35>> endobj 82 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 416 0 R/Group<>/Tabs/S/StructParents 74>> endobj 83 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 417 0 R/Group<>/Tabs/S/StructParents 75>> endobj 84 0 obj <>/F 4/Dest[ 85 0 R/XYZ 125 474 0] /StructParent 36>> endobj 85 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 418 0 R/Group<>/Tabs/S/StructParents 76>> endobj 86 0 obj <>/F 4/Dest[ 87 0 R/XYZ 125 718 0] /StructParent 37>> endobj 87 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 419 0 R/Group<>/Tabs/S/StructParents 77>> endobj 88 0 obj <>/F 4/Dest[ 87 0 R/XYZ 125 316 0] /StructParent 38>> endobj 89 0 obj <>/F 4/Dest[ 90 0 R/XYZ 125 568 0] /StructParent 39>> endobj 90 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 420 0 R/Group<>/Tabs/S/StructParents 78>> endobj 91 0 obj <>/F 4/Dest[ 90 0 R/XYZ 125 173 0] /StructParent 40>> endobj 92 0 obj <>/F 4/Dest[ 93 0 R/XYZ 125 490 0] /StructParent 41>> endobj 93 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 421 0 R/Group<>/Tabs/S/StructParents 79>> endobj 94 0 obj <>/F 4/Dest[ 95 0 R/XYZ 125 736 0] /StructParent 42>> endobj 95 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 422 0 R/Group<>/Tabs/S/StructParents 80>> endobj 96 0 obj <> stream x[[o7~0R"Nݦnh7%nI{.䈜i6-!yH7ۇ6{|gjtnV8{q1~{DH:FTir]fF6O~.[>}*LgያO^ ]"ӕeٺev ^mx|'׃l!'0Ͽ2h3[ ~lTݿZ<`,WF' H|u-\߸Mkp }W~m_B${ߡ0.s\8딵!p >fPX1w}I(ke Ecy1<ՋrVǤ9&;],1:*]蒼hGl:YFxbdMz'+ӂeR}^FY+A{  Ϸe8G\z 7'!jT7]h =}qqX!O1 R s<6)VrH#PG#LN-I]RM4q#כb3DZC q}\`(p,?YR6ES&{%'",x^p` 3>%5Hl{“^!6PBITsa)~DXfS(8#D=z4Y-OsR;.sۀ{\#Ũ ++vzpjӏ+%T%YQFA Oyؼn,#[*mc'([,t2|k^΋2eIjoږ~l_X?@E r70|S 2tG)TNè{$`d,\s* Rbf(.va9 >";C!k@ۡXP)\?)*c^ G#e^n"0yrz269k ),dPc<z9 LyX,l!rr91瑹ЀjAcԷt맴(,%tCiځ&McI3 mnq 'dDѴV0ּiűyib/Dc hC{kN3)uSҦRJբ]礴sb/CL $#[+yH9 PyY$+rltS1,N*7g0iǻ5=[Ss\>ƒ{E ;Pkߚsk{GVJ-h qB0bo2ķ=qoWGmf0s2ka1ڋuϒ MMђįX .JN%Zs(}JyHhKx&5̨0}r@QW0H[7/\MgHv" #vilJ8MWt s1p%b'{!Z5뛽^.8E 1xx;>k[U34} W㋗I DY{QRJU׼CZؼs U%Y_JD]b^ 3|Kqb=ېvsQUO{$j^ )Nސ϶;UUybp`:0ʛ2]K2TG,:Gæk&g0mUoE":{U{RySvɮLRd\1v_hHM|4x~)q+ N[`[j+}{q+_JHyeztnE+KuP$x`L{ݚU~JgIᛓIES#OYDEZe~[e֥}JL&-} e&L&2au#ؒlpm.'e7= ($q>S9ǜ@0ӂB|IycI+dMS$tĶ$h_ P8el%3uSC`LL !h_FLڵ۶Su0jPS,$4:2.6sŇe!F@?!7Z@艷2T׮9Е@'nlO7uJS\y|>Z`ֶ9vm7@ʿ '}g=DRAipH-Dj?[Aj..ϡ GZւɏ7=٠+}pIi1^SNNzݔs)q#մ!mf0Yƹu ,`+htB #D #'TWiaߒ"x ˠ`x2wmʦ(n&۰w/ˈM~ʢKu Rt쬳9[ww>E+ER34x;رY(u,)N7XRYٮd?aoO ?cɢ oiN8jxo:y#ƺ@BXOc1Kpp4D9hm6M ( 9TT l4(Ik9h/~dTV\uT {#޷Z o .tʉ8{igC[Hb endstream endobj 97 0 obj <> endobj 98 0 obj <> endobj 99 0 obj [ 100 0 R] endobj 100 0 obj <> endobj 101 0 obj <> endobj 102 0 obj <> endobj 103 0 obj <> endobj 104 0 obj <> endobj 105 0 obj <> stream x]ݏ77{}g ⋽ k·W#ǻկ&[8>.G"dMf{n6_v\__5??{o٫r{p~޼hz&8Mc[X8p}Y?}?4Ov.pf _yٷm޼nMKvz}~7w}h>ik铟go͛?>} _nV:P&t*5g-6yyO_ՋNwV]Z4Cǣ 4u' 3NHX5Gk kЄȺEKPwaO`u*Ї`5p~yg߽G ! $;Y 5qEMi*T&ʶi ҿr%}2YdN!fJ T'a$S FT(ܑHb:5W]Ot>5KO^n\mfc}%f0+4_o‘%4155jUՉeU:\ߐ.i&ft뻪Np-R_v9l Zaw!be!#u!9B?>!1+!p֛Ǵ,}/K׹-jHǻGnAіIh-`r>5}׳:◘[=BA>bx X\2Luˡ826w1# {UIyR=L-|䕑u@ȕ)gy Asky1t`hpMΕmw%!+\SaBZw/_F+e"g[1Y{uul1D (FK<{ρ&˳7EB#iܛj? W->sc F z; ;UomB#DKթr"s:qm93 u%:dq)o8T%6rjj~‚D]&tͭ4leS/bn%jDp|ĊћGǣ/JdF)-z0µ>N 8f ̋e+%ÄGYL<=&L,G&lR2u҇%867F!x,[9Hnؑsdhw{yE[ v:){Ss5)SU+:9Iӄ/ڇͼ3]mL738%&4 JYl[]˗߽S8|Ӕ~m9 {TO_ AaH}@K W yO>8(ÿfwL 堑u8nd8P#ˑ U@.sU9tQ|n=pP-NGD@mZs\ 2V:VsW^BGTx!:N*cH&!fˮɠh|H 4 5]}ڲ7Ĝ$.~Av3e"F.1H-e-6Sh4ƞh[jh*HN"U-,LӐCrWF`'Bt-pή㾭(J?RbكKn8iDTllag3mCT]3Ŷ?'++۾򅷍+*{}{b{qBpqbSo,ۢޟ vlSSSŸOɱGiҤ؉,U%ce'p--~_kVq}tjʖcHjCNUVsZ4ʁ@)LsS?Ur&"ѲCҦA{~7ecDs NoQ}`J_ִnȝ>&7 JMs РyL5z]Cw/kL>nu7Ӕsӽu EI(IJ08Wc?DąH&{41@D\}Up1\0bS &Θ!G'_9o)S\۶Nxy x}#t8Gn\ګubmUKm4,M'Iؐ: ?hF_ђ?7^^϶P95IX΅ɡ!}Fr ,&8CDV52'^nOVLwaCȋEOuȈ.9;ql`S8Mq@5ǧɥre`^Siݘ| {xK| {*oM6ِ_O, _p֤2ntgFQF%^,OPx ow2٩U9hg)iWj=f!8Љjl&%ᤀM끍T5rB#3;²\Js,y:iCMc@—ě$5j9$HuYfڊLj+ЇEr/k7THj+=-Ӡ8xNja:VOv㳖~MQw>T\LȺ[imgk6TSN-89/~Gx7==@,6l?l =͐m>q}2>JTZn}z&JquԹO ׳ 5=O' 0.UJZt*+؛*lo ܏P29<2. KEE*+$^] KfrEmN F4%:zq4+^'+WyGC wx·Hގ.3م7v)[0_J22 };Vjiv1+Y QCZcw+nߋ>5c8Ϳc1BhXBVRzW'l1mn|*}7V(Wj:"j̨;,d5Y:^9G!~܎ȶmԇ ˖JBu<>$obj<A)"hPHFnkF16}  9{ ;=ΞqX{D+ ~L.X ިmds96<+igH_=VKZA |%r0݀:U4bA&;RjmXn&#mؖxb3 ϼnʶSy/3P~Wʖ hAl7nrHx!Vhvax" Z*Wt@"Qp:R4%<>.'E#8YF4(sWMQY]/("@PNuao9ij~H$WyTmMrS>Fuzol'Sh5,}S||.I#a_uY7jn]J ފUB.IT`*W!}Tj!| T>'qC\#hy'={l{"T4\a{~gb: Vtnȭ(Op=)(°|ʧ\L!82H* `)tJRxJY]~^.v!PςKLT5_ &)̒#f)AV öV6O6L$i9< uͼb  \+PRU!#OmgMDA䭃j7lA~c?cjespi{EG˒{W4l=ɓR_~jNꇇ n>۰u30܉YՋ؏QgYEזV2tNtW%q1 @rPw7Fn!zOG$Swta _WxyGM,+Zw=;ލf8X*DTjb ۬" .cJ X lA]i6Sg[ "QBó*0-0K l3@ C_TXAja"t*(#uB{^40b#q8ɹXJG~\Uigh4QJ?䅞(+^KW.DZie2[K-0y433D]8*P% 꾃lc(-+$m$֓SQz㔐Xq)ۢg&r6xvDD fH61]Ze4 JA<rITJ*"cb endstream endobj 106 0 obj <> endobj 107 0 obj <> endobj 108 0 obj <> endobj 109 0 obj <> endobj 110 0 obj <> endobj 111 0 obj <>>> endobj 112 0 obj <> stream x nH@ endstream endobj 113 0 obj <> stream xvJӧmsLQ3C쪒@8t,7@O{ɾb!_ع4/oS޼~!SXoàk]:jn H""HRDNB>wD",'1$&W(JJhZEphZR) [@̄`I+AT5@FbZmvDq\nxfZ-fwj\j02_'%( N`(G"QH,9Cmzfҩdn[v:lѠӪU 9=|bLTcœLp%\Fj;.J>tV٨תR1˦SX4 nj6a {T(BN`ڑ2%RlHu;^0d:$Sl6N'h8t;+Td<{]c/<C-2PZg0nm( \Tvr^o6v{Gc>zZ-M{낹V)t"=.Ũ{Z"$0P `$KZj n(<>>?52# 30#r^ t" x]6A›knr RL5Z`4)Pf7OaHX}`r3!0Qo.v^bXDe* Db X $ȗ|0 {OB>ՠQHgK,PnDHB鏦f0sG}?r21x^&^F咑jPx/_b9@aȉǐo &0aY)E _<*Q꬞`"WntS|BJL0_VFLx>Yxj͖; y&v |eҜcF @P+Ns0Ťߤ!Y-^"F U{ڕLeToEcx9ov2K@O\qurz%\}0aո]{*,cz-V}rw(rXZ~b֍Dc fQ/$AʹS r WL'B==JkR@wŨzi)0jXO*U(7xb XTbUa$*3=!8lU}n&*h?Mx+7܄rMx+7܄rMx+7܄rMx+7܄rMx+7܄rMx+7܄rMx+7܄rMx+7Jk㥕 gh\Qj7t{xz4o堚".Tcgz`=?.sv!XexѵSFn5nL^C+Q +ZhwZj_OߢvwKxJuحgz.4WLC +be~׬>уLPj w(S|V5VY^Q1F$UjMvw ̕Mѽ\o׋,<׫t.=V~zI~:ڍ*O~N%h \`Kl;X\Vc]#u t2tۍZMB~*KPޗlsz!-q aO0L螇'Y2N(}"Gn}nŨS|=RܘaLΌ.]1gj=pܟIiXq1AjTtXq[LB=~TEBWjjv؜QcJX*WsեLp .$ kVg|hSVզ L* pJ9.yPi 3\\E#*Tn/Q\DS3A-4n p8xǵ.v.J<Eh  龔v inPLhF9'DzܟSJRVk:J@/Z JJB>fRD< P͏iZL=#Tk[nx"IIڤ`u&D"LRt:7T*L•x,=Dχ$JI>PTRF*!z 'x<^y^Nvb6b*KYob{YZ@Ff9Ґ"-CL&3b& pm4~)r$BDjPH}.Oõi  zħP I#f3d)#ut"& TTG71uӝ}/z_E?ϋ #7sIZ/ endstream endobj 114 0 obj <> stream xàS_U a endstream endobj 115 0 obj <> stream xv8 D[,SL vy]E鍕İtx E//O{Ӟut~g>wޝx6;p(n=ȹY2c3ӈpO_PEgi\.+U _1gU: ,ȹ}?J~\yݮفVB?52!s\9 l/q9ðdG]߇'e9/ zI%ARl5ut´78:yj'l2YB%*~Qrܭ .bfch~%coGv #(D/sd<\Ĕ0gLSa@) _x[?TWIO6t _؄x؝#R&E.w:,)jo]qY,^\PAk ce Im{t:_?lPi=J/ pT5`F^.'r2 A)PyLTeڧSg%$-G;+w|&"2aV@0AQôb"gkz#;}bPE7e&%"Li o} |''lyd12|xJu(z3HU YtǿcCүGj'zXܓih7Q-Rah@Iݡ3AT)Gڨ hgl/tB$-0t%~Hyc.)r> endobj 117 0 obj <> endobj 118 0 obj <> endobj 119 0 obj <> endobj 120 0 obj <> endobj 121 0 obj <>>> endobj 122 0 obj <> stream x1 Om ?x5 endstream endobj 123 0 obj <> stream x  Om/ endstream endobj 124 0 obj <> stream xXTg$)wsS61&FANǂ" ޫ"ػ ҋ(6[1n6nv>wms )̙0=<<87CP( BP( BP( BPX>az20;FG|-fIWq6 _rZ6֛Fr^hXruNwFksM}sX}]KTd6g[svRֿww`u}q.wtDP4 N>*0e'5j=gYj[pۢ._f|+1>,_DĿaL`\ךo33}> D{X e1G=1Q:מxfcmр+?FuzӪ309g5qnW)X79܃.~LǢa#:p/QOX<찧Ul*]/?ı=͏>a%^uoسC{LqV溪j[w5l7 2{[3h6=1 bX:MfrBΘx"wXck~-=!#]v3390c g|zwsH2!ݪ.UL*C|ɖKn˳/pd+~)AAYVS[>XYǠ m&埑m&c 1өwtǿWUT@n}CIiׄ :`33]Վ:ml|'?hgD?8_՟- $i'{S3XIq>r*.[}jU7|ϐoBN.׌ } n8B&2ʯVpQCݖ>S`LC]$\Wu"g;uNkn(ym? ^ua-=Ubվ/Y~U$_XCe 5z0$*^k÷ ęNV _ie>[S-Es*i{Ae]sstLY"OrW7ȝ/]le+?'I|Wg^U"T? σ&=!*=SpҟwlΠ!yJלMgB3c'{oŠ{k߰ͻ,NE5n^DǕKn-\M,]wɦ?e||OHm !f Cbwdb!0.O#N< Ie;?Bmo\7jw]ֽPr[UvudނK<~!rWLv)pL}D}֗l %[?\ ֿGhQKŨ2hb@&:_>BPN]G5IoHO~{$\m\7z%[>$76.}5l I-^׋ZL ~L[;Neo3d[?"FKŽ ?ta-K &~Io6nK߰-ǶZ<Wt4JN(r/t(p\_hL4( K9iޠV*iqLn~L'h<vȏj'w˳ϓЮu5K`R0H=VH㶖;LfWx6"4 :jXh< >"Nt#Oҍ4[tV6jlsٛ$ntPLm@Ys^~RD%yV EOD7Ssm W;ddӃb%t.{čSmǒů^S_b Q'8>L%g P|ө7]H6lJ4nN%tX]5e%yV4 XtiFVvT}NYpͮ} ǒZ(uod#,ya m *.ʲIz1G8{fYH~e5o8TJKuH['2Mm8ge?^EPՎY6,,+'<Iz[dE_Q^eG-!|6ܗn!@4H7m=?0ngW q a@w$Yn;r,Iǡ5ˊ3~tl*-8ĥ2]57H:qid+=+ƍ$ lKwKGnCNYe%=t,~D* 8Fr#riqsX}ݾm%&HRQO/(SyZwɶ]ѫů;oC l,IWKf:}KttݬVV":m%%$Xgq{D}ѫvWcV;gKtHr^QB4O{62 Pfa IUa)udEvWdGy8lIKt.ŷIN(r2 K%u#zkv9Yge}.^AY즛= ǀ&Aa?,˹q^yvrIJIx0H3E*}[v,4(~jՎYӭ et8ZyƶS˳)s.]˿Ptmb6X@m]܋sSn!`:1DqꄱyYzaIQկ 4V^U'/b6YR"M%tһل bHeUdWtj_= 8L]5ڸ]V\gIRzܰ~fuKZALdg-- m4e -tiIIqa|;7lV&~C0-<>̽@EŢk42yEN?٨]{p,)Sp6meyEYYF4W|LBwLRsu0nIG}rf٤-llھ*VK^ͽ9?b7q1Al & ӭ:x/?(K~RlҖY6IR՞Ւls+sYgd'%IG$HhHt3Xm\ŋn&uJOH3Oɳϒ&іl".2y畹sjc8U>gX/)݂xQ NI $M_bMCI-}[ IJ( XqGtE ;$itaIi%/ 86єI9g噧inQb'?I :۲拏 z6Qa'" :$’SJfa w"19I)*3$)D #$,׳n$ڑn`LL7i* ?0v]>01K*13\Nn6qJ$I71Ty[ 1/n42O˘O'Ʒ83n0hn3tJܰ6qr$Wާz->)yf<,W#N% bvynKV4ҡ%j,,hdM~R+M'v 1V;VnY$lH$J$tha2K [HȠ<,4[)o4qX&a/ݎ"@ nmBk1qR4G~nR; EfD[ yz,GrL!o4r3Vt񣏙.ɲnRˏnw$̲I9J 'i$' ZIل\c>I7.i:}D.J0&iH{>) ^$[,)I>*JhƵ0 gj|Y:[Vj~t0M!I9&M;NEp'j},&~\\L% IلY6ߣDt{1S mj^T M1~\$RORLƩ86 ]L=.Me.K60#dQ2St ˋĵ G%taI/p'd0tM2G\T/)m"adZKcLEmIwӭzaֻnU" b[.IJ7(^lƼ[rL¼0EH:rz7x =L\}p+1͂6Qb8-h6t\/8&N>*NT2? #N^ ͦˊgj 8CdtBጟn5,tp̻MeP=2VєI>&I:*N'tOG50U[l2u_ky#I7kڻnws-='uJS1-M햍*eLLQ NqBt~T= #j$݊f WhnwZo 8l,=4\J$$qmA^aF+7thn&͘t ϋj42T32>5uItUO fäʍ&:[UN}z~L0U.IbLmH[̧"0UNYa&t7$k%H$UcRF,AG*mG5"0V{o0q+%<˙tF"Jh#%M`M$^6yIq+ͽכnH70qmʤZv%GqMVIRH)M!1LxMxM0HIjVQl0y~&ܻ-&鶈[m!%oQFQ\oiHh#[L 6nܰ:jf-}Ht#5)ԣrPM~n!1Md$[;9kmꥒ$qՒm[rZnQ:5ybԋ&+7X첦' IƑkј#\$@w6QB0Iۨ~!I:kҸ1l|͜ϙʵNY"yK<-sڒ$CD4 IK2^Lh\ #b27ZNP.L _r yy9ˋ-|6q*CjHzrs#Ҍn6HlQ|3aAt?0}6{9w_vklǞz^t{_fy["[i Njf?}Lt#s W\.Ll ;mpCx!{y5:2&LIE1O pLvQ !S^Jk&ڬZl2,c,i>F' %3/_mCn7?^ 8ɢ!Ckl$ڸ6A9;Vh3*$eę[:n+1YCE 8>;U°jaD0VV+g?LKF٨cl=d`D~ѻ^h5?t/ j|Z%9sgCf=ty!ٲ91s/_Y/% U#%5Z5QDx胟tX԰>FmIxWvd iA;ym6[xhsJM]3l-y!%lqj:qEeTm^h02!E}N΃~FV)"+eụ;lVY,H~.|E3s6u=9tI\yQ%ZeZ{ |KMͲЭ6Ǵ},dh~ר28f9% ެ[C747/2Bt54i{jtqSFcc<-FχLi&Я]le:)%yLY'_hS#O<3fN%1|a<-fY#<{{ c޾`oE1j&'O`hc~IAro])Vs- Xξ%iZ7'=[K E~w$|`a Zgi#|(0$G3ш?KB2Y7)e6( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( B V P endstream endobj 125 0 obj <> stream xnUxfe= 8WK$}֣CtPr^I֣CC^w׏J7(ЋX@Ůߒ4&Ҭet~DY7'ž/7k$RԧJb$oh$R-:%In_d$JMTt$R=l?UYO.SVwIZ ^c= FI@a5;%fb$Z?J ( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h$J( h,)zp %ztx%5[a= 8H-)6t(b2% 6YSܾHWw~*$.ɥxY|6O,KX#We 8`̯JD Szс&JZ >86eKb:Q:% .Tg 8tun<73d76jWJONIJu}?7dPNIޒ/YOo-UJ#9$͛X޵FmPW% blPon}aNkcyv GR$`bT_i?r^፝fƇ3󛒬y`irܺsw^fwXYDv$~|V"[^X^klntjmnVgˣ'$t"7gՕfsl4ˋst$no.Y3h*;<:Q[XjejX)IF_'N%mXj W461YT*WTSSKL2bz5ty+7oE\~X,) l&}*N 1>tϴ"D2N2Y:J&ѰbHXݚax}3hYV5 f1tNKUM7CN nŹ>-vM8dYOzKp8i.Sv: endstream endobj 126 0 obj <> stream xXTg&Ds7ݖ ҧNUP*ł4Q(Ҥ#Tnv7lrws7?# 3 }y|ï~8p_P,x5 F̷(^30{ʐ6f]1˾lsEC̲. ,uL3/Ly5/Obiɻ1ޙ針j2SVcBW%s)^^p7\O;vΥG?Sf'poI[N{㴸5sJ&ln]_ז|3IZu.|Y۪/ZϏd_o|ZԮ (#!e᧍v ]1XL?=r#Zd}>a?K~~v?6[2ͻI޹J{/X G߷k}[3LU^U]SnrzsN1j4/!AzɋTܿWGtIzBtLѭjީk?H#^72ӆ:M8«e2Z[ʲ;>P~85ew3nQy (yO22g}?:V~z-qEnrƆU}7nz(OމTOSfVfQ^Ak >zN>&~ۢ&!rEeydZqeR֭7Z+H9Ő6?[/|}%+l0v~CXRޯ=LET@+|{`:7Lo#?|L veH?8f-QyN쐡cs/1+|+xasvjJp>O)S*1'PLC@ƃoNO$[IWQJY2St_~?x}TmǦٗǘ+$A-H̽]_~^7|gAePޅr K\U#q^ !qW )hO{]_n(s8^GWvClWr"O֗šK窯]kOw>C35r9^C̬O&yo]kvwMy7i14iWMTm*ͿWݲɺ?ٗ? CG|V~:C>3 gia|\_PZl¾nTk!fXC΂Emr36ϽaYͷBP9hK_ؗ}FcR}r/ OiS Ho(l}J>k#,n@%#ɸaF|*\-`0$YuM.zm?la?[?+:̓=NE v;gFkZm[oX5EXcs40 /03 {׋ ն].‰'2.f_5ϻaU*l=*|6m֙HWoEi%EigI'81$jC K.\3ϻiY8YkA`$P{+-sBuI~^1vt?]ībܶХMnA1DP f]d| F nX]'.buIq^vZ|pi&y/%Vv"#c{m-혹]??˄gvAۗ4rQQ4yUX(L ` E5v\@nbSNI2.e_Aaeo`4':qCŰⴳS㼸#zp&/$ lY?aTrJL!-p T:] 3c|Q݄%KI^Hn`:e8} 8yW 1N\!ƨONRG~0 Ѓّ0}'Ff9 rXLu@u=xXP9q)Q awn&.zVd/nX|BD4 GThOՕy^qZTd(/0KECvnܐ y ƇF}\ FQBeLyI9IYQIaqyqC,Y'Jn6bPt\Ds(_2 20e9ӌthQOPʋd:h{P:g`1sٮ5`S>-`+ 7f]F4g2/^ul Fˀ`]gMHNC*L<ʏ)ԙoǶc=ݶmS>5vݾpT4&BcBŌ),z2$j fj2/ IũI !nL?3حێy7 V?*L<.J>I3P:L F%)'GxAnt3efQk8^~!Qt,21mqYG.I=)N9E ~vnt/3 կ]ͿܡZwDpLtBrZS  s +u)(C$Ǎpc!C 9o]/F~7" JwX$ Oha0sa _!3̍{adj#-ٞGKeF5š)3̜ATHuqʘ(Z#Тr̰d*#͚nGAC*oTŰhk\*1ȺHbsQPl|* 7pa1Bs +uPä _30ĉcGbu=5HǸU퇸C0>zFq1PҠ9:aR MANt/; mwo%TѥزC\hTED&a0s Y<AbBa˺!-$ C'l7ܐIIY.bUt^1D409YG0DtW1dP~x4p*\2>h& #pI#1jQF&-f:!̈́KL5ݻȊP>,L)%37ꢤ.H/"x; k`Tl;fQ%imۗQ5={XpD{2B8xtG-*+]M(k5ݬ70lv)PQ0^n/ ~Dx*h UrziA $ϝ7-%k`$l;1al_s =){amR~bH7,LE@8h0~C>NT7̰VZ`=ɣ\!oU'%JwA*GDQ Fr#aЏ7ďF3@kiQj$25-x1hT ]Eb0%va0{9CvfZa mO yRv]*# b`E'G000{8.Vx3t?-` 9خoSW;.pc`YxU P uuD Ë)MljQ-qۗRmԷ&vFVd5}|tf$hT vvd'،}MlA";Uѽp)Fa Fˠ. jH켘>N!v$:!G^gLnMeEv=|E n x1-3x>^ HtB }}ڶzz6ƄfDtjP0r^1mr9yvVD;ti3ٷm,+8c?tk*3] )Fu~Hc0cJzL/lY+ jl[mV>s@ǎ̌hb#?~l?!<*1-3#jnL7-kgE2ti#a6ly=X#boM?8Q O`r.+ U-Siu löc} k4FFFX+4pQ *c0΋8Q8QvfjQiA$]F.[V٥/%ƶc|fU Cm0qA pQEc6QΖu_3D K<(l%$ mߊm;oZ}y3ɫXO ; G {бb0s 5 9~@ -ykNvcLA;ijXC"N>ti 3Ɖ섅rUAʺ@?vD;6Pv: K CBg9Lh~a|VANd7c0sN tCL <-ԵMvd  L<(u4i34Vvd;'ե+`-йVԢRwx8&ςe:h~toeҽ'D`q/J3)w]n˙uma亝]IvX8OGgiaO-y'FWY9:H&Tv0p,еM~Ko_SE:kbg: )б´B6!m`41a}5)'~4f>f@2s"yxJ[>kj[ _}[&},c׭Hx oկCg ǀ4_C|Bi_ $2#rumVGn _Fm!{Zeb1ؽf)_ SL-iLE$;jf` 3P e0ԣ¼;?/5ݯ[A.#{܋]68Z,l94T]<} V&.E4L %'T L|o +PӼvPi6j84 zV:fҷ>˙hWjCuU<%zkfAV2bP7|`t$OK Zb ;F`m,BV丼XFY«S].z=E}2"@s0Boh4-zM  7yzqY=',|+%1zVz 0l&,BXaeMtj_#{0#5GoP5Q—Ql^> s98p8p8p8p8p.X endstream endobj 127 0 obj <> stream xIog33,3Pcް;&cǑrZmOV9k+zr"w'rh>Y}rwn9 U|\ug_8}x+-Gwy7H;:{m:tG5(NQ~Y^1i79pIi^4t4q󼐅k~H ˣSg8Q}IZ /]?tCi+,l7pi),塡3~Й"-WA ]#=&i'LX"prtWI+a"s+VD,{i%LMx7iI8{X/dLz5c|y{(/vRѫ+7\5=/כw;ݽ`^s2N@tYY[Fk^gݥNgnQ+擑:;S@5^(*V4m wnoT\6nЋSM]|OjiROVorߣ?zA{*[\ŕɧX,sd,bnE\or@8'gҙL&;順L*Zϣ5;EIt_ v$Jm~Ee[IQ5W7 G{=KYs J&U%QxǼ/Q< Tñhgz&lvy endstream endobj 128 0 obj <> endobj 129 0 obj <> endobj 130 0 obj <> stream x X׹{6&#ڤ.+* 20#l"n{Ķ&m4iozczso!/ro{o'?<<9/!-Sl %A 3vWm& }د` o<CXy)~\WORg{Ʉh-Xzó+miI6OƧ'su?\+?[#\dt}v3-o+xT.j@ׯSIAcЌ#qd2避0~{QvBp)ؾ䶼#p<̉1,I=bWOn_Ͱ.䚮n  t Qvs2Ϥ_8Kc^]@ݵ՟:o~_w 7,mgB%1Q;uD7v]xߠ(:/ %}e`>[U7 O;nXx}ם7YY'OAb?dQYEv7~XWƱ3h7LS Q u@uyEٺAv~Z`<+;ݠyC1iyy%kv76q"7?:|{o::Q1A;r/-p盆ϟ-|æ`ɽ yx"\ܰ/"޸$>o48 at1 RD֍{n8`7wp !I=r!7J8-5􍣲ug`~KvWᠠ=nz`S}5(]e<爾1&N9,H胲/۳xlrTyFu&]U:&!:nUhM:gyZ6&N>,PAYi̜i>8n@ku*88y03aG4 [\ɽhuVyJv\g̥yntSؚت@EV&(f:APls/\M,$7Ũo#~ 9FQU J3NZ[QvwحLPxC CAb䠋 '@H`G4Q0ďkG`k A.xhZ ߯ f1Fy}6dc#b0r#p2 W +%KOȈ8 u?2SDWB/s˳A%.niyYTƺH1$I!࠶:) zZPrs` D!^|tQ ov 5z-j&ǐ \$s6gYDOHP% TXa 7ӧۍlynxvb;6"d͹yb@!:#MJ6)fB+t7wۛT{SH67n`ƴ ѥѴ15c̒s(뜜6Ҵ㰁% !$0C>[޴n<}<7<70684,$C~r0dfYCy:4$H3(L8ċ`*vQ}6.n~P|XJD8DXl}KLdC5"ĐgMJQ lR4„>^L;SQGdVk70BvqCiKRINXgph0CVP2O[ghI lRFu7RgmE0 'jL(ҎJ; 2CVP;)#{!$0BjyF&D„"V,XY`H 4ctauzpw< nXAn#[¤8j 31dVHc(J&?B-ҫlH7j7zI00ɞBfb &cWˇ !$Ђ,6<C0?0BqkhV`e9!-Fd#J$!$ЂvZzΣH w#\VU=B͐2"rҠAi6)|U7'H7r!{y Qts`1Xd$'$$# ս<a؀Jipl᩺_2 V1Y&!#ȈD;tKPWT]l%ƸaEɊh$P!ѡ3`qÐCvbHRFA^\'[nϧ?hMnTuJVx#/ ?fIҔ2kq 7 (!IFԽDyf7n0 F#ܘ'@ 07~:9[fh7&%ɣ'B@(I0ɣƯB6ƴ›P]SdZx q7\i;ܘJBH3$юHS "bC< 1IC„C6 PV"1nF-2 JGXb8iPGɍOQAYބmg+ t[`;l>$J@M>P8!iH#P,hb͠P'PtrBi~ݨ`0(_4BC15 vMC{IFc6)&a"_ DGսCp,I2$I Ի0cՈXMDI" BA MF(0܍n3nD䀐B`HJb5iC&%T.F TD? DhP $=#XMiar6)Ƚbn%p3΍LE4"^\?[+K< cHQK8ID0B꨾[(FbbGrc7(  AXC؀ ,d\g|U ˈ5%pۉލUP $!0(7 #=_ŋlVZl6_gZ+---XVРI< bHaN^,ڤ\kK=ȁ0C& (zxE:1mYM&sMf9؍9nh-7ӃX͜63i(rBf~ @bzX{ģ6`AH iUf2DŽx yt%c0uNI@3fx;j?7 ě>oB i@^ {j>VfX)^MWfg8vQvcyg)-ȎǍneEꆃ սȥ#Ĉ;0~ mVAYMݲO#rca欵X[JGܨ6^L TߣGƐTBU7ŏEp{YaMLnZN% w7`qa~^L KM1dHubc-=ؤ52w꿝ZR@ƴ:`[GƐ_Bט6j9 .jv r#(7'QS-q9(rQ8 `H@"la/v(Lᆆf2 1F%Puz 2"  bq^v ( qDʚ"_9CQ oU'C>Pi:qP,^LTŽhb3Bj 7LWㆩc.M&:ֲ5*Vp%#ElUjᑿ9׶ /)~pIw="c[cmǧXFTɔ2eX"E|(r$R㷑&5u 羲pz{SHKDtWo߯HX ĦɄ|8d3vJ}&x6Ŭ9ԕifTKloKpטV@z 1ٹX3[^jNqrV4 d*Jb&_ڔIYy+V. vdx%3ayՙϽd}4=)AUX؇Q] > stream xMoGq; Y޼68`Dʥ([UoOmOQ/=RZ|*VHQOk;욗qJhv!1҇ݘ0쓓&W>al;9::;E7#H=7B+h݈㇢{ShNV؃ca,A Mz| ۱sI3 '@-:',ԖaEh/% #4 /[9 vFf/mVpwIآ~O(B틃$ef-Iz[$l4ޛ'X&aK#DIزMv4 |bmu -ZMfĨDL&j&5Ddf2Q3LL&j&5Ddf2Q3LL&j&5Ddf2Q3LLA<4 ;hwf=+4 kfYճ@0ctÙ(Lmd4˝MVՌ:Pry2]u?_s淖vrrv:?6OA?;Lɬ쫊: qf_@FbO?к}֬/&a$Țzz {b>{z73JHG;B<럎ZM3 ny$'Rm~{#>8v7B.+ҵ{m^̭ݭ4N{\soTf. \w%\(n{=ZͽݝZ7}?<^̛fZ݆Zlm6̕\&xe .E Fic)j  j~$"!Mюjp,Jg X0泙T"5Gq9i^Dj5h4[4uD~߫I(iUi:S<$_y,/,^_G Ixv!}5`%Bueg{I id79 endstream endobj 132 0 obj <> stream xWy@l|,I$$M'3M2c{ 6&Ď@%V xߗL&6i=IKJ"ۀ@"=W,WWhРA 46>Cb[]{Hzw3x=OW z?Ad!co?^Kf~QởΧ,Fjij/-*_O] /Fwd4xw-2o|7?O 'b&7BA%Kz}궸ʿZ޼/E˥QVp"jqzum_escYa_0G=wvld1wV}]{w2X's^n?% KnS{g{D佇 ỿY˽S?u_.<S%}_̇x# _族}+-',kaKϾq`~u}tVj~JaaEńufmLH*} ;_Miy϶D"2C OVeNZ sNl-D8ҡk!j0 yt;0J$=I&Ԝ{JzemǜsVi|rbtX_&['ҶڶxΑ- B,X:BblWX4mgu][x_GD{0}JkKZyum‚DK$[X:Oel!"*WxMA{FyIs-&HP,12>Y04Ra"/*442f@j4ْdailn!0[kJO뽑Bd#Cad ށU }]A绠i; K* [@K'@O䑛UIJZ[!2Q{C `r>|i*,C̖͚̕r\\7ڎ `cZt"3p }X ]us30!I-JwlIu^-=і[,[޳jLq`lW$*qSxwAu $(733a^7t*i~\zΪ]S0Q]-.e#8[ -ėx-h&!6[^c\9 w]{}7 w=T龜GZ[~QqK ^}\vV>zoSop&L8܅RZ<@`rf-ijDdK[-=eVy2޷INLwa{Z ;*K.|HiM1Y}95l!8زRӣ -Y"2Cu )*, aCҐ)jZgpm ^aasmit+c3p}hvx^$=B! ,eM4nB+,t"[4-DlQdK,gɖC@];{HrJ75~g^B-rX5d-#ko˞|aMbTXЛkܸMBWCKsgg5)5d"Vw m)b%uO" {Z9;}ATFDKYX;m?pZafK2BY̖([ `˳_mIٕ+ȳJ*}򦀲Yr;F$0kvLC {8lWFdPbl9X+̄m- Fl1-%GgTv̓PDOcsf.H`t^@m93nnil)+ٲ1-n臀a!g_yl!d F[F*".Lj<3X 8WZhڦ5)<b[҆>qe;?l֊mI0I\5+cDͰF0DSm;kJ|Ja }> $({%@bKLOw abU1, ˵hYҸ&U 밼)腉N>PUEE$,l![UeW.d"QYa@nU:N)-bslaH`4, ]SPQ([dd"Q&zہ1ْ?aB%It+L 2DbziM4DC2󠴾WTwہ-r8d`1[egɖĚ1~YX˭#JhkĀ.DSu˄> ur-Kp(,uA!$q9=sFG$leJn9*,Cb޶l!B<ݖ}Ed bmɎ+U-jm1Z'5 4;8enQyDRBHnRFUjׄuFG$Z,q'5. ,SJۈ)(k0[rb% ,qJzpmDI_Tϩ߶l!B-drN(eMAuDS9OCLdZNIDr, ^HQn~aY+x}G[2b#zAq Ͳ\_U9OaC4 C$  B)̓^qu;^QBKamy3AQ[f(,JNd`%읝;**|8$o̖R'(jT(eHih=%솜 AP8 Wu K]̖|涼{l0-6KAE.95Ή0I- h؂1la@Vl)qD'іcB 4a4a\Z"Aа%\5#*|H7j& 'oKƫd }Ȗ5탼ZACb5 (Au/i&N"hа4ARYG怼_V- 0I?ے@#[ef bS'1t !PfKq.7 )5~qe&mE[jvqe'i (B{@Q9cV"8 vCXe>i_l쀶&:i7ĖXmLD$JvA#5:iɘܟDl1u}`#.XG-`'l†WZ%hzl!"ْÖΘ-Һ^|¦[$y\Cp)VXѢl d=ҪNq8hUrZoWtHk{e sEA0x%灙bEC鑚:^#UINl&[G|lJo&)̃ AX f!KCJs@EM{`W-%STlv D-hC; F,$DwC sP[Ry`a?**Jú^yhO(j d AhĆ/Doݙ9}KlbÖO9l[FDleu%A"Dg%DЪI"IeMXb#` ۤ{l!a[{nU~Ym1l!E֌8ѽ3!9;"1vڄENDATr!ĕp}YmhePl'"ggC$vqYc ڒM*XK%gIoI9T˩+Z?[WP5 g_ЧC}W\53[^ +V[ [vSV3AQuL`EΆH*R l}k/4VcDDvSZg t؋EJ7tKL>qnW6- oI4xYd5]lJM, Yr!0[Fh'[Ux%>iu[:a !8Ht7iHΆ=i~-K"xNҋX%0ѽ3!>$jJ\;/!@e ol5 +<Iun$ApCp9+Zdhʲ]T&,q 9 bMfKvYX;$UD]."(NL~|9c 7S7D?^tZ~CX&ǖ\zx81$o7gZqB-x=Lі}dFKܣĚȖ B\lٝQQCgebhL:<>} /|+ڲ2&v [[~fUCjC"m.?zyp*Nܫ` /v OJJģf=_`WYx)G?M5ERGTMs]96=j ޫA$.زbBsQS %-/2ږò_!)r |+Ŕ'/V[C\3!,vJJB,u눤ϳ4&1AX"-jVڈe/xQkCB2Ye'G*-U-c5U'gԄdW.cڈ >b\[v-N0v!]6;a&OڢŖIow5/ &oŖm?/x J9"Vz<Dz#+|xt%h+ 4hРA 4hРA 4hРA 4hX# endstream endobj 133 0 obj <> stream xmOPqpB;f 2#BT4@Y(:ʼn/%rνd,CrgYesa#s^m$aXk[%z[MRV/&w9i̎\nb0SfXpܴFX=$Ŷ7'ܗ}$I"@7I<$\7Ia\C$v:(G9>Qr|(G9>Qr|(G9>Qr|(G9>Qr|(G9>Qr|(G9>Qr|(G9>Qr|(G9>Qr|(G9>Qr|(G9>Qr|(G9>Qr|(G9>Qr|{!Or$ņ\&$4*m_nߞ~?jw߯ΎI䋒<{o>\\Onn͏o',V_;|5Ox|lCOOrrʹⲪ]8:Võgr d{wx4j~ލeͱFEN6wvpu .ͤU:$nɆ_\T8F(Zuk6l^Xq}?U:w1X©tBVTt\e腛 ڵ endstream endobj 134 0 obj <> stream x[[W~MΫqª}L2L3>E'm4mNؘI,H ! ^^8}I;MK9؀,sϋ`{}>pGdAdA^$ЈQKC4[Q2W<7"cᚌ|%(?0.KofN'?Oj_?竰+Y;7F_y-3ń%>*,JVM7yJT)Fa;5[j7*Z\$ĄB,QDS-ֹ*kxB~ۿ+_\\[eaYψ7oE>x_Z\'yao&bvYآ_6Fg} #lU[[4~uwZ c?/߭ צV9t1[Z-/~y姓_ՁʡqEbǹugj T}Gs߀_^\Lolթׄ(=XM9vA̋z x]êA; r઼wFl:Xml9D"qjmm^FL`{䳌|[幡JmĦQ^m?E @l!lul鍑-5~Q$"{Kd< JF,w[㻥&5'$9/6x>f~+ \lmA5DM4zZ0Б-C58`U}yz)٢*$E[UA˴9Wynjp[&#x1L=X-tC۠z)eX\;#-Ė焵lK[jV{JW &#p$!-PEt+ge=aqEmAnqeB-UqY90mƻ $X/mmC7>+/zb[zM[DmazkJYm;"ڃ ., * x+zNuFhrz')R >V xtY.5Opa\W YwQj=m pz'B͋" VE㹡v#UT!. [:&z8ѰEHl!m5b  [fc\fQ8f킹м^h TqϫP,Ƕ ^Ny7D=[G*8V~Gdf}vAtQ{np\jȡ2pU90~VA{!˻s(RΩE1<tѼCMH!|"| )]!X`q-C:JŊؒ,^ÖNd-&jKy9 '44&²6UAtYsF!:ҏn*-x8 6J{m3v\s0)z&uAUX2봤kRd ٥ȖmʟR CҞp}h`: sU\E60r]V:g>ˬS qDfӏ(.7DzV֋y6#tƒAƺh: 1U=/L;'#F7؜JՖN~SdXa: q@gˬqIя"匸s\> aUlJˮ٪ [B;Eahet3 a0z3o*>I'c¶ Șv:-lar2 42+jf` 7JŽqyTh@#.6~1㍨mI?T*1kH-]_B%mhfvB<*0x .V)h6*,j¶kRjY (QX5E*, zVq)$hꝬbc*yBsiRt? CH`v*s3b:krS*e`_[orL!I2 bB; $){R5!E- ]ؖ%TlI8#_*5mAh HK'ei rBX$>Z .ve#%-ٌVy+A[/tOF)RgtGf9#ŅB58ٕVF^sbb !SBْ*5#.t]aX9!XN,Aa<ȭ[,SMՖ"^=Awy#`gUbU$! ^_uh{-D|lmbtCPld]K@GwB=XҎqyLbCVotsk.d˾mےXzn# ^h OK#LJ ƬL,bS^Z-Cnm?DSX})b3Zh ,1)#).,\XƐ}D \]?:&NDlItaG-P[t!> " gdڳ2*a-&ŭ郂~!io6m>{%a-YpV .oZ"Cyc\F=h*˿q_Vۡ '}Jݖzv;i"K-ZcLF=hL!qD6C@4un BzN]ҧTlI~?+-YdTy!DVmeV]Y AQkG\71Oӎ%)ت[a[l<#'tu@W$qa8!j =j9UikoUFl!Ö9 Ky A]}G6DYX@'hT0 ҲuI{(RGly-ٵ튕=z"!E~w#R#ª*/n;,|K[='$(Or u[P1rP[  >TV}ytd$l O}VFa[걚?>E͖pFA+‚Zh4"n D$RZZ6!j\q{LdKnUJɖl9 0M(S/#aVEU ],4zyɭJb !>kawqu}06V2@oJaUDX!y"4DJ+YКUIі$r8>E]Lly-߮ȮPf,ȗ߰>qu3"hpHE-F)˶[4Һ-lD?`--'XUj`.!lFaW!¯<6NbBCPDr>XMNCAH9T}g6u[N60M Dh3&7dTcpkzGl i\Q{Znc2*؛t$D=*P ѡ_q+-aa6vu)⢣mi'l ۂ*"$.*3@qZNt;= QLA؊wAe Jp:z[ݗ8x- 68(}JLgkF7b5->yqlmw̄0 ELk$M_v\JPjV G61 FdQeޗf8y K4NF[aNŠ{#D7ߧniơc)9a>]7YƧ~**$<]g;WǏL0y~CŖvΣђNaZ>]='''!֎m! 2 2 2 2 2 2 2 Wyn endstream endobj 135 0 obj <> stream xmk`9Ӵ>5RuɬtuVpTPֲU68{qr;sq){q7o@QߧA=:\:)% ]Q4:)%KjX"뤔mJNJG¬R ;(UNJR芪YuRJ0o펾~,v1jfR3*ډrǻ:)K1^ˍWigR~dʫNI)uXr<x,c9Xr<x,c9Xr<x,c9Xr<x,c9Xr<x,c9Xr<x,c9Xr7hdz嗬^Wxp;Ũys\jfTts]t6/d5~]bnPmLL޴kQdy|d5 vZbr;^_Vv\|urkخ_TZ컛?KrհE (*JLnZN.'++!DαL]Sa06G6UUۺx )&?@[X endstream endobj 136 0 obj <> stream x1 Om ? endstream endobj 137 0 obj <> stream xiw:iȠ 8WGԊu'jޮn'+|OvvE ŝɃQ`>= Q_8tC/"@>=TpD4AlWU!(!~￈ +O3 Ec"KUTdϳY BX2粉xτ" L?Dor*UtV'#A JDXj1dZwGEd2!9[jtn[/>&"!Ի{ȕx21u5)q`N? 5ӱoUVJyX]JGxJ.Ԛϓi.&/O@ܥ91< v )EH !)! !%W"ꃐR^}R>1S[#/x7׼9!Eo7fx}7;|/mEUڊ⨗;zACKE@KzW@!a(ب][M׆WBN]]k;j@XŨ(f**`9]ckU|ןNteŴb**_")Uko鉦x4W;D 5ŏU8u]MqщnD'>;щW?QQ0ϠjC9jðss8#EGǨ߸w|WX{ e1s)V:^:Z] ^:?R:9FeHz^1EE0+$11 e3t,zӱ?yQoc^mAgׅCP:`ނ/(ٓ @ endstream endobj 138 0 obj <> stream x nH@ endstream endobj 139 0 obj <> stream xYrX ,b;.U\bwc{D|ĢIOzғ'?h+ޥ/|!}ū+ĿZ}Yd\7͚R~ >W@^whv;my7ۭmATW7V?re[#LH醡v/0)'|`!«5wp { vl۶LCWC呕 Ӝ #][>q5!<\RLCܽc &[ %!L7ʪBI ha>jC 4~K/c7K_#9AZw}WS]Sޏ4;mU3pnX{/yTdyՓ|/̗HdWTP qC4/4RUyX7m ʷcqrINPL&b>\u ʼnAIB" }MX^uMXq#p,&$GE;穅˦$iq{{y)Ά˺h' !C;oM?]]daNcux:MR-ձ}KnF: 1wAUMt8] o s ŢD }?LDZ.l6|lW4e#Fx].UE# ji(n=CF2B884=nk>!4+C0emSecl @br@oFsy}}=- #Y7 ,$3ef`şNI:SxUYF̄/rjS~)H[czH%)EXHaa@gHH3 8*Na цv!DFAL U]+iB^7 z U3Br?Sue IQJQ>$'dR"*HL񀦧yY%ntnp$ x $t@?BixdՅ?Xv0H%iN*> %5":0*V遹Qi?(lGC Φo Ka) 0p.gT9HR9>}l I)KoI!հw@cILzH>t$캼0R)(R %K/v;6ZlFZ+UjIE# ѭi[xʤ]9>̰($diTPBRx/m_ i!D?"L"ro3w ^[c j-l/=mL;v4Ww$wK{<'=IOzғ I+ endstream endobj 140 0 obj <> stream x1 Om ?Q endstream endobj 141 0 obj <> stream x  Om endstream endobj 142 0 obj <> stream x  Om7  endstream endobj 143 0 obj <> stream xv8Ix Ƭ6f1}'a KyF%; NOϜnԭ]ԇJ9磢twSѢ{W$F%,, a/  ǢǜLxch5awwE|/|G '%Yˠ4( ȇDY&pIx!5ib6D?F0Hq-LټiRqYw~cɬOkhQQ3lHV|Ѯ9VE.@)R6$TKf&|[T $2V z-HFOP"RNgK ɘ2hR7-AJ߻{5֛A6SA#Zv5T20K".6bҭ*w(wUZxܯ:J&h;CfJlpR:j*caH3o VT7Ґ|zz"H9P^v&+b=i3TlR&.DpׄYz^@bSajOzگrȻuFRӅjgv֭dѽ#6f|wz>=Bu7UNnPRS/i5_M m)#G^2 Œy=Yf.h(GbRVZyIڛA~=; %M߂.w!yO)māߝA.Ms@'q5tqNQH*`kU*<^{!jtLOA Z.w }f!)X1wPfW2jw?+),Ŗ0ጀt7muA&IHE=rAHgwh&ƽ#51 Mp"mYIJJ(Rқ%QRJz>JJIo^GI)͋()%yQR%7/J꣤EI}޼(Rқ%Ť՟4M ̝$'o+ɳ Tl=|4gE5_zi~K|z(zdF,F tDzX"":0 'se:]{NA(t;0L;`DcpѾ]9^-/"G8srvׅY`zu32><[5.hrs .v)/fBjﰭmҩ)U&^8 B6sakPؚ_M5+CӍJk8߂Yq7٨\Ws͸z9VDndjܴ]^ <6\&91:[nyiťqJ{Pn9Dt f֯I ¦ Ͱy|8'x@ USt/6hboW~Q%][nحtZGR:"ۼPNlu>njQ F!*y{ L2߿Y$2fh6-A~ DKU%"gXA#JD{3AƺaAA^zp#X&|m t"|iBOˊ82 endstream endobj 144 0 obj <> stream x nH@ endstream endobj 145 0 obj <> stream xYrI:,n iN{U [ֈ 40OyS= huwoY9C7ih`bb^E%qZ+Nfq%Qx k̺Z?~"z8_CLOƀ3ED0|1)*аGbrV=aZuãEZΔ%uaL7zN]yi.EpPː$(,<][#a誂4Kx 8o\c5?wWrr%%M1~@y)LҢ~Q{@Si^u|&< q.Tcsp3ums̚v]ƶ+ɫIdE4 ȆuE; T"(J QU-Uݞ4P>ntQϏnkqfPt HS_e1L~Z(ZjiI>ȕImw6ZCUU|lt-sMꭂhI+2ve'ymm8z~"1UC t'ݮkCDMK̏o,t͵ 19DS[y" V}5 _`I3l=/e] NYnbSĞF$3D 8*5؈?}6i<9vy ڝ&y0M T)tR Y ߇]J!5 D=@fHYWgH85w3$xjo-~X|I1Y qdhTa= t*h"YuMS骥d%[2`Ѝyu5 U38-cI'fUũY˓4@}I/@5Rwj^.F~2MLgl'\_[Ǧͼ;.B)}oW<)OyS|, endstream endobj 146 0 obj <> stream x nH@P endstream endobj 147 0 obj <> stream x  Om7 endstream endobj 148 0 obj <> stream x  Om7 AV endstream endobj 149 0 obj <> stream xYS72! h20ɤqW{O݇]T{+٫Vj_       ١s8-`J@R"A7*@$ ͔AZ davjR &뾾v;mfp':Vo:H$sLzFl*sZ)5:)Vl Zi\)+L[NɚP4[` ޖ~Ũ5qs q6r>Q:tSI0Bo0Έ8ݍ& }f83umY>Y+hco2=h"H$3fO{R6'<UQALYn?7$uD8}֪-aκ8G2ն$uj(8k?R>IjcXmQ y26E='j#e?YD]M86QF^%:8d,T~" %-H :S?ݿfB7U\iA--h@ Z-h@ Z-h@ Z-h@ Z-h@ Z-h@ Z-h@ Z-h@ Z-h/I8 [|ԅY8\:ڟ( p˖`(w-.•VoobEY Ͱs:l4uዲ3v^)(,h&I3X9&Q%Y8Rr\ă^c1cYB7' hܼmV XO$7ZX_*NOExj61,HR mfAfU> stream xXTgրwlbbIP: C."3{슂(DM1e7&n[l?"1 %<;{;w:蠃:c'y2ʌxٗ}I+*.ʷǡ ܹӾùn_%[l3cmϼ8E+):'nh̔]|/ UYK? ]XFݩIҒvD~tI4)?>< 8qL}e,yMnMCc+pXj[܈FXs`Wzv;}#㚒ʫ5Kni,{^np&?6]'YԼeMY$&KCpwKE9 9ncv< |oey=ogx<)h{w4ǝ /+4+CFc+hOiһ5q{4negU Z- [& E 6 nYZK܏:T]T]× 뚅7 G>ubCp]{y]A*.k/jJi dtkw7os뿜U-5ʨWȲU,`֥)<)=);)%gMM0~gS'7@}}=ٱ(k:4![ŬEwlJSb0FM˲1.MqM {CK1MQ$&ަ{a~ǓeH9>>ܧ2" u@Wߩ 7^tGUzUw=o42*>O7~i>Ӟ瞴_[CL&z&Cea1c͏w=o #a&y_ajmlggo[xU8:FJa_q}o|߰?rn!;h6|/}sr[C$(BnoW>qyGY|Qo kzQqXUvy7 j>m#;h`w> _4{{KX= *ޟa}$u/̫ ^M‡"Ϻ/=k?u*$:Əmyax5x롔_pu~w^oHb0SU[p]O'#a_;'zo~0,O07g7gE]r.c8S-0ڃZ7bWH'/<|  ;/ibUsDZ}PÀGo_pg/p,Mؚ?x1M1 @`cwmK/I vOQ_!m圴-Ϩ;/T}0.Ke'%x^Q~&tc0/.A &K`ܺ=WeA I{JbӇQ*#TqF<}s} ^L v3 t QcmV];&3"Pq]H&Tђnnוaeė y%YfB(J^{t^k>JYlHsSջ99/yɇLrmo]}H7m/ʲ vV?H5>NW{RUrũ}eoV`3F-8NJ2(q^X3Xq-휥9CVCM۲kܓ-Sx5yQDgl!@*SCD,N>zVP/zC 2`!^L'NQLiQe " V{! H.N5w`f%d1uǩ oە_)($vXNnT1NH6ŗ+o6 (Ĥ<0YT*n:T+ə S5wPtđj[p*$;-Jύn1*3C6ln6QAy)(ێ :K@ nħ7ZUwPRub[.x,ם&J坶)f[f@5wHiGtz. "Py R^U]^V)|O^L(,䊪]LɱZ+E`.6W2eey,.nlUp V]΋.J= 9,*/$_4_u7;J/(<'=9T|Rq!RT]R]]pܞ==ϑ2ʐ Ш6g(VVpTYȋ.N:dUU79 CO ~0e,*o9@x,J]PHs;+~լ!K/e _U Huݞ)2懂2lQ0ݪ6Eg'%POQi"~l T'E ek1b{{Igt`>xf[JS$:~ghRMxHEߌT=1HE<\*(ԩTRrNP(Cb!RЧ,:*d1w6 RuxE`Nv| f~5򫶥l)OrKJ[Ïi缡,<*d[zvxU/Q2 }ہ)kveWmK.S䝖etjbNR "ݤl弡(=wUA~U})`L.1 7yǥ%i MV˩TAp6T*HT*}e4DlĵIW6-`Wr.; PtVUx&2<4$0aWTN: TRT7 IsN*޴)8*M_8Em`KIdY$ĩ-tj=?n<4똜t`sQUy4E%,uH_2*ePP(Je^g*TҬS9\oC~ydxj :odYCb^%ɋmde?mp)NnYX+J'hӻD)q֡K'TA0^A w=)$Gd{Uu֦,}'r_>Trrq8 :wpHJztiTu!UT{%ݲcl N>EɅu_9Xu4D=RR(gĥʋ.J+薑Vt`E*rNiZҐu&uQIaöQ 9C3pr1L)PKi~l++^G̽JA*nL0y84(~gI%BC%EɅr_Vll<"92HF^еܘmCҬ#c-\o"6E ̈́7yX˲H2DiXB/Um¤CRlUS4n49CD+y:p} OwR<(RsU8 ¥Ab^Q 0*]-I?(J+L䑯%5_3R5S~,zšJ7< T*F+{RHEsp/ n$U0SvPqXyDAHIE`ޘF)rayX_G>Tu ?@^pfGY*HT*fD'2s/%$'r Cz@BZUrҪBE#pfs((2_ v> [Y'[ [Qc RMyP(g4 ZÉ,߅>uI3XV@rO(7(F8,MB:;fVPwRTT*ʰC ;#/U.+h5;?K"*n=DNP E1}D-8$M?(N+LķsMd̽N nQ*\Vjv8*y$4<"8s\YGa2X'&vڹQMRkR&C9DS ,4JyX%M; N#L%kFm̽+R(g2uͱ ȏo&cKÜ{L^i+-!eb{I#HŏkD TmxAM~IAVqXUhբ T&Vo q'?n'jU*3KS.9VRa1vP\Qmr`qvߢ[_e6b JE#/U6<¤1i`[WG G)>,32J%u ێT3.}PƂj:KbaR(e`[øn1?b'7e헤%uu%ےHŋm$v2])>F7 YڨE H3OuIұJ6^v +M$Ue v8~ ?#u[UWI:ܣE&>0*]xJԫ܀9lR%QI[R=jT=RwA.N+M? "^20E_8 %:NNaN~|+^hԫl.oN FnL ?aLWA &C-E I0v@Ft'ŵr-xMVJ[5pcvѫ.)Am*]R&Qi){ x_X2]rɢR=b+dRR!_EzRQR[*9X!k9f^\ ?ucqVShT^EINE5'*dcZJzxTuZnT*ʀP%,U0Ha>1+Cjuqب$u?_J/prSD2Qbi'r ptʇJhA 3 U",٨-6ulUcj/j$mOUr(q΍nDn!c"ЛΙR^L ]KLcݠ8{%{`J,nDlfe6RmR?!UͼA\dXqR'G"M8{$ɻaEI6~L Wĉ؄HGP7Wc"lUC-G E_9%UR0 t<Q7#6YaB&*UUjv&|KUAB;,NMB$=t8Ô0 t^Gނ'c1v+qRQ(Iz͍VU[U= b.nA^6NvFz] _KHU r[تjaxHR(zN.ء‚ʋʉյjc*eP% :HU6z+X5qFbXqg*fy6~2 O( CNiFL ZMAfhWj\(z\FY0YlR`:UFcK3L\f4(1] ^cIJL z5ևP QPJ52e sߥ^ `_vyLu_aRϘ W2k*+"6Ă= )?3 iuC[Gv,WX.3WIuĩߏDŽ3(2tH6v7^Ȃ=x ;t-vjSbW[LQ+~$ `(W,~7Ǩл9DR̘>]6yN(Wf8:Y@ cc\ͫyZ)!g L> ?Rq g;Ҍڌe9QP2J`gYH~=dxIbf4(fdac$%TNOB{i ϙNBIv[0*tӏZӓ,RhNv yn3&<-xe:hx 焭冭㐐-+Rh1zu?Ę WS3b\BB ỤG_ެ+}4>q4+aO|}ǫlc79̳巄VRq{ԺkW/[%6߇}_n.m@g5ĨzcwwK.\ϧ& = z{]sW k~57x/t ?^ _KBHq"K0w=g#a:" PY \_j|nlCi|IS-G(fLf̜BJ7(b_ Y%##xF]1E/iU!9A+X~-FOMzLn5:F0qdS*xVKO/p0l0NVN lFA ^C3Gr|:$l-/BWskA+9KWA|0*f8>i:kԌ\ws(#D3Lw ׿ZBY'Z+Z'Q u#܊1r;F#cEx^9^ZAJ^rnּrs\YI6SE~SxύVs&.93l3Mg'[p#jQ2Zyt,Q(nF` R}D20n q Fb?_KCc}CcU?X̊$1 xpG؅BvjQgZA(%LkjCe(dpg>]=/-02z_3!#qkn}*|V};` ~O|{'b<+>n_d|ictAtAtAtAtAtAtAtA0&v endstream endobj 151 0 obj <> stream xouسرI'$vq8q,rAB B' !q$e+*GP)U=RW$ v" }[{O=Eǿ( ȓʐ3wo>fg1v!u`pmDŽXDvC7cgi[.؉Zn[E\Mϥ6y )Of%9v]OţGP-ޅN].[UơӵnԣyK[`nVdt,\݊߂GXzKpu]E):~6^Yt(|,`Et(jv~ J?obG3t(*V>t("=eq#N#!QO 3/sБ0e糃ܧ CG2ŒW~T?7@⛁d^? DjXNFN(BG2V#}3ਆ?5@ϯg}E:~IydY^'͢썞9A* {NC1s]lz:gJBkǮ`,`2;t.}v4+wסB&Nu NކN;ᘯ~SsƄ4͈a|8~!w{7*#UrWijӵ95tUg01:^Uq놁Go8519t#Nn"H9xJfr_B'leR^\7B*tƓ4;99 c 3KOGr)I\R٤%斐{|<'-R+۟ɕ*/ՠvuy06[YV/2͗*羂NۊU"$ujד鏜V_*t<7kbEDjn.҉GͭNQ@d`djfZ="ڵr1MC5|벢 w芯j]\, hЭcNxjd2_\oln=Mx677V+Dbj4HG5ʭ`S)ˋK`,.Jsg'C[ 1uP̉6 g#SgӅ t>?59Jz$-> stream x1 Om8O endstream endobj 153 0 obj <> stream xYsFm`723JR@*gdz~TK?ŅAn6ܪ7 B4:^ӨK?e@4:(QU Y0YNa*Bui/}.ňRFy"T7=GS&]6ʠ(. PN`pӅJR&>'m653Trew6[/1qA~s{ћx V6L%ГhH}\=Dqk e5D` j1QV%E/JX<*gi-ZmW r>wl<豣$ zܒx>LfBrb&wҧy@k΄B-K$SN:KfWnyj.t&yAkC PTk=_lqq|ܾ6SkŠ9:pcfqR:8h_-:\ϋ r1qpcf Mat'p?da>^ #qñ$DxkX|ӰD?^ZG"`4EҡL a<_^qRnb'$`qG -~<^Y]uD%d;}AZ<>=f1 4-X=Q+R-d3K"arJz==.aOLKm~$2~j"trP\SL,ಚ ߩ2QqWf3ea2_.Szd'Q7 O-mWcBN%߮ZG=xv?F;[kHw%ppFF\NkmKg:3a'iĮlXv:F%w?k9L=%IZ9lZVX:cRр~7rӠޟDgvCiiPivl-ɰχ3}4`]Ӟ4|RhԨ&ݥ4"; ?~n=GPh h h h h h h h h h h h h h h h h h h h h h h h h h h W;o5c,.h}F4PxVkz͟kȆ]#Y|i`4Ydkhd#+e߆?i 3 &ZPƓ~r1f-FI <4@ٜn2΀6 ɐq4, xr'D"d[яE'+T_d3 dKPy&#0RNЙxTKz/<׬JjiF)Twf;~d[w\kUXCv{.G$9iѠ52"tI"75rQJ x0X]OKt\Ӊ4Z&䤎N++Βr'Hr٬x>Q!;DvOL쒭"¡;Z<>8~:lAHaY{uU~ ޕVϏ|j`4ОX7/}VR0^p@C Ef1dta2_$H0pTkPoo_^3R}`,GIafK_fʉәۨQbh:>}jS"cȝv_Po*ۢsB.trD6r әdg7+>93;eP`}$/#e6dhX~Klkxě5> stream x1 Oi !N endstream endobj 155 0 obj <> stream x   endstream endobj 156 0 obj <> stream x nH@hz endstream endobj 157 0 obj <> stream xrZD}+DE㊊PPqI2;S5Sw:ܔ_5߾]jWծv/od#nnn. -)5fx{.1LfY&p<0,vqڈ3}1PƳ\1 7M鱙ϡ@0f' LtYMgd1Y]d,[ի4s qInoB(Vw0Ul 2qe1 G\7>OdVrG~^~M:s Xd<'n \ *IWpo^N ˭Z@n5:sT{q;v+~m"qŤ[|G|Q(h9}||7J5[!,#̟-N}LpmҭC-Xh}FZh:[7fMGbĄ#U~0L_f ϓQv x<ϦOfQm~ DZ~_+t2%QWN.7^wEy4 nwYJCbP!q\xQbY7jx1!%P.\/{\erM=xRl6ɱu^H|ͦә 8:)FT=$x$UBu MN0% \=.n%:̈́jsz3~:lx&†:WgF{#H~Bhܙ=?A{nOHtD|MH  =CD|. $rJ^Tlt}Q]CBv"|DT1=񠑡Ckh4 I:ijbs"`CrX?(,6I!%=NÆ=AGR4ld!B^0P "EcEE~6J[KchAfv6u\XJu^ [P`b.s{G*vr^Vǁ"K|V556JjNjw%e4z/9E> stream x TTWELf&YMٚ[QE q51%NьF,щK\Xex 4XшN_ԩ[>;ϭ[0n۠AZ[[E"ы~#?iwh8E_>'''O~'v8q G=vǩ|;|0#Gw޽{w޽>jvxΝ˓J#G|W;X;oxg GGo~m^!vSco֎;0HMM}iȠe*%ۺuϼR,XG\%<P}ɣ!۷ZBBo͙3g^`G _>_ccͿ3d={cA W^yeKڽ::zy4wߧw.61FmoAoQc#-Լ#ˮ0`#Ao 7ysopvS|}?7o4hvϟ%&&3=rji[|o[=n۶' _ߴiSbbKFfg3܁JL|R 13OHHLLL<71y)1)gOHHLΈOΈMɈF >1#!(>!=61qQӦOKLJΈJ5mFT,*&5* "cf>4&5,&uYʾ iwW#F0+'*ճ+CaK*~UΑrIdS#JQ%ƥ$$%$#r K09ՎaUb#UvU!$r $mIF\eVe\eK.ѵ iy7nD/ۯen1rm=IX0pGaKLꉟ%1ܘh$j">FIIJɉ#$R(siA/l&I)g/Hʞʎ 0 #M8'r]'|(;])X_KϜ_Xz6wt$5H@\?@܀2Z}ō5nD{,'k#[$=U>Ŏ·!.mhޞχoG3"w-ӕgXn󓒒 M#Fз/&1I|~s:Y{"? |#hnCd hIX_v-Ο/ۯeyzvu(~ y={D?HROKI;-)s?{{=6yM( PlA0L2k9͚5ӦMr ޱMm $~S0k[o j9K4mNb3$}&Ģh I>i7U03o-^{->>79< =߱+!0%4.0y&Rj=lG6icN%Ĵy)Sf!y,իW#~YYYY#qiT Q<=쟞 GL;D)5^Lɋt^Җ g4#=Wk;G=Ogzi[OٲeQQQzgZTVSՓ}hϜ9?>=_DO,i~~͍YcccQnBֵsH?7`#B?M5 =dLyC䃵mܿ-h^HA$o5Ǽ9eK.PmKgo GzmNVDmOs~D 4[Ѽ` 'rʄ4yrrrBBB.GX|'ɟRg%k6[`9^Mdބ~%pV?F4YDrf_t)_p!o|ޞ·<ұifi8J y>l* 9Q4'kmƨP[/A9õ[(~m刑#{g};H ǑG/9K?•Ƕb8h(X:E7s $UJUj넜Ky ,J/ۯe4|3xGǚ9_s`xȢ&Q'e\(U79U$Ji%&sR(SYeZڼ3rs4v?</ӛt_Px5nDrvJ,rInj"[I͢DM2eRb9BHWJ*VIz?;;{ԩ#`b$wQQ[G6 &IlDI˻ỈDIUHa[ʚ vYL cd"v Ke>"[m%yM2E?ҞC{Q- 38:u:5zu Q5D)-֩R$)eӛmX"S)ldmli؅͂E͞Z2r333ϟ.G}oO\'r23N\gLSs-s{(txp:}8TN&q"R4|zLs݊ERd,RYoQ[ofH~a`]液yj*\|#&c1Ϥ'N [Jsޘ:],ﱄ{GBo\8zFNǗםMtĪLh-gXe3I[mk".j,lQ  /QY*jVvWkcwvM1m?wSW|0wkDU=5z6s:9z?ݠ1~ OQrzJpNGLhN\evR ,r Emj˥-K_S=dשuǣ7w:Mt{;Nف~O`{5n0Qb-r]_d7 S 뇫 [ƶĴE)u"m_Ąr:!UuVndNt1-:M*D%IS1-EgV 3S;[d*u稘:ژyj[lPoy[jp[N,jw' owRw;Lu~¾5۴Nc0tW쬥2j'Oo?S'(ix%1imLZ+#S12%#kҙь̙٭L&neU̜f&G(%j&Yf#6o h'wbco&t#OFf :Gt,hGoa菺`zOv'<^OIIϟE$ Ojf7LW1[mDY-Ljf*y-̂V|Yfn-Fڍ v{~~ˡNǃ6t+-n]ѱvS`r g9u΁!&3᧥__.G"Oo՝ כ݂-p^2/r-ȹص&,*Njr[sl5*~W!NщN]I@z2c09 Ɵɧ``70"~Yx'N~M)e̜6f~k5yMͼ鸯{ť7=>^La +*KD)}DU g=:#r8U!*fs0..K0 L fb䟘_x̟3+I?YL[JF+;j&aKvB}(K})|TL|U)1.?m3 N 9lo`^k0+0 \W:݆KM}I2Ϋ`VUI&u23q[p"yT .C4~C8X WGpRN ?Y'>j$8YSZIh_QW;0&7j{yyV̖ۙN捎:eB8P¡B8A1QA rx3$N] p$@*?@2 7 85 qQ߃-0!&{1m~ߍuWT2ۻ̶NfgT[N1S a}<}E5\ `O)~Hwbc]Dˉp '":8XGh#7»PF[w`m"`t\!:{?66vܸqSg]% j}v>E.K\[ЗN쨆U(7UF* ` 쯅 9`'Fp,wS1]G-&&C۟644]5JJf@Otn [B^ oRV [K͇o+e9rR[aCle5lQ-lmvAV;{L}ͼ YC-::SϏ̟L8`KU1LTF S^/JX`:W:X_ ;i#[Ozx56%lSQܓ[8HRQsGSի}uNa]1l,DKaCXiúJ`C5+|9WS=k`%ZXzXSêZXW o"FN nr7z6pQITҬ%H>""=m?g1g#l%De!WkUVkZ+G*Yˑ:ȫ 鲦6|ͭ͐U$آ&4+'T*GXQywڗRXUUJX^y2L>\9$/QzXR`aaQ,I"QN,`k4Z$`_k"j _rMV4*4WYHUA{ў#rss~XX DXo͝;wժU9 JȮ9Dٕ0 TYrF_C!U\cf!̨ QK4,g7ej' FXTO>8 k'7B:[K>cǎбcj󇎎>]uO=2 0Yr<0S阬4Ƽ#dY d #>'H~ͩzXH:Ct Di@=[Lyҩ?SdAVAU#[ 0&$TOL>R/bT ar!xbXB} aE^Ra>?$@m7A,޴[VVVllZၷv+}~hX `|x>2L(`b) ƕGY.<x< )gw $jt|8={Qa1K0D9]K0sy0: #¨K?O4SOP&aԱ`T-4=L|۾SRd~`ǒ:Ҳ>v~mS8od ̲l'w}Q%_,%"K/sJ\(YyɲK.KEYr(BI.e EK>-Yz(E+=Cg);]L+>[L3ל)^{h 0]>M30`@z@^7_S/'ME97DcǎŁAkװRÏ~;̫>Oۓ-k'o3277q"<<_!#ޚm̘1蝜0YXA^=Ꮿ4X90D(6t4yjV}|ϋ8䋈q 6! 's+?"s>LᾙC'di9|Rޙ}Hr7M'~5CJ?& }E~[F*4 m?Xx;yI&ex#hƗӆyz Ld<3/{ H5L43qg0ឲaiC=x$L0LꑂWw+yH "C~EL'.j5zh3Ȩ33JzI2xOjpacc ]"8Gi"pw)MJ;G$FooO䜘6s[cC]cWA^5G\# D5gmJ_&IK`N-yq`C__̼Y!3A2u} ˎSryeeueeUee { _vcC;rب9b˰\VkD ͵.K r]2_!L.6Dsx_xMMMK:4=Ş>m#?{aQM-e$e{Zy E^Vq5y5YyZ{r fw_luD(cgXb?^#/2L4e[G;WZy<wOހ踄S歞:uq!b)7\1E?OggǢoI+$ucLJ!WoD^aG(lϿ؍Ä?{v._vȃ^J YTCX''O _@8u#ԠiDA?knҖ4Fے_lI,[^4Ö؉Ml( SNhBR`NRMYBӼH7ZZʽ=%SW,]=ʑ+GZxjTk;!Idޟ,yO2v%z9_Oɼ=Ivz\% _>AE&# ɇ{ G<у6[UDѷY [_/Q)-;X8ƓN bG8|k9xKYP.3Aش :+H`3k4(Rǟ|L&cAO!v,G%%?ұ' O3bGl@bC+CoOU!iS3 1ؤcO}I3'ruSqF \Λ 0l//rGЕDih߼cOi;WO`Μw఻<,7Q,^iπ Hؚصm״|ekfx/9]%1Vq.'zX:w>dBmw'n|Co=%9F):AjjjÁ*6EE_g|1oq,Po_43.+c>B؀س'ZGpǶ87n=׷c|,lL *0Hwl]ů^C6ٗ=ko`Sh8Me#ԟW|v1Pw~W~P+9".rE3%z- -QelG0{57?ٹ'6xGl4| $ȜHűw=igZp {ȭ[&g  & r O(]Z],`9,?,`Ytbrh XƟ|C8y] sX %+`|K Oef?!O a"ڋArt BrfPʽ7ٍh L WmaA`/7_U>S8v0ݮX-;zHs|ɧݩ#{?˧,Y;\,N$q"lH~% `d3gnM\Vϭ7e&P0`[gέ|yW7r{{ӧ]C7ݺy_=[OϿUUU#Vk,]Qғ?vZCzֿ|cnٱsݭ\Y=q}JX|Om>8s_? Js@Pn=`pjknX?4?|vܿ8o4]N\Qkxĉ?H,pI؈xq;X}m;[Zd#b'bl0 kl^Dj 'up.$+&ǗfzU*Lūr}ÀRU捎Pp+J-6?,.Yuvux2j_#PEvrC G&#DqТxqx82r,1rи3i w"$h{$cw" RxѠ=1g{ m_ b${>Hl^ u8$r."`n }Qs_EX~mfU5ez-a ` 8 X ` > -؀TS+L Œ`J|w}o+og3z }DG=DgWwٽa)+"-m&"4dܒZG ( Pw'dDVՠm@BDA%5-z Wd+lO[wZ7xYmݻZb  8|W^uUl{uFsOYhFoRMWf +׭_ȣh5VUZ TɎ=zqDV#,^!B^/=& jh?"-l&1.Yufnڵ+Ց[z{{tuwhkoijj7lm--EM{q+<]jlذ?\} 㣰 X/݋U?޲ѣ0н{Z_{5u&VP{_aV[AVO(/8H{/`mmZ L&Ym:tj5[#VZ1]`[8LN\[NoޤG&T**; 'A)#RpyhJc.纺9> stream x0 NO  Z"Ϲv_P )|>|>OC~~>!?~~ȏ|>|>|t?'ð@ Uc#f@ endstream endobj 160 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222g" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( qr4ҝjrkM[ty$Dʮj[kvW?v]+vZZշUզ+!Sn4qX`g{w]z [˾VVq\lfO97|70E.ki(H-EOԵռ-:j ryY}HU6{6ѷt;vk3C' $ ߎyIJ]lke# FҠx\$Owsz{Klߒ-z}V?(|zzz4 YXBnjtu*L,v>d_μXҼOX/X?1pG>r:Wao Oj33A"0OzֶM-dmj+j&Ims|Gݎ cj0l]}mw*ǨG5iogy[VV-ttEU]͹USý[SIFfy_<$P4-Ke?$KԟB_L|eߞ׵vx> ^SB2 S*9}~\q4(t&߳/̫)PAivV(Siquy- JKZnq\G bcN=jSjZ#ؒpn<9^*'''N YكKYwI~7_ڴTb(N՝}O/N*M\Au?{d}?U?|]g~t~/^Z.J\NkmdSI^} 24c?)ߩlbn|^/3-=_xBk? ]6M%O(ߵr?E帑b۷+ug+>}-|fIa?ưww,;`v3sQ4?(t?:cH+.2NO=qV<=}7A}4G&̃-۝Gw(;Pp~MSDKdQn' N$qE HOx{1oѠG[^ko|,,s+ cA/a^#c|@=X] B98R+|e&eiM6FX c<$~9k6}: G;O qԚ֕{Y M+CUP)3*G+`I<ؓZڦ*X﨨Ҕo7jP+&>Uڸ-Ԗ8qu$tUhn/6ܿ _̃,-r˹Uc̾[WAo5~Өm_:m o\n939&'JWvڼ o=Nvv&5ipOg$ :ȹ ~-9\o|CնF5}o$ S{Ғx>/w3,PՑcއq*м] GAWympa?yOa][-@nU<2Һ\}ocfZٲ²+('҇-C /ϪjUy՛~vEcAPxv[ɧm,feCp 1֍gPK e2ħ#pp z^]-lQKP\H.Sn%Fʴr쀎s?m[/ qǂw)pw 꼰\BϺF&;ku2pv͹prxÚ:^:ͲUfuYxk+)z75ba"l1 S 3Q\˯^'k~v`#oӵ;Ԯi3/#ֺ=HHQ]Ґ:>FH)QEs^%Ul]Zy"~_lbf0ϙ~qa/VE`Թk3 in$g}sܳ)Ǡ5E\Imh$d>KW)WvsTb:vœc^{WsԋV0NZM=]GhS6݌ GXh,tmF5 m"e/ĻR{8E7׾|rI xN+&O=ΧE-ݒWt=Z7SX<on3̫`p0FI#MS}3'˷Uo|O_ƪ@%I[=;G_۾uvϥhV)]FKm䌻WТRooFyczuIb+!o˲/|q31ڹK(eu.e4ϛZWr< .{-ߒЪ]JGr+qҺ=K}ot3[G 8#a鏯jXّ7pFҊGr$u[?4X( .:uӥKs%41)vW@2{~t Fߵސft&),)SԔQEQE1}P+J [ֱ%[7y ?ziOcN9}#RҾXRVNZ92MAxm %-Ymheo; J_KBk[+ J~^\Zדnې%<+ҭnovmƍH;rczi4??f>+.@žo^Kak$1>˅'ݠl>^٧;_AJ4MgJwWnemN6mrf^30a9𖋱6y'\H~8`~&+6oOV^}k K:V) ]5敛s3kHc_Ӭ5*M(@QEQEQEQEпJ( )-boow }ڸ*QE!""Z(b(((( endstream endobj 161 0 obj <> stream x1 Om ? endstream endobj 162 0 obj <> stream xàS_UT endstream endobj 163 0 obj <> stream x1 Om V" endstream endobj 164 0 obj <> stream x1 Om  endstream endobj 165 0 obj <> stream xXgnnl&RPE>a`7"Dnkz6fwSlrwdory(;F>g}9 _ 1؎%OH#~jMxe;+44yU5\ ڒu~6Ay(#KOsJt,_0>Hu\j3լ?nS?\ukֽ_{=۾|a';>f_bYE[+ #ܫ[w¯L>EaQ,vl8@9ō3̛z*"a1l+?(}Wsj4ZE%5/zagM>nK:\Jc[n`[o> |̲nF﫦-RcO7.u۔(ͽ%#H"R8a^O}ھDZ萪Ū**ߙjw_ǖobe+X,{u-d_'La9.F+- *?m{AQ$}9\Ŋ`E+L> St+_rb'QLޏy7;#7DiYa{_.F^Zlj'N?c]ΏۿCX|y 8Tׇ8<8{օtS`}XX8vۻ 1sSϿ 21k C-l,k> bcØrg~P!gS)/X:jҥ/v^gEu5 ^t8~QʤeuwŽ Ϧ3Юd]XȁG^ ǜ߇uB}oWpc՟@& ԓAe}EKHN\Š$E 6U٩3׺nʯkt| x7LP;8>_yҽ59TFXeYxKqVfFg_3Q3 wm>GOwk_A,H.D_zV&4+un3hTgnX&i9a;9j,;1ϿiYwmRAZ9Vz`>\)4LJϧw@8UX?hc6[[_EMҬ vTůvk 2NKs߰(|}}6~o[qvl{~ Cݍ󠀠|h[Ͷ [߳.}۪uk9g(]CX&TfX'/vH2)ɺd{ͼeV%ovV%o=Ǽ'VjHR-KEstӢ qYu$80/0+S^sKabLS2Y2ݷLeʽtd%ߖi ^ Jp I2C(+E0~ 7+fMl&[N3|i[ KtL~Vy4y58a&aRyT2y8eRxeZP',Otd,*_Xz{ dxMs.d$NpLYٻRKp q8\2xAI'WV23C۹r\3&Yr4}L k7xٗL2INOpcmdOmdZFq+I>aQ&, [N.٨r.f_'I;Yӏ˴cR J\A$S&كE8ߛ@*FIܸ0q D쥥L̐nt/> (Z̐bj \D7~Z:)J:*LJF25ViD E'%&w(!pQ}N?'MG cyTL͜~¨(ufyP ~J*^i6x0yĩ'F9a\& er-b7s0=A暡l>Cܠrw xMI3? {{Xp^&ͯL.E=.~0sf!`n@#Wsg`R'`a&vBT;e2X&c"zP; M:&N\Tl6s1?S\ •y^kn\rܸ ~7Ď6('dzer.IxģSx;l 4h$3S#?0;mv2yAa1ޞ`9hOPiͲ&`ΣpIOK>&#L,*h,$aAQqqI3R4l+IJ%$yP FV&$LI3BE>@ռq0<;տuv22u„^Qh*PxWBMJR?&)uF[ȹ߀ՋǏMX6 }1./̍釆B%nyI_!%a{aB~?} 4$ IqDܘCPpJ_ee:ďѓ`'L 3&PܥCw#AnL4o2mΧ1e{C|w=Ҹ$PTPR'!nJWXaV2~ YGS@wSC#>!.܉R@rB"4t)Yō coC00iʬ$a"(w܉R|Wϑ2:pW͵ɷƉ>ȋ4.N> {-o`^@#I1h$JnL8=LdNC碕Zȴ)IKjdVl) 0~LtD)a8AU*A@#Q"S Du3CBn.\M۠L>\2AxYdڧAaGpa8}%NDcJ hӗ#! WQ.ȴZgqi{^@9*J'E@#P H8qü~#WSj62%ϒ'QjO#Q@&ĉ7a¨0~;Î}UiQs6&Shq8,H</8JJqP9W 8= \&G-eJxUvCzzAAܐ(~Z:iB8BJ1P9W Ev1* `chM hdEGð(ĸ( 8hupN?,P\9NL趚dDD ω!qX'hKҊ@+rgLP1qEt:Md U4mdJIVDwb!maoJAR1N07(DxTā;čF6iCj dڡzˍC\)hR*f+~&Ppl+R]!Gc~dm1.3իjO8KYs0 n١Ac7})7{lߔqeJ0N @CzurEa\Dw#@bRjܷmJ&BE2Q&rJh+4>h|ԞҢ&a`FXq^ 6#m}! bLz6J[(NiegG.B+D gT#ܩ4/cӃG^eh)6B&m2mP\P|j-̰}.{8}Fju7k+ !ɴ䢭LIΥ;S?EE1* ( nܨ^nȒeP|v\JA$ IIr.xWL`~Nd/gOH)@A0(\7ЈKt7i#=Cbw-!e^A0* ypq7d#&TlL]hMLX=t* <ԁ߹@n㍉ 6/] ֱR8\JZeTH+y?8NЂg/`c# Sj)>;=+nL}$d3/j,ӋxMY$&ԃnfRm,Y+;&ln{A!T]jWt}u땯JCZ2-}5}Dhp9(o Ϳ@ba4BZX-kF,`fC lA)UdFn umS֚Gdh_|Bc`*Ykg I ۀ淋JՃRtt$?_2OZ h#rK]ZؗYF0N*Fg}}&ɹUA0ꘁ fP##@فL]SM<"{n1ؔ;ےeW<ղ^M*ص]A eճƙy/G VP3PVQwP<ˍݶ:$,b ZjO.}!sy:XC,[)÷XBTp!2lh9Au,_5çUNqBr0 %D&ϭڧ5 ׳VӨnE*^.Ah A njYuj_%û^j䔣o|ﳊiӚ{T[p}kMezV1F)4\G JZ+Id?Se?fokx,T]w&!k=j$LP=0#8c*-U*n60P}Mq9ep<sySU5jFhj > stream xKoQ ZBZJĝʭ.+uոp14ݸ2^W" RIg'|d__?D51`~ޮfnvw^kr5Nܷr8ر֢iȞ,MK$~ 4,=7:v[a*&y`#y`gɎpsy#4с!h 3dSe4ES^fa.[DW"; zElcXѳ9854899x0#(NR 0S 4`hSDAAAAAAAAAAAAA_1#,˷01~ ?0`aꝘpI%ҁaE:q f#՟af!ٹM_=;Իq^C-rhF >\Ֆr&Vv'[`4=eN%?=46֠ -T[GٿXL~`vb$kDb'(+dl#rnsj%Ki9(:$YvY] C3zOXp4&M_<"% endstream endobj 167 0 obj <> stream x  Omo endstream endobj 168 0 obj <> stream xWw\Ǐa,(T-4,"51_c3gs1kM,wWw?ebbbbbbbbbbbbbbbbbbbbbb#X4~).Pq !Vf] Pb;Z,́=7Z <8Z~PpA2r`nոZ]A1d<\vaMrgGPNJ| zÚt?*G6y3Yy˵{VaݘRx\#)~Ӑ&ROUZd1WŧrčP4/r~V{\>Fxx, ;<~* (ϯf1jW;]X)>Ipح: Ț\;~R3cl1,7f8ofS)<Ay"z*҅P# Uׯ}ZbJ1HfX;,vY-瓡u,dSjs0R3 f^-:?&i9ZGE.SUQFA1 z a$Ł(+l2G@&Ú'E%v+*: cqS[=YQnl#z:͖+RNW{2R{z2c/K2h@=VKpFlѓnab( qJ8sy@ tTJ A?uP*( aE6=É ,+8p(y]no Vh b )9֝.%K<\Hl6vS/?)~-_D4v?\jΪ A(cJRt!O0Coݯ": X LŘCl;!E-(&g|:¯b_^n[.0bsB2RCrF/,N_)l)NMvo F%Cpl*ZLImD·zh4z9Ń8Wʼnq)"l)zgK\/'Ӊ"v`\/fZ/Q8S VǧGKa"xeN4Δ]W낤_֛|, b.`+Od؇`JL*ZeϓaݨUEe W-|?T!ƀxA,7߽r_h7xj p:;m)0[ӗǏ=8x(~E(R"qwsRFvOƣ,Ց2V'W/2gTu)(ERr}!!@5YX^|wfoHPkK+r<V"^W ];z5ϐg,T#hJAdWwP@b鶛 jR2sƫ9p9.j>M[fR?  ""02r^-g E2xEZpz ʇjCƳb1 \)Pa">G=.癷s 1Xu%DJh؏y7;Ӫ dTkvȧ ̍87tܖԱN\;zǞw2]n7r{/T>0uD$ 臍vӴL$gTor27 B. */r^q41v'eWc,וJ~kkdѻ}&&&&&&&&&&& U endstream endobj 169 0 obj <> stream x  Om/? endstream endobj 170 0 obj <> stream x[RJu a9Hd˜ ߸ ySsz=xVgg)M Q.. t\NN/nuv~qCd$K' #4} y]W18K;2m1G1[vs|pؿluŃ(=ǹ1eX==TsHça؟"&i}ZѠUFh4#.QL- p[t2R\(D> 催 1a:oEQv2ar@%Iր"OIl813}GNW>{])vxE;\o6xop<5|B7@RBRf $U?iD`N1 )T[}Etj,d;PDF2N$ѓ~aA IFbTȉki:!PFmx}P, JP;:y=n ][hM9. ܽ "_p9)2 97L&3XZi9rdMfDĨlEzq\.8=af'390 D``kQP_^X}1c< հ W0;8'3QV CG^n8=bhp_b$P(?NLiVs KK@Q12#N f7lkb=KNk,~:b|X7{H i*tZKN/]SVX:q'}\px| '&Q|+k/;.!آ`"T ŘRE'3ldIAqficVIRt,L>f t-RH&uJ~FF&WsPk1T\5*g@eIb6WLQ3+@SӣɃ$5A|>ӡ J3ZԏWֺHLgq>Nܭe0B)PgtX7f\̧CGC)o͐uX=m_vj1UCnBFyz87 ]BlM:[ ¾lCn22]SrWjJ\^VSYBy` ).nok4^woP>xs>Xn ӕߠ_Tmb69C?/>g!, bMSF?L}kGfm+Jec֝Vv1Hlf=B o\QUH@xd4J{9f<6ۋԮ..G͔Sf~-A8 Hs endstream endobj 171 0 obj <> stream x1 Om ` endstream endobj 172 0 obj <> stream xr@G9's@"PlY5woϙ[5uUiO_tAoc2(֐Xb٬$h8=dg]na5dBvN?{6.BD";c7TrZuyM7f',Zz) uyuF<4HDž6Qa1óJׯCnaO _bn1>D 'i'ٰGf%lxz?\4LtqOoo~kJrWy([q?Ooo/~#2R{;Fgxx62/)a1/֛p]W0iݧkP-aQz{]BtЭkp(Y% ,'Hf),ӫf]S֣;d<Oyihn#^[ct,dI6$ʋj)j/j80\ʫj!s (l~/ l}$(m82 af25+)ݸH9WȎvK[uKa=o$bR Zr׌]l*lW}THo.KܰY&Q-D¡sm_=it*hGyqvC7D~,ݦ-V?zU)9;$C{`%:c1#H=@#H=@#H=@#H=@#H=@#H=@#H=@#H=@#H=@#H=@#H=@#H=@#Fee?VSOO*Թ A-V/j:qr8]` v:6˕6C1a< DRxXGQb;DDNB *ʥu8V4fR?ܸ]gq(K""]+t=bEI`z R\"hׁDvN%Y ViV20`q +.2όdԫc:/0]fՏYcYN\7+gg,Mnv5 w$IrSF鋢4&[?dz?>>o֫b>)wͤnpP8*cqtR|=A먩/Y鱫||;q~65IkN*D|~V6cEl gjCqo碧'*ˇq; T~P遰9aN)kxد~I凟bݙٮQ#*Jr gk'meaO}#﹍+i8vJrAё,ڨ* cZxh\D.ą鲦5JDníECm7֥Ũ{v\nܺb~۬;SC]ccQFh:a endstream endobj 173 0 obj <> stream x}[ǑG̅A@lû6iݛ.g]^~ug}?\o]޽}/_ϧ8J !ċ䏩_ûO?z"ԫq7~ٯݡxwXCi߼7~g8|?WGNsRpK᛫?=XCpp//ҳ?\<~tY4|_ocw-6UcL;Fo.=egz{5Kdod߿}uxy?L[;6x/{Q‹I/K)_^4Ӌ*"x^,^sԫŗE{/,]W!;["Wrz[۷_×]1gCc ,)~(HY (~K{IΣK9DץD`YjǖOƪ@;n߿<|㿿}·8E%(.օm]-g=^j̍FwE˻^7Bُ3jYMNj51+x`?("~wAv7@ kEG/v0-IROZSF\59'UnUF 1WԶ= ;>40~WK<>m?QA"[* l>J _.}xvoP k\ՙs!.?_<Ϯ;볛.]Βeoʶ{:_ ۺwox]a7ޯ(煫"+^{i#]ևEƏTG{_|fk_|/ȡ;]w6JZMPSz*9NSNhZkFc}YEB݊Ѹߪi((l^~-|Ee[P2͢ZR_I -\HV;`v]Xvc(Sݖ?w:^وtCwk% Xt}%vI* 'xaUj)Tg:Lb5-~M/4w^03%rk ݊-4eQF'Gx`o9h2?*cJYpoųC{;Ol"h~. nG~v$Mlvk!Vz%H~2IÌI6vn%Li=V ۺ4P^}C\t~(]8,"S&KI*3[j%lb )Ve}sSGOabtn}{mfSYVa,tn{m_m+2t4n2֙ iz'_>:OAzn[5N[Ks̈QPf4x#a}/CuDIC1i1NIMÜHΖi^қIA"٣?P$b{wj!d ~0 XO_36 G",7XQ1`|o_ވL~5R!a|/U=HH;r$77==(gaO?v2&'tBꋶ=*-~[w!öꗔn"!y_^:x k }Qn,6OJW{AKB;QڧQ9xFP"E&qW1m]Zvn[ם #zh(c6clM:r^$<0YTuXf:)=J;mo>d+µ02VA: 悈;lRܾV;@̊ړNד'&Sg˽U\ݙoQ>pCIt]ɝ)v%= 8=V 83 k=&Ƙm㎇#VbiYȲ9}~Bc~}1iivѧֽ>e?';F~a憏f%h~aq|yTJnwA H77|ts-- yxO_3 :z+T yGi&wwZas=Ucb|_Y>V{0Wd⹺*i Y{;˶YxfHf6I&)#O"`Y/sU^I2aHirȜۭj*;SGTt9D2v?H^o ~w{.}مc֡x\f>$Q{oGgb=MPHPT<%PxjA{_ڡX3,ܬq !paoe囨$vI5tLC@3<(D Ghp\E?1ei=0 qMA-]cBR:T/Cy3#C{e%P nF"oڜ^BcJ"s\/.quwd@adIJ]+tf@\pbZ ߮0鄷8Ն+mW.bç36py#t r WJ:W15d/+ruoWK/QQЊLڱ''x.E2":d3pnο}}1]A[;8B0նϗ9nXݽrVD8Dy>ɶ+uOiI;{Zܣ_sAB.&syC7a%C3w!MQBMúۡ_;DdE-kA Ulqfv"T &{3; 8uCTm4z:Z5fVdWuu1ģ 4q/tx1J\dy19c4:-߮:-Ng%ȖX[Z]eƖQ|ܲy+ 9qȾu9>dߦ~ΚЊldS'^G,{wi؇`o;1ƌc8FvwJHċ:5 gn>3׵[r |Z1{yՠe9*6h"Fi88ÂP ^$5\NTQ~M"i :#Zqӿ9HPd8Uf8 ͕FGͱrE|#36_[R} cB Vfރ"SԝpeisXGC\2E/.K%lߊR_Q=vnwBnPJRXq[%@@fcD*fbYu(A7j3/uUaNGe+rF~62\Ȃ;n$qJH_6pنAŠvw4;N{Z*QW ĵs3tE$-g'b>2r&bLnXOX) )Zfu3z?>8r/P5Ѳ# c|\Rv-$ª@oA , .0|م!x T̲=hيl)ஞbAde3 IA%Vܧ4(>1Ӷ)viZmDk;&nn(¹1KYh Cv6*OmG+PYS iV/(y֬0Z@EMZ7E3DhSyBIQ,b3ŒNхcoJ[[ aW YS3*k_峦r{t,aiI>ܫVyV+Pgh8 ?CXe֋8B(FnrTbKAtTsx҄6*0th  Y`#-h*@ѩ%tR=VʦK=mҡXhԠX=XkB7r<WobdN LqJJbiװFqUV(ؙ24ȦUr\XGKFX0c#kǸɺaʟ #6 <0{uk֐ J?Hy mq@3Pսb]GEFo-R =0]EfFtaiP9hx 21h[ZW&c䬠MA4HZO3mw~UJɢOT+`}h5ZJ]SlmiАJ+liK;҆UUTgg(rmIV,ĺ v`Il,{)~VLpU{%trEbr^*xvbU1>x5ճ ܫb$[u,P545,UWOYhq`Tu#k.kzP Ԕs#ޜxY 4|]XvR&/UYru) j 1ҘK&gyey0oCZRv\I@YU=TUK 2P=X/md`8+bMv-ЅcB:;βf+_"V^% (^maDNk,Hp1hHP)Ezi*R*3γ}$WͶ9W3Ԭ&C*UlؠUXUM 5@耎z=LQYͤFլ,P5j&f5:JլFK(ɖoV6۵ Uгtu&Z [+Y>hi9y] \iqLGC94$-"WȤg@FSM."Mg'%X&smX]e;2  gm|YKVG(ݬd7F( $͌aa [`<:BEy^P5TlbKP 32 jXJLfRlt JkTSZk-<tO&߽۩OvJKF wRϯkyݞ wЇc"Va4="Q y!%lw/nܘӳ,'r NK|W^/Kyd2~i_'>iiTī 6x2ؓ {A~B{Obtss5{x*aw.f9 K#TK+~Y0c̊1Xan3t{7 ΙfɘG81KzuUkn/Ҥj_rsxÌ?Iv7zԂ}bs'xZnX<5z ET[<۞3J-InV7;ssi^ @W-|Y!B/ bO,^t B QIA`.ɯ-vCl'"v Q̓I/4Ed3d؍5Y)6p!|y;97xd.G/B|BTr1u'Oy1At6զ0n5˂gȥh }]g̼=  2Cm;=9.Kei|P*m"Y-t=N|9Lt($27fq|F>HE֌W,彉9ۋqB]rg\OC@b5)P +$Fe, 2+@vU̟v2zWnSC% @a<86;>xABH%$ I`qSf BN .PCТc˝°ȏD[R ,#tfZ*abh6HdJ>i5"PR I-x#  IdB 3QLE rκ*&biT2P.(HdCJTJcQF%XBEdf̋o[n:~y/ e/I礼ʋe$o%ƙFwQYnH{!nToVbX?)O(e@|M^pS,L%$>KQ)O ~n(*bV@!b(gD@ř t>_P rtCzLU6sOE Ft%Y.$$8%BhsRGI5FZ+ʁOfɴ>%8j&ɧz e`gr3P}U~ˌfieh:HY _!'"B/,2<DI r%n rBUiCcqU n0MtX ~U6dKVU"}##N( uˉؓzAhh6JHqoV 2t(ЖB3F)y)FEGMHأ ՗JN;53Bw(2 I$9}6A&T=hش2nH#Ql8EUԿ\klÎHlJ+WZ(`]_"كp_1.G\ؗ|iP4FDFR5v۪'U|+78 08k'8qNVH LE 2IVIYǔ@MsL(`=$Z4x "gEpb[Q̎\jws{WoȰ%鰋"NQB2n+rҖH$NŦ>آ{ "Mڊ8(RYYʙ^02Kj<`;d URY1{Aeϩca(^'4o k3(Q N'(Ӎe tžuHհR/JE[3#ePGTݔAiYRQ7wu|ԈXWgx ,"Ze+Z9?|yPgڋYy!;A"3rB%)U@RRsĀ-E@PzC 0bxBge ZrR. O5)JzXO Q$\'/2"@D 2f{ bJLFfQsZC m՜oei TU똜S 3GNGJYe%cW1mJl:ke_\eM▝$+%$tO #5eD̉3(e-nGD.7OĔǎ<֢〸UN3ĉ7bFm4Rݝ7I=(wDF KϻⓎ1/zNb-JY|wV(۱߲ڈXɷJE#\S&QPr0FF2gG^H&@</$ BVkBRG?P @L)qMni$'zz'뎀@zk/XHe@r* %X "!GJ7W@sЀ!qB@0 .u@ml­[)@dV4U`Τ`B˘,d c%a "ㆉVdՄ̾>-K6.Ge[hB"@N k 1"inK&^_8||<"gD,Cd!Ll#Nmw%E΍^C @ eKT2瑰ʈv^wKI_.xMW|Cg}d Pv-*3P5z$`ćeH6$ 92^CkAsg:!#P:)YHWh,l Eӗ0[j0gn%@9Pt$K|E ^E @UJƔTD艻) V/ڊ:aUiʑ,BB.P ;NK%*Ga_% & ]:ov6|eo4`XNȬA"d9S +f*PcjMW#[+j]3LVg3c-Qځ[hAGS&JwZYbiM?jBdXtVч@r NzOXZE ,w^VwxE ᨈKd&tDxZ7Rdn!m F0q"t. Q=t *Ӽ4i5hռa/7R9p{EggV&z 03%lsن`I j 59&٢4S)r֋x,HDrj^O𽧌 ώG"e + +بMlֈCvٶ xY#~MJMtp'OJi-Pʟ@:} 6f+M10ʄ#8jde;^uЀoaw9qC7}p✍f$ouķqSvC]'QmӮHʕ{x1`2gF!0.{9T 73 sjJԩ3dIAwx\(=ۋY@yL)x/$]%( ԃ3!AfkKP&g|/G;7T dul rxVTф7tZ^&UOnt9eqmeM{ 7:̂ 9@ Lk(rI`Bl(c ,lI2~ k #'S^b2Yv%%d^+#q'vq#!G|#p@@vr [h\nd暥zFv%4@n||Q 2߂Ystш@{|,౰R@k$sX] +HϳBZ%qP"#;^xr"myTt"ñN0Vʅo.f[]l![鄪Ǻ1r8Ƒ{`c_;Եdpy;uPր:d ND`.V8f.j1(aA-ĥZx77u4%E _Ù{8' VmA-KvSe|Soq6_aRrwaAW6&:( @5̧Fĉ\I:Ϝ; ̜lS։eVEi'g˛w5J/hDn`-& /"&w:/ҧ_/3xܓJXБ!I6 r2[L _ܝ5sKM{|LnuzM߉f% 16b1n,h <6(LBT4O߫ AL5(. v-2 4݋骉']9(pЍoX8ѹ2oI+{%S_B>XvN&9d~;DHցlb 4lg#Htr7`Fݼ&1I 0_6q HV9Hd /,HxM&rG'/DT^2BjQ"t[O)3 iy)&)Bbk wGOQ8 =T*(l)k裝k2n9VFZ=EbD;85DAG$&,1E̜p.k'@@S@1v*rs[@ j!`E[ާ8 Rnd)+KSA."^zvLtU1'495 "SbavRlQ׶TJKbڨm" i/߫,DyW&W  E Q|#Vw#c˜DAH ~4849<.!kĄAtefUg LA>@M`fGS\/-T2A/,-ER'}VVhbm5P[ۈDYodLjcN>4 =j?_zX& ]u+VxH% ;;{3BkvHBmUsF# tVxN2~@`@%{n}e*M8>. Tf)LHV(Ǟ6%71/Fk endstream endobj 174 0 obj <> endobj 175 0 obj <> endobj 176 0 obj <> endobj 177 0 obj <> endobj 178 0 obj <> endobj 179 0 obj <> endobj 180 0 obj <> endobj 181 0 obj <>>> endobj 182 0 obj <> stream xàS_U  endstream endobj 183 0 obj <> stream xvؑ%{bUm_"{I࿈,|k\B$<ӧ'|σ J:({>s 6p'ثΝA E"X,`Fyr(q7bx D_P(*Zh4ZVzhipnRJ@Dv1; P`"ARNo0Lfjv0t$.)al6b6i5jd@ aN J4fw0N`0 ÑH4xbh4áP0}^Hxfq02֛s@aТRkub3Np$'t&BX,JrRT!bP(\6N%X4v1l2rXo:аRTv'A/KJVj4Vt:nw8trl6j\*L:E]8/`q7@qV#ɕjZ|p4LerbRp4O&t61 ȒSp nLp8v tjTgx4{Nl$,Fp$Rdv%-*zFh ~Jxh&m7B6Qe6haTAbC cczT:$ӄ Ѱy7.`r>=^+<`,S hɼ7橋Wl7+@u[R620/ Xp¨jiTɰ1T2@;ϖts>NsbGr65`:L9> 0 Chl!*@^hJ]VRz'x$JN: C aPh*g>Q-=#Tetbj{8]]÷8l81B24itywH22d7Yln|tte.}%:( L0Ujgه3lN5$p)@-obz.'Z&49K{JÍi5VA^pDJ+ZhIx0hBRZԒZ~}B ]0C:ۋ\ h=Y裟5z֫&f;XijLHQ#i>[m d݉n3#N.ZGО^O|*qa"AcG?kf9%=FŁRw=ܢc_a=5)E_DW["# ?"# ?"# ?"# ?"# ?"# ?"# ?"# ?"# ?"# ?"# ?"# ?wDdgՒODޫ}@FS}Y ~G{ޞ+y[yK%؂/}*;z9m|5Z㽣Ӡ0tsjC-˯g{d d`Gj,D{>b+S":[Iž̀|6_!2@#fz6ݢ08*~_+gXO\mVI*4g(]il &y^N\cyR69CRs@zhi92LJ;iWQU+ڮ:HbB;wUqa;[n6IQJTF/)7{zsnP|xAOf\t~L$JL䫭xkƭ]A^LEv,tzĒ.r VnQ#_$F*߮]/e~EǕn=w\$U,/WdP:j^/f^VL.{!$vLj=‰\.VؕAu|)O$-1KE.Q ?J>bcBGf{+zVe ;Z1VV)`p?sLv? Z|?(bt4j\2`Y=gQ~5]*U HYG(U/]5j1өf=?nLĄ}:"tDaG/a-㐂9*pʅL"YQ$Գ3[Q/Kw/3v-XPķnImaG.nW-ĈIYNO |5}Y/ MoYe僦[,r>R!p\prDQ!6۰2l,uZz/ـ ˒=U(lVk &3XWηâr,5sU|&tjd_z1 VaRÞ'=W|pv?i_ltJjwZ(Y"!,wHR+'9@Q]¬d Zi HeBTjڝNz~rp .n(WZ qX`T yũx\RkJ`^_ Dcd*fsBX*rRVk%pXTe\D>T2F y\Nj1:JI%$O <{y l endstream endobj 184 0 obj <> stream xàS_U endstream endobj 185 0 obj <> stream xYrH:ѭՒ-6pm/*UWV뗆 /wr _Ɨtx0=[!ӜCu7Ny.Ev] 1vuBCIvr9G&E;.۶۶MSˆ{zќz{-Ng4Cǡ-IY3Wu=(yq{{.cxorT`6axLL SN5N7]m4f2?!*d,"97.>~[p14v 4@iv{L3KꅔإCJv@`Z_A*:Irdqʒ `BzgT&MO$i^?ޯsaFS(4y)1e;%fC3I,J?FLO 4,ynoK L4 5XЬ/YQZ`hR4ud@$ðD)|<##o"uYٔ!%t%41~84N&6"zAdV9ZaYHhXɁ*ML!?q[q"AA;4>ɶ̄lwB*6!"(ʯ G!mld~4XEUKN+s:|߇YӾOf|-aD+XYoەD@4,Ng x 0Mq.+t+tnM40^.NFIizJT@PLO &΁ȡ ړfgsс(֗ՉK@(M&/H:f`CnqCjx8%*.OӄӵoOFg?Soz endstream endobj 186 0 obj <> endobj 187 0 obj <> endobj 188 0 obj <> endobj 189 0 obj <> endobj 190 0 obj <> endobj 191 0 obj <>>> endobj 192 0 obj <> stream xàSU z endstream endobj 193 0 obj <> stream x1 Om ?( endstream endobj 194 0 obj <> stream x| pdGfቀ]@`lL4ù`eƜ<03\,Ẁ=`t߷ԺZjчRw:TU]*]Tjխj?egKرuݿ_uݿ_u۴1_s@6] UɗkN58](*z WnAo!4 [1AYdU(*dKrVY\*G2LŬR,I /1K')rR RVZ/;q=xz@ToWlx5LɁVAa%]-1 W!]2 RAEVSyW e { RqG wco^*[*kfcac |#M$!rԷt.~cB ~JrسƷPH*H B; $|8.@*dGnIV7R|~F9Ht J.ML)BitjWjz-^ zl(Ev^ŮװkT)m LqK51pB& (ɦ]t!M0I!̂N#Ma3u[~m-KQ'0%$0{)g>l~cc[/WoW|{AnY?4& A<95FTvv&2D.5W">09%A1&8(JVT6my'gK -Fͯ &N\4i.p jnNؠ7鹍*. jT \ IŅ2 PJ5yYΪvƷ|M}RIޭ6%"xT#K"rێ* G7FrE.DdSz]5]f ل!glʐM)"$P!<Pk07dlLx'4IãÁ"媞$g2 u>!mB'Y4Yity8fكG%htG4EF VlDWì ܌5Z"4.Q!IV$pAR uوGPNБٯ*8ǎ:d˘8|vj7 2v|٤)R/U0R P |>DA|K@`' IRUͬ4+3I3U%dVZ~! _t}rʋ"*DD]Aۛ\H-}JcϡC-)Wy?B:A_iu#\ƺG$ !1_W.UH= ?,x0 \ ;.nZ׌+Y54[.r<ɥ "U*HT:S\SĩrR8sEAZJζ2˞^a lT5ca73 mɀ*wLq8Dx TqUL[`2&L-ʥ^awV;@ЯEI^ԩ酈GԈQv#ձsDxhCHn 6LRZ&E%7EܚqIa[m$A{]/$gUx,B+Fa0 voٱ )% nAft$=.jy 6N piIgvXĨkcB:HWDdT ۀ"2Q_$}yR/n[ٕf"A򥊣 V]鵼ϻIxŭ1;`8|IdWAqoE2Xd/3IiBS GV1a< |5 <.TL4MQ2+FAH ;XV_^ȥu꾋vFL(gW^IX510-U{B@9A:)U{Mm 90 sʥ >%nm !ꂃsr=k7ݷqqs+޲GFJS=\ʤTb9.칒h!5XM$`_Tʎ# tSp:AFaIRp)v'}JYAB.A(8P2 o *YUT&AAjA08_cuBYe vMqf\Ŵ֑M+74\um"Ml$jz6s&279?: Ӽ!gU6B*⽚j!a >OqG-<Q1ZaQҞM".3?#k%B@o#@(NqMm)fZiW (@,"g3\F CZ L$`_(ձ+eQ"щ:FU9(Gp7,' S)V8C`HήϦ"|xMnt,J9۩+ű+yF̀rjD̮ZN}:2P%@ZU5\JPȳ`R6lA\s+`/NݸE\dqSb14u`=*Eū-ݱ T#- j2J;i9_Psr1vQ.\Ȋ,{e{U<d{SK3Z /8g̲^rVhza^XeרZeR v&I'ӮWj jW ˵@(x ڕjrnZRdLrW%GSQa8H%M6"Hr]qSk lREރ#,Ws^ZFv_tG#vIAܠՖF-2{Ԅ ~7W]t\c@YRcF#^Y8,7ș CA\dǮfq_pEE FY'A*nfk^[(A/˗h-u4%{@&eAtw )݌2#sNui"mыk)M50, ,i HR Ot#9 GwAVe4 7|*B FQoɎ] 9.$#H{%ltSfU@4Wxi+'Ixu6t,i6j͒ʼդGRBK/|Tȼ @! DVqզF) %^XKh࠲5;D Iǃ(m9EK0UE\eG!I/`Qb2>Q`2f5e5TN",-BsRa7v|^VoDyN,0)t{K%\%A|r{km U./ҔRJdK& P&kn+K{;(},պ&A\Ф"vbRRWcWUx@:H7+D{G#dUvh8fQYcz H̤H:Ͱ]2.vYjA]R> -eyUv* oAHX qީj_WTvŭɚ=N8Uš $n*ݱ=D A}rP*t5;TU3 CuJ˭QA`V1tZ5JŭU[UR2p:PKjU]Z: #8L,hWȄm7VrUbXrt[J8PӰ"Fց :^IbS>_n#+xG> ơh4WP˦j7 ɻh4 R$"WBK*ϯaH1a\jm ըbѥ\^{kx= ·=}@(wAb 2hZmX腹gRyŴ  VXe5-iNumKӹkl ViWԀjNtǮ2"x(9&a)"Yp3YzPÁnS+ۄCv+[.ɭʡjsk,.uSnUm`X(T0AC M N }5bC !vx Kwt"H'j4J[i.aP9bGi:U EWP"rMf z^"%H. ]f3̲RuJN,ivYz8 tOimgK&"ϧ{n?pk^Z Hu>LtłL*W<2rz`ztQakAM;vuLjx"h-2[ .bb\BJ*dg[fBC10}^S4/H !d*DzϏz .@SٮD9٭0Ԝ ĴtcW=v5ϋ1Iby$iE\ZNu&rP +2W &KogYu&h~SFYD^K?VAV$>Hj!o RNŬ4I\ FfXd4ERcWgi{:AqrP5 ;ltNY+r)2,wD9^X&"ցW-l #%X-{+% M,v[ͯlPu 6ik]L'^ "%.\K %"6#Fw.h 'l=2 ?bY;S:2-tgIy A _'EBCEؤM;vE;H]4 [Ll p9r~g6,r&451dG<Ültʺ̒&&iKIَoM.iJq]j412*v1ģ_DYi[E9H/ u 8"m*ݱ+z HpkFéS G.*Nî$VѿaF?9ڔLTYT +yŽm0B(NGcB~V˫]>^f紐"ፈ묂HE2 Ņ~.y=`[G3~3()|:`dtZuZh5#Yb#&ȲZM ]d beFi!Hu F/|}0;J=hkT\[I8;v5͎(>D rP.x)L+䑭 (u=OG`BaPh}0dQCpk$CP5(qŐ.NAF(ÃDևӄg8:Q;uӠ_Ϊvk:C~NͫO1wzFa^cWccY$n {&tpf:q6R I٨wLB׆a#QX1L8 u szJ D]C`è*q2xKѻz4j-hӭ踵!Al#zpn/uFi3 uNͩ.)وGS3 ̇1{Fјg8~:h8!w Ao [+XAh;!=E^M8];vu:\UB &6gagy>ɺ\| }S31^>x∏ƽD#, ANI d@e.W] Tu6;'ӣԚM-(m/wT)K'i"^ϩq;x`uei 4@y&GdiUF~nV+DRJ@dhT B*S#ۀoº3.HE1KM;10P;tiA1ir[B%|(l'"?$sSr*6Q-!/\G},ðs;NVo]r;)yߖu}8ʄ' v2dE3A>}O"H\UML8uݥ;vuZ+h4 ]gdp>btp@r&0 NISt'z r,#ЄijAADdo $psM@|7 @a*%XduCP<Hh«.ݱ*^Lw9<9h탖FA slܩLtЩl&z`Pdqit` L$d7@ *t;vulNq(ADym3qu*4Q_?ũ!p 4@q {:,نe@b8 mAeW1ET=;vuf7vsk rnZ±SA;MN"),LmEsIvt&=E \I'n{X8*N=fdr#28KUC{b͝|jn+1M8&r%7bNPN͐C$g4d+9}HT8YMNQsDwKό~>/|U?/nzI$S}(jꂖStKA;v5BGG(h0_î3:NuAEI[ 消 bj8ILc.> `ԝtjs Ȱ{cRGOLW~iԾ==\ z'F??C1p.8u!`aԭ4~|[ScW0_"?.I%2<#:1!LیL""n?i#>dZr:#?8?*4$$mgO=G[ώ?g/|kߚ7>~#c_] o"(xN+D"3@fflvnŦh<"b&fPInħv'@GrIABIAaC/mKON_] 8l/< >ɦjt^ j7|gC sIJ_Y[5t+Y:v5#bDxr>vu9;F߃Ha9N|Zo-%gxdÃ'_G{G~EET"9yK+Zz%/ʪjko{pH|?{$UjDA\qЯѱ#~.\QB_T# -[Bm.s;i;h W3iy@zjr r,ɹr %jO:?T{k 89sl<>᧟Љ'OTQk|r|)}'l߈ގ[shXa)&[6ؕd3(3 6Q@HHZi$ v#e4@ uPu'Wl Z8]'N7y?zQo+?ǞyS}^ͯ ?ɏ,*ʊ[wN/׀tKS%:vUsk9ňwo. dBLS&9E%5CdpB"$} i7qB|3gJ-_~+8O G"c`kg]VO'F?;O}G oR#r4 @ (oz t)pk޳P CRY rrW-qFX1_~%e4ԷoHFG{Fou緕_tǫ_3~F>tVd1SDAr -Jw k$g Z|b5T|cfI^r>#'hZ0 {e>Z$-H> P-L_VbO|+k?}?njnNDGFoEdW:sgds羰{O7<瞹I{h;Ug뗫c%>`Ɏ]g"R50|fEJ8\yGԼ*5#CInQ! / ͏?.ψ)omKkKK/c~`? G?t}'hx7jWRӴb>Xf QD90ؕy SpP?C߃Z9d^83qm]T )os*Q!B!EF2􇜨\!CN!tHp/zXIG>sv {^K/;?4?ӟ'z@Ck{c y#m=G?zY;F"՚mEA\w-Oֵb?a4M -&/92iNjvmD'a!@<~N$/skF'++Ԟ]'ao>mg0i{_Gjk擟~އ?x=C=ȣm?ZǤ]"@5lTIņJwj9h DAPcׁ)u*NEAoO|~n|B~ban ~Ƞ۞  I:,ڻ{?}0Yf4[fi.ϗiӤK$mӴMb^Ը 3l ,Î"Fd7De\=w.#5i\;=w翞sa|%Z=FcDW~^oS}+Q{wno6,}!X6QL3,.KKSHp{~Ko $qAmBTcIv5q)|v dcWBOoH8lՏO](}gOGrƋG>U-tƒLfK0qIKڲe1~vOXT hw;_}m$FĨ2M6W ,>9 ]TQbtr;OL89ӗqjP[m͵A3ǓNA;cl I8}x2r#LMɠl{K"5~x5"disKC{댋;rm߽{MhrҳlY/~c 6!Z(P]*LCP ,W%0L?YC]:E98l Jk I8?fcWSSfbIm iztpn >ݝ>yg *"e&3:L :Ak ā8 a-n+y5.O8gXLbT'ҫ>|5J3zo7F|5o__?\ޱjٯ ZBL-Tʴu@2,f[|T;Qb{tbNez3Uz01Rо/x+r1rd;OS T:֛RO0vt)Gv|nO:7ў4rzÍUnYsZTGpծ=[\E~/;ROաknEK Y @ȁDbWxPx" a~brמ{|kY+o<\MbY [7A; dej{OE}v}2f&rXpPzWl63$3˖+-bN{^>ju)TfJދ1ݿoOmR(2m ? =5{>QH=I2m&VwOL^YYΜ\ GAg ztǮcWqSix.oAXY.LثN+حUh x`x_ ￴OAon/Z.c6y)"[ ft>E/YBeetȵa>LSЧW/:sr/U?x"m_x/YU{,tX칾a-cF~1eՔbT,rk=@9 hsozׇ1^zf7^*2 ۠g6(C]/4K<ũl$OJhi0:(Uy;v?u|Hk7bN{eeeCV%/9Q@J N7a7)U mek9 *>ا{I?a|rU:USj5պߠ**LҜ}aΜ\=l [$sHw y;vnB7-`Ӷ";¹}CGy!r+#4R G H3jlsio. y3(mL'c2lo֯\]_%T)嶭gpqy N܏GӅ:IWX8F/ gv%t@Xu5EadaS|)M~k DcLwL7٦+L2u B|B0bUڔ3o:\quݱυ¶}ڐTӼjmlt` ! nJsoVlW.; Cmo,؋tzjJ½) >!^F2Q6цJeq W/75V顝7E(h}Kmhi?b*U[M[Υmpg_ٌ`N7A@ҿ--R;XuUEKq2KMsUw1lW$2ZԧiGȩckގ8~Qq2qu zvA6`xzC+Ubbbj^ra4gZ2a@x@f4=g9Rvu՚ MN6L1s;uhj|$A.E`i\?) Add# J8LcWqAq mu q\=_غd]մ=]g@gHlE;:b @A:nt'; | R]Kky7kP/Y)H M5 + 2qqA*4ǮLMr jr*6̓WcTj^RgH飠@+*qJh}>vJq4٬09Y qOCU`.ԁVBX rm Bngkj5CmWJ8B\aDA|% q;v($\(h}0wj#);?}в^n=~t(#vJKda,()mEh-@ 41jT?Ox|R?XA-dWI<Sfnm8RcirƧ#zmu#~?O? ʕUU.]R'ީ 4kx˧.]<~1$as6xo[\c9hz=eJcWɔ[kܽ6ӴRm 1%`,9b۫5:\eZ^Vc ?;_g6HS󃬺H z T2:6:ک 2XTcVmUɛn&D&T޲uZX44'oP}+a]M'mQ=^6OL'iG6vۢ"=wIX;WK^s"]+&zۮ+ 8FXD{8Nq9h]%ےeWKL]/<^[xI{Q,H3]b+Tq*CXSXP (Rb|TF1o_mRMdt]Mg=mBiBiQ)l/;*r@[Ic^^r_/[d1,lU~B(>~yjMTa\$m[d?vnuЗ0?\4$>XL۠WRneF+WI y=oǮxc Ox3e_͠N }E%X3{3 qe),|V[j+*l&nC|~97'k8iI|:B#? <@jEeAˊ,˛-X>}вFjVղs@&H-2}30Q*3ԫ2-W}ԩz1]/85}nNnؕC"Eb;hUC|вR*>P Zٮ $(ס18Y*9h*h1+׊\E00kx 2sxAv_d@xwIU9ATY ?LΘ&hԱt e/*U$J>yrVe@XmAn* ''wqC&b^nO[u/BQwxh9rMtH":}jH{.W1rKDukn+qwI<{4(R^Ud)ςTK< ܿ޸o+@qDH48#邬H0S)/J^",-TIS6 {zzP)-Qm۶6͠-  ;:: ^w(r͛QDAPYPP۷o]YY @777ʃa29<IvDGVQ\2$5!Rt dHMMG+)))D\ %Ο?Ot]VG ӧOSYR$$$())AeEEܽ{7UUUrD- ĕ*U?z*UGޢ&ɟMk8Sc #ʴ4;( #%< GW?AhB~1 }AJqqA555 Eԃd/n7Rz䥗*Ko B䧟ݲOzg%~e"Ǯ,6V,H?lC "WQWW =cH4B;,%  $`"BBBb2K 5ЌA@"""PB@VA3 {qj|Sgky-K}p Q( l@Dޛ_/VǒǢ]Mw^ ؃ipƮ\Nqٳg~'. Q#z x&Me*hPR4R h֭[ј=BJ,kИ4 '`FA3@JD(G>X'-)m d2OIj=FFT}oR\DP:,j %h|6Cj! ][ @PB@1:Q/.xY ByB<+05 Adهꈂ=[o'e* J|I%CjJЗ5JSq5q fT0$ѯÃw'<|6~fg~ 1zɌ޲B=٦*CfAD54hZP &ilzqF_#BiAΏ$,, Kvf8?.D?uI%3? гbqqd'2e̓%BOxbbB@ Ga.\ <^ s`uIB3ĩ9SG&{0I4sA)/a2Iꈷ 0Q!Echtn`\BJd&Kar e6Lzpn:MNN @  5_C5$r+VB'it8x^%|t D݄4SENtN:銏;G'.;BGzAjZtE}g1c-*];~ѵ4 񙚫!d)?*X?BĂg-\ d* /੡!))!M8P+R erBi,Ná ~$ԓbAhCaTn5\n{&vA2Y5-g̞D-i29-*9.:_iDRZH^EA|6}@> stream x FѾKeQ?veS١EQEQ (P@ (P@ (P@ (P@ (P@ (P@ (P@IMɦM9AVwnI>N[xkEDR*J\սMw endstream endobj 196 0 obj <> stream JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?(((((((((((((((KmZ]>ck% U +Z%;lv8˾u΃s Q^w_'lR(>Tnw:^  /4D:-ҡb]9fgdPNY_UsQEQEQEQEQ]_gptv7W ۻԖAccoFr+7ghmo=Ʒfʲyd-Dإ+x#w Z/-ZmRu]* &V,;p8:]CIMǗe܈2$ ⶣ9FbzHe*QzƼ] VIHH8p͵ZzrJ-3ɑǠ{T)eg-ĄO=ϥ J4yZ2&Fr-O!S8?uOj 3?ʡwrHRpF9MKW6jSF[c?>y=\MmmMq Ru8Tn2s;˭Tz۱Wxf9,gUXLLꌲ -ڻl| `2-nz]{ U((+`=kĖz<0>@N HUGq5Ca>*J4rQ .㳶- >I6%Z-&s1Սcvw7kϖ ݩRZi]hjj(?QGj}9u0Hrº"}dՔoAʎp|r#kcip?n Oy)/ncĤ7TT~B7* X*\_Z.*cd[.loƦJ;G=!:"d7-;qV\ۓjKL!u=ԋQ!ff8 GmDcA?Mg[FK EO(Q ] Y7ĤE%x]BTh$F7̍YRT8N:eĜErwstQE Ɓy_Zv;H#s=y IW?ax^ g_ `*m'jc< gs l a `qrI$޳E,ZU,ykfl溓qj4Iu{ 5E=k>0GgnĠ*íM4,MwѾ`=+p7teeq'lҙsk<T9c +=#1vCVْv{I" e|, !nDݱ*h#s4<$z3bHdvfnG}3ZK08nMgR6WC_WMHGhhh>f-,ssj}kVԤ_htoȱ fcSOu=sZ?ٺp`K?{N Hk^ !dێXN<$噝{u}J]RXUH F$ew c᫖7m (,(5ia8["<AN_kX[eg%@`rI?|X|)K}VKx*x9*=Siڬ.`B?ͳ4egJ WbRmAk^Auo[7F4֍\ ծJH9P@=PAP\?eOq'mM,tD?\WSM,YdIPWEmO6;/Zg!UbLz}jYn X>ꃃcRi/AocjBQGa^KWƐ[ܶI3vVc2zguQ2[ǀ+j-[ 4A?`.0   fWg2NNh6 ( ( k; }F۔APx5 3Ԭ'c#mL,!AF0FGN=>i_jg 7^sxkMu!Ӌ>j[!շ&EI 78 +pu`k-3Uc9]T232ڤզf ҋr!T:c߯mUh?XMȮ2)GUe=C ^ g2+6Zx&EwٛF3=vZO[rɀ Pgԩ8jc/G[}=&69ZiBv*HkGO.kk[?j$'(*ɴYhjVqzzSV# (FUH  zY׺>l1ܜT9_C VvplD]uPCpDcBvLv4h- rxzPQQp < ˙l4yG/,llmgQq<rdx=kxT:ss7MRDnrO^y .iYQPPQEQEQEQEQEU[KKv]+zp*! mubN_v3qBѾ#" [j#h~rq>鑟ifCYAL[-­ZEӂ]'UPmn␞]k 3ZvyRAG#Py5x`69R!X2 HMtr ~/ wgp{0?)?B87*ͦ<cC>K^}w[''|X•IG{b練EW1QEQEQEQEQEQEQEQEQEQEQEQEQEQE endstream endobj 197 0 obj <> stream xQ0 DyGAb{&CȲ5s9s{?N%t|%v.2u6dKXi-cq4+nDa dm5W[m5V[n&1ؖ&,07Y%,ڏK6CF'zX5 &:J2T4Rqg5vF:VG?ӗY9i+as(qUN[ NjӱkZ"&kb5K&ظ ԈӰ3Zv\Liԣwy얒uKz$mg^$%}xٜ^/r'%9s?p endstream endobj 198 0 obj <> stream xyPW1*LHVݩ[uo$:Qh1("*{\ (+ 컂*K'dQg8d<>>YEz^Ez^Ez^Ez^8U;mۗU;~vؽ̞ǟ{Hžn> |;wܱyʋd&U>ܵ'CN;vɓ2$$$""bo߾ĕsnݺ7Ν;744tl_}oƎ]:fQ5cGCx{:y%K6lv999>~xII ӧO;wԩSY-9sɓ'NJMMݽ{74CQw5:\ĻC7t|㍾Z9w8wqÇϝ1f:pfggj GDVqq1'Z+**>쳛7o'/^Œt_rK6M<#Ҝ6WϝܷiSԚ5NZ99lڥS x9@k ܡ%$֚ăڷo_\\ ]z߿/ڵk "9zZ_ڼϚ4]ev̙[y7ݲG. ذ#GҙIIIgݴi MbŊeːK/^˗.]XK,.fOHHwd>,g7?/@S)aS/;?,adMf^ѿV/|okҭKnn,طw/lKGJJ [w͚5% i E.$-Akt)88ygWZ&,w" JJ \7O??$iC<^$l|~{x۶-[{ux?nrPǎc X|a-ňSXXaa1Av[l"CKZʨIr6G@ǡիW=({dw"窪")Gd~ +LLn/q{Ͻ[74o>W5٩ZhXɛ7o}5L۷oݺ%ׯ_I9\A :@6AB?(tDǏJЧm7VVھ`>}=w-Z`}YXW[ 8TK XS ;19.W$K~ 88UCNȑ>VhzvFn۶ X%Xƍ LpM-q¿ϵcMݻɄSEK%@MsLt7AMh <- xTzܷ4T $ 6k. \7k_-Z{;-ZԮZ93DmOOA?'ORcFzct/<(K50I11ಯ Bxgo "GD1P G!@N9倣P7ndGS/!66z0^zӫv}:tpmݺNoϹeKΝgmԄO>yyyt8͚$KJK~+b*XGaSaKs'E='OhLk9T%# 9 l{f6=.-[Ҏ^ޞqSoۚ 4h` +Y O¹"K ψg3"~y(UPqA$p : nAxZL4>to2ZS& lVoh@stposRcvI 'ĜEM2Zx#X5 6ZP8%*_"[^~bkP(pKr\u648r3* JhNٳGoպ1ܳU[/tw߱xqzl,=n߰zuF<>IF " )1S> :&I'NaVA!R)$ie"7PP)VAdMErAy}M֪hϷ^kҔqᴂ =Egn@ e97Zk=@`Mהi QdFh 3MUZAx2PDZ8AȂ)*B}n]/Yywo[oo{T hڵk*!FG(~+JAAaa5nrRR\vv)_SVpTA|%HAQ"e.euFCa?1ؽb1y}ڴq_۴=۶;!Æ \M^JbxR/1|^Kp(۵Bef>޽YRRK]{Rf$php( JyG{H $=>=~~Ӻtqpjʣu[m;kUCD/Z |VVE, ~GM{#SK)++Me8TT?z0: 겤MI"*Qvk . stQ^{i]o #k?0m'v=zݻ3שּׁ/}TD#* ޮ p|(/+N]pې04Zꂵ$mPB)`X~P4<ߩ/vOկCпpԀ׹s9ӶmMOO/]Lk0 ,C1ӥ#3lnV84:^Q_*0JT$2A\SN2 [+cT6^ Cvסp@l8:8i~)SR"#r3Phzh",~XD`TU5(*]Rk 6SMe/< k8p999d:>.}Mgj>zI5@x!oѷ]ݻGX&brKh3\8ZB"Jpg a, Gh%QDY-܍H4Fw7ij;gΜ{c:toTvy';O ^#1 -@BI.)v篃N'HK^1аh.N$*Ǎ7ӛN1~c5v-z]rϟZ8Zk*`¡j- n-x)M6)o"0 /vڷqݩ?駙[f'&JBaj [fHX۬R6ѿd-[wLL LQNJJJMMxY_$oVw7kj{`iݻuUԩӄΝt4w#|}1r!$)a1񠅝Zc[PFtr.4KYz]_]Aoj$˅hm۶%$~uh^pt\q>uZޛرΝ1w6[ŕΟ}8;7n%`"-SDZxYDҒH֔ʒ,!#Fdrщ'01}KKKϜ9S^^~Ŋ  E E"jL51Skr}rQͱvS܈9ݺMaf. yϞAzs,製6gd ^DHТXˉQU@].\[\zuQQQYY,6GH5J  Fq5ث˗$Gۚ52o`ߵk@׮zXջwG굊:4-heArrQA'jZWAd5,"Ԋt W]LQ?(Jwӥ;w\`,,$AKdr7p'K$lj9I&?(7p'$$5 쌐N'&9=z{㚏?^ӫnnsFm.:rޏЦ#Vv5K,|;ʰ*L䖛۷o*iQ4B?d@k՘S'.ɓ2?Ii@`TCyTG=ztcHϞiȑ9aaE'OpQD+1Äa7$Q,_SKʒ((LİXf}.3'nٲ"$D:ANB9, X攌n@%؁~#gBk~!6/Erwh?R@ /+puH`d \TٛI?~9|h+W@S C`VLWP_Hd;^oB+{h0`1c׬)T޴Е>mUk#,JÔ"R>̢@<\=z4ѰZk3M ’f3 kX5;zamLVY׷z'' '[==-ػFzm)`ReaBQ p,ExV?X~~~ׯG X*JT9&Ӏ;AKF? DAdf%%cԲ-n/NOO2Gb`$| V2OwCE{/+UBd2-@^=qf׮]{\Fu5 ^J0 u b) 5am۶!3f(ΗFldi-QB& `G Ғ1x/p<[Ǐ'~if קOdEϿrCBR%r"X{^ݛzksv~* h "Y"ʀ*O:1ʂ1iaǎcƌ%`ei-:%^ _\:k߇1iOe%%%d)tNh߻x1vHur$@;:F9`2|ӏDE+.M-?I2!۹ _{07pq>R:irFaek).Z"1{V^-ABij`yNyuyowm]5^" `:%%FS 2H?Z3hQdad''Ïuv6?`@فCдSqBr]uÍE V H o>w}Zү0{L&X#9wGUi Eۺ0K##XOJK7 el$=`mY+a=l"4' 8px|N\cn:h>b)*`moڴiĉK.aj2[,O*Ql8cFEUYd!L;!Ze2){G7| w$GCX//7u4egg..f(ڵҩSbx+5m4mļJfqVZ5uٳgAT Cy{{5̜9344PVf@@%~/ƍhX?(p`-2@,eu\}(Ayt99pq..sKSS^ i e4+i֬Y vZDLqK dDׄDk d'@` ȒUiogߨc/4ݭaj-cάݻ*Μ"SϢR ɺs6駟FDDz __k:^mR'\@(YG֦1v^^uBKl(aBFۿL w@~rc \x2%իEaֿ?23"+TЙ111ӧO[`e`R[Qmt&O22r@8)PE.4NĻunFG,[d>>twwckᕵmŢ2lf6(AB+(F“nv/± ]]c49h7i.8![j;5%.YL?Kq.'^SzIa 68Dm4цR)\l3Kr!i$Q2MoI-Q?# e'TK6k6<8ptwXA 8gύ D2JjK~Kˢ )m=%,=C5 -L9'esg֫muyJXtzJzDD%dJ'5OmC @{z9$`ѢII7 Z՜MK/ Ym)TD1'N=zL)Snt)kC!Ik8Qr=pM1hZ q5F[!b{3 ֎' J9p%%- .cUq٣Et{1Qt(?~ގlݺUxJWZcH .HPS np G5Z[X#T NѶMh/ <<ܒI?pժ˧ONW*Qj]D*%@̐BlvTBC*]\\zݷo_j,~ƮtׯTx`ЀkS<nYQA$8tcZ3,++ <   \1xxz˛1ڵ._Ux0 X'5;dZ]^Yn1_&L/SG$n.-->|AH,b`+Yr N9o )  "(ݰ5m`%Y/msl|WDZYO %QDL|F2ݍ* p ]WB.~K]udңiQvǎi e/;<;z.22+mP)C3ǧdѢ&Q8˩*-2 2@2?Aee='2Â1sv.\_ b0[ͨby턃ӄl k[5ӎʖa/Yxop'$!Çuua@oZҥ糲ݹULr W2h[p`- :㍋M&C ҥ˺u[Kݳ Lh㚉FY S\niHrDe-5HH5 ǚsÿ^^X͟έ[2!RFsb!yuu :^UxgϞs8qơ.Y AF5N"O>G9rرإjK/t\ egGS5vNTec#ǎ#KܹyS'dQYJm8m4T/K$޽;Wdv:%qR`nBP+2#eٲe-Zܹ3[Ε uVZTME%^jʒL''9xtXbS qwCM*߲XaMA'ke 6r> $Dk\\ŋP,X -eU|X4Nۼy7piӆ!?&8oQeS jڍn߾Q1s9{qL_~IV-`-BbәxϑFn۶ )%t>BER>p7oH2dN'|B6\w( 6G)Cxfk501X[2 F殅qqqaaa`Q$ DW!bjyh,hРANMMUԳJu $LE?IIIHZ*L.z1:MhS +{h|.~BB>}[EZ"ɒ%ÇG3>\?zsFYXJx:`}!,ޏ>1xA4(Íjym= Xh9&l}$udſs&MJΛ?f2)LÅ /{zz1"<<J6OKY-YW~,}QZd5H-P2ԴE:MeaCF> hV[681ʔaòhFrp(ڵk׭[,_KPN eT4l-_ s g_O.FPWTR]ϹLc)5Lwx8" 廮z.{66FR٣F+jV?c+ifeΰ-U,6IX[&V˻璉gjV_[R#Y~~eewu3*'w߬kU5|-u.jJ׭34(,1c f,>=sԨcw]S_Лgu^Ǫϒsėlc/kKiQV`T0q;qb…E ޾tIkmSYy-]!x, kS`zZ:#[V"-J~+Wi2WeKa؀H K2>~7+K/O3&}„jцš#XgzX#}!TzlX}&<`Μө~!`~:~(Ӓ?9lZne@vy4$dg^;{,5o9*UxmjK!n6~sK,9v2((Ԓ]WT还)2\3y;D2%^ԩS9VZ */,Ւ8rdowj|Vb 5~kۆ;wu`zh,??s D# y 2?STu.p<*Fve)KF3*rD gJˑZ,E|S#"b<m|S@psBV+V OZUx;***d,ЊD_݇5;T%3ER>fkJ6[4_/ȇIU*NUNL2IE$LL&&3*3L)B"֖}i7hlY7D"<}n@\PL)VÅ{.99\'Žu+yoGoH;ha(5YI!x&MU&[ o|Γom;;|ᅦo 54 c'MKվDK npi(By~㴲[k Cl='KHːhK1byg0!\]] c wAQ|;]<ӧ'OOh@MTĤ8XK-ey%wl/oeG @kӖoe9}),e , EEEB1÷yjHܱi;v5~+tpFt".40<JA7d<蜜.I¸BO_)Gl ܼ9 Ҟ=#߼rxGt4 wQkZ/I;R~6Ģѐy n쬐U|LrCzM\nR1_>[4MNL-YYYd̓CuC&XB[GgeYL&[,f'j=l]].Ǯf+D>90:}[(rXr͊2 b ´4nyLFNv<~ފ>8I^>r!0r"왎֘zU:^J3E3ZQ ؇Ao#ԭYCXv"'r_HtFF>3 &L99? j~㡃DCo>~5,3>Sj4ZmNts?£|+.#㷸|'fs~~nJJJqq1<1NUCm^^޳j˜yt]4́i <|$g{z-悂&hS(s+"X*^X,ͲD|VK"1j j$p &ܿs:-6Oȟ9}{cށ ˩S- nMJgfGG[ZZ q J7ǼX; 5-,7_A2԰Ppv8 ƥ_tl# -6'h $od^yꇅ`G/E_cSOiՀnkxx'NK7GERR A8 j%nYp yL5^qW^y^i.Pm!M bv,oӓ)-|C/{"Px+C̐hk%\!@3)77ז?1#TWGoJ5""wV0}mذa֭;<888m~,h999"d28ܵ {U}|*//cKpEHD[N;NK˃TPpgqO' 4y,pѣG!`/|EC7+o ok I4|3ghZkt*[v~*oJ(( DwDFvtt$Gq7%TUU亂[H7[\\ з3.f0x g}k.|2G[~CC7._MJQ'00J@pI`àF>ZO3cc氰(+!:KחfA1Ĺ"??,$EWVЬ@iwFǝ튍MLj{Rzff Ƅ!zAșTCluNɤ&7n:D ,;j ?? h4wOcc:OU^QT|OG'_ai,<BO@WCK'm c/@owv&${!ˎ@V;'gd->>-twwwYXX,N0hkgRESKѸa1}нgϞ>믿WoŒ⁠oE4N$L \Hwԩ$* 4R.h[BB'$:9ٮ̞^D񵠻tCCyʓjs#gɰ,;PoZ <àN;r¥DXgn.9ydBBBqq1T7F&! vX|j۹sԾ̞ܬ]vN/Zj+utBl|HV K|-_v yA[w ۲e 8b"s`hE%b! 8 I4<'N@J?:{M+X[[V۝ҟiN͖ϷtkkYAw^q:iM^:5LYY}P5MߓKB`7mRHP9s! ezk3[A;v DYho|emFX+K^ggvή~]^nMNIM-+.)q;[#)*MKLd \{α3ҙb&n݊ap ?u G$0+6C+x2'+H)JTC]BW۳yyj[nn^]T;AzMpSŪV&)IԚIc8@w|,K.\;wK_~%&t b_~y߾}6EѨτ`.D3dw!11D鹹z'HezTPTxA]%+.KD+*Ẻ W>!6atSeI(caY7Kxrss?W_}uƍ_o(Uĝh1DI@=8tsk_q,*%{ynjJyrCKJ쥥㫦fpCH}}_Q!!$??7''++ =t#8Hm/)8bcdlh |3gݻhܔO@ e ~\A􀄶6.** Q3l 9)Dz,](t0TZ:6?\V6\Y9TU KRCÕQ¬Wbggnd.:fh&18Qa+n]n 0^eR̨ ,C!` :~8ﴴ4% }H=J*uʛmm 8d2 54 Wڮut67rt %t5 vDbB\i ָvWl(cdm( WE\\\\XZ-T^^ Q=`4^8oj2hK顡ݽuuҼO5550,L{DP "n"%'8c ?Y0 0Щ.r)гfB2FkkG/AqVhkzcoIHMssP.A ajii0|f`R@9nr%4b/hDòf ^ hQߔ]RR3ea\Pr + ຣ Ho#7\0UR!,Z'"A^7bt181!rPP#aF/ U={Qx=p O Q$S7~Rz{)|+>  ׫v;膯< K:4Q_i,3.gSG.&ƠP&P)ذˠXD A)RSJ[DPVvkI%cvwoݺ;qE[{EE^ΆMLLX{qP i7A`'UEHi!"4V$W+ai~5,ɖu=6(v?=vukddڵsSwn2:} J ҹ@Ac")G-%‘ -Ġx 4l ,P`V :qkJXp{wq]FE U^1 АJa?y*|TkxJT P9Dk)y@'}xxxxxxx& endstream endobj 199 0 obj <> stream x0 DQPE^JO5wȁ.$s. 병 r㽕<餐559q|U81f39&1$$"Ԙ#*8ewc' 2CJc9FY-|`'.#E$ z#6BT✑KR $ #۷'@CuG6R7mlmdld#&v}f#&1وI8BYl$`7J6b i#&! 64&1* %M_M#Mb#; t)kj $Hi#9OC8@߱@`$( N>JɭSFH |dXS(b)B)H̹KLL5[ΛxEɶ`.Q_ h!1iioΗFjs9䘳 endstream endobj 200 0 obj <> stream x hx endstream endobj 201 0 obj <> stream xeW`wwwwwWF,?q19ɉPsW&k:|'.\9!>;9"ډ< ! }u~H(LJG""C$lgxNnGS :P>T* B QAjfkp 2T Ni;_a,{ @`b JxvV Fd6[ Vfb`fd4 zVR!GXu4?Y* FbNz}~?P( c0~].nZ&#؀q^ܳ~70$j @Lf  CH4O$T:fs\>/ E6c>l&NRD<8YFN˺ET48c7|He@Pb/ Gbd* RRFlZvtF^U+RXe3d"~/ХjT 9LQ~ @(ވ/B8 rVo4[Nhp.ǣp0zNlԪR1ˤH8¼,&NÒ$(vL1*XlD:GH @x|X.Wzސܽ Ypr\,onըW0L2 |݊*؁Lj?_"c:\@(OeR7` k|v{yd*2/||~;G~j*B6E0*PpCOH"Wj`2/R)h2%52>3ɗC9N8lA\AXr!NDC~f1 ~rL$UZӹbCA 0X_~ Hb#2tR>դX{DŽiP,-V- XKHw>[<#.`kAݬ z]6I*10G,Sj 'IZMfsRN?@!Ű`N^Q-Ri5Trϻwpt&M$)Tސ`+/BޓAU+R0'ŠQHE]xZoqBqh8=΅X ^&f*tl6`u|4cL1 Q Lfc Hr&T^ۍHzJk0]ld84i&BuDiTK?5L ͠aL :''Qlf;9i3wوۤHV_ݮfnn9ղaQ)9z1̞x5opA^`DR̩Ys#Ål埏~Ÿ ~1&<K-nq}l`ϭF(@|+z%|yXIq ]J='͌߬4X;D{8@D{8@D{8@D{8@D{8@D{8@D{8@D{8@D{8@D{8@D{8@D{8@ў@xhwYVF)sY ʞsjRn0'=a-'`5Y?ѺOywe"ɗg^+v 4+ugz-i52J̻؁Kd f^qn)6>0cd=#10 4V'hT;]mz(a36QAq8y zG(SMw>0OU{J+v'3j6h>V&ؿvonDerӕFh&F^tr!ﴱˡRL if lkOFv"@2l=.}emiS!Ex) $WVӨtZ]Sk1èaw_$טhX &sRLGQ;Ԛ-R"|ÈnRJMjxXג}PIHj&LZcHGRJ382}j߄DJQUcZ;m 4aQa8)V]bl~M++d ߮辪w2R%$)_<4I"S -^DM:9lCb>w]\'t9jLԄn0}{龎U*WV')0L,ݱNXⴺmFVĴb6 vAĒYw̒_Kj09 cKK{$k$+peԸO'hH:;L{;cy{(C VHB- Eb)i9\W*}r4҃z~jz!<:b鴱^VʥB>3akN {"d~G+% *RbÑh,L3l._(R\T**:Ij5KrT* ȤSD< ~%0r=5Pjǂiˀ0t{>?Bp$bxr:6dm1ǨjϒKPL4bp8.x$%p6Ղ jȈ)d.G0ov!@J5Vtz`0OYpQQTb̄Hp* XT,E`(Cqb"!q.]Od& 9Pq! e@#8 Dpf\Gq+\|lw9Z?q׹89'>??O endstream endobj 202 0 obj <> stream xàS_U endstream endobj 203 0 obj <> stream xZrJ5ńDs )u{H]^?kJ]e 3a?~|7}7}7=%m6 Sc vc}$d8~'ln}*8 Ɋ RTxߤf;HeI{HgUM  c5v=?|ϱtUY9DuQim`9Y^w!`9('ۏ,"8u@,?,ruY_y&KjxIٶMښ!%SM/0@Yƾ28u!F֝(/" hfzi=/SWF V栚~ZVUeO#ix^ ϐ6Feu]&$eCt\6gph#ຮ"5y:At;~:_S_%.^6j,4n\vt>.ѐ~0U"d2+ȚI4sz|<0,X '<R3{D8ɀ4 VOft 6sٴ?){4M=3yYSk2)~s~+BS}(ItrsV8m]70]?~8PPWEL ɲ,/*OF~ج<P(|.ʺi/<$%iݟQsH, ()~"6 909A3$JIg(nyQ.?|@q?vzim>kro.wtZQٓ+&FAŋ cV\rEsotMf%U7LC;LP, Bx-yчgnLr_uLM>rf""JT/{>* 4$Eq ݎoU}sA.Dd`9?84"hHR:p:6mIAwag3G9J8m_FRiB .p}#,$c̒ dL-0>X L˞ P#[BL<#40epWD110|oMytl3l3dXE]KIYI+'}fgRm%o;Ӂk~Jz)tcIfX.ߔ eU:VOQC$-Sfy~,sl -]݋~bpz_~UyZ T^nw}/}YeO7wt5} oz"g endstream endobj 204 0 obj <> endobj 205 0 obj <> endobj 206 0 obj <> endobj 207 0 obj <> endobj 208 0 obj <> endobj 209 0 obj <>>> endobj 210 0 obj <> stream x  Om7! endstream endobj 211 0 obj <> stream xkSPqɥ4Ljcb]]fcږ~/5 }<_û(}g me1#r-MLiZ8a,Br0hLC, $d'IafM8"䚢)SUUI&HF6"ƕLVvHNӲ 5!F,P 'S|A׋D3qn~\1*F|lQ]͉7v u4I4kחe}o3!pp8!;5口9 /*|]UuU%r"-Tj7tgZJqdU ٶlGtiW;NzXvndw:KVxo8888888888888888gN?ZǶ:M5UN~}U34 su(99z8z*)`8~S)m 79(@sk9@9CY.Zq(Z(hr4YW3|Up&4 MOK494qfkHshsirz'~nf(Yϳ5Oq$U+\xA?ۂymָ^"Scl>?=\8fr|q9\,4ͻ۫jxÿ;jpk0_?O{ Mȭ^6/^fSYçkB^Fi uU^q+'cAحe!14P4{}e[ʒ(,E8v"핦qE":s5!iDA4ܱo/L2 endstream endobj 212 0 obj <> endobj 213 0 obj <> endobj 214 0 obj <> endobj 215 0 obj <> endobj 216 0 obj <> endobj 217 0 obj <>>> endobj 218 0 obj <> endobj 219 0 obj <> endobj 220 0 obj <> endobj 221 0 obj <>>> endobj 222 0 obj <> stream x  Om7c@; endstream endobj 223 0 obj <> stream x1 Om_ i endstream endobj 224 0 obj <> stream x1 Oi  endstream endobj 225 0 obj <> stream x jR endstream endobj 226 0 obj <> endobj 227 0 obj [ 228 0 R] endobj 228 0 obj <> endobj 229 0 obj <> endobj 230 0 obj <> endobj 231 0 obj <> endobj 232 0 obj <> endobj 233 0 obj <> endobj 234 0 obj <> endobj 235 0 obj <> stream xàSUz! endstream endobj 236 0 obj <> stream x1 Oi ~ endstream endobj 237 0 obj <> stream x  OmBW endstream endobj 238 0 obj <> stream x nH@pg endstream endobj 239 0 obj <> stream x1 Om 8v_ endstream endobj 240 0 obj <> stream xàS_U'u endstream endobj 241 0 obj <> stream x;ks7U0ɭp4x\$6ޥNm"-N"}h09qrLt7~sb\t/nqsZVί7~>zoyuquY3!e-|匪5vTE49kuxq{Qu돀V5t+ki+}-ggMu^=;{7?W%`oMVB lZ7]5kZ}[ypw0.Lw95Lgz`CtOn}uꟶT٨Ztp76f]%8c7.z{7T?LC?X]lxd =o1M_oBfx ;9|fQs Q0} ;DklōOE[J{*Bz+W]mݺ pf3̘8df]S;_ܢL@?aWiZcvs\- Y3"xB Z`"WJaœNE{n:ƛWUsb}[MV٫i, 0r`Т +Q6fhD`oCXݗo vt; WM>Mg~3s% @j-N80u>[U72 ܅0QѶzCIA` ϊ@4s}Լ4{h:2pБx"-mjci0CDRy}J \PKJfx:(IDЌ:D9_I|sM[dKI8kw%j o?B H%!Jqlz&ć=V1F IHܰ-!hmх˿4A>dW=xwŗ0 ņz)W7oKinVYLA@"_1&Z]qաۀ o!ӆ~)rg=-4_v$N4#^#&B>f 1B.u2e٤c}z5cc 0B*2;zvJeB9KYYs@g`D4A@=.\lT?7C|b.> z)k 2I:tE.Z)du IP&khux1mU z硔|v<<yJC.0aѱgOSLrzݡ`='*yI:$1#\VK`8Dw61`csԊS[d mu _JыLyrZmhkόA-\;J-LݷC5Y1ҵPHW bBb[.\TWH}8.M-}N^vmͲ_1)]~_ƿs\x 4Ͽ3G\1Q%uu{ ,zq|Ss&[~wYm&?^}^精ץ'+٤`Na?h[Y>dU_V?{7lSǙ8B`2q-&V\˭!=RyXBMO n,^ɀB+&_k9U`fs֞|J#1g \Pޅ*M1':rbgzB^LamNVտj*LP6dm [mhMAO>=)H$YA {uU^ v&Ugq~Q#x#jsX"&nw|Ѫ#Zk?!N+QtjkT3vOtZ=A> SЀ[\jPݑaCDm++ںm~|QHـ5-2n) c5)ZU㰓Sqƾt"dFgc+"]sh K),ĴԞ~w*|&.&PW  lnkVڻ3}mFjEU63a|m%ԊXiӎ88 )ax4C.DZJ8n<w gi# fayxq*D?R"Ȱ 4D)*;n77?eC?k</vaUEJ޵;:3|AΔ/8? ܴCג- =|YÏx0v9"BAq SXBNE-׍|Vh~RB&<;a<40^@:FsJ}]m KBg|'tQ`b$HEbzAdX=cjl!r6 eq$0'y<SE!p qI<"11:%&> stream x1 Omo7 endstream endobj 243 0 obj <> stream x1 Om / endstream endobj 244 0 obj <> stream xytUCd*"-XQ".A_۵ZTlE*"ڊU!L2H $ !!!2HePAphZ:Tw>ι7pG?\ϳ9B!B!дiUj?QQ#IFNb-V>O6mMRSdֿ%:<u6>L4 %bU?qC)F!j¼y5g؟a~iNdffp n)Sp,F&:EAV{4w mbjjjZZƍO>_!'O>䓃ӧOB8uT{w}7U*1qd2&+~Ϯa1w$3&=zXc!*H>DDO?4gZr֯_|&!&ڵ믿~)|>B࣏>*))]|9s&MO$SL 6?/c}օ('|o߾$6`Νx|ͿoQ+2ٳg˖-֭[lLDv x0 .h\Eýz#G>߿ȑ#ǏC8"ϐ481&L0& 1}Fz^ziŊW۷o߻wԂ8cx?ll:Jw9ꫯ|~ 4-3nM|ᇑaW$0q֬Y-\f dܴidܱcB^ }?vB4q|ɿ<>MڵktC}Uu>S# 5D2𡷌#=>"b@FDD7qС4l*Ucl bd8U ǿBpLD)!LN'2~BDD:p[o! E"&nڴ &"|a]OCQ%N"$O\|T7&LѤJ&2;goOUCƯ jbMML1bDF2~הQc" LCfSx#G8p5k,YǏo&3&DŇ~Xm$Ehqeѣ-ZTPPuVDp$wUjȈ4"d x ?nLԩ-qG>~;z?Qf̘9'''//x۶m@q(x! |83xEpIT&hhۮ=X-8pI&*ʕ+WKIjj*LLKKKOO빹EEEȽ6wѝ8qxe=zt߾}"h` gAdі:x?a„SΟ?p&nܸ]U#ݻw/Rqv QJALv oNֱc>o(,,\z5L5kM^[&y0OYGBZxqff [ [D>*-/" hxe":G?!&"b> _,<ۈVY:";^d1sf6%&"ًwqat߾Ж+ m.?OZwb+~C?vwDZ4wEL9z(A~2LA8sHm۶~뭪>GD! 3 A-M&JM7n\MDW= (bBLdv8_>}Z&&g?oݺu޽ȴ?z*p;U\\S)f"0#Z/I1;Exڹs'L^hL;vlL|뭷7qj2QD$6SqD2QDZ4Dyyy{9x =ξaddYĺqHD\9Rk nqر&.\pƌ0vbcb #㇁45!"i"bb>_KS#GMt GĒuM$Jr_&Dp;ua"ak۷o/((Xk13U.7-6U-jآ36M>|LKoW&Z &N>}̘1ݻwLLF$2Q$.Ic"c@a'O1b25LDE gDLLOO6m?裏D!]O:%2ѐgq ugΜy;w0ԉ'xOC뽈[GGtADs,[nOKK=ztL\nk"bL DLrM;"aڵk7m~mh>J W&醳 RЃD(LzKKKܘ8|f(ȏ ie>իW&?~\&"9L1cL,..ޱcKe$>%+W_}M7MN<隈׹#<_~Ŋ0qԩF' &;vL&vMtKg&K2Q "8cFIcbNNNQQY|ӧOSFqp6n4m'}-[fdd̛7oʔ)=#<"&:&Ι3'&fggoܸq۶m,y|)H"19v&>m+<2a6o޼nݺ˗D!*&:&Ν;7 ٩LKB2Q$ 2%Cxwf͚ՖӧOGvZXXuVISB1hlo 蘉2QT`"+,,GWJ^^^NNNff&<GGoBTJ&f$sGVVˑpΛ7oܹlٲeK.ŋK=,YÞ͑6qʔ)4ȢY54#D<`&2:tAqȅK}!/bZZɓ'M /1cڴi=97&>2Q`BDD:&zQF=3Pg3fرcx<ѣG9(Dy~d HY&m~ȑO<#=#Fx𞘘0 LdRwc"M|>tP)H@?y96LMM#!Q]vmaa!J(lPpp"pMDe=(999'";EN! 6 N9RS&L@ʊ#SNM@o*#1vZ(DL(qB:NrU>@կ~+"msz3g;k5أG;uY5I&$LDD<pg_dkR4bb߾}wW&.] VTI% ]%vr c0[o)))2Q x,K$6{l 9gmo. &vA& Q>D' WX|rt233WXreGVVްdǡɜ~^ Xqz BD2CD7H8222M̙3gIzz_zy) Ѡ?$;L񉙈.k x9K'رc9Cp^1n8_&Ɉ L2e LbI>%% "]8uG~GSOqhjj*<1,\:l0x7D!*Ŗ4vцGz!Na\|&.^=\^eVQH ok ~׮]ӹhZ=ÇG%Kyx(9Ǜ z>s=a~dHzAWd'N3Axf!ME1DD4iӦq1z|G " GsDĂXw}ρYfq%ĺh.]lٲ+V W&.Zhʕ,XZZ(dܘ^=泡X\\P nرB}ݻ7V6)"''ϹԂ/!CԩS'L͕g85k;V&۷ok۶lb&",[Ncy&fdděnvΝcmUu96/… a" 㐹Xr>DRq2O%/EEE}1q:uUA&&=I;޽ōqt mqnnآbkF²6Ʊ(w:3cǎ:T4 |T;Htf\tܛnxY 6իWZm9©"q:7RxbN1鮉 B?Q&V Ч^Hޟ%d ֍Q4D+E20(ѢEXTsΞ=ܜY iiiD' w7}J>x7w\`CȈl-/A44$*ƺʝm٧xr7?~8%{:7=zȑ#T&h’e>{Lw|Ÿ`O242<""Q4_:u-Yʦj5 O=ԓO>9#$3?qVʆ*OIMBvlt%scV!ftq p,5Zx; (Y!l}b{VG؜C `SW6dQ'< u|=;d ЏĒ!Y>Ɏ`Ml\(ړ=p2DcPcÇp6+3\[s숭mi*+Ldv*{i/}nw/TMzğ!dKݐRpct& 'WLSE qgVI=w^unј)R2!TtKċ\2kx'+j+#(gQ;9h,w ۜ_2KyA;)E8>9}=lvІpol&;wPKJǬ'Ifcr%Hp ˚B\e\(TžsJ6 1cC$lҮ0]y׿U5?G8v\i棫j2%<}ZɕA|C,ka"4xN񙈿L6} X}\0 {!_yq C(&ay&3!C/WGAވ} 2`_s5Yq(19GLDgyUR YCC卷>>-«9hĉsNddw}=D4}qxӗv"8#_=-[ƺ#|YX]u47PHCӐT6=_sW/us3O>o <9vl!DډFZ`zn *Ռg4퐫fWgsӽJ\ITu _ފ?*XT>=2w;e/eeenS\`/>}6̓C.x3g>K;d">}j*Kd4͢R\, кƬ'xrJj ][-ZY]0eKlX>$V^_R:wf!O.g.iL|8/bnm۶nPTj"QfnzWRz6d *B/Nwճ]d"E̓=nCc}v/xFm <>`o9-Hn:suH=MWOJ% S#8†,ӭ$ ;_xه(FXB1w}xg8B4Zc qƱn8)D:#+IMZʮ|PWR>g+Wi>^!;7k`U[?<ˈ8nj c]|Ϝ9߿6mbXD 6?68+,xι4Ԋ&^n_Kabaqo9sޱ>xŁ[!eϖ>xa9ydj`ɾ3`a/ *3^$H>=/4Kɸv̽7#)0S%//6~;`%#z݊Yȳ tտ9,>xշo_&"A:p䜕 Ѕchsi(Wʰ~rݲ<-ꋭ|¾ mVKw[vsKFܥ_>[{>|>k1Kmݖ bk"t\1ʁHӓ)(v!Pw()+!<2mJa^-ºo|,q&n? E8V*dzGdqQݧy{;߈CK]Z."MGfV+'s]qf\nT*@)'!35O~Ѵ4ʕաeY?Z_em*dVu8W3q./r$ׯ}Ê .hҤIϞ={=<ȉ1tXqCژ1F)A#D'VBi~/XGjߐG-fs# onKxq^xa߾} -[<)ŽW[T|-:$SYJF!G0MFNdk5F3 {Jx + 6G/A'F~h (cqohVU'{m8b.+Xǐ@.<a@m\͆X".rL^a !ޡ׮]XM `hݯ 2q R1O(\uCf;20{x1z/VH/ X exAlĞw}!淈P_{_=܃vACN5`[`mVrp'جΉe2"!2"}[o8~F{nϖ]ѦM^|@СGP+{.v@iCr6{Gfb}BČ:uuYu=X^;~i9(tE͛lٲUV\r rRRRX9LK/6G3[h79S%DƌV ?|֤IĻ֭[C:\ѥK]^uUݺu!á{Q.|);y۵ka*?8HOAb\e\.24o4u|;߹kz,=rwj @ ߎS+؊`Ï_@qt 6DDѹsgzьyQW{|/w\pCHCk>>^wo'Hr#E?A"@:#dVi!C@kDseݻw>}n>Agw>UO}+3 GGŶ8l7qᅘ !k۶-R2t֋FX7,fH=3ԧj X_sճut y > "&~1&+E@ڭ‘.$Qҍ+K ˓4|? |b.H$RRR.a%:cE} d:FG';'<- Lb/"$0uhՖ}5ڞ 42XJXXٰaCe٩ۍ&5ԶJ}pGW\q͚5C><áQg!p{aضm6ikݺuc(D Zep(mX+#w[liWC^QnsUO 9̝"O9xW_}/`yYD2@Lmgg֭l߾}f+zDV",ݻwLN:k.V*V&.4źʼnJ^E+vze͛7jHV&0yWsH ].] V_٪U /~h]Cy|K$Jʔ6m \"511㊺u6mڴыD `СC֭+aƺps'袋"Zs_qEh 7nРO4VaJqХ,WfG_r% n<">"s~yh;wf<C܄V"y< 0I&=(8ù2TfJJ[ʲy殡o$.t PF!*s(~R<:xk׮u0e˖=lF`+Ug3¶F D*g8=eih֣MtK/@4EHI0?Sz,:о,*:XU5Ӂ e"Ҕg\ܢE5y~L 0MP6lD2 ټy??nU ؠAKlÍ7NP926"aLiԨQzbVըS9ăw"qУaÆ jbc(D˜%tq Ȱr2 P/1/Y>BߪUp"xݺuB$%`b Hd;6llW58b^R$>Bw||>7yB$2kܤ^z58ÉC^^"楕O 'CQסPo.d!bk7(2QOE?b}&)h$nB8H!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!H w endstream endobj 245 0 obj <> stream xip[u b$E$N"H"Z(k_͖dZ(LgƖ$SvҤ;$qӤ̴S'N&M[܇\d "x͹{y= Ne_daj7l5`r@~Ko5wzk !o5"Yw漤V19\T9TEBi օo_l+= O[<mgŨ$meٝіRmg *w&mkK-?m CۖhG[ڒLhKlydm1,kk=l$~p/^r d<ܚtwwwuu6VZ>oE[懻;].W+CKsc]U3Ѭ}30 ,/)p،*)voa ??HGk`"̻JSSR IvI _]9qXD)hk UvQQՑR!}e̗%TpT*E"!$-8J& 7|>Zhe*Q@^XhˇXw% A[&\]ԡj7oݺusO?O>m-Ϗg.<9{b|@ԙ`RIhkY{{z: m- vRKCVwG(;٢ֲj*+J RL".ZҢlә` Za[I nZp Sh4uH| mb3*BˤR`!mmp@I%b@$4 Ҷl%'#a(JE|.і$z5th{ĘHGx/|ڵks333{ܻyxxxhpd8+ޤT>>gwwwy mЏ~cS ҷ4ٽz&Vd&W955Hb Rܧz.JJJ r3mQB?uoև?gD#$b;e%>/777'';VYY i)V&b5zuShM0 "PTZ ar$='%%&&$n#:֤W+V^Cc[w!+SgDSKJd{ ?7Ǚ ~8B裣M(X==j#54uco?=E<67O%JHiɠ ?tZ sFR)f L* ~U֝_zfLz&J rHCLXY, FvBc}DOW B,\_#0xJKMJpSAժ#݊d d,ϡWXkޝ?(QՕP9 iN8+h2tu8Ic#ˮ1zu^^b ry]MU9BwfQvƓ83H"<||!>[um[w7|MuDTzr#b2OJ2$bHl-0~xq[i-n!(?'kCj2D9HD)#ddMl(=B;Ak=]]`|yY)R1QxRGGAk?^!7UUB>Sh^V2xZSEc޽_zdL̾t(=3)(mSƺʲ\')+ĔNٜTL-yB[@ܹE>0K$"v{ &bK~t?~viW/|%SiqLTș382mlAݏ>h=ݙݯ?5P[BOdt0%ylhCp¸BƜ]V=:~wyȚݻs}@d2Legz*dк3:Ӥ+L޾ɳQ֍_|u^Rz67ғ1E.~VɠTM'l% -YTYj808yd|ܷ~Oo##C*J؂ LI)åTɵ1TgAIEu]Cs+?in:11{ϡ Ͼqv߽Kzc6WmDTTP''Ϥ'ۘ`|  ̜W{WwOac[OLNNm۾cΝ:w_~7zgy_zMܹcmS[F6mgmeyqA;L.@PyUm'/DY3 Jʫj1b]{8|>u…gk>}đgL22m.RW'$mUD-/HҙĔ Y9DX X`hdbzSg:w.]rիW-`vKxSgNݿ{jdSw{+uX%S $vu$[-/[:?V;=:VቈXJNwW7un:sz3=>rرǏ=yp 멓'ggO?~#:x`33{޹m`wCY^$,{9t0 jHvIփ1% WhMGrfAymKGb819}ӻvsD |?of={v$[Ƿoko,LȞci5}Jc|^0W[[ԼWgƁMCf`dt`Σ#F`2= ۶MMMNN@?;::y|ƞd{lLGV:{B̻h3A|dScm10Ac>7,_lj-c3ɧ x>$; &rLIv{+ *Rg@}g n}`[b~>\Sgv-#A2'zC,VgWbz畸Ϸ-TSH/^D9B`1#S;s1]~Gd]$1{NvXcAm־2_^r5Ֆb`J$T??c+/-MYI6ra^!w} #=>TI MkEhjj(pXLs+EFl)ʒX)]Y흑H|-8|]s[5uCMEIvŦ}֘I#X%v^QU]TTW8Qz0%™-OyĶ**'ԯQ:ۘs+cŒH-zIVD\YyEPBGPHkDʴ=mb_i|oFز+%E4ݝgR!@)X?>͇߽ŗ[Kr@3#FL+.Ө잙2Y!Ӎ+7'47ozl,EOaa~^NVzÄj46ͧ,h$kU"b yά )hHf~x&6bzux朜\*~ 't 2m:n N$y)h3{$w$9lh}qߜreqc˔a f86klL4NO0>aR;$^m>-iTFƆLj79qVb1ǘQZ+2?.$ [-!%%5H<[P"Z[XJ$Ī8\%fbkUb`Kg%⢕w+TYPjR&PͱA&ɨV{s1!>g;ǽa%2L 2:gL-_f0C gO]~N)r.+-TцH%!g7 Wz갏-:\B-XD\"k JY#o+<ŗ> stream x1 Omox h endstream endobj 247 0 obj <> stream x钢J۶PQTDpC }ynVA:=w隨;"ά*"8@EOzXGxdC^'tK;>  %N ,FáIzh<ɧ|2B|.H\@lALe$GBt"?O\H hhYLF$7 jkj1N@}>F`d&ԍNZ > AWd{<R&|o*{ IG_(&Zמ-S{֕E\_ OFw4[mbdVsH$xֻv=FIDCC1PWd;8,`Zlq ͺ,&P_ *&.T[ls8_.v1lW )5V7CUsp=^WqO/C/9or-Xo*nmɬڲ[K(Qx6В$ĒfZx헶Y+@3{>lv)tp<u{~9l3/B56Ӟ^R1t |cbʹQSFPΑd֝Bza[Ͳtvd><#\Fz-,jivA̦况<@f%bC'__=8\l (d!ߍK~>e!.Xp4Bj6qhrRl"8  ԑZ>4Jjr=GFCr'>X%6|9ܮ ~vXga&,QaA"~ޫa?uGT1'QxQ^n ϻm!Ѡo;T8#T(&[6ݎ[ axt9Zvjݬ"UJ(6@i L\+Ky)/+Ky)/+Ky)/+Ky)/+Ky)/+Ky)/+Ky)//UÖypw6+s0;S8:"o^-{5lOG{}ڞlOد,g(hpX B yO*[L]?ҝzr\ /uZԍ!y`lys\*6#ƄRc<׬xsB4圀OOabLvӊ oY̰GvawU9+$ofZ3_j˱l> stream x1 Om  / endstream endobj 249 0 obj <> stream xYnF#Ov,i;m\E>Iy;3ogF[iï6?|[GJQp8(^.)OiZi':Uۿ -r:sg&`EFNzZx( C=p|''϶1%YdIpjxGHoK7:q^DU %(njhܳeۊ/羴|%Ev@6UF`%NJ%ӕk\w]S&!wä?t,+aiO$fUqI$M$}^E . ,wDqO8-aǶL#d9% <>Zcj#5L3IUUUNLEY׋"HPJ2S⩦oeh$>_]DEŭib9qK~kB9M'eռ0D>m۶mQPĘ¢kg2> stream x  Oml endstream endobj 251 0 obj <> stream x1 Om . endstream endobj 252 0 obj <> stream xS6$A1DTE ·t<]o:wknu՛"Z@Ew08`[;ںYjOx=JޟO{=~sxyy""""""")2MVSZzRzfR*SʊGfDJpW}fO?8iߡgdx|Y63[ Sּ#_&"sr$J` {;,'%JH)kw:>ՖkaR?u7 /w}X"S_P+PFHRl#g♀fK[\yvA EcWj2D;jh ;zcW1Dg(zywspcWP|_v͓x~`AcSm2v}^"SWPWyUku_X:6X!K+zsU>oAOo%ҿxV)VZ|c7_}^"[drF?O~HW4L+rlwP.WOH?; 翘;Ϫ"+~\9 4NbڷUS[-HX~+{ ,S0w<]a-Q뺂[gO>]CJ VX7zfζ(aOà'42K EG:b/$g6 9hX?9@t9W9@| + Apkr*ȁ++Ws +W} ʻ 9@|ȁ+w ȁVp \a3X ,{Y4 V@а)@+a9$c3+9O۸  J' lyQ  >˝@F ƀeM ?7%=Sx1`ruoȚ_ 6+hW0\RYjڧw7[,gp%!XsIzbI[)ٞYgƯHbDV3k!+ 2VZqrzYI׽4q"jQד}d"3g)9 m5O}d"KZ#Jp8^V9FHLu?U+(>|2%f.ɜp+\ {_DKU‹+>ґVPhall~tvkw-F(Qs 6yYFsReNI5DM}FH^UMBݍC%ovlzpSϦrx;@DDDDDDDDDDDDDDDDDDDDD˽pMX endstream endobj 253 0 obj <> stream x_L[UpBi20 =11'dh⃉4&Afb2q/lgJoJi>w?9=9WU@ (Y-%vb,OŭkoMIk#F6^zc}C]OŃaxNq~0 0*w>h 0k{ۏǓFe0r\&Y: 쮦lZ9 8_ $>NQjKI08AL R=<58K,^=g2gvͅt~?ɤv=AI뿭 6M rZ*P$g6ĮW `0 G- `badҷŭaT<]G7D6H9<5͏EH.#OH|{D(L͉ؿ/^q@8; #ylzs~6uF@f鈗%CH^`}K* X{ #@zOSX@FUQH89W (u%U8zg%U8                                  dH!/pGp?!Wt"( {[/(wk7@ֳvdkt5yK :??rtýߕ5řv޶RJ ٧3OMG#]^A#@.wݛg:C^*CSSSc'Á3JPfw;64:662ޔ??##P* w0vBEH] ocH#䫱Y`К`S(t9>Z*-@c8e7i,B\56ŨS+P` p+VQe$i-`{~<||D&^zx endstream endobj 254 0 obj <> stream x1 Om ? endstream endobj 255 0 obj <> stream xgW:/$8ͩNW'IV`r9݃>XIabb_uYqp5T4d2M&.1XVˍD de{,6rڭ7ʧ?2j6e؜nl}|D QsZ͔16[ }nP$|!xbɣ0{x!+d4qX߃& 2Z(BE@AZ]XTo5k%tc5A![iA y7t11<|ƃv5z.&(VkbsPdRZNzpی &TSi+oWF.8h>\W>`rD =P~1Yɇn=픒f07ADUs*&vo8]/U١מM:@ؙ*~>įThM{lR"hbJU\l | /^2a^1A>Ylzk+ES7hs?ͤro7bLuUa4LR|"3睂ʛL \|LZyO.Zv(= 3ͤrt _7'0i4}ea&\kzY_I3T0iKNa$pF9_D|."ACPqB|Ǿ6h9LmcדV1VXqJ_l;Uy*ÔD l6;4PB*cqJ?NG) +Ttlælcsbb=\O-;Jі v{Ă^\awj!ZVofDMP찛>l4S2۹h:p1ay:}o-Wؘi1ߨvMׯ_ke| WBL@ocB1!ŘbLH1&R )ƄcB1!ŘbLH1&R )ƄcB1!ŘbLH1&Rfk# wn)fQ>gRF5D=DRPSwQ~ޠVC*z\mN-:o1;n)T聯 ? 6t.6)N[ ]=UbM7*a3Fu1}LpƭBf ӛ:^Q4Tzr{P1^b?;:{ ZnԳhL 6j-gZ {t|"_뎦Q-Gi+W=C[/d4;V5G뺓:f%JkҹRM9`_OZP"[,iAoil TRݴa|X" x U'..AY\Ӹқٺ=ne}[;9\6_+j endstream endobj 256 0 obj <> stream x1 Om Oo endstream endobj 257 0 obj <> stream x[vH"H ,o6NL`0]////j_J哓wCoWO>Rߝn?כf~|\yx\[jt,Ynn('vLodp{ߍ"`:kjqw,k3v;)eE]G۶1Q`gѲZqO%,aQ ]e繎-,Ő=b>1t? }pB7[(BsdF(N8 _Q֞}>-I`Ȼ&I8~(I9Ye)F}=PlEQ`0$1Wy\Y,b߱,ۋ &܈F[VdyY5 tZAy}O`% 74^u]?\F ok1 σQx,-7 Hxf, L=̵Z|tn4O0u ѪU*rBъ);aVjI4x{ bx1'8.Fa5!Y0ZODlB%TuӋr()p?.o%w(鞀hXb/TPTN"(vX#}SĞ[/qzP:AVus»T1W-@8*d2X8`4#]/)?):%E#^{ӭn!L,\\A+jxj`n0-EK]"}J(~K*=C3S#sЋ۳קqS2 Yr3QQ c jM$cP6 V%YVҗ{XjMBH"x@˥_ ".-'de{sK6JOkƋs$ܴ@QPLVH 80FdJ2 NӘu1QQ2; zH@2B[ "Yd@> m`j݇wқ@C1 vj v]_Й+2,#,][M-ڑfþy ROGrޏ+ؒ2Gaٛ1/Fh쩲(,ۨ*ҙdZ٨x6A7o.xޭIndstcp(ȷڅ ު駽]avdA?P \O;ͣ>G?9~8"Mm_i4$- Gc)=9pz~wbxDOɻX=5k%gF_鯁rawYzkv0kpY/r<_M7@[9ˆ!DB]lhzr4.P4=}ԳmC߶myzyy ҿjƉHm%;+B2iy25l]Ks4 YB>z _ )7ڡEybn8br^ [`jڿGlQXnعH(.p@㧣# `]'

y(B̍0_/TƄ%Gx)@q(2\+q{;ю7)kwM8z|8ق;kIx:Y;5M$}"sbCeC-SOJzT29{Ǵ5mmL)/%h67Vvr+oϘiN~N?Yrvo}z>so6}|?DMK}KKĉp endstream endobj 258 0 obj <> stream xàS_UpI endstream endobj 259 0 obj <> stream x1 Om ?0 endstream endobj 260 0 obj <> stream xSuqc; _pT/8~.(ܤ4aɗY`wj!2Me7Wg"eE2eZQYQrX܇qigyfDDDDDDD2@`^iHN3R fˊ$ޗ"2[2l޶[^Wh4};f0,֗7m9CwXl1S&Qd߶̂|RɤMْviiL}Yy.-a/KӭuDϔYb4+QsV>KځvuJ0G;zߗ(^tN7{yKlO}!G"%} ։} rngA$aܢ7ˏMVU~ҮeǦ]NguK`w85`aoʞKYAq퀻mtUOzߗ(-gp׊k,9Q?,Yk{r>yҮU VPwG'W1 WZ׹T'Vqeh@5k˞ԕX'`JNYٿkAARښ-]7^`Wό*9[TjS/{;TD ԼG:Z綫mW֋wBNЮ@[b+~WNM@|Ceݟ]zWsG\+B`L݂O ܏ 3T߉/x[+=$in ޖ=/N-zHq_A`Q7cK^37i8G= $@ *OOW7I :=q+=rmѓ@аGR#_׾a}6YvƢǀu}%*ZyjZa3W;At9{or^ۀ4@+Lr` Nȁ+Hϩ: V@|' +Al9`uo9@  a_r`Lr_)@V% 4 @+8  + or`+W`X t}ȁVp ^A > >ar_rаkXar^A鑏9hXGX 읇?ar` ȁ^AIU@` %+4 t\ar[ɚx Vy;.r_Ae@V. VsฆL(_W6 H x.˝;^aLfuX\PӯXs/+,;J`8lpuuhmVF k^ݾݖV&ڄ[AK8JY="Q|&+ bDs+G^+ bD xYɘɚƢT\w|,sQ^ L )[Q(zz_(%-r6 hND.ɘ )97}]dNXwGSW}Yd4S7nmr',Q2L6U;|\͡=B~" SOd/S欫gZTMDDDDDDDDDDDDDDDDDDDDD1f endstream endobj 261 0 obj <> stream xK[gpIr̉Ikhj5V:`fel vы`EFa.``c`ެt0v!fZ[ּkNLe/xͣ;ѵU]3_/p,p3TYONSVّ@fՠQ+~e/퉄gMUӑpKQ^6zZUxEYy='c5DM jmnp9QgglŤVzڝ7MNbVX(@j5/U$p窥 zRai5jBWt7oj|VPdHG;̔o?4FNKYT'H;MzT><rOſ2[3*mTZ#^t_[^@7#o}ҙ`cҩBH_ ]T2n8OOLw=u 69 쑨WO# igs  mJS{Iv}`[[SϘJ<<#5J} mcv6In %Fg0(*BձaO=?GNg H7 endstream endobj 262 0 obj <> stream x]mǑ.@a>;6= ȫ:"@jZm%(ʾ{3MreLJ C_j&϶]vM/ox[/vwe꿟>QZUWyg杩L涩.>o'q\+㬌<<}rym7iZU]7՛O}۳jͿ?};MWJooh꼦Woߞ/VOn]3w̝}?;g/}=]xL0腾7DjGյ[Wgʝt!0\ 1k)p;~_WW3eady,?vsG׵}&TePW+j.=Rˆ.y%fǔ_&^'Ojnx*"9k}~qMF~4@w!gК-pBIwdݼUD%hc]WˠB }hw/jmK*͊DŊfvޝtpQ@[&1h$qXа;Z<(5o'cwfٲ8k`?eS!|s ǼO$Hu䋯*`M$ ~}y^]:I/K~)T#ԄG; swBeAkMRg G`)KZ &[A!-E_9,]v~^7nLS^db}S YT|/XƝ= cK`%>B#\"I^a>s?x1/}.;<0߁|>SmaaU:wV.6S,}})^KWE:a8I g;VZFE莨Lj%~^]V@ZEA@rf{T3Y ucYY$Rm;oUXK6[@֋3wF3ٙ(Ф/_쾎T%$Eڌƾ[D~X"V܀k+2+Zw ̦@c4PCdAեjr aV1p݆'{d3DRHOrFfZwYPdw*hvld:JV\ 뱅ncY>A=ȫ̔g;CJ&ݓ4n1DSv>L,jD,06+@̵A+KKfy0Fo'sD._᠆xvLb =<!Hl!'й &m۩}ꍐĴ]y q$GMfm+ .0l'SDqF aqEw'A2l@0֑ !_acGҼV!=>yqe]]o3Wܛ1x1kOfL-ư f{_fxftF+{P6ep ųu Yз0r\lnՖ>[aA(\GOIR|cUt+VpOۇCSOb~i-~n5Llb+fȠsMnW:!=՞xdb63rX>|ny@!VrF1 A.ކ_Xh ׎dN1mdq#e&i:.9 JO< %O|z/xU49l,c8`tgȗZ9u",H6)Gb:6g%EFऱ:yQ\k]sf$d'Hmtm:t?G;Yd!r'v:XJeGC?n<"#>@B@${@ұ)uo{Mb;&Q't7h9Yis:mS񰲱l~zaIړzﷺہFKr|k,4)]Vxnúrz JUNķFq-VdĐq-EK ڳmN6N6VbeۉN]kRrV0Šam8LE>p)͕ɧRVLQ3V2Dc"-_0 F{a#||B1A2KilN)Rz`.J$q EtD,Jd@eE19}CXc _98~i;D5~ [!fTθa@꫹>5<4Avl*ߗn Т9?CFnfξNjX8KE)Iؠ i%J UGH ?': (Hu{7tb]-yY{U'0o"XGkCv&Hh e7sPLE_/CMNKᳱYX4pE>EO,a FU\9u -gd#_KŠbgbhp=BssAB]bRV N\0'O/Ml*u2$iɑN³#%OgSUB)@:c9\ͰNuΆGNTRfVjf_q K/JȰᔑ17}uj-# M[}^?jnMY۹vÌRyjա'PŎt~Z^s=Q޹d!>u-0OW&0CG8AX*iuAra9}՟+P%r[Q5{mq7 7C`4{v:q!4CQ*WIql"/ٚ*l$ mxWs[0 >&dtap,9H̷VaY†#GX5~gs=ä5c ,k%JP$MDS"C ^nȰƷm.}G{5ОAqt19q{˱!;pe]$#D~و\͓uU_Cj3U)C! X'?>Zϱ˱NJkUx+۩M^6V$וf~} yw 5s7!Fa|0BC#.{jh{~),CGeiac28Y׊- CJ:а!črzpk ҫL >?S,'hn|+n8Ap9ԓ֞`hy=R X0zIN4 9A.#q?lsLndpׂtubS9.i-3u֕K -br iqݿ+/3i-i2ȅfm-.` ێ̭Yz=3Rrq5y<8 llT?r-=QÝZV$oo\yrڍ|GU6m3d#΍ƞS~rZH|0C+:[Jilo'6 8 \MfV23]FS 2D> QC'^XL(aA1GL:u 6m+R,'\"D  {/EWD\Qy^r 2SfgM3o!|&GP~e;/(l'8&PY1/)Bp'uƩlï[C_zv5(0!DF=tX?k1qv&Iuj-6bS\j )H1Uf])5(Rm*[Lf男4ňWoɭo=fX=nD֑ъϫjH6l-3)W[ז(6]N>&P![}f<'xñm1u3J#xEޝϜSTNUlě@E!i5v'V3w */&uz( L/'AКXݣFMQ[< !"l|ۿ+enj: ݄/9}6 QL7h y Ҙ>uH( to7ˎ_yP#;z9Eg@Rs@|GT>o0 ]lo80.}4'9J]IlohYt5cGui䖃+bU2#$p:˳VvzmPu7Gا؎VJbHquQ˅԰le̔6k~X0i;l$Mwo˄H:%+[6[1LR5`:/cFIoI@Vȥ𘸨oY`t]w2[6tXjgCOI;j; wy ,'qp51' 50# z;paaHVQ ~-ʣl:PZKO5ȄZN:غY%tbSŭlBD0*ZT9P) Dڢ$V7*JLGHA,= {4\,2h-2?Zz)E +Qu)qjq"C)ÂǾDeLRA}~bǫB#f#3B ̐M?qρUKP!I^D7jv]|ۨ!|a)JP mĝ mʂiOcAt̄0;^ja&ma[?KՉkP4%:`9`fe# !UԉEibj] z~PƤd3,o=-$*ب` d5EKYDߐ *8-ژ65MR]!oxRNQ5R(G VΣ^ʐ-aQ(XP`@EhHcPV";ai5D@X1qՄ*!@Cĝuݗt1zB0P9 M)z%;.e?jQ`zxH{9hOiЕ\. o}.9Ʌ(^aD$ `;n-{ٜEmwNݨ=QDFOhr{ G̈́Ѻ.,.$y2;8X V -Dيnjbٚt( S;X-DY&A=\ZrZ_ endstream endobj 263 0 obj <> endobj 264 0 obj <> endobj 265 0 obj <> endobj 266 0 obj <> endobj 267 0 obj <> endobj 268 0 obj <>>> endobj 269 0 obj <> stream x  Om76 endstream endobj 270 0 obj <> stream xiWHV-$AY"{QvvΙ9u?:7^9s2|}ƜSX'-#4IQ 1$In fXmPke(< AY9%3vJ/yw=`XV((9NKgA/ēL6\.~3g9'ޕ+1ZlV&λ|DT{luzfnRрh? 9)Z;'3dz>b/v%-<ŋrVgㆿy ͫ}moYMDe%(87t^ïN%wq`/j,rś/U*|}b/C6":Frp/[WsG:2Ʌ/|/5tp!#Zu#HG:ґt#HG:ґt#HG:ґt#HG:ґ'k a!9!tƗwU:+  J{ Xbg.q pɌB}-/nff9T3#{ьpj[\lmVౘ muz<3r4mm\{jU2/+r?.3=#[Sa4 \XFVfw42%{f 9t+DXr|/1m^m=ӈ;;z$K[O{, S+B&Dצs~9HA&FTI'㑠Lj^qˇˁ 8IcH34]W2bf2ԯb=$XY2ޅ M_v;ha]DN7?-? ؟={4@ endstream endobj 271 0 obj <> stream x1 Om Oig endstream endobj 272 0 obj <> stream xàSU3"^ endstream endobj 273 0 obj <> endobj 274 0 obj <> endobj 275 0 obj <> endobj 276 0 obj <> endobj 277 0 obj <> endobj 278 0 obj <>>> endobj 279 0 obj <> stream x  Om7 A@ endstream endobj 280 0 obj <> stream x1 Om x4 endstream endobj 281 0 obj <> stream x{lS c^ 1iemIVuL:mhji,T&}m$%EҶv&N&6JXK) ᡮ׾컶18!Z'tsP# A"*"FQ3PAs!G9f6Ȁ*my2IWĉcR ^jBva ^ּ֤ml_ uT4 3al8|oǶ?OO9N9gf#-;&A[%oAhJQ%)b RߎW&fuȤE tiʺ&R%ᎏ%!w9fy-d8Z- YK'x&K 'a17{#=wk*:ZϳgsnQ`Ϙ:QNZ!Jc9O񕙴 $Cze4s#G;5\;-Ú^S @'A;UBw[Y`;=xf*s;|+ݦS7ExԀj;}yoW^8t߳c*//#?:K gXsZn|fd&s*{d6Sգ'&rHVg*ќlB幅]d2+DYg#1V9*S=iSf5Т|UOq=H9urUG'!y铷3IlozႭt#.r .om [SkbH]:+a iff-d D Zڋl/e[9Xqm_z=B#b~7<eHhMXwԕI/Gؒ4*Nzwk1:aGT߻чw%leRm|7><'ͺdD!]RWAےC D5۾nVo~"Y&^ t&ɞ Gn8ſtK_~eӖ:p'C 01 nozpƵC_?>׳PBL]a> 3-N#L,Z!;^¬*m[8b7 j>{<y6BX D>y iEB-R+MUMƼS\D*}k&L̂6;n>_;nC@ʦ}ZG7 x dSuPʳAE-H;;H6a1&X6@CBah D+big6kSܗH?5$*^6pgH 2 endstream endobj 282 0 obj <> stream x  Om76 endstream endobj 283 0 obj <> stream xYsHT@dQwѸ/A(GhtLLy&_w5\"bc(#v6bXQ0@(j~o ;IQPi'pjpĂ8Y7ù]N$pي D D"|(u;)?.GLN"L*?*(b\ תRQLx}՛hw@H˵VW{VO 7g8Xɣ2L d2Qor]+fA­)o`$MiLJh.x(5JXEbWK'hꏦf fzRF9˃4ǧ|/#wj65ɰ,GdB3/ԥ|^c~Q.wvo >=b]Nv)v41hSqmc4~F+&Xl gkP˵8Tn>P;jgérw܂~uJɐX<)a!SbY;M/5&ނ,}pDb?YnjwhӚ>]߬VMto4ޯP:ԡuCP:ԡuCP:ԡuCP:ԡu+ HWgn!V;XZ|qC*)7oP[u'%puCTe?g+|n緽VR3ULasgB,6?Vh &UkY*1'{ Ny"h~p uicOcWkm.v (b:(x#ٗW]/e/ub60i/ndX֛V@ZfZ~% p = D*+ E} fS !u_:H #X> endobj 285 0 obj <> endobj 286 0 obj <> endobj 287 0 obj <> endobj 288 0 obj <> endobj 289 0 obj <>>> endobj 290 0 obj <> stream x nH@1 endstream endobj 291 0 obj <> stream x{SQqu.e$DA*+ _ 98sxOp++D.M,=5$I^$ih$+K*(L e^ ~UCmGώl>c&0bH/*n[*=@׹|(|woغ+ H"ۯ _C1=t _rv'͖5'kͰݿ.f7qN1e[@֬H2}]y@p$vE먔vhpؼ'b7r zlp3a'SLF^V<T8b7\uZR ,hV$~ڽn05*ŝXHxv^s]@A}*vvR&6L`UR<;-~Tk/bWWKoRNȫJ/K-/Į\.sT> stream xàSU5Ů endstream endobj 293 0 obj <> stream xgo7-m;r;=)hy I_  '|4-wAOGchM(4M}Gs`F>$iYi~Q_ϣ}j[MaS N*uv<=u4.,P7-u1ؖAYfЌN[?~9zQ$Bߵ:~ ρaYM"L0H/2?=_L7Li<׆F2HVeUpk% 0cȳ8`+LxA:O"6ΰvV8M8][y~Uv4]pDʹ8,ZTY[?ۺ3,Ak-nF0M[^Vi Kuq<,;>[~LvfڪŽ|/ i^MO K~%8-^)?m}t+ȻrWYm[mhId6Ypsx;,r]zhS8%|B(,(@H+i9ϋ&C+5L'_s_Ii#!o|ⱜSxaii(VNH|T~ۦJlSǾrzo$Ėļ]ouY|UO:web5R~3z]Gu߱95F~?Xa`Fh2dEyHDx V~m'}εCE]P2S#BboX'uZ"Ct{#S^bEc=.򪮊,ˡ~uXPm0v7 F?}E2IMMo^_Wy #x rU/!Bs{/*U7MG~ED NMTME%;8 p{uhvاhmg|uVm^REnZJ={)]6D}#lxch\2uV󺌈B9/-%4T(fȋ~"("瓫?*G|@7^GY3.ԕ` *j[j*CIQj EvΆģyѷ=5qM(o*0p)^B׃px y 82HSXA Xypվƣʍsn` Gok^޷9ģMx6T>khZgxv Mdžp+{ ybaVVEP-/ΩCEʜweDUq/&tEחuwT6$b; ,qoXM>'jm4nWj,kQR _tכ<M`$P씜;-U[.9Dd09 U=i*[*QjyQ,:Sk0FS\>!Tzj"U{7 =QԦ%^^Xs<> endobj 295 0 obj <> endobj 296 0 obj <> endobj 297 0 obj <> endobj 298 0 obj <> endobj 299 0 obj <>>> endobj 300 0 obj <> stream x1 Oi m endstream endobj 301 0 obj <> stream x y endstream endobj 302 0 obj <> stream x1 Om S endstream endobj 303 0 obj <> stream xR"Qa@nQ2P,KP_bƱv=r/ dw ]aBaC r RDx]lV 9eYQ)() aUKA ]38I3Jq8ͩ0{6 eI ij`4Ra2nDuU\gG׭ ~Y;? l/][NvvK-VNw z/+5JT+a6;$BB.NEL,rd=؋dd" x1>k+8O7L 4ssg5SVTMsATEv> stream x1 Omn endstream endobj 305 0 obj <> stream xYvJD$s)y{ iG?~l&l."M[ez!oܖ xx'gYMx|힞v"K77qs'iԾ{z_x\VKn"+X*NC< i*2| nmXIA_dwQEUi`3Mu2CqUF R|" }?s܋5>EI^ÀmeH4w!\WgGӺǁ .2gwҞWAk'?8agx&IVu4KCߖIພʶ k@Z乼08_}9naRA+ ơoS5LbL7F4UĨi8\p|8 -@7u$P*CEd)!&/שIi9QMPA@4O+ 잵Sm[HxmIFiٍgX\Kfi0M=ßWȏ-5tȰD !,oiaOeEUMe9z>}ky;q"߶a<Iʖ:G!M3P $xNӴr82ԨO0 =w(s ɣBy桃쨡Ozpv-Q(32WnXŦe\|/HqǶB 1:- 2+80 }v HF5J &v;lB4 d,: bP 7%5 N@XnUh<k#WxTݶ EUIh,OOB94M\ z}y2;Ȇ @G" .A8qBϕ0#g:ed20MiT$A@aDȲ_ 5S Bz& j?ys"K}++TG (QJ? 8J8jGX'&K@z`Ě |ϬJHȸ]Mg3Nhm+@@׮;H(5u(D@ɤ{| w,k<4;@>4En3|xF^"+a:ǰP) :oeՐ ]gH 2J}ӭtRX^r^ D' ꉃ}%ΜaN ݢpƢtb +! $I0HǰھGt>: 7ǡg#w N:IfS{OEQօ1%J0Օ4s3 z9x %xhݣҏfk s KБJx%eiG@'PCWBP;asMd95dL*њ/r(C878R eأULanUS}|P+lBNA~<_쁭 G$@=?OT,hL(^եA,`d7 j1;`<9N.7bFwql! Aȭ3ʟYr * dTdhwV$r{U?1xͿ}a_vOnZ#_HM6dM6dM6dM6dM6dM6dM6@P endstream endobj 306 0 obj <> endobj 307 0 obj <> endobj 308 0 obj <> endobj 309 0 obj <> endobj 310 0 obj <> endobj 311 0 obj <>>> endobj 312 0 obj <> stream x nH@ endstream endobj 313 0 obj <> stream x  Om7, endstream endobj 314 0 obj <> stream xyT[ם7Oәbоolv6m1^b/}ߑ&@@lc06/xK34i;Mgitfs4 ryx=?~O{>=}kذaÆ 6lذaƖ7v@J{%Χ ;QZ L؟c9@bqr>K zٺpC}/oӞv"/lI6FB7XԪH ߟX3|qڿ/>Gw4M*GI@J3OZ?3>Yy|< {x xJ|GZK.ΥogZdgc >Xk{=G_/u ^A2|?{6l^dh+ UznL o͑# "ZTKGӼ3suz1Yi09*~_J@mU/=FggɟhiU) :ѫ>Ď? נOZ>u'ؓ#o快|65:ij?2/i;% mGN#}h0q-B`axmI.P*1OB~~l73ίOm#͙s~v?n|g7) 굅|-y䟯ڦ}w=6X1D k-ڮGzryeDu̵;?ӼsWA}?zEBsHG}9롾}QzW<4ʠo0^ѷc_=ҫã;WX@9 m0 uĀh@\Ā]+1F857"}Q Ƿ?u>zO_""/^$=O 'q]K]뼦e S  uv. p^ b-$, QT@dYuǢa,,fw8!yy:jgerO}뼶eFm8Ef.Ӏ8̨;tp|8#$#/KXQ}{OĶ׷ѶVnK ڳ0 Jš!Y˴o\Np=;B28J@e4IqQ|bl=}i$I6DۅCiu}]؞GqPyTL/bG>#̶s1vOo6c@ a@* eBauyJ~O۹yx:}v!"rq< =::묦yJeA}akI%:ȢauiӤvO۱&0l>QI9 2YUø}]eV3ah?"UפMZ8~7 ]N$X!G|R\}}ۼ21Ojo`vބA{׺iX@*" Wʶym}}׃X8IsF²|!ׯH:đ];iu-U͐ DPyU8h״tO˴^"!I^a=r=]m fD5CҢnAzcU$Q@ΗGv E힮sʐ8crj/q!2T: dwNkRAP}] };>($( ;j+u/:;МDBlU,̯vWkӘP2P3 ȹNq@\?.ΩJwrj/PbA*dp^k4M*Uפз`@^AȏP,"o׍-VWu:+$$,b*caö3[qEUi>.$b@mIUR7urˌ~Oq_߳OP1  }b\BlO4RՏ)*( gK9y1niT22t/Iy BlB%vOg4V fDAI~GL)2Z Fr[Ƿ͓AAD؄$ÇR %gH kÀ 4 y6ӀFb]bMy2i#euZx؆*ՇG JφIn2DA{Qr$"-O\;"7OZf4sZ8WBHZGmH:R "KX1%~IN+R Àprxe}yJ2n2䮮s2Bv'!6?-y&ȘsE8{&i@ZyeayR o:]y_y?X bzzlddT-αr/U3 T@J4M*oPCBhy{#{_P񖪎 H[M$<$AmBbNWސ5R3`^q/by?!Wy=5YgS UMr8½T.dnSX{CtK<ΨۼWd8B|Y d.@Px8Jv oʡ?DT@8 !9$mPTJNMӷ{Pb ~E ʺ9>Qf "U!ș"N[ 7xoW4MZ B&`[}XfV/tWПzE G" RnT. yZ]PuMR?&ol2dFzG S;ڼ dNA_NdПKs0 _?C(Hl&᩶ۓya}Ys=|R HR^ӊz F JRXpj/ntyg!oKmI[}4O|ʠ?8 dU 馼~\tKjluڎogh!bӈ 8lR[f4-m!VZnk[5c͓+%Ad@\#7v@N䄥7Ew YݘcˌIE_ATfX^u] *tsp!<5Mp1%-&m!V"ÇyJC GjnȫI?4E+gCvXJVzfҫPfbۚ WПzMQÄdƨv^[TsCJFJNIwt|7A?v- A0 hw~@8k㕻DC21OӦbhWn@.Û?DA{!?IWM;x>2['.A2N.Yl$/)geuz,l%, 93&>x ړ0 Aȏ$`J]dv+WXyMR}Cf:}L 'mEND}H:nTi& Ҋ~1缎x?SA{UrSd}xUR5$ù $[τCECY;"krsn{ .>,b,ktS`*+&=BS}Q;B.t' nv^`Re.qb(pjo@N.zAB,1eziDK9ƃ HΕk#2-aP\yMZeM_Oay%Y’DT@.3HJ@À !J5GeT𡤆Q)(@ >g.bT@|ÀfHjȂl6GeJAͯ0 ~ B }t!Q/V|K5)+EpRuS#GV>d0p5ޢA5CB ګc0R]ïpj%b1訦aؚ!B~IK\b}Ϥ HfKta-:,d!d![-ϫUeP.aaEW .v;̦9YH"2G]"Ca2a[:u0mW;2 5RP+y5-)8(0AH@8T@b]BCL0qn~:خ_1dR r[\G ?%b5dAd bjPRs]fY0Gb1訵Crd01形 Hd>Ӏ\d bd! aDk_\m.~&$H)3WÓq@aT܀"^!Y場%.s{(%1j~a@@w@C=)/sI!x9_Z'.u侣܃Ln= o$éJD2bT@jyÇ_SRoT@“r0 p| E! r '%-X &WՇq@jpK}DA{QH?-qp*%פw+U_IR1loŀ+IZkNalIkd!V]C:V> Bmxi+9 =@қ|cpz%aYI (zBS9RC:V.tv cr`:Wv39P%2~U"VKC +u</J,)ŀ*9×t@e NJb!j ݂~n/½R oeS1  ڝB?]|r b~GLa.,sid!VIC(u{d jE t5* .~]s9Q!VX>z@KX/sJ]<& ' +3-֩ƒ3Q9m\һrb!^^mKr_$LrxYhϗk9P_(.1Y7 o; owV.I" 6A5 N{Nnycl|sб$Mk~#DA1 d@RnUg!Ƥ~ȁ:"|sбTFy쾤?9H!dá~'uI@>ؗOVV-]G͆U+[ǫZuOzRrŸ*KbB:_*8Ε}1Ӏ):+S[C;#)KXz?:#DFǹ]B&< o'v!h'8zkH7X3"z/ܻ)[+um6regr;U勵NdElѺ쀈 ?;ú4m6lذaÆ 6lذaÆ 6lذaÆ 6lذaÆ 6lذaÆ 6lkwr endstream endobj 315 0 obj <> stream xNaζ3fh鞡B(R* -HW7z0s+o&_ g^Az˲e²ӓLq'"ӓLY |T1=ɔ$odvafz)rw)(idJ]k#ubm$SzrཾvRgz)1=ɔF4XXW'2쮦H{'rUIrH9R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)d=E50=ɔzݷoǧYx?~-Ra?>r3{xwWA;)xk ׷4+&7WgoJ"vWrdKR Pӳ<+Fg[Iw?)r9 Gr8IEp0nYvs3)([XNL&R(^Z^>,DqD0{\bg1> stream xiP[%L2i:ӦfG !/qon}5XB !!ͬۀY%vfki;ttK?\ɀ/.ga$t|;O=5Ʒ}<j u~NPQxn6KVDZW+9Ҹ(5)iGƹpJfTOOʮ)>liC˲qVpV9/ .jhp˲v#VL{'>9~?w/rn3}CL8)[9MQnOy>zR~-{o|eD3$[d-m7c:^uw_?<2č\cxbqm7DE6\ 6Nz=  rTu}O'}ueQX1cKQM 20)A8cd%ن10ybdՈb+lfT_x5㢆0̺i ~Ia[8MBdGcÄYi沨WL tr/ULWaE0$Z%{6dD[`yiN O"od<8YՏ0J`k2+e½A\f=+Q(Vfg#7B ~rU`Yí$0tn8dg̋ Wɱ<Lgi)O, 8 ӍxM$dbYV 6BFx&TM2KՄ@gJh)WwB0%Fk%n_.GVSĸndl7-`g1vX Ey.I^(*@h²烸zdX;&XeC%f_!%;h(WR9!A7r-ĺ:ܼ@|h GA~q{X1$YMKy?q!f#I;1 :Y$4/Fy]3j8dKg*aaEԇ$xNi+.Q`E)j5G:Yp2.J6j8nZZ{Y !\v]H9)7U~?lLXuIEd  ;B;w2 UoL^ ;68o+?u/!oaa_ӎ 1q\q,IنlḮ#ႊ~IO++KqWXk ,APIi0LRٞ2.KC:RSup.M{>iU!NNEFVIuIOt"*.**_T tCB Wj[s'v?t pZ =9~0 dBـzx8PK[xgN@6Svs +K)V(DƉ1I‡qERSwr&u,D.-$Y LU;[˫ .aHD>~Y/`>~ij(Z؅ffѱ]tRi)?3Nᝢ Ȫa9Մ dkdzdif'{ɽTAL7($$Ê]#.?I>H圆G3n:/9IpRRG2OmDvFg=@Fe  k06r|t<˟-5[cklmjj@4 endstream endobj 317 0 obj <> stream x[O@a;t:-RB"ДD\lӇڭݶbqze4}WVIG9ǩTy1L1`s> Te׿ӈgESbwE bXee=!l:a5Xg׏NAj%"@K@EDt֬T:թNuSꯪl'Nߊn{pMfgWSxwVZmg.Y5W[;Gsϛy秣NbD629eͺs{(fhw^?^iܲ!6'6hfkcYfíyD^Jv]L]McKErnħ9M3F> stream xc``AFC42yki|т 4:Imuh䝮'ѡOɇ?D$o-)KՙZճ, 7_GCxdImupftǽ?+z"?{*gȪmu`FEv\Js oZlS>hvv-lX'VP~j]FkXdݾڮskr$FةamW#Lq*YmSLjZ,vn]Ѻ<SL Ke\M0/h[B} TXDPATTcѬY).C.!i zu8QyJyb%A+ #5exȶ)H!,K'  2] L&j+Y xu4E1(+Z?I/AȶzQ0 F(lJ endstream endobj 319 0 obj <> stream xՓN1itXfQ̀Q"5+ | _A%xZŗD" oK|p""̓^x)̅Hgo #HD{纂@@X5xELa8KFaqK*h͒xWqYXKN}k/a DYhvv-lX'VP~j]FkXdݾڮckr$FةamW#Lq*YmSLjZ,vn]Ѻ<SL Ke\MFemK{A*{2#5eȷ%D1A/4J*3 V!j LD]8r MqiKKPD>qj4!5 F(` 6 endstream endobj 321 0 obj <> stream xՓN@ig:)],]S ЈLpFQw}-TŹ7~Wssf r9E4]OxegΟ   UB'B,,2"ύLʤeX|٨GnX}'`EQ5x25E(jf--fbƦdS endstream endobj 322 0 obj <> stream xgP3%UiM]]]( ,m)ŎzDQ@4mX9&sm.$3I%39} XN|^->G'8>bg`~&KY dNUڠ&nXͳFDZdyxo92,[upb)yXџC7ᕼwWj󭟔_,Ɣr=Į7nOбtN"aV.qkm 6ڦEa]}G.CcdGi_u9YwkhGIJmMd*i@flEV9_RRj RJ-aԎCXDwYܯ11 i5V䏬2R1{h'2okN^SD<(qHY)kV$CZTaW`oXޭʬ0T(r73"1LW)}h\5:(6+zZ&"xV$NGs!y\w:ȸA;aP&\Kn .Hc/)zHq K899y9%219wQ4(R2;nRril"T!$X;.$NK< 8g씅"5I#EJ-kVP \(OR^0 Љ +-Y(:.hI"~32O؅%+[qA2ɮ2]դВa5Lr%)'S-Tu5ډ^EB41<ׇ*0T֋Rj>,";0c " JǠQM]R?@yd GZ)Ͻ!G|"a~V:lu)VAK(QdqHa]Wz,ITCZҨǷcQ%uSzɣM1)sG<)PZeH}1⨋r8yG2VJmL]?JbeVt,*<;}`JjUɔإH$2RxW^28yJJDQQ7ȍmnF,1z)sC^ՋC^rt\yx,ߘ>ȠԚx{3nS[GlLm3%jLaMydO=Z<=**_vJQF5jԨQF5jԨQF5j`! endstream endobj 323 0 obj <> stream xR0a$Yމp0Y`&IX[AYCFW%Խ@wa؂(9wDH.!t P((@mj,MqS>FX=BQj2rw5e]>ԬV zQBPy4 &g3x1-5q?%Ԡ5A jPԠ5A jPԠ5A jP`4?j>e8hMf/ˣNEw/{>lxuzyNnh˕`_\"6W?$d?r6OwDmժkRT0jw=u;( ꮭ:-J5M fRM1lŒ܊#l+pn%74tMU0RpU%'*O[CD#Xb?u[ endstream endobj 324 0 obj <> stream xYPTYiz&T%$qrE6QdMY}Qp_QYdAdG@Q@yy뎞N*ʅ B9{J%or~;\GtAt1Y9eEX2qU׼NjCpd?X&@Wb /9Ϙ2hebmΔO_* <+ /5Uu6pOF/qbz_ x 3+=Fg}2G#"S8xaM#G#%^ oqCk@ٚF?)K9o}9ÙWw/O}3SPftʔ! ,zrYzŬO,|8y>,N<&(TYk6r>:7"v˧Lط?bnt}t#y`ۏ}L2cKL6DM-` xzʼ bMYҰ2}BP={jhk<'lŶ\ԙʴ{;҄Aqu_}C l=KLWb{W?4'+aFd̩ VO;N#_E߻=K()Ww[né(˙^e|CAquM6 >yp]|'䔹~j@?BLd?RgN(ɣdalY˨S6LD| W?s+xnxAatp>Lki2'TicQY W;~!0ԉM۪I1\ @+ k'`u69`Mh3!xhR^IL09^l512Rlui-ohqOZV/ ~ig;x݌{xP=M&.!X2Y\4Kdl^V*[*Du!SGQȘ&&̡*e&SL)2Hٗu ۥ^!piGYE<]F&)jjߴ'{-Ur.emRs<_4J`Suڨ*uWŤAyB/42IL0gyl=ɟ(3Iz@U=Qv1CemEiL!l8ߴ2;TV3AsuC'큥`QZbC0Il. ۸;l' Ɗ[^yb2yK; Q5 sFTʔ0*B\vMmf^hݙ΀ EJbo0+IAkG,k9U1_ftBTF4Ug6\K+jaSw Fk H&&SfƸ(!h"NU+NL'l]*T΀jH` 08bc0/ g?(ˠVLYջQkˠS۝)~W9M7a$ XG q1P#7{fg*Re\َdgA&qt"O8@tD(.0rs/>Çhl# =i}Ikٕa>&P IP! (@|)qCٌ?8'lv;ʶ'9? ;dtSۥ0$ c̡<&SjjG"a 9lgl ;ˡ9mL ]p{(,՝֬Ga[Zb06QT0pف([V)20 GnVX;Z*^y|!o@\F\;\"R*=DQ7$@:{" }J˜>K:I#kgu/9WO!+| 䦜$$Wi 7,1Cld[!.euN|lOa  VV H fuͷ`e7I\l( ojK|lOf+þxbG"!# Ă՝(cb$/` _'=F#F^cibBXb2,N(1LQu %Aq/F6+1AE]Xfhj)̀IuU&SlexՎ{o:AR([AD3$<sn):|`I`Ul'a \}5=WX*w Y"a ZaY+,1) Xb)k@8~爲D|(Re˩ FTmI]髡~-L &4P$v(kb0dS7#VlUAʰ*c}'7Q$h 2oO!.:WB/<~[UzO%PdUw\?!jk(Ba 7&1ZFq8gQ~kJxY$) 3%f]ï  xV{,a~X=$kFSBf G8Iq &SVWs+)[uMEy?TO @EK (NMa fqT8(&SVWq+y<s|O9A`F<@j0"AxMZ~H7W#++tO J'5RBf KL( * j!WAxj [un,F[N*0KFa 4oldj^H%GR}7~ʾ`=JOaFƛ_Ue~KeռJ;x=ERv8k3 0 ޡD CDY/9iOΗnF6_Yr\^ed_xe"7Ʌ9V т[z1XAVyP_C9qwn/2PwUo',õQظ;->T +[|! *9p޻d㮬T2J((UkɕӅʱ> eP 5! w_b$٣aY;E/2aH8J!{"ߗ{ߺFTiNXw ] k]{ۺkl}mvܝh8;Bҳ# 3`O:S')O_9o[2:蠃:蠃:蠃:蠃:蠃:ce3 endstream endobj 325 0 obj <> stream xo@]Wh RJ;N1l$s[nAiby?W綶7EiE!SfHYD(cRAxUBMH}(}0հ>Be4)5-ݨ'"L3ZTil Rj 7 :uM!DRA"7}5V7 w9khv~t2( }           t߆&v~Mqtۏ-WonV8X[g׫Wz<>xzΕ Lhdq~ynnhVwdozt:/*n>;=ߋ{I ɣdzpXqxnw[hzl'Q=&ہkYiv"r> stream xiPTWS5S,IBC " KwCڀ!QqAADq_1S280-TMs_C{W=sN.y8pxV`r}.wzߝH{y( 8O#mK'! k~]^/Rل%ec-Rշ:e4<1yt.;?ͦ[SԵ&4|{o!?uCScOS9_86 ,51O.vҌI]_A }e_,/1Ğ/)v\;5 M;1 O28`9_,0/%- !gX' YFƞ.K2ޚr>5;Ⱦ wW|-˼kMV=e h9/Fs{k̻=.xxڶ4mv0si 8DwWsKyMb,LGڅv>K]s>;$D5;y!௝]ߩmi$X!<]tQqVVU|[ٺw}v_WJ 򿠷lTyw97噓ҴqQrWzJۯ]2aL>PQN 2.+orɟ-x#tOK/ʛ|ዄ=_{[}CqUjdjY'hfsm#I$Ͼ̽w;!-|gXWxZ6X_4~S0_2":zIc"d|.-ɳ+ ۄG,1žq[p}w0Yd˨2c^G^vAG yI]Qy5%Q}lQsP0;[Ĵ2tUC}Cu\:"4pja?r'#GS+H2'DɃ{{S` Dy۠ҡЪPШ\ ݜFXJW I~#,"HeWmBC!tqFnQɺ&ϸ"C.Nlg'+];̉$vh˺ {Lsΐqmu-U.IyƄ2*6qbRBZ߀vyTD0˧mRr8A#?QüSB˸"KC(ΎA V1hg_QnR2laN 3W Uu% <,2A#уa^G,<-"SrI6!ϘTfPSA#!K̔!"/qTUDA"0^.2&#J2:rܛj$$ AkʬIhTʠKhwtӛv|v9Eq(ئl6bH2F0aDʀF{cQ:E΢G^q?3)@yy5,[N*3Ίrh2n0:Vhwą&ymza)a 4| 1Sf^dˈ(ej kB~Xi$uR%D !H78LN9 IOj{+wZ@V=v"*8z p+`}uT>*J$ Ee8LY:4cT0>ݎSZAb' yHj]RdL3'W0p :*1A;C7?xh~}W*z e3OzVe6e1t"bH! g+bw6H8vZUͤsߖs+ .$)C2˨-Džd!v/_;fxŴvdFǴg.FoGTüχKh%ub $& mձ. n{R:Y#Hmy}Ms,kC@" TyF+uǮkdRn !%T!„6QR\ooiq^1Us`tEH;ҟ}L"ϰ2 h6`/-I{u^iϽH53hռ ~Y Yh~7YWQt^!ќU`F s·+%n;m7ZVIk'(DG\@J (& ^'hgd%ɶK'+1vސJE5'm7>/k}+L*w>Z KϺNHܜW7F|ۆųp8p8poywN endstream endobj 327 0 obj <> stream xr@&&JPMVPkbz8՞-HqO{CW(0eËIȿDH$TJ (I>4IpҚDT>& 3BecҪ/Ibԋ&pIY0"-:VG$jrP1}Mgʤh7&osLݜBD8?n$z;54 MhBЄ&4 MhBЄ&4 MhBЄ&4 M9&8x`\otk__WjHN^t}FM5뿚|~)4MA۳-_lzhrv>,lz< rHQQ?9>};Ln2>췃z4erIr8<*p<ﴞ_.Ȕvߍ:ݸW~q܉v1F٠a\|ϭM),e72bڎ rlʙ4sn_U]c*KE(Ul~JA{|p˵ d= endstream endobj 328 0 obj <> stream xgP\YvǷʮ˒fqwGB@t9H# ( $M7ФI34 DAJ(Fv?xڵ[kWY>5j-t7}{ͻ{z~2 2 [L6ۄ>w5S)<\߲S)y6V?cYfpwӠ?jh _ ue",zx ~8:e0l#y-,5/J(Fg3*LlmŗbN>_YkXvh/!@֊}w_ |:Y* 'b9$YhfA JOasg9ueC4#ɘ{)6-+ Nw ^\'˚V̪ [¯y^V_ _ؑu9' =9T S =.yqM"MY-E}8 η_yʀ/ 4P& r7TǪ ]iZ>.1CO;F)" "C,sRs.| -¯P?)XV3oќ,'T;[1a%@0`_;J|  )r]e*wS|ESND>lIqڨ s#ҮA\M$IgUR g ZA  ?Oy9ҌIqTD_tJʾ 1C7_-$"X@ ?Y4}T2OlgG\e>pTD - F xRJ!Λ_e0M2&i#~~b; gW9Yg 8WT @1 =oA xBVl 겫-sOsW}%a $lRV#@ /<+lDqǽ" y-6N; x/$\ GigNI$C"}?u#S TZr*Bͻ B]vu=u]i9iA&?u"#`,GqvD5/Ud藤2Y3컪@ ЊʬȂ`RbZt\r?he*^| )1tx^p ЉʬȺ=8"N&⚡-@);*/Yd)IC̀ysb! ;*me4ȚeC nXa @=0PMqrʁJ(;U^P1SD nl籋n;_#p(=t@#w jCeo nl#%@)`/d_6CKbV?s@lm7Wyہ(`_B8uHJ@p^yF& -Xq| /2 ]\MC`_6 nRf˳QdOM`Fd0]J%/q4R%@68Œ(с&8"4%ϚeN2$i7:ϣ]c{؂]hnQʀ8,MgN`FZ)E֤g\>*1B';81G?w_?uP[$G l@S-M+2'8c| d)L9ѵGι+tD 0Cv }bȁ2*"pvd@?8_`֘g]@wp$"lL6_3/^^5*` 6*Ϙ@@& 4aaGCd| U 9P`YG>yeTD2&`Ơ/MC#v[1CN% C$eHf#  }B] ˖|?հc{m<'IrHc d@crjpISfvD3%_ 'y,Kh$@)Nd#Xy2 c ÌHR%s@ kn\+GpNmv zb0>/bVT) Ѓu@F%@ knl+GPO zb0>aC6C0JX$Tj;a6¯P:HfKg674/;@3Hh~ 8XP*n0V6A| ;V- 7Xˉf_,!vF,8_-onkco׎M'c\ }ead>0悱{mAdAdAdAdAdAdA܇ endstream endobj 329 0 obj <> stream xn@a`cL7ld(i,@IU^pZU]ҋj1`R_?T:Wc\Sz=OmӣʘD7x䊒he;R|2:ٙjSnJųuuykM)]K[2ƍlXtSoeuj@tSŬGߋnJc+̙\YZPtSFM_=ݔYjjjRlWHאJJJJJJJJJJJJJJJJJJJJJJTW?׭4'7W'g&Srsn2 vt~W5 h|#b{mV;=^HcxvzkU N>w_Goq V 7Rt;v;f;˫:_Ѭ\X֢4V-l1nڮ( }/gjverݴlG.m:WVsMӥi|6Yl8٠U+  G%& endstream endobj 330 0 obj <> stream xyLGKvG-Iml@Ά $@c|m tnH!\B6ԴZ[ϤMڤMڒN~kb(Ez'M^kGp?prf*ۣdOwIL꧛l]&jc1Ԏd3+pENΔjXNLM3;-h;8TUlhZo?[;uڤ)stXy2 pu>wgu~+p鷈_>zγm:.>UtU8/fp!1{ijϲ hydE}?9"G%oKRskڙoanɊs9W0T0|_DV0[[wuOX:ϷO ru89StUxo5qbӷ`v+"璠dgb Rs?"սλ8{v-mZ\GC򊇰)]:o?fu{M\,r,d>~BN=39K`>YE(ɋUOџv%iy()_XbY&t7"嵱 n³h  6Gѕ~V.q_ws{URv_\mSΞ:co$=gs9TkS4ڰt^\ {MYC?nŋ^ܫR= co -e{YN_F͹ɰ<]J;Į%)T{+ ,)[FE}!R ~JIq.q4>D QK w-[ /occަ+"N4*q:]Yd{XC5)C0wa煥sX>hNʉx/^qΈa6aãaAEki' Kfe[<)lxR2/=x9wFlb(Y0hMACb(l t qi]8߄qəxA9DF hkQtc;' ۦ6+ X69ư9PJɼDg6,'@R:+Fm݂nO mwV Mjv EQ;^G- 0Lm?jC(Ҷ @D B 6:ɷLPpЂ`j܁#qr>b!djh z_hE|g `` DL8TDNoia ayq䃬|І@@;|8x&CZP1Na 𭐩`BPգYAKN`b;41 Q2] ')E9bnUE=0hvCjF dNB3}h> stream xN@qiԶ(`m*7 ;aBĘ7D)t*ڙMcC33XhҲ,e5IώboX> stream xc``оU#Ƴ gȡC RtL#.38=~d_u@Hl^?s? ?w  L' C]qҗGϼt?5c[)V . Zɋץ,Y5&J{ eN4VU+RҊ0(m]j•`}ryUUȷK-O#[7fYd˄~" p~n!%SRqRl /+10(ÊUdȶK9S=W%U9E9"5$~ӡV$ EZNp$hB]`Q0 :Me* endstream endobj 333 0 obj <> stream xN@`Zf:B)*S$ԈHB=\肄(ЩC]OE̙H_B a;G:p `Hp;2iemECVJEX1Ry5T~wFb"crf1lX)Y [QbyZa.0֙;Wl잷 ڳ{d:NƣKk \p8t}ԮUxlu=qzN˶qE;C-SZmvQIsHPtXf4+R!) ^eUӍtKеx຾fq$+1KL%r< X DaD鐁 5(2;0n endstream endobj 334 0 obj <> stream xc``оU#Ƴ gȡC RtL#.38=~dQYHl^?s? ?w  Ҋ!.̀zݸYFˣgh:P-A\Γz4BUɶKÿV;zA"u)ox]v P3)uZmOVFiV9DFˁ!~\2UFaRu֍l?"㺁".b׫֥[#dJ]*.Yͺz~@P_x oSKKs*sS"&RsLR4!.aU+q7HLĴ!HF(` u^ endstream endobj 335 0 obj <> stream xR@p]D<)h49Ja.q _{RUgͷ~D"*_?y` !LK'6p2DI, h(rR4/(\&&ͫY#0&s[& ÆREҼ49hxY+.Z*J,'RY 9 1!˲ `Mנlk endstream endobj 336 0 obj <> stream x  Omڈ endstream endobj 337 0 obj <> stream x1 Om O>H endstream endobj 338 0 obj <> stream x1 Om h endstream endobj 339 0 obj <> stream x  OmMx endstream endobj 340 0 obj <> stream x1 Om_ endstream endobj 341 0 obj <> stream xYwHADAQ\0K0j',Nwz7@ː}{K[V$$_%:>X9Y.>h@"sA <c(bx48Iel6˺&et2+rz X"JwKVjfH<tArDTNsOӮE!^F#bMә[dy6HY1@aO= 8FfˍXZ髥2X2H\Qw8b֕aKǽ;HsYbP5vڹXa[H*u/ #Wgs lYϒ^z Bbd&WzV[fKs1~%1ox absEz֖fBWgւQ,N$SE]Ag |{8M?ԫb!B+}~||ڬX㘤=Y@>Bcw@d1$iITY۫_=}t\;gדuvKC[Ev/+s?|wi.F"<: dT[o8f^n?}?}٭v~d3A 7 }<3;h땗v_\?vSZ{H {JTȂFBq2Mg"x'1?]bmY/1~{x4;+g\rΐ2 endstream endobj 342 0 obj <> stream x  Om7o endstream endobj 343 0 obj <> stream xkwX("x[Tܽ&6&MҤi;o9&ZVkx>k|هs6\{`;` xe,x7ԇx=Ϗ$2 pk $t 1"PW>,HL6_(FsdX"dTfD`* h2 =OUl^"! 3$X4e*tl nk/hUf(wp+"*|1ӦB^[[z]wD$2gH-//sm:l ^D5 iȗZ,`r%-js}rM|x~AEfsy"{0ϟ6 pSoÿE<”["bf11]}ىvL,"]sY'0믪 j"@~F-{E(A1zg0GiL$E$7Wi^LY4S8Yٚvxjm|y|4۷wNFi6S ST(x,q$UcZ?ŅT T:/sT_mJjG;j~L`8M P2WҐW¾N41 'B[mdcZ- YnN6f'vx}6eU> stream xYP[6iyCRbw6׉7@@HB @ HmvMlbf`'6I&iKgty +a% 㙛Nu7^Y|;G2\~;>!PVu}/|Nl7՟: J^sy#EŨ<q5KFBY6 '7wmC?Y4Mhcet3c]~&-lU/4惯?'q͆ e]}gi!qכ/G˟u MϝxB*/Dd%t~}Hجp\<, Ms\-Vz3_Q]MsҲ{rX7bP,%iNdƞӹ[lݕ[+O}ۢM;z0n+d iΌ(j7$2H,uEʪG-ߪ2?QXIKq;vSocgvn ӒeInYJij0x5zZEd7/5?FJ}EŚ쮴tIR+ LsXXMi} (Bj6Nu_Rr",+]F<˾qo׍3,X!I%[o_0˻>,z8Xon_oÎIXee+aK$yhn vFשf4:'rT=hq< Y"d%ey7V"9I񬘄|GP8˿M+I+]A9̒.mƂ,Pإr’\yFF Kg%aJX8.(s &*hr>usm"DRR Pw%vacQ}+ۻ9x%4ӻТ:h&6N!@)zyNFjĆI̧ m7Wl&ڜ5fVZz_0Y& %̾[0!* I8h0ב3CM|Pb5)hјY̯` PRWe "HGX0y\ jcڜ3q8qs1B8!VSBIas)ۢ;"pLB$];t&gWYglwE*˹CԨQC$m.Ƅ1~Vzcá]TϘsVؙ~I&QNV!1a@7/lQg]>+ nH? VG"` #|%QuH9H#Q u#|f'Շ鈕މɈq м-$IH7O+Q{ p.r /0«]9Q{H7,Cu2O3WeٽϮ솧Ls\ul':ň> stream xN@ai-ږ"- xB@#4ƅ11nʋUT]3ӝƤ od_FiZLP;"=;`X{2X(cB{*CYt{,'= `dy=ELEvYr4a/lP/t{ X-{e-'SƌAՌZqd6[ַ Nܽ oMA,=]{Rp˾nhqt{V'PA֓ӥNvj66ז2FA BiZk|*`9Q'rR)sA?{$/-tcrӮr)+􃕈0'0cq]S f_Pja\ZH%=8(9>(B 7fX8 !POwn_ endstream endobj 346 0 obj <> stream xc``2ϾU#Ƴ gȡC RtH!.&38=~dQY@Flv_?s? ?w  9 ".̀:ݸi#l:P-A\zq4B:LɶKïF;zAB㬵)ox]v P3)Kt +[mwf9FiV9DFˁ!A< ~&dۥꞯڥ34~E|/uEB\,W+SŧFPlTtH?L߿+/S, 8edhi8 9h8%b"5$~ ҡV$ EZNbZDI|Q0 F(m֣ endstream endobj 347 0 obj <> stream xN@`Zf:Br 5"{ Z^C*r៴˙33ȿ @oD0%[&!B mGAˤyyA Y)AMbP.KUW&nܖBŰad4o4*.Z> stream xc``<׾]A> stream xR@p]<5MfRcyz.:G- +]u.|G(/a0#GDx"py|T.Aͳ, bXK ڼ׆aHh6ȅ;" H"ez1bx)C7]˚~sX;jrR0e=_gdx> Yk~;OmO' NQUh8['fLKFYvZf}/Q3TjiiFKz QQ3TTJTɪ9jLM&qu}IV17QE" ! A0!q k0t_i endstream endobj 350 0 obj <> stream x[u?ZR"88ΰmb7M#ɖ-Y֤D{Op pIDR$Ed-;vIM擴y.@KX4> x~xK_8p?}yq-PwzRLGPw:>)V9oo |}۬xN\y +}o}M<ꟻ(xMx^i7 VyVYykmC9}XcWs}90x~?K_Xσ.R^H^o=mٚoTjO~~{6Զ)䕴 u۷?^XeY^ C_x5@T7& ܸB~IH7(5M:o_&.,e}ᩦxcgq6'MeDuۉ?-5\v㞜b|x<\n/) J.x߷;~{߯O5l=ko6fZf~e_[ H'כm(^Z% O #\wo)q햷M` _}sw(^'ڲ?_o;πD& ]Ώ}c\ Ob>Pxi&L/N|'Kg1bUT=)7WYqJ\7˯_;sßgM<7{l?K4Oc\) Ai@R} 06y[>oHM|s ک"~UsIФ_StT:]bHFݔ|C߇UUQ8n;m&Nj l iZq V(eu=r=^Ώ>]~C~\Bn`Vy"(u.4-︦tTu߉齷}BbCŪwvQo(گ,ieظPP&ӦK(7Tݷczƺ0|ߏ P;o+2 m +7{@z0  4qm: l_|!~BD{wɗj:oo);)ls$ ~>= 0 Җ a~ET+i(+:ɩN 4>ؾ+aA]tQuRuTt\[h4|.œI@1 hYVb@{󀜁EIӘ:WoS!b{}O= 5I-\g"oM:67f~  J8ˀDNI㨬m(؞D/Bs<ծ~]a[.ӭҦqqm?ŀ  hWv^Sw݌鹳(d^Jy;Tq]e''A$ȄiL\ܔjo9+0 T(m,+:6\:9/ uYYPb9|Pگ);ʭ2r"jzß\;SyVaeU?BaLm-2ub1& ㆊ_]Uv\] 㒆 "m|s*1 (Ha@J@:- a&wݶ]VWՎdꮛ1bLb&juUI}^nMcQI ^@}faMSm"v1͘nJq]m꼢W-2$aQu7/ +$dntn.6 IS2:m~C KXiIqE>O%4Oӭ1#VuG5Gz&Ay' RlO':!a./Q|^>̗ I(Գ H.tOVeEی8I#~@XanL(ݥ$ 2-}eZiUu^dzU )9%ٿQMˌtaһQuR&(.I8Jd)SGNM2HH;">`Yy |/KHC= ;YuzAU4eK;ec~YŖbKizQ4JA=31DėR|r"+*NPb$MtEiJ6% I"鐛qinYPGc@P@gFeȓk{%frWaI Ւ9XC6`!7Mc҆0,(kf#iv=HLn_lRqRf&]`׎9Xfv ,2 0"6 @=70!MTC5HtH%LP"VP-r&2ㄔWwA=Kmt]Y_v@$CXDZ'U?,m>}鰗e!CÎ[tH鐵\2uP|t]D\q@B@xPKG-t2CN-!"7A'V.t@=󘀄{, IOKr4iBl*3nr<6<V V+4 ņAI=0ٯcy@̗Pm/}@k@/nҹ5ª.x#tYGPe2X> Br!YH# H .a@B^[If/P VދqenQ~qMӘ=/y@OD*Dn>VfbM-y~ϐzM!mrPi{^Vvڻ>I2q.>92FN'YJXnloy=+|HG%g 8i5a< 뫾)[޾$pRv2 NGab+=!M/tUwC= $ D+~Ȼ񜔪(>J? dЧ$&r AC:G5.gTmة\  Z HTwIM#2ӉqY! tӈqXZ?DIQ<3yg#9 aMX%#tc^ZJb#r:|H%$HH#t@=GBm7Ld.SualcR19Y>$ CLDZz2gŀAhHR7_j#wQӇ KGesjXʤC|[X LTz"8߀8XͪX]5y4]!VtIIUu ;?x֞/fBm/醑ed]?,%%*eP!L@^< D/dxm.G#$\x#4B$_>(b.tV:ePQ'g"8TX#fȒB0H& ,ft._TCPqR7D#B!) J+p:Vgn&yt{^ĀAh[ 7M! %!&Ay!:>aA!Ի$~ImGTau۠!{ ?WIE=ӫ>p_Mb \WizdC>HU@N+fbC*", sjkHbh Nay@=s2kT}:~VIo嗶 :EUO'u`O!q> nEg؇i8A;&IM@4 y-48JbRL:(&bBwA_hz‡ȑT  N "frSa.bR5=IUw5tmB3|쇟- 9ۋ 3E)ڨf^Va]TMܬ^PbCT%b.tkx&Ȕ~ ȇag #SrM ҧSL7-(,bf@D  q>H\DV㣀F&Wa@Ў$~۞WX%6a99EU;I Z!ƽ=tI+ozj`@P, 5Kk^XؙȤʨ^YPl\eUwT;%Z؅'1s;oz@~`{Id9UD=/ ʠ TB6= ݇8r'Ht~ sd6t^or,t^DR7>٠OW9]+HT )*.v~^1: H bʋH$_]hkІte eTUBl}!d.t󚡞#Sa6 's#˹uхF,(Bŕv,YGbR!b!9kF5A=GTÇ?oxdEy3Jx } !61WBf zg.hkzHe˛Aɜ,CTA+ڐhCI*!#n C/2EcYS{=9rvh' D )\SG2F˸wf9 H"On@-HVDB)'COW,h%J"˂#22tKz!zĊ{߉ߵUӗlCC_dP6EC1K N`beڶxthˠ8Ht%Ї'~ˀȾ3K"uܜhhC/8TBFڡ~'.v*3D Y>HBŠmfA=/C~ 4|B; e 9&& ȱsőifr bIy=-jp烩!UXQ9 LsxBYȇY<< ɮGh'&z̀^< oAFYMdj 7LAd6 {'Vˮʮf衞KCe>{3J_D@ev:=Z:ȾEjgz%ȯ:c* ?> stream xNaζ3fh鞡B(R* -HW7z0s+o&_ g^Az˲e²ӓLq'"ӓLY |T1=ɔ$odvafz)rw)(idJ]k#ubm$SzrཾvRgz)1=ɔF4XXW'2쮦H{'rUIrH9R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)B !BH!R)d=E50=ɔzݷoǧYx?~-Ra?>r3{xwWA;)xk ׷4+&7WgoJ"vWrdKR Pӳ<+Fg[Iw?)r9 Gr8IEp0nYvs3)([XNL&R(^Z^>,DqD0{\bg1> stream xYP[>KfISl-Hh%pM3IӺӦ'&vllvb_%;H!`lvm64̤4Midck?;h{?96~g$x` +[Ü=v̯~e%h;zo[+ѳ0e܋oXyp^XxwKw;oo׷-t 7.=#8 ? 磇E0̌/J[8kn7MWvPRܻ$/r`͗-~uA۝C}1pUTma=>rn|tg((ߐ6y'n x\UwKw_/r˔i)}Kru u>}u}Vn6潔:9'VqUiՎŰ[;g7|SuǼmF:!k(YGywys?uw=_6F>t](!5oQw,hu$cߝǿ䭫G𧡮E~EiV\5WttM8-rn,ymZeWw^ u@ð~f-oN <%^}]yU>N>rOnQ٦Iei9OPM,Zʣ2X  P49^}s5v72hՍH8i ڸՌȬg܍+Ȁ6ԍʉa ~RC!UmLeR:rX|NR=orҌAsM|GR7"'WZ|TBevݐmS*2lrX<,U [m@){EUCUCS86\@Li͐؏8BtSh)?>["J:~L(6 i萰(i5TmJy)R=(\m#;4㔭'ϔbѻJYn&Uĕ$i`'=KOrnN=.By:%)ǔC6^@'׏ vXb;/jdױP<+U/l ~JD. Y,=Gf d &8YfVb,X9f~A%ʎ\zly5U3˷r2kX%R~0u6AyI!yUXwNV;,3IkS\ NAodXs2pt ʜ/1!z+| djX;>qKTډC)6PN~c &8DIR/(G4KMdmVlHnspg?Z LV~VR–!d } Dֆ=tQSXԁCiSf#XJȅ }dKGT剝Ў-Ny*P FWhNޅ-kAUHM&PX,@-/l߸x]#CDR"-.SCXCx#]U|f(1N|_$367lEoC|tZ%%)z0e·UlZ V]t(?EKF}1XV.,!디IEERUW!<)cDk㤞\Rxd7*) 1}wQQUAJgV-1s6:ʃbRDKG|a0]|+?.-+1yՄC AQY~(s<(ZK]fPL+\$7za, <}8)Ef+s<0*y88k"ʞ$5܇bDo"MĢL}OR~,02y1H 2]:c=7 ZvXRcP8p 2mR[K +6ӪpR XȧSq$m>J}̡؇ d'xy?ʏ2va}1^V?ٹ{ﯗw{o`%+>oXym^ym^}$e endstream endobj 353 0 obj <> stream x]OPqڞ>C)婴 UGXEQ݈de~i W*Nb*YVˎ ˚}y/f~ð^_sl3,z}# gF+ q`L)/桒׷s뻒Zs d@R^-dDi6altONg OO=wcu+b&_u_zG ~pެd}ְWۛ;ۍuw7Wjzx *rk|i+dih,ڍ,G8͆]5 X+iV2^pZQyלeg5-U"C1HN2QCJ:Sχ(B| ]Kx *A" endstream endobj 354 0 obj <> stream xc``zYՆ P<ulvܲv"Ahq'jb}nnt'Q BeN;.f|Ai(Ohb^ժXչXof#NJ "iv.R)UT#j:rv]`ԍo;;ef.^-Vo3a톋?2xu~Rgj9JEmʚd[-0Cgδ.>tKh?ٮ[Jlzf1kB3 ȴa*AQ^t^*n)9R**iͫÉH'rk R[X@PDDBt$V9*Dɇ#d( IBEDI`Q0 o endstream endobj 355 0 obj <> stream xՓN1itXfQ̀Q"5+ | _A%xZŗD" oK|p""̓^x)̅Hgo #HD{纂@@X5xELa8KFaqK*h͒xWqYXKN}k/a DY> stream xՓkO0ڮM7a̘T0A@ BxA?MgO伧9->y+*<tQTz"hד JEzLCz*X(*Fن".;qXz,{T ޶S{ ׫8FړuURuXX^VyݳClt__p_O/nB/gagi}߯Pmv"d2 ږ vkv?8ꞳG@L锪f ߨydy5.^R(oEҕ8{0ٺN>ısYk)҃ 14]7"tk9X50!DF!#FG꾅Ez6 endstream endobj 358 0 obj <> stream x1 Om ]< endstream endobj 359 0 obj <> stream x[sHGEb`Q F5jQqߘnTfj7ڪ|u%o s0pR!h"]b px9n"h/D¼"ā$&D1!Ἔp8].EIڀl0.UdK@7**ͦZJG|Eon8Ġ9!Skz[b~"ʚat\ΐNUW6f a3lͰ6_d@3Wx(cT ƈ7cP(Pp Tȸ-$,v8I}H\(Wm1X!E/nq~>( Q/Bs>v@[ѨKdJ{Q$ch4ydփN3>Z|Fb2ѮO9 @}Jb{ihjX|Ȼ"+n8k*JEJd>dAnjZh44fKӚJQ {?Sj{06-dt3D^ьi_|: ~ZHY: ݧ2tX.d VԮI??3NZ \49=.z(PoxWٚv?/WnZ>N9w:z(~NXOϻmF,4P|<9LU̞6/~4vdhiYp_?7ˉQ/P'qۜ_e8T3'G0x^xd;;??Rٹ endstream endobj 360 0 obj <> stream x  Om7  endstream endobj 361 0 obj <> stream xז8IN` `LMpyV%w;sXoE}R8G|>*?H~W;_Hae `߿VC00ZM) ECwc0X,*paf^gq_'eE"UV2bT" T D_Ix˪Kf 2Z.eB$5%?lz9 F˂^sZf9$/JM63(U(W htaۋY%I=bcJXK{9Ͳ ('*ZwX(6*3KT{ȅ9wG9nf1%tu8;z>03@ ɜޝ<帙=Ir*f縙%Efs(h;yg;լבbr8[帶z<:An) b{vA'fXF\ G&{{;]tҧf!T[=Gn2/SwQVLKۖg1ՌGk}<_OiGKlJ=Y^hyE<1O-7 ڇnXJ69:;l,EIAL5\QRO&*߷Ɗꛓ>R:lujjZ3j9I$M6#8}Yc\c |!Y4hPVb5w*ȹf5#ސӴԚhqZb^pQיe[s\nOQB{x''(GEHu5~Cʸ解=$.DlJ]Rܱмw9,iLOǟHތ/% -QRJJ(RRϋ()%(RRϋ()%(RRϋ()%(RRϋ()%(RRϋnpΗ77$aI&%u$NĽ pwG]Л[*zZOZ%MC^6'erud~݌~]hVycu4Àih̬Nw )HT΃qmzL;p,Pޛ+HQ%2 6FÜVc"o.>wge5 YYF+yݜVL7Π jI&.i3Z6E!Qtظ*j:ӁmWX/ߪepnȔޝqmd-#%|خxkHP|<]j&{-^)T@-P?v6Z˱|aۼ\;.rE1 £vEޑ}:]6<8'psc?xw\<֌ 'D,Z^v;D!foXmֶzIjnj 0,|EEwck6+94* )Jm̖^PD"ZcC/sefSBZ!-pū?[BWYEoCPfd,~%GLլ‡瑾?x#KRE(N*J(I?cE0ﰱDZL?]m`0n[Џt&  f} ?':z*oW endstream endobj 362 0 obj <> stream x1 Omox f endstream endobj 363 0 obj <> stream x[w\ " jEbke֎|s#ͬ;n߾_i^:uD !#Q: !o'i&%NtN̥Y:9qD R!~G@RW)Pk 4Flϕ0J.d.b{ TQ&?'Q;P{h'0=#8`ltFe $A#ai_l#*=r+?p׮d| #"LgD0mQC2YABKFI1)d~EGRSL,H`'@FV-dy.L)AZ6gERM7F֠wOPax(ɲ$UԎiFU*/8yؑ [UZ溯RW /bsR]owZzkZn,rq0a Qnt0Lv:Xfo U9 ;~Fw8,kNv,[I# |5`8Ac[ O_o'> stream x=rF?2! TNɔU6h-Uv`mRKQ| 0`HXfR[@`lWbv[/nɻߏq<:oWv:>NΓ<}"LEFJTnR'FJ6˧O~[zč+yq+7ۧO^L3iI.e*󤨪T&o?èWU\?}%ϫOM۟>ypDB06)JanKfVEvnr/eZMfryjtdL~-`kB2 nW_ķP2S6^n:frW/*SSCo5\/T?M-b]n62~251YOZc~v\U{9q 0= r|h t?^RTlU%R rEЄ.a}ErNH!#X1(Ͳb/~r<=&͊D ]]JVIC kyrs̙8 f QrjVbnrx1YB2?'-zNgWݻrFңd#?s)@Rfh'|D|x𜟭W0lw湬7SmKpA #Y}7:NʮX:isl+ǣGH[G&RO}&Ɗx= [-C,ekȻ)u7G~= '7du!toyd*Y=f1G;yfF;iH[#z*3[>&ՖYr'gq-F#eCEN|vF~ l}cWIypnv&qbŁ'`uZ| R6.d`䎫*x0]_?{V$^Q*:n19cNUoOg2k(NUqM;閪!MK<4-{=I||hf24QY[kBjBEy'i iH[ϓKYf}q>MnOy Q@rVhEOŀں격Dtk>c̄jZ`.=#f4ifTQQ7+X7K=1KbՍnlq!u3RS~q mwzp`&⻥ESI3w؊u;޺bwr4eJҢ9 ߍւ!벣נs"lSb  i*CpDVvHFlF~]^DTk^Q,g~N=gn~^=Df51ΏEcΜ*k gNScv%" !]X$nVL&#hn.O:aLgφ͢'E34Mqh _>n)2x{+ ’0 iYئ՜[O6hɜh?2 F- x=NᵙܬXto$0U9Yb=K+zYTv \׫[cGgB%K`[ekTY 4ŕ^5!27@ N6uE/-%xj X!`Tgn2+Heb%K,H%D֦U|~j;.-%eE}NN!A۷ڽ.l6bcb kcCy3f;6lag{oY*8Ș2_p K &rtRxQېJ=y w`%jeFXB),'x!qRlNA\v}kyq"4GDXMWtVyuWc)Vgo!\|I{?fv`) dK^岬6U{Al^oiBߒ*L*dn(^]׋06L`E9*zP ]g%i[ܔ5=D& mh>cTAZi'x",:`8,7;:%vk^nKwlc2З<&Î@f`#kKD$!5mュ5^h6E`u# " q#% 8RP}'/.T1c7B"4d`26UԢmrYeӈq@nxhWw&g$\;Bzea~OYȪ͹3+~L Qy$"uiӈJar }l4ʒK .BF~*8"n u2]}rL[w«2'3ץFtSg ZVy L"gIaƖ~W) |Բ;Tn TB%ǘtN'C@K;*vg|o6;~A9c(rItp_b !(F:aϣ#cvR,h]@2Q?Sۗڋz ` }:mENK"\7E18BP:]"7Y%.p2;5+HƜ`WH4%:[c}ζiJkN NPv?R5yE掐qogFIHh룗$Jayg B'x*1kH\oniAg~3*/MV{h:zo .CoU!PՖV|M o' R|-">_gê Pi5ȔOl)3i97Lk t|32o7'ɻ(Zo P}%TpOԌɇLBQ= |5νb̢_aixD(J&gBt _'0A>nhHlE`siź=/X#$+3xb'2N캗raer m Kz |`?O=<bJjFpÜ/j0cE5gn>R;V͆:PȁQĹM30t\AۦąMFWK3 <:q2šՒ[a\Ra@mõ{ ,I<4Z&/aE0U"iy:0~ǤGj؂.}ɁUdbJ;mK](ɬtQk,+ݫƻX+}zt >; -oh!=+auzNBR;wD+DBϘ4W5O,>BgTv;yc KՔz8[̨ saI0NFd kc4UfP85·CCpX~3!B6 endstream endobj 365 0 obj <>/F 4/A<>/StructParent 45>> endobj 366 0 obj <> stream x=ko9?4p_Ũ|c±3Mvs7@6d[M$,/6e=L,u"Y7Kjz5?Wbsy~jays^6"z}v !e,(3*.TR4226E]|/_v9.v5|}'q-J?\2et$~~$~.7 MFB A(˅.%ZeէeNП&gFNәnN33qpC?|y|@æ*k3NOgo@ a|5.<lөPFE|0qsם Lޫ$Qj1L}Ÿ^ϓEAQί^YRnE bF#A3} ge1J1H-bEUBeBzo/oVYtl)M,@ H4+!O ?_4q_=>|rm_dOw_usʡXBF8m-PyZ "%5+3Yj]k6pF4BpʺRP9T/ҁ :+i^ g|$Э$yδ|BpugXTc H`@KPTxZTo_+݁6@3gw4=X~Zݡzȴw?j7-՚;W*5hZ &Gdf2ŀ| VX!b,Y~fyzmbj\Va%L Y8R9H|Vݶ=-@ L9X;*wFSI:U؈uyh_9qJ,PZWix rdQϘFdʴDޏQ'jy^&b=yv.<@6WH{R/1B4h$y`eߴt}y!y[b||u ;#C?d|:0a-BϣTWO#2t#La|U6k/,8ɫr۝-ECOڙApX,F3UyGS ҙ`g`m ځb'[ސ)@,R%MrMY'ԴWRI2uicӪM v`8Jd p)D(/(YiF~z^2d/ocܯshI8TyMahE9~,L`Š~Vn :cctƸNU||c'5 ,ACXDɵ!h8o>|NKv?l }4  .$]GuYsal$Ă8QIy^Md)AA/խuǒv0ժCMS_֕FJ]G$K{zD'YAG$}\!}/ߦe/3aФȀ[b7 zڟ*H#EQRH: \/ T6Ud+ALUC7H,\Goޞ}ߒjN_V'hb 9/XB (2S%ю'f7@p~] ]..ZTI:`cxm NyA% Nr?p\ƅo"K _W0LPYc`B5q8n;H8FmX/U*A*o4(ϼzW|Mc2]t%{ 7m,0`.*.2~BU.Zq |8|AAk봖Y9.ck lP'l D{Vɞ*0=F}6`<]dx('/P0RT~ݾd~b?OV^6mOIHI~ƱuY=*t. F쓴{!qM808C4;"ľ Ua;nŲpTW0,+W–X̰ƄTbsI)LR1 ["ta^(m^RT>`} !:B))6rW͌67Y tD կٗ5ZboCb9n2 x¥{X:rÁ:hJ9MRz~JP0C0P U޼aCM$[ğj`X<,s'Df$aHXߐՑH^DZi.cQ Z!aV i0) nn* : 5“Rg 9.Ɵ; HuCe;<؂v++AHtTba_S&%J{z2 x dgr9nX:d)pZY)4G_] }HmK3g$o@\o|{D s$Z,oe塯akޑ梱,_P6S*"Q))K'F) oq-ȅŻ OTߡȪF^ǣ]k w_ͯQ|0qsH3+H Azċ>NWöLE)\˷BwL˛]oF\=0H/S򌭬c:q^^l~67Q*%*.alt 9x ?-CzS״0Cn;_LnJ k :3EisMm_99YACwR ㇯k ɠt6iZ{)(RJ}cy/e:ws $$ЎTna,0ihIkۮ}(pi٣[ lνl]nc ץk_GS^*Y9啱тH^׬c؁.ϫ=}SN*Cڼ'6mI!*Ynz@D%.s`Iun?km:|z[= k%?'A'ȤĘ̠^,8$9jBAC%Isc0`Bfu.ʕ\4L)hsI^}t>G<UuZ/+gTEuMFSw{1Yߺtq+{:[=U֟L%Jnw7%Kw;&fQ/f#h UiG?p16κf)P/UM9 >V?vkSnoL?lj@?*֯qyFRTN]tMa%H?̶8*U2M8}?(1+ZZ5?w䎘Jd`gzj)"=+*neݵi&f&v)ME t:e~L;TUL=ߜ`3'U).j i&&v*q|9!mWD&f#'=9MiKF:;¾}5%`|3=? "Va8畲 ߷R6@"SֱZFV)NT-7B }cq=2k] 2֌C,׵ޮw\t8:>nvr8< [u !^.1٬ouXk4-q*әSdRvKL{tdGk?D2;6 <(k72V3YIx;G] Z}x_+ n"x_3],jԝv85x_8<;'y Sq>ő"$D%['8׀qp![ H/p$ludv mV0)ԁyK )uռQyԑVXÙ4[iu2>:wܤCx Jm8(j.ۛd!,lV&z||GI=W>&+?ޏ d5=}1UsDAEf;!҇CGqvp/.`b4;P% %_ ji 9l½e:\l8)sv+Rd-crnb‰yKx/wUC$8Ůy`clAi\I2wUƸp{{j;)bU2u;gꜟ!ؓ|JzlyoMyĸ?L\z`i"x[Z5WӬeIKcSU )lԦW_kkN? endstream endobj 367 0 obj <>/F 4/A<>/StructParent 47>> endobj 368 0 obj <>/F 4/A<>/StructParent 48>> endobj 369 0 obj <>/F 4/A<>/StructParent 49>> endobj 370 0 obj <>/F 4/A<>/StructParent 50>> endobj 371 0 obj <>/F 4/A<>/StructParent 51>> endobj 372 0 obj <>/F 4/A<>/StructParent 52>> endobj 373 0 obj <>/F 4/A<>/StructParent 53>> endobj 374 0 obj <> stream x\[sȱ~wĄ07\R.UٔץY[Iw ȤBl~ 0`HER[k\zzz Oڛ/U~}m2|i{ɧV'ͦio"BLIiTVD&EbdfdzH6/_vܮv"\'@$D+"):ɧE]&/ds~M>`畉É,mRVNOshO?Y%'Οa"3:2bfҟfs~xyK2KnǿA|K_[UMd?τIl𻧧@UQ|.p7>_%P&u1B]On6<2^R8?K:IWEqO% h "/Vfs߻-l^*dcZO4wLif:e0PK:`8 PEV@=I ^l3 a]ahgM U>2oP!ܣĺ6c$`%s=7xabk Jii*+l҄oKpC[@m; 8nK F!Ѡ& _ʰ/-y TմM97uMFeu; *}& $Y7n ^ygsE 7o˝5K>FJ ; ЋOxG2;یGyyƖW: GM{O;  Lax9X]eю՝iG LK-m"݆qޮ7d` \(3=0q]k{^pʛL,,u&eᔦJTu/X(x|N=SXmR;&5{EXl;U"5(e ILt$Y Zg7 jGK b((l|#eUa v*:Yq"{V6X$`<'tz G*055Ypok7MDp*a{##){h~5W7LXROLawvFH8O>CJ!c-wϤ Wf:-*&KָSn%#p0cSEv%z6M:%gŽ߭lcp笖2|ί𲷂JuQ 6kr*f$Pya5B@Ñd9<!<6|M \:_ہiGp+F>d~t{$4~<&Y>{6 S_L p$yS}z"vb۷WQ c@HvK{CaSMyG#80jI4]OӶI!lh=~5"ƈd}WwM@JunzkιTe:P}hltF0C'zj+zo15]&9  X`@@A_Jd \[$C"GXs;r`>Pj0b,G#lH~ÃZ`#ɶ'~8+ {Ên} ?{rߜWa'' "dz,z+C$( Hζ"9UvH.U i1@Rr@@G b0jsJ]aRx\XAT:3*>I&7TfujrZpE?'<1w!q׻λE8Z,;> Ef]sY.}D K -H.RHN4`e49+8ہg}CHgv 0cnZ:RQ9kN9-^0عVTm}3luhjP6W.κsnqV*i1;`DصJ +q_cl(_`U!w#hZ\ 8JZMej}dkg5 EĵX]ڃKi"lȪ38|Q@twH/9"ЋSO›S(_ApD]ÓA0.6hhEK{킧5>#AWFV\] ^q7#JNt峱x9w#jMLHoT?uA+{Mc{q갿@^v.^VKN ? eanT[pߔnXW:8c&  ?ֽ_K;~iVW _Sh㕚ӇQFC0q`;U@y߹_**㶴n xхj9<\ubjG:rly|ωY2j#G()!eGe_[Mн3T,iF8Y%c.ʕǟS,yWV!;MĚ=A$4M`_͋}+! fHqt]F]#6Z6GlRi1g٫.| }Ll9T"4 ]p>)[BaKnbn]09Z&2h:ݫJ֜ثLӝ 9Au5+\.H%ۀc2Sп Fj 9x<57nF7\A$mc$K$ښPh)F=,ΣUyo^$fH[hk][^iϷ{tk?$#$㍍ ~CW9ݢ4⬡b>&U|cH5Ź/0%}1m-]w+/nyOdNI_rzUV8cH`mQf#9w=XO |mϛkI9h\ .]v_l=8;:|-iS3Ţңy8>l?nq;@oXvA!2 ГH*oH@Ms{d0%*ؔcvH婄ݶ/0gDϺsAv C/V~ftQo?؃~{!ܗMg6lX;>?FXǤ endstream endobj 375 0 obj <> stream x=ko9?4BDfս3I.&2l˶f#;7믪Hvx<|8f5Y$]Ed[].wG'zyQ|<ч_nGoWbڬ⧧OX]-e d)T!Rv|]>qpN\#<>9zŊD^+* e ݶe]|IU\O|ӿ铗_?{`l8Vk-t+f@s]|88yZeSG8éRp|?ɷ? _з^?@/L wLNSo:Ǭ _9¹^N7OȺ(f#yUq~,JB3ϫ~4P3ϔ_z01W{xGRۼ-Dˁ(B7WK]n R) `AP1zHrahz p5=t!P ]~ݏՖ!TA!΍Uv^%nR!Bb`{I]6^!J*xɍp89A^|?eAp K˩lwr9eMg$5}"p7ՓvHǤf:$t]W(}&|^ h7m5սvm>okz|J4r`&Hq * *(P>[h\+KV1BmCc+`+X$l| ]Y's~)#u%`XGDHqǷ7E s kEy @ Slpk ]N`tlvފ3]U{B'l}g#?`qY;_ \g`_g >'7c wv`F> xdAk?1 { j![Ph@mTҥ}8Y mڈfunw=BzlJck&ڤ]i,3  bj S_#T Yr={b̡l $y-FR!( Э$l>Mgu59]d\9ݜKD+P+g ' $ ͠RRu).rtQ@xհ)BL6(JAhˌR$j 욹Vp/F90C!^^y7"6Nܺ *Yz^"(;^OhxY$(:[|-JM3~H^P;Ch9E_ϪDUMEj 6#{H Ep^.:#blgkcWi!-jbd pd絥S;AO҄g^: 4g7݃OVtWSj7,KQ;aqɐGK<\$JbuƓ=#J !d u LP W>x=]v9`Oh~s_e7^6ޭ7Wjɍzga,:{nپ.;J斐CJΎB'6+\)n˟:y׎a1iRx2M,Rcx*T;_qLScDE(1H.]f]:38(Y[*鉅}p뉍񅃺v~_E,eQ| 2|(paYQy~̚j&<&ӌX 4Y+bII3LQSTPr5+7 dD (V` 76ofԸ0yw<1n39?6X%I{ wf+7b!V=r'Na (C7K7"̚zPN+C^B:@xA83RmT$*%HuauKa]ꝣT*Kͤ?SbIi vnF%\+ R+au΋ R4(d'WzsJ7gFU|PjEfNr"uۉyTF k&ʺ@xI)N. PK0-2zwY@]&\uv^bWd% +Fߣ2 0w3uLoAxdApШ&9TEӔ /.`-s~›{gD_ٸҙ~h]EoFy+=^Ädl$;udD,6p1cLlUsP8ۚ]:߅/] 0wlkm!(Р"h.R@ m"$h t@z*OߏePBwNAXQk!,:}?P=JZIo ń m Rv- <,$X(bi<C49kRMw |(b$R&ʄ.8U!EB_"K[XW-oNCMSURU&SPddM]?Yٔ(waVьb:K [\" {ElDhXֲ#2+[o_">m`&l5)_s[Sg*daWX P5:Gv ^aexWq5xh\W NϗϯʨB3Uof`d~UQ^%#2ݮW_gJ?HvՕ1%ƃl: =,u@YKӪ[^6mϘWъE pLz KFUt]RIKKRGM&IՎ*V"̩`9XօDņ\<գz30Lxl ^3M7tҮ˽Fo}v TX4t9W {&|^>G`w=&;o}М` 5omᶞl.BOhЛuk٭t]2]Yr驃xXLVV JisEYS~rx.E.e Ss G2@ߛu.qFB"inޯxֲ!Dd0<ٔ51UӘ x^qO2&y-1UxEQЊv n/Ja/^$ȶ#zxԖzc4=cjK^-#Vy:ձ@ b\7{g1ޚw[y&b+SP_/MXmR9s~E7] ~jgY&sEYo.@2%p1rOP=Jm_l|`FfmL}YtG6읅Lڹ-3!{P(P/y#UWtJ]z,↼O\xc} bS0;@ e\u㐸]K:%7@*þg4}E|;J;}%p-gIPJM|\C37tm؛S4kdDC;jlGABo삕0EFBfA.E8:9~]5kAkN.kd|  I]RG~jr7:=5]P %wT~ O(^\hr$N,@jK'q K]9ZjC›{ w\u4gKOr'?/ +;E]޸ :x3U9J3Q ْtZ|L`c'x[*ݔ /lvv}4K eb;tzu=N)~WLBIZtGKƒat2rpʖ7G+CF"' 5^@7S&Ls򪰦EKPo3\-#zloiveaX5[@=DxCҪ@ku-AIt62 /0-MؚT~e>5-#}HfJ0죔zqwMzhj\V&o ۨ ^ˬT+c /iGEȐJ9Nm-_uv[ ~$1 hл =ֽHRGlt?B`C%v+Ua T2h6} \fe^cDB 0H׋L a-Y=[QWg0J6ܜ""^>XXHV#~-.Ћf(mF .2@1h,]ص,lǩ L9*PS[ mG͔SRf˩Y&%ꩇdtv"Zj@KWKm9/;w:f6ZVE+E&Cl-@WrXf!x)*2kbDbޏPV,OVߖog1aϳD·r!N5AtQ́*Su,z/ 2O1,ZMH3o(_Aj}WΧeA)UOɔ _'6N'դ5> Ú_`i @KYtӹ׮=z? endstream endobj 376 0 obj <> endobj 377 0 obj <> endobj 378 0 obj <> endobj 379 0 obj [ 380 0 R] endobj 380 0 obj <> endobj 381 0 obj <> endobj 382 0 obj <> endobj 383 0 obj <> stream x]msܸ*~Iy(9S{:٬KyS[ci$M(x7ί@t[r3C6 Ah4wxx[_/Gw;zn}jsmeqrvZ3yɚ(Q6ZR)ϟo<]m餥3DWˀgGYQ,_cEX!k^r])y~ìx_ϟxX8 f{ )ޟዖy/P.(tf/5Сb5G;>|٠FjU((kͿ̙og/K>$/g+^mζ83ucd]&;.^VK J*ylKdWˆ>Rmo5mI* d >L!h .ӕՔU0 B*^=-ncu"Ve"){)Sց\H-URXp0;F[|7gn ‡C빜݃Q r]{/4QyJuC0730pI2$4`H D8 {[ /Cx~R TI6FjɤM"~yt*Ml{BXATB@e=CC*u O|h2-0C`!ѷoOߜ7۫b]|}2wh1U~ V+4mZ2khխ_PS/n5[ϋv46Pn_D>yg6`>gmD%5f}/8}:'IUW52[Б$zxjk<4 $zuK \amq/[yH4f ˻+u<!"kl+]iDD-[Od#I [IK>OUj}wqRӇ}z l&Ц %J1miܧy?3׶uBd ?auZed*[kM*IVt8F&'A$X 'TJVeR5l R&yMQDn܅4'kbӄ63Mgάo•Κ&\͛&cm e8qא}2[*OimeZEVpr)%)V2rЏAɩh{At WXj]Džaޑ8P:cet#/3Ł5߳gbK -&J*nC' xXl ,,F4)X$\JO"P1J)G2(p \7𔭳Z2uk3/tN:h᝝;oR841ÅMj3{+{u\ ^K(75F(BL9w1}o L\T tʭrULfA>&ƹ8CŹpL/a'tѭےngy _f[S6Q)F`qqՂC!Eu^E$WX ѸV5^D@ 3к=vdhw߮n] عh04bdR.&tv݀ܯXȋaOސz/7 b.@Rpv}c#fxGGSȋ:Âo<Q˹ tfc+:Ya@Z@Dt~ q"eNҫ8p͈b : D`D'W}IGOoTq3abN LLC~f7-ڵS?5P{WwCm(D—M֦r4MĨaG$'z5/HtVkg&LZZA@x`dN)FyYo67I6 XI2'6YWG7Q^i엓)B[(>◂?=RO h &Zd Y P#`9/KZ@Wr8lB?97v߱㒜0[^Awq P'䳇 p95>ƿ2⏏^f,\(GUC5 6ĹV8^, FQëG J~:\ͰNonOљajK\5=IpfGXgA[qtW>1ߚlWNv*Ԟrʭ)y+__M'S;c+OSd@3mt66))jݤ'$xTd^$9~d$!s~s-W g+/8%+Nq@{z5[f3iT"mOn 5.٨9%wO9jh#/rUr4xJX^ sF$Q#$c]&I.fv" #g.+^9rTʛ6F:?ffl%h3*iqj̕7`&3x/]xk?K160)[eӌu£|֑ᑍ=|i|/q6~,(RQg7K^TF.u햾 8<[X2BCIGhE:S̓^6ԚskFH-=rJ<1X ʵSQMB9Kc!y9#AYlPALO:I;2kR\UwGusBhש.]1nށ \Ыocdb*p$Dξ;>$H=tE4I,)-dD(e)8>(GmM"ڻ?riv@`RqތC%:J 50"ڥ1A6AEiLY#[ %q|n(d0)qҰL*ez.ܗU¥!޵-|zx> d{BI¼@>YCorhOfl's%a;q6t;sg> bH;?9^9|6Gi nEo@xl 8'lRƔB;fOaχhj#ZkSl0y+5Au(tNl S,˝GE 2܃ҥ\$ZÅ`@{CV vBIBi*ge0IB<"8 -;}l0CFĢkrhw?LЋH޳j]ƯvpMt{Ef[WJ-eiᕈjjF(10O鮿\P{@;JRi0'k#0ۧ\%)%cS *QR^.'3tي1$@rr[:^2Mjy"-Jt;6 *$qLJGa%Tڶ:Q6f_Z^ۂ[wM]w\]ҭҰW(=rb9eKvduPA,yծĵU}!9evvOicipU|sK$f[xN ;̧_lsc?  W#$5t/貊VH/:G Axx&û34H Dڵ[;fvp/JQ9I7=U1~@E!/ 2@3<1J툆ᙨND)$3-Lzpklf8r/TJ臯5'0j[.;k$,nrU=~l֋A |#R0!N KS>&4xvOCk4-Ŷ$]wf]dХSW%3 eu8Х#"' 11] KĄ@)Y Τ?Ʉ܁D2!%D.{JLoyTIj%CQcYQ6}M^Ä|d%xG= {ϝf|.ODw> w>{&BҟR>'Wcɬ8BIj{`2LJY(r$TH"&ʣYBF^e6n\SCO%p=0|4 S"?S&\O xyOs%sUQ pmߍ_'JSљ(L-hcәu0AU_BmH$l\t)$ʩE{;&%.LnƗvMr%}5||#x|i9q8%1dR"$Zc}NɅ[L,^v;jE-cLHP5+oqΝ5!pFN\rMD8iLczƟ1&ƗKTWPr^d.5g砄Ǹyaj῍ ~\5gzuz xG KhLa32ǿ{}/AyPh;2$Vi5Mv3[Y>vuu"8W}˸AoiﶸzW9So cF[=)͵4eZr"Mv&86x`_ lȘCimb'x7>@>OwFaիoey][]W>Y+v om)ힺ _[-mS65 , -WEb > endobj 385 0 obj [ 386 0 R] endobj 386 0 obj <> endobj 387 0 obj <> endobj 388 0 obj <> endobj 389 0 obj <> endobj 390 0 obj <> endobj 391 0 obj <> stream x=ksܸ]ʇETeލY&wMm%YV"kx~8 )\]$͐Fht7xn>tyQ?zѻ_.ެo׻qq'BRtEcT٩Bզuadib{*n>qp-ikɻOE[Vx>VTGJYl=铪?>}~Q,TO^Z<pbܰ-VpCsŪЪ)ޝ_ֲle?4zӥY|\wo]/|oۊoe*+Uj3ܷЛ?,YO/l<<-A_6}$~B_Ha ("Z ̠’p[>Z>n=@k/_K%|q9AhY/,P@.T j[(:y2 jꞨ BTFA-"H;P۰9~-ª4ahB7`<;}^oۓ%[I[`OIunl\[^[An_n?§ͤ ㅏi\uFp\%x lb5X{l-Z|}]/x4mw˕zw ;P{Z|bQEp^bԋ_E#Įg{ xn=R,fЗ!DgqׂdƽU|@Z v;`y5_Jh,&`KdQq=W.5`ȫ<r/ $ +vk%eœX+6a,P[(>͍57u[ A<n;iFLMN)kGkma5;S lu?aNM^[tۉC`kx+v ]0ak/+%sW$jqPiBw `_㯽o).)aɚF/YW2(/ԺhU+mFՔ}[;Ky62ZUinU$X>q%{ZzZ.M0^)OOzIIœFZ9aZϰIQ2̶OaNNA^2 0$iƻJ |[V?}KqvѯdIȢlÀBgϞUSl`c6QV~z.򒺶"Y^-v^?x%xpϙHQE0JQq"vMTK͍)goLhN] ΤlXh&]8gԧ`Yc)*_(2$|`?#/QW?_fIlᖵÈuob[ cFdUt"ƌ O _ L((F3<+<3H/+$55 ?Y:|ƅlݸe:uL<2aă)!=@x4Yaijr#69ЦvrK\tYQ(c#a!T2c|S _ܟdTRu|y9},DZ.&rֿw&+Nʶ+0#\״90ˮltj5I ׀'5bHHMpXz&Ld4jW92>+YAGߚRGHP+j({$N8Ք6blJ9xM) kXC Vk,-\:l)Ujx3!gԀmf|{‰fE8fad>^uL]ۉl=EW8=Fv SÀ~Té=h8RApE9>!06J 1b-Y\B }埗5Zk+}ֻ5A 7 ȇz k^tQB/D4>C>`WҶT:s1>XN2d##GAfIAAXNmQ6O}L ӉRVYFUiHnZwRm# J3iIʦ=f `GcȠ\3=8*Bh&X dt!S3zA9>מ V!vo|}Q8ն05@ a73A)=bftCTV ̾18 pe6r$x`sg֥H5?RX߄X[p YZ#ma7TWTm@|8BEʇ!7Ip3PLRAc @f$NC1I_ܛ ߙ)̰1;ꎒ88&Nz _CzR)1.`,>#ܥu&r).`5 0&]ҘfG` N!zW "-!18`Q<.%V2RygEi䴩V*Txb|lUu<{f8 ۺdr7nZNvXha{NZ1k/ǪXMm)FmqνG\ \ñDVFq(66k#b1Ot45c뭏zH`<шNd^F1j37R@HITi(&N{a\vڃfEPeDfV'EF B;H/vhZI`t4naĆ81'2:+bG 2Q!`?Ntغd=zl_0BiD?~d&MXa| Čab>bcyMukk%a͘xm+Xħ`;d,KUCIVC~}쏨_30 }x&D4X>~\&&T1KL;u.unLmm!]Pf;kۘ[D ϱA27IхN8pZkGqc̑6*(rԿTE Yx! 02c(zZ<q@5*Kܹ@aCQp |p=PCw'E.lj% K;'z .Ձ-K72>nf{0E3``MN%;.81@ʻ z,J27*[Hʧb 7lWdMA X)D⤀P7"X5)HC~շW=qkd(ϡ}8u3I >>ul6 ;EcTW{BEBJۧ*a? > `S#43i* PB,+ؙ<DZxxY}9*\%L5(Nsܽ:O>Xg/W[ݺ@[ad/DWdVu *+VF>03 xU{Ӹ/=I" Y.kl8!4ATbRE)^QXnd c(~K Wy9lKV0O7^`tgvUgNu!w^aBSQLEb3]'-DkJH˼&/[U]Gf@_X,5ߟY瓓MQł\\3V3{.pys8bA.cMSHB[Vubf g: 6@ zyQ%j .;oqXPoEaYyxt+`ٍ7(?'b ~QiPh1h` ƕqQ}0{tTiO!dCvNu]x.#[/veFvG[L{n6iqP&IEyٸ[OœЋoL](T~"+|.)ѪVB X=;8 6-lF32.rT`?:nq {%3_43lj6/z ZG8xU zVDkm j9$gs:LNjfEtS = M ^ȬJ5 jXHFuqB7.3KE3~uHJH3ҦU X D!HKzyR:ꝡЉ榶Jba }ҿYze3ߔ^2澇flaQ;ǿ3 Ά*wso9Ƣ =VH6/Q)z4M6eւX=鬪W^FtմS$TW|sHC5%+k;2aJӅh >;N>+Ψ7H Hx Fjk'5A:,>d܊尬3|YqAXĤK %rdeD'Ka ia_-kILH!Crɚ ]k|.6:ax5ip@?i6gUc:}A *u| lf Wѿo*BtlySNWAh@#mjB['2H9gZHç-K?װ䭐-S|5˒Z"+Z NVi%2ŒXGv /k\d 269&j\O?9iu 5M l_rB~G| ,[&27}j8.ѕ5hf~M16k=cHݛD:Ճ|RZ,SI"FbQ#E=jO757CY]An~$X(ZufO>1>'+(LQ[ brӊ]"(|РMjKb' M VѦ ]36.OYv Lt]3T̈mhK⮂Nd(^*J6+؎f=4>dƧ4>ʛ0֯Oo&kiwԀ:ǖJ9~N,[@ $%ٱdM0TC}૏HЇmAUv۟>|\0/˕h*iBNͺmOն-ZZ]< km?!“gw oi)H* {KDHa KoǼR$ޝ|τvo7yj*誑LL668a4nJITªfNѪM y,Z!u<&u{99yx!F2:ЋֺWw?~=ȷC: Β,S3˞8qZ8!3 4D$N#OR#u3~hgy#3QՂ6^~GV5Mx)/`{M;a| Ʉ*ԃgڗ EDa{f8ݿёO> stream x=k7 ?4A 2棛Y;;gk;88@3sFׯbMWY#u"Y/փ:}߾_^'ON˫x{f{7ݭO_.o7vsvV_^?=~$\0ZPuuQEG<~ -!Fo?:}.fQ{hV(t#.L.dGeq|Y1G??zɣBpB-L#+NJVxsv?F&~;;b^:?ѳo? NTptC_c/,BW}\To%lccSŹ^^nUq1#֠埛Nn6<{RJiSU,K~L(|^5y}vbYmAJuVz0}lrvS%~vH-ZЭ3BzO^r[0tcujc4=T)miM-(~%rk {Ei -J;nvֽBHXųo/}Txc]~!b=*hbWU)(zTk6zs=S''zv?? Aҫ$f}/Z I_4&R!,Q yE Z{n?v;bMWh`\ŤI(4PNբ Z $ICЗѸLV)Bmc%+`Rd#j`|6jCCVu tQP:2CaU1!K^|sY/bޜ|}>giKȘATB5j~f ˽77ZEXS}W%|v[]dzXeww'U  }F[|qU~+ @ CA Iȭ6pVNI',mwNcحIpŒ6C0Pu A IE`nK}[؉nwDr?(EG_miq2 N cQq_ š !d ZP7k~ҠISk5`X 06P`Ł.=*ՓL”W ɓ KEl}ͫt0BV"얅m`Bc>XƨcH j Y: X`ZĝQ*>E#?x1o"cb v -Ak=3olXO+Lu^oR.LoYʓ '\ÃB6U''RZ`]4`Ṃ8Ru[/ n?"Kkqۛm>QbBo)}RNWF/jU 1A[Qi%4qej0F0Q2/ٮav fq}X%eFՍ1˅B"Qjq);HRԪ618R%܈|zKLpI[PFdd'Y؁kRjɵ?[u7d/^EJ: 2fߔCJ1MÆVʌ Ӥn 6Hvڔ\mMYbCYVxɔB ܈JnM>Qrɔ*CF9I@88 `RKN\ӂǜTPO%:q4gU;GD%ߓBm`l-Kf7N ]ӓvC M箉.(`(1iUDEZ 4 !-%ݺ)n<*Oh@rG ?dX%m8&8vK,a#{9c)s:n:nGi m*%+1*&:B֠PeִP)9)5!Hn?%ȍ] mrPYpiG ib(g'lkiO?e~Dm_}Mp];QR=1D9Q&:=MI+t] "\4혬IYLJS<5l>EuZDŽMfQ=$cNV9-45=Uv7ʙE|r8mqxR/to /#t/YssJOє XYʎ2g}0񬯛I< Kx +OzaqP3 g mYù:K#wvls%rO%N` >s^9-Z.0A&QvQ{v3ji͕$EL656Ȓ[TƏ`D@>OT4tdU%(H :c/]n0^ j?{_35*X墳AlKߚ_jE0kgD<e,0<ԫdR9O鳡ǠH eB3ىEe\\Po Do ^КE NNXI|RWB4igGtiJKd+0/9IXU/~!/')~0%{Y{LXI/&)Es< Aj'O@&"MڊW7,[Ʒ{uئf{zYYh%y`|e0:[ʴSXAQ?H=dQmglZ[{kLYLkAnjw3V"׻WWaw[{_7@T1`i/׻F(U{ k7Y{+}Ϥfvُ&4N2`\om9ض%lFXOfFxʓ2?}#/OZj[&j;(*1h fK*d99[Sޔk8쓛ƩiB"k$S']3urik}|F#|#Q: xnI xCX1 މ}]?P%a?E0QQOJզF}%NC$3{q.K vTa|vҡ^j i;pw[fBJɬ܊2٢Aۦd2@H#U 膨R0HL'2c4KEXX*.W; tVI!`*sɩK/鉩\y II3ߏ(N*ƐdCu('c 1R|VmK'{Jr!Ptxb=<ʟvCΟDMEnZ~ThtQ(W.!DHYaG.-1Q9jQ;8m\hB^%&^Κnn.ꪞ]Ymv:M[8W0á|p T1đ"xWBx?h ނeR5ښA$;Ko\|C*l/%7KO{f|gGhxWȦ Sx-PEbWXlrlw\z~ptMApYl&T O>EqIW$hi5u9{\}Ϣ?HsKp)@[E85+[U x579S%cq`B`/8\Ϯb0UP9}*4"T~ɒ_2OE#G%]nxRw7Yԓ)Y9^,y wQ&#K$dpΗz~;oVsA|`EM]LUQdpD!0D&1b;b%*R?VyDY|(PM0(QoYw 9V{;d]-`/)eS62T+]?TRwl>'"[L'Hw6nݿt |Yw)}tKBv~q|:tTzG 6~3W5_|b(/lE H)Ŧlh#{V[}f:`F"';o&eS oc  )}P)tsZ58&-.N{X~EAOq}UHKPlQ.H6)9h%LE]S1t`w «쳚^u?ؘzCg;06nW?qV=B8 *.~Ufxf㑧`YhG-\%vC :]AQ?D j `]7l~9Av( I`bQYׯ m녆n5 NLJvϧsL[PA6qi6 qn@ ݗP*ץK@,V]5R״a/J/ a; jª}tkMW;UtbG{.! f>qh+' ѓ& !$=@nɊ vn gI[|=t/=f=Q{#FDW1\m %ցи!HU{MXt:.4zzIw_m)o^HKx~SXL6DKv/[u Ƭnъ )X>GHy z'lƧХ55wa=+*6ru@F۞:TH~aR2͏\y8pQ-S]ݟR(t!*MP(~\]k]E|>F S^P ;NDLlMRΚO:Q&g |M4 ,,62٣(fsuh:nFXYN4QpQF5Mrېl0?-# *vk XUApMZ(?lm+x4@o[Zk'K65Wt{ \ҽa]\ rt6XNWTyXW?kJi;Wؿ _JKidџ{YlǶF~]s9yO%maI~XWh s={ȝ ˍ7ݏ|. ]*A>~ Ϋ9 C;D;?3]wrhgn8}puNg"L`$etkѥpivWy5Пvwڽk#c%J:Pʜy ǂ]?9w$9H@0 ='tC_ʗ.$!(Ps"*ϨJ" i> stream xZo۶=@a?VMy].~]|PΦtXލ$}q"J$DE'=]n褡D9$5 Rcy³HE£4NjA]guqkt6E.f^I΃/o .Kl7x(/w/WCij:jM"E 曘 ~;?۽"Ox.X3!K>&1 օ<آߛ :Ti*X?i*w)L`{:.4(5e$ 8qx)Ċi?#RDhQD9 L3=:K/#K$˜YZYk"[KA9 >*Iu$'")5Y9 d.YѳhԲ~-Wm똥/T1M \SL$ojAR$$!y * qP=*bC\_Wߨ!fD(C~VJh~5 \{)yiITY3k oy~u\2=E sܢFd&!(HuїT2՛T1[/RM3t4sn1@ cBjVȨF`Y|ȰI!6uz]$O3j'BmVRH4:rrrU(O2r"58<ט2Gf9Z53D7"yg{x/k^E]@V Ѿm~T,"  XdCrNK)vjNHpэ5ֶ2I_Lb0.߁EE@,|UȁMH֎ a/' 50cMV67=626UdWMJtڢ(Ҳ5В%*?c+m&~XםzBFr$.(z”hd@)idygѮ*A_[ "tH` ̭vZ-$KRmY[eƱY'Cٖ+ņM. Gs+]jwd`ҠsC\>5@$Ɲ)URA}_v3 _V4MR=lZ.PR֛&hՎTW9P~u%H=~lMi„kGz /yBV2;J"ŋPm[k)۸jK hSEi+&*^FsA39Me.qX/)D,ɪRƊqh6xtі-]v Uh7b`0#a" 4AcS/&ˮ:6`}}<`5tg/MH@J6n(C$V.ImJǁ*/pk%m= H`o+2ta땆[ʸ^+&M}N i!D0_}Kw'cIz:\d(ٲS՛NFQ:ў7k*ͼ۬gU2&齃U7^az+p=7nWij^=+2{Y%˒B|BYYUQ|*X ½3p5'5Ya9.ljqr!ѣ]P~Fa]^:[ǽ ZBu zVzt:Gn(l^|Wb wfMqJMU 1{zJ3bD@LIyjnɥb \GAwո89+W Gɘܐ )ynn;x0*ݑiDQ؁߹&ip<,jC2#]/VK({}C_'XQ5A#H kon,r2$ZR>MDNM#!h}4j+ _'֌Ys>i"U.A*?,ԗR=(?C,*q6LLS?]=2T>৥nGIt,%B?x1=Y˒Zhxn/gx+oiOhK+&tSAB+u`u'Eh{!yW7NDh~УK>1~ҐS+;@SGg3[~B)s z0Wل=agHT ,+V(_G[ N4a7sjܿDe( ~]os Ԍ{VOB= "LfMXV9n؀k>J:=)Z 0̖OL]laxA$&g5z-lh@jkةskz}s,{(X܀x8 endstream endobj 394 0 obj <> stream x\s8r*xdҕ%ys{g'*Vj=꬙h}AIZyH6uzutZ_m7dzOg~?lϾ_֧<~~BH:FTir]fFΎۗ/ GW1f:Kt/>|qȪه(t%sYfs}xxnϷ/_|\d˟(g&3! i65 V6pq?~Zlbh̍N4w4,WzkaBݴ NN Bk?P60 &@ULqS.c_o:\ ڢLlxe* 5c /BZ W(WߕLRWTKb=~]3Ǐ"WTZՙ-k(}a}>k+c8+-3h͜u(Ͳr;_☀|i6?my]vڪUXByw%H-1e,y ".;W_1KlU\qx~)^ *UcR/ԧ wUIT>=Ax\q)@mIi) 4! `rY2~ |;<ß} }x P˴ DGj빤Z٤F"eIljmdjHPXD& P%aa탅 ѧ5n`F9F{1ʵMḿE{\?V^MU?HC=[=ШV RVѦjoC`q [`%&*tt\+Q.~_ -.,6˕]l olvz)k\6LŮPԋENʰtD-k57?<&t/*/[".;\uus-`/4cF`M6fnF]ډX:r5Y!m~Dǖ+QcB0x *Rg_oHGz֧'g ),o9a{)bDϛ;#ep bΒ:.٥p~%OGjoV\ܡ>2gRqتP4i D4`3A0UstG?CmnB†"xzjF^?{S!~0򪃄{,EQG:[5 L;Dﱅ6b[n<`yjM!nu(xĉt'50,/+=߈U\g^LXd%ri@6k =-؍hE.:f\roݍ/ԝB%[[N8 -ކfkr5T8aYPm2ѹ-kHzDTw$)+aU0"|I_ٶi,P LbD$ͬai EdAYkSooF1إ릏?F7LM;a-~s +5*'/YyYw\֙t|Vh`BH V?c(47B (djkUZEMq^8U/dV,%OnTDXag4lIҪe# ?$A\Af[Ua%m*i.-Umjz{=X(Uwץv\;fF OF+>^CJٮpNpw:leHWtS"'jc Dp ކw y0->ޣuo}`hɏqx>V2oB M):„o[]j zU?O`]Zpg.1m (??t!Fm]pR4I,.+Q0 B-+4Ib@I@4Da(>5X4dsji#M.l4$m?F4 $6\b#q-ܴt׷ (ڥ;q -_@X_rEp476s @ 1GՂ!q*?d.)|q- ļ$()3{کars@OT /5Fa=*\%-R{;+Զ ƘK!Wo+L7!P:D[)O'\R}̯u0Br$ANu}5GOG\˶, j\aB*mb0k޸uR;T5x#|DfcLMMz$uy9^ Ѽ/-VrW΁K }o4&4Z\T(p* ZElѶ~wכMōѸf%eehp1t5_5ugW78;Bg3"nWf~`f ҄,Ђx14 e\$@@Mk4r$R0>qbTj/Hc4AI)Ͼ)iosLj QAZu 9Q4i!#ʆ\3=XUv{8 1ZSGmhFm! `dzQXlFC|ov-]?S_'$q Dl dm-gi *ڝp->G%7Nj:בp_GF| HPy:ґ~]ݡٛV,2Bkn =>\Jsּ io(x9m&ZM0˚6>ACjVG%S9ﲵ gHmơP@0n4}OFMF_(AI}XpJC_\jLrP^ OmiI ^s:!En-B z!Zَ#F ampf;GT_ҔIZ/쳤)*8!MzC& gHYII-7W-K҈xf^Ö#Z6ށ9_ BWy? БS:)2lg(IHkج}κ]fWQ[WiMn|„ƺJwT8R/S*,8T!-Fp|tXAڲt@stxJꡤ,(J+A:sk jԬ its)DT{(ٙfd;.09h0~aҭxqc#KE_ozKξLoӛބx6+ {jW kXpb@*6 %ͫ^טѢ 3pgHeё= UС^>C*x4mqy(U Fاl.pG} G\W+> -[WBRЯAӔul"s-qFn ԶDhѳab HtߪL_6Ql y|yDYwtP\{civsj\Q)B Jٰ,B9]*!0fGj cᦔ,r`dbқf+C]|H&c( CX'2M9, G<,ʐA >rHK(QLZ$c $9UR]3*JJp;W vCa 0 $NZ!65'Vɢ9|}*A'(CBX>0˓IV4aAѱ d47Qi3+>9mg%x)+ oǂUgĴ[a 2  0>i8,FM5lz: S3IKE_llnwIjAwHdvCTUkڔW=VƴyUA2ϝIM3pƕl$'d%3nÖ.`5E"S*1=4%AWAn% ^!4Q mvU^ Lee.=%9g3%4>W숶zd멶K-jhۣP~ۗͳ~] :QB&/zW;lq[P'7\5W*zPniTc%d>s!ƈl7yjq>#WiW6ÏN2ސH=.#aK qXcbD?Pk> jߌgFJI ,9%݉dF9sZN]1t-tؼۓU̍uQ*@7],<{P\岶x*pqجt%T4=!A.'7*h>#<j+/I}߻J,3Csr0B{zv@'7Zw-ys{G )/`2JԈh-H&Z:%*/'ܕ&SltDXғtnfk8 `{qrvB`ؑ=B 2*kht8 _{ab_r=$eR9ݰc9r=iZ$mgvn endstream endobj 395 0 obj <> stream x]mo9 ?J|kv=do7},ZKv%-fMv, KjHaȾxp>l՛7ott/~tlwWտ^"IWIX#ּ]zؿ~?_r)M9˵+WIծk^}QժZG*5m*ukZ}{n៟^>UnV#TlɤjULV?-~ϗouKMZCsZDsK/~~v?pR@EtBO/߶ZҚH4/X|OWj|vMS=~@I{0puR%aM; v0їo;NI${S׌m#5k>s! ~7~jͣwf%٦QJSR_BKJWd!LͺwLlkUv/SeKr4g4 ƍDWO|9b]ˊ%%ZVQ[rBڪ~Hwtra X;% $cB[_aٚit%'/UJB/R+r7'rR~t R.<')>P\=Iu̠_vZkg*^GWA? ZS?oD@8)SVVTvE9Ea+*jt/ L40ʀULPPH &d fM,  e-MҰkqV<ۘIo oK`K+5,n{wT?V7'mɀ(_2 $hhy `|RHt}V)PLg]Z M&ڔ)9Zۮ~W:ߥU?.!| ;@Ķy  pkK]\)/'KJܸITy?ĭn6 DZ +t(!Ԣ)dШ'޵xXd]R3WS= m1}w@3:jU&i%"[-UXDVPe @}2릔J.] tsMeZ|>jcGfIjqUQהu s&=Mʖafl8fڴ2Qc YSYXܟn<´nzء 4q^ Vw&pYkgiccAnʀejJH>nǿms3m6Xdag'Cf@dB\TNN+4%4 6^:Pr7n݈~L!\+:罂9^F! E3\R3ϨsiV a=ZY#p"Q,f~0~= 0+ipoZ]c4p`?w4_&MN]]8j 7yGG6jHtz@sFOEFHxX'jxVl41PBR1@bJV fc'$ $=Yʩ3Zv'^m +Cݯ|BW@3ޕE9K^,]3 +,|55GGB F22Cx6^_Lx$tc|'qmO-IqaܔPAXpS„N$%nJ+C+%s'ygCwn.Y@W_em͏+H au_+?k$1c>vc21;&EĎ6eĭcMb;&qa@ӁO1I[;6,F--3C9ڸQl~->I=:qxod->+>.D{-OXb_ˮ$::P&W}G&yubq:>a21Ű8oC, vX\w vD2 ;WXp=<H2txfhL8kysa_RxiȑMwN1ӹ??wqw>˜g{6vWgRL+CL0m + ^Ny+ 4˽鼒G+ቝ+ :WzC^aE5|Ľ z zr9S3A zf^;<o=Ȍ~qwA|V*bm$?gL~ ~BC<{GhXgHLԏt|S;܏tA.v1O:rG|/p@≄ڜ{-shZ4qa-O3 ,܌~XZ8ySFFxi<װ)3lƜ [-?D+ܐw/hAZ /Q qJ2H/(0?%,+Dm Kp pOhP" 7'R^zCْuU Wx2'=9=72tt,4Lshfk4gk::Fէ5"?KDc7Q2W=.0F b ]Ă9ia.3v9W&jc 5 }e[_,$Yi.G ӚfnQ/Y@0<. |V/ XAN]@ `.^@D- vgEd _6lf7o5fƂf “:]ҾO4~n0OA02sѳ1≝=5射p/"B̫yl24]SǾD5ƼBHMKnN{x~wLMڋ"97oD3> |\]{y ӫ]beӠPye)@@Q=?}J]/!4wwۣSԙFAJ&d#׮i>Qv=UBxPwŋ4RѤGW)7gYa}>kŘȄ@2qka nJ~1Gj[)!Q+ BGt\Eu~)ܗmT#4:#YpN?S$˯I_Q1y^&6m QF&:vQ)@6jͪf\7+)".7l"._VogUBEdޘ V?Ukt͡%Sk"7D 3?K[A;m_?n>~^:7\-z[1ny$퇦nZ~:*%"M AD3ɒ=TC<=+bz?:1;(F/ /vp8Vp# Ik7)y־pNUj:Obb\.(|SL[j.-WaƆWWN$~[$ Zy^Cqwu"-8%.|("~=79+ Xw-+v$rq]S T%Ѭ\EuwRv񩸙2MzMdsI)L'D?Ҳg=K}j1`ϰ -}2\eZMœl@ܾi%AjI%[.-~ȥ0_R:@ӧpr%U5R7%!E wʂ\sPRtnLzQ󛄬qG#{[tlpT7ĕa1#{t;VT0B#x~M(3_ ڍ)]pi[>P۸?m|`f%-rmgD0MvAwg{Tnq+ĉvXPeG/GUC!ĦӅv 1|-srm<'Soq endstream endobj 396 0 obj <> endobj 397 0 obj <> endobj 398 0 obj <> stream x]ms6*~ZQ rϥ*۲SMvD˺fiI_w oUR$nO7&P=~p\|^VNo8}nsΪ篪}8PVԃDֲZ^Cu}=Nj:Ett_Vu#Y=yWayWMuWV>5x؜ h+ճjV%{dauVFؽZ?Oۧ@af_?=o0Z%mC卨ea5jk֮oO/k[6Y!^XEjofփB] M#ęm xw)Ϙ@?RoN^4I#:_PO@&_?MΞzDkEΟf)Y-*909 h}fsU2Խ uJ ? mM*+_\ᜀ}d[7 Fn~7ꡛITp)^o_Ur8ob.ܗkP_(bS` ̓r&Xޑ):fJQ V/p-[f;l],W9Oot~}[7k?} |% $ y0~\]R k+ն{^ߠt.uD2\e BQ'HPJ*Y[L24"R]P8WhB:k5!SW Q@z}Lܖ6F}-dX0b``!w߾z{^5lvWj;ڠVY ?Z b.F KVRH9V VL397Da]^9]M_3 cɡT}^\~Q V~Z8{q+TB80tdiR7ڡ4wkS'faE h+ S \5,j+1ru~j?KȂ@=6k =(6i.ʲN]hإ=)9HWAFpyYj@/h? aucrAuN٤i|&gOZaO4kp+ E'"\"CTມÔQ+;UAbH/&Ypb_x/;LzX׵ncL D9(Qo}Bt}{NWVz[ȷcc!8oİ bwZQB4֗ %cd'd@݂ZJ8U4]1Id{ mx` 0c0f' )=G?=׋~$} FW>1u{%>תpDMZ)ʎjp5LzE;Ӗ=)v >HΌyK 6a`)XF+I{Jgbunߗ5A/Y6&:T;KpnL7"'{Ci>p\l%^Hg3O YY|اe:Jj'o[9 xtӃo\B .sL5XҜs }I'pO$iڛj:13rSkKeOŭ y=io^zbx Lx&mI"y&8b9F: 6{DрΒK; Ci/G81u@^"w95g. tQ8w T*uT s5ⅿ%,Jrb;v۟e@'Yo L ޟq5y]o4ȕ]h7bijgcO8<6}v]c.Pe;">q]GMK*{9ۋ@Q!;AJ|^2/ 첗R[6m,ඍ~m'iCsߢ9>;9m"/gA:CJB5FV@|T149: d 0&VpQh0ݝIe|`B6H2ȇ 1x{hB YB'r&~zF:.qkPl= !y qvg$i j d9yT >8欫2peWR/p<;&AT^|8> >yxD> 6`8i{ee1Rf`IGK])ܡq>;k)#r@w^n<ҏ@g'Ig{0u = vK2xʼnH0~y$ z&: [FΙ$D~[Իy!D{sqAA 'u>>lө,G.8Brqɐ\p٘Z6䟍@xұc;hg>ׇG,!lc̮>s9(8E<֩&q%q6O8MU'e!g`#Oҡs,L=xYO[||\C Cc8%Gg_Lޣ} Ѐ]B$-Y Ccgbðp v?LRۯ?,橜P6oDL߈H~<4-'~ ï{Rr v#*"( w *O굽6 v~'~&09`#4vnT'HwH5\TZʖصf칶-+;uϧd84{X[6F?A%ʗ(o%'[ 6S:}XHna`zn +֔'n޸RC LyӔV\eg2zv_vZ9ku_:6UYߜeByS L͵6`x;RcmuRԽ.l[=7..߷>X]2g>m_Q)[QF(?&Z#Ln2 릜 ^S&Y1H^or^ tX&yf&psiWL. Z?O5)`ʌ_BB,%o-Z*nx05eMK.|Ak=2,tyC]j2֗o**?܏y&RiSY 3yl愆cM;rxyЩ $UB̿Ӈ.x\*u#Tu{EC~nÙ7 HG59Hq)4LQ6h3psNٙptp6gn{ڇaOXIa/jqbqڀiEd``[8-*V;ZPQz3EON ~d,k/0j[~h S̽K Ipbz% A;Aq#*恵|Bz'1itxE?*k%'iUqڀgfC΄D+[rTJ =WMM R=f- uI׹;Lb1Q?[ﰠ}.[ };L7g"';K"Jhwcݻq;RTzFJ{x6o*OO3{i-Y_փ%}*1nuirL{7Kiҍ> $~9PnM>Ibdl!U0jmB&Tnk ̯u1 NDRJ@k;e5'> dCK'[uXmw>MMH'NwSxqu`݆ߐ{?TN rERէk/㶰W)rj;Ugnd[.UP怛Zlƴ7n.(GR:i!:DpE (28#OYtq:p:t4xf$,wE6tNjI<NU mH#^na׵7,AztyO^> *~\Gy.F.i)2DiNjzAQb,}eE6rH+<cp% >O"Q>B@!1aGU;p}32zF(; rg)7hYOov7 F]}xN׿__`s&_譠1)?Q endstream endobj 399 0 obj <> stream x=ko7 ?ǙEj G8aCqlbȲ"Dط㯊nQ{Ѭ&zسvul<~d:=}vwO~ttuys4|PڒQk-/7p) spݧێ7'ඦ?T6jZڜ||k.o_>8x42PpNL5'goo~М=v br/^l\ oxcqA_~iMv"13\͟D,!,1`}KS|;axx8K |>k}3.l=?m~YQ3Cr2}7>0`9%3{Źjo ݫVJ `&AP;$7ZUį\.&F\j8.8ڇLc gcU0sc5G/݄޿Yn>LxpŮH 1+D)IA+('(o[aR t[rI_[H uGji'_?qL(W&))P Rf?Nݴ\x}׮ ; 9b/K-~xL`RI$IVZPND5 lUF}WH V1FB#+I#.1>hv)tC='޳o#T&XGLf*LJMY_<_Zma5*@6 dYh~0m}ih䶁h+|Cwf-+X^//;jH[E lKv~o3FnO21%w= R>N 6_sz:g+F@?n^-}Bޢ<G.߼FR撨9Z$୸)j[J'dGɉC8) * a8HԗDAKh}XAH*e %m+0"QeFJQa3gGG[C*C-E_Yf8T>ya~|q7sa4NsV3t_̋FM/9`Oㅩ :{u9.FOSqPy].^wz/ ^'uZ$d'hKT$UHwxËL֋&7^4vH.Z";֫:p*p&[QIw|XA}= \'I>h;Zg2TXd%n*ۡBLnUu$\VYPY.5T>\ ;}Á&h@ӖiPիMGFRBaÕ)ȉ^ל!v^>ۺiC17m6]8]|U~U# t7PYȋ@RMou}hl_ꈥ"otڦNhCr^^ Zqb|D74aiV/Id%`6# xN9/EJt:NFjXݣ[DӗwV!Zɼ(B;IZHQ w&92_ښwlƃin;\Sz&}H 4ʿo#b7j +7^yCD|Ɨ=ch@:駯"*F#vb>,W!FS!U6?t&14tANݸb2b%7PWm=_r_ ~bcXFdI52bR"8&IA}_ \|5JD sYr{O^m6պ++N1S0\`-@R'n>ۜ#x/grSS͖w:Kgigm$ <*%O+XgAaA7=ίBh#.u_:J aP ߍJF4Ja7׮{Y4Sl=s@INK& &0IyW̓'N7u/L-.;gpb$GEǒUy!5V@Ơ˝lE?RF%Z{7rcd_X*]b75>WΟJ; ɔE"ݒ:?.fIÖplkL֎xUio/W^liy0+ &(LqMF0 V!jCvuA843#_}̴u ؜?HZHkfHǒvlwdpiHʅΖ6[m ?[-Ho;g7چ <ucg^=|9I+fp[yaJ^5̓-iL]zY֌PBײ{]Ef<:,oyU: /\v0O87wdʭWY4{eIG{8 $.xMnW7#d.'R5.xsH1G/.0}B/s *˙Sb 5!$&$7GׯI0~]L@194"'X.Pɲ1bB9V!ՋɡuVK*^Yu>eKnYTdf57l3_e/">/r|/b$И©ϵHs5\ط_ݗ?6>o\~u; 2&}lϘLU A{XH0;2N^V}$3NS̮'cvUT٧oUTK3؞aLULk0FVw coZHfe5;1{fMfjvcif3̞2{Dc'^@q[jPN"Iͩ=M,L}ZO#jyy%,>˯VqIU2i!+֊epi?.caK?țˤW)}'՞&/t}->'= sLYR]\ty#yjL:7p1ţ-m4G6[Pހx}8wX,VF*d ijO0Q-8DmʐyIj)ꪝ4印c0oRqT]fMCY4U;AU mS6:V},kvrJTls9Whv|~}u~Q.>Y]LbȈ_"9|YZWY|0S tEae׵>,J+g,̺AX׻]3-z}=u҉nlCU3z&ZZɈ &ҕ+*mdo}fi`}Z'\a }'jHphqGhl ҫ7gV/]_=\ǵQ[D5ܳ%Resuקge )b%%R.6K)kHE}$ ( ]QmfXϪn 6抯h6;+:6%Kp| ;V~j=bI^ʸԻGLnk\4qٕHmK\i-~1T.`*}\mh4kHڜs3R:#ٓCsFV|.¢F:3gr:98Ac? ?Yaeuynuc;=ni3"`laUI* v$[*grs2|*Oe);`VTڮ\mWvg&49N_c$]<>+{O<BcՕB8g0?)8)Wm!Gv$X7Fxi?PKE"Ӵ2oL \_nlOm4( Xu9uiՖSS:^zV!DXf6u.67]e7lj~ >ǝw݁1=smϏ{ ?=1»ssg~m`7y07N$}f`jS.L%]M7q[LjpA߭ylr'$l=M@ "R`%Wɶ\xmaBH*WRoQm|b> dB|U@'3?G&s#)L$ jɁ-w?vrf']ZQ;jp6РsnB]ܩ.QΫloڞQ3l)}bE-Ybɵo]bXvp ]Apy3Tr/$zlόgW'Kl{W˱|a>t=мo 􅩟윪6df2|-,ݙ@uyx12Ea:ßԞΝeafN96i9+_d93E?:oȿ~ltu//>F)lhǼ!±ؗMϛ4W"Sy?lU^K{qc{ƋXӶzc_UA旎:t= y{fo=cɒqI xn)ß-g&x1b^E{#t2qW[00isʀ؋Q|@-miYqk-`W*]Ek5^XEǴ̤@ʧo೯I)d^9sN]uctapq,qZ׸SiɺeX.Q4ǒͣOt"}h$>wS@\1kR0K2xᑽȗZP߬'@Ŕyʇkh?#gq5#KT>BDtSa>)Dh 㾘oy }QLDVK+ѱ=Ds04U6MSqDWZI4>rsvpl9W r ˬ."ƘRr#~cKX,oT1gKLy#(^Lf {]\G a"pW-BDv qd^w۲ݘw[>NsL:'3sKn|Ɋ t[A ʮKWrd!urw#+,11X<6_[>zG=*].{|jg˙!\e%'\SeBNvˢӤ]VmH=͸= YJ+>θ<~PZ)|ˈ;XM͠av7#@;` ~>A-/]8W.,]%m6s 5 q{@G,K%{jO3w&4Xlvvlaag҆A֡ڛ #X9ܱ@t:ݽ1]= KXH3؞ǎV9Ү2CiVC2ڕmođ',9ek,$##Tԋʈ7NɅ. cm$?e?l9kCJ^8jxM!mR ybGףނ Ո}qZO-oM^ִM^p!dQ) tW!!Iӿ4{Gowe%gu|<+xZ>;H1z@'K6yQKeٙ.l,b{SD~bc{F`fo ayMPysaڃU\X>dKTvM%Ld\JBgvh2muֿTԖ)٦"'aiu=OmL<&A8D /$d>7 `V endstream endobj 400 0 obj <> endobj 401 0 obj [ 402 0 R] endobj 402 0 obj <> endobj 403 0 obj <> endobj 404 0 obj <> endobj 405 0 obj <> stream xl-kFhybpᒌ(8?GJ_xa q8^/N4KuZ)V!?O 0q>r2x&Ϡ,4י8+xJe̎U^U@R@%!ɅYk/^.^,Y@hT2VK؁RG77}yT(7nݑATL9LI@UeYΖU+{ {n!@w"t.e22&1aPŧ UzP䡒b4?N4 ֮B]c(D+J6םgh|\Ys. *(,OF&$;ٛ8~{ӥNX0}=c0+q ^߯Gbs DNٺ;»X T-׈oOv `|:Hпw>G<Ǔ\G b2fEU Z ,Y^1NK/j^ [kV`G /)ZuRUqu3GӢBFߗ-.b< \-WaL⚤.0?Ɩ\.jrg$Ћ f7dwC Ɨ8[h@ y!gр/?~6LM1 I)'@ ;;a5<;9A`!(BU@^7q,x/Np* bXr>rm.P!P2ڕRE7 ('m4 1e&^W ?Qz%5Ǐ'".qJ!HHv>B$ W^ EDz? ( :t%3%'-De|ŸWK /o/_~JJ,dJu[48bШ!i(&RM<_Kf@P&V 7 D"k?5>;aTXL>5a aֽb=짓 ~c[uӳ0(js\*djRlW7k]Pe0O+mfij9:mҋJ]靯_$%ߣœhd&chq ~LJfQcNV3Ynɕ:WUlMYxӐ׵wF;9?Qww\}uJj '"i8c ̧%Q\ :#.\FWoW9@d=$ "PzmL8'JfPH5.ܙb2#),2|V6.eMC3*뜉Գ2薻h*u5$%oJo$[Bn'7`޿Afc$fƧB e2o!iĜtȯA(dŌ@~ݖ!5GVHd'l-nتTI;Ujsܭ4;xsVaJ!CΪ2RqVP! @Dѣb:_)r6 J=Ua>Yt+^h <, q]@.W9ܸ1ù&{ZδL0BεM[F?@_*K 5zxY\!},k~[ܜu=C)Ls8E,#ي4Q#يa){(\55(5p;aI;FͰ}ЍM&+LWw [MQ`(ay$aӸڕMpJ5n:zBv;5'H2EߟO&d~(IB1i(95պ=dk$ i>\liР1eF+k㯢JKSr:Ґ.KhZ꯫=&ʴxvUVW yG6%U$'AJ-l>U/>d'*!͖CDY7Q3l1uѷT: _M o]!/ES`s^3:ǒp ; $DAXj0O.͚KsI$5 YjH,5EAXx9<)/z[Ɯ4Lͨ3&ѦTGPgԐ>0ƣ=ǩ4!F;lny:汪1B퀌X.cc6! ;mGZHXk6YȃHE͢69܉yZa`W Jx5-bQ^˛Rɒ ]n?tJ Of5fC8c˄z 1j@ub6°CfXV8KȴV8^m7lEt\l ΅JNlMzn`4K*M @l)x^= =gѮDkA1H kfcaDCwNKM04mcCBvhI6\[ 7.]"BNCkZ7m =4uW칎7mrr{vw>HͮRAJ]t,<|W; i x{ʾuNс,m^PQqRxR'xeNwP$q;'͉;"[(z{D97|.>zvv=Xбu"mDbЄ! rmlŲZ8;5欚3): &@:(mE_[:\&6 +!qh֮dA1Hi5B*R眈5%MXQ.4nc2IR٘G{Dќuy| C#cA8:^*Z+6VF"G;j$r4NT-93hS;)G  s#nub݊Rk/64xƐQigUZrFUA PS"\tLG+:!^y9I)'Ui])A/Aw pd~؜F~\QY &JyL%x4ygrj)ZiyJP 2VP#LjA3WV^ h^H H P840YMSGi4O. Hf_3 bv=q('J9B:~Q̖lq?0;߼r Bg⻉XH'q,~dM9 Q4~چھ}Ə]7oi^^cnOA-t Cnh,ť|G|(YcY?ՉT Ԝn[F̏}mhR],DҬOv, $=nBi$2И  lLko)+ܡDP6,/f<͞X2zչkS8JNN"@\;<*^Q2gA R.˙ >@h bf-Թi+ (bH%)I`&ۄ$*Iloa͘ Jg٦`ZO endstream endobj 406 0 obj <> stream x=r㸱S5G)U  -W:q3;LjcK4ݸ$@Q}9(ݍF7&ᇣqv}>Y}ͯgG?>,jy|eyŔ|xK9e&Tz?-߿j=Nq7K\d7sx,?eV)5-o0õ.En?y ?{Pdui`EcfLIy}]9=jQL"hʩ=rD>[*Ӭ$>8?Cz ݦZ|*d39o)픵G|8aqw٘7kUqusņdcR_Dq=?V?iyr<]vF)ؔ\eBqhBw\}}U*3jZ@49I.i5H_< O@>a  .5UeWMC Wv,;qꧫfϯi,s\/$1*֢CGW^m|ʵq<:A]Sz$]8%Z]9Ap6.~t}}o~-=?j~/Pi|u`r硒4T?'\hd惑ULPU[X& bvZ>re'>sP="N #y;QKM6agbSƛ۬l'^@f>̐a`.RDԥy: 3)RX훻Ofmv:ĀaH(T0GIn{Ah˞SG?.l9p:d>@nQmVބֳ[ϛ^nn^.i;D$*0dyco~BYFjں\,Y/Պ]mvC]M !0A 6ROYuŝd7( v?|sx2]q^a ) x.074qHl āt(jv!JҠ_w q|vAބX$GzlGrl+$)-a)e Yphc4 3nrpNF1Lc&2G{gu eWza?:IhE 1b zLua/uXR!I3L\}kgH8tōO G7p?# .FE>:8iӓiwѬ/⎖@8*w)L樌}8Ʋy"Snak؆H1eZLזM\WzSD v?C)P2:%qKmVBuBIL_E$`v !OD ȧm_蒄`Y$qi(/)+  i9S:NlEqU;k % #:i|w!Fx$w,s77'7!}y#F1\/cf"J:3)!cPg$ocP[v)i{7EOVI5fۍce{A::qcIJf22GyKYJd^z Zk%fOEkz9V樄emғi,]; yl4̧v ^JVexx fF0MGieFdOQ 'ŀ$OLUx4.j:^փrKl꣺icI;'iVd'u"Ʃ¥3Lu8y'kNW3m kcu1ˈi2B'V~zْސ۞0j MhQj/D:BV6m\x\7ړHڷ~ngiC !4vǁnl>@f;XZjӿdiJ`m66f%~f9D,GDZG.9/y).m9 /j;hv1y_lUn~RZocy1ZI СIr)NNDZW Ik>XR l{+ÑK; H41k(ַV \, uJޭ2nʛ70w`fS @+}ixSʲKdKAbFCY?6_/힅ךnag*> O俻GaH0=[!isor- (u(/FҳwmUEɅ]6]p/u, h0-&÷f=6#34"o&jĺEktEh)ɮdoƿ^`6sGAg1A0{ QT?n '\wM5>hg*/ʴWK)HR'W1X뮞֌r-dkgZ2[6V݊rx ٕAŀ3754-(oΝAU endstream endobj 407 0 obj <> endobj 408 0 obj <> stream x]s۸L>JM|̍gb;ɤNr}plq]$HIכL,.%tb>d}wpޟ}ɻ>oO^?^wy9Y%X.YJ242o?lZ]j4<{+yw궬PHk2iAz})gEvya?~*[#{^*@hfUM 3vm ՚Uٻ˿,5yM]_m2 osÌ*v2X6.![X<~8sQ +PM-٩."9aפ~8QS-xNچzu 5yd<Ё{+.ݡNOa"UǫmwX` r`w ܰ@=kl~*:v\*jS we$@exv캼{UwrTjeXaj!xu1oJkkppA.ඇLTJ0 UedWwjy}T:A[*{º|[o ?}݃;@?2,A3<4j KQ.?o0L_+= ք[TDI92A}4I(MjNhvP?;M^/nkYS)>A?_;>#|ofc7趡T]` o7um'XOߙZW10DoY!(WQZPn :rbXK s ^g+Wt( {EV}e=^?\M" L1ҖyoǕ{7eAH0Ф|ҥ=^pӋ;\~_ӂi"L{ +}{'ynnrjRv׏*QQ9iqv^c\QGT |kzUFHrɄs!U#Jt7 ^R&:A"F8K.C,aCT|zP1DKuO "Quo4f`9,Q"XJSӛѩkO*yC8h&LfP[\oeO47}ѕG5&#f2h' )ݳpLJA !RZHm+e]@͸N-0$4.x[L& tސbۚ !9\HC$095:x<(JSzg'D|aƮFG?KP܃%u[x!8LzBDv "/ 4Hĉ?Q>`{ۺl#Wl%sfRԲUݔ%6idUx(r:')8wՙ!ޓ-e1} cc{cx&e'.[V]YTtj*D䁎x'ZuEa$mt= fmM[aVt:?*ƥ/5%6;&Bf%mh>l~:e^oi",Hfagi=[7%D=ljeÝ&Y%MU ^ʜxρFN㵂xGj)#N;9w*DĬ ^:xMaI=z b,%RSv݊߁0b0&9*п$U ;<#`i-I򱩭yoxSQ;;6)>a|Pxҗ*(Xb bralĈ^@}Tz—j e m|"_+yھ$#<ڜm9FO;RӁ.ڟwTsKG# gqN nG|  f'`Ь͎tmx MD޴N1U0Q=KJLfFT;%Jx,%A|H'1xY,d9N Zemh,B!S+k],D$b$۬Jy$I+NP ^BV4J'8 wkdDQz♄/޲Bh\ɞbB^TòSVSBsyX03-:8ÎWB9.]Hr"A?ݔ!Yaj&AO{ uL>6i|8!xaLDpc17 zj8Aő z$$8-3XּGq ڤ тx %3#N`a{-(;Ctf~ ;GJF5kS"./ !K7<>%C e=.x!\`!n:W?6>&h4'mJhTǂ>XunNNx*]V-!c_9\#YiziN+H{ɣ},vN j vMXU<Fx8Uf\.LQ0VÀ94R,)a {zH#%4»rdzAOpIhp2376HLx\j׃QcUq.S÷f_\jG6N5[ #WCD@Ƥ_Jfs)V 5(s1&i@'h@G{4B?j3ⷵy^UmxhQy)h8-TDj w?mg":=VgNWM"^/yIК<0o^jKCΏM^ ?{g;8Csy WUujfTxlL\)9&auw{o /f%\PIQ=CQYތQ~Kk6"R?Pv\ˮqf-{Ou;@ :ͻϸ/cuRM>OOo |À3kL9_z3ÓmV®O9? J4[l;}26^6136D/N7W[G@\}0vX*Xo\:;N-fe9u%>z1D>~ Zt~sefmOw:_ƞ0?66{yoV|h/-{[fxȤ*c &Caٍڸ*G}G EMR(5"4iHViB#eť Naz.}IL8ӷ^cjP*Xv/R^Q"2/rl® endstream endobj 409 0 obj <> stream x\[o7~0RQ!Pe'HۤػAqdǻ.~9\Ihd:ƒsC+/G'jn?|jw?>NNϖ?cL'U*DTd~?$ϟUJNv+egG/XRL.$X"K<)Nyry^^"yx,Kn̪/?{?K$??v$6Oc`IQ28dAkQ$Wgg-yZr/S%s5m0߰GyL.7*D*UKͿϙOg02!O9.b_on6*YΙxi 4,6~2!%Q Y&Og)߳cM<:͏&8?9^%h&ǖ@W=gXJ z[DjS+V7"9$uYy^dyaj礄4sM( ܠL`~Iߒ f ~Gn?4tC =+9LNtmB~1pbj LiՅV)Ra ŜeKe(Kz.g[P|Zz}]拜ZU-y1yδiI_~$$!МghM<~V1LT+n5 ui!"'"-[^ X8>UqXP׳ _Ȯ5(<VA᝭̨~ޡGk;c }0?US|Xͬ`XcJ,ՀψT~&ʠs,cM9kr0a.Ϩ M?0;*TZ.#,aXnĴ=2F~!ù)^xd24db,EF+:N#K(czyҏ Hyʅc ~qt! f,if÷=mk#K>UONw=]:I`D5mcLJHkͨ @.U{-mScdm0\򒌁)3lK< BviێJpǖM,]4R}\gM(gݜ92Pl[ ̶@l{Wiuϓ5KHyHxhn`֬pwzdּ<wCqu!mH'HH1GB6xCL6ZPHf,:#Fe= S`rzy0 D<Sٜɮ XſjֶZ-zQL~%5Ҿ~B.Os+a)(3BU] Qt ";/8I]-]*E,S%|=+U!1YA_'.½./ q\`lURyZhE=p"$qSj4E8xMwP';`RU֝<^lҼ:fd?&JRmOԩ:5jVVCvӓcȍ)@vZ6$BEiab+Ypa~olkєߊNA,X-Jcy<4 _Mh+ Kq;o5k&SDdCJ~xN8l ů٦2; UR`F ' V¶* O7 g0*D\S(+oۯ<4coSU2MrL*zq)눯F|m5+m7Ϣ V9y]9V*a#rC%Zry>_5~w< o_ZVa٠\GJxǸ!^+R Ó7ӵouv,OaU3MU'g1;e 7CɺnWSGwfW^=φ S/hIHyyc#:09&.`x2\%4C Ov M"NfU᧠- w0.] ƍ\gK,9LO<4KW^se@ ^G}iE%LI$уLL_7Q438Uŀ,1؝ߚ;fp*Q{)HyQ^~q: &x\12|ruXx.ERDl_7N|M$}t| )AZٯz)&lGm /B٢)Zn7<&OҾEgmM %x?n(Le,x×.0in )M(Hn({5H,"O;Qs{/J}dڔ"S!hV)V=v`v@X0qbUOIL&9-/8Ka s7v2}*-FtRvҝ.Mݵ)r>c:RUS]3<veL2I6j-8 ˱e)zKAM2 ߛՃR{ȥfDG .pޟԃ~obOғ#Y~B>% B JSh“$zrt!c7[p5d#QcX;оԪ˄n/qj̔=0ah v0YL5)KGeTN5H^Cz,~h]C:l/"UGC; ]ZLDW݁7ubxfv‚{ s(i*ґ[ʚy=j/(NRNmjn7c!U]Q}ISzNX@Ueޅ/OC/W# fW6']Ps.xe)93.ǻ/y>7^nނy#ym4VydEev9 endstream endobj 410 0 obj <> stream x]s۸(4"rݹqΖʵ׿x >v:wbuzۯ7oOͧm/~y\^-כ~ݜe/_Js2)XXJ24*ۭ^7 ׮2i'u{ />|qdU^ܖxEsZfRf՛k%/^勏l^x$p0 4#f"ݳ.;)5هߧӼѮ?N2\~w0˿0G'}&K ,碧78?Ήw0sq|[pkr oŜgSk%8ucɆDOcg^?Zܼ08S̥DwiR^ى$rZ~"'tILe\1P9Y247o+]n3ۺyY:RNqk,=戋p}rUv4`^}N{@bopcY|!E@HcBW^ YΌq8;ǵx='E@Aet7|E*u}W=OJʵԗAxuLKXIӔh y9 v3|۸kHW![*7pI`ШdӚJ5)'brSAP&55koz¼:eST^{@ҐQRT6W{t>v93dM`0cڄdWh<[̊@TaL;,p؁pJ\&e",ls44gX6"xV ]c:L 0aL{|sa6 , h ! ,pF־ R;n|*`glh|AUk- R]x£`rt3?`FlGӏvxFe"8nJ+4\TCK"'ª %w}6[mN\]&T=}ȶnfPHZ>['x-<ÏW{'ƈ hnzZQ[ jwe0)vwL׋C e ϯYwG3()E.n';UT7:MDƗ'!^Eg#pIHjWef5a}qd"DHa[Pĉ14TD@|RA@IZ- |<'Yo 12Zg'qB'8~]`&JHMK|M]ܼ arZ& FsZ0~wazK07>]@orj%mؤ%q9}Gb'YB|9M6F Mn(X!ǃn z2/gD3OĝXPa@S9 'k:'w S74N$`]\&' B,9w˒r̼-3~mq6鞉շ;;PwB,!C-fU4 %Kn( @dm,e"H*meGJXvWw]c]la&s1@e&A0VE˞2g5|LlWGUF}B &^QjWOQ/ίe4B&3[p.pهĿF"QD;2`$21Ju`.Ձ.@GG~RFpˏ̑@/VjԔXi6aeN&{ىȄAl'8m)RݢQ ׬HfB8,KDR=28>eld S6!i1M %Q%BiTC&VAڋkxeOsJ7ظ-&pxoT ̙ Lq 4bBQ!+2rAr_kllWMLF!7kW^\Z,’-fRn(G .␧$$qI8B ٮWoSˑCAif4A(XIv*2F|B] b3[sY*]ZU٪UMJ \D9"b;Ȍ9+"4X+G 6hj_ r2^c:4$@:V3H)f@;+Z"\f^_0|{ƻvw8ܦUd˲'B*/uRBH ty c LJ yO>#Ԁ{BY%^J0N,&gc`TWa] c>o-E7¹.̃9LR/rt4 #ΧC5 WvPP14PӴAM3L58#Ѯ&/dG +599#lq& M+)a5l-D+m) 5 Hʠu> ,3C!|N%df0Q,b+h,q2 :]á!G X#eLHD]~muAxLD8:Ċ,FcfZ c夈 {R,N2nY_ȎRS}pD{7nRn{hvz]\cJp3iVtGJ-}bU T@wùB~C0X9S]pc!Ó*>ztDrVE6>E#9#fOKM84d>1|^ !6R}pxw=ZG#e5)f)t޻y2N< i޶*+yHTd)sF76IbO+o6b vuf5`AeȈ$b4uJ|7K9isq~|}s{*LnVT42]W_\ϙSDFU7p`HNh'h +J^]W_xY8;jFrˌ*=2{rnfD0H@gYe!]@K Y:&.| Yw8ڟnP};Vp927yQA퓳+kV>ZapB:c,piԯFO{42'“=iT+NTU{ UۯJ_ܶjb0jгaEF7;X/W=*(5:U:Us+ 鞗boV'3`/!cG6yѶczV}%= H dn*ҽt҂I'ZztaiM>dU$SfKg߻;S[6*gHM6 la QjF Na"!Ch1 % \.+@9f-[jLwX~lX{( wى)()7(R&}?)Dhስ|p ڿ6G1U(s֢4(iIQYWՓ:6xoh Q!Nw~ +2ܝ>m˵'Jtjf~F 6n8?g8Y $oj,N endstream endobj 411 0 obj <> stream x][oˍ~7Џ3Ncǻsf %YGXK`O~K]yX'MIYɷ˫]OG'կ7ǣ׿]ۻzuvZ yLDjVTn^U/_tIӖ#W/_fUW7 U U5o+mLͫ{zsntu勦ʦW/ſ|3Ucs@[9d+4@-tuqqu-y菫3kk%#NjF^^'6S+|1ۡˆ?Tqo7k-~:1 Y[|œMöޝmUufن]vlJE4BKG)7D G"%}[JCN! 玷7:Vu f&*4D5-'T5[(Q LmڙΪ  tJV(2vؼ>ձmPŦ60D˙bJHJQ :oW'kxYA_:Ǘnr zޠ_}_oZKSG93DiA5 \O4)y08& T8]Iů@KxN϶@^2/wß$+jVjSJ**&U [)h4Vj8D#Z#6"6w,}L]aw/uań+ҊY~Axj]>V͛Wk=p{X{5N(0Zf,LZs5]G5+hwG?$T5ꚵMG?:lbN|-zz si"c~Ȱ5 (ijkNbLDE1E{]ߍf7ӹSAHڀ ~੠ \ZhBk1㝬;껶 haÔ<=XnyXfrmk!;~hrد;qJwgwh-N$@!ҥ=RE? "Ƃ8I8rLqoc4X$B`FL=YVߵ)kƜdSxjv5v8)“R0GB*7!A2L >ݩMkʚ S_Cre(ڴǘnɞT#vL(Uc̦k;.#=Ky2Wt96jRL师9}#:J$_)5.}BχԢo аaO\}XO }4{0w]d RgLd 9uˠL)H?~Y3PC›4-QSyэ Xn2n"te '%ns)B':7h:\70h hѶ1YYZk2B;AX<>ԡGEfQqNԜt"ٲyl`ia zI")֭߫;"çÎ@Ood бCX/:=jj0Պ ѩWꠝ#iC O Уd㽾4uJB0E$# q<Wia j*.]Kby4yaVH '%G?~!=081#'ȵ:1$ay_+\_?%H2OœeFƴJ4(AP ,gw7]yL#ܘN2X4jSd1|1VzG.Y7?}n3r ͹B+RfzR]KpMp Y$Y4 E5 nD5]ԒҘm+d _K$k{FΗ/V"Ni#)}.OvQpBӎ&ۣ`funkO"[TrM3ߢ$LQIũqYbU6٤}Ezߥ0ly;et@t޹IR?Ɗexy6i=I'bTKU )먏k Í.f.(s#J;dZYS`M"mKrJ_c?g!# NDN`W "qJ? cER<)~# +߰*[msEb`X>aem~!%&yme[I]Vx! 3U s QG$؂ZeF"ܷ/) \!W{{3ng)X]]+UVSV|aH 'd fbDr"{N< >h{7oϡ-QJJMW2]3y%H2xC4Ok,=J9!Zxٞ.L ^ jta>1ޑGŌHq- y% f.k;4Dco /dn`'!D$V7gme16OZIw$V];<_3me&reQZ&!6)瑔ܝ; KuRnJ~+p}75X/sӘ J_S2o^:Nd|noE?ZEE;wN^} }6x6"˵-hžIc2kXӲ[xUG o-cH*ckb 6d*:5B6ͤRD-OuZDO/沾C1vp(?li?r*zqg[V|-g.0+3gSYvl!j&eD2xf5 FHsfXN K ,Lo|y$uz/rM;^"r)VfC?c6Ty}+D̬&Srɡ،dika]-R)i9-Lx7Q8j8U7vw oNܕtٲį252Kpu2}>;gU\#Ln,ޘ&[XWx̰]_Ѐ^~ܣOǐEЧW ]jp"(ldMDI" Qc31#kb.)i 'o>,raZf鑅gaH헩IzA.yyeu }cВN=\q!F-=T%CD݉$Sc4='f;u:d{0 endstream endobj 412 0 obj <> stream x][oܸ~Ǚś.bNRI]CvQLg_sIIIXl2(wTO.nyuN>_nr|~o֋E4 yʪP"D"r=}\k⏟eF״6LnnQM5ݦqq2o mԪ=i@d"' aӪ8(. q22̘2I?xz~ddZ}57BOVx)aS]\-Ơ-*2mSBCU6 [b#J'Zxf3g<"#;O,>On)~Dp535 %,Y&s]$- ^XS'(UljGF_QuNbbv Yi+dZHsR%2KT`oe P)AKge-]+ v؂[gS}L7>66˪ [jB.,=SYMq뗃4.7ρ5>,Vmsc!Z Px &.x"kk[-^Y@޹-jfyftx%?sg+6د;_NMÕdG쵞YX+8 4mǝP nY;NƞdzA,Ieu8qίIMȽ+t;g.oll=XOa͢N1`WK{\_qe5X"wm/,{r>L͒ 'Y 5%\GjT9P%G~3^~IE«E`Vƀ^F [z^[#ZX({MHP3`'z<^#Ԁ@(wls_C1SzȂ|@hxm+m5f$MR+W#v"Hsa:OÔ n`Zy`@5=&Ie }Z@@0JE/Tu>a*mfqDۂe?V0XOP{_w`WbWRQ,Qch͆YwL  Ӡ` LtBOcI͘p$oWri4\o싩 uZ~ﶍ dBz CI v%2tw#Q}\+,ptC34sK}U)hs[K1ipP(*qK3ΐQ'Ҳ~i) A#4%e5&br> ]a1pDycS ,׵ X0FU2A*U5N +Q_4DiNrGIKT`^w(,N:3tݙ{c#nZh"Hf(xk76ÂuPQ/S?9һZE.#|ў`}!Qcp6=ZͭcYwI1V82b<RTLk:Dr,µzjBj`Wz`KeÊA <ǻsǹk?\^f\]wQq<>&ewUtb^p7b!E[̴~CY;6֙i$:VH di9c=K C!_Jw  lǘ׍LjtЃ60D,kS/%`h Nrv߄u Ÿ-'<㘔96–1kTOBV=`XT?4Zt+$'T82P+yH# ۈ-I0R:R(p6Sc6M0JRʰ{HRFCJTf=6J`Ug 2FeTۼ0P(>POϏ8vjv?1A1G5%[]FN7uhH6u%/Ӳ)vMxߔ2 L&['br184 KU tАiQ^lUMdžl!5\8/nxWQz:U}j ıw=XM qi7{:J5cqQ-0;Ɓ)QHODB۽Hᆲ7uAJrpygң.H uTmQv+} D'ױx4ZuuƺL5\7ie8%13̳?[1CqնxyάCIZK4mΓ,U>ͤ1tA6ئMQSRZ^!Uc}+{T3R6Ś̀ ]-@%# ^#_>W!޳ 1)Oi=E@Ǭ?1jD #" р_aZff!+7V#ŸԓԫDQpEAJLtQTz@Sw P=‡%9y(\ {QbcB`A4JήOt(a'46gZm'ϵj^^ٺiƖQoҚoפּ[֦=JnyQ+غ2l^V. oTx =v G>VlkbߐX{ӂ `` yZ}]uSaֹq&vJ&241{ww U9gi4`:V O2DMkP*&@uG7оiW<#f$4o D (ĠEa@zop_9?ɿӍ9yZ& HE/Qd6TG ^#NMBӃd|:hyHUiίõCScX|jla !O9DAFp`@ֻζ CQ&\Qvj&-6贯l$pjm27T7.\8캸=i𾲁0y<"sSbR͇QQA*SpGd0wS4㞦Ay(q W;'FP4s}*< H{ m@$}۟?,0Jg- ` ПX A"4A6/=h3F#jO2Xx" vj3q tyff]YzUxLiۤvvx7(8>8Avs">z̚FGfM#fu!t3PMTsgPIfe>\#둹]/Wўp}!ozuOCΓޗ?Q!n\9{٤<NM #ə]һC iNbZn' pV6SYe^V>4ob$T߻nB?!&*Iݮm1G$C=!T_s?gY}( V,@yn2 ɿ r>xtc?22LfeL}i؋,Ѡ/Lv.'0OpeRyz:ُLcx(~Eٱһ2 mOsks#x@\ C3cKԺwGS:Q ypΈx]ps(M I,uC `(A|\㲎0t 'VjR@|<Q>S߭T4 {v cd9Bga28¬t`Wz+gĵ?ͤ endstream endobj 413 0 obj <> stream x]mܶnAȧD0۳ vW${KrD(ivWf<ӳz={vz_]>^ntzۗӷWvZe엧O9Q,W,cy n>O׮2i']ŽO Y<ӏed9-3TNϺJf_>){ 'O<$>YҕPf"V첓Bf2xYsW4+s{حb _Գ;vS x09o߽d~҂\{ %WBO%`UN$vZ#?b_g%aL#q}֗DgE؊!?Z||E\/V ?:/W'IVg' m+r f*i%z []l3ۺyY:d4J1&8 ƍ\&+,0&Z?qʼn R*;*Uxe߬Ӟ~﷟z[Ʋ\ie -); W\mzGZ+g93 l&J0C%_Q'`ڮoxV%R.eeZG3. %eK>)- M\hrPk-וom7y_sw7R_~\HVɨN0ݨdJ5)'btSA@F557}  you*m{ҐQ1zk3ؾO\Au9 dC`ٰ`Bӷ<ެ_]dE *A0]nڱ`sTOۤlG*i. [A.DyI#Gig<R cU_>߶]~ KpeD0&2p+t\SN h/AQWZyʵ,k ;zTq`Ԯ-S9TJ-aUxIj~mZ|2! 48(pva0f?blՃ/LC_>M|| nob@'Dg6gБ)U w{cz]"mA]ñB-1sI"e DZSʮ d\l"iFr*#y,rTV 3&YE1W DDAYs,3ee> 5kQK5\`Kw~^Gƪ.hb 4&ݱ=Fviz Bph} aJ}aV< ÿQ7wl * $tøm9X74U|Sy`ݒžH:}:C4r05i31$|a=Q0w\A>c*&v:^gn'‡ &0i{X(9ƙN &m/xT#l.ßwD2; dԏ bie4jo]ܿ?rƺ즁Wq$K1h'ͭ d~t^^\&FZpг9Li|5\YlSf8j3ԋ|Sz}(Ji|8 5QάBp8~_ _;߳Vn?bF_Hs!Fki U3ps ?]0*l}" }Mxj[ͭ>ԡ j-E02 `%,Z[+Z;X:ef0M6?c18%Ci㘹(LJGWd[I.vrVb(` L̂Yӯ,eĘ>K3e ̂i; fB.w}D`wJ&}p =LT㐊{I0n#6h";L)r1"HwkЗnovZ`+Bt&clRAYj)sr2Ar'$#ZOf >'@dY-b*jWX?61Ntj@{z f2î$ 5uYf+,_GHRE\y[Cw6Ұ5K(`#.<+P8AWF ڈ@ _CWtlÂn+4ʃ1R8易ybM_2r :vrAtrGw{-LAPi,7;3H`S2H[pfx,Ǻ3´+ȳ=êzAؕA@Ih5W 0c6`ڞMF$գ*#3!d[0v=ܜ4F"K\`ޅY&:`ianhӥ(aev%iE ژJp,iqCUt" 6DPнy;bpEvp`[DW+Z4&i2&qFZv܋nƈ$X;ʼ*ӳU5va#W7rʂ}.=#e{6݌atT}H,QO)z*&!$$7ڷ !7owioJ,,#(kͦʩJ@j3V3&%*o@kEdMH}LFU։4S&7QÐwP5aY9 e}0pu6d['oWhaӠBLmڠ H?/ ʜJ9Jp)"XId0jx>CbeN9$޿Blj#9V*TbT9ej$SyaöX99sQK+b"l"tDLp|p"K-#%v"S"*Ð:H{ A2Ń/`Q0J;,Ql>d.U{}Ee{߽3|nfrtj YM;N2J/RfWݱGjd;M]d?뵨lTmN+y[G / Нv\kڿ V`IPHOHVU}h޺;IR fo&39N1+bB$giS1CP"ةl}pKWU:S\XIXT7aPMH( i[ oB^ڄdEn[˔0 a(B4cp 7Z}9-ݝ4)ep[$7\ =T)7V+&uҹlGKuK@[%}DFG.VGHNqQ!Nykk;DԕoW̷ZqQ 麦M\.?ٌlȦ/}ؐטxv| 8dqڳmF@{xQlB&ejBfK YctLrb6bBtmHVQ8 ޥ#ɼz,K^"%GiGQa(.B.bHK^uY3BupD CrP8b[}ir;v.ϒAT²nqA`6y,͸$MAQxsE-hz6]GQ{ '#;.iհwԽyG&rzg[ZW$UӊCccd:HYCB8zgʿd7#^L Jdެv$)gk1s(wS^gHBH%Z0,k `MؘW6eQz[st5m2uq.m3MuUwJW{^z%X1zኦU&Ή ')47G8l{r8y$WF8_+:S:w.MPLA}I;Q4{rû0G7y'̤BƳ7qH YwM5իݶEPP8B%]hV2ͅΛ%]":*=)>`7INV:5i*Ea%@mᦛ 'Y3D-R8U{wlgh0~Nk.C!zw k9FKY[<边$> stream x=o8g7aiz5{l2I^3NݾHJ$8d2I")أjzut_^}Y_'.Y̙vڵ@;pAp>k."!m vYPh{K󶗪]ḠX8`e}_w]ÃtͅwMtx^º.83F^É `^@-z.[,uS JW;[ZR{أG;A B gwpHgyފ7"'YyeS8\!OESq9HN%H'Vz =^D3:8ƙKG`&;R4˷wW]{yqtYʏ{{di)^UR1L?'w&|_Q1YWl`6cУtU#ٵ"9a@570ϰ©T|̶E?y sZwjf86;OC|,Iqwmjqߑau #U%= +Rcc&$]i 폕 tۣLokX5I>sgh~ g/#AޓnPQ)[>|M $y0m~${k*-ZZEhS5HVMܖ–a݇ գrUUnYUZV hpIAUekz9Edex滻AAY٨ cѺEAC<þArwm~nd"D]ç/MJL~rcO7I\XB#nZ{"!peٓQNIҨR#8#U]Td%zd <HftIkx$%H.n8U fxT.)܀"`{}@QWL>׏pw>m7l^*ve?&WŐ+ᠴ#*Ywލ7RB+@7=-rC<{zTۅXdK4 c Lz] bK4β-; wicWdگuv3y,?ؙeфuk)s NrRfwpG,=dw{: aL ܡ1w\<-qYZ]Cb|Ejւ^+ܹv"{wz4I ]js2䐙MyNKAN{dBvR͢@%?'֓bqh-$v@Ӈ~zQ瑘T s(r׎"U vɐ|WgzWl+(gQ|-s -rZ!\7nT鳮yA Cl\}T1wYxls;i;ҶK7 wf~@tׂ: vFV"ܲ+QV̮lE+c5nN&H>3{W{}6is#"KRؒbT_l-ϔQrz"];}D,^mFn&cr5>/.Tpϣv-Dd"Ø"YdzW4s!"&DDDN0h_Eđߤ&"m2+EdҬvŘ."3˳nʀݔA|Md?e0PE[[xnK|0n|Pg9P~3ZXEE]V=\b%M:jI$>lŇSx>ny4|Oq`c7OB̥#6g=Ŏ > t|\_{ъzC40tkeBUy({ΛU@SHKubK_P>älto>C ѳ)egnt4FŻ|nУ;oV?򡡆3qGcoIOet[Тu^/ Sr~s/ ZxcvT*zqBo뻤M>x?O}"V$ʏӭ>Auz߹Opc`pr -nYVpT~wO!TERm5jSm&UJ]y4?~ZC{@5UB Uw9; -lO?y$ b ~"6~}-gGZݦV쟚̩nn7ؙ"@ kժAwעovv3UA &(C1Jcs9GpV"HPf"A w\LƩW:d&+-7GySBwSB-10rc=Ȭd *Qo8XpF d԰GzPO#Hz5 ۶> Oa@gtCﯺZmB70dUZ0^., P;,-b!jG`Vq#G I<@Cjrb$1y9``LϦ!c\pgDj_cdzNZ!]a(3T1{f5E<@j߄27oM]I0NQ\h6^Z*Hb^UCEp#ƫxU5*<f/RXp}IHznÒz#"> stream x]Yo9~7UQ*yg :,wm} e,kRiReLfLfjr#>A׷_W?,?.nnQqrvZWҒ4lX(,-ES<._Ͽ_9qCW礨ˊW_cE#iIe՝z{٨r߾~iVQ\Wo4XZ2ԁPi UJFqA*?.}9-kivd)xB\~هUzf*fo/[dҊ\$ĽeN:f) ^X%<ȃ&B[onVuq:'ŦuvlH;!yayu?|u"|& IŎ 'MO 9wJۊF$'%çYS)$fUakUJԚIeTb$7s*_u>S^8ѳރd5e#jTU/do>Ed^Rz_GYxU@zZ=*%{Z+g%3iv x9'U[*Kxh9GmX+i~ QWwOs5o=i %}6oP \4I)Mi0}U8Qů^ nu x鞻w}Z_G%<X'4dHU31TlHma3oMԦo{XiDU a˦ ҧT/C],}t`YFt@nu^Ez܂a7>rZ1V|cOF A^_dцΖOnc[i-tc5iQM zIW:1zM1[=Q{ꞓivǤLe&nlGT9`k`vއl'T+DRݗ]D DԄ$p,@t $Ѥ``Ba,_ =,a'A0! A|Bzm\mbQW9 t:f7dS?^>j fg`}5? brecUtXD u& #y8'@(P F0(c b6u]r\#RVƁ$`T-eQ$:0'" NkB'c;  gÊfORAjU?lb$d$b^BI:8xpݖG}_S!2ZyNk X;ZRW1̍ jҜ g+; sz> )Y̾:K5ζr|zF $HCApiR7VH%E͹Jf˵og޲ms=ɳ'IZ7AE8'xF:m]\З]י].w9jrFNx`^K s+TbfrsÓrr3;vVx'1%Ns^V)缸SdˆLFsͨ#-xUå43.VkŤܷ7u >YQnI`IeXM ߛ#5rL#B^16Km%!uXCa^'KWze?bFYe`qƢNm#@'if>W\ @eEK`*46%j%"4.{---Fn#.]Q*"?.FMcIsQaX;EKMevH)[Hm86I{ЯCz|ЯL~X&:*,&a+5)#T3L*q(fwA^b?Mw<7$A&e0<pxM6nf!ނɵ_\ٹ9w4Af2r?}MfRadNxnbX\̞[C1;8}9'ހr)5G83P!\g~L |w|Dg-^t.5yxTʙe-۫ I_˕F?bKGc6fRd&å`#]MCflfLo;`T9C5;V^%SÃl0qtGnH=IOhn 9Q q?JJR|2މ?8~cb gw?T3{Sax[<~K ^+7.;ݣCX(.ួ5|.k-l n{2os {1[/=]i)>ӯD7zV\IZiOVΊ^ c+#;K>,wӒE|4Y^J8xc-~Zx2FGʡŸ5+%ThPFf)npJHqę:%K(-3TkgYw%#'TV7Rɧ"qЀ4 3'l`?*~:4 uc8;=̔zRƁC;-Nh?`=^Bf9|X/pU-J]m@1;džN^+q)N07AKjn9oS뙎<&]oSldɖގWU5=[=V#MTԟݮ\_ fB&Fs׀ŠA{XV :rx =DZ[by=f ニDxR(I'eZgq#Y˜2g4ݺ C8F, n{ѦSߗh1ε8=;NniqjZhsZA?B7txF+pW_ʻG \|Y: H~xȾqXt%W^HA.}[U@#T|kw^teWv=a-R_Ѧar+!s:ء#I=0.\%?=+~wQD]CE"U/&d-Q*/ܱ\eMD)?ګp½گiqDuv|CJ^e /SwQ&#eQ|2nSst6GC/asܖ.AMmU6݋16}](;4$^=> stream x]ms6~:# xV^.winC8lW[9YM|HKK"}v.@d[__\o=:..oWWǣ_:zqح7eXLEd,HTv??+rjWFώ^_cQHifQTFwʣϒ~hKt^&Fue`im`FLEy_~#rx?R\EBq0<B/qxswqʣȴ.8JA,r$ж+_`} ü%X FnԼTD "wgR?vy-cxIXKʎ`2\mz{x1}lB=K%͇\̶ԻF拌Z-y>ϔnI?O$)[ fӟg r ~ r]}}os#Z>w_CxE\F4Wc &G7 mTSͦq3o P_ U}%BjR #p"lZP>qe uO|"G!pX>,=o^DI tСv x"U |mFA1I^gp0h>vRirN0㜐*f{wqj|KH˙C{BDFTǧmz&q"IÞP+Hy2<~Yym\{{'y "8g;n4%@.ӢM|"Ug$#NJAHMAhBC0Q,Iv0/smZ'SjG&Gsz^4R -"]߿Í]|pUUI4T^g&{!L ĢE#?40Z0$ʵngIDVҨs`]YIه0ڵ(ǻH'C⵹4]SG}77vzW<ɠ)Wn 89-mRa0JOQh[Y#̅k:P[YYUupu?RwGrOt1u)/I,j*DoX4!3'̞ ~ -%;]Ⱥ<-StypNAl+D&^34wW=ҕ \VP[hrԹ/, )V0{;6sevpPMШ <ۭ{V "U]38(ۃzg)'T(m ³VCAi' ##8VF,IE[0JW6e*l,%O- UB!|G%IbEx>m7/ ; (3FoiL@1+X<mtxU>$C['h+U}e=L ]u-2#3f3BL: s$c6uY%U,}6;ڮc^]^Ai^{+s&OcN9WV9ui=R9~zB;僪-O L}%zW\KNP˨Y,ifk4DimAE}'2eSOnnB>  4Wl$Ïf`J¼6ک|!j…xgbDݨQ&U866 endstream endobj 417 0 obj <> stream x=r9?ľRᮚp(Bmc@Ic[&==_?yUEJfOL"Dy"99Wիnuy[_eN>n_jwYf篗?_RʜQy2eMmfdnl[|/_49+ux勓"+BgYVDKKe3@}rEvC?u~ŧY6G_x($L> B:\)< 3u- V.xiZ˼]-lnt~/`t?}{a%;,TMoq6 3{^9>e?OX-6Cñܽl9O[֕C嘠ƮG'DBS (T(|^Vܞ.> RS 0^?MN?U]j+jLW U%ڎwW7^o2]@ Pf!(kMn/}r< sMvK X%{kWWWIA =Wev0n9e׻4 I, P#̸꒔䠗Vr e\ *qبz7_\_7|a *@ҫϤn+CG9N CIh) T1/3 a9_]+x6kkh>! y22- uաZAv(v 'yjlV]D,J& W6"H0>@ybt2W:AK5Uӄ Nޣ~uV4 4Uvp@ |ᵰAE e[@־1“< n*{Kz`jX(E* X\wu$P/q@$ }`m/F*N\OΟ+pT\7 r&0 T#5@pEvX%\5̿~Q3xGK qܕo]_Jni*9C:s@0sd`֋jA|/ʆ?u#1B+,l9ׁǐGlqv(#ЌL5&c<<2/쐄XxW5N௢ 3]%E?Cr!(eg(}0=6!B5 mu%eH B$9 HHfp#UB(@ҔIz:`VtiJɒYuWd;W,Ú#5XXQ}XǏ({p>A>"ٲ4W75>=ff Q K.;;Nq/=Dd˻j 2P| VEKQu6 yx.r &ȶѭ1ȏh>1žgܬv mK Xϩ6\q t$Z~/`LKQ0!h`imwr)r32ֽ==_ ^UͼU=Dgh@ѫ8M笰2/Ȉ|!CeQ:vv;l>fb>m/@r%6 fs!MQ؎Auމ.wuh>qP83i&d$'!ȏ,tC E!? )Mœ.|2i{J% _:dWzХ c=Ko'O-߂"2Ű H|t$W7h"ynw胛="\藇H.S1Q8. :HnICoGڨkVRݘ{\QPʒϳd  m2'}u5afo,6 <;#TV!tR%3aYɱ"KҤ0R$ p; ;41#,ʣr5vuBl$ՁEMTaqE6Z#İw7>B ˊD75U6)3 B_;ah&ID3]:.'6/}peZ`]:ho^Y)[ "JX=כshIvb rSnXY([ܢ9.5ȯwP=Fu+ğ`\V=V<6Q)2xޮ>l> *i>{A3hZG7;'(B<뿍 WR.c0ֻ=NzKzX$qD|%VREeTklpwut+%$@'N|A4"Z)(S@95m1ͯ؉! w/,7 WB7yĺDa ݒiX[$a+r>XS/HVgZG7z)Bp6/*A-ot\'8M+>eĭL9\$L(ʋ2$A=JŶ'da%kGd 8#Hɪ{`w"Ls^mr-ql ߼c{xdѽ!vpQ &wj\z')P)m8Q*h&ᛜQbt}+eskFXs|0[zY> D@H|oB8}2]^LȄ5l ds!!MT-t/8Q9wSe(dSƏkm:O7tK!.LqnQQwH\/!y\FKɸ]E|MTPah`P?~ m`†?DJn݇t rط E~ HYsbAK6 xLUSKLΆ!*:35fZu{F;pzL)gzPб_>saU%9<[)GLK&P<8+ȟ 5O8[ZQ%+/Y1Q:cF1Ih.N xqH}b^}4Jq U\P {mlޒI@d6`yg ?DON'0M7@W~Ke ͤu?P^(9$R'bL:iZ:&(K~ȧlt2Ғ#ٍBtN:im΃wdt!i1D 1な@\.QF Q}ݕu({CԒ%PbV"}J$lxێvD- JH#4n8naO »8IPMO'W-y7G "4=5=^~;m|0^-ntUxPZakRVm)8!ګ s 뗅H01T~)Cj0%Vgd{fnL)X'&J> &p͒&'HSs7+V&7Zc:9+ ODW ث=ȷ=69) <[۱kܨ=Hق,ÒAvM=v<؉  4' endstream endobj 418 0 obj <> stream x]mo8 AgY| $v2$!:v.ζ;7뷪Hꍤ$0U*T"sp\WN_UN?m{assy/93YDnD&ʥϕۗ/ OWY:iJdͧ/N߱ }ײcxuV=PєEvC_eU[_x ,hxX_Kʊ9H2N e,/ZQџW' NJ&ĝiy%򿰙G;?,/Fr)eMȥJ{5S:*) _ aﰭ7w{|xamJt ]vlI%* !$ϋB*%Ү2=Y 2y;闪\Ȅbe%V\HvO/vbEX ;;pA>k3}NZ`kLkJ~z0?SEyDBUޛ4oG8b&媠?7ۮtK逮YGtcbt: Jw7L={ҹ4C=jƷg!B4܃^WԤV]l.'%RvDwO˅><< &0N Tӕ0!K'zϜd7`4*ŨnzOEI>n蝏of}"҉,n(>a\7Y 9U)N, ݂~K۟G4w?1 =ECntDEo͋;> "F0Z~q?nw1#kdQjSx8Q qm+G-whmc`-K['\wj`X7pΚ碇K<@j"D@@BHPux!53iZ%" *3N*hЗh>x۶4·`?ErIw2Cq*0M|&vQ eR- N&@p6UyiZ% vv>иoM]E׎_ɓjYZ@(ld!Ɋ \R7ſ~IcZ΄ā훶 Ieh4e߀^k*x1V5f;Pô;5aKi $DWm3tἢeքnP 05jsRbHe0p@!=ZnЉح\ι c#i6J A<=D'ʓ)`ҩ=}'zCQ`WE{4nk&VIhL]S+?s?fԃ4w3a2-;`U|<ѡכi\c~K5m+=/ Zq GyÜ]0V}W*RMF泈!ÍL9q+3D/ތ`n_zozK}oח ZᚉDžżB[%D9vتL"ۍ&Aϙ򾿗2#DRvo'Z`HnY,% E7k\ɗL+'c߬"Iګ9 Pd阎9熬JZMIʁBK eECZyK}PŦ-. uV,1!EެvT32޳Dc* uέ1Ja*xЄ>`.*Fz#ǻ5ٳ􈩖b*7- J n E&f޷JχfzPg$ z[(ςD4!UR^}v:;ުB,`V@ Kχ>%.{DL$R4U)Fwyn+ڥjguN3 [euLQzdzLbl-hƖhx%5D-%d)/x.$BʌTirt6\̪ZA<]\l8\ˤIV<&W;VuX\ϴab.aDWfGKAy}%N\_\;+V[Zg̬vW [H&SX?TXsѾz%n֡~|m#_]CN?PxlԽB}T+lZl)ict:h֫B#d,%6mOkPLk rk-}='%RVc\cRbcZ1)=U 6p,v7-ٶX@Ԅ#b^ϿىaAb3 o[jO샛h<ɺZaXF# SBBĄP9D4%ҽ䎠:ހk`^QᷡNFz} ,Zq ,1 -Ny*Q{\(W!(%\p2NOFN"ipNhKUm%E6޵;dhHqWal)R*R{>^ [!BܰqD1;*5b,FH񱍵X pSCN< /g{88ަ:GN5&[y@؂SXR~J9:Cy5lDQV=JZIiJ$ʈȣ5 !C$ Z|lc'f(֑sC=Hڲ/LQO6 9F%ZjXU+:Kk b53ω Y:lC]"`4*iiIFikљ&f^5RmIeЈhJ YҰIGYi ,-N][OKvI!R5:ɝPMkxgnB\qD;FiiI;6yYVa7rX6+))Ϊ@GOsh|?nm_ kg+B@&idr+f<Պyb,V16X 'ơ>Hkӣ&erkNdsTŽZsTه#QC>.m<O: 9Faj; Pe3]®Ox|MAl6%&O8%ˡObH{F78ȴxB\NR '#d$NæWG ZANעu3D |35Sk 8թC<  Ģ4/>'jlnh3ǷFBɢ=*FG1k1kIF0KmMAft!h7Q9{61<| Oܰq74|vK<ٝ$-{3QO[hrpZĆ5^K kKmv k'`ʆ۳69κg*'lXj)%uuzN9p׉O4Љeݰv98Hއ{ wQc֡ݮRmXRt7oM7 aʬeR;~@#'4` 4ziݔHZEAZ\/-ytI8 -wX;rw_]Gy­^t՟BO8n׵>'& k"B8B2芷h-,4_(ϋ&S9sRT!щ7v֠YlzPYOG_j{ޡ%;„,j|<*/$ $DD,ܒB)ꥏw5vPg?QкGK\= ~x:$GsGީ\9›zo0ѻ# ذHu #O1B)b9 O1Ixks@OQE,9G [K,):~#9oeNpr!څrՅS\I8:{,ܦ{f+#MrA2GڐbJlfƮ/rz;H! rmFHCy}t2>8KlbGSmg.g!sU#,VG7ˉli-w bѮ}ӄ)4=z}wx:ye\#h9WkrӢ>3(mrKmE("fyeTL(̓gӂƏ*0XfBL~pK(,Qe:o2:teDa\;Q˝Ov^XSXe)K2I٦VCL N endstream endobj 419 0 obj <> stream xko{"}s[Nr4vilTV. CE"3ytY_;9Ww?O.~ޜ_?2;;_e~P)r2&Ee&h.tۼ|f/_TpN._8yM2/xvye#/iNeivPo.n^([7/_|efx7@3B<6S%q<ʆ\(4/i\\4_ُǧ`T_6doM˹{9xu21oJ|ţMǶޟo*[ {i /n%/!?- ~j9_6_pr [J˅`|)hq@`dw;nѡ)j˅^MpaP&%ָYP ӾZaL%o|\^+?!-µueM16Buov]ǹוټcI,,%)3D8$ekF'Qw@;n\t@f ŷ}uFfYo zj]<ˮdwn]@C% YlgZ_e FVd95֋/"{3_I7pf-%`,YK[ 4Xem$zk+ڙ?Dx1Z!\n}n4(ѼlAZ͇p|Td# ~S_AfFQxc4[?lnǃ:ҎǃWy<*@-6ѨQ"/%:_v_2 4&4ŀD[mU>}9)L C(1!gɌ⻫G887j+zY't;67r|d_w#޾^Ų!4e]K.8mTenvֺZ` ǎVyAyL jɃ26eZ1%Xv>8q~IK}ZKD;L@Sr IPaQl{]ΥX03Z9WH:O?jIsuΙuP`ݡBǹ]%D̺O99BvNBO72^70UlDC6<8b! RrB}DV- "ArХn]_Wz@%1b(7ۂ aiwr~<քi2Z(L|>咥"4%)-oRrɣ1K~,޲N8cc2p+A |ztDKJ.U2 mK*S>d%UZ^=<3gp@DPչ㭺mub:p *b_DsŞUȎXVp""͎bkr XfﳹO{kø;i&3]I%K7ZaZtAq -ck4M )Bi0ILiŃ<󇍖b(>&D 5iX Yj#c .”^XwRRJGlm@zָ*jc!n̺Tf-h[g4'&-C2+ݱW-e 2ٲE@t 3M['<'AZvH@i=+-H#xlcGC3`-g1 Ңrmm-+A4zV:)K Qb2|ֆ%x-0%$RP*VBzTf:aӏ#2'!&~LSX? s}*-{Di l~m[[{~C@ T$VV4ֽjk?bS^w-2 {`Mz uHυP'X_eil8csU&s}nh7n 2-P mleG4j_[SRqQ O.az, A?` gA-稍bQ f)|(|*+ܲbI&ָxy(LiJ@q%SK;2NT9gma.Q%ۺk!Cqgsju0^Lf.4fEO0WC%I `X`t~ڹ2ljvf&6/ %%5C8!Qb$m0?c\hE \0>|/" _zS*f٥|6 ׵J}b ƻY_D,|o(`~H$ ~1?l26gcPh&)>e7Qhr}{!hH&:rRӦ22&0'L0H XNJr#"aJ~ kڜ/$\9ϛ; A[d/ļLi[Vyz]{T8DOu c=1] \f4ia zڭ#@K6:(DO]XK!Y2'xȬWNWIJo.{mFe]t׹'ssQefGlK>3vDk̥:ԏy,QD}Ezaέddzji.f^}xuaitOAu rUE=s =XijQ@$&Lmplr{&E:eN`S`j9H v|OZR։~ؘ6#'ghO]gq)*>q1JOem3anI n:{d Ew"TE0RS֙}L[PY(Uahl(S6TT tFap^Z% ow wbdz V k3x3x<.9P`*civL9v1gF|b&Kcgx, b\׹Nv;)i#ߢ;{0ӸrW&:9)~N\ J~Au]g~0;;8h1 AWi׋T~EC@ijx⑅IT 6w*~+Jq܉bO0p’@ng g >o D: S`3)00?d HVt|)' 6\ŐK_ _[Ok#(~+BQGVtr[2`N6g@)1Yf%eYW) R^I5SN $6}LkWbRp1zY;b v?ZLD65L@0Xr@ji|Ldo {T~Wٿ7qP6 4ʷh:AuWNɄ):bXU TNlW4Kʅ@p3 dⱭQDzQU|@ $')upս1V-)?\(z?h?h2heVX:ޣzBǯh`Y8e<)hht=cx>.;ʇtJ* 1?R4o endstream endobj 420 0 obj <> stream x\o8 ҽؖŗ$ds7ͭs{2m;q޽EzP;=`0G->XEUdvp%?pf[^߯n/'7O9a=l֧yׯIaTjUr<1256ٮ^%ׯ|Ӯ^AJT<;iϷ,?R2O kS|~Z/m=~%wSgׯ̒_[?A&E)LEU|22-e//w FGȝ}<>OfaB?iL.?m2S6rQ5f.@oρ*S-tpwxNB}im 4^U62z?dR1Y߸gO٩UErW%S9#ߜ.'[~*R)?GRTQkemL"WhBq[&eg8 `aٜn/^P&0?AGڤoi#մljX ,$mvcl_og/d1K-LŘ)2RTZJ3_fop-^Eޥ2AzE/pú|S-_ <ϋ/\XW~H hpcZ `Xp>P6koekz}R|y W{ BA\WV]l{Uuk; ¼9@ꛨD& DrD胅Mm Տk$lm`OGXI;3)mO!gMRBdY҉t@""˰#azF Fm224ur(7`] )f{xm i#eZFѡ5 N 0hi6 S< @@2%LV}Xs2>ֆbrXՆm=pfυC5Ѫ٩B$ޤvD%niv8'I&?0H 5?>L64;ehOp=H9JOc. rvN6 + O:I;Gedx;<~,\ <ݺ@ -;- hӳWlBKd低jwuWΓqTZ\#@ASQ9`TL ȔXUIN?̊n=HƐ!&T/OǥCK&V6ݮz8o osQ@E^ [[z.Ј_T ..7\陏rPB~u_;l*y3a7m{ "S6#>1[׵mG53"axey-d<9nU**q v$3VIќdw G=Pqs&;(R^QЬe00hBSRf-`Lt6Sxz_uh!%=уaC4-RxmI<ѳG|Xm ?,3z^VC2/n:,Im#5b{ g5"s@zόr$tF ?3O1ʵ!xt|<jG+dcJnAK6WoO^ut]N ۫n~[Wg6FZcFԓ {YӅ{nXОD$M#]5.Qge!D}$Oa`MQ'h~IEj|0`Cgs֭ m8lM _UҤSAyT" ٿr_>U=wCq@DhX|O :=>;*T>PMqҡsZX/wP[UG*ۏ Nc0vø[~=XOLk$[Qkǐ>c2}.wDe =XOkE&u\;EesL3X h|ϵel~7" y6.VqgѳxAl|#YWW ?Cw 2pr,?[K2Tɍ;8Ғ+ =jLgc˻FE*3}Lm@JR0!0]R1fg] N׏P{,R&x/ԓ4hmvtI~*}Kո4r5jYAi\f#= Foӊx+nB(W3 ĭ5#l] ! _>nxa  {".`ϯBT(|Jt;{Ӈ1ZR$`揘SWo SDklVݢJWZAyԞNkIY]ݑ2tx#&/6i轏U_M/{XPF;`TSUR9L:uxTmy-*W8T^,؞**Pei@BEӵAdZMkR SmAlgwʼnPxaƘ=z;0qr?&!lc)B,KپMMԮ m +@rI=g=஑{TYhZ ORe~Q7 W>Na|Znaݖ|E+h#Q\V-iCGțINV-' 1gw$* A\8\Z Y鑸?u%îq%{Vt|p #!/d?|qĜܨ7b &[\#GyU18Ty||IDwнD"-&s"dveF$n|[~Fi3lpr3J{i*쌆4Ǻ3 l-: CRm} *?^ yxEjIw0:t0Mat5w \.or1o>w1K!ScLޭ lz\i*>1tUj:H"$'4 ײYB]JA^pjCb '-.'KpӅ {^I$=[ &>e7᯦Ӱ:K׮ h̛xm̾g[|.$kS#zGdJkoLKpAfNyʙm<),ei[I ,: mq f{ uv!M!Rֆp,_dٿ0i3dO==<#%aO+ y \eSN#|FZV .37<( n=Ƀr$y0lW`Р?y }#_[_if*pv9,x ~?eg] [X}| hp s#2l ]!g|F [3~zff9+[”xߜﰆOD$x龗kübeiprHx~bΒ߻VOII1Z]jqPvqjB6vKa٬QLFD|MY 1<}{ bEe$ۏ }n:<f Hj`.1k-HbgA1KG:hu4݄Jn<))=:=}yd_ϳf.gL3EVx&g.9n$ܤ\#NvUMA${ڼ, endstream endobj 421 0 obj <> stream x\mo8 AgY|cwlvݞߪ"DRRdyg$Q녬ȒOgŋjsQ|g,>2+*-L-OZIWO@NJfȝ/z<]o(|ptB߾{:0xO.8?>:<9ZZ[1HJV zZBZKh.c뛳ˍ)^wmJ3mFM NJHDiFK O#J[*HӟliuVMB@=Diq 'wM.wyXpcL겔ՠV)J15QBLJ6kڂQh`ן+w>ԫIM7fwάI?4''99 ]\ k=9ux pa2Ø=+#|VJLՀʺcq̛/b=xue HjAWL† *$n"oO7At)-ѐTepP+^9e2 :DRj7z )X3Oī='l'| 6pE.xc<%}s -m4CZtz:Dk0F m=Jஒ.V]Y"]b ⺻Kd+<LJ$#S0rq/+p_(E{$xj4mT;@!+ͥ]hJa܍Pt.TYe*Hu1|hw;9 qr0Ifai'z`-ʗ|4~kޝGw7DsMqt:db`OST뤙-.kU zPS]᾿o"FBRS b*MԦlF1#YHIuv͢B9bL>RU:Mu/3!ZHc) /0+ܖ,!tNڰfcf,*&MeYYCSi2͖tV~dˮBHup˗ݧ Vmo̮n 5,<ڨ\Oi Gr|O8oJ]⮠YS!$@/R)8 {p8NXg/j@';辈X57J'7LMdT `r&l Z$)aVcXX7_xvel.9c*qÿzf RKyXz)5 $oW-~ vW(gC$+,!WD{bqe}t`7vEM{q,ߵ6K8b7VHʼn澷L+fZW4Bi _9Rt#LՍyLM WG5a@ £_cx}{mX[a-A(*NM]k5@[py!G(%vhn}ע!`;P X#n:e\׽8:;}v;6{"QPs%3ڠQA-6NJEWWTEhn7'7N6*m[FݾVd鉦[F=Xi?ּm_{|zGwXidMs=~\ X0idTY3uߚɕBW[s9zIiL|A:9TZ 7̍4쁁oo{h i#?g)*A>/棄WJ""wJ?x#51FFB2C4Ü-)ل-s2uw̛DDy1V ˑ{D7BRڠHCJ"^eb)C;\ ,ca%^KRaa6($QͽUFZҸ?37%nlvcmTF4C9'==9˙)q]|]FuQSޙGޙ$_jjM=.e@ٙ }<߳\'b3m D$a "m=?b*Y'>G*>GT9|-g0 A^^+Xwü2睰MϿtL]rĭle9xn8__]}Xg8crǁ٫s9|gFtw1GY!.[9D%,*LYLdvX7$g߁owh,Ow,(? 0s􃿻;H/)yگ 7 ֟ 0˚ 1 ~=czKY߅)F_6`qK:!cپ/M=`TPq@a^YD(XL x˙?u-)>* 5yH@ 7~= Goۙ+-!ED>H,""KJ ZP!_`fG3,.u#"S" r>G[#ƪc#ֱw+[ ͬ z3P߂3 ~=dUȫ4׵ ;P T܇9.,no GѮ1^

> stream x[o8? x"@.mv7;>“:NMsHJDRVee[:乐#?og7kz=#ׇWWߟr_-)e,h3 W2HIC{,J '\!j'W{()\[hFrG(Xd\=d񲿗*Lg.&0Bi4]PolՑ&W7ד˿Z`Qד7P2)Nr遘|_QnЋ 3Y?ULȄs_TN>3[,xdU$Ї.ޣ|!SlZ1an`%.9?GJx<G?ppNсkʉHv|t`{1q /MƎ!Wt9fܶaiűqkr"^ЙR`@-,N 7xڗ- O#!3XYQO]&3‚Ky&zzLMU&晁@V :+jv5MJFgwzrx9yf1Fh>gHdL*%G[^zow'iqK KRF3c~ Si 5j ?=/ػj{\×i22A{9AH~T'[/Qu h D5ܣ9MW9WN F+2W2X:xbt"G ݆B/x|>xFOL˃󓩯.X1O)AVHrh7 ŷ IULVzo|oئԤILwƉ>L řyWdu`8Lbi8=`t2A,]x` %. ,Н 8ڂ!|r+>Go5-2-'lgIѼZVL|*X|ZւXj],$u]XQR@0g`,3aTwmfb!&阣nVPUۨs3^U_6{7!'0AdB``&0)3ɓ0rjرBdTrj0݃g6kXיS*< ix=4*EaIi؄zSZ9.q]>`"1p4Zk{*ǣ$dx. ߖQ`Q] NWP'KNm(Á mJDm],ˑ%OIJޓHgr^݌5#.2x>~Lv  %]w@V9 ; Е>ɰY|u3l>TS)Vjݗ.*EML|U % gNk;,^’IգۢpNҘ"8. %A XDx\rqM^)j:۩vH" 2AKhDfI-QؒVb۹& AԻ]b&F2˰qxflhhMΞ:Ejhp{1{;/vV\|By YǨ$OԇivmgU0n0niv<A=8J;7>:S㞎TpDxw(}O&knՒ*I졥Ww!. ]$J@vTִnqYSGmFḡ (YQǖq4Uv_&j;,''OofkgV!sW1bр[)#TBD BzaY:Ya]:[)j[]!6V~=1g;i1-vP3*2C"p lg= %;ly]هLs+<3׭? Uݦzڎ7֏sq5iH5P"S t iLt/j'.,ƵX )k8ED\  "!ξAvW< Ʒ! 1B߷OɎ0= O[[' qķQǶķ@˟64%!o;0:2 _Bے6Lio:| zC|Tv7[&7'ҍo߼1| V;*2),[ {?{۫nj,j^ySA68,6#9RѧPdNWI05v26NVSEYCgg\mA&\ @0VKO1"hY3`n⪇q\OSsaL{.y!Tk56 b@7LIt4z {KT=a:d:16&*%b΋l.ڏ:+ZP04'C> endobj 431 0 obj <> stream x]ˮ$qkj) @& H,/Há!sީ̬jbtW<3NdF_yO&'iz~A<,n C2Dh(r!ɥ0ݨn n fF S|BC`4q"\ @ B(EDf]^̰B/ Y ᨝Mg h )(#-É90 n|ggM)/xBZ${} 8(A.Ҕh 8@ ƉvgNP-ʄNaS#`2e'؝0O@Yfa9L x˙p9"LkM$s6ŹILAa7 {< 4I0[( 6BzlI80[`%̖!fKd1ԙt_:jc@[ uKVLҺi^N $!PD&OdTf5@Twd*j7*!($\aJ@SIVhoJf_%3" ʀhEi\*e(@3}Vę2?EqY S^ÍA.)bJ3%(=9(K7 g^%h m6X :B-y>B3Ri)O bYFiOa*4y)9S2Ph\"0()yS^f` sY`lJHa2$q o$(fy&YgMbl@)ya'.2?O 9PrVbRPJA!1(( E 1q@ $14*1G~0Rs^s b #9YmlQ]&nj\}scXF$fnĔ3d1ʙSd3?P9n$gFp,(DF4sD9gZdq̙,GX契`2ଌ P^A0@7HG#Hbxb 9<QY!gRi2PaSJ^N)EtXRےueZNa,=h&dP,yڱHR2jͱgqLtgF<{b."0HJ}JFm3,K6Q+l8QJQvHĹD^Ua9Y{"^h R3u(V݀ B!cI!l} cB+LS`!~󉄥s騃c+Ī /[YXA ?OHVB!9I?t2:J BgNT^VP"RR ta-S/)0 RR8U?ϴ #qn?;ZAqTQ#AEbR5ci_ΜZCyya; #xVJfW b'(6ĹJt f^IG Ks|€+q@8GCq{" \+ϲ2Q\;b /8WƤP(qS[#ʪYAe]* o )l#pi Btd! rT{LȲ,ŕ qY=,^0䊊TOR.(!Ÿ[U=7:rE%S/9( څ]s!@io߼]7_7_w|W޼~ o5]sR>/rC >}xz=ӏӇ~~闧wO|Qbpڗ"&'2zjϼ{5힆uϻ/qG˷sׁv/-\u1߾nbDU\w+Ԯw ҳ\xG/mrEWK:6cg'uqx醫w\tԵzR/5R/ţ XSnuMuVRn,/܏7<7O]-߳{V/yWпj{ibiŞ| 6}g#Qt1E/uqr YةVP/G<=92:"kBr8ff΅᪠ÅD`I:cJXK#WA7 h]hjcV]>V ==| = ,L;%4UW+Jc-ANK=N's8a?OK%c s2ɰ)tE<;!SfuJ¶iv4>x@_LQ~<~~qt= vzqJL串7,,R:x&7tM<]o90l<=9Nd:tN^NvtKzIvWyX9:KB{?RdU'SwӾSN|neWet- zվb[TlO^+׼.v#ֵK[clh|\N̟u HW|ne㽪؞Fc;lر.+i;Rw|ndV{znREYGY-/,[,piȬ,QR5J{[k|G-U>73W>%v|ndVioUjTWcF(Q.*GO~FoxޟCM2OlN*Wg:j=WSi5_rݖ8n:MR󇏗=nwKi6rV|ٰ?"!=wmmcq (~|~=.XAeV7&ձg:! Wsa]Mci+ai+{|J{pQ>/IhPFihl|V_cǍ?xڏ+Y~-?Y+FaD=֯IlgŭFFvF_kldTF+vna~-?bZ$5ccf=5jU562*53*VjTWc+O'}& squ&kѹ&Չҝ\P%ghKa|c_~o{ zn{a#La)0<$kw?iYĶKb_dl v]XM;R"W(D޺m0y q!0W!M'.Un}A Ak bo$j%.֋lrD=^1=H\ IZCRV:C\nq!8ĕ q& *R *-)bP)v_AK1m?%]x@O p!0W!.*#\ըA*ᒆ^f{{zzR_4fIV7P,~| Jw)f C\q+ q!.!2µ9]PwΒ[ۥ~r"o km֊wl;-07WC\i+qq7u=64XKzۊR۱Vsj;jwv5ԛ,힍l v:`j`X!0W!.*#\{6t6YѠb *Ѡb@m&ݏWTh7=PW_I[WJC\yKtp<冸63u[dPI٠b.lj{jjj՚km֚(n~ X]wf`JC\yKtpy qm@~ Kz!ZgggggZo]`s!ڹ+0TݟؿW!.*#\nctUad'+j?]v_rݲggggg-Vik'=xҫ+> stream x]]$m}Џ6 qȐfAE2ى}x޾{SdxXҗu鉖" ާ"umIIK]R,g^jƫ,iV/JT(+eUB 3 eL}j3Xmyh˥㊶\*zj-6 WX(W SSk[XBWA 'n* Wx,qE, WW WT 7PsȾ.%!P3L?'f|1laqKao*/PeZ7RIvӁUIojJ:F%mMq`A!JU#+ﶡN\ *eITyJ>:JGˤ:jUG#B˪(uB;08*ɒWJy=hEjdقRZWz <$,b6kgrqRI۫ ֫ʌPSI[n!JUc@^S&Q5raSم~# BN}I -ʒW* Z!R A @(J3O*K7O0JipJYV4* ZQ7UjJ[*'UVYPU2ߚ孺Řy!!)!T[5O*k5OV :@y\٬k٬kvXeibؒhKoe2D_4fn)[T7fѩn}*muXS>jCC\7>E:L]C>n6A: }S-y :lWѸ$ "Ǫ wQ3dCDb&A}Q*0|2+7=:領Tќ VۺdndJVkUCvjWaS€IBXI] م`tFL @vuVV &J]MH0,<V ؔ$@b%ۄfRz]%`bMZD?f0h~_Rb[ 7{aSUTmy <;oy^DBE͛h&oy#o"(f/7{,KY lK%|^VRV2[1.2{1w1xs"Yp0"R,^:? V4bu2W#6]*|%D %]\RY`bFQQ՘jaðbabX *2\4R!*`%UhQ"2dmhڬWH歊rFa!]4##47#4F3HK#H+ XZYՊcӪDky6DM[Nֺ*:V7*V` g3HBV-cP~;pWdLn¤jHP -V,-iQѺѪh05jɈ1nW/ ڭRlo6_{(.m ڮA¶hS t 쯟⍶oT[VQ4AvFNC)͖U,xBӐ%whۢ D m3DцXGTI`ض{szKCm5Ԏ=;4[dT AG ΗVPUYXv*B[7B*v4&+T V*V0mLlƔ4Y16D 1N2DL V1}@ n}Cctn/`C`CM3zlR#ڦDO*b@k5 FEBe@WE[cۤSBЊ݄Ė] b 5ӑ6jjds9ٮ e5Mw*n픺K7LY\F&𫈙 ɟ_pL*blZd_jX*5n*vkWg[`6Bvِn6vh]srIV/%ŢZ@E,K FbQ-H %J !?E~(͜P:+֪*Z/*꺭VɂPm^א*&T$]UhAPdǜQ (^;Hb'ͺT vFAh6cwɂ Yr As$HCzҫ*-9-A=`M+B$KMdb"2!s0*#!k4;JH6Xh4pc A*B䪈 &=0dFSl6/ɚ 2nʄ\-kKE䒄qFm[ 6; cmEY> zXGW3( I*ںUp<,!"pNyPQQIT ~HVmy.P1$e8:GW7b_q]۟?~ǟw9>[{1Xzb0$K'Xa_|O,cW_ײ-/a|>`Xno߼6ޕr}×e+ 3ݷ`5k1XQ 1`'Z>E?{=yQiTƴ8a#ZÅobw Koaj b5c0N(2Eÿ_/{=uĺөtiLÊ?E9\=ZȈd\J Vc1`hQqq8n{=RmE+㸮WA5=뺓{qGq} s Vb`m(;ѡY\=}qqC I\~[nmb rWĵ p} (3nη;pdv.$ ŅBs.W'nt WEs-ݤs q5kA\x]8 83nmt*SJTb{L$be7zdZ>;t^ɷO^sWĵ pqqw &fLvJSBxHMld:dЍ[?߫۵<>z w*?QAq)A\ 7+Ӟ[tSJTi#w#w#w#w#wYn=Q3 VkQAq)A\ jׂ7g;czm)NAv 8??????E듉󮝪wʇ!^mtg=}H 8 .q9+A\ ZC89I2Rr*Y>y)A^ /E"K*EG3TC7q7KmGr'N q5kA\Gs"KRy)Ae'"K*ERwJm,{R q=;W( MLKRy)A^ /E"KRy)Jt!*!Jʯ$-#\ jׂÝ+pq'A9KRy)A^ /E"KR]"~)BQڡ^)kI˹rW\9 8 RwNRy)A^ /Ev\`ąBvAKU"I˹`ׂÝ pq'A\ rWθi)^`/E"KR{)^R/EH~TM/,#\G8 8 .q9+A9K %{I^R`/)K %Ie7z|0~ms \0 8 R f߉d_GSK %{I^R`/)kNQD79+xGyLݏl~P[C^۾n|v|Pm"7|/ooR'vgE[؏{c(ŝ8:vXypϿýF˷O?Iݏ?bqrjr|_(t8gQs{՚D@)PGO{ɲ 9˿pWM3-W֛^ZÊ덠byċ]#F=Ch"G3_uE@I&מU%P{ oԾ4#47n;M8y^ex4q۝>O{=Q9 \>G֙/Σ]&hCTo`/@I"ƚ1FYUY^+ӓjXrxc4ĔTWY/C7Gp˿~}7o[}M5uP.3#Pki+#l-#:u3Ja\sg vR{7ӕIb*&5ğ1]u 07B^էI"~Q zl#O䨙S r>~+넷#<7|> stream x]M6rqHdq0lؾ0'/mߧG^uHJH다Tgg&cٚlM x169\I l|N0Y"]0$ M` 8 d5YHP  %8qM>#GIxWIܣ7dM1^R $K'e<̻JyO9JH/EUBs˵I!*VpaDyJ8(HΪdKzAD\!&J/qYy%⹬dRJ/ N4G (HE#)A~ eRQ ZZkz7NP4+$ RL<:V)KsN]a;Ad8QS4N0ja%1^0UK P"lzxMy,"tY5^j:RSRWPCV-҄,JJJ z`/AMO7:/h!P]w#%P! ({fRq bì<w՜AE.N9A"rzo\f=\}"d"]>b)hA)GjC@\X + 1^K&MJ<-ZcLᓋ&,s(HbHB s*buXɜAB1#"NM*AJTPLf1SbFF$zCM"xħp%}-p'&3uhטI#X+52+%Cdyc^P@LE!m89M| -@FsMD-%C#Bsz1,Y,)5Hʫ(vm'XMr @ "3'Pbј*2@`K`, YPR'[dK3D{?@!lE MXJOEU\a52ɢ D J Q j?DM&y*nv6P-;> uftB4B$Z̺2ALwOy^SEyYe&Ιӭ8Y( 5^ r{rTE _>Tp֤>@+QuJFۆ *(3b(nДD .aEW]|13ʰ\%,.T%4y(yLML  9 eV?aaY;%2t@ j^J "<%߁3UAGP 4N(qso ti;-d tixOB,UgL>ܕR0Q i|$EJؙh|P!|GhruyY,5."LWYE9`N͌,ZQԬtI Cnw%d8 0 dAռșhXD%Uv`QsU*bT n@t 3I!nB\Ddz 6XguSBA"n\%J *ꕚCT[ RiuH4YU`wAA QieF af5dT "Y BE ""aBE\0BE)ȊA|D >hBs Jє4CZ!-X(ćU LK$4 vC TrS!6APfn܏`!ܐ"b * T_RxUpc] &nop>22Hfѐ@r`A\d̀@2`F Pv|4D+])hQPd&a0|Qeeլ va" mdx?q5((gQ,]j57:CvdiUwԲjKml< * F4@L<.7+n`dE4b4DpĊūjVԙ 4% fၙt5h$q!+ȼF+7X{Dudu_|aN߾w}{Ͽw^|W_hTF}_V4A#~loia>jx;dѻ М{К7ۮ_62*^29+EWumϛz:ky䂊\4. gndR`KFu1\skWSrVkYk+o;]zwEnM jc5{f]n2}`o}K /!ѕ[ٷ-zn[1{x5s-c|&YU phZ\Izx۰δ>%L33W˽ٺ7ͧK/^6*eC M+-a{coY܌ls6a2:P>V۰W*Z{(X6IcYiٺʄ-}mau6t$; v(F6J>?.cC=øN{^g\}Ʈ2$f_VXήֹt>bh=g>f6˓mT: M2b흩KB5\|hU-]O q7D_\] n;:X6쇴l q. 7abQ}k^Mop m/^BDwۃ>4qh1L Iha7i6)ihtj :- M Nz;Lҝ E,R%0E1)d@ ='ab(]3c|w"cbB4@2kX>=9V!\CKAt(wo+k$w{Kkd7mMDCDnK]ʐD_D_np["gU4Ehߎ.9#tv)bGHo7 % -D>wI=w%x (xiD| tC&at;ɲyتpN-ݝι9wB;v UlIHْ(rr =] =ȡ{7 C]:NO7Kf7 : en8kh7.J`"Z."Gk"nHW #E5NjG/3_4u2;-W H@!Y†poGje_k`,ZFɐ F9NyHwyhvʢm7/چ_m*:b 9λF Б y;{b"9c[}/vDzoGY4{Z!+}Zjʱ2b+CQR>4rش=ȲW{c9h3l*cvvW˅Wh\fhmieTlBS!E,nq./bIFuy"CDn{O7VCb"Z*KwY/ypȺ#t\oe.bvз*Q8AFaHۥ~MC#}r#J޶K8B̫!QI²Vcyc]%cj}a=Bo2`u_9\y~ou\aG,tsWPHt~o ϥ?J.}"ήFApZ;2HϛkBj#H[mHob{C67٪o[^Շw+ŊߜXD8yBU޽|zWqJ<)~R:v :oڻ>}}s)MĤ|"{@D/E4W۔kjzn*\4jNtbC JC tJEGW3_:ш+\⋅bma e._~k ^._K/~{.R%̦ǸK].YO.Yu53v-ƾ˸}sq2tql1W{[p57&iS6!_P4]QaqD辱2u=cGa{Adk6Vӈ$7G0G"H,i]-w?w0릏wo͏DZM]ઌVRǖvԣ53n1WXIU I% IOkzk>vc?^PKɒds_Ը NmԜ4'( %V͓NR_I|#B/_6p}1azRIKJC`)vIn%#/)?X"O7RZaIis&P.Τ~sRƏ;j6INLSq/owrNP M{ _נ3WXᄁpanR)@1-ٶL{> stream x]MqbeF~ +t$ݼ0̮,9Vv~=dEwV/`ü =6kZ뭞8UNqN裶)x+U10Ep N(e5P.m*"kb iѬ}@࡫ d6{d@% ]&PE"{$U!u)b(mRQٵTgp>ZkG JSM$sRP<ʔد:٢#R) r^S*-BRq6K]Й(e鰲$R S1yY fҬ7욶]PQ *U2/(m*AU+)EVT*"JYo %U $ZrQifs:gEff'<]j&+N4RZjM#\xj0.lUn!B\MMTZ~վXj-g%(UqMMUUĮE]pf5Pԃص2h#W!جmO&y&53@QUQ? upvij=`LfP++i„0í)֨RCʠ`jAFjA"Bn7, oDd%m`$&sA:Se>:$ VK{Ŝa'N9vC ł{,UuDUmVpJ7s*$Y dfڛdWdR $t8g?b" *j{[|t !$螒  UR "b:F/:FJjo5raPCVTj$ dB]j#`bW[xk7/i'|I*A|I3%L:43_lW-͖dQh T\sb׮fuEWg7ae M]bM1%YfSa\̫ij96!7$2oزuaư"z/{%I]@M/hl)aLHܕp(D`m~iV mZ2X*AC~$*>&["$ iUI&$֋Kt< @Ӳ\GmcyP@iTv L 0HF eKc lɪ.< Bx"0EUAth %6%Of"d9؀G([Å)fgtjs;j P?8Ob1qCm)TlyqWYL(TVeՁ%Y@,bJcILk66 Ect$D ů[ uUMP՟kTCbS&x UhE5-Q"2VhgDzkŮLu=dCn+i!4w  coi!7];۽ڶf[gl]baYJv`pJjoݴDܕuwں*i"H`S>FЏ^.pC5nO>NUE.j]a# tQ4Bj ]ݪ3t錊!~UFv6U,feO ^=5 '7sqբSy6~γ[ 7#fS_"vS)7Dlva\%+H/PF(iD%_͕a_LTT6X"v/zk< z#]NuJWR&@}IG}MUc!ു؉ڛ,F6YVS9%AiFZTiQ gE5)"$1c#%;Ȧg8HyS&5R'kGPU*vu%mdWEI;Q_Z4Ŕ;J㤾D H*L8{z˽n@oU S]37h4@.$l23+iQC}kU;8Dn$Lɖ (HTGY "Kj*ݫD3iR0Mf1g4 DfSAZ [iMp+ oDZ%W8|P4[`ͨ, M|p #J6#f܊r3Oի?.'W~޽?|z^?~ygOo>O-O:$m_} I"=?}|>aXX9 6Q?Q? 7>L刺=M?<=a#8_a?uK$aOӳR~Au-6ZȸK !+2dEȀW_" Bd!9VZ=,4nCgH|zF;nugP,C]Y~g;ZxrD3a$ ŪݺU@鰾ra}_y:߽9ǧ6>+x<nMt7&:Dp3]y+DDDDDD^Î p sFv q>HvFv@ҩuḝu_3J|dڅuJHP Z$/4VVO^~p{^8Q:BGY( e,tJJJJJ+){{nxuݖyP{e*":N=HGt$F<[Fz }zREzj|<\eOמl_ihhTJ#rj1}݆B9;8EN$FcW9ѩu^}E.<ѩ0gt=Q./Fr <0O?~zO99a?]5H xѠ3tFh :Ag43HDB"$ JJ v[d%0J1(a݆}' B0_n" (O^[NEެƯ,ƙX'q0,Bh9aɊ;,1vp(C}^p!ɜW2Н<+F( h+XzY>+Yk1:siqG73!r#r1^%]rW0u_sq_r#UWq~ݧ/F.OBCCCCCCCCCCCCCCCȉL&’ps$VvS՞`10T ڦ //Vnqgx+g{F4_L&b!_) y5:n#0zE#Hhx8F1bdj^8EJF ;ZW32(Ռ#Xy#+G`_Mӈ"zZn>=چ[;ly.v֘֘֘0 L&eIl`R60) Lʆ+ϯ .6|W:2NgHɳa$;F~$Lw#y"+'/, #N䄈Ūa՛YW0ǚwqqqJOT鉘#sā9q`80Gڕۗ!7m)gHy8ĥxe!P\W2u^*Wr_KEC<FDD/UUAv8/؁d->>yy˾j6v8 a+d%4:FGg`30 L?ӟg`e>~f-+$3nf6+=vώ|8=;V?s?8mnh807mͶȍf_(l670z a4e?ro/cě+8]Zm]6r#9+N 'k>'Gno:l[)xs- Vޮ~8vel5fBݬ31%\c jmg$2Q%^aCnlfۑ>Nx/s[d\c}|bj:ޠ>:mO5o謬=|Wdv+k3L 9lB3ܐ Sl1]sZ\+i6xCf?봽T>.kpnO>tw.9!6VM ֪/oH9L97f=M*8B<CU~5|McX=b䣜1d~xrkL^j份Ҽ.nV[Zm;_E?<}$eÝ=ϲŧԈ̴DfZ"3-\[ečf_Jx;'"SIX2lx˭a+.g[Èd:πJOP Q;m7NYyW(Fx\8t>޲p?Wݧ|ÚV|"ruXa;6v_G@i|i|갎Ln;ڿ8ya> k9vf_jc($u$Gf#3ɑLrd&92I$Gf#3ɑLrƑOGn"S7Md&2uLDnbvӇvzn,wwyc i\]LrӁ'ʙ=ArܓH0Lf}#dH3݇})H1e>n'ǎƑ_p,ie 'tC]/iv=|1׺r=Xn%NC%_M,~ap^p48n }|( e"rXٓd‡/ @ _-<f8)bœ0+|HeAe<.s7m͂gHexֺ'Z[dv7s3Hq}r?OQ#Ob^ϬvXώbrs0.|P0/*, rv+2 onK#=n7O0) CRY0S<㻃/vuqrx<_ ^B{.^ٯ^_MWSt\}r6x;8 ^4~ |8Zp0+;VnF,DVFX6baZX |VJJV2g]y|)|6ƜGϞ0gOHKzzkYE ?!G"YX-9]Ӆ§ 9oa[k9o9z6)ŗSjqȕ9֏xk˩^83 C]~H3|y{;nŋ[xqk^xH):aA8[_8ΗWSavX5W0uiD^~#j OŠ'‡)La S0)La S0)La S0)La S0)La Sڵ~_62nk<{ޏ󞱌W „0+J,I!v.>rv 3a+ 69ra\xkǧv[b0/F3a5z#POxq"v/<竻Ʊ琊`}1d{Hq{qr "V~鰾~ص|9m`f}p<&3@"D&QHTML&&BDh W PӤqñq/>Br7!i}W1ͫxWq_ikpE@cUhCjW_;x:z/+f"g/oAx endstream endobj 2452 0 obj <> stream x]oqyS%@\jgDe[O p'ǣrl@]W5Z[=˜NTqv꣫뫻zf}Ln'S7NarEhcvSeD6+7TXueQʼnl*l;lHE"J ӥ؟KNe) Y s6X4NgP[j2gG\;6طyzqhB;S9UQ>Su`?%BCcgBYl$Tw#xPHFXIfUb `9N2ܼ?.A+DM*O1z9pR,7T:q(JrCcbb:<]lH \en.Kq@̳\-\ yv!$ظ#l|!d f|3ۉ24 A"FAg2 <)A):傇v st&h qT$~3 ↂДɽVaЙ=U]ˆ"]hXp.b!E0*sYAQTDz+ "Vé9J8ʿ3hyB1wIj%L3np*q _IAL W(!BʃcRNqU,JEpAbwA\E tH!,8~2@EAW ڐ$E`~wAn@H<n(å|7I#FT=~BLF(5̛( NV@Y*D\ICg$ŷ(JꑝJaD;6 (lZl0",DdB$-"B$Z _H&1DYQH=DR+Egqi sA=FQ%;I P(%94IRORfd./s%߲A"\$V+1 ]XG2 .RHb7rK;Q|U&J*NWxhG,A*[ӖE;%(Y,|y06UI(D^\ݍ  -7X'Bd!8ʜB*/;4I@0([ sJzG2qE%J.Qd[S5Vj=ʄTXG E U4#jpX(cQ=/820#? ^uV9t@BWNGr =*u'W"WX)kA4^02#bQM3(dgfEa& Ȍe{d##NPI$1Q $a{dBđ pRL˶E Y`#xOؤ@$0Xބ x-Z*6*dQ`X*326Ƞb^2(bC&c?!(T[ċ{X*3n ,7% ;f1hh s XHKXXpQ#C(1,xT "Ԁ9U*{\ gPW_Я( VYěT8I". +/WM2"PV#C|5,zL~S+$ 8TʴЁ@KJ;qE-BU*˳o:Ξ}{ogo߽yj o_O|ۯ~ ho^njb|v%6GNAyv; vjG;ٙ#]x2۵t2Xn,2r T o/!.g_LnF{Ջn777o7Wf/77[yyͿ3ol^3NwM| w˸y][F0W6N{BWwWKPHiJ+UÔ^]|7?)U>п .L%?(y+OSvOtR1.ͭ+Dz+孝HoaBW7{Z6|i~¾(YGQ{4FC}(*PʤI)Sm:8= ѳx<窪ڪj (SBgN\S5V*[IhKοl}5}y//2|s}.m7ӟrv_6G+˭iqq<,^@T )( ܈PۡGuFGhGkx i<˴ʰn@ mo߿Ǽd88Rk3pkK5[7& h7/Z1:o.Cn۫OOsܳ38;k#cQaY(h~ :Ag?rrT2vtfά41^fZ^i>i>\vvvRii|w~/kbwg*h\f҉&nm ?TgUb90/={~v籸>|48Ӈ-Xb O׳YBr }}}}5Yڹˁ4'wzyqV@&L\K{<\C q.xWl[O>?W˰߬Rj:E;lg,/&{y7gO/7Ogra5+t22"^{uW77?n~v7[UZ;͕?"'2u fY`V /S2\)3,L^E<=h:)C/' (?@qY)?8--2>ؑ>*`'A>8hRϢ]׬'沞zb.Gqz,끲K1'jz&뉚'jz&뉚0 k/9k/9k/9k/9k/9k/9k/9k/9k/9VY]a;;}Ba07yq~{ea'[-ʝQ*(wG3vix?~iq.P=8F o٢|(UHlD/Z*|(}:}:Gev͛ۅkAqgM8u,VX17ެR64 [gƹ;0،Szk.BiB>*e+I4ok8失UJs|pWug:ugsz.+K2iՃYzd=GփYzd=GփYz}{) DYxKe=v˿M3N%h:|}y䛯 (їW77(5};Q:U;wTEPlEѳvM:jlwOKcXd7+ N'qMkxoUX>(sЎ O2"O ]L"z:D^|gpW `JO 44 g9bFW8R>)=oPBdwmLsB myx.ϴ;wk!FlRJylԱfݓ‡Ck=&bvEOmZ61~1;>_S~K<^_À)׭/Ux UOyb{w{wM2]+ BO.Zj"mw^{eEih44exZ: -f~N6RK՘}$II%4Z5&}|i[; : sihn`xs:ht,QM@(ĖX/;{輥B3wVfŅ:hV\Q7InJ.;ҝM5X{Q2[F]fyxIӝgp`to0MzRnۭ`9kt/)RjVr}YMZ\ [!}YѼTKFm] V8G<.5cuOНoGUx ([/ZXݍApQQbxH\RfU-E ͝OPɭAwt_؟o}"tpOf,*;bSȖ%J|!g"D`UOn#WҖSbVly;hweo%p98L=0a#Jzj+:q+^S[VR'Af9vi=^Nj[&p=Oz΍XCG:mzgءuhpCLEӍ^wB܈h ׈n5,C3\&.`VA=|9Ex y^l=_m2]kj껉j-5lz=c~hJ` endstream endobj 2961 0 obj <> stream x]ͮm; _* x3.18 :IUE*J:N[k?oB[zn*+cDjO}mmB}k([/z>pm^mms@jJ;~"~AB-шH 5pmk*n2dNZUn.&(Lq2zMMP&&tK䮅_sי.QT\(D:%kƬD$P2[55R2.Jd掕Ez 6 զUYژ*+ucᅒXG)0&o ]u;F!yx$צGr3&gJF%^BM6ZX-U kUZgS^Vզ`41q`1B5uvh*SWK&LZ#·1r!kM((XWF !RjZ LdA_BMYͮ]0.778Ps똌PKkx0&ikt*Cu.ۅznzS IuPr"V(1%JPOS=B2h_j!YI&!9J4X-$@1ZHO i %]"v[ObzL.J9C.b/q> vE}ClZRv'8Ym/2Au_$tgk&1=5>DK);`"1='B5`t&FmaɄH,e^ @bxl)JPJjJYBJGL)1~̴ Y=T ၅e()0+17!a/&@^ؖz j? ]ajAPGZ:2]IH[jEFP)B+HQud*B%+2 %EH 7#@ \jMעERY!W%!mEnN6m1eQ%dE Rڐ㊪#RM EXц k:F~y@QIK-!ɊPGH|QQK-udp 45*ٔ46Ԓ, AW#$}WcPP-K5_@BƮ h/PgTVlT* AA@bO"Ab4S7:SHdV!d=*mD;Aw2cB{$=IylH,aUppFPWRt J(Tm2pR"ҫ<0yA<ݑAA\JB%HzlPVBbӆJF rU(tU*rU5w u i߸BX&z7a˂%Dbl4%+z!Ep"GăTc#YAHc!}, 8aobt]!v%[8E3omfު(ͼFRuk'2?=N-_?O y]cckO?a"7v# _߆>8~Aώ>)1ǡFYǖE4Em6c[o[fHX> vah0ÌoGB^ԎeHz1y1ؼP-sy4ϙ%2Z0<<1kh/j''f-y1y1zXjFJ[XczΙ*؋'FX,zyyyy.a'_se/2Yvqe aGSC{ΣVۮ aﱝWvWp4^/1GwS;pzB(8dsݤTsy)|wϭVjsmn4שmx[ms2"Sl1g]=㘠n-h̰<- ﱕ=6ϧ[{:~P bm>j$֓=pCx.VA#p, t![R/`6/`r]m-9·ct,GWC#/9yI <H<u5.Gاa"v)NgFdB{l63Y _]0o-At5dnҝ=i>} 2    6/p63/j蛹S7Vv+3wuᛕ+2[2n)T/'k 4<^%l^ZhˏY~ֈrE[wdЈ$#T/6/s]d#qh΂ @mO?l|l (dyDKp\Sb $2&3-x E列ang\jml]U"S3?'4/}Z:+, m#Vw/Y~ފg[}+{k%/@sr\vO z=v%Q^~QBW$2fg9UQbg[[ҫKCи#brx"TFl!F698 ͱP4 <$:ñ\hcwnq(v_(J;SGqcr|9K ض *%MO} p8r6q=˅F8Ɨ&-caKf|NVjjl5>p,X41@ټ fFBcR-±z9iӂǬ6}Q8eE^WrfzgY9ti~ҼtJ6xl=O =U쉑guG:@c$*y qyPٯJ;cs\7i'Ǯےȋ價؜ jp*sH1N,tA;/=><%@h:K W'l^B˧h.jgeDyuϭ >,0d^Axy5fT˺6/IZE4"&]N̒ôю#n#tz叾3smyS:YF0˧K%k7CPAq#b:Рڢ덈I7 Nֈ kDPԈ1BYOFōD7"fcpkD5"(jDP܈NJYOFōԽШAs295"(jDP܈NKYOFōX.4±덈Ud7"'@Q#Fp,FĪw nFE)) PԈ<˅F8v-c[#Fĥ#xG)WVWD펬2%m%3G|r=O |Մ=θsѶ>&w3x9MvI.3[AxNqO8%Ҏ~1z>Hh Y[ꑿe%wNz! mˑYA Y?zԸEolYFzW˫.wjObpsl;N·'-h2FcFZ;.ًW5fQJ9ۼ~}? |c[f4ǖ9[|OB#ˏ[7Ƕ{ZQ\G^"g6`rI9@+J!>{Zzg#eByp,?o? nY=>qe'Kʳ=*#@#:f֑ ŌCޯ~9_7Ǻc"W?xc~jyhm۪<&Wf;ȹ?SwC=9:^ָSzAhP}p_w nErX>rY*rr(S SlIP/J63K&]Ϗ Fv9+99)KyI3h6%lC@qlN~~lg 1[Tؓl-!]N^X.> s5~4 FPսIؼIؼIؼ-cSs3\JD7W~{f{ˑ:o\+~u~~C㫼䋎l ~ |&a?}ڶ/wT;W_Y/m//3|բ_7ݓ1%yC7ۺZ<[ϟ9>+N7#]V/ԎW\#N>}|&[{Es655 a l'<"_N9nr8-)%} ֑'r-B=awu3w Œ/ذ2~_H.пe ^'l^_ljܟYڎ/>~tw?tq.6*jK&]0ícֱoj0^?\5~aXؼu}z o-2ň  vf=aNa9hpAW3Y ^l`zbfbgyI&p BH ~xZ,jV=t)LPlq:ؔ9EG@>ECB;jzeHwjv_)(x0CI])T 9EGAs:E;!v]9?K݊p;$ye?_:}q#lO=k;r;L;|c N 4ϸcUޑ*u"K 0]ϸcjۉt}i"äj\7Xqقo sx}7mFy>`o/VTÖj՚>`Z.RGKɻ ^fԗ7kZލ9 ܚ*]/.|U#nkG@B} endstream endobj 3467 0 obj <> stream x]ͮm;  /p`/ ۻ d$F,nI,Uԭm:6Rpa[!\eUo[zn++cE ϹQ x#^ 6;ͅ+\6zmk+u+5#(tP,ꃒku6 (Jߡxle*Qw(sS-[ %5)5WwX[[QH1qM֚RM($cCԭ32ia(V~C֡R'EʪAi,JF^ X(\}*%XڡUM5A)tcBU' ?LcjrQJgXm@R `uv@ 6d{a֫Z_jІ8ZMлjЪPj5~I&" Hj.#χA+qDRu]5%Ъ/r@#sVVmpV$>BU*ga!#<22@04(XitA s f/dV`!qDpN($)`$Ci 0PCjмCZL"Xـۥ$RJaqCUu$;Rgё{S 8" =dJ.[D4ŀ"$QTX"RK  *tLDJH%A.WDԡ#P8:JBpU @U}(F<#Vrjz BIIV4sHX袙ZȊD )^ #$Mu: dy1hzUW K@nA>Hћ: *&,OB(:(Tu]JPQH*c\$w!sGE :@ FTRt;SNH@9*U Ы"x PUApO`/B>@VRR zׂ\Q[HA0 [jv$ @J*3nȭb*MY,@ kU,SQi2!Q:H] \"BK"#zN΄ *sQiHY薬\7@$4a>5'DC\ !w%E0.m*!WPBBZQ̊r(œq/b XrAai~Ek $ i*VMz8-"vi0 t\B igC'k,YkփMkIjJJkBsܤ.PIb.l4IL dlg$n'4I$ۈ].cAAZ)GCc!Eoi $@+V_ d=K }(kA-$C%$! q UGI,2nt(¾[$G*I*@NPqCPRDHlX;44]1s!kE2oXKiFuX+?ațB.UD| U*%eTuwu%qCCmh H@wRWcRuHӊ;Dĸ `Rgu;f*IMIp(XDͺn{Ϫ3P@jfq*[*%ᆡ3,ѡ:AU_\E| E:Y(XBZv:c"4TU*TG,+ծNl@ WR@j@6MI7 ^CCĚh&;Dt?]{ Q1BnX|,+{bSc R,4uYLR4R#t $w /vmB"Z0oNח<(/=z@$8,h ]&$?GTM8&\]8UX@5 VPT(Z,` ?jZb.$ L7 PZDXE0=/:7@OR(B/-ds" ,D36L(Au=B) X4_'6jj|V]8ehTDB/$Ḋ: $F XXYK4au a}Wu^,|M [؛J]|( k]AzF0]mnJާ8 %;?ԙ ը]m0(o ;tA|*N`_o_~ǯE_MA/ﮱgl36ʓx'7 `#֓y:Z&}vpF Ԙck戄R(t}gl^x$l^xp8rCBpqyo|fAmq]1a킌%8njׯ)9fdG\^񺼆TETdدΗkVzogl }s՛ՏarߡWw"-aPs>=YH,ƮAu&M@(]5|qX⪁`IJ&s }HR$rpvO z4o5BgNVn<8*P¼ 4(^ܹͱK1O~=rpp^ܹs2X5t6rJX<4ϽFVC#rܩ1x5Ǯ-5H#.)HO9[ q<KIͱaKf)xJ2ZcX.4±v9i1x3Ƕ} ԈͩLO<9[qlz8 pN >-cwÖ%:*9[qlz8 p_N1x7-O EYY`K݀l7nnvs{7#lje?:]²wX|j\},Cj3rmm~-HP߹qak> ǕPT#a.-B{$4+srvtզcjWǖPx {$rX~]֙ ojنǖP3rB He.96gFle5G!rͬp; ^[7fnCgcj(CB#p{18ca G9sf=lYZǪct:cEI3nTPKOWlqz8 śI[7ǶAҤEМ zgE 41J[[apY iR"hNFi=(n4. pͱE@%HSQvZO%rE 41J[/hZTy#>jmu`Ӈ6H4;_1Bˋ۹F/^k U[91\qv:m}MTA&W} M@'e' .{Z*v~qyp@\U@s@#{:9m2IU{Dä2|$InF|2ԈDL/B-)]F9'+)] R5 h4Ujt98'1AwA9J=rVjƹШR!-cfqlgz4 q=K<$J؜͋͋ބ+u5_XpK>+ ; vBGKEB'<!JJsW,J#W:U2;}&=4W,}fǧJ\ojgmFNlZ_wǕ/Moq~|V?"}M:mzrvc5=5=5C[Ҝ_߸=r>cs5~~i< ~'Z||K(P#~4ċ4f m&T/6/6/)>SY#X+P҉0_SnqExů)T/6/6/62ٛvZ7|~i8uFf1[һْ}l,mzzJel]Q;p0}a2z=EmQ:Zh^'l^'l^֌ٺJeu19#ӷ.^[ra쭋i9"I+cKR`|߽OؼOؼO0qyS΂}~RTQ/XoL`)nt/6/cz>E -:,?ǂ[n:ֱQaX1߮G":pcObΠ'hf-Vl8`gk߬V7asɎ#li ENp:V[ fssx%LN{{2b|&q?'Sσ>Vc>rB.~vꥲ݋Vim_`G_vt<3θ2V>c;[LH 8.kazl+-L.ʼnCuzgKZs|v-9U7B4\} tƟ9Nyǯ'EGVr{Q ww n-; 滓fa"gkᶯ;P?ռq nmM{6ٜ”[rR-rz8 pg툂lnJ<'E f͏ͬOP7A7Of ۹4 mʽ^app{rvv#BCH?yDwˏШʿd`npd:eGxA^~Ɂ(< /JS^rpҸep/{ʎ0n%Cݳfz;ϸңsyGt d0g\mM_oo8^dGk'i$򸒦 "wyM:#i^2s+"[Cgq+8(}rPZr:g.E1ų3h -yB9r@ ] 7ǶCq:Ո7Z%{8Ur] EJ-XI:a{ҞW' endstream endobj 3969 0 obj <> stream xĝݮ$qw77`]ِ!Y0${aHKxXoSɬޜGA2vIm _rTAdM%`\J)R+rirUːMxI"[:$džu2C/6oy$Ce8d;>)yZ(i۬ZkÞ۬mGVߨÑ^tq2T Y1CRf 2!{+CbØ91eP_ƶ$oÊiW5/Z[Q'v{_~5C(?Mſ|~6))Kjڀ%^Mv= R+!):M|k_A^%]{`{e'%]w=H!YiZ7e>_{`՗#59WhepBckcl:wRfKɱH> JKPX)޵80*646_܉^W8{6?+9+0U)=ڥf\Ӥ]&:kfLK2eMM1qmskcpAu2ks6{ *m2G܈q󍌓[J^oKa2mؿLj2NneҳIVZkMw\ޮ I/Fmd6fݯdf|ٽd!F ]Dɐ!52e2^|LVk{-toFTP`l`=+r$F &g}2.rElG/#Hz1c }-_Ym26SqIYZ}@/e}_`v*AgX1f!M[ԳJm|gǠSd6pk^ 1g8ޚ/"yVfváMfhpNM| Q;+s4U)۠K-`T6ׯ6zk{l-rV7<ʬW8_QpΉq͸K=y421BW\I(bMڰ 5-.xms8Ӽ:gӗ}-7&I}l0\J 6ghѭƀ6-|UgR|Oy&X[q8DP6gsn ¹/s|;k\ .3l}+F6*E:ɘɠ2ςa{! AX=S4_ 6@2ٷ m4YaY]n Zt0k$]ۏ8Wo#ry .|Td6cF.nU'zOmi v'#UoWj /q,&&ߑV+`y]؊UC%<_Ku貤V_本 :|QS%u52s}C_t4m_ A"+ 뒵֒u|Mge>]qM!.Kڤ_u5/–1. l!\T1JS.ݫϐ]uĤwHOs\jMx yΛ^kuKmyBhШ˨\(K # TI.@uc`́.[p"o}}_+.*F֗f!]uI\.@FW]MP,_Et>.lƘ3|?v5`"`vxdjC ㎜a!oCL~j1$?/RAvr[oxn}7XsaŬ;#o4w|jCZh^N̥9;O+27. Ρ1?Zs2Ao0O mV=-<:vs(J`EĊ4VvvJVF&\dڲ!{LsaIvq8' {kl rQVoRAg2 [ƅqww6Qp~dd έo ](S6ɨx>gxs+ag50N:zُ:w.un `$UuÆ(>Evuɐs}g5 cۛ09m d_˶:_{R\~1ùv=6_AIam'I2w&&6Nschb֐*|`ΟoΨvtGm*#d3x}V_xWn׍lYjrיW]Gm1_5]_;FPьz]N+k/"$a^W/=< ȈX8*OFclFǒZ1y#5M5 CfnbMiϕL0O^)9)u)}P_'bRw*ziGɒȦub']5n{vx9:^x[u\m]fdǫFBe Ȫ%H~Ѵg:[][w_+g"6Fxѱja֔Ԁ_׷kbG\WĦy)-F)* B׷LKKbӃUk{[}Eli)H6Vrl/}>%Vw_[Z1=c獮X:=jޞa'dKZ-yMlgW^[^1=c獮XzxL3!lɋE|~j_g;tK藶H:+v|q#^st%SYfyڽbnX]gj3Ov;=74X ﲒeI3fJ=+KG+Ii_+Vv'<3aPZqrG W\q&buW>b̄UVʊ]$*{q-kZҚR^#? 0c%+vrGm4V^DKW~\uGӮw[_ aުOl}%R#g¢[_N=ZRvMnѣϮXivqG+yë#;oxOg q cu8'ؽؽ? t֖Gq#wk3ѾQ/}xih̀{ɶ ˡlk^44@ UW( }ʽRKNg1}1z߻=OnsVi%;PB "ڊ GrЗ kY[VWH-H 6a !X!V=y@ƋA+*˽ͫF\D̀g~(?"2\Ots(@\4GR&6c^ݻޟlRVV/{ţV#j{UX+Few.ͣfN,RWh]VFjt̀c Ż/Ԏ_#qy5>̜i<5W +w--ډ{tRH$YHj0FcVĺV#Δ }E%؀|$Nmnʐ%i@&=5aB:ik@>.LHGur$ ʐ%=,<3a(.3:|+f#{]L䷿+r>0.{yrD{99uh߻^{+b[z05]WTd^ymݘrBӺ2 ےCR'&!"+}?jǥ+tm.3eq/gKom;ݧ 9:%oƫ+u}SJ=}縒HC&[ Pm\$\fG"5'׊_ Ewi[t~x3:QhZ ]1Vξ+vb֔W.LFWTN 8jxѳXGb&4mףؑ48+[EtcOXyjOtWaWv b_╥Y؉.H;ZץùVy+v>qaMGv:=:TZVTW)+vKxأ9:$\yxn= a8K^fE7&4s&5JյhI9oti+KX U"$a9Z^GhiZ:b{Ogugu63 |[ڹzzW@UxI*GӮֶ" \O Di[kãSJ.h7sRtrWh/iTUOX}fpWWDŽuBrplWTҗDŽre9ot e<3\[]fE7h=ZNǍ#tj=x}J$a Q t$X[=IL-0Vvp$]n- ױե-.=m bK8z ΊH괕UgDRĐOiLS\J!_(),+u9;^M$Kg z̔Vkt6):-D[:][[B?QĴ/yM*pH3';WrD^+_+vz\'l<5a֙X V *"lUΊ?}eʒN5'=3a2OB§#1SN `9+v$ ʐb֞0b)֌e 8r!vb_: 7}rd.˱IUJ<?-o:h5k{15Ư8+`q5޿xY}jr \˯{w h zA5 ԠbZW m1n-ƭm<mŸbZk lA->|+`ϕ@7oEHXdm5jըQsN͝;:m 5hkPj쥢P9g@ H (x4V[ :}4Q(ŤLJbR 4S$y{e+4ċoxa`} 4@Dǐ `053ΕqJ &*LTȤT&1c ]e*,;Ԝ9SsL͙353Qj- ITHB@J͕+V*TXR!l WؼP WꗽyؼSC[y i,cA Y : !7ȸAƈpT ]$+5 HA 5) NipJS48) NipJS48) NipJS`4 i0ɾ5 R348) NipJS48) NipJS48)SaBZ:*T5h Fk0Z`_tmzڿ&:JPB:С%t(C JPB:!tC@:sڙ r) P;i[VTI# FN <㬄)vJFҼ6 /e lA@?jMИr*W6Tʆo y&@|$jx8r6 POL=RRA m1, +4jn>&@<̉@TșX9*XKrT62 b D휲R6F0 @+k*k*˄L(˄ (RBHԞHMH6d0bG9R0TdP*do=P Ȁ'l)lS!ؿ) X\8@tp!.7MibI;u'$֝|( R=2uư3H4݂~ wW_Aw^Q\ Q`;qõr 'y߅o螷'4ֈwB/d 3IKF[S y9rTƄ:m7}%Aa:# Xѣ~O\L ׏ΟC㵦ǿ]:f?=OW~wb/oo?x/mOo>}?ۿ:5?|UmO7?ߛo7_OǛgc??}w_nC\Uq^T;ya^T;gb^T\8\ [vaK/enζJlQ\:t"-az`;.Ch] \n컈 7Z.qonmpХݾo);E #h< R6G28R!$eE0m0ݬpDx|ExbFzRxSa[7|{'.׋'כ'n׫'׻'ˊ'mۊ'uIzqzxtx|x⸼xzx⸾x~Owǜz.$"2>18I I̴~frKS>v+W$ۭ] QEOc(GLLȧR!1|xXx -ދwk[3KyZy :5㝩wrXbƎ3xl1}}F`* 7U0U#:#OF`}~ntn,g44`D   `!@}0 B#6LX0A % :*M 0l;X`01=czLBAc2z z`)ʅ*QDO~Aԃ{Hރ{0; ,6k`I)/aqv#c/ڃ{X1z]o~Ճz=t׃z]Aw=k}`vl*#}ݍ;L-#nayA_C߇oݍt7FaAw#nݍt7F,"#؉F6Ft5F,*#VzAo#mtj]ghGQ6t5Fȳl<Ao#mt5F:ZɨjԢ πSw@+ˆ)օe3l6vd\+g-ecG# fؑ](u=²m6ml6%ق"[Pd  W ic µaŖ)ܷ) ݔKeFaE.(źX]5UO6` RDY*X c*B->W&`,%D0(.$ދ@c2&d,1x!dLi!d,1ik4"@cI+2Ƙ$D c ZE!c2 c(dI2&s )A+XDwӁABd.2) 9D!c Y,|B$RBpBX믠@M0 6&alCV9ےd1'aHX\,wB,3Ü5Q={< &X%* VIms?9 ~HCDGޕ}3\}|~q8t;0mA0 X"y7AwDm9b:QUk]-^]Р .]P Zs!(EЗ a)<YNA-ݳd#hĝYP) dA,AΤ|^^w|y/ a)X> )(,&IA4n!aA3,x+M_`1r@-.ſ<@D(W^=v_s 1g@zcPLC-@}0>-?uh p37g@A;_9x yk} /+@J}?_Lޘ  v K`<n"^r gQs {- @AzK3E~!/L[{6(Ǡ~m侅^>U{ g@y ԯڗe`|ނ^~m6_ w%o 1@@20ȿŵ [kU|g#\SzK1-{Pg@? a>1_w>q*{^Ԉ$*x n(z7r.Ι RTp!|H'R6mlRTp/z%q8 ޤ鏟"iy2&rTUpBOSTp<5@=ȝT+UpKRT3UpM|ST;UpO5@{)\WUyUZVUaUX5@={`** '* ά7jWWUpv]7WUpt<]WWTqmʀ9p)Y,t^O8CJă?)!DH(yh޳Ad%R)p %B PG*I %MHIPd(Rb/EJ셒HD P0EJ"%,CIV$ R54cJ aP3dN á$$S2 )J0DH"R;%BH P) #J-%D,y(v |J䇒yG P)%աDu(QJ!%硤R>%~H QB@%D QB@AJ %(D(郔AJj/ |AR!T;N 'Q2 =&J~HĞhO&{B%,E KQRh%EFQP[ P@XH(ic%bEA DQR))JRD(JPԡu(AJPg(J DA(QJ(J~(JD6(^+⼯$R||k^qiWsũ\q!W\onşZqV<dŕXV|_`XA"x+J"!{ixa_XV|?_řWqUqO[gVU_WU48*M<G∪m ] MyP=@0Άk)p8g)nM#sS)R|{!aWꁖjP3 CqP(qA۞}bүXbkWLJ$N$!U LE`B * 1+q4ӸbI+6r"CbW !\1+#s+q"XbVފ[`V܊m.$=@#jIv+ɕ۶bVlۊm[d+lŀsb־+bVlJ2%8SbVLъ)Z1E+gެ؛{).+Fe%b]VˊuY.+eŖu!+*IXc]@ȷ{NAvXu7 DXRlĊXIc`VLÊiX1 +aY*F^ȫy#bU #o¤&, Knnτ6I.R=U)aMXqV܄7aMXqV܄7aMjڄ6;aMfӶ_8y Tᅇ M= l [k֚&, j 0&̧H i|z|IvSE{?:*$E:҄4aMXCЄ3Yձ}&2!%, Kgk&bH3V̄3aL*ʄa2aL#D1(akL{wL b²xjQ1ڏ57`GLvĄ0a,L שa60 >xJw $ ~HI/6^hQ-p2e7dw0Kp!#sP`=C{yQvC(wXX8dRϝSr]NFNxXXXȰ88ޟweeA/sIauf!|߆7H;'))))3G5E,'''''''別hأأأأt':gS|CYO+c;; =LwwwSӞ@`|0~01 ݇Ŀeo /?'{!sAcJ˞olk tcp<'{i W?nSp<'S%) V4~ Erާ 2Ukïuw}އ˿og AQw9Mds Och)tLc C{J) endstream endobj 4360 0 obj <> stream x}Sn0>lJ$H"qCKTeȁ%oK`xvvl$ݦ"U,5tIp׬~_4l ]M* CfŮ[l/Kеe'v q gUG[D&&*퉖VO8Gb7/WHs[QY,-hO (q8;Yy1'_u=*р߉z@Z⡡bKٌ#bw9I)<.[6{vZEVY( endstream endobj 4361 0 obj <> stream x |Tս%,$ !l Ј,4AEEZXb\R74}knuAԪm-*ϝi¤|own&3 DçAs6Iɗ~qᐖ̘wdkߪm 9 ]wDS䥉 4^46ӛFFw3Dm3lh˩_~gnǗS;#f_ugWk`k[pYמyߝ2ŋuj'Ͽ*<ש( /]qֺϡe/S䇤!{-խ:yق#/v;ܸm 4CҾtQ9 Ke+VI޾E _Ư }uoKI8]|F sp.7^Q߻\C>M6xd޺iddML}7󱴏|?Zځ9ԯiq<-].b)q[u@%CcVuT/[}<(?ƕ+)~.="x:w) AdF㥴8V۩R\D_{өtNVR$W@($? :ɢdisg=X: soo+OMdSq$;׻=P-?V2>d>U un @ @ @ >`@ {1v F~0r (OxbXo8= ã!Y}# 6Ċ5U}رVn2{*..ڱ6!#zdeFh2!`?*3.@/YJp !3^D@9X&&]0ì~ ,VXIma'uhꄃ'+x&C/F>/A(B4i.By_ \("PHc@'~"HC0IH;0MK b2$ (%Q(S5 (1Vj&x!J҉"ߐD5i Ƒb韰 1t!=sՏpq,8NKF4=K1Oe.BEMW`GI3IY8l,%=~_s<,'=M;Az!V"ACMWLu.YlU8R|_}]82G5+p>镸*\Hz5v? ~k51V%?*jm\KIo@ne7rқ5WUjHOq /ҟZ ?V;t-~B Muwz{p#齚އHfn!]O:tn%݈p?~Mwgs->+xwJӭt!5%}>ux)`{<&}ԗ$6>I&gKgC6> B[%##/CM?oIߩx/~Hg~xox:hP&xO M%~xW}IŚ~Ok3^?gMk|cMck{}ki~cMߡ;ZwhkmM߱ך7ښ][ӷ׆hMIbMέ}XŚkk:hŅ}5Yt(t0:Yw:`2Jz#)b4e0@3$I/yhC%scF( hN~.42dC@ "[b+YG&[yle#d6flj6Vށb+ce ZJz^[TsF [45Rl%f?͂CA,!dj@ q(8@؃)1ʤ#V:d21Y(l1SXvt [wV:xX&@leTVA\":pHP A;G™gPEHìkT/:]e*j1[-bZlPbvRLH5xley=Z=%#&" dj@ q(8@ Xb+sq>7<.;M 9t:Ni08 |arڽp(ǣȟ?=fa?0K#?2Aj@ q(8@VgSle(1X,p,Z<Ջv]z}>3:.jy^V.PE}].a qeBT:eπ͖ b̾LKp23?2A[=.@/" dfCjl5=}^ yB~S|,31Pv[e y(t*U3gfS4j5,[ e?WdP2{H(7*onA|^_ 3gX|QN@)?~u>l?BV~ϕ79@ #@ e@$ UN?696-元BTX)/#8p<1cK c1dLyȑ>@"wOq_ptAa!ۤdO`@g5M p,D~qe޵`pbn\=.@/2rKJW82//+++Ee5҆5_9j|eS՘ ?(Eii4-L qxlU4>#:i)a~^g4d!C@ "IpӀ`0&x" F>1cT`„ USk*kN@턱8* *PQQZQU5+JjJJJx3A6#":i"w#Uo_*MZ7ᨩ򺪦Gajĩu ( #*TUWUVVegg7Ӱhyj䔑#GR63`?Ź h*Ah9qa_P AR r{TtCP(@ 0 3p ߐTJ@U y~qQ¼7nQ/W0խ_߲?پA $ o::=2[68.Ǜpn^D棠0^tذDe#+0zLeq'LZ7L2#v3g55={-sM8#nYKc7gG+h&nIN8aUGU,QZ281찢xaA,?Drá` ǟz.nZ&A% mJ*ޖcSr*hK)T5y>)M3I=?=ɾ̥JCLI=[Sz؜->֪>ӴZNh( 9kSRXVO[oYJcJY+R?iP^NNT V=HɅ S3f4ԇ֒)V 6?XmYuA6MP2j('eۺ.qa~[malaܖpӼ)9)=u-rNTx%u̖[\[[i4V*5NbcBI+[[Rl%M#G>E^ӶDIc]K v0hw0ܬnGAjnESB,t:{C m)Ngof;MiyqVߙeܣtA ycⲨ ] hTj!="'um]j^ǧ􅮘 }}k{k :Ԩ}w>U\J$%bǔ|G ?GŖJatQ_֓|*:g 懺Qܚx˶-yKm17j)te{WX͋MƙsZsؼO)^֛KyZԛBJܾμbK Ǡ] {&*LNڦf8GҒ=zLU[Oyl]29Ks,ѥބx4DBQUqk txU}:z:KOkrLޣvΏ)Xfa m/ue[\-fK!v}>V5igU-j[P[fwV⵼^@#LZ$Щ A3cX#\$ӥZ1u-{_=گdk a9a;$.΍lqd;kJdBlV?ΓEzY':d/)oUȖ![\9ܭD\5Er;T2d]E̠5. J֒T˴dÒ˵b{8X{ttZx[uQtZ4IiOIuEPcv.JGP^ODqK[EHGM"N6*2U^NS&Pn|?&$D:. #YK%~5?Bq|.yL9_E*Ĕt&3,IgL3/tܷ :c7$%"[X烬s뼝u.b Yxy,fa֙:VE%7SaO{Yg댳BY:V쑢݇WhIltNHS55a+dVJR'%?9 Iriu#4zd:z#'$ydvdO_t$yd$3h$uc#zK#\WU*_f<6=O͓*q=̾s?>\cB.=WWuauOERZ<aOG!,Miywx6 svLJG0)EGXwTsKK#O1Q̓FE9\)pCw|l9)5,J7A32+>'2WIv>7E&Ol l&i;<-N76ˍÍQcĘk L0Ld0L u{GYO ::-`/z$rTSq{SYnEe)O#kSUō=FuV1eqLzƮlڔ[zʫVx\W^a+hmENr&y&Ni=MnljIݕۚ*51_

i>Ikfy"[,^/Oomma~PاԏO~&zbnH+ԯ'lF֯l﷾~}AǯCWT!),dw)SٝOj%.ya "u e.#z\Rm&NoǾgʢba\낹]YJռR:l޴tJl`<r*Y7BR顣u21zŊ4=t>%}UwV߂YP'8vyDCSO_؉[0F@`#-P=n¹hS,nFOlY=-f9G+iJؑ2\TO\8`9T[+k;3lPA,YW7PB#~6|?4K'XSOP$8|aeۤb"|rعrjJ}zq,la)NSE6qztcm=x30lsl wM34 ce~_K6}>?G} Y;i] ?AGl7x6͖Iˤ[`GҶ']F$SݺrwmWq#nƯTaeT'͓nv~8,3b31l1;]~Įgϲ؇R,$˧jiku._ᮖ]rb̤BǸl3kLϬA¢h}gWZ fy`Sg=J)D7?(&FwJ7I /hy*/#.~]PN\___[z櫟~]صj]ݻ6G!={P5om =ޫ[]%Dv$yl ;Eg3؃t^a;g|.FKtڎI5FeK([eXyB>[^-g7hSu]DuSttn}@?W}Űp)L404kʸGp?~߈vBAWJ0< i]ZJ:m gIQDsF4NYH#{3dd|{9Y;_iҜtx]~u: 󳏥;t'gKJ=r)i^{ހU@X;` !%ՙa,N龎${ȓD&+I;0[T6{05s-a5Hi 0< BV*39%rĽ"v5xh䶗dL4meDjc/5%`1%4tjT&.#xSK )b7uݱ(C|GGөF&:ä:̷EbB͔jj_jKV?o^}۱v3遲 .xKIY}.IT8d$ɎÚ #Bil]}B1ŨjhtL5v̮d:Օ" )TW jyӿ&^P5~ܿJh#G2_fK짿sI:@".T4Q+b;; _VxHO4QM-I4bFtC1CNb] / 0U!g#zE/VY,[]Dʈ#DsBeA/tYOYrnrN]H$ ,l";ppl~Qs͋D]6Sm챖kBIX:aveNQZP.%o3/ƒ~@ts[:V q\(o>nke֍C=8n˛i qf^7U}f-n\k3c3fq%t ǭiTP`3H3",52Z?J4tҬgM|E?n؞-sZYM}1P[/wSbz4hu yԥѶG]` 1A~7u<)iY5uuղ~OW=n)Z%{q:a׉VLq&vFodnRѰc+yTj>jl Tݼt_l1nW1s\14~zKUS@07Y"@Vzqu+ǿsÙo2*r6xv@Av1AcP$EnEcƸsӍGS)#"G*[fgLs'o7en<.A'#le':M pBAn4`hQ KL]|WUdn{qAKۛN4L{mc3g,5Fxe)aai

BK=; ^ fwl*>'R4sQ(EB9>1*_WB^.^0v*O^C ^ۅmI4& hIߜ#d@xB NPK-YVT?Uo={A?zc"2,(`(a VnT-ܮ֠Y3c3+m4IQԠ >h D m bJ_ Xv,I%HX ښb/5l{+4C]%CoC!y[yM}Ph2.s4v,YHxٱ"fYdFM?p8,Q0.Q=2ҢV mr e7T=o:*G3}N(/+1 ۰5Fv. "/qKK"s{ٕ<+PX3 "i2cN۲׮ƿzo̜v5/}. _a?mKc^➽B2k ;)s.R9/%2/,RQ9RKUQ*/%^ʼxu ˍk fuCX(x! ; Bt, N nF7:ExmlI=8,Ü^mv*vIi0>PYfh 0Řtlm6_8f2m@0} "z,A3L7_pvT %}(M423ϰQ7J طcGU3ݖ`Qk)ښH'>)l?yѓvD@~"QzztzxIk@b١B(OhešE/!>3Qh' m'_ApbD W8bsAA( SN[V>QDռ!WUIU]P@ӫ=^.Nۋ]!rm?uj[vϚhha6E%!3ByP yЁMׂ CR|&/iP|0_\헔@wAfv:x1]@C>ab/[ܺeոU7>1r{:'GE+#en2s췯ݻ "J#PÄ@pXmJ,/-5_)ϫQių /]\9ِ8ӊݴNNtH%QSRRfxxbF&T{ OXw4Q,+c=f W+W3K0 AVJk=¶Uo۲jmƓ9}a_ VSV$JC0a%~^˾yWу݉SȾ[RayW /okFٯp$/9x*7@L)$"tcc?z0Hahtv${((ك59n;Xmk q q q yQBn{^f9| ~_o'4Os!tIs=!x}aDg̺{yd}AؽW-y͝wMbk.]i;"=Xq{ {WB/f钉S/=ݸfS ?)Cˎ?ܸTJQPYK炋rϋYҬ,c3k=u_0sӒ;@N,&Ǹ~WؽQCp'WuV;).Q@iZcp%Gk4~Di8>Yܨ[|?5+J O/-*|wtC`sxOرwh0j#[, crwtk"RB|%=0*[y+ΛOq>SGŌ֙4qY Pe܎ԬzȲ-fIaGs6$L?1/ fkKÑx,.L̬-/mT-}Tyuus7㭛Ԝw?I?̟3d>ϴVvE:.gg{{~vh=]Nrc~GqЄ^Smtš|e%:qTJd%%JAd1]J0(04|ݜhE{n"w8DčmcPb$ *vpQ`2[EGA_G맛7l+)aĒMqRv1AH$$*F|( M5v`Ĕ?qɁ=-e&jLQhHKR`"DU6Әb\uE TE$fegF n(Szq$ǣdB}BpF/sB̢֌2QS_:awE:TU4'ڧOE),Q!2KFc;1 %d C2dن,<*J#PZY( 0P˱#|0\ǧ1̱z1Nxx%]+WlEήn|E+reg*257fٟS $ =Ƚn3lU[Ӓ.VJkRY:i\=n+2ӡ]4|G2'$?2[]M;Nx|/M//F4s[ZŴϥ[ۦEf甏 {"bds E Ң5ds|6(ry"S+sol5̢[=w{6] 7'&./3".o]M7b5HT̄"p `"R7LHK :ndOTr9,-\d6 biI/wPI 3σJl74:3z޾?г\C~'}z;1/||}̗+z{<ؗ+Y{̨f}. L|UH㊩|U?įp..2u}_>؆;RTU" _ע*mFL(ǜL;Ee3a4_1䊜Nژtю!CqG K][2 e[G@;ayGZ=>c1cakT2P2>9lc&㓟FXo隆s=N2:G|?TN'^z"qO(~P*.!5Je+oIВx&pQD$~GYJn!C>TclrZ^EVEVEVTP[/HL i4r000ۓzc=%~K#‚BA6f?QPDiYY'71J8-t!,(ZWg Wg~:G)/B7޹{Ys9;ߥsZ=P5ka%KGxtu¹|P-x5:%* F~8eȸ,yt >P |||N]7])ipIcQIYNqHS(n٢҃Os7է+9TRp`)}}diWSlwXKW#e"@K#)|OpqA3 +nh >as9 0s2h({R]={WdecQ4{ {u8͚FzASνl$/d!'AʮآXC9q%/yqarni+/ߺXyyvR.ւ?&s&mNel¹’56nnM˫W=Gjn皙p`F ȯ:J4/81/ym($ eٍSy5CS{EiPG$dOd kMb ʬ)软ůӍM Λsɂ7f|v l_vɼvT(W@V>NX&'(7F,DJ\)=#~JH{y5B n-F;x,ǽ-^Z,+jC4]SuIŘ$ ed]')JT]`J66vWItW:(E*^sT)41ًev97a>Uֳݤ@ ^'bʈ9]m2@wykcOqeaKS )mu{T!Jz(eM-]@4v !Bd7q@/[Twiq ƚے4B9\D՘9n;7|n؎vհw{1Lf+e^ y). ש̊K%x]v11%Q#{jܼ PP`0[n6x›%xQśeƯAƅƅnB,s\Bcr`ZudÅ[mtbu:u"{媒S JRݣMSUMwqLI6'Um? V6K࣪̾edf0A$`lD)QAYD X+VVbֵl#ښR[BVmQkQq*$ޛL~?sLNyϻ<^ e7ug]` K 6Vy:͵qt;, D =M0 (V@`)qC m!|z}REД*Y (mLκ7ve v55#`s(>r sWV'wG5 HPFYtP-@ܳspO2=dzhd?8&>lIR$@ϹF,jwsI-1 %Ldx&wDEZ`QbiZDh ؒ3Si<9gkb?(Vf(m C?Q!Potc2WP,"ۏHzy +{x@ahow͢=ҙl'Ȯ(tlST5 z㣻xZL+4H_mls:"PC~лS ~{-^soP:G!{J@3q5ـVc]:Gt¶nt9Z^9'vn=M2/HA zk$; E0O<>Pɂ (8%|KYVЁ Ta2@ xq#O$aC$Ge.p bjO=_,M*3%YM&U?|U%u!ڈF?YG* _Pz~-GP_/m{4ץ߁*}Gl/gEֲ=Ŝ8EGQy)VF, ȟ9c<{go;||<"+LhG?;?7#= Or,e~bybN¸Ahܥ=ftO e,˰ UL,$>R#E$)EaoEL%E$bdn;ɼ~ ޲B6h{1]2]F2 _%zxĒ=qG ;A0;T rJ[m0X1Dv:֣h5v~Ysn,U)4*Ldo/>f}G_}C3Siw=T+{"ԎFълobbؙ 9:53TE{(15/zś$ 6@aD0^\ȮbVliNLά_=+̯8F^Eq֛IޛT{*X~$Mޤx2Y:TF UcsKS5;wT[_XBRҸ\][ܤܨdjސ>wvqg0C3y_<8Ҧjc>v<mt<҆&s(Dž8drLP\t:r(Bz!_eɸ(,C(x.߆u5KVLF3PZ6!u>\\ɒGW)$\JjQ-1wNQ;E^662㐓`7fD󶡯?O;,N=p*윛/1{d8Jg$}IUs >Pt$]?E@ 7 Cl6mg~ڂ_sf?t%?znc[lޙq{楷Uc]\>ТgWouM_VsεkZ)Yñ y(KDMO-EfīOAi^#䍟ӈFxwD.yV@?r<ⅻzZӊ%'"(<%] ŏMmu/`p_紧:OdH1#$.m`Odzŵ#ACP)"f,Gʀ9mX)!mpu/lnqcFdO~~3"nߌ q̈L5.Qr7SضN/Lxꚷvq{/<#}L ^@|W%[':@d@4Ä*sk#9` [NdCI` ,i`P@c]6n/82I"hnYXZ'84ar0uڦ((mRêVg4K+"%*_H eIJ\@9 =h>M8(_$EqM uD![4~irJs38z87qaJۣNNDwtʰcC֓ZcS]!rqX$O5?9_2މ}z9%U9b 8zcźul-Q0MK@'ub.waA30ҪkNAIѩ8?oRy֗4Sfߨ$j57!2:ך;7b-mKmכ(-u,7V<;[=/[. VW .H`%5 r J#ɰG|"8lQ49>yAQJS釃u"(&@0񩒔 g6iZ>I#AΰL[☈i$4~Oϲ(1%4JS*ۦ84sW .t6!-ƢS{cX72mܢn˂oq{:X|H;=xh,GHO&GFsu"١ڜ=ەE?/ ߇zTOh?ЏS+B8Pz kֻ<˼+}ϛ;_oI/p!Հ|3ffPG1hԪuM/g_}MhKώ":GC[<Ƀ}eU>lC& DEE|]t )I$ToKkW9`Z J2+r"P#F,6\$$GHſ%V$VKh'!eSpƾdUAJLGϤz;jz<`ZfeФ(tʹPT4HhvFJPAhT _Θ6\N扅zG0n.-#g ,S@Ja_\QC4!L1>)ﶁ# G[`U;%;~ե%jY &Csص%¼eړҽ -@z1:KyZZr_MC~N1TVQ+DE3N/+$1%>VZurA6~G:IDؐZmȐfmT)>fȤ!E8ddH? {L x܉j[DfD}fOto͟kı!D*H%? 7>RTP7mN;G[H\RXnP_R־.XM :baنL Z61Loot}ty]u{}u;jgHtiymuȆz wяZD,֩qԞo_kS= IN.e$v/H;˒B):%%PzB>֫mK#ߒ tLP|W[( #!gjLonFͤŒt ¹H0A2 ǰ^N< &8 &qg%G`BQ`3VJ &pPG@Pow@)!>P|Щ&Ps|*$] )p𓘖,܄U{1+*F.wgRD=|+=]7-klNtis#7Oϟ|ʺ'n8m4_0kv.'i=M$jR%*ĩFkq\kjkN*&V61PKЙXbKKƥKcݩwwF?"R}hf Z ;Ә]Ľ[/AŚ=.LJC#^DIv;OAb+mJ:evqIǼa4SH>d"kF oXX':YؗqWhMh3ڊ#6Zt }Ȟ @TGD6<5D P49iDjsdV"?P޾j`n&UUYeCѹr[ґ_=nO|'ݽmm/*}Yz~to~}/BG}CX?}J7`4`4{*B 2D|+g} E$XAA$7L&@'OGX)$> (8FxVpL^,֨+uKީ!uw+va~[amB ~@]'cdureףV}RV)#}[/`wy86H 0 B0)q A{ZZ!-_: N>x0"ްuBh*2z.ʣң[w,J8Nh%CЖm_ҿW~zSMm^;op $?<_vo^`3NMz޾ZY-5hc51И8>[>+0+q1[$]hKt~(eG[BT!FҔN)tV;%4nԦIssOBQDAFWLE(tAJ竧Aԓ<4b2' jiiVaaD$N 1SOmeM:Z-OdbFZs%9={9+tg|^+/ ,#$aξGBD 34 #W.pabrŴ!\L#1lز9A~5K߸a;zOYGZrsix⻯!i HIiX:~jST"#"Wf+ee"E :RV"b#|c#NO͏8߷12pxF Pdn6id Yvӏ]in?V a͠Vքm GPмSG@ҰUCZ,E|9>MܠJm2uko@̬`g4xkzG=8pɺ0dsX01-"omoqK2uzja d7PvOK__D:9(o[zߥgϹ9:Q PՔ+}m^XGcq^¨N$dDEG}cj(%Վ*DQt!g@f.aq1YoG1bt0 T& Em{w@_I3UG\Ae|fРЧz(}21$S^߿$ǡCCE''-#`Z$"{M,ވ#:Tq% I0ގXO5$M¶??v3GPWլ LV()UuߩN՛6 2j[+3jΜ]D0sam[]Gݻ3 `&ij8ڇ. CWPP>W_W] \$/̰n w:$:a~mmLmLE!8kar 9 *S L)S*x3ؔjLǞӋt{ԈY1*M\`fn6 i0754hؾH_nׇN0)zX@t#Dh2lhֿ>w#ן5W?ԕp^֛Q_]3ϿCvbBgRpy+62 hCXT+p2PdճP\;@Ɯd׏jPB`pC6. +ւ"Fy x,}^]Dimհ5t8Dmm `9iwut~Ncb~0h +*w@C1-8aFqk/x?텣uby]G5E@j[PЪ`k9sͲ8Ň]@?Y?Y6m!C~aGiy ].r =^@gBE <ǽ+:phyE{$9%a]`iF U W>xge^qv|7{)6ÏX hrewYX~V&gP`=BO;MX$.d[)G  {vJ,>lva:ZXA(`'A"H2.*('Y#Ķc؆C$$/z%[XF7MPJ!CKqteY+*ZH Rz4ePtNK{{Cv pئxE$'g-0/ŝ\Qni$l㟖+=x-9w!D>zu[Aí:-l ]UMjӆF8|st>a'R;9&ŭ:>V]ГW^7_ X2npHnU)ˡM9:md!& dC @K:]- by e@*ɈXFga6Q.@.' E.1X_(+pV*TKj( ^ ](G!l)<T^7TXR*z=^zkꈤhl qeupjEbyw8+V1.YjőO z8'7o?_ oG+Yߝsy6ǴٽeWo5}% p]ufǽx'61~2|?,X0z C 8XY61L""?Q@( dH#9c6.%ʴQ[u$+"#[#6Md(95~k0#Xe jnwrp4- (8~Pjӡ@-IeAfx3ozҗQ 7V&~fۃ3LsȲ~2nԑ__:cx5*;oKA{E>A9\b~(6c|cBqߔи|ntYCgEs˥r((vs6w|z [$_+XXQzLl?8 qR@\[洵u `m\pQ)I{cmEx8 YJ 0(HP !]ڒ/GM~ 1TzS. f{ݬ`*" \Y,% yZOSn#rc7/(t7_: avڏ>J"W^o_y %lKJ;ժ9<͜bi:U*FGV|bEzSZ+Ϗ/Keדҡ*`s<;ٜg~|^Q2KgB (C ]'QO n6eȔmM4Ev;#9ݽH>IDz7 TD=%AͲ$9( z$(,‡$hjBS ʂ'A Y߳`V[Lيoxx7[vuObm%ܯn9󖾻*1'_ʛ6KKT/Q=$r*=B[)MIoMϊ_0ޖHT,bҕj!L7d23ϝ33<3g337~=)_}`bKCܯjz:]SU0 8=L1"35 ;J/]߬L>R^u,ՠ2 ™TG N$*W0뽴A<jֲ0r?j+Ǝxhm^#+3|k!8. (LD, @Et|y΋Uj:ov^9~)gzfFLwdB˸1ߘoww4Fn(Q ͟kqn_=n?̇?.TiʼnD^]^-Q-Q(-QLMNł=+EnS͌P]r2G^-GFF&GE|HKO571""OAz@i1 ?~N' mӚ<srDNv]"_ſBRL2d!aFHTDeX"z(yL}ig+}e2}V߾>[$DA˞)#֕22 {bntJڢ$|]|D/jwn ˣK@ٗ(2^ E/z&^%&%>+)Y!DS&2% KnScE{vAȯhyhsYN0~by=nŋVf\ZCS%W]uK1xAwiWK ׯm{i%h6ߍtH^s}oW6mLK+ͺjx[e㮚4fMqn˗fL?mX윐?xsٷ.:dӆ'5hmSk|Iw,NO d ҭ(m`D{?sB%MfΝ?d=כ6?2V }j!,S~d#\DCi(H0\^F(Ci.%iyiZAF@f4AZ:M~#N/4=l/kk餮Ht>)SVlfen͌g2a-5 ]3|۩:/RgEjGӺF9Mf}}iT 4LyJq:} ⋷Pr5j7y7EL^t{'ꎊۘͼ;@_mOso-N')L [GFϴ߅Yp'ؿM(1nc+$dtJ݌Q6l`+[C;58輻G'dCCZ)R'< /JKHݾ Ec=D*nWo7{+KTBL>ue/Vs\?wwv/^5Af0ؽ 9exm6d׷!ibmD֜˝>ǟ܆75ًN/HnD~={5?E6'yp w֜WLwǴ):゘7\!&k_3w'}m/ᔻi OǕlfTЎ`WN;/BI%=*x^ g,;yZՠ5xSnMoar])>~Mם< _v¿ǷFtż1E+9] [WT#HRXtaT{DR+n+U5l&ѝ*9fا/P,苺b-Ғ?ffˌG,zemeˍb˳+ó|JCG4OFU. u pCch6zV{. _ZMw:O?0 9,ݴ+;KU)H|KL>1sѷc8 BA3>7:v̐R$Ogȝ>"~\̈FcA(tP_@յ?喼iTʻ>/ZQOݹꪵŲ/^z9ӥ,W|BD2k+1'~^OEbgWh1g\_"yq;ZFg1JOr]o <wNSY˻DM&?a9ipR5ܷvӥVܨDU*FE$cŃݢ$OJ󟔧J\PyJxzu+V_{5MѾ +Wm H}ᵟ\W9ywC娘K:D:n nx[;$Cتo BV֐Z:$Z֐5jb1 4$ye^0?e@ VɹWdQHbǻCH,|hǪhX|_A^x 1A?~uGgJ8>QݝoJnw>kݝ7{4#}ǟHC|lL`3p{5gc(X|x9(\&&c rtO7,q-\ 5r/ڋä|NL3wx~RMNލ|&zf{WqxHӢTyEPw,rY8îCߕ_  ǔNH3>rsPֆrF弓N軽o-XT)*7 X:f`Ye}Y~ِC3oU9s&z^Ho "U]i0$sیM۴c֏5v8#sYs֜5g<żq֜59/}֜5gYs֜5gYs֜5gYsҳ9kΚ;UL&1d ˏo;,~n%0 Y>Sp W;"n%s3%w>އ9pJ̥SJxJGΧs0bn|B AZ W91?0 |r{+1 ceBF; }FLg<ไs> ROpĩ@.ҕTtR ȱ%<&WwmG&{OqK!Ps#M3ɝMGPI|*s8/+)$ +SƑeN OϦTscy Ly&Q;! KO>wd`x+]pQs 6tK‚y66q kڰ.I1@``'aŸM6̙C߆6R76q0zԆ5; lP22ԕ6d: 𙎉UE =@_FFS+"iЂ-ZC xhjJlЂ-ZC xh%l">"؝%`Mpl){ NK PgQ gNJ8WܗOl ))yS݉<̢ e3X=?fvRXodki[l%_ث ( H+6PjvW8ᷱekau-ZsiyJUe>#,n:xx0P105%xڂ璚vqMm_jF":9Fd`#i@N'd6FOOB(h`Qwsr~K.9[ohm5Jzxi#d%vZw5ajܗ#V;=.!vm5lNRaHі8\P?:nɑ3-.An#5$_LDP1/3n{Mۨ$2!g*A"uNJɒXei@Z*y % էz-NZUJn]f لJ<-8hPtF}mtbKsK-m-m -ַN]Y۶fhhuvyu۲hK7cIRN]mĬڶx2`hĆ%m-+[P3fHyitr]]Òh贖KԷ4URְ::zUs PGU /Ӳ*zMth{=hkinDkV6AusMK~hkmښ%k6ڄ<% <8(fՒ(!)9oh^Ҵ&hinZ-n]~ pnSYڕI\PK{rYm ȵt&T[EmD- UњՒ͈S_z:lv'{fH9pR/x>rf"jǔaP(દ*0=-Ӱ>:HQυ[h YozߏlmF=a Y09 00(j!c{;j t/?625jڄi"5c 8ئ`зqAq -#q{qLJP 2E )Q\JJ&u (_>t+YerTWk_^r|z|q`G9SCwRb\PCm"It3giPf6ʘk,\m,[g]m{!pܫmۀ1|q#.x%w'(υ9kk ?t}He/DDd){Q O,];]vT_{Iތo2>sZU| aCaԚ\Ɠc>Mhy4a(Kcy +xgemͬfrɽL:ro Nr_!˗-_N%]%7ܞv "ŧ!gjD4;,BK(sdY,尞,o3;S>>G؄^o-g&:  %Wgb>W |.·=92 0cɯCF9~Y~#V[ȻvY_1GXrǜ,s?5T!-LL#VK0^ӆ:{-v/MxjÀf54ڿ~a#k [lkYlݲۖ=Jt/o*el)k۲妖ZvQ֭/lExESVԬtzڶ҅Vg+c߾W}`Xhu$mf}ġx/jk!DhkM6{&M$>@*Q؋Ve#2jzqe-5jfW0RzE?b01^4;eΘyYnnsMp5ֻnw:ܷܳ09˳ɳy۽z>՗.{R3W??"QpXg0a}xI$}J$J"J JB<œuu4R&*齤Kj~K%zpEZ4>xn'' JJJ}JJ 4*I͟"ujR'5~R'S˔N7ŤOjƤOj~OjRћM\=BTR'K&xRםWMiNNNY*uutrR#'ts 4s?X ;5)f;|\i \zD=Ѓ5sϙ_$,Ȏ^wᥰ`66 [[N/lz`zSɼXq7 ` ̣y4(jAc=h G;DLYs`(%O|4r{ =bHE&c˘v"F8|tς l.llIM枬7N͖!Or ={X/P=Cr!s <*s@AI:̓AP+^Ij#q5~O Q<l+b o|޷ J;7W8N^PJom oXm ߆1_ 0u ց-H} AJ`m:P{[ hW5i:$}EdHu#È}#kW0RF-Tw{j/REHyEʽH)"^v/ۼ%Z^[|q l \m8~GŅ? _b$dS_,]4_8̀;X#"1GrRGd< ᨘ[ @NqbCtK'tK'?tXX6CXxuM%--+Ũ FNȩ@.h7x`q^v)l=/ jKa&&{D5YA-U͡|"=Vt䩞r6<.%^N Mm+=M8(tSJYOt梺KԀw"8q[Yz$gcݔ4aaKuތro[/II$b%0M<$anC$K\D0Hom횗2)bia=H,Z67 ͢auDb_2 fvjKa7Bp8s<MͥM6:I'Q<Vı8!y5QI,\uJl p V6ؕJ4lvRqbc'ӉD˳cKHXjR&$[ `ֆ%E:m.A@`[&H d?QۓʒNjڹln&7۲)lqKdQ̬(YŰ$2>SY^LI=J;lQp- V?d)9,i}蛀M4iPu9H3; DY祴vԐ+nQn {M O3lܒA 1H*O-6e{JRקPfM\ZK~k))UKX)%:l ӓK>A3Y ~vvP<ٿVPNԿvmIғhSHWO{yI3l =1 <ɕ>0 +Q`b x*o*aLF3a=`Q]gw{B1B %Bqj)K,R wfnX %p0sg\RkYK.e-e]JZKe]kkZkX 4~s9=ysg̠|g$8)yycdx0=<R?2ww!ŇkxYaceɊrfa~~x}}Vi80znl6 OA88|c-dw?VbKi-u=)܋ ̚`md6Umgv>mc[nMl7 ~)7B>0,#H_rq1q0ښFG\>sX#" C$"R D6"\c,}r0 *20hZDu18u q1fc뀥mT5Y[-,8K?m"-Ŷb[embԲvSem۩VRzRfbºX64m,um-u-UI,cyg^O]zKD▥2,/RN[qq>X.XRܲP[."ڲ-3m59],7#tDt6W*:[U[e9j#D]nWD=Oa_ Dѱu  80w~(=NZ оuQD}RPD.w{ GS4BvC˱ƐcKVv"*AmEp=H:Ē۷ 6;)} \_qˡg>9lM^,#m[?4 hZCeSt>--m=zm/[m륖ؠ}]'" q.L_@F^d#.7 K5˕펶2dI*םurq= VASY $~m|mrAlhR>IAgM8)3 z,#!g>HmJ|Tx7ƯZ۸ާ kk Qy:L(_E}!.dwzGq5۞L6YsPvڽm<"uj-<K&w]'@?34駙Is G觖fp߱ps==!1X II➂e܇CӁ.HG<X}"<%H}}2r_Gq ׹Gop߄_ǹ roq߂'os߆<;wIw!=x>}(~>!r?~s?""| X{>ʽ½ 븟s^^2u (ބ --+WP-|6| ż|)_ x -|%_ *hjhe^ oM+*_ׂ`p|#8&\| :-|+hWʻx|^5^>; /[o/wO~w;K|.~|{a7 {5~>~3?B??~a~}|?A~o#0¿ȿ;?'38̿̿ ?__qUU1s0ȿƿG%/oo'_󿆟o'߆S;;34G2..L YbB3ra9RG. }}pQxS_. [CB& YB\l#Ua ~/ pMm!_ȇBw5) wAjZ:&F^h71§O3 fF,B;$%|'aW_1FaREA81I˘_QeD1yXL 1YLfS&S\!`>(W2Yb<*iL.f03,f-f3O9b'W1Ob./ySbX%ZiqXɬ*bXT(3MQajZ:1b=c,6"63bԉ̳q S y~~Gof>G?oAzKBhalEtДn^>G@BAE@BAC\@".c,!n{̦Qzل9bIXMiL&f^D5P x2"q@: p`f*dbDf%2L%pʡg2#(GȭlW+}%4ң"eS&rIšL!ՠRSH1NDBP!$ebP);ReRNXE*[٫*=H)%SفTҤT6SJJjMEAUJW X eyV)Eꊲ<#uI5O)HŻ'4Ɣb1[Tb oiF/6'F@iNO<>0V XD{4555555\}rKml@y9[@y}9!"JUST}тhED`)7yr'79r%5MR s9XCe9a"PRZDb;e ڧ/ԓ]~#8h fx}cKюHw _$j8M",FW10c} -WlccH຃lgQ8ȿN{ˢWOFyoMDϗ)1H%ySQ B˽4\8LqEܛZ{<9<9O!jH ڮ{m7= O?}rSQ [f]ï=&ZS/v'_!ʿ.:|dGmu١l9y]ﵯlÖ#-{ ph)g=˳w^O?2Ob3߯ɮ{PVo_K[gѓc>BCjGp 9QsBm8:9c 10OכLEy!f=`c X]\- 8@W JC^C8 V=W,Q'\Z\{ kEzwG"nqЩ}o 㿁m}>lP'*Ƈ^Wqƫ!W琫- ȕDb<ݪ";BЅ}S FTmqn'Я&~M`-YJ>Հm7Q]c1{:n  ]w\ j BC}ζ?wV-ޞV[f[O:҃=ln 0)3j}0..YXNrB㼖Bjg^T}z5?:?kǧA \;q6Im:d Ǽe֭}ZgsV䫞MKXO"y`:c{&,֞@&zE>f\ y4/륙4pFo$xZמ1M=!JiIrMgn:")ǥw IuʾSo(5ՑϾ3`R/wn<:V>Q~#Gڑ5plȧK[ yNs48h6XT)%T jGI4`ɽ8;ofq_4m;:vēmsCtks琼c3ьul CA'hy8tII>9EOS<sQ% JW9OO2C}̓jy6IN s^kG{;p%3UCMgFw `Z0Н')(/|)Lq:&qck-Met_i%uŕ@oĈ>CNWII\MP\=L ppYi#Lٙ ')r qySAK϶Smԉ5|VTggiY<\ ^pz/gׂUkN8뼷F_L7xΛO 9N('w8Z"!I+Br;L$.ҕIvRӕG` g09wҺ6ESs/ʹǗe sz UwA_iWKE@^e~_^`9+pþ]U_BԯYØuq&/ / 4̊y8_?POEXXB>T''\Zg9 ${HC!|S5/B 0 @axë.[`3t0, ty˼\cZb>&9H̋ s2&>f.7̽1 <|e>(l0 ‹IxIxQ3c/>}$ ⷲ|{_aoOǿOĿ,4LHL &$'nMe-{^,.}eC?ȞYj*O,Bߔk{}!~TX?qI~Z^I?JqR"JR6- 7l. aEOOǮcC%g?l [qU }} sHϕ~ ZY+ig]p>,X),L4%_DAߨoѷmz>ߦߡߥߣcq1~FQ?uM $Adi.eI|I'K2K*jI&id>oI IWӭp.z HCxoQ4!Kǥx5%MKKu@mP(V"pϯ~|=P*|1UR}2BUb?5>ry`͏s.VJlQl<[[ [Ll-<[[녁>\ID˙Sbq1 Ye5 m)FCZ&%I+4)SMʑBHZ+J0B:QjZ1$I;]AƺҘџӟ0@ GGoצҖS! jxW[ô&2>[[E1`_ÁU PHFe*"-:ND(S:EZ*/ VuƸc"'I]]_^cLYԓdMƎ%T rdȽ$cGh2)#0|{w/,oqq_els͸q,3D|˚$ 2F EXWcPfȚ%Ҏbzx.SY!{GE59'ed$.YGKXJ*%1\%-Kե喨x]Fl׹!}V+d:fAne0iN&X|k^<Ǒy6 ϜI=;ǓYW2k.QX$z&"HL5Չuass"O5ޯM>ޓO2<3̛if 9}> Oѿ\ۄWxLߣJϹE2LI a~LBIW`-y_=0A] I^="+Jn{܏j<7_$zO6`b,Mn.ȃ'׫a #O,RLP0`J rI9e3l/40='1L"ozZ~+(?U|L %;g/|zrbʯV Iŗ + i%-L)٠*/e37\'datuIKq6ϖxl4T*?e0_&ЊtuՓ%tJ uSaJ2 ;l,iACǠnHB p0NΒq##@ 3X^Q]ID' EC :rxs=DF3,[/^\lXGiK" 5'|wpa}]߅}'WX?~d袼QxzRO+@x s,xސ>ăyzzUו/.]n}K@WuU)bxЀ!"I)FdRJ)iJ)e(VZ-"2 T+ C)PJ)C)@RL) FK[5=>ϹIc/jؖI5jƈejUԓU K ȕ1ZR QSVfKh^b;m޴-+?#~}Lc~e2 5il%v%b@ЈKCՕz-)0 9j7'y6#7C1rMG'⧆T//ǯ7r_%p5# Dv|fk'5뛈ܕ/.u$~QQ5$5'$ʪw>[W~0QǚǶ$jtSbC'dU:\u2ՑUHDsl`VgVGbR::ozPQcVTWWOT]4e2Zٺʚ-Smwi_KuLlI h$?1N˴g][S^.IGn*mHBzB=nOC$&=:KztK%邗/V/MRjiݨMmKHK^WRln/HߝB[S(ٶ^^IN'pwJuc2=L%Mmj^ yi6lPVo$m}ӇW ڟ?mU <>eRt&ZĽ^MYn d,zm.^[V_kvueDž ZSʺ>|'(ū[+7d:ʥmRHnn XF>ۦỮˇ: t(W7[}Jۄv;O/Z[gSʎM%ҋBz XJp;ZnK=ImÇy*khx)BӅf Z GsʟZ?j%ܺٹfiژ:;1Yz&a{#u?7:X0s'MΙ7FS88fBg輥j|Ҷrc989{czt ̽v\z㽷gܔ֨ZT,m':lqyGR+'^e۸/=?Zio2NaB :.Y KBW\Ҭ΀NB)=E@PXhWDh' (&4.& M1Mh 4T+ZXhIQ-2GcUɢEnYt˸E[Uv_=-hCѾ}q0o0DM_,"!]v-|5' ;IW|dwAERʷ@F8Ǿ5 0R+Gl_⦿VN)$q_GG^Z|2K,!u4/Ci@~;H78kmrfL7y;o񝘞|!߆)0QR_O}gvl 2DzzWͭnx[/PKtOk{a(쪲¨I=b=ZJUtYTnk]㠻}Q39'`A9]=Meƿd65yB[0R~ܝb;ezFWGQү>)׌Lg"yȏEѷGQj9z {0z }GggEq-sw& }oME/[fc~ݍ7]$񉖢^S)r!'z$]{5eztK聏R>{QDGO,Z=7=mTuӣMhsIe6>A m$mKMkcS>E3,Z֧\K]˰kצƔ>+ ^'?Ϙ>v]'B&1M0_7T OO7iL8|wn7| os9g#$4sebzj{G;x$ZׄklJ/^O\'D' J Ju{K7ẍ6.I]rk6߽y]?>#gmr뽽`Z$@漮ݶImy=u"=׵2Ln3Ln#l,Uߒ߬TP٭6*~676r{Q {%mkW1mX#=MJ;J+h ̔ڤly$|kN~W%+k]&~I%))w339|,7)t˸q][5Nh6NU.ߘL]ro勢773:Eo_isd5{hW#꧶|jHA"=Dt"=C"}’Ї},ڽ {V;fw5ݩz;hc=y7uKK\, r@-tS_|Kaǡ/}M(|1Ɠ%a~v/7Sme;)geu(ʞF1)Ï2 Q/dW]x6J;.wbdik2c˭cZ~+Err(b1MjTsSL[=|>,Q~ Mf #=̙"$r1 Жm;6lj!y|Gܵ:^V?FwnlweCvnܣQ=7 rOͷݷeّC֜eW1ٕ${'o#~Y ;I~<'_~]j'vdiN'L=HU"ִ];r.J7Re95vCVy;v+mu?t\ kÚq-gv^ #>" ~Z ?%NyO;)eb5k_թב7kK5t^zzbL$LV0+S(/i_]5HaYD>Fȫ&^ڗrGEl0kؘ'dzB &gK+M5Upj֌}GL&.BrEB!\t^ *D.Et4sܨhz850Llmt? 9uI_m^8\CKF-C*qz!(S`ݵ֎h_րY-j3,~xȿYhv D&$o)^uuaD3_(:uļh_StQIwGg'J$oU/䛊K47 'O`)RҶLEs6]O "r_PzFwjz_Ӌu.A֓~A`%i\=F >N y^;dENc6;:'9+Wź>˵n?GsEzp&ʻKϻxY*˕UuMD]=ղ5&$;,+#/D |G1o=HM_jQV)܅'hIgA%Xvȗ"S(kڕ$ xQ\.[OՎo/i:DOZ+gpqzu lT$[em+7qtƃ`&xu~J5yt_5`τ?0 E wrL<{)'{1OJ ֳ[щ_?` AFRjƶMnCk>!iZkv'mv s uL MHMH4!{]IQ`uߏZۏtt}tܠL_촛mk?H2ZJP-SWO{'xNPM9ҞumHb|uɞ~G0tyr_3 ֆ͏tk}Nu5GVSl@Ҭ[^ݦ;펝R\ 4{o}*wkit5K;d\#8tBZPJ Sh%rH}ޠF)}T b{$2=SȞ[S\nԥ|wEe\%ܝvmuX k8*CϘ[׭i6Uz>Fʠ)/oFgNH<<ߝ!Ytܑ:gen6ZmZ;SW^_Gg%v֨74h.7޽ni$fņԥ4 Gt HYwKFExr__K!O?[= "@'04B8Ῠ!O^jw?w,C~|a1 ` oAvP`{ѳp ?jel} \σk x9{j*·" gгs˻ *J?͇wBD>"+T?֋jR{?/~c˙gCer=w{ ]Ep6;*f_w & |UbT3o+:H J~ {QчBʮ1Q$?X(G0ܭX@<BN~UPP}\@dޮ v[1X~ Gbۊ.D b{F|kMy6t6*aO$HI|-0, 2_W'חDk$1|y z:$OXH3@\HSp2H۶4&^>rCv4Q(:v4QLÌxtUXx 7V~4: k=Ex;ءQZςȝG? Hc >  '#4hމd48P4 ~ko@N?E{v^R qahW!R{ρ;љGH?A?;ĕFd_d}EěJVW+mUv}xc!*7`ww$k~2_,sm{ #!* qDA{]Pf'jo ^㺸R1P_9V{?eGU}K VzpzNPm/GܤD>{8?ȌܷiVFNB>.\(OZ; !%؛糽GЀRѼ:'6>i0 Myϝuq\l.vnۏU]Q+1 <;cyv?XDSo-6ZX|7<,٧] ~RKW3]zge/d5ȇR'e6Z `µO}gv|ybv>N|1=ٯH*ў<'05#t : H'[H~l@ӋպTyb,ykksP$ w>ՌArp݉wؘWwB"p 9󁇵|owRj$޻ 5W[b{F/&Us.~{/Q&$@VJ>Pv7( wߵiϳiDw\1OCKBx#8os,+ Ғi2v}?󈓿euR~|D,|Ҁ؏)Ys:Nu˸v8n;ܓi|]?7}N~Aפּ`*_7|~G]gXC6 ׃鄜6`O".:kf$o"KQx_"9f\IVОy[ZZA!y~(.w(8o-sm='"?@/zZ}{-`& < OWs} C nW &Og/=|ց x]Xmؙ_@++(5ڞ C`u>TkcWi4@rXB6ЏxKW?ޏyާFΒ ϣhKE쯡,o퀻.4KqKZ/+IʇT>mR/@f؉aao}PtL}Ŷb0`c١|/P`僬ix}>q*pDp6>?B pd鼪̈%z LaDʵ~Dll8G?ߞ_X?|C3|gI Ϧ[yMǽwS ozɓz6W;}KHJ*:Q rǃHg7s __~X[Գ 3Q)` OikpTy[ ayOh6a̶kqt!DlݐmJNk+n)`<,>Ul|(e~",/h+ ez]omcj Fg2~ j ^N־c{D#+jU$̫Q]1+|_]t-1o#PxKziE_Wr>>և|5z"E`{-hqk6ЌARK~c`6 _)pw'Мk>{|m'xZgS1FJ|yV0vin5*؏7/2k>Q1MVG~ɶ,=vs]\,^q"a_/Y_]y =2(6S]}3|6+[ @49e)vw5LW+OTNӽx3&pۧ;fvp;1Sf9mU{:3O6˙Ug&t19&K,_e&brM'ojik wMn|˜_,6㎯כERp90̖wn{ {k!(nNgj」֜~M<[r/7uvcgm}0#R0+Cv1}MbM fnj̬2O`mv"6 ל4z2W&}+u_ғ6ηi)'i6͛i햺~!Y>o_M\iuBdQfiD9Qwo4efffffyX<`V5fl]fy3oi2ԑf|gC/n m'}./C;$}V%}6tSEBH7^2&~MWH %7'WI ' sC?BfwgCn N\D{s&g}$C?i<;/bx3W=iw@EktM5#4ACA ʢ" &T2PEQD+93`DT]g]{{=+Ǟjza>p$/BDDx!"p($OROJ"“"“"“ “"“"S"S"S"S (D7HOE`!2Gk1ܤ-I O0[8#E#8%|h! <+!g^3ސoI>[^|-b6f8aa89#%Ǚ3W4nDgٯuGI$_Q3Y)C]}-$ZĵVA PԹM`L9qBꦸvq!:-qt[Gw=IYh3¹wkmp@ˤKK.q[5/N\'jQ,UIrTu(P1C+a"DOT,* !\RT-1 x:3_&jРbۨZ.߮wΥs(jB=P!րsh-ZG0BNO4á)40fl|?"XN3{~xGa-<˰ 6Vo. >="c\rG B>4MG( B( C2PAyh9ZT֣BmBŨ'UCCQ:.t5&Dw}=C= z>/4%h)ZA*߷6CC衴!mDӦ4K[V-@n;DtACR Ќ$#(0UFc2c+Ǝqd\Of3Ld & gOyPrhA-<PxL >a:L0fF? 0Hep*X :<2xV~xfyXˀwEv)| ?%| W0,011rD9#g`\+0C#bvx>f0GX`K_`1k f`3a{"W4('3JA)-D +fF`ew̴,ٖ<1fr03o%003q=XbFn8b0L -~ہ?fO`"f0 3`?jT 1T3 c>_30A0jA- @7@(w' 1=)z KD5A;0#/ X  A cMȂ y0kC$b} I`z0H5h 0kE`  ZEX1 ,h[c b 6A:mI[ &[I vA6Jz=b<`r:N+H+*RA>VVc` V$X( :ȁ`=V*d4A! XCFRCPj6a ˰d,Ɩ%X`+V+(e<Px3ޠÌ۰ǃX@; ?aXX@ԁ -kfn`aqF oNxއ_>Ck4 +4MD(pbQJFQ**G;n\:4:.&xtu zzQ>MӒ4|PVcik4GP: uIa a9FQamfcX06¸3#8Ə `0әP&5x !nF7͸ĵ+8q*qĩ$SIGb#IG!$KI83>g F|ƈp3gL0#0'`A8qp H83q܈ N8'q/#xE8hc%K`qXZ`ѲQ?QDIDD?N&jB:5uQtDD!DDaDDDDQDD1D36gmm&ڌ#ڌ'L ڜC6͠ſf [ ͻDC"myZt C؂_[QH9zޢ~Ј ֦,MH͚jӜfgf0bmr8HR|=Ndu$d : [ o`?xO 9օ^nt*޺>{oeEŤjh8JG(Ce,qM"f^ b6@g@a_D 4?Hu$ޫ4XVBڿ^mRO.DŽ Y! V 8̻5!GVjtU*\9V)Y)|r!)]`u/h kF8z5 j˵1Ć|"ǐO0TTTFq1O8Z |BAٌASF999TiƠѸh$4.)UZr8r2l(ԟS^8 @< w:4U2ͦWުh:[.|OITyY~ipL)8%iZ!k- _CIgpWJQ=>aAbLTta0mؘdmS&.#!1q|VKp*~/>>Ymnrt|bLVs4kښ|| i9޵…v 7B+R`(CHRtL\T2FJ(JEώ :060=VG80oGhDVǻ]VZ<0# p$ယۦUydѯo5j^G s^6{=̬1~o3co5QפW#]tmݫeƟ[HZOmȇТ=w*Re{$5]Yaao"L8_>x<-x`Ҍ#]9>{Am89~2y.S˾C%Y1I:gG) k0n7Ox vͽ5c|^:`ujѐZH"K,F%Pq9`{}]JTmw"SC˰4S! rA)Mߐ&71%z(,Ϸ Yp pt̓ov {vוQE,/@;Ԩєqwma=,et*-t7< hnUΧ1烱ݗ܊9'Sr?9魵=a?{7:Xzͽ|3i;vNg}-oާm1~-_KS0EO1pN{җE_Ms{\·sWמ}w[ -O5i)jCmM/(luv7WNRx백4)ʸlGCEvu;8[[I{1~})mDb cBE9x:BgFUcc16cexM4!.w~_R?sU:> -ńLlчS*:t\AS]* }/J[*vf鹊9G-`޶uԋITCfvߩ찐J[{ܔwႷwU/W{J?GM;}:!sjsoˑ[W^s+vKƉ>įtu͕ٚb\ً9.SvGg?^Mv.|ɳ.G*:O9zꢏmAQ"yϦ LےΐTEd4dBH#Ua}_ Z\'ց+)ʱNNN73 K5uMg%̊%$Ƈ KN2s3Er8\G֞R9Ƣ͛#i)O"lp30qC(ޕƁ7>ߦPJՆ7YU:an^nW5zݿ욱\&_'/k7r9|U#)1[WYO}fJZ AOcY>kii#;7:cfG$%N:l>8g&ogJnj͏+٢}zm=YNn^޿{rŅZ$D7|\]2?)l;k{W->;oS5Bݥc(oKx#ק- :S=KZVXyṈ1{I扦݀Ԕ[b{zCFTBKe \q,Knêb_oV| w#[MFJ7PeESܲUj{7ߛxYBbD|qx;9zhe0e'qps? ;X|e4%?W!폙_Ҩө病HpdV&xz4e2rds5vPkgץty1Kfr]籇fjzJrSOt'LZpv~}Wѕgm;kݬSraSZRNC&|S|:g#{7~\ehN~Eia4wn+=NL^W- CR_ *ױs ͏lPA|MP9K#ߗeژ[ake! vGzd w5c#===}m<,L,X+w^|}VOLoJ?"1%&,?z(CCG7lK8k}pHt^bÛW4CGo`Y|á̲Nq6oT{ջUƶ|rG]K_Lfʘ^o!tv&†5%95 W_oo5*='$*3jغkSM~7޽\aѾ6._x{2:Oߒ)}m)f[I̛ei,yʬ˜֜yZ:XzW{^Љ/=kj{[z-FjYb~N2غӍ.7% ptl lN8R1m|k ]zp]&e! fX(MlXH~4$|{ _2v \>Ŗ.WYs>l70@681 $xr+.$m|9% dKbpW64m?ejĐr&nalE) KG}|c+7ȳԑ+4QqDƺ.T]{#&}@⣖{8NNsю*~:FF3B#lxC-mKg9ڿ#ߩU]{tߑ={F%W;BƜ>m֧f"%R$,vۤSz&LpeԿ~L>Џ˟(-0f 4dw}{#yf?VD]q@KGWL*ˠ JYxv: Xo(_S|e s>ܚ**\{dǚԧ=sxrvcã?".*f9}Ũbh$ yt|-go|i)UQ׵OVgLHb[0֦mz0cQrJvtOz&Ja&oãΜ2Tf;|NZ0qoKM+]L'XQf.ovJ zdԩ ?e뚂qoNk)/҆aeF"Ւsyfw ]3ܟv<̻R[-!6|Ov?M  endstream endobj 4362 0 obj [ 0[ 750] 3[ 278] 5[ 355 556] 9[ 667 191 333 333] 14[ 584 278 333 278 278 556 556 556 556 556 556 556 556 556 556 278 278 584 584 584 556] 36[ 667 667 722 722 667 611 778 722 278 500 667 556 833 722 778 667] 53[ 722 667 611 722 667 944 667 667 611 278] 64[ 278] 66[ 556] 68[ 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556 556 556 333 500 278 556 500 722 500 500 500] 95[ 260] 98[ 667] 104[ 722] 177[ 556] 179[ 333 333 222 222] ] endobj 4363 0 obj [ 278 0 355 556 0 0 667 191 333 333 0 584 278 333 278 278 556 556 556 556 556 556 556 556 556 556 278 278 584 584 584 556 0 667 667 722 722 667 611 778 722 278 500 667 556 833 722 778 667 0 722 667 611 722 667 944 667 667 611 278 0 278 0 556 0 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556 556 556 333 500 278 556 500 722 500 500 500 0 260] endobj 4364 0 obj <> stream x]n <a51&m7?0nI*d}fI>>Z9It蠴0O+4J_!w`l0ɻ.t Hj%XtyEΰ1IM/ Nhh}!MUA|6fs,m" )+#9DB]:z;:e{"L,js-.}QboXaYEC8K3C.-q7#>؅pJU~Ǩ endstream endobj 4365 0 obj <> stream x xT{KfI&L&w2$d! dcJhŚXpM%PkՠZ jER&aF`mXZ*3%"~'O .99dCe@ a왯klhqſMGg6]pc$3[_C9 Zf^ sT˂Y+s8wAYgmؖGFk88c'GH~Y6Im=Ho ;q-cHB"sXIb{b{ovoM4װl^ _NReK;:`"d_PyN:wy{${Q.= 9lHovKnˉqn{ /}7%<"ɝgҋ9u9ts Į1];yCK&;MDZ'4O>u%c|<ycMn3ZmTI 9PMet,j~%Rgmd$Jl ++Oɲbf0 PO(h9^#L3{IiRs#@ ,I3LDflⰆLf3}/ϙtWuvy^.1"!S(5_QV=>pi/4 .3c"Iد+t!(L2#@ C"~K aTI(øOYtEKVBmdɮJr@䄦puQ pJ^h&tA 1eR452QlʂPR6ThTh.iG(04\PZH"*P1?\KZJ2 -8T@TOTJh5N i UAk:&AAߣ4h-Mߥ:@ӡΠZL^MA;͡Fh̀h =fCh35AAw|:J:z,5mF s=Z 8ot"} u'Q+R]D'@s]B'Bס'I ˨]SZ =@Oz:-A'CϤooR'-~CϢS7h Ӡ+MCϡ3\ꄞG߄: z!_oQtt*sѹЋ<%\MC/ w[ˠ zvZz%׫m}KBwp._r Hkߣ+r]>] כit V~u=]@Co۹nB}FN.' ݂#=z/Otmnnۡ11k_^ԟq}~}=t/t t'mЇ(?G?0@)}zǠ_A/+Of$mBCo>E?n~z4=?CǠ/ӳ8\s+Nz<ig-EzJA/q}Chz^=}A-zNM;ot wz^K/C߃ާ?7 z Oz>_ߠ{ONbN?Ԝ?s59}>s{|Nל.w9}7w9}7w9}7w9}7s_9>9}|N/9KĜ9}9}9}9+7*t193.9-(Kc0)E/ ö,fd2m(#3-63{ܤ1YQ̊]dDdKld1%P:M!|BpHvA !+G0Ȱ*틭4`}&EAeX-h0[,K"JZIWV/Fّ1.@0$b(&B*g*b+bY dح6+,VӺ/⡖ fqMn1'cuʷi1^`$ϋQ @  X9 WShĽe4,4X SgmV@vfCdaj8L[%cuʷ)b+b+kuȮvA !+G0,J@b++ VJ90DX'b+6/SCf#jVgb# ߦ_#lb!vA !+G0u"2%b+ߣ&F}s0rV{[[V#~BC bA䎴 @  a%5?1틭4ir8.RINǙLLadAۓ:eG@nGuȩ#@ C"VaWFHeN@& A 3 '@ӝb$ӓN!R`N0"" <@n0 ?!!8ʙ.@0$b(&&oJC{j8hpMny=4 A}^JzӼ^XĞ_\94xH#-DPQ B%EyTUKx)rBxyC!;U ȇZvqNvV\fk]ŷ ŇŨP]qr6bfRYZ S_}ii)eVXSct&GGy168.@0$b(&lF~W+A Sy%MSM̚*_S5=X"%hi%^JTVVZY]iIQ\+nTZU7kS٣T,A+RՔZŜqx矯xC⛉Cp_g]bR3k}z`oi[[92{v}%Nb {/mkIb;vT[nd-h1k.v\@wp(6=+IfF̃{J=ۓ,8%>?(<7DL[0j^\aMUl 򘵾=31k;nl1E+d}Xqq"z\S8'=Otkp綣mrN(.ھ(-B%f^kѢ8Eˊbr;;׳߼=;~YsSMIӽ4ߴ 4V}6TKW,R[,y$g)7Y3Do%17%o1wB!m̖w>326yV!_nj9vP L@3ڌ>}͢wollwA-kb3lA,&f',]>'*]n𗷴eIokC_f S.oj$Fޕ9Jx/YIONy(5N^ڄ$!m@R(kvVD{xO/ج0\_fr~UhC+$q<[ 62$\HEZ0 C/#Hrr[|-܁ jӔ;pTQv$IwX݃-xu{v;Rn FZ i;΄GґnCm$+)ݪ֦V#%Ib7~+"ZVnf$bԏ$c1)^2¦^[Jpd-v*z_ۛ6Iv' fsIR*gPTe䋑c,Ru+`1|DUjt@ޠ([OIge|LQ^C\#(xmU_k3.})*fJè5W])6\Y?^b]CiaനQY>o86TQ T%|g(9|9Lg+?/.,?kMȏʏ Q!DXF_'L@S?BnqAFOa.fmX8%je6=՛b{|V6VU6NW-^6.MS7uьh$ZݨGK7*ZD+ѪZ[z?Zhi2(:*V)LkxKu}˗\$Xi E$#]t!ҷxKJs0t¢E',:E'J$fvXâ[âhvXsfX4âܢͰhE3hE3,EQXDaQXDaE[DaE[â((E9,ʹE9,aQ-4Xh`q ,4XhB [aᆅnnᆅnX_Hb,`1-`1eG00MvdLvd701x]dȸmV!FZla~s~~{Db1X`E[`E 1nE 1n`XlXlYMyėFHjwF*jUߢ_Hy~]P>ϱ=wjj6S\DZ a$3/mGzI'Ds .\z&f&Yv֛667LV%;} ZޓK3Yf205[f޾C(KP,UiIMԴHYl:)mXuqSY*nOh푤/G',ED^$)ҫ(#ӽosq٩56h!cp'? kR+%5X!ߐbHʇHX Y!!HQc6c,+zǭ\{=ܸ=e54gw-^򎥱 Ugc~u 7c-=E6E5;z״+﫵ake^{Z=kzt:Wrv7X~a"6Ytw4vCoX@]d/n9u1'*-e]9c])USBY[hhߩ%6)6a^S,VvĢf+;7]??{'ϧ8᮸gE )ױ}_q_{=S> b:z};{C~A~QbTr7[ҧP0 R8\W8ӸxwM5%N[߶ӢO_K{%_E}{޷tI I$Mb 6adu."dG(qd\>M(f|V**sVsؕIϡ;!vBp>]Z\G[d0^uy*@$!#md2YD'Nx09BBڃ-^Xt]}nҏ)zA 泵l>n›BpQ(1,ft%(I˥Cҏ +`xB'2Au8a?jB\6 1 YP9Z( ĐC;{\'Dh%y")'+EO܆{q^?  =&; }6cvkOhD%~BǷP(T۠<x_xKB-| A[w :6A?@T_;s쫎ae%Ȼih d @>8GBPKJ!qhzޓ:w<1>y ǍX ݩǜZ78sq)C0[X)lv o{uUX# `o%>M}PvW.C>8uV: ϗ{7 pF# L Ȼ!iTVsta B< '4MO艆ݨ *k9XG}q6~~n"de*+LP7sHG%{Eеp:Rȇr&cL67ˊdrR:Ǽ}^lԟ Y&#; 6E$0"Ub&F!YLB_yHDBluz^]F5ZC+ʅT ]@Qʿ) 8> Z@ z!`N!K 8R)BZ(J(I,<"P=mo+0!UkrSPICړuǏmO&:=u2Yأ??`%,9d|r1_J%8dkgte2KYDA& lMDŢʒ+Z,S$GuXQڌ0TͲdU~{ɶT2m@vY1-qiQ;v:w>=rz9L>F:`8 (}8\aD-UѶ.Ja׋wuZNB55zI#座gE!>;'ZxǨE˧^[7?| g~duS%òd'T2U]M6"unX6ٸ5?Rǯ6s-OZw׏+c7Wo[9|羜~bv9fy[2܋_ļRdMTfňq3qDY(J!Bqx >=]U(YWq bFo/%wFȞR#V (K:hA>{nYǓu:@- C r=+`=E9T"]a-lmڣ ~)NެHu"! Uz U<"a )ˎ:HumVr, Q"2]Oo{yΎ8B+Ԛ(zʨ.S7fecgE55?-<5K"UbO}0,^ oR> wwGg!ݥA2&O7,g8 8rnDB摡#Z(ۿ[ n+OLҀߥKb<􊞁lQ]_VڳK#b圿6X6̟Z5; ݫ l^u-Ȼ!>!y21p+k4ML,~ abQ1R[&Ui9=PCX%J=s*hyُŤ8#g2`"6 vwFCrH~B3lc,@bBrN0'<6- X9csFzf4GE+3gʙ<.~/It3p#@!F`o&Ƴl6b㱳mZF,} uv+P!6 P0ɥ)h6pZЫW fWUZ.~# EHă97ɱCc(*++$l'ܞ9e~uIdlo(5yiy:XWfǂyi|f'O o^>x W"kQtoB]/'S{g:]U΀ַKRUp*%=VnYޓ*x)+ߕ0xvN33󦞵Y3_6h0HzJ~?H@ ڌ5EG YΫT5Xx.,\\ ٍ=-Տۄw̯~d#c`CwF-%vn ?)`W@%GIAfzٞ$7 Ն5+-s\7Kۈ# ! x|:%~(UD`!"߃,5W4KeUh('I^鞳SI(*ͦv6v[tsԖ5lp9.6}7~(ӠXiDQ-wW^ݲt}L~ ӎ cGXw1Вy S_)}}v? oV^sbK{kW^]n8%F!K hrM\V`{0KY"ȒG <5+aZO 5x(tt!^*]5f<3a8 G'NL(0U1 } d _~RT Y0rg'yh-B>I^0'Qހbр? 2ZY}Ϳ|k~n.q_Tj~~q>s$r˙ <ߋ0~ۀ1ϛ|+ڧBuq HlM O U*MrqXzܹN]oԉI*X lPD(G^ _e=0 -?i]G8nEO=jؽbJ#|Aq.%#m_w=xGm,r{ԟ6o=yjXV\ѝ%a+WA,$jHZJHZ8j/@\$`E+Wd?YMJ*ڻ:ϰ_c(-ZΙd֯ iԀ+EMK+e"(Bո'Vjd2-Snno5tdRj=s'go 7KmQlymȶ8(1#`AH>.SV\9FeQ֙>9b9! ]'ͯ}o5ʺfmixד#R㖿~|O0ā>NgC-VOau 8lsj0[x^i $.?VGR -7IC;aMgASi֦x55@ 0Lh B0Q!X( =چ!1_A8b^R0gv., rB`Z;ܷI#,VUʠY)""+܌$rQUHJ*kp5p0 i,ɬL! a2ܒU(e_*w\0]/=~BB/dZ~:[v)Q͞!c|e%[#6mIėivVq⦄/rkUU7oуJUR2.O vnrk5bsiZ +aykXTs׀%gš"knS&)Wr$¿I!̇{\fRoz(t&q0HfBX"Jߋ=^YLT'H,~wLxxbH4'iAA6^ 5ګwflQgaC_)ߪTC2dqҍEbu*&+9d.{A٬RZԳyտT6)OvX9" >G>Bg(+4FL4u6ǤWjhe*bGb Zv(Y@:XQ"$TtJy" *,p'4>_h2H*9vk9bӁLb5HsGo;|JɊR\"R/ 1BlT$g9ۛoJ@ܒL T22-(Ӣ4J  ,Nm tz>U_ ~XN+AǶkQN" 5Xד5b n_/Az Z'6P(h@fnk]WXl>]aETT&D |E_1+fNcFІi5:CkH֪t7r1bDB)WI.8*usi_t\oBu K~ Nj>s8}W_s:fƎ^@nLx ׻7H xpX nW@W'KW2K:'d+|Ⲳ褱 HN,S>?Îl}z~~7 -[6>aon3l]\ :g<\-MצnEeQ ~ccSuux^sscUfg.Sd߫؜YEpmNzt/mEc]8|K%u "6U<(2q8K$]+y=8"* yŞEܡ?A<1ZDqԿ_oxNo2;>PCd#.]99*{"^gOOϳ^n4{R]!5dgKqp`TE} Al!Q $LG{)yY& ax"^6܊e3U:ì{W%}G O EY6ѵ{W:|1ۑQ9ѱnayfqvelG$8'flpLp4*{]ZO'?wpJ o^geoT_V:inD{%$?mQ ڢF!%ۯdJQ,j H)%@Դ(` QCPo_#_Bwu",8:["#7X +T|yt^.p yBz>Gq%Ԟ0\4VߪG3{tZ y8Gp|l!)ϼL9b35 n3(KCo"[j>|2 @rBH@A& ! I 4j b}U>I@}rm[kڎ/6bKKۈؒNBqVvUVժU e$GʰyN$"8a{^!^<^(/4:Ϟ2"B ؗ*݃?=}:X/~3 wV4"b7SE.Zy,I(B_Vk7[=PwJK\Y\0i? 󷋏'~dRrSOԌP\`{ABt!w%9B5 =!dBCrI ˩B?<1e|ꄜw']ʰPuXchIlCÏ~9EE/q1WZm/s\Zb [Q0$md %ڲ/eslUݑ* ӽ^ӾH#iip 2 4Ύʨ 'GDm *6! j6ZzqLSrm5nIcݰzxZ'BI> m>*iݻ vZTX`^b14C@a^^sw<%-1+>-VK;iN=Ҧ ^ J`Ci.3>L$ˁm =GS?TгsgMQvܪcK!;l~*yLN- 6ͻcRjN$##G+noְ釩cs(Rƥp9uN&sI,%#l#<)c$$ؔ}A0= &H^ZMs 58ݙ1=@vDw\*M~/9l?Myt嵸v\CkFc9U+V>y#|duOĄ5_ҰA8}nkt־'G|PJ !k:j5&GSpMh;]b7g3E337=_ћu]/ U>^1bg-4%ago^b!8&H]2 *2 * qJ ܊$LCq(E43"EїN9[pl5Ԟ*0xjMޙ2A47"h8gi7]:чy&g?Cgκgw]V?aKsR)2 xWgFqe4Ҟ.z/W}U˚F[a$B m1L[Á[hۉʡ#Jb\;a0[ج6"DV%C(TH]O{*e7PꆺMou] VhǡRc[~wV8/Jr 9Tk);m: {էmGòqb:-}x$~QfKu >J8|~}5W2vtB;gz$%nf O&C_zB0 8ӊt^vI \WKx]n尃25UT?B#xB= V윅?3;qWpOk rqyc~[wa_(Pi2~yGILA8 < <<!ASNNdӳu%OG$ 3voߴnxҪ?BCfg_\B!Z]jLWu~"d( xQBt0D JD$3Y[f'HHu{^6C(ZCsk)9IҗI˷AqˡfLK1)&uLڜSjO\;8:[z^疢('GSl0'M9,%Wlw*ޕ_7؛((s/_{q9ϨT -oۅ7nAY茛B=b\iPS_V^QVՙBIAZV^) G,D>TQN'NifX@ |1_ʗ m$Aۇ*H40"e򪪑2#,68-!4Zc༰<ijj&C@%jm+ 5kߌCx܆M[.mN>{BlwGۨ0] «'斎W0Ǩ5h?@{;@c(wDr"ȪcUYz/̛,[;!q~X<{5<;+̛7;'D%\c7)JpRDr\X\.p.c^Bnr6XZ*Ⅹ8bq:Geqk1 8Iξ|Bg@?0| uhLRy=;6?ħ=K܇ !qs;v:~Z8-~hs_~!T~QzwV(DK))\=PLTFzGuHs`:ZOmb9v+N$=oő{[[mkm˼&_ɟ}ڷd u޵23ù|ܓH'&xRHQޫ]Ht{tW9LӾO9;*yk:s>b+׽z9tjIY[ kqѳ5XsmţgR'Npk0&ȋ PITdD>MNîkJZ@]*#7پJn^~w.s^y^z8xC{z'Nx{NP%^<4[h[{-5x-C+4pB'8rMqOκ 5koÿ~%7)3`~\ZW1$F&q\9it.zUExc>gsoz s2]3jeXԊg>62fTǡݳ]ؽܞdӺN*A95̓rj8 „DHL (o)ipEb'"ɲkrn>L4X{Iӡo3i͋BZBۈbҔ@``,l[C*TE8,V銰LMh vSTmfEFrPOsE0A[g8R#,/챌p)gka 1S(fS'i! kSV`j Pp劀hw;&{<.R,ݩ VPb-7]qWn\a k+k-07 QihPnuLq?E ^{,zdg+D t 9$DuCnsUzwR .f'|VfI^?!D-$JOsHF*lPP [n`FbCCZtXt>;a8:DGx&-%h~UtHC [:];ϧUmA8r~قNTQ/]E=v%J2Kj.2 Yl`Vrͩ\ *)DI(4$w.*,̷&+|ܙIK1݈x=l~h(w;/7} BV^{us^B t> ?GÇ>w0ʳWQoE0{輅EТtdTVЭxmcE[𯔴[#ћ~q!Nj;L~b24bx[H=k_}\>mi|sڭ_N;X_M%}5_ђed 4}ꮨV;m5Ke.jg4r5И-!FGf55DuioiholnkѼsEdFÊ CFw4׵DWD"u :F= ɫZ+4t{!E#SwhkcQ(Sf%6UͭK"7DGf-jnLm^RbPdz]gG̺zH?R\>|hM[WdYݚH׊Hg亱3o^7Z#4_"б>h <iw$Mww-@>V5AF-]Ho&Z[Dr" Ab÷ +h))_/>ޗVfxKg2Z U-muW2,zCGJoXI qZگЕThMKXꄐw:QAK;sEh#[CٳM s@Ʒ5m5^ m8'W0ȕ98Rt>aO$Wޙu5ߚ+r@2(2!pb$R~œ!PZP+ށ]|H+dc]~zy`KgYa\9!dM?0%buPeOrW0uD*s"6C< ~~]~x7w_]nލxWO<Z?/擀{x3Ad:I'. %wV6 P!xT(<\xX8V)ـ+\#^x KRF\-qq#MfJ!,=,=x0#hW7"^Ik] 3ޢ(@+T͆xͮ@C^' /J;#,E̮ϵ_Ԁ X)\__)fs"lsBm7ۚuΡ(s3DdЛ! 7ʛ*.ҧO8FAZ!H+b3YY~E,%(-hmA!Z.<*ڊGB]G"YZѰMmjXԁuD2{FU@}tdz.!ЅoMT]s˧W@xs-]r.mhEmbN:D[ч}w-]c"1*3MӿG5y| ],8 ჲ@'0JA( ?t}Sxƣ>pk~H Z@ވ֣V =G3EǠ_8s0\'Yx>1|ǯ1} V{νߙٙ@B QCZj)RK,"Re]r ^KZKZK61Vcm4ZkxMs}܆UMUM;vӞ|A}mIo y-u;]z3_IΙ\gtv8789:O:էĴΠbŨ@ubLTJ%BPAYj떸 qqq+튻ooOKJؑp"b•Yku.Rknu@=^OTTԑt*YM (9)y0(,vrs  0tLg,vy./ۡelw6gwx.d߁e;l'ln3\\vP%vrsP^.2ylw[q..e;l}Vsmٮ-۳M{1)v[;Mۭe{[=Z_SelWNb,ۙelWs `,ݡu5ZV}T}/~vvs%|o`"elpI|}|V-fCCOEC=Cf2:~ N'Rɸ;㯒J$a~ W BЫlLRi .K:76^l@y#OxGzߋ>gFuL}σ^1 3T- DA!` =JcCy(oi#Zwנ{Pڍ 4;B -"`0c =n o` C5/^oNoTXMFMFMFǘ-zL{SV)-Ǹ=AQ5Q {-1jn1m ӡO]Zh+"t:HhfCcq u1Z/ZKz| u{R^ %Hy ǜHHp߅j=h94Ρ9:V8n.P :Kpy-+YF\J>%Ч%"Kr)% ^F. z!w/$t֬zc?!!}) KJq]K1 Bj_ x8sSRhX lk[wFY,̬Wb[V+'H U) h''ynG6dlSKp]G}o܂nZUy$, $156-C~`34vaƤ3#}Dř*7GQgd;}`64ܿ]oX AU[&1zG~ o12My;1b1"zpj r <cD%3M,6YT-eVgxj2I^E[/Z~6Ϛc2<،g!/,1S;£鰌}澻5gcdLaƝ})n[gUc^2k#9`*X`Tmp ^3dp {_$kQfZjXQכqosi5LstfH! FN? 1^忳Yl4Ҫ;J7yS{ٝo"{@ľ4bu?C'pX8+} EJ%aUʾB?Zg 1V!}N\ |+xZQt%QWb_Ek'i.L>W+Yq6T*7HVJNo] tփn2t/lvjWaUv&z8 \0q=׀D Cpfseά[LV˙rtҝݮE˜]8Vƕd;s/:xHW-]DET-w/p%8o. '8[@ւ߂@'Z psuj.'#յΑZ ta\WC>]G]=#\{8&pLsr1B z|}R}@WmPFWl1ҳ\hӋ~{7 :#0}YzN}܁1e0euQ'rz\0wM"qqMN{p tpC(~(>uscrub{We[\Wy|1h31jt C;C\N׹oЧ77P յd#B׍: 'y 0NX y0c֤ùaT 064slNwц81X5s0 1^g102NFc'u 9~n~(_ooР&Z{!A,NmmGK~G~~++Kg3|N>G??=_{{O~_~CC:($D #r?(J"W$rrTUw rr?VP3CJ*WҔ4LS_t%.+ӕ2SIW %W2LRe2n(g#ebTJRARʔ2+催T(UyNyNHTWjUq)/II6^UTEբZ*ƒj' j$5YM&c1u:VS xu:A Չ#j"LS'SGT5MNS jNW O3ՙBfOj0K U竅|uHxZ-RECu_QbHTMXC-S˄gr\(V+ DT+MR%jZ#jTSrĹb B:L~!h)PAڼf3i` 6E+aUvrrV6MlEy-h?0@qyKUzRbMTIu(Q'Ǫi7t. "$ Ta'/Ik; sk mv\D;΂h{v\WiUhZ6Xۦi-Ժ"m8A[aekZ\֡hik:p)ZPKVUiZpqՁ-,Z18U+*iDm^eNbu-䬖6世 66 Nݭۦ jRrB[(9  Z)j((K"%'KVL}'x}Q ^: b+oRb'Q5~^o'f0*pk `<` ́%%%%sJKr+K J/Iʀʒbp5%NPvqDKVFI z+K6TmRWj,w/ū$/, B/> |f##O+K Ch4~)[G?JOz4q>'rf߇-;W(.*늍gkw:5 rMHYDb,Dx+YGmc1PAB_*a`L2QqobY9@@\(1ʐ#.(*B&XD9RNLom ɡ!M_ZzbxY?@9at`c6ʺvk9bAŷUƛz1)$:\`(NOu_ %;|ɡqzo\h)y%4Mg蹡Yz6JX)zoZh囉:y(멐󅨓r^8B,LEIo^B/@j^R/CoA(C~D/ӣV86 CmzZ5qo z%JVA_ihU+}Րׅ]_کB._$u|oE谾mj_[-}oU[5v; Fo3Ƶͷz|/-s*+qlѣa~?&gc şNѝ fO?l  .y6 cQe57ۏ.ݘ/giE\Q1-;Ə𝄧|E?;] ݊ɼc1dx]5BՎn##F- V=ﻅrB v +ch% հ"#  46#{+O9JCka̗>Dfuih.9Ga6= ;Bz˰M=FV8šiјb|/* z95]=&b6W.XƧ.j#.G&hS)m?3:9x V]hto||D[ !6an 0_{һ)4C #b/|^@ =+fXp8iL(,4Χ|fpot`:u44.@.Cut}5ߔpq5^»p\noE-B{\[s_ ;ɁˮDZh,5@~ȰY}ciQ9o%X .B 6a`j!a2-d::{Brrx@,#|4:AѼlS=. <},O!r7En'x ?' y5DAFF)oQ=^-xOd]o>ɺ`2Ez>aXno'ffSj5$Gjag}H{8ײ,8{ Pa S">C5BEZ`DZ!y&;c%#80 `}0C&uoGΛ}H4"a.цym˸~vlo:&yGÂVF6 zV^wCi;8Nc0!q@M-i{^攻|{wCuhq:V u>$=ӎ{cX~~E_ /썝݇ H:~=[$f[P>A pE1={g0{'ݘcCm +"'W"VE.`wjXHhX5=ashհ3(As<#g<Xjg1 7/tSo(zRWyreg;xă6s)7ZЗ 6Gڸ=5lqrW5:GZˮ`s(bl<<47Iڧ)d'hoҦ~09seDNXznʆ[Z{V46FM1#Ps_~ÓPtҸzփ+nS0ƍXCvSn(=Ӌ[mz4 J=1WM[ֺ2EG3>hH+aF׃'h@CES{ [ :BP7/G{fMcUx傏f{6M'XoYF2e\c|n{D@0#s$8ǃx)ϥpySnƢpkG1v7eW=/|ci{cgoU#Ewyk˷;zkTGƱ5ŷ!z4*2z8 mUkl[z;'ݹVFiѫ޵ӣ7ݍԘ'Ɯfטg8Yhomg6O2WlNssӤy:$z&͙(b+,FnΉܛs5Rh {*'H|ig% jmb[Vswo*FeN wEEn,o{|XX /bخ_Ns"?chմ{kn lli`eFO͏+&/o*_Z'.HOąlW|%fRQċTykc"";}&R5:"obZOߣgh#ꡭ/h;-WMZF' 9H^FC(tgUhB&Tx[8M[j,/G Аe YZ--\%rҪ (;b7oM٭(*³x·Y' Saac|8~(=~.8~8#/ĿMrG 'Mbsbr=bKL DZmNZ[mm϶ݶm( ie5M[]d㾥8[ĸq NJ3řD\q. bMY$EY))'>#j/.RX!~ƈ//н[tCW }\i4A9dtNeLR-זg+-lEm][m v؎؎N.ٮnɮUXiL{=>ߞo_hGaooo1a3"}}e/WU7Zaﴯew~G0l#8{+=-D|I_ 8 >l}Y>J33a}ܚAX3TbͲffͶfk5J_WKZf-|h-fr*ɰr*Smmmmmmm pvvn'Sp9l{.y"^iٝvlmElj[` s_&a-?9:Oһ80Чr/޷yj 9W-|x7s>"0F/{ 9Ǡ p& g'"~gGmUReP %SpC0wxrZsoFx˙>Gpx}}Z{XWmTtA19'܁kg0Ρ5Yy΂@ _%AK(^z]-GuPYE0޿2_LL_Y9XtZ,/Aw(_y>{ 8Ͽ781Q[:j_ujꌪC#ƪ,^3ש:Ak"cTǷ*5H1?WWY]~ܴDȜXX״U].Q=C_CnV{nUW0b.WCLd/Rp=XmBxpI-:v*X?\bp%⯓nrp5k&op?LFg9l5^ëb{9>U<2->VeWVeQ?/x੪UŪU`wUMjQjipjy=h;ւguj3$bm0v-&~nEt,u.w>\U|\\\|ssss_Yhq(: Nڗ'K ~2v7q[*~'ҝ9:>#&33WQMIDDž0gӹJfNy4k]]jBw{{%>|p7qƶxԌC+۝4aGf]-'֓@YId׉,~~hC?sUBA.{ɵǽו>~jrGi\*ݧg]=ˮΩlgZOǐjS~]-=6a+F1IW>܂,յVe.orG9}GƔx-- >Ox:9;|F1 WgntUzx qszp%Q$&~XTDxiM(kr ss[#iS dҕT =ڲϜ Iooڷ[$j_oI>ooշҷ"KvzQ^Y=5<:NqL7C+eŵKvPKE=qB_/HoOߐ?:[[ߛ?y//oϯGW(d _4}!gоb.,(zϋ!t܂G/$_A煦Bw71# =2U+#9 t#i<*q9c,^5S(}6gN|aC(~/\7W-fw?h Cup5WEAn[=%#Gyamxsa+p6Izߴ3] u_`Om9/߅|1X()|d"D}HR~Qh19ﻜGwx?"!#c6GΡ9ZeYn_(l6gl[!_J=-Wq]f] >zUj-&ZFTO@Hh=&m1ֺ{u3c(ga#wnkooy3^5#XQ:[qۧͥ*=(l7uds449!'J1I:x `m7Z\oNW0ҿ֦'Z>9W)^Sj/bX~HNaW$:Ct5.>q,N.!y\N4g*|xS QNP}S{vaTI#$IBb.1ۄDaЈ)SVOJ읔vR$7񓦦lKT09 6dcO䟐EE!mr0?N/L}:!荝<%G3nt*dS'GeB̝Xhv$:&f; Eӎr9Ǭsvg49*Cu3;+Zyñx,2M:LQFh #M'1!&Z6۱;fi~aȧes?[H$M}Khet4[)DmZ#K Vy!۾`[(,Ŷj[b{Tl_}YD۾f=.lOÒ o% t>K&Sgg#e0yBR>K os33SR2Ӓ.7&&dt&{[HTq>oKI>SSN%L9ԟԟqɋHgFrar)ǩxM=;lR/սlM:lM%:QҞiNLF#cJReէS3_Iz,63Z/$Yaz#ZC?I鍙"{ʩHL.I.I:t9vRUv4c(2kTד.(O˴F n ڂZʀ/ھH̶\=&ֱ>/R^oOcR2i+޵+Ve+K9!=Vi=Bh-{tLWdz2݆L#ӣ)8X>>L?[4C^KAvZۨ%QgWbQOX$ K&X|h%cnjwpq4qJ-!,jQ4-b1[}Q۸q*k ʖkhmFQ^F2ʣł߉t ~/H, B:Ē^ l>P 0OGEb >3_K(L\QńބB=ݒюg.Y竟/GlPme'm|mmÄ́MD-bnB3-ssؒ=ķA'~mb> Ϫ8XYߧJN؛13U}ɶ0G㯉w&Ȅ|&&$2Aބ<&&$̠r/YI'd8P_OZ%H\3?:JfhT p?!VWufΗ AI|käTuaD)U0]YId sA*~C}˭.Zٞ~y?<((ͯU>Fɯgh9+!b|Q(NSLW۴GӚ ڕv忤3?o6-O}2$ꯤ'>Rt&Ka2KN8A&n!3LKQZdu\+}Z&St~ r,Lv"Zʎㆱh<k5W:\¢j[vGT7"!ό uo_ 58NT{=M+0n71n1}1e\̸qSstČ%,$yg4t,)gArzhF,ؖfIKl nOx2w:HDwQVlZ+1Q;U[/D>17-X쨶˱t=~Ul?soԱrr6O;>֊=>VwIdMza5jm¶v|c~F%lj4c{#j0#BRV/7TF[KHQi\5 ;WATP=pC?dFe5#(` /AU7Jt57U2JyxuQ1Z,}7Z$NEYi(=VhcQZ I"$!QkQ[ç1Y b(X'͡7a٦!!#oP[=N&oa4\HW^%? | ǘ7}dd7MQc~)ZgÂ.Gލ)![H7@:wGE@/00T~*> q =yNe~G~()y #]&.:KrX k/ӽHd)z}vAsS3v} Q&'KV^F:~y:r%fuD*f8$sDVdl_W&&0l9Q$MJF%,H_~ќ g'?~%lv@2[))f`-p!fne\a<< y Z)N|@\ /t T#i7Z<>Cf×װ{y0|{a$9E/1Ү%](=B¨N%0 6OV 7V=t $)d_ 䪅\L!`T7'O~ǰyx"yv=:q{T[X%'ghf䝤Tk1BI$q]>TMbQ5!u mnU T#xWyV`~BqkWBVsy('NazKY"婨a!w씓n:lQf9] XkS;^3i2ոfZ ؁s/OUjR'45|uO`O> Fi w1]̞ZgE]gWٌç_#6|yM>K2UsJs|x(Ry DXf| xX F۱F<*9 |#X"6kU"fXW.mk@5w VrSy1G:0,h 39U#|hS,g/ov[۷w|)(m;b3i+9#0۰ljXIy`p7J7@R )3i3&|t> l>`<>+OEeBκ7XB$4UD̂(cW|>3[0OY9ijf\I\ >Wa{ס0?l1 _^]K4)ݷ[O׀׀x/+p0-2$A{>NeoOo|12?by_ Ё92;@fj̑@zx3..PdU{-nj6;dBF6b(e5 p*V-I w# 3U;:B*v]>_eڠ>l|Vw_< ܨp͑i,,+HPJu3CMmbM &QUwp5Yq#V]!ZR#p#݉U] &bR SXnڏR7o!J'Xüy'rX/.5¨+he_uCʈxA-,I+y{CPa"w"zWf|J 3m`ш3XB5ҥנѻQZ٠Rqjޢu;!ߊVaCkh_;:,R_QW{cX3#ϭEm=$lb4c]dcawQ+7xe>V͇&HH+K|g|UjcW/bFa'jAsUϣ:W`'Q=(2Z@ -̗?c9j?V ,?Z)M_6\Gcx f?6e: TdcӐdFPSboIe:U!Qf4EC|$o?|:!7S @H ߢܵYs o?6$A9Z{Xam *@oh^EX^ YŰB|A)q]}v oŸېQiKQ*T}R  1~9t^/Ӡ߂H^8\bsÔsoѝ1FSC9qU~x,WP C~x/?AH GF_=!7[y10rH]Q.A $,<~F jɳ`^G|1 ip0_@UF3ZW0j Kؙ'τ}:‚΀o|%?]'BrIja*UVfPKTfM@E0Zh>ҏC| 7O?NM.䷨*ˀ9Ÿh~ @FCr,sKC06ugS DL7@fh{Bs>`1~4_`c,lA+ΆqJ&"f/E*! bb~߆ #ȡ#B~ v@2yC!_yw;#Fr:f@g/pe2]d!~20uQއI{4B/NGm#9q]|'2{uhW! }`4goxZJs iڊ.W17@RFX;_ed 7ԺߢGWG Q+^ (M5M#PR<`Gʌr%kԈA6.!9_3%' > !n}j􀓁(fnހ jRr;{(XnN>;}hwVUhd);Ǡc"$ x;-j3 /*נ5<<|ū@d!yTyIKx27Cg2Z|u(rmVxYEEh 0 UpFdJm%r;$-Oڨ3Õ>*=|o<ZPy]PO1)RS5ꕃI! Y< VDuF%>4BsrK@D!;t`^t1W+z9>Fw ,[Z+|*x)?W.b'M]XÁ3=#T\hmF0F bߢ?NfOxeV> `=!ʈO ?^43=sR?(=Z;%ڮYdC}uղ=nKam#GQȽŨ_M ڽ )ہ9O#NφCMp34%Z!W1[)w '8/o wi>Y_^ ˗(X8<~?[?1[::@r|"twc~6[!Õ0^!cC߇ڲE\- 5mބqW2*%_uZcDxګmfZ F[>~e~, ~0JZ>XK(*nj`o 2oAvY0/"{4"GoPC4V[l;HtM **I@DD @5dPĄ `U"bX֌kVT Ú Lﴳ~w}y<=޺]U}WvL+>cߐ`1FE]=v ŵ %OgDO-+qu`7ʫ$/bQB9 کA]GyY5Pϡ'(EJlU/Z[r$lsxVJZ8`5;q\(غA]FWXH]ir Jס}R^+>%-\gh,IÚ'Xu xiČ@鉭KQz_i&֋Xo}T`JpTԧbC(7j[oK^4E.QVQYq!h3-`(k?UFIV!JhJstžh-܂,~GT@x]phy>RjdPCkKDxX/)m. h+lZ%J@GqOD \\qwrFqA9!Or眗zfd5๵(kPDL _lE/šX3[x.^:ڏW3Y ECE0=R<xW5 ]nm( ac!8*1b M!q0Vۯ9#!-Ё`S 'A0=v,-d7%hGlKmaXHCr<(׆DȘ؉r_L\L2By"&)>΢: Ƈ#/FF@ Y(qIP9 ΎC pF*7!FH>X8B k\ȇU0M=gYuogR|6f+W2@_KhoʴOK u/J-Jm7 ?B|c 086":\(L1o0Ba8$x`B l}pN% 'p @;,Vrb%ݬȴ=XnTŲXQ&>,Kce;*f`QqbůXnR²Dq.VaGXXnTòXqMX(NޛQ ]Fi,ge."[Bڿ9 2$d.J\٠"sU嚄u ""7%DnIܖ&!rWB䞄} "G"%DH<y&! ."/$D^JyH<歄; 21$|>J|p,EBN#DD)S#Ԉ(RFDIՈ(y5"JRR뿀!8C T'VjQQ jDjDzjDDDjDՈ(QQQ6Q6R#lFDie52ʦjdDQQHJITi.\BRJgD%DZJHiIqQI8""N"m%D%D\$DI""n""%D:H!!=Lg52{y' T /_y>>yI/\D/$iL~W$mp55I{pc00 5#֌Tf[njF鷯# OUI|9j~fF53zC͌ifX3'fFUUkfb_f/g LS)-9K,f3f Yjt{F4Zw(/͈Vxf5Ϩo[[jv-o%,)p{9\f+suu2[QUqL[ivFhYu.yv^Fa!w g2g\O#NSw]XѮiFh75-v5˛=R6qu)wZʱL+`';j ;[IX(G/js-bq%fr۠2~!bާ/}o9k(⊘m?JR+2rWD?d:2_Ƴn p\>2 %쉿·>ĻBpxMX7!x38C`("O!=q"H$S429$, IYAVul$f EJr IHJrg6Ԏv3 Fh KӁt( QtIt @'4A3iFgY4H\G%4Bh FwtOGIzV Noѻ}F_~u<_)ns9o[ּ oo˻n|ޓa|EgvxA[`)X 6`'8 .Q, ݄Bo!X  B,Cy Q߀c蚱uhIZPn֡ i8%.xNAA)dO-MAL'A&A`1t|zlU@=2A,%K>YNC3 JCZEАFhVm4f+M lK[`V08rRfle+EhV*XUKw'yL5yJBK$/"U`˼Z3O;A= D;=^@7w#.D?e[yL_hǼ?2n{;PhO#i$tqБ&DDSh xt~ ™߅>H>(h?ZG ,AYLԃa Hd&|HMxbRXXx-0E KI,za2 Nμ3dhr)|{=dN0wxoY i,ʆt>|"3u6lY:[ul_t~}aÏ, a.D=ǢgrYT6` y` YZ"6E-,aj? *A K7  ^ /,X!zJѽa`EX͢{0a> ֲ(uB,,ڟAiNZq&L2,$?ed%YCdُy%r&wCƗh+򚶢LڃtLpMciMci*]AWnaAzV^h%C'oxuCڃoH,f|,ߎ3m(G;:;A_0c\셶A|BwW/  BǮ59 dfA6#kQ+JLDBFAFt!###GFjdd2Rcd$#d&HM!# "!Ϙ#4G@DBidw \. /) c%=384ķv_=cwmpWN&Fc+L%Hw2u/ Ue4kfgӕ)ŒYUWN&sQiRPڭy\A>*ojW ucLnmM./hʐSeq}Q/=Yl6֪V<'1OlnռgLXb|R|dO|bXݹ[Ccvb`{{dΣcǩL\UnNO[GƺNЅU?U+f79JBc⢒0*=Ra>2>.Ĵ,Ukm{xyPLTjۧ*Cf,LFd2d21n![:opV¥ۘfGF¬_GZnV"ܡcJsznѺ𡮥YEg4y~Iд,w}V5Ȝ꾴_K,;-a3jgN)ޙST5Gj;z6MC玍_k];iwɯɋ=yz3nc;-=-nv90odŁZOjٕ(8e[AٕTT NrA+R DBӗ:2&$-=sN.O[F=83=<կ6-/U=q2Y+T&bHڡ%}|WRrFY߄=bBQ{W hl;zkcOn[9r"S^[rxβ&nl5Ith^m|J܁=ίߥ7O[a3jۜ CK:\gǞD?usoMrΆ/oo]ݚpi^VN+,} ~yج~M۾鰨0CX̭v;|&S um|{< ^St:;1Eqx1DŽtB.mQ3 ǝq]$GU[͡*}tq{kwwS)UM藸6hD^`YI{Na ]58m>5!dK{W~4VV;.w=#КE5yzdU3nhT7^8;;՗nvf{N,/ϛ;vRwygeķo*%d.lMwXo">mu+>.sOwŠn TO<-u \c :YR>`'J^毹(vK5syY6M}d\>zbԳ@V!oXʍT:}f*BB cG~]C #bZaI>AY e2뱊˲ 3 F$~c)OcCV}rŧhVţKFrOxK x{3$$]|~Ue<տH4|V;ko/!d|EtK}V'_ϭ!gÃ;8p.dUO[jӔ Yd_l|){&?:(318(XmMMϿ@?8cܣÄDf؂n7X9kINL뎵:lշWquczyvOlVH+^N%b쳔T5Yܫ Zտg6`|Ԋ?s&iȧQ*R;;:1##CF& ׸y2:vڿSPه"vN{{lNmvsg}nmޙvL߿oѵc"Ƕ|}˩_`x]/o+n_6hڭ=87e]˯ v|[AÍR=^\>&Y1+Yv=1uJM46ng,,m/aN7C~-4OO_WȂ+N ђ;9`jn\|M CG#絤;21o2Q]EݳCg#gUM4'rrT`4 ̄& Y`j=s(dzfL .Ԣmv j}unޡY kܧyxe̤dEFZr>z3x:qeΝ:]SvgmyNw ;Ԯ¨lmT|ڕmϪ?:،zDsfJBT=~nrwz5Zxy^aBi븫7[ipj TqyN;{ XnGk,O R˷35=+T)sQn,ra"rT[xJHZZM|b#}ۻmVۧc xMmċ2HL JfK^YCt?]SzP-Vo2šULC\v6ey׎.#Erb~l_u^کݍZZ)?pz=x̬]>6%NO8jhݥLJI[X†kmrBoһ>֝<Z1Sexn>)+{%iu{hgC {^pjPA +_;7vP -rR=!1BN&Sgop##⧓lZQ9#G=շ khN;2WWNn >l.PE~s8@տ.zB A"㣸HHsqjP-N<.!>*1$!zI!uTkτ=}O!Mw*أYuz~cbV{K[53dOU㛝.W_o;- ˇiWj;mS-К\OUA[xc`qA#绺R"e{=nwtK'ulr5^*R?\xЈfvŏ|{Y W-Q^kFr]VX11ɑ/7]<$_H҈=K +4:;@'|*k*vwG>;Q}:?15-Ա>ppd7nmYgW 1/Aդq׹_>L*?.|PFXݳNB<|B'O7D(tMY߄_hrˀUd.?X/^R>inU>wϦ@wLZ>j\Űܪ~jTmVffۜn͘USBލCgEw|Vuw޽%[<sۣRŔ)?ij"V endstream endobj 4366 0 obj [ 0[ 750] 3[ 278 333] 11[ 333 333] 15[ 278 333 278 278 556 556 556 556 556 556] 28[ 556 333] 31[ 584] 33[ 584 611] 36[ 722 722 722 722 667 611 778 722 278] 46[ 722 611 833 722 778 667] 53[ 722 667 611 722 667 944 667] 62[ 333] 64[ 333] 66[ 556] 68[ 556 611 556 611 556 333 611 611 278 278 556 278 889 611 611 611] 85[ 389 556 333 611 556 778 556 556 500] 177[ 556] 182[ 278] ] endobj 4367 0 obj [ 278 333 0 0 0 0 0 0 333 333 0 0 278 333 278 278 556 556 556 556 556 556 0 0 0 556 333 0 584 0 584 611 0 722 722 722 722 667 611 778 722 278 0 722 611 833 722 778 667 0 722 667 611 722 667 944 667 0 0 333 0 333 0 556 0 556 611 556 611 556 333 611 611 278 278 556 278 889 611 611 611 0 389 556 333 611 556 778 556 556 500] endobj 4368 0 obj [ 226] endobj 4369 0 obj <> stream x} |չ9[f2Y`0$,Y0B&$dA#҈UԪU\%Tj݊mVm] |9dqyvV.`,nL)ecx{#bV4[ocCQ5v/3vԵ7}B;c#̇/A}W}cG}~ c `o=Q>ב! Mэ[uS"rX4:E{[jˇdzc57"19ʾ1c-mC FHu]Qơck^6>93mf"=?m_}y<ˇ{0QB=#;=_}ˇZ>I[Xyl13hX! 1 \|J݆͆q9X;Gaf8 uSzz/c Ua>jZ%Oe:-}SDO9~OW?t)%xVC!IyېLɔLɔL?nZM`mHdJdJdJdJdJdJdJdJdJdJd.oER0=[ N+ql!ǞEc=1wv/Sf&<?rm4w݉ߑJy(_mpK ڵkNYjeeE`yK/Z`sfϚ1iSL.4qBar{S]Nj1NldJUy9sF/C*TvOL=;O^ORiF>5BO+V@_Tc5P<-@&'5Ҭ5ƫXҪgCQ#> kLJMPN٧0C6- Ɩ,(-Tj6VŊc&-mfFbUZ_mpuELD.]iW׹p_IlwPl4Cz_c\Oo &,\gLHaB mC ѿіX ʫgʘR%Jw@tʒU1UU?bꨑ}O.\kC]1 ?kхVa1 K+bXo99WhUb1VU+,-RKJ"oil\ϡ}Uql<ecRJ*jb*O-gZɉ+1|P%+6^Q-EMfB*l7k \.-+ft4{t[B]nQUxr*s(}G<6rc>\0M#oѠjiO jH40۩H5b:"].v.l h&1Yj-Q+|!_kȿBM6}󗮬f;J"XeF),i|ov see/}LBys,+ TZwV5L1|sk|S)&_DIqX@?KI')(xWK;)ޑm)ޒM)ސu)~#kR*ůHK)^R$A)^)9)R<#R<%ϤxR'x\Ǥ8 ţR<"R<$ŃR< RtKqJqwK_IqwJqKWۤUJq7Kq?F)nz)HqJc)j)bWJqKqJqKqP 8_R'E?bJqgK!=\^{py嵇k.=\^{py嵇k.=\^{xD y.?\py.?\py.?\py.?\py嵇.o;\vpym//nAӽ3A[)wV|P'$:#>BDm" X @ʢk#YVfri"j$ZP :(L@TOTP Q(HTEh ;rV$$ :hQh9Q92DK-"ZHh>Ѽg.h.ќgh6QY3T,͢TO4M':hyN%B'M"H4'GQ!M (DD# #Jr)"` CR=/ D',i<7/0чTџ>{D"#rR;DDo-7 z\~C׈^g uKtD3@x*>]DwAt;^8DPD7F'Ct**DWR+(w9eDR%blхDO<ϣ\яvKtNwWm@[Ίθ1?3:h ULN'wׂ:F DډDm:BO#jk@-<Jz DԲ:"%j QZ5SeVQWRJzQEYNTNhi<ZOoXO{Q<}ha<}h'Oǽϥd,* * *wf@3D3DiJT)T4&Sg&S+@+Al<ѸxHXOO{7$ʧ`#SaDCrb(`CT%D 'ʎNe]k@qZP(QUH .2:RDv򴑧"3HԓQGq"qV{:kGޯ E' 8 (3RCJ]w`;-6o^~X}1kWy_/C‘} 8`{}YC?8#}$>x|xx~!{=^ݍŁ}@ Ӷ{mv^ۀ[77Fyuﱭ^}-kFk7b] e%Ũw.^h]Z=zwٺ\v]w/n t83%p-n2[nyc?h8}@G`C` sXrZ`==ڮm%|t;WX]m٣Hmo$"K"XD?59QX[{x#Wi@ޖ@s]ST40\Th[+ jڢSkX]2j@eQEd(Z](/ZXwi`qѢ",;?0hN`9EeRt p P\%g=<{Ҝl^8d}aΙu0Kg Y<̿d3 Wse,\^1.9RC܏;=N3ś?e̤2PGCw""/Y^ymJ`mMfmF1W9gҙE+[}?8~[^?̖͏r_2fc*q~A>/V˟}l=+:!B@2ج5mm5X E._ş(i,;ֶ!E1ݵ1%=vVlg`3p: 6@;ڀӀVhF`p*z@ P *`-8X V@p2ˁr`X, |`0ʀR(f3?0LS@0 L〱`4P@>0 y@.0@ ` 0l 27ҀT8`,0FgS(k+K ߁ρπO>>|>>  #]wCo77ׁ~xpxxxxx9 43I q1(0 p?   >  nn~  \\  \ \\\\ \\ \..v]9٬vf'csϱ9?csϱ9?< 883 883 883 883 883 883 883 883csϱ9>{cs}ϱ9})kL2v㾕X's({UmPv3cWv]w3~|s@!cWG'>:zIh1YeXƏ|Ly\hVӵG:z cdjv bA50FfkdMY5uȭMja@EY;[-eivF6f%AlF&-89mՔdlc٘sWuNoۅ"v1å2v9jv +4UZv֌( 4%JbO{؝.v6559.ub 6oChu%z}jOOB l9a$vri?f;*eqMZ u؁SP7@N}70hJ2Yn{6ݎdwh3cXgwc&en]edߟ{-؃X!8i#-hf bOz=Ǟgϐ{Q|U{GKwY ɘ5l N68Et&l[s}]Rbez?2`fzq_3|M0KG=t>3}#oN\x>y1urw^ygh!=E1ҍʄyǍ;]0>78El'N7vKs_->bTX103a4(FMuʝV0Ф3uiؤY7~ݔ:Н10lNj:!˿R*7~u8u!+fEo4v15g g?ϕa6ڇ>r{1XG2nҘnNWGgZ w?LC5~oM4dn͂pZe͂zaC&.ee: ÖziC@J˜:n/|%Gq^:qRǍ}JTO 5R{Ŝ R28m7{3st6ttrt67Yj?HO:zHo0slyMNO?{d0f}W&d5bwo1u7mƂ9?32{gL6d1*ŨLvFj7( {.L |ab5'6oSf<ԣO!'y㻹~B1HWc8M0͌uN=Iw)u@XXb#'O/:)mDO[tϲq <ϙXcDt"tvӘ֓?*-nu[ E3DQcc il#vQE1ŹC٣'Lhdf trgN<Б3d]AŜ^`ґfnYt:ͼmbPlZR<)9Ӱpr!׳U""]^EN'$|OI>'$|OI>'$k'6N޿]Q`&ZSyh937,ѥ%e&&%@ i SuO&Uoc+t&OIhr^F׽XSCBsf2] 3,~efK-6T3mjIh sY%/|޿m9;|E?ZoI3ig4ΤiI868q&MLƙ43ig4Τioe*F1DZd6Ea+־9J jf(llemZ.{=>kYz- VmF f/m]}jFZQV>l%5 ;>h i{}}̈ UK^G JFj4K11"|K4j#֚he3,M[)gO SśZ0MzmwSw~ZN8;4fUk{s_-VkZܷGb6j/CEk"thО-f/OV`zk1Z{{CmO!)=^ F6/kВ [͕(=0z"r‰56Q&a}JjVx˺9cM{>[{ʥoH[; QÆic:>ZZ-~O+Qgh{$Bwh+^ku+"t*FNXG:[mxZhthۦ06mQmU!m;BVkuh=3Q7ҧO6&Ćķ彔5vm k{XVު>UisbeQ)vʉ#){MjE8עZk;_49]S NYs"{bjgVvv4Ɣv|KzE][yZZmބzFm| ű=QF: jeoUǎ3V]EHkK$ 43eh,ՑnSjSKm(ҬTԺ`SC6mƐiio 7׷-pPVi4"mܨZ F#65 6(Q6Rmk 5VhQ1nEPmMmݢوزAm@pSk&ըZ*jcjSZ`zQ41u5͡mjSCiG?AїHF`*^7=ڂ] &z暆` E "_ &=nУ`m)Y'z Zsl1֭\ӂ7Cm kۆ!uv%N),ܰaCAWhGkK}$QXki%\ _eK;Cmo h(VP)jY3Q2v ᚆ>uZTňՆZ1V0jj-͘ajZT:Y:c4w1-mHK2j [dŞ]۲%hsZGw1BG[ۣᚐi5С3LֆX֍7,v7bwV֏zz3/70> c~>̓Xx̄} ͆pNG)싎%HNyKc1p "zn4z-"bXb?tzڳȭf^ݹ}Qa:\ztj܅dq@Ձ*Dszڅg;JٸblZ4ۜdgخ9m>ۼl7qEARlYDN;WCM"=]FZ3 ɝO|aij"OC(9a<Л؁#w)j:",>ZǦ4͸Z/_6KeY8Izndqvܚ, Ve]dlB^l*ֿ#r:!7D΀Gܙ7U$7$iT([ (M6AYT\X, .Ae)`Z]\qdA2:2KY,شa(m )񶴥6V{JA<}]}yzEfs6"o~eˢh0>-v9a~ν2?ךOW-?}Z~%4Sf}LՃYI;AQ),V`FG oC :+i-Q-GֶkS|tֹ}~gwH>Kgk6rgOyc"9_OskXml-+P lmo`Xěg0aŒnz9xV{%YփIMIM֯YZuC{烟,26%/?QzQ fxn&mJk z(O[R{DB6esK1S:Zw>B9f.*C$w6eYvd)|tJZ&ˤ,f?]sRZZjNK:'ԭF9?UZZO{je4)Ư6mpޣZ˔Z˜xK=0CN=!}w˿,gQGyY2' (G=)2x*=m|2Q*Դf2uYOUT=6U羚>+PzM)NL[L[1UvtZfmo{]fUzW݃);浟k~ί [0a /Xy .م[6,ݰhO/xWXȒƥ^ǖMX֜#̌̅dn,]koty .+Xq9+(]9p儕ܸrC+߿OYf+Ԫn^ez۳\ٳM3ŘG_?SZf3&;'-陧M9{uCvљ2/shm)g.[ǬiC:ƤM7x [Lc|٢smyWҦW|̸o>Wv?e&D2BzcYάsV mց3+&?hO9˛P;i7 ck/榖e~Ȝ h6uv<(s\ʤJ{Oˮ̮5FV`,j3"m[:fY6w>BV%^}N*=ά@-Yim6 l1Oד{x OgjJF}{3hە苹j6+g2-N?ku,N-nGR&П7T34Ʃ6#-#P%SzAI)^2jxfTJNWآVՔl`{O3\1dqV30sUjSeu3bmʏ0W6%ⶖ0Vk.+)*eusemr:M~ޥM1ܻWZt6.I'sSfzynt̳'2@{vPWo|3;i=T:so;%m lǴgNHrhqR6һz\\D#Uki-#F.\{fcfyQHU`-< <O@=~ P Rr8P Ur8 ah!qq1fo )~/RsVRfa'[9fR}Eb(R _P-co@P'rOd1^$ i2%0pT0 a1ߗA&,~| M|.?"lc1[cVcjY41f̆al1b2i㴜qZ8-Wf~pX:ړu'hwN/kevzY;^N/ke,abXsE"\5e}yY׼0kc%%"/"+ _#5ֿdֿd?L9f yY^#eZ7?{J>70W0/p}lV9NHlӽOT)+Srg{_qug' | >/e]Yٮt.R UVW1yl?6+?n9 eϗ] WpB?t\ec rahyq%i*+ ؠNHDp<A{ ^g2tv$n'q;AwII^~i<A(͵p\lwr.|0p/ VjȆu\'ηA4Y`bM( đYKZiA XPǂ:Աu,԰u,(ci/# t.R gz…^@_A޲@bCp0_( W `<\W50z&$ SeI.Znip3+ ,YcY!!CG Ӳ < zx6 s l7a3+e+ s~+2 ;3ȃ ȇP{YdLցd8Jf6f<3ƌgcƳ1٘lx6f<3ƌg;ʻv eC>OB.| ;3ȃ}m_ w"]'j@WHT?!kOJվQF/&9=b{N,mW;cƵ|'@?Ӝༀ{{8>_Bpۿyng/Zl2g2=B]Y*]]O,vY켳OB#h[Na]}U#4hv^QVhgAFQ~4j`%2j#a X'=p#0C.%Δ{g2< < %xg|8pƇ3>g|8pƇ3>g|8pƇ3>g|(P(P(P(P8נB*dnTDFi> ]Pa8*tAvnڍWQ# 5P# 5P# 5P#52P#52P#52P#52P#52P#52P#52P#52P#52P#52P#52P#52P#52P#52P#52P# 5P# 5P# 5P# 5P#C8ȅF"v3Dp.h>yhS6萌}??~ӏbQL?G1(o3571\{^mz|ubX-Vʨ~ȂUxr` <kbnt17]̍.Fsb^t1/]̋.Eyżb3fw1fat3q c7 3vÌ0c7L5wk]}F5wk]}F5wk]}F5wk]}Fߍ9ksQFD~Wr 7N)8ųvFHI_f!f]>]>]>QUQUQUQUQUQUQUQUQUQUQUQUQUQUQUQUQ0g 2ߜEw#ԙ;>GtY^6hvp \$y:@2tN@WHTe-֢a-֢a-֢a-ֺFBhX* p-\ 0p'w=p/0BXa ,e aPȜè*VX7zril OD:.p!8`dX+Ί1T0:+ 0:P?1ԏ~ cCP?1ԏ~ cCP?1ԏ~ cCPQQQYtV9UNgYtV9UNgQ71ԍn ucCP71ԍn ucCP71ԍn ucCcn)m,4]EvI]ڕ}BGjG*||C)#P(a027£ (G< Qx(G< Qx(G< Qx(G< QxUQUQUQUQ#De2BTFQ!*#De2BTFQ!*8<qx8A<qx 8A<qx 8A<qx> `ON\b});Νg2j=>CBSס]e k+jwHDZʹv2>E<2sGy-ׂZ$X3R5:;&hG8!JTTpLhYΐ}0Gq s{%,=;X1Oҽq,u߅I_`ȑ܅\;Ry}O'Y ]Co>\+y{ayR</›VLZO1T-ATASzUKQUOj ـ (ـ -*j5(X%(Xe(X(Xe(Xze(X5(X(Xe(X5(Xz5Wzi(Wbi(RJՠTJ5TJ5TJ5TJ5TJĕ*CPJC) D/6|w(UwgKkd k#;oXl<.RrT:ISܩ^y5I_Gν-UJ̔s#OY%>/cq_ i+ici4ci opSyZxkjqRs75ҷ0}sB9F"j~*wS>FGjT{=s>Tz''N5Ȭ!CdU by8Jv%3dFYQAV$+N'Ɉ##bdD#bdQ;s'q͘E6~!ft=awih"JvZ|!5*g'}bLr5d=w9Y (Ư$o9%NeD0z: )tz:o=]n&?\8ؽCpX#0Pỉ!ΏQΏ1> _#/τ'NvS”gOv2;b ;yAώ uQ4K!!{y4^2LNs5~pC'{#n͞ӵpG;30& ¬pMpl6%{<NNiL4])E^Dgu׉"`X/֋,NԫEz-/D(jEZ,/VV+ET SAtjEZiT QV4*FyѨ%4,MV-+ZtY--D&IdhTRujJY:;Jev|_ov|^k^kd&.o˛ě㢮>1>eQvԫy]ۺζ|պOZ'v.`j-TOytk1xt^>7f'I޼dlWf;n^c+|UdDoc Z<ՖTSQD'%N;\wg`7Yⷲޚ@gw}wf~0",;ͼ4:z,E#`vfiff컝}WWnzݮzXoSoֳv]B_<_T g֣23 J;O-RL-1=Z)vLV`x <쥎,ȢizZꦅinZji1g(*&6g(h&ZAK[ohFc\i+=;BNןgYa#a=JO6 (7?j+[fϯ +nZ35Z3K5Tq;fiffhffhffhffhffVhffVhf樿y2U1g ` j̧l*[eeYsi0J<̣8|'S8 gp2|s|%/t| 5^*{%<[*^xoEeomEí j/k !R_W^AeWPTvE_~hVyf [SG$')ƇRWS7T]XR񤇄E#qTx6}4N'1"ܒ]5KҭhwpKeyL @)VRUȠYԠzb?^8'EC=89J[UD~с胾8GhcU3ql|ķ\xѸ03+p%~aoÛ9yN8y=n 7܊p; {<X*VMX lu8BU ` ;؁wIx)_Bx}<>s5Ϲ:e)As*ZMtknw.#Gwb1X y O O O oGЉ؁sʼn\qbnrSKI2F;AŒD.0~{*-yv[<Ϝana&E3%~kp-~:\|thֆVthEﰢs+:NJαs/Hd:٪N f>YTX'1c*6Ge2I|S7?JØ1Q1eL>ďI$c1^/~?FRj"RꞰ,uo/K0qVcM&ic0p+v~C}nX>gaa̱s椷DUtA;ò}q?!0Jc4Jc#00ib_)aYUYX97\97&cd워}o27&܌[`p; wc:0d¬g$\ɸSl[sw]mWgqVgqVgqVgqVgqVc1Vc1Vc1Vc1fzBſjXb=ҷJ,[)Q_̠/gE,P @(P @(P @A;@;hZ)VJhZ)VJhZ)VQQQ_C(1?Oq)2\FEpth:\4͈4#fDӌhM3iF4͈yImw&yImws(Q?˿˿˿˿˿˿cE뱢hZvZЊhhVtp>[d-gE Q}>AT@iOiOiOiOi_Ooސr2QN&D9('dLr2QN&D9('dLr2QN&D9('dLrjjjjjjjjjjje2eX%QFbYY,[>Txz"%Uf燶1RvPV+dSeQ2۩2(͉ċQ+|:!+˵r BTV7<㢬,岲\VrYY.+ee,岲\n[)VJn[)VJn[)VJnMt܃{1a&~ps9\5_5_5_ȢY4#fdь,E3hFȢY4#f̘Ό̘Ό̘Ό̘Ό̘Ό̘Ό8=%w`'va7`/'dKdH(P)ʣ(< *ʣ(PPPPє8GScƇHjRjR*bz6OI(\귥_dꓚ?~O Ǻ0ȥ78rGQ9||BB $^>%ʨ buA.J.12ZnhK_a NٞJ?ť`^j&Cv1p2jX _z"VOX=SA O]SB("V[jXm-bEL!RHc)u^ b=t7t74jM-MRK RFWy~^Wy~^Wy~^Wy~^W穮ՕrTWQ]9+Gu娮ՕrTWQ]9+Gu娮Օ<>ʡ/r~1~vb$F᧡BQh9 -W9;7g焅|UrUVu@_u`|3| ƹ,w}YhL$MMW6R|Y/Ke),ŗ_R|Y/Ke),ŗ_R|Y/Ke),ŗ_R|Y/Ke),ŗn -YvaͲG?+Aϖ]Kѹ#o' _H>x!NL oӆ"\bC5)hN6aM]Ea?k'iX*vȭSTO, bW["jx#ZIQC~z_*ìD1KE|"QV\E>dlwŞӓK<">+qo?ae_)?S&F$J?F'~Pf^:Tvw3pba?aӛDbZsY,].3ԓ3u&MDY9l)(*BBȢ=3,_y/+\kkz܀PCcYIT 4*Q Q?zƁ胾8p(#00Cp$Vo&jLTL 5-ae٭ ܉pwXY~\W~"\oBPX6~ͳm|k|l_bGצN;bWH'vwLjL ľðD!KVtmJNVvLVu5&3!ژ̆a{xn\x>9WJ 0p&jLBc!ØG01< MU^` dhL}*u;7>O|R2\)dzx a)cOwkK+T،mv =aV?!814?a^2L4܊`O?3̫<2<64V~8dz5VV^!~tDZ7ª*? B!3 \q3{~=cgnMx3v܁;qt܃{1a&~ s<;xz-:28:RWP SJátWF g CӴjwo/9ϽQTłko;[R]tFF5 +e˝~A\ [~xsQzϕSP[yΖD̰{kW qP5y*V[D;[ltTl#d4,@ iT T#9сhmN WB}r\4,9WJ 0p&jL凩ههччɇE u۩Uf!,5W3fs&/"ODꢁeq,38SG'F~cJWW5wGOlS2O&ONHcCq~Nkf޾:~q +i6xwGJD_BtOd'cOG}( .SqM twU)֗YefQW ԾyNTOZ[_듸W])m0Mzl qߚ{WjܝB/8tD?ďp?zg\#0g^K6FcjQ_je]?hx4 Wa2뱧?*fUbV+-f=O"~&? ?=#X՜ޑ!|0y8MP>:4yj''3*`k4];y ɊS]+Y:=ؓ}zW]ɔލ{UԘ]ɪ(.O-SKvyr4k^TF֖Wxokӈےvv^7Z]3*JVw**v{ Gu1@o7z{Gb[>~>BxXhm#YrYU[lJU,ʵ8V%rodG'xb*xb6V*hc+zYu>gKd=?wοkGwT<2Z;; Ps9>z8[l35D`=:\ P|O{*˸]J_j|<^_{k}pyfkC|>WɵX3,O3QEw+ŷWqɁ rͷ7{} 7!Hq^ ?#,́j_CIb-?b·z0ᙁ!9Rf+Sd׃Q.mƑ-Je *Q4v`E%JQG=>a~a";8:GQoVN._ğKRnM)"^(".})UXT;\TjQ/LVuj_JVwLjjCvXh9:y~,èg!28yyp zn{n5U*kXw}^v{S oP{=K[腲)eF}?u_EffwflI 4"4A) }賃Vl)4;((PHHG@zwONfgϔ{;3{r%-r1G@ZR9g͛.f*Ē`%JD aBͰעt%զkZ^.טt =C}4fckZ@Ch1XZ'2 ʱSi]FYKva emi J[=^d#h7{{& ,^cYc+k:t^7`uxCސgsX~o X#~oe)_ɚku9o[ y[ޖ]o己y{ޞw{٥#ͻص/0vgK j 7wVM>b.L("IoEHcsE)~E%@T'ETT.NgEmQD}J4D։) 粍h6DKY\%c[E+q )aQcQ?ʿw~¿% _KZ_oM6o]?$}T22)$72]BVuET!YP-tFIq+r(nq|N>'n(q+NJ{x9^tDq,ɩCEΒ xLΑr\$rxV.sr(?A1RT񚪢Yb:O](~Qe uXRW5FRmZuUlVw;u"8UR&RΛ2ʛmm5zv;ѻw{E;DF}MvfD͊~[]m.vG%dzNJWH0&ajLt W7>_w{~u';.2Ew]eIM?!K>YA҃dU=D?+az_/z~]6oweS=MϐGgK'+yV$? z^$zlWmvC~}PvӇC=Cr;B) 0Oa)9 L03,+ ˅JXE{=嘰W P99|.&χ7ÑHVb8N_yb01%X&1K'qxH[rFmfYmR-_ 8lF7o5pvi<[lD2~;_~{uىkzvx><)PC)[7X^@\c$B_S@ߚf%¯]WX(uXf3۬mW&Kr35P*3v?[:L$#%8֘(cN}*t6bf_3/94Xۜ/aY |v9ػ7W췅 JbSu3VSvoǽOBR=<&6eK˿l@ے}̨$La-sDZuZVA3%|ZZvVUuzvhh/ʴtYidH4R;{(w^j)˥T/(/+4_WQ:_ }-t%f:}MJQIB2Dz "@B!~t,Rb2o qoB Vo'vy)!hN+:rڟ?i^G9HNV򺚂o7pTμ>@;'3 35BA?*hjZ~U˩ZV֣ j#URfqڎ6T;!Kj7=h^WQu%T)URPauy2>eY4A4A4A4A4A4A4A4A4!4y aq)YL!f140ўle鄅 (L%a;%[!aQ22)U4FPk^zwķ-ߪBfz;.Իn{!_ %PzhMT_C臒Rb#aJ a$uRYZ*RRiэJ2 B\X aS1IIVF؇t`R^ G1XC (sb hH¢!%[4d [q4]84# %Puħ? hc? @W`IFv8p0`A͒Xk}#N~@+;%oEhQ2dġd4oSC%9L( Q*!ZVTVvoYrW^(nDz[v,*HwR;HQzJY[fz\u!0Ƶ@ܢp&%R, uUjHZru tkGZݬnFxWZ EHIuBʃ@:0.P lx zH8j\OgbQ/p7D Aža_C=PS/DƪSh/ oqP8̅`x >T b_[EJ9ԋ:+P/ݡ^CLzZP;b_)}2w'D ]S$Hݣ)!ؔ텔'OPO]Bf=g+ <+nٿ.gyͮӅsfk:[tYe):s[xb7{D;_&ظu84cYR[z8fc_w!Ye~`(^bo\1V/~K|C37reƛ7sR!}:]sͿ|߲l},Ρl6sFK!%wxRv2瑍]mՐcozǷ}1o+w |a!WKȑ'vǷ?סWf˽ܸ-r= ' g]?הx N⬣{33C> wCwثfj,e3މ'1m>5Mq@N@lM'bgҼgfLg<`L[򡗚_rβm6mWƘC9V?bvmlռq< 3cCRrۂ;0t=dL>E~ɴw4FpgQ[e36Vs|4ufX=#'f_(:cSNs ;Jq:uw{!}c7~/%{ZBw0K8[n`{ɍ^f7]8L|]]3WR؛,Uj#LBs8w쩛m bŮ8wĞ*bqxmvsL%κ@v1F`8`c2'G뙇̝QW?V81)fo8. ' b~O>hY'Hkgk;Ѐm,ΘkC4;X-ji:^Aۻf=6#j3Gm;;_j5.{q4xyX/ 9o 2/V{7`?=7N} gj|و[wcY“r:xH(ؓJ+],ՃY]ֱƍ&ejf9 =iv*zg̦*?;R)iQ~{t84L[-jbcp87&e,qoKcʸZ:Fg#s>ryެ*iM3sGdq#nL󘍡~yv1s~}$@Ga?,^צy=^Zt4ϡw:/-h!ż A|(-Z_Sh5ʧ&~򙴅g|C;w{i7^/}BdB929s,*3<Ϋ\/yKt^咝WO.UYQer,z}c;͛d7vn~_ v+YguXwأ{`OYo >㍍>M>LͲ>\F>ZnYnܳݸoqe@yS_7j֯?uUWY֣o(MƛYn2э_n=G7>xy@?$ w$ǂ ? +}A%z\5>z\Am>]C5>]Mf|Ɵ~(wh1)=h[k|b)_$}fAߠ/ 7 ߶;z_3w`*X,K__`i 6;f땍^Dg+?d Ɉ&R#"DZF4Q&R'RG9CT44#M"*fE%VHKQ'rm:qFHG Z!ZY4D3M\lK6q&D/MM*1~'fXom3tiuk}fOY?m~ڼ%X?m^I+kyYOWij zWiY?m^C;iZ?m^3ͻi.~ڼ+6*RZY/k ˚zYn^ּ;5neD=uռG$z$Qzgz(.(G}'# vEU1 T(6" ĞlPCk;ԮԞkZ`_P#%oMsy=gӥdaz49L?a'Qyd_ȧ+9PPC9> Xs/pN!пCj!2܎c$ "&#ij("l$jl`l@)[ ݷ/tW_侩DO:{{FA Ypoz{7GR7{21L:֛(ճ 5 i; L_/ABu0LŸϧ % _Ǩ)KHY/#/SWPID _O% Jȴ5nRFXw(&ڶߋ!ߏÒSң/}ba2"$d tʐDTM%7]f@>SYVfrYVPI$W!:S^C O֔5)Q*OCӑjڐ# o]YqQWgʆl$Ʋ)< H hsKy~׿(lo7[({}L/;eg:W>$aٕJG#hm7|PBo%<&|/rI(9 w{p|XW@ dKh" M:_%Bowpu4/CrǸa|/tx-F7H~+\9QyrZ6/ TP.r\(ȵL.CrZ'סr#7MCnwc܃) "JP=RJSJWeR6XNUjt:EՠFSDRPBmUuTUuqntjƪ16QMP),g:3!gB΄ !8Bp&L(r&*c9Bp&:r&La}iAr9! 2`NeN @>hOM?B^(EAQ+x70* R`P0.x0 u`$WWb˴EQ˴i!BpClE,BaaSH@gDQH4E\G&E0F#T?R"H*5EҨnd$5FzF$E2#tjL e#eQKV$ WE!qp;!Bp;v!Cn!Bp;ZnG]IѫW^k ~mZį4Tt눃!?K`xB&gY `Y q"l[SA@t݆JT^m$NJ&} } oC}dw#~@^ܧLGWНCH a7 aw݃Q{ސ|L? Z!g!3LGG(y#HȏңQ2GѸ:FzK-sj`'Rsk5L֓q 7[TSw:MOt3|'S:Y?lU_/! |@\F  ",ֿ,_S=(m^EU-WrʽlX8U qPͰo{Pi Pph8[>ii4Y>Mi)if Ixs6c8D{c9f|c)_q)njK;fqF.=8=;=Qw{|'t{|w{|'$w{.v{Z8=eϿO&zxsB3 2-S?L%5t\Jv5開7bd"̺7w#oFއE?y⣨Xcѹl*_Xy7w,|Z$ >[8n= yP a0Ty*8~tOWř5 ku{g$&XB0!BB)&B !8R$B3B캔%^ץ~:~~^y^?z.r~..z}(륬%w„46{;|νǙ|tȟBE4Sd'砿Ԣ_E+W4(Sݲ9oi[*&e:7dur~އ::z]f?"x`,iQBPAcQbbl?uzfE SxsQ)PQ?x<NE)_?~9E \K`x6to؆^ Gş3*"iP_lQD9FQWdRa&dڄLu L(?UPEFŚʿ-Pϡ5*xTIU-DMFM5=qըըE^z]J=+QQ'.-EΡG-^ X+DjjUQ[ǣAmIE( PT=b.r{*P1Z;Zf[#0Jތ*-[S)؊BToJ>fEp]= Or!ͨP%oA\MJ.A2BT[P%J~U /_R6-T>.F}-BʸPƏ@j2/P?EQW2~+_F /_ UT/>iSaLۀ)b*LZLSaJ]oYb*ۀ)bc&LdLK10EL)b0ElӚ ")b0E,ST"STkRT"ST" SĒ1EL)b0E,yM S6`X0?L&?La1?l懩0?nM~ 6`~ 6`~ TT%{6a~Vaob~X%c~ ^Z[dSD'j Ki'߆Q3yI{y:t&g8c8Cg:љ3[h9;9iiX@;'ל99K/3COR^sYSX:vL|֤@ UhIOK 8Tt&yY,|/'O>4`i6Фtͼf4/01/01/q#M߁iv`# (@La slTL| IS1S03s04{} N3oZ Zh` >>i}2,Y95YY5>}}:,8 tbO ~vz w}{Ʌ9\Ʌ\$;).+Bt ؆SCS("` 0 6pAts60[>!,ɀ14g9}5節nS(eP=^PO6p NNCj[7++ŕ(d@$R3p}Ҭשٺzͣfz 9G/rC+,/\A L,D4,<`0 XwwW>lwweBJ@ H~t@gdV+ɟ]~]w- #_6Xeʕ5ەf-=pA5:;v>ԑ3A7vM7,u=Wn[\(D.Y(FMMw,=u#U=ףkԍv"oXhOwg:Ğt+eg^7!/t=*-ΞERG~.Wckf;"+c;'tN8qhk,lǨLQG)~YӜqcL}-xmeHNj.\劎i9wp倜\1<\m;KlfX^[{^i 0m[-9Aeras-S.u m-ꕖrIn[>rj}V |V|V aۆFn?˵rUi~m&JrI6Y%`6u9lvz5NE9=bM^o%p[#Җ>fMjOZ户~ށ+|ƚ%26!VC^3 <O{w5s\wOyK}iK%k|<=|Ak/[U1y̳ޓ}W2y|~^^OYʓwt#A{n -.ʭ'؎ǐOmpeh]fO몬gsvrh/w_O_f?|~Ŀi?P~st p3eV:߳$Vf g5XZ4 u vh|A%~8>j_ΰΖpmRhh)4%RB'Y:u_RnMYJZ*)_Zj R6N PMHo1JO@ZDf${ ȥ`EjԖUN3Qe@g%I sMeP2ʅ-{%_-%I6PrH[J2q)czv3uU 0\@Sˈ^i?pLGC:qn}[(E; ;ue|CGBMw|H{;3B}ws a$(%0z4ug[ƤCˤt*`nFi4n.\k%\oY&>XgYf\`n cz5}ܐ` >pP+ #,Gr6ב&2KGN!ߑ8"GQQ3AEQlvT_Q`f79!7oc04:+f09ip:y,F5m3눀(T)+FCı1*{zapApq"1kj=a`|T;LN8.=p1s91spq䘅pq㶜aw 6 3XTtK3.dL L+L5vDv0pǙ̒ `vY̋*gq5Y,E5Y *z*ʭ)Κ֮ -:dckfks{|kg*Z4%dʕ= #Gl-v:2MotA*oq8xh 3Z!픩j rksgTOr^ٹڡU98B((A" G@y. N֝Γ6Мs-2>yn:2ǶqN}k9]:7Z:wZ8 ǜK']$x +c;޺&ķshq%b#aWj(+#:a ^qe2@ov\L5:nGPNMWI(uζr` '\U{P~֟l$yk\:%\FyΨqtNwI}cO0&dk0\0S]ОOhs0S]BX6u4~7tE;6"V94?NӢ3>8txʝC#qԝ r]C8BSCWcRa'0S<avW3:96jݍmxo#Y2zqmWV)ϵno`變p` n_N6 n ;H#ҁnO$Q-}Hp{W$]8=n`^yp{$K, 'Fr3#¹Sb1GC…ޝ2a{,Ruݓp{:R#\ ׻g"ۅsnvZ &a{ DG̢񾄈[L%G|b/-:Ps/o䈨gȊV-~(vӢ79)ʾ3Q?(}#]s"A #WĽ0k8r=u:(}gģȼxwi|dJ{0x7C#Nj#)y8 <$o6Xw % bc l8;]8[vhգzyk%Qzb9Q%.āOVߓ(OZ؞`']dEc+rv'72oI)G,=% 쩔xw #ź#ʶwosƷ%>זF{2ý)'V9}7-}7⣞}7}=[V-kK'ݶm:ZV"CYB[Fo}}w}?frmj{ f:NVp٩E}V37LhLӶ3x3w3{"i;Й{ ϶,=6Y{2:=v\ m;^n,Qo4ƶNsDN[Nw5W KnwOEg(ʽu2̆Pyʭ5sOͶ;zu`b#ږ;r:OgzsM1y!̙;/5 yД ǯݛ)J8ɔy-j*0w g:yp^T!rv25y4Zl$WILnOFx Bpi03 xJFOyX4T%AOmC߰l:æc]]x0ۙxὦs10`M= >d5] %+ۍ]}lؕǷK&_s+\W[Uԗ*KnUї>UݗٖU\ܗu{j+ꥯ W_K's++ յfo}7nQX.-Z ]gjF]HI@=a#/0gc>$J#!b9Րulgf6L6d>Cf~'P"%PbH)uO}r @Hxw d1AI 7.(%0K6oAy(俒#q}(OP?EH >?^ʤ2O''+guFgdkѓY| FdDRt0MŸIÄH=Fϯ`0 *#eFŒ2?&"##g٤γĎO9b8RM"7>fŷ-~d ~!M0Fc+\4`c1/̓iy|˼`^/%VH4!S"T:a(`W_- Pip^$ SUaV!weqc81QL,1W,2(bX/n$DhݢO A ҫajl+e8o^a˓'c/ߌ<{y*DZa/O^$ Oa/^4glb_}?}y/@_gI!yI~O{v -سK7ao~{s9W7=gpз$^\+~}ߏx{s-:f q=3ΌVo o|;}_;. ~' \u7AJ+mՀ:6@#mSn4 ? \gZ2Kera擠mJ{0%]0k? ޾ռ ,} os]'ܷDV5Fubf]fnGLIVgJg!{X"y}XgP!-y>ckg/EAmh?D?GGE]|~|~J4}3] 9h &>ey>Gq>Ma3Rg>7>y0/ڗ> l6=} H,x }~vX]ÂN )V6$%9B3T) !e R'' R'P"~fKBT)JuViۧ 5~?D#F0J&AL:Ā#ד$gG "~G"nGK_Š{t# Ⱓ@+ b9eYG'qH: ?yGp\:!^rc;ˆtS K˜4┣ؾv,~0VqW1ha^;5ᰭ^c±d')pcmOjwAv >{@GU]{ߙ3DiʟhLciD Ɛ?"h c'3̀F""bL"E 1 y4E@|H14(o9BKծnws{sn\+%f(Y8<,%Թdyln%C=Jq} l:J/(k@hP3{hXD}(SRa_%'vMĒ3)%BJBZIS(Xr-)G/ %04I#*';K{+]Byi]kQM&$u^hcqx'94/Y[xLԾN\5mM$]aG>O*qDEvkxo}ȨfŬ}K6~&\݃:Fȑ9)7G/KՉ=AD57p;o5:r.~-iDͶDn2S}ev]fŞLK<{3ož'Ga[ߛ}v?ܯֽ]bvN %0rx?6L;{pyxo61Arx ʽ]$~_JKP}]blf/ܛޫ\}W=ϲ=E]yO^k{7><#Zɵ(q݆xJᜣuq@"z)^=5"\=|>(\mQ<2!nq=KJ DT,9|6Қ\Pk./Dzͱl^{3)6F6ՏX.)1[qrlBqJlrqZkQqXQqV_ Ģa D{QŹ\mE8ZXV|:ޣ>Z|!^(-:okDxtE=8?"iB.kndX<c(O"c"yG5VE|db|)DWL1*"k/(@AiT;֬S4g9I BY4=I/-E}J_oЫ-I!Nʶt\?'V_+ ūz;{y{xS 0onL4px'zxIy5o!8z=bM7wUW:)7S{A;WC+A2Z >}5kk5>kh>:_C(+:jC54_Ck:\D &~DG|~W7ѧM4Dh> D&02,0,P7щ&|}_C'SVyΰӰSo7tuō_,Rw;UԿ(~fAމUsssivsoѺhݵ^Z_46CJi mF[Uji`m6m,0_sNҦjnn77et9b4GRpl bEC>C#>;yW I (Q=o7Yi+-1;tS n]Gu`Fwޗ!~d+K> ['sW*7]lUtdNTCvI.w֎ ^%ev`ip;E~/I4s(_넠חIDS; [ˑ`Yr5LjJ%@/&5iBJ5h}Tَ6Ct:܎}9])7C{F+RD;Sf ]U޺C6j&=R^ҝw%{|ɞA4m(g5#uL<'ꀲr:Qw=Mn[oR1Z_w׏DWVMiiwkF"j]# ED>OyLD墾yNWk}7E'l5;U׾Clrd Kih'٩v +bLa8a9hptj?OuMISXE<S*>mjC;:DJMmں^wɾL5zZc-KIZ8RN96O䓃,Qsd^o44 _6SvGOg|Qa4yC6d$󆫸 OCga*7'QO8Q=oa)$^$HQ 6߀M&hγo*/߁%4#ǭb~̵Tc ( pAJMٰLų:pzw'}F5#WB#%v`ةkAhlP)?Ub>)HJ!Y'y*`9 М_pT=QJ&`.eQgOe@ V>_N=p|5`8H07Ь^1cXhXhATsjByb00<ʈH1Ӊu(" Fw1#߽ a+:2@~3{ȑ4T!o/[2_Ԣk b3jZWQY# Y':Yȅ?5;1Z[~0ne,M JI60aϪ+•s#qqg#K/?˜?T| hC+}/գ uWW[Now O,S2,m>!kZ{!&B0sS2NP~j%lݣ7#TZ51T˯B*,? ٲ }3*[_>g?ʄ:> ϣq/(8޾x.XKᑪdo:7뻩[3}< Zq~ka}ܓtY*] 1ߪ4AYDq:sOM=q鯄+ԧ(6U4JqXD"[{vlU%»2@ 4Ͱ90cO}< hţXȻV"sX+hѽܴc4_~y:5A9Y88|yb ;Ga ?A }/KHFBVf ]gbg}Tg?+xC t`HR?oǰv X | Iplq968xi[6e) {yu-1^okag- ,A?KEfq&G,PyG-YXS;) {X Mxv 0aԒT1AQ;).,3SUUKzz{q1BSNbv &ObN3O2@)sO58G#Ea.dɄ2A^ׁWZ.-,Bk;D䰄"aHJ~F [?{34˦WSeƠ+y?}kx֎} 7Ճ\M8? w~!{-&'<wط2id4oPDE k~+ >- Ϊxh ^ 3}qV?1Ît)֠΃ej`g78sXC;Ϳ_ ܉ڌ5GS`&'/E]OZPpB4X,9OBL`y{@;0,?p&Vyk !X,5c|&9hAOk Χj2"z}bS/S>R%pF0mb?Fc7Okp:;7Kgǵ G OHxǼ53 eAOb]RDlDR`7_uՎe׀t ף+k|!b3xa>(5׀t~?Շ-wEBىvO*B_+' |bUXb=Q8Q?| O镼QQG8b;+(dB Yn~EYKԠ.b迉+~TT LqEO`^&NN|7Ƥ]I N[?e|3$tS zc[)T ;1:%̓&qu8 x ?wKx`z PE3( _NLE!ٟ"Ybs5_|i*t%GN[_>wAߩ)7s#Ͼ3O7̇8NX~,Ų g'x蔏3t֬|"嚐w;ceYDuk ߑ@~ y?>[kV^s=Ȃﱦ8qkr3ץ'm銬oBvf$OFy=a/w>T?C.wKzS'Q7s7鬆|5zeyCQM`ġdI_~cT3 _Mv C߇R1q.j% O]|7U:YKQcx6gw7a^^ǩ_È~qd OT@? x#ze.?bB' Á9+w=y]@?A 0M54leTשorrF|y9 :P|T«;/m: S>ǧuӯ0'fdڛ$kO _2Q$<Şy>?ݴ6K$sy'_a(K=:AՊ{EUiBAEy|THFeGT@HPo>ThcTAxWa8ʅ`S`<"0A@ s Jb|(<\ \:$L-8>q,b^րO0j fa ba^Lxtw_ x*Ϛ7@>o`̼/ۛ߀`೐,yC%$oA2m< p/%h:o<ג;C$< La6<|3kG#L˷01G׉Y T7t?K ^?*1:=X G.?*-+gD /A3ŅQFW7e\^aFEy?0 8 %"p9?SZNlI7jG@0vb ,՝{b\()=YX di~衈ko8-f#}]3x :czd^m_a'5FT-]̦؇[KF++O"gpM \ƨ/_W?;C6>0kס ۛy$%ո@3>Ȉ_etX>!ļl`PU *<JXIBs14.j rrd:s㨟bYjJ} |Ms<*>`YVV'RAgh *q4 :ǁn nXȫt0! ogE< ~,0|7ZPvB5X$̦\|XD=7 ]M<{Dxx)x//5miB1lVn+őߌx8sְ- TrSohB74׋kwNg8дϠ7:#ԀxJ`^oFgfO>VwVS )dkh#m3`WA'|p(5o WYV[cN"LÍb׆0y-60 wuc4#5~z4m]$ꊇQ-RZ\&*°3ĿS~ҜZ"ˢFjlbd(br*U|H6Խ qw"p*%+ZfSEɲSl+ì"U1O͗eX=Zሯe3k.(AM#=fg3 tnfjg5둱N@c"2o bA.{Ǟ::$pA?ˠoS2 vBJKn $jP]3A+3נkEM} 6p.J׀ 9`#3Gׁ?C24KWÞ|mQ$7_BГᓯANGR>[1}돑,c;H[C[kPK> ]G QZ ,η.Hv+}^ { ~gkExۺRxR,D3imǁGd9>wl@2h<@ҏ@e0jUv2dXoA3 .J1GU m<ΟwNԅoT`Y2 Z|2ǏNh˟؃M!)FȌq?nqjA8іw6Aݭ@Ce oC[@?=藃֝ =A |2~?Y._2Z0mvc:Df`DC3yԵSFмuctB9l{2aO'〰3C#ӷ QabNو +hc|(YF<du#p 33?~ D.r0upyu1Ÿ3F*X@5D/%B yF{LDĞc55' :Y |rie0 PZt[ yT(Z@w=-X+jt=胰'sQg=lm /_ChkZ  | p*<ނy;(5.B(`C=XukJ# u18`#k44N(Q$ D(F Ga10Fd!S J_>c&!#Fsc?pDhn}&( jU0l ZqBr4 _ ,{&7I-t)J_“\-$8e|? zm^ |bN1ƑMsQ\<)s hZ:""'~C& I#$`63MhtVa@o@z1w]cLwZm#22j$A#d?@<"f?A>w!PG!ڐg l֥} 9uq6 $CX7xm 20mgnw4#.%n`7= so8GEI&Cb72 NGZ@y`o3(MHîE"D^l~E`D#22NeIB:!n8V{ Fcd>C4漓kn6t3so+zts.H:JGs8l>4t&J?R* ( ~pC[}P9IWu$s*q)|55dmm |(VdF+7l-9h d^d C*rcIpg0r]*p,_a7W䘝xh`qMu@v3i(aJuxМ~a| ߒ k=}94DS˪.= 9Yxe L5 (doU4;ƒC6|[Ώ'Mpwt,cL_B!#i!]xL~1kz,&99O1 z0F@W! c@2\F쁶y ꌃ7@_?Ǚ^뻀8#h4sju~7R/1x1 a, 6drnEb/K3tDi ӐC[q܌Zi [Y%/ t%n~"Z#BWg 4<[eTH3jGUA'@r"3С#n`m-1F³A+ƴ1u\6t|VUF-?CK|#ڛ5=Bԝ h6? b4MWo Ϗ3R UBi @qtġ909d:41Q\%g@~2$~ |?/\Vrx%ي1}*k9y}Ac-,C2)<[iqj:{L1m~40a'2-M$' Jsͻ575yg m~ţ.1_?Ѽ ÷Y6 ߹Ě_sĚ߃|J6_:{s2_QF< :h_ $ۛ۲6އ ~Ӱ9Rw!(]h,28OEL@^ Lrh@=> ,y ty@NQ4o7ph*ZGЅQa\6(OFOf,p 07kK~S\zdm/ W8&GGg GgQIQmg6|Y//F"s.P2 Zv{`2ֿØqWBTn%T:RԱ4'^I1cXzǘ/a%}Wq4jNG)òXhձZk5Κi-V[ۭVE1@b+ b8-29q\s}n]i+ʏYnmQyGS|IϽ7WWoty䑯e<)B7sFNe7#y?W:!O` =,?{n+sU58 G?kǺVTHWb΍w5RQ\9ybyη9?U!4Q56yVs~y8רgYRGkm[LG܄"?z*ͫVj愬s9-wѺHnXWU-UlzH&?f/ j2pD׬ 黑4 eZچ(mUׄWKX{B]n!AP'EiJi ij }Kcڣq8*j[WC8J1Gc@D q{IC4BI? p#, /يm(َARz¼#bW jJBڦUSLfŷ;L9]`}G8Vg9jnVՕFoXZ/Y)j[xc].;U*[i zWD}qƋB} nQR(ODhLEE+DчVߏJ Ch.1N4x֊b'㈎,ND\r׳O)tv9NUyyJt:;NOeqX՜B#{OX]b^ o$>E\ J(RUqΧJJ|*r~U^vu;Ǫ;՝\PݥB7DȅUUUjǩ:ߢj\TT5Vzڪ6ߦ:ꪺ\\V\RuT:qiUu2E"U/zqyG e2߮|zMwj(WT#KTNPo7zKŕ;ƩqSjU5Q$)|qu5CL5kj6߯9\SUs5_Bkg\[}ԗKF}Ïj)?V\W}z{=Wk~LUkZ7T&n-X~&''کvrS['^R~ZS縙.3*]ss2~:x 2eeZ:Z:{8B`9g!3)DEErniKiOӑDNqR*^SUBs*EUU rݬ* TXݡ"Hq*A%;U[M{=TLݫ}>Wz@=ɿ%KGգTZRjQYAuryUW>5QMzLj*Ttz@}>,5jGT[}><5j=>U#s9=ETW}zk5WKzL-W˩ u\MtLjΞMmFmPum,ڦSjβOzhv5G~Z-uZKVezV]QW_Y\[^ǖcZivYb{1Pv(8fTM{OG߿/8D_seuw;brHGfTSmOI\/te*Chͥi a:MʞE%2;D)cJ@{E±wk8~]{i!8DűW0{GDZOH}RqL~^ѣp&}>Zn )o+{GűOtt^#4Ͽwy?3xfbIG&xdZGf0Ȭ#|xdN <2?Ȃ# |xd)Lxd|x#|xdqX&̒3K, <<̊#.Ȫ#YxdMGYxdC| |HY xds-G1OG9Ȏ#;<' V%3 S|Y>_KΗ9Ddm_c n =w ;qg qAQ)ͽ}ܟ<S'D*KxF܍]8 x].iKe첦gڢ+]W{2]߻8o;'cmrv9rPo7.ho E8;- *Ev۱Ch;lgGlecle F:¾߮I]ˮEJU<|WN㵼7?-Y3bt]&40N#ho(uѷh gXG{>Hh2M4 !ͤY4>9h>- }J-/+ZL_7:W,eVзә{ZMk(:Z6fB[GU~3v/A:3:J8tJ3ty@F)UoI))ru[HOIxZ4ψ梅h)ZYh#ڊv :E'Yt/dUt/%1MW8(8*8)N8aqNgW\%.. qE\k7),-rDNAm{f(&OpSnɭ9n]%CyOO3 o-moy]^ǿ~>}]V{iw{>{}>hG1}>iOg9}h_v}žjj_3vmعN/k!YG>,ʺ/ 㲡l$&2I>!'SiL>#l%[gsl+β|A&ˮ|Qv/LdoG/~_ A59X.ȡr.Gȑ2U!G7h#ߖȱr|W'ߗr('r*rPΔ|@.Ogs\$_*KRL.+rNrLk:^n?ȍr,ȭGM$˟SW<(<*<)O<+(/tyM&3u%e̍(KΒGrXΕe"_}/_ ~-<8zxHxhx}t!0w;馺o7[w;ѝNvSitw;ӝv?rsyw]~rwWk4wnq?ܟw{=sO3{pW_kon{rs\<{x!w;Nx'Siw;.xK^wxW_ko^w/7B+""#N$Ht$q#^$Q|MHH͑‘"-[#"E##%"%#"#e"#"#S"S#"#3"FfFfEfG>gc}*ttq܂vsk~b5swگW(VcXc:u$֭S/X!-pNJpb+['eLcrxxxYok2vb}^) S 7W@ Bgg݄;Zj>(& QQw>Ӹ]qo;5ETL_T ݫLMUhTFu]3h}F5U %Pn()"(Ch=j z גGE=QlH4"'<6?7;+YC?feGIW r>X͚i4fz46vbj^sjNU0h<~ ;뫎g\sLW:jґNuӋn{XWȻ+[ޭ^16/+Jz^W+Uv蟯*ZV|*FwZwk?]wux=z &?.ª/7^VA}+gXՔJG{E_gzz& Y$D EDɂ ʪ((F9`vלb( |˰}ow;u[3t{wso K@<WH C '0f0'HƤ,&"h2Ì#?1Id 3Jfл糙 =K=@/'%{D q&;$jI[F4⟣yiy겺`ľe߂1}&l[2.0MMsd4͐C#J_e[xU>W/ރlH>B3=?ƴD& v:ftJ& 3:-6tܫdd-ѓ!*ffb U"o\s7׸NX͌sK3fWHh+hNcw4v;P{*j0jR`:FQF16W,Yb/hoڛh?~;R=ݨ~X?lw"⼮?OGХBHeԞ<6.SӀӐڳ1 ڭ1| s<#VO S~P?|_%]|E/#"ԓYԓ埲Xxog62 c'Fl<fCy+ކo7&#̫y7ރ^|K5÷;| ~?g#|?'t~&B_/R~_o7[N~?) _s%U]si%CtDZ*ViM9DH]X.ﮑx3_sO{ &O/ d1!L/&AJEi}<ʷox׫n}}SwO ƃo m㛂m?x,RRW5Z?og>]/=&dn5^; AI(yd O1YJVa&bt\ǧ%bCڈ:C=80f0L|=3/63 o-+=j]ˈo a)ȰOMU03Z}: ،ms`\5Ŷcmk37V|X;l3n4@78bۉS`{.3y؞/iOڑH$X8eMX?Ɇl{"a;sl'oX='F9lsD|l#2"yC44i&k-#\ ^Z{WE  Z!*k3 >ƙZ!Q;Ar R(ArAr(Ar2e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"@P&e"_i!&(^b"dtivȭ 0wb AS6% KHDRnʀ0H&8cVl1ʌ"$ &)$;-:7U3gyňZqg li-_(aaHe Z_/XLzuRV \ŅF00>=eZGŝ*1)cStINKn雒a#XKT&u? JGFV"ᦫ)o6-A!~PIv? uL|{T6 lR{g\ٍ1w6(]rw!h_.jU؎qUg.lfxM^ ,N ;3.kJrҌcYv脔?) 5#, ^x2<{jKKZ*ޤxvyŤ7/UoսڦY75ѵ/:AMlMxX`N}l01Tؗ JѩYVC"ŝm׸ӧøзou[޹EK磧UZVJ3 L{LOrزle“{lWz%::*JsӓyrojĒ+]%I>a V?6 h'[3ѮB% lν.FEtR5F{-Z&g9h2u9GKg͚2ѼMQ`kmZ MHf6/(y3n>k'̾QPlZFBt?D3GZ/hp.!.o:GhYYZd!+U.F 3ZHK?ɊҭL糳zMx/4g nssՍK]֣U0-WgGNxA?K{j~eVsOy;mcO:0ˉ%OOst_1׵G8젋oXiD%&Wr]@m;=T/nPC+:lsFC &[2mi.*;a߀ۻKۥrO[ɚ}뵅O`P% TS`cъԈzց**CkP#C{3FVrxҏT]z:[m:D 1ɑf+<~3·بg+7Cak߯6_5޼X|UH]]s}Go̓-]Tz؄54+;">Eߴv4xvqCO1cbj/h7JE^O]edx nC~גsNnT^ dWDE_˵ E/ѫ/Nsj ^:Ām6}SԎBOq=%AmkfHzLRvAPruAr"n')?ui]sYZJjiz>2Թqy΅.Oj 9Fry.J2׸\!O,vW^Xt(7e$mpȋzTOO+.X[8^]9Q舮z;wV4d[616#TK8R2ұJu1۝NHTXRrcK>s_zVq;ז9σlreM5]孀w?Pp Lޙ=:Ժ6XIJF2Cw;ž!_[羯/:2;/+vy+ojzN1~n<89lQ!wþ;s[[ ҧܽ4+rɼ*{]i^%$uaЬ M;H*O,K<::;x/딵^ﻯjk\yr3fn8zU+_ldkI97dQEY_i.jm%6yơI Vi}^*e|ʗ?5cuĥs}Ui,^ʹNM(yKgΆ]y 2 g_۰o~ M7UY&LqU7sׯtj?bͲ[fur[SKNu^.X>8<àtSÅɀ?=]K1=Zy/_Ǜ9|xG :<Ɉ'H/NvAkrOmΩQin`;Sǽ%̫f|sPr ~St 6[:N.m`j`yWy=|ͦ V[ kzz1ӊ"Zk?V}{-_{Ȓ%ߠN]C-'}~E3['saQ’|r?b_.iQpʡWgvkNVV-Ng'&Gm eX.V=4^tI s2 SܟxnԞ{_ʜs$Na*5n0 .mƖfstE2ɲ- G՝2Mzp{ȟ_RqO#7X,gҬ*ۇņz>~q=;:{[ȃyӓJu>6srQvϊ dCMy[$~a w?x{t-5Pxu8(t?vTըBN>lpG^tչ}۾aB-6{)et+2vdiim Tw-o\/:%i]n'+g>N/v\k;Vw79aX0{SkJX_8sɥTC]`Wᳱ?<4JM:pGKfWz_bZty~+Vl4@=?ȗ}p~}v[MZYwB u?59lcH'm97_C/Ju\h?1BH4I#)t:KL2I*nHl'E GMLMOLiX"i lyuՕQCU~h*iXٱWn,gzn3ϽWdž/h骷bZoߝ=1ޮ^:6-wʶ+NUU:kСVSrؼs!bKW*ILy=|Y]r~)eqsv9|JZ\fvT=tI=Қgk y`еFUG1/~ʝ8tS9o"ZEf+Fݙ|ʳ:(f̅lqel]29|gW,#C7<V-N ꦘz"V]KM]CMw6jܥO3.% 7Kű["YV[nWMs#-r2eҰ>o?hG}p#[^!na/= ǷͳvQqpӓI_Pa9 .Q^gotN/ow5I+Z: Uo/1vȣW37۫?ylyl_r(}_ӡ&!MLwIl^?N}Go{3GC]pUOֈ0!÷[ endstream endobj 4370 0 obj <> stream x]j0 ~ CqK{cClJfXd8d/t0 }i'7'8-B'uyv2QiuN84UנE{r!{ayqBJP x5.ؾus|068ȆFTu%@*($Oߨ~_xX{,yJCT>?!oP endstream endobj 4371 0 obj <> stream x{ \TUsaM°o3 ( *%0(03Ro- .[ˬLU+-+L{f00 r9Y<9 .3ǫqq; 獞 -XЄT^R9gp C%ڒOhaqXapmfba啖9!o2 N{INCv/ \RJ1q6@i&‡Pn֛l~n8vY3λ2ikY viׇσR<1LvNYGZ_H9v Cұfܭ4r@ U]0@*>DGIJ׉1n{Pʸ;b1aTˆ 38\.Ie䍅JEGh&i f/C_i'*߭_M0=RBrk{理"{KX"fYwNg_z*A25D9 vpgDpAtW&u!;x z'x7 7\91!BrC0#r!@b("*A a#!Q ш1 U8xH@LHD$HBLd2HHA(@ b*`8 A3 a`8p?gHt012 Y0q$/(88"fC688r!& NaL ya TĩPX4t0^3ZցJRR(C,r[(f!B<a6bT VBL&9A5b5E3-`AZ,BbA0q.(·oq4 6xCðq1,A\K24,FFX+a%*x&&r"(F\ !>xZĵ5<O"> SOW4 <Ќt3ql俄 q<__͈a Vĭ"/!2 X؆ #n;`'9W_]v#`xuqG~88x@|?7!x -xކw߁w.{p0pE< #??cS>cH##/pDB ?ēp F4A<mi "Q8"-|{x~@.!?K3?Q~A/p2\UkpW :{﹁ xڑA'QXq( vXwNn>'J߳I仱gvwd#^ r{ ݵO>gßzL}>&7jع-lpsD$wa[lzLw1{I^)yv\f1z ;83rՇq)K U }o3}׻^R`-zfw_rz r왭Cls/ O.lꙭ w•޸MpC=ݻxuMwb";HO)gvwxuMw%-{fwگ~0T}LIAhS}Cl% LpI=k}5s/h4gvne14 w^3 뽟>ǔ;H;83z'"{IyI=G&~t5/ypy=k{?1}K*)Hms𨾷(虭{? }{bM8&⏷#C!/oW=nrswtB4 /~DB/Tr.{:x4Æ 2h@D*!>.6&:*2"Rr֣JLTLe!gHEЌ3fBB[YIeY[ޘU83zy|tD4aOdΨ_eSf *X,mu⤂̀8+)auU J2R*3r%@V:(K3 Pr3>s|bKYN66.͓ XX}`[&|dQHǡ4+yEr%U6,S4:(G(g7Z!>df7 gqe6_'4op~KZn6Ƕ '箄VhuνY"hatjRDRЧ@.a*$Z#b:d5* |UPrW#@yBwΑ+@ qr+ְZcbfh~@|\m+4)8|`"V[8X xy1c]88`hTVH(9Y5Y(YYry#y^VYĭ?WGV`+b<;O=iZXdmv~=>](€\X{!!E d)G@lMm,$2d 7j?,[ { Q<>&NS( ʎYi;-iu/Yp AL# xd+'㟆xly!Uqp^ xL /(gɗ0I0ˠq,!xغ?O>xNLj\@Mt0vf8! dVxBӅ72Q'Qy~.3a+Z}BYW G<[_o;R/A{њsX x5:9u>Lv,7*a,h:Xy2ƙYOHsƏ o Aj;fzDYd B1$,DVՄۊ7+8Y8Chkѐd2Iʈ%VE#@&2e0Mia3m/`65[7wُ/0NJ"F*LtItY!Vܾ#c:|^ALLQ oՠU&zhx}'xUh1Jޡ +8-%"!$$QxMq%BC?x _he3+Sns Gg%8(6Nge- IYv=`1jу&+wDCčxY;{g%IIU*:`;-#YJ^"X901 D*5 $3TVGH)ϰ X8""yDRypS&hō67:a3}3_H\ lbLj ZǘTnD3/V&`+6gP<+i?pn2p|)ڵ`aŅLl"l}_OnLFd~ ~E>LUCGg8p7gOypm*eY! T=Hǂ\"ֱ, ɢS|csƷ(W4NT'& D| |a. RV`wѿjE=fW*iÉ{jjCF ?09 RO2Ԟ}(@2BN3 餌1n8o&'$h4עf͸HaFE g+ɉA.:AưN"G<O\B $ He1:LXvhDi?sf^N('׷; S\nx=qxZZZ &^CK|qO.OjC<${C{fsI=["do;:̺ ۩_!ZQZbU WE2 YR UrʠPe+]>|TVbh||=}||Ho$с*/$ۋQEF8NO$s W~#!;qCCF,}Y "-M@TaR'vsM,QM !n>^! ?BBH2T*񺭔a';S¼sua'*ۯ7ޟfk-7Nhf-l}+H4 M؟ pN `CÔ$D$#$c*:ɩHw%/D%q{qWE^ )EEŶM0|/*ܨ|Ri\DDFf NFF(C%^>lSdD%'fXF%fY#ý慩43gz.7}/~{<ӥBٙ ȩ?,T-w]3>!rYm튣'/Y 5HܵkUQtĕӊ3= ^Di 0l40Q-u6%jJ9EU81F.6M @F&.(Rr N<"I!=00ZHl"͢E0&^/ '7pjԒ` A(xd{/^yCۧkW4"n`bC/~~9)xP͵5Qe̢zpÂ׾F/>^}g s}!d7dA ?'C"6MAG#bǜ8cǞX{I=O&U yn.&O=uLo]g@SoyNr̰Ӣ.uNW WOL3rLFz 9܄ܸ1Y9yY\ܬY9rgy*k\ rkhv`qYǥS/ SFg+7ʻŧJWQSMg%.5Uqqn ќXh{_U{TV/FRmqE<6AX̪6c]UQU(*ai<k, Wf)WnOGRȩ*q6FJuTcJ-[ީ ʰ1QMtN6r:Z*6Br0^%Gs*6:w֦S3r T :.vmWd= >첄^(d2w]"EZay«^ cL뢢+Q тuT3!gݴIU!D`!0F❁@O@0sF",! (Yx|p9 mcZ[zk2Xk]) #h=:KLt)A):ڣm, =ɵ tVU`T[tr]Ė p*a+[nPRQ.z:zҫ}K^rkf Ug Uvt` I#osUtRݼj[Ìv}UjkOΕO9jS/cgRg&:ڣӹ;:St7ﶻw?uE$JeF"bm-(xO,].]V̇,}ڄ^ iI9 M"qY$u5M|lrRy]w!Nqܘ*]Bb:&(:eyfAh "L!MGr_⒚K;r~:yuvƒ~_~8yCe Vg]tau/0_k+;77~W^잙T6]۸ywS=RtAon篇䒽3JL`\(Ds'?U[ΞyqE̛C}`fږ%VxCojmm"? sa}{? ;qhu3ZL2Cї־kο?|e!ۗðP/\_"Èμ,:)O0+hz‹dj >t,NQlߜXmoZehN-XE` W%!D>z8c'HmV׿+x#_'cox7,z^qNHX[bkL0%.iyʒϯ& xsdܗwiy{jOv>o-ӳv~2$7 %8yus>K}]z<̌?NGuJ8BUxЈބ e^䶉Q|C5,8Ժ^xz["|xM=g77怘h?:zw~j N͘_:`16d g^^:c4no:6EwnBa3K~38Rt]sNڜIUj"#_JO\7oYxXk,ڬyr[G_L;gd3;%zʹ׽FʏO=Zܭі#.m}pOX0Cdl<^_N$GddSǨ#i2ZxN?o:.dJi} d鋜\M~k{ۗ]>篏?\v{%G42?kģ["WyqtS?񗀉a ?VV^sNuǿxAsӯ,s[7>1om˵GP0:K;cuktv/qxuI2ymxsyhܜԾygyɕG>Wkܰ+qˏop BZ6_{|Ֆ}Ϙwi^R7q ͶAXaWuNjzL+sn3l /TIh*L ХHY( " HSDP#EM+^:"J]{g?g?9s23ya VpH4|+y=m5Y$&z\O  h&dr7Or'^cJs퀩hVI2))pՋ&1/4f }[ I u.kptVdߜ>蜔"إxJV{Ew oB^p(ċd~&8)% !ĹcTpV4a46͏EW+N6,Z J8meRYTc#bZs-o(Oivu҉f.$TBQ($&ੈB%a7X,ιP>Kl0bNg<=g-Y7e7bb;k⃦FM{좑i$UCk3u%|;kRw(szp-kq_+ؤw' 53MqG"k-08_TKpbJgt܋#ڦǤԝȯv uR}MK5Ck}aP2} n\l5>2}<@w)N5FPeQcܬꐍB#o%ל0żxVY:9}QEeXl$ֳ{L"X<$! 7 8/tnQrK|ַm67.w):ʶd :O uu]m}K`ώy1yʒ)VV "R5hSg|!! c-*to눏 Z f-r5Bnmd;}=cIE%[t*2w0iÓ!ɢfXEcF{ɫ^D<ܥ:fYBZgp&x=\̚B@5* |d̆U{3zަyoޛ.]~ gUj'(vjk ?S@ɡin MFaZKYIJB&cvhݫ"rm!ۏދn}XcD&?//x}T_sF윜d#!A)]N_G^Qxrod-Ky"H_CZhgpkK@FiV\k[Mc2v'f==?oS_Rτ}MИz<J\d>{'Gߎupד!L ZSن$"oR6 f޸704gؓy핟/vT J RsbAitt0̷;?/wWQms2 @jˮBNTPԶ(]}﯋>?7Hdn[3!:{2Afd+>ZFf> ]ӬI_06H^ 9:M+WUX|>%`ȢSdrD]R_œ@=݁X <2\ zLt٢b@WXF ;պ>VhgV].5O֭?5Ei`A=t'Oixh/3Wn,3n;beUcXcL:IQD 4v:aZPd;mzfmg+_Z@lD(:o%v|_JWk]{x q  pL`kɮ;Y2XI( j]58BҐ TY5'&4Wc~d!/j:1@$Yg2St3GI% YSNli{,t;/>nqETgd'p"6xn2SB_AO endstream endobj 4372 0 obj [ 0[ 600] 120[ 460] ] endobj 4373 0 obj [ 278 0 0 0 0 0 0 0 0 0 0 0 0 0 278 0 556 556 556 556 556 556 556 556 556 556 0 0 0 0 0 0 0 722 0 722 722 667 611 778 0 278 0 0 611 0 722 0 667 0 722 667 611 0 0 0 0 0 0 0 0 0 0 0 0 556 611 556 611 556 333 611 611 278 0 0 278 889 611 611 611 0 389 556 333 611 0 0 0 556] endobj 4374 0 obj [ 250] endobj 4375 0 obj [ 600] endobj 4376 0 obj <> stream x|{|Zy&EIf\DE H"JBCT$m^B^JP{U/.8-SU=3ڞ~YY߽}kc15kAUk"~fpVDeok֋D"RG3vi9h1)C'bA㲆w*?5y-KO"_:uύuA}ӊfZ^osD'jUZR4/n@[N.EBF8{ҙsw:)=gM.*R8h7x/Y4vO(*YrM% Ȟ=lNc<7ޱnY,Qȯ&);SNC+^hxBgr|&SԗzJ)r$qR}Ld6=a&-P+"dZ !LB׏Qggi%fT"91Eljʙi4B9@8>mȩ=tr8}DT*z[a TNk(R@**@,P)mS-1gd:(X}-dXi!*m]MkV AQ*z}#L˞ƠTz%ٚ%QNx otDK0x9:ΉO1%REcmc'tr m܏@zg$s@wG_2V%<٫qr]MY8)W(@>I.QOlgVDHQ2F3yѴާیxKqZ.,rHȕ=Wi(؅FArdv i#tC'9Ov99E/0`N0 gghb.ũ"JbY˽%|^Rk@Ӟ.>?oh }c_N8zz _;_jX n/;ןkxd%~4W?A^xC6 }RwoTX5*Z-XH4;IZ K *k ϠЀ!ob5Be5ڡG>h`} mz'ei7IAjE`P>H^!ISMqڽͭcvF$_YBzS_˯GqDEF_( n:?/7?;~O*3w:^hΓa9ǯ`BgQ_r.4l<bh ! 4D-jIMiU~c"?^l_sclV(wM w,Yï>k[a;ל^|"\Dc O|ǔ~P8m,6MV,KT?)2vM_(n;`kJΉ6+n/|aY.RS~RgFBdiNQ nfPc~/\Ni}>gO]Hoj1ۮ@%ϻy|ڻ?ҶYy`7 &s# _Jh _Rzq Z{#pʬ2EUgIZf nfKi4l ކ^ O*TNb/6L_4dFqh)ZR@Ɖ9CJEN^W܋]xwHұw"L>v-O .&*T6ٚ(? !õۋ{g"Z7zЪhs[(o]9-e +'@/,xuY-z)a-ȅRr<2Md١b[P~$= Q} 7.XN8Wdx+v7 SVWr {MBT.G[ eĠD;G=C-~y#>-op`w@3VI>tq%Y"b9i'N>UCrK;q%aWX$PHQjF(9a\Urn M>g9E8^uD ,ޫᖒk7k-|6cǪMgKZ˷+Yz(҂HHVBfe+,QfWМC3}wdHV9䱨kU1hnF`> ‫> z:A{ljNdEc]Id|c-Erj Wpjw9\~OH:yw 9@/-4CJQ<9Mx$ Y [btDXǡG~F_p} X~Ki!Rp&O$-Gau' fJ.zE'r#o%f sm`۪Tx-)2\ý΁75a^wi剰`ѝxC[@ϣf53˅o4M\^i n~oEp/)'abp[ (`D(H˥;lPv~`Pʮ,I+ueJ:V)uh~WW߿իyWy>O '*w34$'}7pV4SdХ5Y5HEG K}9n<S]y.ޱAG@w"8G(­p[?7)əRh>?CzaMXS*+<䡫-@ӥ*vGguI"ab҆W)ڮ>vyݴ닽˽:g7W<%O6~T^[Ω .|t>pbUSe.NRDQD2-ViǤi "MӿN}?ZP +R ~ 0xZR00Da(Qp(Ty acR+`$E?Q;jRMmžP;`B+Em؁d1.{0b k#ـ;LV؅:?R *F`ؓ^I> LUؗHG)@'uN=.Yn^LY8}8R/pJia n.2 nؿs)|aU[C8q%>AW)\M Z\p-h|RSt'i7Vҟ>Gy|5> T |6~ˀ[Lˍ[i>N3njwaWw] X=U=bM-zR6= |2ޤwgѳ7}Z@:}D(R&*Z(e m"MsA鏲.ͩD)'zrBVN8 O0 L0T)?U,kPe Ni֊LMDJ"Q'ezȪ/uPA)gMX0VP#ZBr FҼr_j89& Ju@VVP--=ɱ!&իײ^k{m굫vQ*j'ax9*#T踄nPxB¶'&91L Ο\/o1{ O4iҘ8qIC.$\ѮcMbw"xNi-8 #U떉qe * wC>gqyn-aS1'DpO@O'iݵUb6hb>iG[1zI3M1=jZekz_ߵ^qقڍMZ|(P\焅w7 ["SoZ>"Wl"B eq #e!&E!tQ ubJPqح A<k݄J6wd2kL3Eq~$a |sEHxx3b~ͯۙӖa3Hnq;(SXTǛ9WkhiAcG[c^tSIׂd: s‹3i WR7p=+VPo.v^jא(ֆP5_߂}@spCWɦCkR$p~*^vq#M?YA#D+zkL&ɢĊ7OW5)G95N2lupퟏ9@kA !ZPAtߡC\%6L ޣwz[RMC7M%0H""#[GX$ʼn)HLt5[-,1&($ lcb[Yk>:ZG.) SRVATKLO؄I 6%J0%:Lp IX~±V+Z[bye_~\o^BԊ[]mZY5wQUw>"  RAAS253MMkfV׌L]3s5̬\5+\\3\53u͵Zׯs`Gjۭ?z=su7NF:"[vQ^0..-ol]$%dRVq O{GDbc]1TLdd̅4}꯻3>pB }vEpڢoHM4)u팏UVVbc!![RۆF#ζm)Ԍ R:bYԬiqimgk[/o7+vqXʆO]SjF ֗W}6FgcCs_ s] >C_pz,yR3e7kcI9_,]1It-3;vvjL\aŻӦ;N\%:Pz)S?^E|ÇW1alYdR;+-~|O|?=Tꅎbgqf%c-ڊmږԽR=88YNի@\XW[#bF6dʌ׌wC[c/Ŷ{~܇ګܠCF)j^ Zw"뎽,>"KƑToުGB[̎lÌr)6.GPB&PtTD Q EF5R;] BBBQHnC(JtS,HAս;k?\;whw}r ^=EQ{G>xjzP1wQ3´!c]\OEv+7܉֭Zl7P̋Ud%?_RjjrApL IJ!=:Z\}ϐAgt'HX2L2{ñOj^@LW-kׯ|o zZ%ei[n¸iO+QaѮ<5;}GsPD˯][22$,21OU*_0>>eO*,F_tWa\dˠĸ_f)߉qE۔UZx;ľӠFS#Wp5\ Wp5\ Wp5\ Wp5\ Wp5\ Wp5\ ?c馫糿o-`z4SAonӎID6OѮ'e? ~L;l'l?)HiA鲭vH Aar':)ʹ9Y5+ 96)NMchڴ=6Ц1i{ mCЦ1TtH@MնLtj[HЮ뙎 o}~K.۟V\MLBÙn8әhg@uCY#A]@ "*DCeT iTΜ٠%ȹJ,*Dq2p$IH3ע~ .f<@%.< ^RZKY].R-NPyk.,]oa>U^pKzٍG : X -Ũ9t |S,yoMv^A^%B Kr4ēxvg`4T#\n<[ȍz Ƶ/.[Sν)@-ў)\W>J6ĖPe_#?a캊 +.鹒(a*AmTC]kW%(5j/`Mc`k*j/FKnڮ@K%WJ 2&ZCj%&qIܛ=J_9GY32X Ҳieeye^ƒk`ʉ‰ 7M(.N'ZyVeE^AqV+겊KJUZ\YX`YWY¥ 9V~٤JX8fRI^EnUv\X1QJ)ί(X6|<ܙ3wٔOaeeIaŐIi֤h:0ʛhV/T5z]}oDn'+ &WnL)*/ (4dRVYKPRȇTaiײ+/+-f_cJ5*lXtUQ8c6zdŨpbZP6,/R4:n*Ƹa:&UO '*’zE]0V c/S5E#^_9 /bxQ*^Jlt)􇬻I]M>GV]!PfoEFi"p#+K^j}ԦNJIoPzn+ :'MDL_II堟W~gY4a )NY"Dn&"H. N'Vān%Zn-Zn#:V䭢8}ŏA?,Q q:/#DpRhG XjqrƑ:Yˑ# t'Gg:pr}6з;?\hc%;~{Ar< zL!M$dq#iMFomwd } z3Ql%g/P-MҺk= mVأu Yԏ8B+up>"BĮ(g|Hώ#$fV̢2b~h&;?nG܁Sqv~v:tkjeiȎgqPtZYVokUiͳVZm-ioɡVrVras&[)ߞf8H@8hg8=釷P[iSA+8zG`v҇*}ӑ^`X}|66 /}c B~[~<]9p. kky  zӺ{{ޞu@Ar./|.y7OF}~XF;YƠ^ X( _`; a o HBAo{^ yлp ~04]c G ~ONl'unq^lKOƚkَiӰוz;HB'gT;Lγl@z:CGv J gB=.>3ly<.}ϕZt"R=Hgta?ҧ~ە9moCf_=7ce>ҍ222@]~RpmlQA6c.qZLM%X;c}P/3 >T`yZ⛉oZ҃ƘfvҐ~y&U=p^ g@;, 4Z܇;fnyw d|59-Tn;pKRdihFNV`X#ֈ&Zo\M2=Gq+" !ոkϚw#lϋh@kҒV vRAFdptp.t??q! YҍO7Αn/ݓ1Γn#sk#b+ݸ'mF6 p@000PX#ݍzY nQh-j-mm9LSOmJxT&9JJ ٔFs ŕ ggC(gg;9՞uyyxSyݳQzEнރgJnl5SY)53mSs2pw;6fJ[կU'|@ j,[-̻9`/l'CK?  TlĂX veV6fn,؍;`/l%O h\aS 3B)CGTP7&oNޖ#:yOCGO$ޜg2$&&8&ox=р<3<=s= 0;<{1{=<'w?1z?1#gĉqQ0HHspH?im ƌc.\`FaFxF<<#k>, 6<­.CAIv'K:t$xr hHXn ]`{fI7ܺGŨCV3n;|׹\<pgq~bǝΓΓԊhT  2K=SvS^w{;x;jw{==ힶ{ܳntmֽ̝^^ ɁmW#lm ب@R,B~.,lJUV?Atc:ݬvi&\'m (]A_o%o8.<</ M5S='Ё:e75"#*$B=i@aIJ*sBwsh:v1ߤo"[59W!B\w_=hoQNJ5L!\ZM7]FF-WUm}Wjڳ曷3^H{^h: MPf׶bM/- GkNeJ+8K:zz#¥,Dfs͵ö6'"4hns: s Ӧx??|u5jҒ1wߴ_vPES=O` q|׹=aQ%q"y2s1)h C3JiRr $jRQ rj~S]?ϵ8}>h65  ɣ=kRVՉ2O}bM͡ۼݧ8}NxZ| yc6_Zwg?P-^ʹjv(wXܵ[l]?Ԡ11oοO6S"qjA9+3؟s8 uQhɆr .4(uyUː=aHWK"28Î4B*aK64956꫗c=gj\53~op>ҵ$}$7Wi˵4ruk< T/"]҄_ߣ@zp WtY:ge7D;puU@\*Y} Vn7[-AN}'O5ߣA CՏB_t&Z51Lf3U-ǾǺ^~{{XcOQCZZ3,4p /NS&<Mx!t&<#5?`M\w:\gNs;MxNڄQ <9Ds9NGq j! >|..:-p<0|]W04RUu<قqec%Z!2 3Pa:ǜ**J tGcksْGFI1£b|9KRe[iN-<»ػ(E;m] Jv9p+[_t_UVЀ8[a5"ZR*=J^,UX/03~mjxgP^SA˘ic7Sbml]ssYԎ^vA/R2~ǹq'A={$O޺/X\q?Z* 6+}jc~wwY!\_SSdZ~чMƟ, +3C鬒fwHvyۡ)`u;k|ֳMv*LY#G9jA}*RYjUo}kNW9&={2OM)+(|6[i&Z3inDG 9ekxNzA)nx0 ToaT֜"`:Q0T"dÛ:?Kha|[nvF˩tƳ JťyJZxeIJZx=h-%e%No/,(T( XwO  ?'L0o=d=>oZa'*;6qH7e ;q͏O0bӑڏW #(4YPXPsҿ%h9ZbMih}6Nb%Rdwu[u{Շ)5FQY4kKKp/ėo`e$~Vp8.-PhzgD $o˜eܫ BDCy !>2Jˆ6qnJBLkEDHi+:b#s<@TEbX&VUbX'֋ b$6b!vOqLi8#>wKK 3e'y*7[m#Cp' e/9QNS4cyO/ɇGqS|F\ _7o䛲Z^+ߓ_GcBK^04CF3#ha$mD#H11`t2537zC(Ȍ50sY`%fYiN5g9dWWG".Nc1]#>R;;8Pcc4F^@>[j(;R%,;S"P.S'-){ҵM]d_ٗ8t N\.at)G dY$([QbǼIrYV )+e%"'KNŞx.So9mrIYrl+9#R?9WΥrG|wr BS.Kh\&]r\A*~$5+7 4Dnh,7rJvن4B;Sjʓn%ʽ/T ʃT(4ZGi<.S<)OR<-OXy7qFP<+xy^RC-epP445B7ieDz/%&adÍS#H4#HF;Ho5#ȠFE4ftFwm`@C!4n <#4c!3ƌfK%=l1&'Si|Q"%_|[# (,?ua i4:ÌWݙS |̙c$$o99IvRW=DH -R[-7BI*R7]*INu1~,9|̜yß%D BD1DLZb=Q@l%RW"5D=qh&8!`2 a0:8 W1R<'^DC!!0xh"xH<$ M&$C)!)4G# ȃW+%2xE2 ^aW+ &Oⵁxgl`]Xz@>PnF@1PnMr3|&Pn[@, (g6 m; XtE' s\<7 oyy@Bhm6oh6-h ږmA@[0BH,`j6 ck l;Vʱjk3X ֆ]ƮbױX6= 6Lwckp#q[wq|!zߊ㥔+x ^V»[x/~?_C[=>=C!`TwRCD8MIr"XC-vM!#&zaq|NVW>%OS}@Sԁ> O}@ >6Чt`PA`[# H4g@8H4-DK qh$ZD qh $GG xt]t: ؜l\z PO ].BP B 4]@h @h F@h |Zx#eHR4#H/B>P=/D! Fu5Fi.6FM1ҩ,#Aq-F(5fSSOrx 9C !r" LjQ7F1(qxn5FQ7:Ba>)KPFc/Ex3D  ĎM{SҹrM&Kc45 >G'TpDjHk^up 7޽Ip@x3suviz:׿[G==GcRopsɍnq7FܨCăSCU ".^w-\[+I[aNjPӻܼAy}KѽԚhD"o0Z "h-z2gTxV;ȜgvQ *J*j} mDs(Zw#9Uq<Wl/#XjTM]4m)tV L*qӯCJ==ecOg@FmKDw0#H9Wih)Q:{s>nkH߾7_C}5LsEQ "RdTO=&{DƃfHR"QE| \CC` }F/u%IHɦI#& a0ib%ˌ.fZBomןR!>̠R $wb[}3IArF)&XG'D-#b8CN3YAa@i,YRʓ~\eI)YJ|['oDN4'Y,'ɂla}IGASmAP  ه6zh< ,ٲtl_wvwɛ8m/fvZ'JvkYqt~If`d_n 7m ,* 튑fSOY?75جiX|J Ea|2Rvyk%=Vo\$U+h[ļ%2.9#yMW5=w+p8<92w~\O ~ ە>xxz"ۓ _Z]>%Ӥ+݊d5#b|hVQwzL/M=Lߒ&J`pN%T#>)>&H辨)H8.Ir/=Tz5|?\o76ا<nv}/ʛQ"0.(Dyǧ헼u2`j ~GܤG.vOvd|̘0A緍4>:K~gM&#Y _iqq"wOrR_~āRJ٩."!R!u.M_aEca/-[_573KF1_RUJY>[Z;NؔȻ/ diVKZUmeX1ukTEwNbNǿ=jzzƜ0meӀ:¦nE|U|!s*C:͕n,igܶKڊglR"oN5^k(lӨ:X4jh-xYl)kjC/ ˧M[3r K f:;,Q$ϯM&Jefc'W@r.d8FZ8cCFNDlF+hD6ksN+'GHQT$?p3T1s4':Nb?R3C.NkH@Y"Yv{Et ,bolU~[CNwR;oCn]aHʨ4M:~^AC+Mo„St[-{jm5e)Zϸ=GKCV?`x{):of-^SYkO[-&R2K^LPkEFfpΩ{i1 Bc)~qC5ZHsSǀ2 bOTR$W \ƘUKZ=1%Y+.q}ڨe!N̯kۯ%Ύʪ~ַq\_"Ϗ\<~H}d^ɠc'x˟uhjZ\R˻^eoJP㹴s^{*~T;=v匇ߌ9IJWэ獩ߓhQ-RBس"_vl2`-l*XsV+LKh$jbl.k|&6YCK:NL*,O;3;p~8G/KvFoP{8}NPPV{LYW$uZWi;Z5SyރE¹zF{W,4pRDrjD^]T 繯{zzު25d;m.g^ۓ83tB~K=r[Fs=1 ;Y#BlslFT*'޶[g:z!KdӧscH%[px@lOxsG?b h 6+ŎkD].|assk#vSs;WOiv08*pjںc^(+񋢚7R GmnT%o_y'lK7<תkH}JK1yybouFfE|) ;"o-XQכkg՚^La#G䅽T.Mz댄Xeތlw 33dDӴi,ybϾɠ1wDgh3\oD4aDl˱sO?26<n dW$E,[BҌ 'N85L\ˇ&6*o0֭ьT%pCnwwmTXUźߜ"ySC2Ea5)W3&YwY(/]=6_Jy~ Zα6z M ER;roԈ}]|:9{р6 4r<컠|Pf`-QQi~ "R{uÒQ[XܦjݯIwLآiv>`AA}у˰ȪW); &uHj]-RxVCX}p3?>#2d5FZ*.N<;=z87ܐ1W.6)X=rx=/J?MyaOi F$*lUՕ+Sd #-ϦLOrUWٗjWΣoMv=69M&٭˭'o{S-R?i)})hUu xdNF#s.oKobډIc`8Y_N&;u4RK~$% , h!^"zfwHRfԿ7m4,qIQKb|*z 1⹰ cpV9}&n;h ~)T[8imбj8ǫfR[ħ֕p@$젃-tDt}jZCWw~J^7qE{ *  Suљ ƣR#̛YݖoY==+*ό{aS\$ýTN; 7;ljmsՠ{K22Un^{L⵹yn{ ۻ> .<0+#3Pog@YJ󇪜K-"%/ķD4j%8kUrPzu=.溤>zK޼;avs8E$pOV^糴V|xv"[;;:n_2ܧ8EymyYwe@C]9^(*sjbQ}FpDݛnb ,cq> stream x}R]k0}ϯcP4[ "tv~M]`m}X តˉIM^(ZpWZZƋ@OpV0N+ΐċyr04IY'ggw$ygz[ۋ10v4%UE%3O4Aٺ~ܼlfY\F& >)S*Zhy3QuGg{vfiPV#;DQE9 C߫[&Z";> stream x `E3 CB$$&H49uO0>]DTI]/[Y 7I_v}g߮IpHȓ82`%K[;UUr[ W:wxak7ݠѓ*G|uUo{po%'27g#}o>½w}@ș~i@ȵΞ?@J1g% _Ξ|֎w@z͙1|ii3ypal%9`njV3 Lwcx .;oEby O)?Ӗ-4p{<^?m̂A}o0Y`R- nh3-2 ei{[Wz()~aT٤omܧ=NkeHX(1>O4dPi÷ۙq@lGv+` " ^]΅$SWa˂I' ``D4$@+~&U0}(UA$]Gce&q?@VӰlLn N)?g;zu!DZ e.Y`0yNcX MeD}+0|E p/*p8p8p8p8N?p8ݍ[hY.7b7B:tJ3@L:ǝ(Znp8N_랜DBEG̴k0j̨ZjG=k?@8PbN{pC<ܨ>&5iHо$HDC귐 I=j/HFM7 A 5iHѾtHE AjL}Y !Ծ2Qs 5Qw4@j!`:PAK(|L@j1a e: #P1\ CP˘C10:sP+u4rԱLp0uD0JkIP:FcLZPa<gԩPZPfzLA-: Pe: :BSQg35up6\E=<:E=k aWX3Q,%L B87L< ,3^ 2Xz9, Xz,E.@ .D5#娫^%_`5\p p!@m`z\[JۏIנZ[a%P3 CQQ5w2 >p#:h@}nB]E7kL7-w3}AM{61}~D]L`64:ԭp#uGaj ܫa#}&'~'ԧAM QPxX{-ڟA4>MC3 ExulC} nhAQ_f @}^qי'MoӨoWx]Q߇?~i>yEԿ.ԏP?ph{2'LW)V؋z9z&6%8+xkxOڋ-|CcAmP58@˟V6=lz2=Mdӿa6Q3f2S6=LfӳM֎M(~ԦE6} PԦ/M/M?lfӏ0~g̦f60̦2lz+̦2O6Sf?e6Sf?e6釘M?l!f1~C̦:%6}.sM?y̦6}1KM_mEMMkM6]̦b6}默Ml.fw14̦e6OlӹM67̦e6uf_g6uf_6Uf_e6Uf_lf0=̦a6}Ot@ c&DQd/Dߩm&3BS9D  crt.9__d-S:E}?(St.&8~4b1$I2 3꟞y"4x|XHt}?qߏp8if~l{|XHz^g 4f=*p8ίޞ638~gŎ~ I Y  Qp89%inY~rgiq >Yd--ōt?z{RߏK..}?5sB&0L2I M&茲h2lp8SNC\.j uVTsBf0:Y3͠d~_oOC<]<6>:B0[,ŢAX,7+ ֩p8}Ӑ.{p NBX jm6t6 V--dp8Nk9 v/1RzUUtxTUMb.|Ip8Qwx貟`Ycp|Xap8&Plxp8Q{-!/X~wݾ@,;t ;8et|9~wL~ 43) B.s.^$8+--҅sQp89%ZNC`6Ot_Z,mv 0n7X]f--ŇXip8QwNC2`XTfh4L2b!}>g41m{vG;buzpN sӐ`ZOt43= %71њh4)=11^kWw4SXip8Qs6=~JX,/J$[R 挤$p$ؒzwKt1:= p8Ӑ*y6O}cX(=5X 77FMƪ9D߱: ) @\\{ Nf±P LIKIV=RzwdΟp8vR1\.{`34sp,6"JtWz!MuwKt1:= p8/rp=hXqXl|,YY,eYYYJ/yvwp8(__Ԫ2|42ѱXU, Y\crss*Gbuc9Dq rfV@bb"{ \bgife,V BNaabaa|tmκΎz; V$~P }$uXl`,T GU1z ?ab%L>̪)]#nOnjFxpE(,蟗ӯovVfF(OZԔ^Rw9vfMF^ɒ(( ")58bD&a´j#L*?L$PˊN.ƒd8Z2+I@efʂ`LPKՁH+ aa)E,IN-e9 E/S_V[k4K%3h4aЄ;e[U_, &DĔi3"'T&$'WgfDHBj"ª ÁՁƌkZT86d1mjUDVM밇҈Qܹj剹 b}.@+uNMZ]mrz EO666JfhJ@S?W˓|vm?ɑ`F'O\ 'df4ho6ZmX 4T11֝(8A$0=- RY RMp ^H9E `g'LHѥ_ `c8 EPJp CXfƅ-B~pvͪfc''Q]s1Y1* MUGZdǜA[ISc65>l${f42X1aJUo+&:B*1A "ř85VF)tl&hQ8Y GQ6&'̍Z#t+:YG3#C'?yz, O+GS__ OkV ½½ jmHj<9d V5ɪ arJvIUMJjU7¼,UXƠLo,+a{`˕XOo!?"DTd4N憅MMr-¦fՕCM lv\>.l-ק:DAOTI8d;1SSb %\rrq&.k wv}l~}m -)} .qĭ,NxCf 9EO[?+( cۛ- KKo qXּd\Mє)*4oXew_-ls3٦9tm~,?.#Z]hj7V֓Rl1X  ) JeJPaҐ4W* JCHiHQz(NCzިuzI/AlCԇtTIT%V^Q+a"s:T|]l!Frp8*b0O0TѢh#2FBnԈ OIU-KI8kOk뫫!bOc}@yOHm Dq`mZQYyGu$+S!.f&t1i0-0]a9PLA VN"rAV]\|\0>pR$-NWXνX$56?k+#H+cd?+)?^$HVHI$e,XhMaPY+0\l.roxMLx6g bOH-":sDI .de ;$ Xi3&[:2fY8{iY%' :TLc's ՕtpAz)TD++"xlT2J1i&SY3E4QcciCGAm28?)&T`S{px;˖RO躽N;Lh#K)XͰ_ frX=p K"#O a 7W=}Rb8 gMڍ$L.>/&|4 x79-" eD '-vx6bö%ir! XrËFapA|^ݮa-'=B9a%xw;Hc#ew<ސC .yv1|K&YBH$.dim64nq2%p9؝(״? @_k>g;N$&#H%#" 6߈|qOB!-LZVіikOqSl_wWUxwNX r >oA"2CG5F&#{xiZ;iolߣY&93 {ӏ}= U0kn۰a Dޅos|IܤC2I6'2&Krr%4$B5O?w'{Y0 6/2L!K+V fq|">_=Tq8J*.?w% &IҽeS;$ ,tnnnt-QR.S.WT/ Mxv4⑞0ɓ(:x>r+8O=yU"!BɅBpp Iu8Ike)/k(aZ)݇]df|Kp.ꮁEKgpoTa'#çxvI1󤍬 wO3Aڄ}df ,wx=s {Aa2ly/yXy?#YB?♰FT[!yC&x-Fc(pж,/G5&_sR>IBO8OtN7<3|Cޑ6}؁ /<:F5 10@ @ZHV nj '_~I*#(t 3-x9"C([7NwNyWyBXw͘m[ZcKjj\P|ҽ^ b"hX[ w,D#J A xtDod5IlEa e"KD"r@H$:%I Q&4i 4m xug]M[`zCEj+`=`5+$_>x8<H=fhE 5ذ_AKJpeCH-BcQ<چkUn`1锂=)=ofMo5Knz/<B[UF[Y, 2^Sdpo+O$ Nn4 8:YvhYg{KB ~G="hz&D<4h`!.+Y.%g;/=Ny=# |@)0ÕruZ<1O/3ԙ, uq |;wKXuBɤFy?i6[葾YyVՔ .":ǡ:ol&k@d\$쁠(ɲSzlZM6n9].Gq mf}VZxA.C;\z ۭN,ح1duLV<ߓ<.'A&`X@#aLF#`4[Sh!*=,V:}BylJapUͳf֚ML)W|/L Aj񌑽>QMn|3Qbd, ]tERU\tZik^LTy;Zī :T&x0pF]HXzMB&: cOfXTlpS{$ f`v.WRNJ0jj] $yzrip!͞dՌG, Bi!5C!J^{$10:ֆUm;>F[`{i[eV^ʆW8A9>:x+.AۿM V4;lj:x5P,w9:l#Ɇ)S)*(I=Scg*;5Sa})\Nw05Vճ~ NL&re/_|S%UA9+M aկWMg/圝GT5t}f qJ5zUtL1uqQHrE 28ʥlfi0CߠجF_0Y^V_Rm$[ -Y ȩ$Mfn="\RTAY tqxr 9t`gXQ{a4s=͘;^=cyu#noڷd躧Aߗ'/a75c(z퐌`PiT^ѥ\YS*?^9AezMG?$Ҭq_#IHp'lF3!!(6jIЈ,)>Bq! (6G%u;7,M2)(nz1z |bFŅcLK/!}>CxS WNXxbW+) mPn\#k4{>"1Brd+jmh,lHđyYʀ܂l@܀>cT9!Om2%e[2Lnn:x .=r]vդKM'&-7Mu;oJ7% ~̳)ud5QD*l6*8qq9wͥ@PIGxS_:P$X+%X*uu8+-.YŅfr="N[٣aN>)?;n㣿~?[V s2qpѹ>[J^q"ˋc8<\{{i/^mnevxڬT׶7 KMmQYzjI2#`L'Kw^w8p>kx֩Ͳ.9D3ԘhdX.8>:="bEXʭMpcX߰ k*[Zd#D{ş ~,HÊX.s _AnV8z&,7| ‘E -,c8۵͞uHTZǗS ?浚y?lېYtҽ.$Syz5FzY:'Uퟚ_R4a|(66F:2JB2uZ[g&hMo5#`"voLEr~)NSZnǁӆ݌c1ޛZ۸4Ժ!R Բ_ZFo2PX&MM3; T#/1& `ǹ%7omuN{Z.7nդt{!\t(o**ʣa%$e( U(4,8rAXyF5nP*{RP5%MKzLpSO~x wdҊCzLp0 /_f]mOZXw uʡ?y^Ѽg3}9v?[7VfgWo%OgtpCmAauIrᚤ~{Ӿ7"iǸiO,Ko5.984py.{l@Ge"oӏwk$M)2Xah(c-laIa[ wڤ7us\y#bˁj'tv{Q]m[G}f܁‹Ì^9ȞekA3zh#>fn]=w((I&ܵѹcG$Dq.i'qq킐\ {5~q2>p[Oc>'¥ruZr5o8qXugC{6!'9z 4Ҫt:)}K \ /KmSА#jO^ӿSRzzfx$;~_勉 Clpawb0sW} kyG@_|߽-5[ܩ63،d\̒4o& NY2HҳvJM0y.?e.h/;/f%Z EX!^Sa<(i.fه&k~l{Uu&ov֪ a ݍsTt1ˇmCͤqVWz/Fi~}FYgM0N>/#X\BGIt5mv&:tfM}vˉ(wqHT@$PE8.bUK"eq&z&%q(ApҴibMPnQ鯝. :?hFܳI|l_1cJ~I屑 w}{ӱ$+\gα#>^hޯo:Fxe}M,=3 4'aSҚˣNOR"DŽ$W[0 IpT .CGU1$% ̜hR ]={b$HTԒ$'!+,|\T|Jr+n%TMvڅ/u`E.luDn6gWUY Y:->ttXC|R͑w7֏_wy\V|7}%X ȯ7 <&e.?gY(y(x `P R +΄xms!nF/RnF͇4q̗Ev 1߱uLq"@t݋ EhˏYz/"yo1IYD>%ݘ^0,Ď䇌']猟>!_Z/͎"fsZ-fOJLJNv3:]2Ż]{dj]d]m21bu|$sʝAbfu{ :@egf^;ߓ ^fRߍ;.UѝU|'Ns|9tujP->yԞo]܊1+Ph]L3 8ߺe6՝eE+|,կY˨#/Dz+H :+3FtT=㟚 k T_/4N־:75-[,OοB\~c:eFA~EHm{.u,@L! wxE_/)/jJPPgZEWœx|>a 6J 8)Q͒-15k*Up7YZ˯ ewuj'#i e 7uV s Æ=';4j$>XŋQAl{0“:wlO8R{I$7 Rjou髰h鈹ee_l7ھ/pVzzzzz'zI7ʐ[ėD2أKOd2Oyx 9o E~" HFZ&rIh" gakUMep WpG>p=& 7{ݴIíIUo pJ3?pOjL,Yb]uĦ5\O*4@hLP4J)俾%K˦Ne(p4zu\? N׋IG 4/QӿWqU*_UWU\տWqU7n݌z&M  I?}H64\F{:ܭ\xQѡ+F}Dۿ+Q߭8C"𾼽@ޠ]J̸)1 :S4#LAF92z :[4ӹbo#%%%f^,=aH24i4Bd5x y5E!x3ׄr6ꖢO>>#CAzлx5j=سBM#SZ!A]&7+7*ʱ~$(dul9(~rn/V*ڶm3!30F,4Bj{.4k%CL1VPiAފuwZF~_G~J>5צߐ ޹3=s- zF!_?#.*KHc*kjڄ-%T_5>1;-ZJx# ZJlBgCC +:3ZyƷ-PcKϸ&ƥ پ`W7qj-mmz&kG+3|HA'{ZcmeeK}hXm$*>mq VVT{Zʹ<+ V56/̨oy{f46{764U̬k=s[gȒa ZZ=+W{ZW<^Z+=~_pEc(ԬF79 4lk yG[ecsmSk4ai'qǷcZ7E:.}зKse޽ODٍ%[lĨu-mM-uW+Z@ 5o y|afi5АvNT &rf #o>7Է^zLzVzJ+~#S=|W+PsK8זƇ5{-VcW`߫x+Kaנu Ђ^I_c&ib7f/4OfhW5_-?y{v;c#,B+Y7{B=єE&!.66_me[!`6bT*$$dnKKv % -e$ #uNzNɧ$Q3ϔ6”U"){NB} _T^e!.WwM |a,@a< %+ >O?2RB̨ɨ3nFatwDƧ6~oHHZWT nV6GʽRIexDyJynHe|()]S?"42dRgk22HW \z!>e,5KKQY7"5>cĈ\.M "׮6Ar QMաf2QMuhz),SN_--sKr_y,A"M;E޵bM+E !s&"Z^Ux V}vNG≋nDI$3ߵ$h9L^"6<@)IK8y%`6ڏAZDe4HПѻf>N$^DgZf-Sˁ2{ZW-Web{D D)3o{2DHKh +}NZ?gVSyE;y\V;(Yޥ>-y;RX8eᒅA"\oD+C;Tt/q-Y]RIZ+gWWTTJRumjJZԲ6u{vYZ9eۄ`cTG-t-54D1[XufGX'}#Y8䣥z8$}Pw*JDY/+OInfݧ: O"DTl? [ O1E%XßL^tsyc [,w[hyjfYG[Xoncf؊lcl2[-(aEdF;)E~o(v2=L{hJh[ ldt\X\ܙhuػ&N@&ZE͕~|R?DΫh{ mOictb]pRЦ?|Qû2v`w}Ne zdRMLlP N{~D);%XvUZ]]'vjtrFw (QR=#&8\2 d_7xR਎ݟYFS`oo-O1?|%Gc}DB'` Q!zg}zDD?Gp&ȷ ®9VĎG8;΁sZ>nAs, skaŝ<(#7aI:a"le"lbbJS8hʡB@b+4h0lhb't]^d" |@ `DaO &OAtOI= 'A$ڞDh{Ny7jl:P ԶVhl(lGAe#((mƎXhlx jP Mo[~~N,? zr IGk=ﭵZsE-5felPkGWkloab+ *A4ӠrTNiP8OiyZgBDt#y}ϧ`/bc`ѷM(F ٴ6=B9"J@`9`9zıQ.6y< M6PJo|.b)WpCk.P\ )*ѦV@VVG_!I5V@ :1Rs|t )vH]Hȥ|Iskq6al:(.ˆO`CcMUuЇNӶwhړhj wh&ThC@=XXX6 VVÆ8UJWd(ĨQjBY |=ʥB;'ypW ppAJ*M{|6b6Qy&18ke`!6Ċ8A$hU&`4OB`+~x.0z]BƉbm=#Bv +Zog@y:Fx|u16jתvHSYesۄ^Q%)Y,$fddbY bHed8† 'lv86 kMa36gTVt,Ddk,f˘Tl%1*czdwFm <~6dϓ&B,8@"?akԆL@00Z{A{7 0],TM--a!Q 8bu*%3r4(P7> |`4afmoG4l<؉IZݮ:G4xYqʿ!rD/zQ o>Qi'jgvq.^ykZoCaȏKZ_n??o?wZm?"ڟACg3*]a~ 嵞mn^^?xM_)iqZ#on y(PIi.wwEaGdaKGBG Ra[$yb. ɑ)azgEfy2Իb1b$=<&'\)ȡH~x&a `g@Ɔn.U<0DԼwA䁢1[~=w_xC׏GA}8Y3/9~&01YTfU!Hw)shS ,i#fy6zȼQ^}ߧēƓ^ꪶ~믻45|Sːv'jCŦv\RH`wrSg`O*Ey f試@cBki9YM[]ʦ٥jnyJm2]# HsQ_sj.`7a-tXe@ڥEڕ4̅eڕ߸ %`5,Mkn?͵6)6;\-w\Gf!>8IR'5|"92 !ތ= >u_kݣsiXzVu1UQt"=u5Xlik\#}-W\7s@&eڮ%3@fr=FB(y2puBKz\`2z'p]W@)ܡ\JXND`%uMAG\:x|~oc9(r:V^ t:pW],_z ~Iz^?p/{a 9uH\^Ş(y;y9#E `Kne [K Y\S=Oow:9 z.8m˾33=>k}Ϩ=:a]_禯hwO&݈Hk=Wk'=( *}ng 1VSYgַCtv55}Iquu]-Mh( eh?a34S=.O,Ʊh{_/u϶<,.´3y}_wh~74 zkGt=t}a p $yV3gAA/ BwqumauFZGi*#cΟ|,BO]1 s+ sf *ÝX׷êYP$t݂{oQ|mNUISTL-`Y`kdwK[-Q[scԁ/ĮcΌ`~8v;zG,㠅}DΰAViwgL u}\\fEz:~:P9ƧNz+gvЅ)u}C)(4ӺDI8bzkhNW׃?$ىk `Epcw%r̂i*J/|*ߘҪs]Ӝ0И5z.` !d9;8.8qAӜ5aB%[q)"<{*8{DkXl$ޟBg&ZuΒ#xo5`;ʇ <Ϸ ݺCҸc:PpR zJW_ËlIa:ރ_ku=~kDk#|}DN4 BD*^2A(A}I#4iXw yڳ|^#牾DeNx]W=IW= ͗xuȓ| b5Oi?_E%ϓ< x11pdvfzv%\gOuhѓccޯ7{3B9awFKT5q 롧Ǟ晐lW{8]$5?Fn 6lQ7 l;ܧa5fhAzРjfR}wC 龩baWi.2ڠ={n6|W+cU.!7sJw 6֠-,6e>ro-54ZX[zy.lMKfcm94;gs[>jҦ'M5i{{HSnۇS$5% v>;HAAli;kpy1^ZyEvՒNk`Kz[Aw ZvjjѶuw tpe_9E i8Ӓ|ג:pEv\Fc8zMfq@IofJev!ۊX%6EhCvWY &ƽ%~Kg[o>%w~ DQʝRS:ϸśoq?Ehw?g?~??2 K-oeId,͒aɲd[tR~!RiX,H}rc鷜\_R[̸P\ޯSq\6c\W$\!W8ępLFV9;Sp,{{m㪹/Dz%5kMmgx_g--li=-R=.՗ZJ,-=Vzd[,=UUz\+#7JoAzt҇?*}\9VΪ&ZKZӬ,kUg-%:Cuɑ0ƇCVZ HV[k@jc[k4r[7%_hD9GXȚ-dNx,AgchBYX3 /0싲$;*sʜs2*eY}^uY{[+"a`%(gY.Lo[-Kej1,ˋŪtRbmqNq~R[c'OBp{ŧ@W|"oxky`[|rm k [[n[rq߉ߘ5Z!~!Vo'"Y}J7aI?l c:ʳA=D0m`_a=m c#-C!1ƱO1_(/w^[A6=HSz~(2B*8B*za./MH+ˇ5Qzku8NG?&kfyQ{]TBIf_FAZma^l)3f}Ik)MeC濪N8bҞk2Ra\bڦ ӫȼWo!} &TrO#cn+Kk>B }"`:Tcd(GIH+2(b}2bB im9a 6IHt&qQ/cЖ bG?FdO8l'"c*~^Hcm*_%~l.Ǭ|-X$Bc%hW߯ȳT* x(?(TETT9d w$PZHp *jِߑY]SŠg⽧Le5jOvQ>"Tx*n:*n;WuVL9żbYXvV:ξn {oWTtTfIIOS| C1>.cY+ﲗmzs$\'( ʯ o?ܲsiz./ȯ"4|."ݍEosi>%vuAU/w!I3JZ}LKҥ@r2uu{tyܡrkt#WA89up׵:uݺQYe@f(aJ㓀E`Fj!|s aN>g(=.3*)aGX,` |{z<쭮\wW J%莓gA@փŶZ&edlSrb,t*aۘB"#l?$V5v}4 VΒ掰rCk1f!6! qI$dW\kѐTW4Rthhhh򭙢E3EsEE EOϊVˊ2}>hFj}BA>S[G/ԛV}Yn\8 'W?/ECECƢ1#A2)TJȠE ΢QC*HNz0&ԇp57ޠŨڢ'ޢq}&uY^t v {rfa(\,PI}a!7~}k&$ЅlZO. Wh$ FH'Q~Eߚ/藠ːO:ؾmAiP| %5=~lĿV4f8 gPgCJDC6#0yT/ 3 z`EaS060£]!ǐom)7wԀ-G;54؊& G ' 'aqő4.Xsh8e2e~2,k:k`l0 n ۦLb )C>p f,/\LLE]GJFF4oZ4-BLVGh3ffc O껍puzf55Xf~q2vg`3.W#mLIoͽ5goJ1cRզLnSdnaA(vzuAd\a[3/h>)2Y21UjMNScѤ_4njۅԈap{cLAT/Ms #~vA-aԨyߘhL6<9d0)7fF~XP4F@k;wh41ς 4?CXpX@kuFч23vO{¼ǩ27^ L V?"!lwƫzq035 fYH5uf#v?⦙NjPԙ 9ة42k9)'=f}ABfFci|̸fzJ04NJ=c}.k☐ΰ3g>eojϘ6I4~m, t 7qO[y!Pi!hkx mփ_9{'Jٟ~9+@*`8mgiD2M1 Ku+a<`/y,ϛ'Ы|*x,u|JE2rH GH6lV7W2ܦY%껠,o,b۟aJz|,Ίx=B$*/gN8Ot>%a*)~>T_ql^F4vqzUbӥ ] ؖ pʉl|LTDX%.w}ĶaNEm 声E.-k ˠ%<ci@%. y%/cPXD>Aj#&{6vP4V!O1|`Lc% ?ӧ<-D@%j/ݛȰDY|-s,`>㵷pT5:>}ބTX[="Ǧ>Y ^|FgCũm>#ɞaKE^ 3yU'F[^yKǜ m[dz)pY,K:Q/D=LQ}fiM;ے>y*b{_ν ~)%Hm]`0X,pޛ0@oy t.>A^ pp pI  )>bfYevX{]{S{°(Nv^U cLԛr{J͆뾩ο#% /N[oJ7%w$I A+vd.}52}/2Y@_}#GoO"QIo@y`4;xcO"K  _ˮx< ˎvX^7pQv"N0MnF_ K4N7ѷDSjrAͤfї@w?ߠ~jɕA67 v`񝵚;ޝӚ:MNi CMN'pkL7Pҿv> H< #^?hvg;pz46eN4 O?[1S'n}B#X1zOVv PDˠ%QFuP"ba<.0 1~0zAz}vt};n@8̎+;w~|hㆹa&~4Mi)7 /Vů@$XqqzvW^c,z4#4Ѹ CDiiuJݯ9>U_Ҕj!MƯմ5tǁ7VFs`9]\&>O4w4pPWYFLFQ25SPfft=yAMfth AzQm'>fQc<ДiVIo7_\GOҔ#M}mX"|7¹+"xxU}:ѡuDs1c! S;Յ >.PQ Wt]e յӨj'!L;;)V YkzY=IW5"(UP qY=9(̓#T]4@B~%h݀N> )X /G}\c#ò@aq#P&n}JMo,q_ށ9}{s;˿&X@,o\_bȿöӗJz|b|"KZ| !\:I  /u. r)ǁZ96v:" gd2{9x`lI1QOH>ljN}["$ q sgZ1͒G+ <R_="WDwI$ ΅o[|xtzK`Q<$ƣx86"WxO("ï{xslGz(7EGa-vG4ן7WF>YB>EFU~}#~+F4_QwD2f-Lc_2 ͮҠc'7jQ^ 76nڹrS Ӑ)+o`ƅS#$݂tbmASlKV><6);?W$a~%6 F)"PZer:cͧ<}P;Uֆ@ZtC)'!> g0@ J=0k Δpuby(ˁ6 ode'>/~7\O*),}(G/7< ~*fK+!͆?ʬx?$_sGBx%4{_^v9/ 0fL#14cK x%gP1 ˑ/ѷ(wS%Λ@\B)%kDOa,yL)>Bq!9FMqIdequosI"E K "PKK&Fr( QDPKo][^2=AA0f/I+%$'Ss/5'}x/qο4z9 %{wQ</'UkI rsg,&*F*sOX7Ffs mGe~NkR'qԊOa4H#L8=3 DT@ApCE.Dq_bp "Qq 1}A4¼u}y~sԩSUNW (6< Td<(\؇J#o!38>;.c јJ?s=n!&3,&$(͉b-y#M/ht|ˈ,$،}c&4AnIb⎃2H:܅ ;7BhQz W`)xŐ{ߊ>k)#ad?Q4mσ㉒lC6 9Q: ZFb8; (b EKXei*/9(]2Er% e0^kQ^0B };\1|)LDhc a=GQHqgӼωLOo/w&A/wb/@#!|Br\G"@/B+_ASDO3h`j3%Ӕ*9y߁Ϣ?W@̣+L*/ J[tYe*xՖB ,A)#{P_MK= ăAS y1x$~5x$B F ߠ=zvR>$%3fF-G:Rn49 ?|XwO#.G9~8(yxIVuw6S3iJ6x_6.`=hDP Qwہf\_D~9 9$ WJf{K'jIQ M^`:4m*mJ SYv5%I\%ݦ2 ?5Jg he(%Ύ셓D>4᭜j^[%Ws2JWaEw#\$c'n0X9v;h& }8>f>Jm1LY-03=x2("HA!mx$T\#b \|Ófq:VH#ѝY򠶤Wq4?QlA/ SO'e?dO<_>]uT{d}:la?Z]4*DA҄Ax%/@zQ Ft4@PZ9(DQwYzj f@GpH4$E | p:yþ>kN:F)џ:5،JD;QE~+Q^F]Ajw==FFI,4/>4ڝehw> |䗰,CA@Zԃ&\<ebIB Dx `0h ֿXƃ@\lYh(JE7ȳٙ!gm+4uQ}3-j@Bx`585i(ƸdY @#o}51h q[,@D!4 D?* Ů*s" $=BX&@oA2 y<\}c1d S@XxĂ`+'@? Z@@7ROPggW!A/d 8 s4>(7s?(0tDQдتRhtd1"!υS"[Eñc uBWI W9J!Se< L< 邝肬肝ꂽI6haȂ'Q rA] 4s:4 B (V/a3XZ \M.uycA|&[ l &~)&%f0ZcvOi$J!gEG( Bv 1#g c R̂4TEZ7¾Ǹ$J%&3Qj z¼c`r m+} =t#3ușa'1GBNKm%7a)+wy/MZ'p",w#rU=-UG6`? z_0pS>K9g wYW5\YlcND녲~2hٳ lr n'ȫ=VIU jJQhe;Q A=WnI\= 9p5F Ia@#M`W2B^zNW+v,`u#Nġ Yr_EJl-,lVޠ.zDw-lp:F7?(UY,:D&M5M^$yK +X{[7O*{"z4/I6̆d3Dx.xYVC]QN𼄫$0Ql[ ys~Lޢo[4* cuȜhl b.cs |6C? [ȃD }K E'VBd>yCēZ >?bƞZ,bUt>g#h(0m`N^K p),1)  ~>m dC'Av+F{fMkO<\ 'fomlW Y+&Ln %)kdo`Z {7첹`=i/ CI6XJg0֣;8H8iC_L3[(+0}*1HYD$+O{9A9iKօd  R rږd)㚊^bm%Z/kFXq物fA+e&{M(Gɹ %dw>)gEXyr>^dGX!'-Kqx4GHGޠ's$Qb Sa1FW"{/4)Qaب\(NuY⿐٭ }C{y[ob@8v8 ـ: <&,t,+,"0y|J!4 g5885Oeޜۋzkn 2TDyoGu5^\o6p;q¿7HXLjւ8܃`p(n*ĥr\&r#IJ\9%B#)b'3 >_T|^3^ex-_XR }O|ޕ0z_|x-?0#{Y}%ؤkD'| jޓTx/x-$>`Z*Kq\$"#'ȑ HȰwDF2fܓjqjqjqjaQDD+GD'GDOLH_H +@D,4T"bDk%"EDҸ nFJDl*S" iD^^1Jdȴ#8)qVJW%"Q"DP"VH;%"핈tP"\>w+fy̕qy7~J|(qF#*qe!J\q_GiUD+DdQJDF+GD*D$HHHP%"㔈W"Dd"D$BHʊR"DfX%2o~{;Kٕ ;t,^^7 e)l$E5t I`7El B"idl9rnl>zq,pӹTjizUK3ZJj)f~n`>0E5Xi-RGU=UգͮQjUThnUUhqUThiU"#;" S#ƸkWvoq_cUSA1`#o7]79Q{Ӽnt$c HU*JI` #"}4ZeuJ*bΙQ8'`s z '̩epӵ*ztJ*nVIUH~&ϊyG5N8Z[;VW 0.?mpi3U) BYnqaWCvq5=^#d:΀&l V^kYA|e*!Weg6eCIdZuzkZoO &ojش&ۯɷ*magо>?<=sj MzƯɏqчe,̒OqVfպѵc5g:Yisҹ:~c'DO:m?<չDS|gtp>TOS3uhuR%c4|x 3w/&qs[?Pmu= 0fB7_:f/ g,{hky[~T;p8@}B|Ebc4#a- c+WOâj4`sř>Cλ2f=o}wgk^U<)6瑩~*enٰNɃg- nθ3lMo"2NMrgQ# Exq.Y=SNm.' u_UU0D#KCΗBp|c$ek9{µȮ ^Dv4Ze}ݚӶ~8WF "ǫYw{wBn&^PfncO?uҋ7=\;fx6D jjOFW7{d:ﲕqɣ;u IJn8MhsĢ o>;7~2îM:uW|mO I}׍Ԯ9j$&]u1J~5}Vwh]?Y6g>2Xvc;厹vqjú;8˟$~2rulQWfI:)fr29kw՜,˲FUEщ-7/i0cVw !kn?pA.*FNu3sP."(.0i"A eRZ&tL2/IL9s#NL ӎ8t?5űz;l6]^Ss;ǹYףBq^_kLY3~kg?ȽxJ[>7bKqA栖?MϹ==n/W&gc<󟞽ےۆ_޳ ^'7I-3k[4 *Jٻ\j}ؖEq뺍ypg_GlNïV5>ijY%_YLiU]$4% %S`Tr%On3GL\x˳6J$xn\Z9 XYQbNȵ4'¡%?r"MŞ4i;t(Ҡo.|n|–I5fO, ~F}'[__휋 5 1-6i];-~etN23@41oVdyaaJGRfJQNjuVl–0‰Dz1)_ԛX]>蔄ߦEnaxW\ydu\ 9H0Dt endstream endobj 4379 0 obj [ 0[ 750] 3[ 278] 15[ 278] 44[ 278] 58[ 944] 68[ 556] 70[ 500 556 556 278 556 556 222 222] 79[ 222 833 556 556 556] 85[ 333 500 278 556 500 722] 182[ 222] ] endobj 4380 0 obj [ 278 0 0 0 0 0 0 0 0 0 0 0 278 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 0 500 556 556 278 556 556 222 0 0 0 833 556 556 556 0 333 500 278 556] endobj 4381 0 obj [ 250] endobj 4382 0 obj <> stream x}SMo0 +riHi>ni nC1_s,4m[-wV(ViLRM3V۲ B'^v=nfY&wAv7Adkو[tru_EӋ(sQz(r"$vMu?CKnjkue4 =49j+G"Dc(%ɟ*gi]0MiuO4ɖiA9a00a'9eZz꤮RHKrJgi`5_Tk ɹ\0^+',3AtQ DRewhq\!9IXNs2'4bm:8iBEE1FAJ|0Ng*%`_o~T{kj:Nmh nlv^o endstream endobj 4383 0 obj <> stream x `E= 1d˜p$!$!@# W@A@C.E"( (0TccQU ,(")Dz)﷪@Bё|إ ~8ѱD́%=w}|5Q+mذo^1 Dl J0aëOLL9~!DCpT&u Dj(8:on쉽>~QC}]M{Us k~>6H196N6fO@ZsSCTߘ$_j}k7G:7LkV:vKԳ(x_- Z;.wdi@j^dS&RH?~M[tI0&Tq%G(B2Ru]'~}&E2(:Uѵs5󲇖$::/tr-pS+Vu3fl~#e@*c] ql?O ]~?ʟy@_gjy/UϲAeGbﯤ,epޯ9~X1c#o#m_ϋz>th%KrkJӂL7QٮKXVk$7 ?;Π04Q5>EcAW/+9s +NƸT |Ɓ;A uig-OYmp%\ W•p%\ W•p%\ x.,q.KSn^ciſ7eqS"-ʯ;܏;Kջ+JJ|A ?RHN!a9IO%Q7KhG 4zS+KWz+ne7(nh\I\Y+ntܺ q{6{=g/7gۗLϧ"( Po0_bi=eG#/+*yQ6Cς;vts {uSϪO۰ڶmC <Ht,ùVV#> ~j-` rVƲ*6CSIde2UA4lzdRF:d"3YJAEƱE0vLiR}ە;;]Jnerr/g. qB;ZOoZlEDAL6 P C쯴GEt+-h -eD1:wНt7rCjZujw6 Lbc[/ӔGf7;J}UUN΁Ǝ=U1dC_3x`QaA~^3g@~}ݧw)]vtZ-fѠש BGQݝT%9SyQKv$8^e89'^)r:/d6{?ꗚb/t݇ 6G>%i@Dp0fBwl;,)lZ] ͬK/2ӺšZwI 6!RK|,!mʲOu}Mh|ur@VkpPZԴ(pwh4Ν((t';Pಋ'`n}aoPy/RO1$ھ#ny/vKOj%$,oqxD K]"nr%WjgQ,{.^HCUXY^8ޞ~vT=~B=ך&GA.Yokas4䯩F#&n(u pGȀ;I.a|7UON+,6U VmiݞI=AI*lrNtWb~NbJt_UWGasw=%hgԎB.-3MvVBG^?a(Ѽ~v% gG &]*?4862AQXn%eِpN<j"7PW{a]%Qzt=bKMĕ4hI|n*uJ搳Z\hgɈ>[,JcjvM&&^_ qņA5uYQTݫŷp|SPX] ^cPm/VZk~~PKM“`KKli(WȾtˣ0%:jsڱk Oq P;~!"d~RפJm.T]O'Jl udh&K.fԍ]"%QRt15 v&c+R4,ě&Z-nswO4VVk% 8mE.J낟%*`_ 2T#oy]M{1;ᒐw>1)*.OpNNM1]%75_텸eP+u9]coQi47'WviKsN9+͟9#w|+͟FҜki4_J4K4J4KsB?Js\cҴIsTP4wҼ/{]iޑmiK[iޒMiސuiI4Ui^ei^4/͋Ҽ f4I4HGҴJ"f4;.GfilIiJ4K4[yT<"&i6J4Y/̓Ҭif4kO+=ҬniVJs4+S;if4KY"m,ViIs4 Y̓f4IY̔f4(4inf4S,L^뤙(M4Lf45TK3NҌJTJZiFJS!iʤ)D f4H3H"iɕ)M4+M4}-M/i)M4ҤKC4io&r*[,BVĖQ6"ǯvJۦa (ނx* q]B ['h2S[Ѣŷ*syei@Ey#)s8e6l.m;MVmڕYʍ,7~?)ԉuRWdTWUT+2Vď;Jiut22"H-)gz,$uxEp6/f l_1V̜Ŭ( 5"/5٢1*Sɞx'kq>evs@ћ{FT٩r{z"窄Et!B0v!\ 9'{!gY! orJBrRȗBτ|*! 9!B 9&䨐|(!{!w-'/B7.䐐ׄFȫB^򲐗r@~!/ yAB +9! yF! iDBKN!;l,-d<)d'<.1![<*dGlk!<,dBuBrBOj! G*!w Y).!+)! Y.5LR!K&d[,+!Y(d2O\!srYBf !dF!7 !ӄ d)B& ^$!B2QHZ!R#Z8!cR%dQB*<kR!dr!eBJ.dB,! (HH!B q 2@H! !Bx"Cz %$KHO!HtCHBR=XYdOX"P&wYHD!W q$$AQHVJHBbD )$BH0!BB؄ ($<bbbbbb Q0!A9^.gw[' 8 NW$|>O'cp@8 >=p *o7up~^K 8 y\۽9,xA+hO]`'hSI<X81< 6G&k< 6! X-Rgc`Bׂ5> `% wZ[aa!fa=qFrrcc#Kn1q:%sW~р>}Ft]00ǦkQ1s} 0@T| yp|΂?3;-+p| 18c w}8a[x^k7U x`?x^x<ݠ.ہ47[q#`z X` {*p7X +` K0[ nxff0۹`6 xdA#L7` @=LuLA X0TѠ`$#@(%`8k P@.p٠ z,d z4Нj+_* s!aV]HMFjմa&oŴU: , 4},.u=2D #pKO}g ^V0wJqIKH;_ߢ ꪵZCo׃)1k&!KtIiͥt͂LEt-E)bKh%_y݂SAWhyy۰VaD`;U?؃Zۇi#mˆo1"퇔'h+mfoRw𧍼t.tBY̖l(V:z v͠iF h!Z6_Z岯~聻A-xV Du|#T7^Z&mF˟B=#Ob"rod߶ۢ} =+ZV=Gq{^D:H/kt=~e EZ}:F_9>8|19Aӧ}3  r8bbp 'b5WJXIxrk_W*)̾*[CUN5YYd*ΰÆ?k9KG.ldxJVr@;qng hӦSl]bv0ܧ񪼣n5˧_dhvIAۻmCݖރ$h)sfFVÑQaMЅEř׵j_Z*W :NoRh0[Lx)w^ٰBY 茆\^ǘi!ON&;&4OfdI}(c_{$82TUWUm8q}셇=RY,:RWoIڃ7M; Z&gH[`L[b!179z6v<4};5!$n0vTUC23(aRZwq61k\qOM?a`n%ŻY->k-=Գ.3;zЫیnKbz\LWQAWuaBEĂB:,y!K jV 0s= ƜDl ;`&dfDFE$%9:)ᡨmo[_xyUuo}_q\6!ӵ}`(?Î }CBTyaVt~ZXJJW;qcSn;r__hr9%5ܭE:6j nșw忒l߿͌w\'Okrx]s`郢-Ll3ճ{ô:xG/(/@kVƵ yttQA&P6#+J_qd:j=68L&%84DUq>88,\6F+N33&جu`0XCCr-+cd𯩙|U CfH(5zF6_`m~QuU;,STkEmqvgn}_Mcٻϲo_^hKYh)=w0b .)\բZL\C>%#''3;{~ڼ֖֖u»`Ի'Eq^CTX(5+Q6peQg ؑ/C.19>\\ҴUH1ĕګ]jtK+I7ۯg:ͽvaIW3rĜIj-<`8hަ!Lwt7&@AE*`S_9)͜klEyqE`yҍPYR=6?􄺼yC53n&q̣X;N(&LcoNKbq=cxܚkgK&;My*&Iwbc1W^잕yqӤN*=˰EܕS73#'ŌQ Zk 7\1Ley4 i5'z[ꕴSg>g@Hdqnp#a \&܏s71䝳"#y%d eGE |zbҽ=7=F[=w}f.L:|hOd>)fz=6kHz=7 U5ȴ!2jȬ!{wL _zNrUm `u;xv;q%]gᝯ-:?_h s(#vl@mGGZsCٞ,~hyFO޽sg>1m=qyܹ^mnsƦ:uڅC^u?D(Tf"uŤSsOXszז4Ȗ91xo)WX2+1/zH95o@VNcfC'}0c`b&]h ktZH Yuvs(wB|oR0PkpHEg 25UnLU0Ŀ Ffã6mmآ|䋡XFdcjFm yh){b7؉[wZ_ iEnV2ZTp f h`hsk뎺>P!&A[ѡQ~}l0Kf[)eξl_&nv+l%{i=TXw;&MU&=T=;xʹx3NH|2{N՛&z;v>t.fD[Z)vpF{ TLo Bv23`_62_2gU-f+z݊ Qn*WŦf?9L^u{ԉu^p CI]xW1i+33'_ YT^D?,+{l93*q%1^>/.{F.)-NZ'\DZ>ҡG~уE|^/ ϸ=l=b۝pS}L{pa <-{퇅.3&77cXs vX{SO+W'*cXA3ojyb`٠Nkswו/j3ֱY1QI0Q(x)bN`WƧX\sjiK^Kǔu{I֭[ V Ö]R?kT.!)gg482fskw[ pJV>Ld GYK-KeRɑO E}BԢ[vN1&u:à'\tmgUwgm _Z60 m>7'/jk-Iejw s:Dvm'꧝Bv[J 06к4}۴ h9W ?)Eiٺ1U6>p{-geIeTyc Č1W-~~Ϯ7ɲi%)% !牕Ӭkd)2 "Hl2XΓr&d_\3qc:"heD)+!˖t&|ZgY>Xqg+{+VF{{Xo.ؗP5 &tPt:YSxov^{u]ӯ6_} xSU9fߗfk4i6mInIBwJRRJ""*"KAD"XcToqa*K/9&m8? 67{wړ@)ȇE)r]^Y?<A9,;yN/X  3A_B3}+Bn qȱLe^H}*k$r4 ewVR4PC$vMJb4۵pOߔfaB>W]/+0uʤJ wq_㢲9 0`έdׇL#f0oT'>BHXm%˧e3S3<ڢ^6ӟgg [o(*\J =u9'>`-t/a%FÇ2(EuMQTsn1Κ)]MАgN6dOl{]?Mm8 H?"28/TыKx*EjdL+-3.EE=6ယ -U1ap>?7~ L>FcbGrQ@c}vK4yD߽tѧ9S3Y T;N.7cBUnsChV}$ 9x%QS@:+JVlwՖprEԻՄ<_ܰ}\yA)0Y>;Zh; A _uGfI&+Q9Du-![i9"~O\5v@s Z 6xcnRq]NEp~&$\61EI;S YL6P/k-Y(#)/k_*2~W(^LP[nBzۛQl%o7y{S'R9"xav` _buZd9k"uQxo|RT-(3Ͽe/W t|C29|F~By3\R >שaGzbx`|}jESp_&M/NoCëG($5OLx1՘*D9vD! Z_EQC*Tǐ"gC6 "w8qx$FL؋9Ff4kM"ɓ 3:/6l^\;tqѶwyGE!&кrb TJ^4bp8jy[ȟTVј3[0Pߥ\hO<_+xoBI-UG@,cG>b0`r!&-zU3Gf.X|BLb?!~]D|P$3  w뇢RZqg z5(VNڙM3Oq]u'5Kw"ƚwmD+Yq qkN9.q'&Yيu UqkIS!^?,G.D!(ˌQ1[BBQ__pQ+6*1<Ǭsxډu%W"!?T L&1 cn~"2@aTd $.sE<$Zdz9MqPCiM W5!}Cd :J!RҌ:xށ!59^siIԘYfufی:7 t,~'`!_" fGo7K*!Z&j;ɰ.?<&lLG3aHJKI4k¨B])L\H&(nR 38t|87[{\̮߳\>KDZ o|tma{d 35i N1[%j ~+WU!r4#b yJya< +A ÇmˡX\0cYiQi~2r!f o]X*Er4-Ӧ:1RNu6Z큊-޶2G%VmOV4,(X20\ȁp# 4ǸaJ$Jdw#i[AL8M+ X֪u݇o9$wPRGGT3=$n,p8c$'RdeC wZj'K)/VNLoI{ W#9s+ K#N#bbsrG#*@:))Wp'Eho5k*Ί%xOV~E,sJ~xUێWJJRY;{87$*q\]5{2ҽ1k{=s yRAQZ,N'4husy@MnG< "qakM3sϬ4@ĪL1\s<ž,@JN y|@أ@(>.QZ67w¸Gj,gx6sjڼ($lt60ɫAZʵ4za=D+uD"+"VK:e.,ep%~k %׉CQxAOBbhK1FHM3Mm,N um(J̚<9ᨙ2*٥y;#&2*B$#M cQVr)5UbwbN`E!uH^ttǣJMrv.}M@sV+\d@#-9;}ZμC<1Z9xiAd=!avڣE+ٞ_Rqcgw ՛j~eCq~$2=ȴ=/-t-|2I4fL x`ͨHJ.ZZ՗U77z@Z"vU]XE+5Fp3m縰yn7Hg4EooP8nǡv"BCYo?=L@d#$ZN"ئ#pAjX/Fn7 llQ÷]MCg#pFd"I}$@{X'C bC; RK\GϦW~_$WjzuL;]3w5[# !\f;ߤPГǿwэ% !ׁn>23|d9<󡨀~KrlnVK XAw1܌"]x@TK %*eIt·e\)^R3,a>߇)68 R21OJP&Q\zbdwβ@&'R?<-}UgSYUf Qi)R3beШۦrDJW%^ljOG8ibTHHpFV[XW)+_?<ݜnz}Ov$o1nd3O~ (^#ѳ ?~Dt7j#4#dt;نJ0 ,< @Y+*CӦM ӫ dwK+K_frKK/{ٔ7Xp0rI';.)a墏 } !ą6FҮduRVELv!AJM< I&Ц֬i-]5b˭O 0s١B0faiD{Ka[$7+j/m8.%&ylzOgfmVڰ{7p-\8|IC^ u* ]5$mRۛl'5eƏ(#l&WI*.$Wk jjj ګ ֏b) "2d%:˱Ť\g**ge{|dw[=??gΩ UuY(6ӂ$'eST,q;LwУ= l01Y:;zQeL`DlM~I/U E)'Gʹ/,.Xq|>LeYE҅5)˲ ~زߡsQKB|T`)[xs<, I'|^~DE>G,YGYr_Ն-3—|dCR{?2dYT*KBܷ7vL-u_t* ,=[oȲ1%;'8?J*zJAB`p,EA\;4.~,xց\<}a#(u{>{w}v:~4ݣ].`aIs^W_b"Yy;) bqq jX2 ^ gaCcOlo| ^)zi.u g=SUykڲ;V_@g؟޼LGhUJ>;UvkSIe}QB(BPulWRSt-nL17㋊vigo]dڲٝ/-5UvnnILYQyeL4ڳg^pqVni~|QHl-n ےs' * մ].wd2=P< HHP\DG!w]=^+S y/Vf$j)劉7k 0<SOadǍFQND8ր^"$QJdIh1^u8ST$q|nz2*Y|_FhXMnSIqD\Q~7zW͓ᾎUpHّ v}ېV] * o*BF#4a01h2ꊲ{f4a*/Dm-0i|r|s?~qK^ω<>Y™Ԋ23uϒmXשڕӽ5ʝ#&՛~ѓi-/.Hy$ T'7+tX-v?!Åݜ7qVC{E{p)9 5$&$| x@.<M$ʕf x$4&W"l̊Zv=3 0I]T]E-v2{cUBhA|*rqI~Yޑsf3=vUfѝk"mEP {JguҶP, V6nh4/X~9Cuwߵ7T<:Qc ,~V^ZRTR*\et1w1#D=6,*!9(V(3Y+ܮ *uC_rb6$!zl-X'?~:`ņSk&osx]-/93LŶRrq RӮ}3"lkgIit_a$UZ5739[KF֥6Ug' ƍ@n<HVh@(Ŭ֥R696?S6kȑFW]2e⪒yi[ïBj^::(^ɾqϴU=#&zE@&jjh0>8\oGB! QbEE$XY~9*m߃*-&̋ɘAx2߱L< 51Rle `X~:RQ8RlHRC*) #_ "|iICO*2gRÉsƜP}77Rt`2Ѿ M ̺|kI΢IM5.{Ytg`J yї X"\T+T Av4+Z-6Z2$a9[cexlJTeff`ruP."O ݓ]d%Trdz߶aƷ)rv‘IJq f@L:.~Zs3xX Fn#ysE#FQDas!8B~r>ɯZDxD R2QK&*<%G< _WVae{&/OKyg<*Y&&.+F& 4:8,AV1pAq$\H2'_~qv3s5w[G(+Y0ynբPKA!DR+JgM†39mk2::=E/.񷮨J};L\h$%9R\66V_0j=U Nae (_ú}5(S3Isg=q1z@*o2}}__WCz66`6`+&BS~`[˶ϵ&>•V W9=pׅsg9NG<XF.-!49g+;[mȶ99hd{:鋝s,cFзڙGc@c#6F'2N \F< Hxٛz w2|gT :P3Y4Uk da(^MdŞ]]w=&ͮ؋B"lQɅ<{Gޜ. ?m<6]>Z<'/>l~|<{S+Շ#7_H˔8ʀO"(:`A|ݬ Wq5>\f NYI9XSdAmVb)tp~ eʷ &U9v~J!O- >p֭۵noDU :A^;C$k cgdoo:boxaMvSnvܲ0Z]0[Ci;\HQҎ-yL6FppamPUVnV0)#ۊsH⻈㳣Q!2J8J Ed|r Wag(kOz _}U׷^p:ԆdډM#:Ś; `GT.h 1Iƞ,5xc6$ӝ9[':9 ޚA./[њRYbɡ'v)ˈe&#HTGNR)`5''섴q"dA.f\%v&y,l_ܳdCٌ<'q{c'3,I ;K//{_Fu-|h_,/xɑ=e;/rlNB6ٖm9d$ ,H Gy~BҲ(y4pJ[MC"sdei_}}̙;w9sϽ393z|ܾPPgR*bm-%?\SOX!Wx{Lx~_YGF`xDϾBO= <}a'~}gbdG/ 7 w ACȂ*= 0dO %An_v/܋Y [#%}ߞWTɧ.0s[m󁎺̪|ӷ5,5WfU)~%3}qz H07鴙 MEmچ5|L|;^,''1+m:&$SZZěE }&oEϓ2(~]g?MfMuʎIE-HQ6+19ҋYX]w S%LL^E_:wrɞСMe|LA~RY뻞Z }~Y.KY};秙T$y4ғǿf_ƏgmF̽'e#υ&5Z2rGz0DyCu^7%߿{Κ ܟ19U%;2^s'/y[7"+3)aJ>作SR(ReWJkrt|eȪtaՀ#0|kV K( :w %?gђou~ugªɁ:}(%{:- ^y3B[O,m^Rҁz3T3e.f9^NB[;0󃏑̹p4_Ia,9+c^oHfn7K% xIgBߨΐs#rMmȅ 8g߅7// +qnYZYiyƇr W+^Z,V|h1y2qYCw=ʬD#ϧu3'L>؟8=>C#id@N"SRBBb3aV{\iWhJB*$K37 =YX@^HP\a,u4" 2eH*e}[M{ l{0S6>O5#l r,9Tr0==x[12M$YnqL&Ց͂?p5dɴTmn{VYZj6dV:eV"ynW%lԣeㄬ$B6%k~UA, Ӱ)(-8զ$O;HR@|ӌ664J%b3_5#"Y@Qix a] 7&!$@$_.yz]2ăWV(v˩؀,e`V|1*Qȶ+KUX|N2RL}K6T (i rT*K(vKJnQʆ@ LEH&'*.+8=3y05Q  &,Mea{H e~8BƏHםU͗[2l^/->[ s+Tev69dC6K%~%+b&K#f{mUf$WU% !ゲym[{oo2K+Ry,0?=)%uuƢ%r)S/8TrQ*Y1lu\.QJA+ذg#xǖ0> @XJ̮X-JP %+*(zB~C 헮 z((Q6'+ ɠCba:'\vM3##X-KCG?#AӰ'8c݌`6A"ɭ#x!1 \ ΍C=vFVH?Qݐ)ѧX6ƮJ3G e17CyxM˯ 1S_XpgJ; A\| bJV.\e -f≆ l-;;xOZAB3'Ǯ_8%Hyzn|LyPKg[B%n_,,l޸4ҹycSX|B}BBĵzGxU^j%kK/΅-.<~HXP&횘p$xBbV$:qQ\ܯ:cɲ"{J>6w+9ZrP'jӈcuypVʴ*؎h 6"h~t"c6{)i9VjSչE}Uf;)=^WlK//ΐ+Kf}[6Sz=PKMJRdg9׮QY lj,\e\96JW2ϏF*hW4H.N7יu"(~ 'KusHJURf:es[8 cb%|R(D#D#u*wnPUrk=p^Jc_cMc}Kw P|ul}\vi6F*eNZ"B]jw ¤Ű,CXVv (.-|ĨvGE2*hv=fBUzgJ]MyBx81Ӓwy4iJ*O@-mZ'=TP7ziS~3"8^cW9LEG(7ٳ+`s0#_%'Kk^tOou{,FX>#a iM՝TgVT^ YհH:^XVZ,k-Xԑh0M4 /E%lѡL$0Yq 9 k+$hbKr)YQnew`iza^zJn1ٴtCDE(aŊ%f]}ÃyIE5j%iZ7$3R&1*׼<Ø_UdgHkHM*.iHY3/;!'k zta}B+R+#S ϑhbXAǐbLƦz+/7݄c ^zN JѪE=8W?(zB.p^`B̶F>!8:n@s?\ '&Dŵ hb&&i#kX`I4',_, ̧݆mx4}1o͌]*dHŠtY!^uFAy0m:y V[jē#[0wS,̎@=ۃ-w?pkOY5MX` # gVκ 'zeFA4Ԥft mHYC #ˊn+3QpFr.J_$+/Hg+JK/pέ$lP-6[f, }0J@c<t0̧J*)Ve!”@4(Bd zG]g݉3CIo23)Q\4WFCIA&zl0"'.j*p$1S@QkDf^Q/ 6j3Wں9ߓu3FeiJEw%|F_alr?+E<^d*aH (6_gƅҐ߅^xz` 2ɺYi RD&\Duy40*>VbSߜTΧe~͓ژ-$DȠ/i谂W9U!RQSZDL8'K.W.sBp4 8@»"'6ɑoV'GԬM'ZbXvP*`$18,cXvOE /h!<k5COb7?0:Bh]I"iVHbA$/¨gCf)'$*"#TlʤKY-Ѻ?FU%+t[ڪ⍣0{p=G߲"~.Ntoēkk}:~:JLtl,64'=2E#( 6ږ }i \|2uډ}w~cOTƒi@*$9yW>$g$q ڻ0Z\) 1@mtEfa\KbmjAuhVIh]ĸɖi RNZyp!Nf+;t䰴K@ViXqj*\Aы(UKҝ%ߚ_]?W`B1x{h;=P~f8%+(DZ u>G)ʒbCNkĥd3J-;~<ВŌ2:,Xr:| )UL|t5]MWt5BEL&);,@{gV򜈳*q.%_4\K".G[D\xRĕH}勸˶_="A$YO8FrG" F$[Ĺ:qiT ]yVH+Nkq%?R_ "FzW5U{kQY̛ \ rpAE,ҨrA.Y9 g,\ rޏxdE%*kCnԏȇQ1 P̋H=@Q' a8{.غH -zRMH<^c!Jy)rl'`O[AM/mÔ zDjCۣP'HS.y4)rsyAZ$(T䨋;Y#-!pSa<ܳ@G%JwT,'DQ/Ad<".*Uh>hth‰  6Dxpё<.TmDzU^Pm_oKǓJTSRhU!K~gB51<D Nѷx#(ڂ=tl='~Z)XOEs}׋u'B_^IB_9K=/T"ʥcHX޸8芪_)\@o׸ t(C֒ |AA[{<|{h8;]5P|gwx{5xŻ7wC;./㣁 P 9is i<0w$w]?ppI@p7xgnsMݤf!?HxqƐ7.y\xu|w|a1 tܣ1<&ǹwzfAwy!J~ TsyAB=.w^yG]~'P@îB~ ĮlqTc.O'i|I`-WHHSnA,}q/73t} 3a\}N`h`Nи鏘v6*b=,ȝ/-ZvqpZr:yڟ+2w+n"3Yq ƽAlu?0K>8 UY,ţƋA0m2Ɔ7[DĪtIUq0tPPsށ$GT DTGd,v`?HXvG뎘 HAc~7TZ0Ћ0m 2m]覼WVV FP:ؖ`uynt@FsFTa&K:.%[tA5ap :=bg`lS }wZ.PC )ɾqbP9` 5^c;x#^b%x KRp͸ex-V xn ,ĝw. {pLL30- 0 Qbٯد?Ϟ{$/jq*95U2_V/e ?~Nʾ28WvAB_˾FXN^aXg乀 cR,HY B%]٤lU=D gJ࿙r 1?cd663?Q//<?8ÂL |} [[O~~SSkg3`%%Y@$Alrq2*O5@-tDF0KΥ2fss\f +Xpm `)W +XUp5:\=Fb,k@\ Ƶq`cs$\.h\еe_Ьsr)@+kVky<`<Q}炅`%R%B JvR.Z#ZۿA C~Fd8^D{D!Q{ɏ@{ RD6wt4!ƣ-.`RwIitz(P)| 8}N91GB#{`_?DEd_4(eBBX6q [×xRMzY9}BOC>%u>%ևbf쀱HH?*Fj9d\;VSDLzdIO!.nɾ9hyZ-rxa$-+Pfyoq2/j [rP^]- ǭ+"[fus-EA# GZ?" -|%!LEKaV@_D9[c}<'-L`tI{N6ye#(yEyh) ? _DlEJEtSgq)L0| K(,p!zŸR3;Z)!Z?x_맔t٦[? 5=%6 k~q5ClRpNஶyVp-z(p = (i.tk-_["pG۝.N؛{)C<){o=כn mF & Z$o}Q@#z4Emj;K۹0B6mkW+@]ۋnO&uݴ|5 =>κVV?-DJh)I rXٺoђGN>Ui QxT,!_L .Ol_)J٦vϴ/| ;B׵箣=#(pI3j&,9Pi pi}>B~PiaZ~\fu m]Qڧ(fc)Z x9iAۜDڧ 8D:)#\9ӑU^9ߑ6QBKʀom~4ђv +z7\pcPM6 ?D9>Rcg#vZ2O9>ʏգO9!G[s7V579Nċp_"XӨ*8s&hKf(~@wڼ#A)ڼJ>"KĘ B-ƔbBJiJ)#T#Ŕ\ĔR)Rz")1H1 )MYs\{{_~93sfoߘZrz^+䐅ٜٚIl^W2gg^wpQΞguv̜*q8sGf=+cr9H'+7 9]F>$5;35&lyS`uK6|ut@~/۝_nj 6{{~f2lNΙ%u97gqVenºBך^,-Uh]1&w $Y H@N;Zݢ;wei _ lӶ_hԋ2-=<\3{NciNtOvo?yK@CfO(7/>x)n98,p~ h)'NNT`c4ir35x<{sD`eރ,?xtu4s64p9J+ gJ&DN(g--%f1?;l܇WwQO..ӆ/\&2)ma{A ;1dEAB&wPI;8\;Ü=@,=+؛K~-3ݱmޟBݗ[/}lw\nxe-;eE-V$_ ›(TumqrFTƋϫ7!o~wJ{ෑF*ک7)Bq"I$dqFq$O.M-G{]%##G)r$$iyOEѥer4XIÔD%QQdiI#(?Ϫ+xIQDOTGT[*7>k~wWc7);j#}O=Fm#mbQv-N#5k/ZKW]ګ}F˖jZtDIkZԮ{{N ڗmtF֪=mtN{T[-hk>RX[5m#Y6iHiiyE"Gi?՞k;]rG#_#k(M{GQ>T6h=Zп%dz $Cqi(btT%fj߷5oZao5!"S#S57F:h-MkiJKZ=/']6Yu)ArCs/W+!77W-P} F_oao PM3] 5B 1C3Q( =@E2HHY42t!&.4xN'_ʓn$d9COW W>8>Q?e51}\?ƿtj׌+1^>N'Z'v~yq|R+iǕ$zcяVGO'_AX:{jD~Pj2~Jh1mZ37i$=$Jh!]K 1#S93 $S##/d굊_Sb;(4Béu)"D_!4oaa ŷ(DoSFrk`SF@^E(V},%Rj\ݮWP]]F1@Kth$\\pQ_F$P0>0+i=jC5jD~(-m3,$s.`LPJ`l2۩R>0ҭiݘ9sn}AaV=D)32I,gq8mjv NsNs5jnѭ1wς;ٝztSSԟ:ΥA!Kj܅YTu(ٌ@M JL6R +x4UZM3@k(<^Ck {)iaHQ\^EuPl0G-F9qotovov5utouqH14.~ hmtk\k;^>D>JqgOϸϹ/,uxd>ū3Žİ<xܫKagC5)L&3Ngh?Ⱥ2izklL>Bt[x˓)xJ-2\|ʭb jN=՞eFC;S=4FF}[i&<-zx$*iqLz:t!O'O񄽪W7ΛUTjjk#wiXծbtoHDs$>et]ӭiʌ?əFq9} Q,Xnɨ ^aKJGD;C eX\|GqQ먳G;)68ͿM99y.NIBc/VGpt:ݎGة:#5Xg3љ zLwfڅsGtgiY,wV8+mK8u"q\B8.wtvusnt[c;He'I}alOvااHL L/x,٧JX( UQCVjMUYj/PoR;lP|A-VbYEW=O?-'Iђ?;B 8vpӭ9Hdt >"ҎN;fx9VʼJXq[Mq['n ?9d\ w 1\2ڈ롲x5>a}qD%p^ 5:$e򊐕Ca)gH*Ns̩F#h:q#{"H$!:no%J|#Y2ps;vu}`pf\)pnN_AgVwc z)衠7'8WC(_@7><δ8ĉ(y@p4HHߥ#gTB]끏>q F @?3Z4*u#H2JHS{G*1(f{\ \F$raHio!-:QJxJ T\WY=QAoF?-9I%Nރ|s`MOQc,w`*=YvJTb~aQH]hBW'lw~[AFJ0mn \QV!dN8w 6RQ6MyugN= }lr`+:$ zдX |[/4u:e$WU׀U,:͆qsu'Yp3QMS𧁎AZҚk װ}8+ 4b;$Fq?ϠXO=*8_Ş5O,L6>Q~e5m=ʟ&sCm ^c1]8~{#f㓚w#Au~ojMi&hqk-l z'S6~ ΋d|Q6ow|QYno }Ch> {(K. اݭrP6س3Q?>C{aygG-FqMi=B h &8v&ezMI$2A'E߷wc}C7:D>||8M5ߵ?/ޥ;.#Ir -}M o¯X/v? Uނ[̷8z8GoatA_5NNUиٔ%0ާKqB '%㻫zT]*~jS?k3g( 6r?@nD:;yP`1]tu/Z(f{O=7 ijE@? (>;C8~?>L GӇI%~nc ?2- 8ηw'z(,!(H?%8]ƴiU7?X=g lOU@+})f֨FCv'vq?I\Kj[!~F!lcM]$Ƙ a9J\K ӕ <_h+j:񬪿'̻Ɵ{ʼƖi| dc*T~=`2A? \ 6jU xA}l%]P;T*͠ك7 ܍ Z%Q J+W[pAJH΀9-h4yk;WzjлAW~%I[ZJr4 xU!Q}ΐ< D*+ *QѰ #s6p:Ӵ2ق oL!̠Ú9O6[\(=zϗ3  %̽xWDp6.PNgZfT v w++(E@_WV3t$z(\33`r?*[ѐp׹ϰ0c7":`ʛ iz@돆y >} >i VK bq$lljX3R:!Qs|NVƻ!Uu5dA/j(2^o(s߇eޡ9%5ꦠ5l=l .1[΅Axʜg1C\}^-qO+}hp )Mh$ǡC0¾"XNr;{ч;LXE rv QsϋxDGX!Fu8,}،׀*Gɐ.&H i-plJL6>`12$U+&,4!_v|>o>;[>N;A㔱h30ol$୍mS @oL-ʼyj{Xhn:Jc@@ -6v?烓l}[` ~ogࠇ:LkY;ͷ66W?:3g W>K؇7D}DZwpLI fۇ7n}xow|@}߾@Xž@^a3*m=gT F[.3P |\+"J(n)"SibE4ZN1XTqS% g= ~eUK~ḅD"ƉiOSD! is<@,K/NI!NZ#v-^/҄GdD)ɒQ^Qu})oGnE OdŢDY-YmcD(bC.rEᥜ}}~]<$yU`, tC%yb`ɽ~R)Vk뀛 <l-6`s|^UFcq1@׼NNyj1X V?@ X Wۀ I{.` p 0QO/0j…)8 L%S>t`!aV,VWZ`l66`3pxЭۀN`УÌ z8`"0 8/JB=8 8 RP/V+KS_vsoLZbne/٧M%!, y8#оTܯW26#?U:lYOƸ++@ Jt;0YtUЉZ-Y'։Il;E'6q\t^I"hi(%KtiyTHriTgE)J˭t3IL?xSDY~n3N7G[YuVLYnm('Ǩ1ŠԘ昽1m1f;#4jmVjib1V?;nZz'!Jך|g6Z+}J[MS!Nm{= .IyRizMI^;V4EB">Ee5X/ȦGS!KqY zt~Ar ݸ_͆eþ,RЃeXzBVX)V zҬ4aeXʱrЏU``?VUlG#Ϫ05b`10H$ H I ~fMQA@=> FĬfVNjf; 5 ]2/˓yҎ'E"kʝgj'3[}B_88`06nU[ :vv&vNGx `WCn55f8 hm/h񓎸f4ǧ.'vVw4E`7$Jhh.1$az</0xg< f0wə דDf2Y5 [0lnSݭ63g* 'sGZL=DZ2 $PƥƶFV|lSh'3'0k9 #t@֬ Kv hp?$+]ZD]&:NA@QeTcʘ} 00vF?|@W&OM{@7f"3r{3a,|&z۫Xr{+.=9ݹz-ʴ;FbD >~ z5ނY\M)cmb֓kc ̒`^mWUO> T !$HR"RKiR8!p-n!e[2f>f!ff tlYj郹ss3fQFIIzldzR-4 )"IGbNUUՈՉM5M5MMjvp 6'f2Ad[p Xl3{^fqkq Nv D |ma]e#{87>)U{sB}=!V&u bUw=+ >qo V ~U)+ iū Z &bSL߄r;`܎n@+jR@n+侉HASbuUbu5buubu 5vkv6Kڼa>a!1GWnfb %hϵjWC@B5Ft53jʩJSGcT=u:MݣPS5zO}>S_h,-C tgZ֤i]ڀ6MhSڜ vwڎv{NtoJ^Gt=HQY,2bYVU`؎*k$bDBH3t} .gh6P9 &[}:ĵ[9> m3?{̂mV7 c|X/?<؄Ϗ;r㿚G2 z~@LLĄ11q SZemXl+C:X%V(Qm d4TY{񅟺q#ĭy[|׶'m]SRy-ǝ3jʓIA-/fgh,I(=:nj^fkrpG"֬cÞ5DNv+L>v\BҒ6%:pӽ#:&-o,oqbFsZܰ |]q`V}vҬO-na45!F2E~hSȸzw.r|Cg\bxԿrXezNً̒x6hܾuO?]htt{Pd~Tƭט=scǖ)Sr[avi۷u50;Aq\X :_EX ?u~wgxo*wDI["5[syW5hv^$X@ݔEVfk_ oOMc{՜>bXmnӠ-tXEjȄ=ƀͱ2M)8U!XF "m W [whSb۽% `@b/m8(Q+phPH 8y,(T`?+X緂?*\;0rt4NU/UlnE6?6ij5:{sSxI2iUn]$Ԡۋ{2z]N;]}Jm2.OZ2KQqʮ"͠6#{vH{?,75}/e埲?QUU3/0~|hz٫e28R{?aM/Y>)Zr2řurgG3;mjWD\-*:& 6Vg^U8XX$`q0B!r\ B3b {bM.@Y5ONC?o9ⷦyk34w[q3htLVed_B`dM\<*6d6 l'Rk.:TVb_]PG,!Ky-M?vձ[">3:r.Z{lKY+M\' k}I֌| wِL}9x~Gi/ʔd>55q~YqŬw/>;<:o{Ja$WXcJBrh}ږ~FӶO`ZW2 :ސq.n!U㴗b~gN:k֗5 $m<얇<#nTzZrrtRQ@VKӌVT1tL6~)pˊ+T8{̰Tݴug)n/^Bթ ۖ7LiZ}ҧTK]T;UmH,Ϫ]]wo ekLowlQ66}9 Om6bywi).ũGf$6Ԋvjlobfck5"' 6JF+ vyuGx;`΁iiu\nkiaMJ.OgpL%lѯmsU`l`ak4Ls}K;^m /*R{pf/ޛUޫA?nR)n T+(fMN2ޔYտ"tؕq6d˸UMeэ1*u]N_92={ԠNE/_z$\캊 S3L\IGjtS=1zo;cQEvkKmҞذ/5)(@iƛpCQGW84몋L3 MZjUB$/ՔWFj N*U_v5Ju{.AlA΍hrtZkoKȼ M??-jw-"|j˄nSYqHeݎ:m XvK[;pgř,56&njyqwQD_^FL8yglwxfmLY7f3Or[+b%o*]s8Z6D%?Vzuj`M[SG^Nbkk[N?0p\N)0,WP7%ORKF~̻;Vx$26bQeOg?dgōҿv8@Z}ҞQQ^A>V3X>6uzv֘'.UOf1}{бa_Rz<9O'&v1tblTҤu㣧xh #M[?3ӯ1nYzGm'k0KUڤ˧5 1;2e MwN<++zGSƘlc0\87I/yrs*N=*PFt-A(p?N0@e*H%+,"c<%Ř}?pc%e~cQA}:1ld8*OQIϦ\ wP8{riXhtlQeg+Hg3K9~KDvi|\,_̞=qs׸-|7zxђq1o/u8ֈ {?4Btc_T@rwtqWQ>Ԓ8urF03U5N_  7Uz^p4EԿH ICpNH?L0> stream x}j0E -E%#H胺].li jY_=4M\ܙFIUJZ<7`q/00Gwp ۓ ;ZgnP~Degb+nPhxZ5N7G?aeqz8 e-\\y> stream x| |}_dݼlX Y9Ipn$- D1'm-aL}3;3t.BHف|Ousju"TpBij}>sd(ӾVH޵bdqG-iiHb6BM+;y(\>gSݱP߱+ڎО}Dz9S`*B>BٵGlO>l¿aƁYdoóDmP G.tA2Q! 1HB]XQކH&K&_6QJ #R0S \+N tuM}Zl#hoe_'""&/\;C#X vr{"&»#  LAᓀ;?§ }}*++ǯq /I|EǾ| ?է0w`.-uy }ZEoYߦ}3`ݿ?>_ ~3WPH|?H/?y( 0P Ca( ث\\G8E/c3``ῷu}_}_/4P Ca(6x*! )~$ĈUGQ*@Q.*Dա4uh=A< 2~{^a{9uXz53]5rBk"MFUZkB 2&BkUڔ Z9p(fY~&~-_ @E~zϩSU] wX`" >+FZ?H`|A{_zef1o/"< d+ mFZtڂG=ۊnB7mh;RN݅\`,B7h/%g͜1}Zbr҉%E|^dge񦥎LIrV^U+rT" F#3T 邌@ Y% :B1%y(vIIKbs<:Y9NJ8g?V"<#+(IH!rA gu^3`UzE^RQQD %D p8% &xl/dj .nj Vl.W  Th9y~jxT\k mJ=lqOuA'8+ _{+<'8+*z8hv8(v8g':ϝ9}qNS$G}H8&x#sH_nQ3$j4DͶ>{=A&@i o6D Vp.2TŁU ԑ} d-7ኊA"|SDt/o jA/4qd8̯ U"Ղ DjE_@ iD;>45~ͅ0(I=ֶ#`klsm ks(qws.B-Dr[36d8K:.!IF`ӏm(Z )Ab ]XJ^jakdI.hK}ʮҤCÝs.E#d."22Wf.1ЌEF j5r`C|Ft-oyW^3/vJ/Jك" SXETHO҃K^E_;{d\y]i40}@bIRY ن0/Kq%M,%=M =H$UA[8xpE:R(J#@aDD,֭T+4h~I\F-mlRE uA%(UF*vU ^]%E&Zn%i%)eMi}%p2 6\)\zgp\ԑYa"ysiFp'u\#Sy/z!3ӃZak!-! R!''"s ]g6B< Pw=ԭtYך\ݗv3kZ(g` § Bj(5' +>Mx.:d+NfYK|b&1?u^Զ9 - Mo /Θ4c;Ә) Gp^ L}j]C^>Rw 5 թU U[;6m+cwR|/)|).I-n(J-l(Ho}rmAf/ !z3K*ܥ}~|G_BgOҭn6J7S־xЍnCzJ[l^(]KfJ(] Jb]MiPZMiVPrJ]:)-ϚAi Ŕ)-J)ͣ4R9Z)PjD)@i6YfRAi:i))M4RzJu}@j(USTIdJ&Q*TJi"JŔ(R*OG)J)4C)RLJc(䣔AitJ^JiR)4/h8Jɔ(w/{ZݽJ;h;)Ld: QJ3\}2-()SQۧdddCԧ+2R2PSQRPRSRQRRRPSQRPSQb@ %L a``p93?8 1|+i_ G;Sw'op[ M^ZSqˀc/^<9_4<< xpp8 Q#}^@`3uA~ 1? p/݀?3[jNnY p#@;61b5Zee%0(0m0bz$`p`>QH,⧴f.~ _yJs\sRX3cXtz<~i<([:k%[`5ma{[Xԓ޺˃v go,nO"a {4z:w.x:;;syWgg}Ic.{HNER]4I tzIYKZԆ:QFc Hw>4z}%؎'tb2  #yx{KX"~3lbOwn φև =F dDk>7r '_٨41DP+=RUh%ZV5hZ,R7kt5Z66!Ƚ7>7y&,C6CowDnA0J?DWɏރ~B]Bhڋ^!Q8lB 8-,p5H$z@@e݉=1|֋zy Ņ})d?t=A݃g//ܺFO'_~J$z ҽ |C!tNZq,6A j`(×L3~t $bnSC3Md$%R br,~Ur Y45K@{HQ)ãp I49nNK3YTʈ%1rv|'6ExD[ vD|+bY2uo[אsF72 x,9^Woѝ!?1valte2cF1&01& I3'&ˈΝELI|OgVNGטjHqW7p{N۫um'}/j|'sfK7ܚR<=cd38D˪!S ?{!K~ө«T~TjVo"[Vu:PX-Bּ7 1{3{hwT78*-PE E%jD1:WFf{]ߝMZ×~wY;7d*F9]?p­w* Ntb8*AfĘ}B'g @\.c]lK#3Z'  puZ&SIZRϲ#!_'2WXSde")#JURW( 1"_C&Ha;JL)'Y#|_mṞ,aђRw9֚)G+qܻ<:)s'Ŷin|1hܭTdDTHupq2!'nl짊<*Xk06^W%,a29!,"|燕-o;6l;)b˙{uuW9]]3i?W(#1}_%ì*3w=c;l>CI: I^;%\GH( aPNrG'q+HT:cs*H,k\jUaZz#+W7[Z6=0ۛ1`|R#lqJM-̄9ESno#:*aA-˰k*%&Yn7X#+ $EOO ļ5,g}L<1ۧ&}ܢk aUUld6VF#Q+DJLۏ&Ӱw* RֈQu?d8 X0ͨ+FD(հR.,Ji Gl"*ʢ+sOU;*_t.,I,йI)eF{[FԮgz]qc]]X1qmO.^R2}ŸMi+J`bj ҃fVpY"5,wjqnxxA "edj=:lu_[:dp\6!N DJaվ|G9(?"mIКs]@'3{ RJf-\kRѭD23K#{]cK8OHj3z6Ff8m{u.q0w .;~[ ~{]|G֍s^yCw|w9vgޙW"F.jR)Ɖ8NGcWWr,RՐp< R 2X0hCYx9K.mY+5e>WzElv /Z_\ZX0n/:,BOT+~.յUXWLMSa @dH"cs8G}7k**?x);~{F_,ސhNL_8K3wo6>qY]u;3̞bĄwfaȍz#e4h5jcÔhRtjS(Vg?avO Ӛf bs\yO=',|3gC -X.!G@NJ _rr/̛$5::sQS=lO1W|̧G ՞wyYmt]E$r}x ,dNr-eff50RB5).w{.}BͬEQOz#YQ.ݾ|o?gSeekްP5ՙٍ\jm!9S: qْ6vPV,D lQ0*)>ZSSaGx _[+LԣgLJY3f)ط16_0y͊ gf7qukw>a!=0hVzj-AяoMȝ;p[zBhm N,զF-1]qx}팎,4߲%.9`:,c&q=2@!YmÜ<:h`ĀOb,RaSr\ eLI$s n$O-M:"8&鮤$ I7Ip*%$#`[uc1&~X(:nW0cf&uv0Zs,fIJVƌKU7$޵H$WTƏϟ4WAعy2(I6eKRaGߴ└>w7RdZѤ+Fj8FljJ$4Ւȡ^̐Ϡ4d** j:ݑX3vu'm/FeXȡu#p5 C ~E!3rE夢{GK_]xBo*"gvc+jӶ6Ɲ8{Y{|yY{|†~tYc3oQ+ĘV,Yjp Xڄ!/$zQ?oMטǷ&g.ݻp\+}+kF nWѐא]9e(_"ZX5&TVeR&B1#5Zf=}6#,!s2rt.J 18&X8Doyk۶Xf`=;K#Q(hթw/oS\7tJݡB?ж(̞?*89 z[zSxerW++f UϊXR?G^#+HB0 :-,؛'LSC/FMoa3bfy=CdCP@8J:Zސ`XbL&A43Ę#Ȃ"iJy#  ےX yAF{-%N\~qQ#gkw2 }q޼ژ7=wiUV1gFeYȉ.=>d1 Ʃረ6A\ǠcM!"}3ia[_*ق9cDd'Ӿ}s_XZsbvU/'ae琏q ^sB1=ya怰٧}˝×=]$ *Lc:T+fY'3d2i Xjl¦Z;GD[B=+zfI/|h_b\]w-ga&: Tj($SHX@*@Dtx4"nBii`N20Cw*q [%;\CQ^"  [J=Ls*0_xLuJ(  Ж!Ke Bf>+Ssnw 's?iJ{o+mt]LG.JDͶ4ՙAgz(aB!T./ш( DpM숃*񇮨h(^jc˪x+xn>sdZV&Im[lݻS~ Y .)Ζj&%Qxդ$Q2FļD{^1<66jć7id KjT ΍Tn(667ՙ\AZQ}綢*Zc*1Y֮-H(.52h6Kƚd&Uk,eLR-CℳbYm/la+BFE+QUYJ\XP=KNq3TtNv& J:%֠_יMX7b,).0:RnJWt0D9׹(zTfeS:JJDh-;7ŵ4ġ5c2x aGIA bƋ#s&3~[pEZ s)*AӔT1*R+QQy yLT=x̉&#Ghd􁜨eI RwؓW}gգz -aտfwpu`Nca/֮}?߆g•[F*?!;4?E\.H/*\wg΢~qGg\Hpccj PcԤM)ɔn(.`nQC1[.Jھ8c`ˇNNt]?TfqxN/Gq6U۾mdO}g 7,6be#RTHًS@͗/h`TFQDc$9*_(^~xUÓ`/_g>O9Բooՙo8Ț`Ao/:6xz, :"\<#*)6UU] < ~hPQ]6lY5r׷DݔzfƊҌ,~]emrfU=>t:Ř* )v&)K2HbHXD37e(D1[.d.\6BWSppo)r߉[*BW]|x.`DeA˼+Ʌf54 g8Rf՞Ǐt(#9XM=Pg5r2_?;Yu|FGܩEK[\:7|Aؓx#I>ǎD&;2&_W$GONFỤq&{RBcxfCcŲ"[nFzeAr\i ܽ<5!B69ewguKWZ-%NKE T-ܐm/H_V.-,M0۪E%%Z9 ҆td,2@o_aLY[y6 051sXз"}J#MB I+llћ"Ȝ[n%ƳgEP1ݒơ|8#{7t8]t Izl,˦`hHX~&bAމT[BA5_|4(GZmFD"TJ+R;q R}R`SPâsrs"9YTpr,ٌDS[2J:kXR+8Ce{}!R՗edNP/K0YC[[)u$%ǨumbB^6oEmKJ_j IX9 m_ʞDyw12H*O2%A^xYpūzG3- xeD꜖_sX2 :j2 <џ9 63WeX$9OFz!Ɍuk 0|+ixث ]Vnj:z]]G-Aڸ(\}e{%:*WɼV_Ru΅K+-m&2 곰7Q$(ՠƒD| 5&˝Lo?"g:h4rAEsBlaZ%4W8,D@by-k\ӑ6y WY).]_Ԑ̞R.ܐ\Q'ӧ򺔒 U6+Iו֥%i */ ߥV7k藘gx̦6hz.V۴2ceX )XzKŎK@¯ "_UDh2A3Cܼ zː,֨)(QL׫M2Q8-oNB%)1C6ЇN6( eE:H0Ƶy d^shzEꖬU|Kuji_`_)zYM͓]'Z;K 4vV,FuuŀQ˓kEJԒ&CoE0@:SD+G1}b/bۜӭ-)7oܬYjX\G_lҘ%^ϲCR,=<h_2uvVW14@ -u:[{S$i9bFQx20"xoO ȷmXUԫ &יos5GG2KgUK:R;30q_HM_hj=9IGU6-`ɁR4;#} L59ԏl:QԊ7[; Λ4- M̩@msr ~)yp: ^G{DV7-% )Ï2⣫u%]Iꘅ#;ʖgٛ9ͺ:c PwTFɠO(sTT3ium.ﲥIM5u 8$u /MK17xFZ,yPSe22ӡ=3cccSԭ' 'ܒٗoj[ˬb I?F]OM[eo (UB{6ZZQL TZ$ }=M]|&dSXjHq87=ܭr:?.NOou9 Y6ݕf?)<۰iTW,[Ȥfsb"HRd*S uNH'/PVqvs8YF/v3R'ך* ]mlKQbβQg MO;2 S3J쮒s _"5$,Ϧ(\k4RO@. 6tB@RRq+!05IG 38չD$UIk=+e_ڋ6llue~3Xʠ :ybR{WoF̫Zh*hz+,.(IL;7ӌq ͖Zӹqs{:MFVCwNky:`^ʨaZO!d_TK6Hߔ&;/S~"U1r=WTs1~SM_aJb_a~ŋ5*<>Z /O韏c慪k8xiᑯ Ӿ&0zppTE~ECӇ5;!| ap-\ µO,EORa$AC k77 '/ OBjp-\ µp-\ D tnÄbBZry$P$GEE)S"/AD^Rj RQ+/yNKE^c>y5rk";%s"O#iO1?yibb~)RH]eh["/Gu+VK "| խ>(jTJ$qxgpxgpxgpxgpxgpxgpxgp!Q)*A.@~8B\Mp>TWz!m 9s 7-\Jy<:8NP.G^t2JjSG! Ǎp %X1".({HGSb.7D4U7).(Idv=t|NH$å8X -p慳$#6LLj<2-D^7øxXQOIpz9a֒6%b|OO;#bE}pk -Qm3 )S9 "61v8pqIF-L"V!Xd9Vϓ $͍6C=|-5LJDOu1 [yX`ӱm|UKh[yQ~7A-FX'?'Hz8H[@" nғ'6zFoʋ،FE|? z^(-1"!H 6vyLRb<`>l{ nB<3"Z6S-^H/`/5#wae؃'Iٕ)D kIn$^askIh6%,~FlKrD<}Z&Jm,0J*?{;خFՐ]z|@9|կ]Rx#k.!r\~Ҿ!GcĻ!ŅryoQJ[l0EB.HVѧG (a3c\^j8}x>V`s89+`0B[uè6W~" 8=Q }n И;<x0A~ ܼ  ƒngU9\c΀rssOyCcYa>y=~ܹ A~0D 9DA . N}X"b>p{p.HBPЩ?X 9,Ht.8!Zf>@[}Pヮ Mp!~ Ml.PPsqw Ah1BXU@LTe SKR^sN9?ȅ `-^w7_/i]ZhI?N!g0n7:^ 6,t َq`X|EQii8C!bN@wPhqg`=Oԋ:zW} !7 ? AC']`XPhj*^nKmbl"#fsm[ោ~!b;! b.n"MO']!,Ԙ5u'b5"x rA/u}`< 5]/ĨTС"\Ų#@-!8>Z~gt S[NIC@1wbBK[GP38 \+BdUf? rpHvҐYXQpuzP TT#6||3 | Bj!EQmSwPwRwQ]wSP=);j1TZ 2jߦڎ(A/F ~?QsİNY;d:܊y1!Srzpq\9\ GsOC]Rˋ@OӧL UUӯ}~ߡyq8 '@_`@rs KK@_a^з~|SSf /_~|s,3(K4K@UacjXhg6jd@x)l Pf@sylP kZ-aKe@+ Uljh-[ 6mb-@`!l v`l ` v >Rڝ``WbbWvts@99\%WU@r-P\4NZˍrZ/DdtAGNA 8-%p:NGQZ J=ōQ!9̣8NqB_?}JR,jB M'BY^ #sI*D12pCԏV|S~L8>oe1]8% 8p,}AWDTX e4cJ~Q~ فGs ^).8MAmw#zF8qć|_u|ǡ[x"x k1|6sb?#=xH9BH ?~UAG!> 91IrDB . OZ7 cW"D^EP_z: ]L2_ t@=c@U=>rW]Oh遽@o$)=vX=]=\ϐK:4Qr9%%?MxzrV$%Dw)PoHɿ'%,"| 3~g!O1 ع®b? H&j$y)Ȟer5ouEiSҚ _NhؾJle>L#t"aNڷwvX1w+py}aڑo+'} נ~Aǁ2[R(_T^/ǜ^X^ :)U)i3Qy,$Y.DlSbW )]aEnAA X+g(Mug[>ٝp3L/ .K).-]>2k F(C݆}dXjv.SiFkyUD E< N{0/@kž`BQDq+LQ$0&8ZDۯ(u ?=z]Q6h#G9`7h4roQz(BzmE7h*aZQup7hNpQ4?U(8wzF6eh9aa*kݑ/p, m$EA#?kFk;av(Mfz{^tz ׋1G"[͚QtEɑbwO+3|z:_8Q|/68683?՗`R88CkK+jIbw/F>gv*k:}#L  n˥sy1z{Lxn ;mQi9C۰h3.Q.̈́dTyZ\] 4[!hҫ}>jX'+j)ϋot֚n`6⡏#wosѩ̻ҷ'[,'"!u>o)]qHaApTl6>EBv`wy nRa/9ZcW:_ܯTm;4cf-x0J[b ٍ3Zݮ{zNMqfP1GZYB7,q-ZBXhV\<-DxFl)݌yJ`l_Z `=eԻw%޹ۭhp.p5I-n7wX,!so )+(TY| 'amd'kiJy*˄%X7_.K5w6s4 *0`$IV)$kf?C|4h\Ȍ~& KP-:!ե[ Fй?tB./)/g"{EF^e~>|u ?>ƲAcYnVHLkdu &w* m{ɶ~~D-ˤ^/sG_g؉=,`mQ]XD7g,_SJHX @KRAg\[qe2&1JF.XSBOo]I^ٔJƣ稄brz"uoƒʲ%U4#[i>6(Y6dn<e vԔ-.[l+d5qK(P2(Z\d[Y-ƹd'pڝkKQHAi$X09@qL`ԇmsW|B w{Y  SŎf<yŽp️mueý_ @< 6}xR8T;#o'Vz6,@;a[BY̧Ȗy0lρ3q&sh9."%}aku8AE LgVOTMix*yTDT<} sp) D)U¦#.U^UW_VWbVhXh)S_ +󻑅*B#d*Cbb'K'9"~+wGG%|R\G AK%IS$Et!Q*J,E*CRdHCqJ&e~^]& V_PJc]T~Z=fRKOGԷ/gߪo)ZAKZ$mՆhivm-DkHm6Z_گkRVK-Z@ JoiZt\ԦHhӴiiRJ>RPK'_$]"_"]!."L/rM9H$`ONE||C&Qp9K)dc@>ϊAԿq&1>>>F}rxTO'C9ޓ>Id{\єs=<>O333SYYYYETƳ޳Rg+;H.z )Ns^ԹxN縧s$n\٘+ruO#Os7%G+N8im.WY*QI}ƈƊIuȧNqQ.J%ZrbI(h/I§+"J=D0=\}LSSA=AOzxH $Z;1?r/*k(r"p/ ܽ޽j{L{?nv|}>pw=>[ɣSD(=~t(s0kh׊OC8] BC3Svs\)">"߂f%\H3?rʕ)ϴo.t~L?'#Q_[ߚR;_߫ݛߍo%o5.7qk䓮ݏs5Oҏ>Lb{濅ΏZO?W܂1[y;G2e)j2nJh3GcFqұ%/d/n4s]n>}Ԯ*(=i'ۇ2mOg죉K9Jcr}ħD4kq]{RÖS_Zxg]SAt)A&/%IIna"k*Drf˜ę)|+Mƌe)# J\>V B:8waפTU~SBK/i)txRxҝ딢b9Y!)UE1HLhH}H!ar6]9ssٝ7@N3]i9ӑәmC7"(#Hi3Q$OQc !HRҵ$+H;%c5oҵTl@#dş$cґ"v{}c,簙u$# 0 c137ˍJʘn̙(c.(VaԇƩ럯LcJtEc>>Ͼ8l_LǞl_f_i־^go=\:rܾ29`nEz O`Y7C#tJ}~۞bo%O[ .{V4VJ)IA5rMoo{1\户ػG |lƮ+1Gc#gؑp9F;ҍ͎\#1l#ۨ7/TRN%G)hrG厉yDO%Gcccc ܱ4aow1hfirG chJ;)*cc\ b]Qn|*o|EGP0ʑ1?|7)J95hʹQY牔'Sj^js<E7%V^Ny5V^C^uCQFʍ|nu7彔|Xz͔R>N3J3(N춉16aRm666rmOV\OMmmmR+lmkIv޶ٶͶӶǶvvtNN..'IIl瓢9'%pMIJKLr$Jrs^M*D-"iRҔIu!]'-KZ֒TOZTgJ-Vڞ]OuCjҡ#mIǒZO'tRWRO҅d59,929VO)#X+>OⓎ)"q4)!+)> "rp5R)J #) %nQjZ!U'>#f#zD^4O$"v/A{ymV>c^4N&%zʴ"ĉ")`z@I/ئfg$_ @^ĥʻy#8fgq֘? =kg4<<>4قl_րz.H$g=Cq׬ْ58Ԟ'h#|٤7Bd-&*u+zyl?1$m=  C CAlU~\x偐Q_bf$zJKM?K[ جĊ3uɯ<@4![YZ+_cQU! x:JX_EKOs^|O fbT ~ 0v?-@.?D4$`-p(.!l{<L(>Py  "'1c|>!|y։u7>C^T:2#Ӱ'@a]|ΡU,ћA_a$@_~pFZA돑QKn\Ƚ\a<1_}Y>AuYf,>_Ȧ 3g,X_ a~1Z|cJ 8c>#Q]r/zw$IR߫|8 8H G<$1gPYH"NM?Β ۾u g08wK9VOR BcDX_CδS:jq6Q*@xQD𪿺@2MwÁY=\cc1pd ߹h|'|6U*TolUGFY$udF=H(R {xJqĴf ј\9٪M >ZϥGx`5zɲ?R/jBkAlnK.]FA3Pk{V=*߻a^,gd#}n̦y}fh!d-n//63yqŽG{]H⼼U5>T~BoHPWV_ N#j X(Aon>*2Dg(=ﲞ֟R_螫1d:8{wriX#Ns-m6uyF/S/=3RoN:Ja1J+U\J1<_)KqQ*X4>pVo@^hp: t #Z`#JV?лz?Ot'1x<"Pwגr2ʬˣM6`- 9)ٌn=c}VxG1aIdck?ƒg";PG&9!1O4E_lSp}(Z~sBf>Ù6d$8O7~I#\僃'}[ Ѹ1q6k\i'j_xd`58gu< ZW ƥ+^[5+if'z^5^oƻ!b_< ExX<*/'W,i=+E_">M+i <1^iU*1]słϊ6O#D+F|1A)_\cZD8qHM(" *$1o4'B>D|Mۡ"]_‹']w;Ľb0Sx}@RAjj`9DD a.+Fq‡_,j1Gӏ|~l%LfG .7 ,I4KWģhU»{Ԭ̅sOBw EO~} O|CɊ᷌w2F W=y?eM}kE[J"p-`-`-VƶKWN.WGqqJt˒*EHR4DJ[' i4]-͗je*i&X\[9uum4=Xj6ߣ$ С*nݪsCNs%rR "*DT I*QD @ *̀Lc4W]3w[kյ:]uW:ERvJ yOoNX)DRU"J);k:M,Ͱ3]楈|y;?ѷ\3 yۊN8/wMg?/8Q4d}?=OpVj?** ' _ $$,biy0Xkp0R]Z:}q`7|`y0!č* 12ܮn-[T*X nY|JNI%p\pl5xep,@rHN966[R]$Iq$94n>XF"YKv)i̗Η4KK 1.ڃ^lO7%eͰtD*i:i&i vW]" K<#%ꅯCau> >'.~cL?4c?XHďc,"~%c)X1!~ec9b!BcEX1V&~?*ď*cFm4cMX1&~uc]X1'~ cC؈16&~?&ďqǸ'clJ?ďclIc+ؚ1!~mc;؞1v ~c'ؙ1v!~{?ƽcWǸcܗ1v#GN{?ƞďcܟ1&~?>ď@xc<1%~?~dͯ?c@?AďP;[l u&8,|2B2>`s@zpa!hܾ!<2v=]_A֮瑵+|v}Y]_C֮%kב2 l {^Pa58(8l $< OS6R W>"d>!{d>~<'#o !C~f )t4:CV(@E(DeȢ*@m P;j1NP'4u:eFRP:C9TZH].@%u *SϨgzURPzK'ԠP_&Ph j @ZH .-EKA=Z- heZ* 4h5hL:;GAڈ6=hq9mhKִ5mi[hIPmThgZӽ^Іv]-ݗ ~t?hO{Ё#M{C'ڇ zt}i_؋`o:t0 !tKG@7:1R,=Xe'+dЋ`%`Vެ4+ ,aYy8Ud VUYVjjЏb?֒"i4 ɊdPHEy„~uɾ4ܞw4}' SOÙpfnAĂ [b&;N d1A}dKy!x 070?_\h xp.R¡ D( !2H8KH"DG(Mdp,\p"D $ģ|'@p"("D 'c/%2@Gd0 pp#q(r?TDi<2ydxdyDfI#####2Gd.<,<" xD,Y#2O8 AY##Gd9H.HJVydVȬY#Gfz<"xD xD yDxDl#GGd Ad !";xDJyDxDyD*xDv#GGd?o+xd⑩ᑩ9#R#rG(1<"%RCDNiiii9#rGyV <"yD.\#rGG:o+<27xdn⑹#s r BY owdN (10F8D gT3< J~e9088 1)000 &!gΆL@@ f:C!(K\ yAy( ehZL &یEl,M97;4=q E0ꒇkpi Q)y[fmEvTJЎ?]a{qjUJQTE**jGUSAUCR::".(A\H v Ƃ*MOpP]pHP# ̈́:hZ3 鯾^Ǚx$15Xs%JBI DFC@o\#PCPE+PZ*AkѺGF2 6c~iR7R*#&gY(F( \O0HEҫ1j#a N,lh d'N2l.(+@]nuF̐@׸Ԉy #hːzYR4WNl; t# b7[-wG \|86˘K! ,6H>ﮔo/MNڳCٱ(-rvšG+f]] ũHw>!u[,) v;;!v*KT<+yGp\w>/Hh.i\y(`.[Nfٗ1kcX(*Ԅ@3h +>p,toa.\ 7-pQ˰Xrp>zF{|&XXbP rPP PNJP JPף=|f{ı4ű14qwha mbh v n>sʠ43W8W}v gpdf83o(f43,|ʤ1f-s618q%S ~3' ~N2Ls3Y?Ku0 0B FELڔ̞yn~)<3j΃@2t@nƽY V@h"3]ڄ]t =ng*1zel!ӟ?s;GLL@&O{rESf63q{Cs2a ,R76q8vvL3 칽y +pr ) SŵB%aF9_~˷[2lASԠ:E j>-[1DKlV؆bf0ma63۰%kk 4NuouJtDvjDGD;D#D#ZD#D#:D#D#zD#D#D#D#FD#D#݉FLFz$1%1#1' mPR-{J'7 kwy~D)=$gVleҮpXP `!MP%@P$X(KU&Xt#B,U`FP' $"&!%-#-'-`x㧗! D0ăD R3- q.f`#fm}1skE0!!2 b[Wff!H8(C1#̃1wr{^`v[ fybN^/_.p,Tx4'&"DY$#)4N`'KlJؔ<#bGv(FlG`J0U#L5hŠ\ļħL<=!?Ԍ΢]DUԆکc HPuzF:[~EBZheZVuh=ڈ6{%mM#L]t?ڃizKAt0BC1,2`%YiVgYeVUc5X-VIdE"En ?3@ }?tg \Dm0[0WྉmƬ}Tq_ȾX;=? ..QmZĸbmi'X #TV6VpGP+,T&8]2!%H=&V%?**Yb4畃6WP_(g~f<-Y9掯:1ife^7eau׮h漳Y#^Ef%&Nŏww졵e5Op͞q.k4XCM%:BilI! gyƅU V|>3&wjsllá ^_F~2^nklnItۛ+?:vyzBhf}q`^cn[†9XUQԂtZqƪtE%l4OU„}e8| Ycݓj|GXM%O24:{| Ÿ}2>(aL7VKzo>YajTwGy>kS#Ñ d#6 ]rG@YSʻ_'LS"T⏺VVP|I m}~3 ÞF8oeelNU'J5_Iw}/Pl}EM_Ştբ.:9t[u6mo-0VI dE|ߗ rE;Z?֘ W2AW"PDC (6ubTD|9 (TDDucbS?.R70jB,U߲BٗGUy:ۖYnd7 SSx=ؤA֠cliYw֠Zһ:m 92~'L_ܗ6iq3|朚>:kTY1OIFmW]̡ݽ 8X{hAyKwܟ6y*ݳ}o߀ޯN;p֓N-l)Y(6 lϾȳ{q["G FX$`aUrSXԬuv:Eqߵ="%lY(K!3"Ģ=Ue}* ?lM=LQJr?ٔ.%i~K%7I]i.1ٓmSrn:-:1uNO^X>pȶmr o=Wd21Pq3n>Զ%%2u~f}s[/ϱ(b붒hSF79Fr2vй6]VdJYTeV]ti:<]%5n5>Kҳ`sLl`DuG 晿W%3 &ؚ;Nʼn#SohɹG;ٶ`W5<;yQf샵M+ro(m5֭[ْK_+_%8?cze~IKls:gw Sj/\.j-}~jEcMM[\]^3ʞe_w>-z#LzIc/O:FRzxczɐ/:^2뗓,0z=^t֘PUҜ+K&_R9//gXk6p}X_qCfyC'Cg\N`%X ]:l^ߥ)UJ[ϩ -<:wKy7 н.b,Ζ -b"".2~Rj7nZDTK@lh8I=Y\ ~VadBЁ8a[(sOe`߮f=4dUz=|Yѧ e+k>Ս:Ifj_#uaME~gx0y惃c`bH/֘}; >+ h9hkͣkjzY9G搹+.,ɿ\;,mv׺r:е=Ͷs 6q}RϮԝ+(,]44۬Ե:-j*oҷɱ7U8.yd#fL: 6Mm迏mb"&we{Άu;sm#]lԎudnn Lo j]L{k|sqOؐ<;kw?6 sީ֖>/ƒwEz!ҵgy? ٘eU=5Fj\.ˎ}՘9Ł^} S4}dY?~R/qfMoI)3[j꣄ae]]W;cw#1e'^uwo= 7n!aPZe!ohԸfBWNHCT,lm'r~'oUlKfԬT~=S#pךƠX']⾷D;y7ܥΝp8g[{KmR,fաxsn(͐*w.7)U98]wThʹ/͊4BVHf&0zDәPaMO8m{uuiJbxL:~[l"kͩ~su{-1ZgF_:b3;Gz y`f]ƹb?+1~z{]7u$i]a؝QCq=98',Z^O7ś'CTHPrђkR:!3'Nb[[0q;iwՆޮKYR0牫͵V&7с-i̻g/:U|"*~|rU?wHay`Zcޘq1>AoYiΩ[iClgOψ<2Z3KzJhNIQGCf9Mky$2ɱ3o?vYq̘CTZolk:sM˹r~U_2:w̓y9}ɕ3 3l卜67d^^.3/7#bKN O*CnLOQ--`ǡٟu?!VGS/- BKM #8O7shPzF:*z2yOL~ s;.?[Qr[XZ癔Ǎ֗8nߢW7*_ݳG!hG#}֚Pbdss )~ImN+-!_EEsJ\QJ5oh7 K~^^if N[޵% n>~]IAΗ<* Xe;1I"쇱967}@+!ŐU?ʔN~&i%#,6A ؛!i+*dvκ=. L7A ̏@ Ma`Fq_>^gMH8CFgB}u˖{odmwkсMJ!mۓ=bޜd:]WMW/x{Z+mBkWOWa}ʔVSw.]{;E:I%O UK)_rbM۬]WP8- {]MM5<NTQ#?ߠyMymn-{$/_rDVi݉/Jt|?t32lyO7T6 \O_^x1PG煳(td5o,\O ~q>O$h>;f-ë3}W/3Eʝ{ctez!;v),u#t,6vMu> stream xeR[k0~ϯcP4^Z:0`c1_w#'AU?JZ7`i'00@p VyתHQ Gkf9w$x5T'IoAY:gꗶl[ 7v:c@#̗ჀQLN@НO'^uWk;vFah(I4Fy採~Y,xe9=-oݚ>"- endstream endobj 4391 0 obj <> stream x |E_u=\Iɐdrܘ Ae#lP]  ]E]]u(*,df~MBȺwIM^_zU]3 Lxfʾ9,s%ey5:np^5uEo{/ hI˜xa{km%Dk ޠqΊ厑P(n,X7eԆͭ-`o.7,Xj~uC2k{G70[dg> `}/ӼGpٽK/m o30&︨yɼϮҋF(oYں<0^-kI^Qජ:m%ϩ~(|,oA}87wV>̫(`9WL VAS4fp<iЄV#ݗ(/< rPo& z>W/`- e2O([݊2&^L߉r{/Q,(*'?}~o;CyWVgg kŷW3r}ǔ X}Og( cϭ:P >ϭP83`?}\(I޳n݆P Ca( 0P kgΟ ʅcڧHۀkW@{ό{`lw( 0P %~A<31 dl&B! Ja @3,XYv]DWFWGGO=zXuW(8`x`s`1\_ǓXGyiuu\sa,-xKe AO`Nblϑ ?w%,kva8;)~qE܁u@:^b9 >~]ՠls ~ u~ p#7-p+voll=B Al#S?n옼ܜi#SS'sZÍ}VV)r(0H)u59 M^Y<]͘< 3xMR6Ǚ9=s 065Qrx]ϯ)q58=\ EB1tb Gua˚޲ KJU?397| 7LxP7tr]6wy`6F)N%7x&~e_ߕ:~e}ߕM.'ҦߊVَxfYW!fUc ` L*} ʯLjw}!ߴ~Q/۩NyQZCɕ) Lj j)ŎQYIq9M ԠDS<e $؃7K׆jX!sH>ʆR^m f{Z(a):xi6g‡#G!M8L=-! o N8@x*o /^"'H&@xaY^3 {OvOv $ t:^㝑ň!0!ƒ#Kp7.v6;n#Jp3&~MUpa Z5 _66"~AiE\I+: V.#"\JXiXAJBXJp!"B|<\lBsDEI800Hh #L#j;# jՄ*Beg8>Xa*aJgXE/(|r(GP>D}PG?(Q~!ߡDySW(P^Cyߢ~QQ^@y9}gQbQ< I](ODف҉:#֋8c(<QByQCQBَ N;Pn 6[QnA&Qn@(BيrmZUנ\] L%ZF*6jKԶǣvcǖy&34eȌQxH& 4 ,Pim `ZY&kW˚WTnaNakgd0֛dLa7^7,eCcpA|CRj^*KLߦ\,xYyez]N(guo> tY:qnN@afrϲښI]@$rm𣧪ѫ؄]Zm\EѓѸ)0ɻO<$'alMHG~`˓159tyϭW[[,ǀ=-%w7V$.A0{$[lA\Vx#,El#la<]8 YOg@/_?PX tMag@ (DŽ\0 [ f&@&'#wf"X apZLj }yµp+l[v<ҷ0 ax`tI> sh lsa)qB'쀝XI)^}X%-kp^7Χk/btƕ=wߵkzyP]oA86# ރ` O8.x P#Rσ5kpMG˄FY6z[.+`e&Xތ؂6{7}h^dߠEٯ}V|m۾L-ً%[i{v~'YLPvfa ?zRH9O[#bghվܶ_uߗJ9K)q' dQaYo'0'J9LL߹1=30{.a!,T:7HfgNY%2X6agy˗z6LeU->oa%Ofׄ>kq0gc0?DRhA#;h`ۅ߱C?VaET/ 1MH zuOCN<ҬP0 f-9cLvm挩WOxve!Z}QQ[\egK,H&ſW~k}WrlZXxb)Ǘ$FG]_=97 ˫Fs(zdpmnDCm f0g檈W2<ðǘu{mdjCVճ2+޷,aJqRKjш13ݘI 5*vxɮ籧uܻ>z`AлCB, r&y@&MTe?DNw^qO2K#\t112W蛛4igCg4k}Iɚ%o;FX&*]KY"ךtʢ+]֊KmȋZe.uh1qvcLؓ ҅Y2d߻W/<ŷi ۜ!8&Kҵ.qM= *vأvw'DžC3 _0zR\͵/LLnCOGz:?cr#݅l>! >-1b2;!a}ҳDHes -F!6UՆn֭Xe6E'Dg[|C}jMk9W..56Җ:.eҬ32הuW֧FIB|IsJ,ksU7&+mzZ9"'o d\D{լ̢aub%8nn3;=ZvRqR1VkTrr X[ NcG ۨ)"|&Y!FM]>5Q|km{ p7 GVkcu}P0GmEGDbb'U.6(?1WgiY >iď+ֿ8=0u|18)&ōIZ%[_6߻uμd-9KRڽ;j_a*u;AĶjF+STVIP4muHYpmcN"{i\518%xo38Ý=\d'=6jSFT)z*Jl0WiqTG̷zh(DAs4z3ꨗXc&X#=S2s5(i1Ö^ LM[rL_O1 )SHg1=! N}G^=xŃt,dS+u)*K.\S_Әg_t\cN kmxqêWO) Wݹ-E8o{U-6rpj 6|њ*:Wi Y:8pO3X0ϏԪkpM39|kj躔YկuU&Fy3kWf7 v1b,4;=w 4ySz4SŢA^ݸx+ :&Y'S ̙*QV6~u}b~u;v\wD3`p6 0\Tٜ]L 'ĸ1XgK=IFϚZK>oWD]2, xKYjC^d[śm3$>i&>#[BDզ}l-|1t oI:oU1[za,jܭR_2II̱ifc{пg?PǿD(D e4k%U3&;ϕPP9|F6`49LϞzDyӄ *iJx8F-Upq IR% rZ* zșJ) pto*Ƨf' OKPATP  AlrFzPGi4!".B]b;wZ0U 9;C%}9?VubRtnD:_-v:]c{V?5lֻ^m‹'(VTZR#V)BB5H7&QNܚC5nx1'.v/+yJ,N{SC>^tܑrMEN[j:n< g&>i+-iӧgL;5PqWKv*_UwV⼋=зG/RCNƂkz5=NP[ϟ}.pK}5C­&uMq֐:c‡9h@ 74a{2 B`ƺ6wJD_)#r FNɉeיI/pv*C z7|jM]h&\TgxRWn41'QJ%j8>+ }nZnx d4 0z_RQq2qsS6Oy^q&%ɴB>Bl#3uVsi?wC03\=Ķ62Bociꔦ|a^} u F=Ipnj@U6Q{XﳾiIazl m'I0H)?kgZ - d17Tƽa[<|{aY-?/l6eKޖ%id[~[re4ͦ$4M\6 `%RBIJͦl\n~ K)u3$ m{w0;o̙sΜ!k/='UgeL E٥E:O5gʊSU$Q.-#$cmk~e߾]eL6 ivcIQG1x{|}78>q\Ow'A^q#5{uttyr03i*Q=qZ+ˉq膘L+| 0:7I)ޫbĴt]Jqe쌃co8ZHm$l7Y3Ri㚇#=jOՈÔ&|*X%8_RI Z%H&RV6\-ܯ}#=>ߥV4ǧ[>KhTj1foLH܁(tRbQ`ĄpLS+V4tu ĩC*?V~lH8zG{>ȕ y,MThS32UT7Rt/3zFq Ūq . .^%Olt\8oٍ^er"wqSc:R%*$xPi!ZSDyyNl\^QMՔC@M)aUM&cLnj&~rqu!-ň}m^:C.~DEtzef٣,2+~ʌ>!>g1 dr2'stx/Y% r>C`S̙1gf^~7"+;7 ,sOŕ!,~)1?kK%zHKn+)~ioVTT.3wqmy6gnH얹9S%U9 v8#eKc2p׶_cgi:T Q&ne[G̒% 8ObLԋf_aL:?H@NtcQ?]\R$F&I ^}K6I$ԇTN9D\0&.>L!\RWWCO):~ĉW«O32Iۙ+oO\}+/(^s~J8`t!d~^O劢'O n=do i{'oO/1;7Aܷ ޼ Vͤs征vSG͆kOn8ȩ٪w_,Wș'2W*˟d ޘ+PR%Oge8[ϙ i1/75U~@)+͌7ʬwNb#: 2C74ݥ~Nx''{W|.;z^'^;OA?SE"诰1@? U= y li?`Ǹ|̖}ju!fKsN~` & Dw}eS=}܅OU(eUBAq櫲Y"rbfq*D[/Afu˩^Te99gkqqp-M^ʏ5 |pC\(_ W͞*Z;-[OX]&wAMŸN\`BB{k::qeUcֺek̛VV/ܻ֐^q>x'8Not4k{0 AIWťJRbV12Yb>_uo@?@?)G^IV+UIlrr R !ЩYbx }&>b57]qݫ{Sըf+R(YֲO 󄦗fiL`nQQq0^& dɾ"BZ΅CsjN\\NLNVTp86 k&  &OxhjhlȚ];31OҤ1WUjir5Ks ueJf'eY3/eJ^Jɫ2f2PҲ'8Lfb)a| LnCL_sNVMnR7jNNSVsju*l ([MtM_#M}<*F}WQқ(Aκ̇aܯ-zˢ~SnEz[{>?7vEkIMΪՅ;Ĺ%Yr:"H^G#YoFeL{"!رdɚp8Co+P#,B+N*\ U?/Eڬ9Yܔ2ol7vGڻ9?+VSn2%ҽl4;m4g+f=E5V-ٸ^ + 3j,tmr).6ö,khӫ,ؖ\Xgjs1jV;&Ԑ%z`M aAz!aܥ@E%%W jK̝ټmU2ӔlIf"bۊ6}[% q߼mwX0./|$Gtv 1N2=?]>ObWO?/,&˹9iE˺Wd)œ}ٶWu,`-d1,Șp#<{EkYںYs4F!^, d+57gV,*8KW=~ƌRQqcSG4uZvRShg1gVԖT!&=턙Oڛa'.t\p<@"T֬IOT$'\Μn$ZIo;Mзnvta#]']q\F[>㙼)~ɲ/d+4zzZݲ%3fbG;KkJ;XӋջ/)I_2@5.CVWFo Dly ǟ* Դ.+5U;wʭ^Rz5 {0$$rhdPQi^JKSeg'$ŃT9y7O4G|;-ϪYW=s\0kYHgw΍9,k)Yj5Vׇn2{s$,ޟ3EzJT$)U *qEe6>LRW钍U8ܕ%۳g7n}OO翲P<}deK@g?jꟁ6R]M$2 0U& {&}R]۹p΢a7{zQo+f =Ie[}8>&e:Ok4EIW|MiGz %fԷxAqg|%y"IL:#mJśvWvnlgNʜgv6*J/_^ew|!(r6ǫ jk'De8ukavh*4F8whg*V=nde?ʞTonf~uEB ) 2n:eW R5IGٯ`j'Y)A/[Iu#|yceݛ֬X`ys ?qt}M'+%f/Ä́ RYa蝀 ϩMӽjof-'_gdyl%K.Lͭ()ĩF'N*.2bLQִZON߶!~ Y=Ht&F|N+w`©إdAHo^QzU$o)!!!pIl\z]LLL2ƤJ}1%!IɊ҂?+ݓgt''NgL~SJFN #5M ĤO;NꍦҴR%M饐RzE-4Ki/K kwҝt'Iwҝ{"Hwz)͐$Di(eH䗧J4Od$ZF2dW%ZN*VV#Bh+&%qN`+I oҫNH4C:O&CIBnu$Z忒hٔD+I&EH)*GѾIGPHtch KR'YE=g,ҢEZԳHziQ"-YE=g,ҢEZԳHzTAT; $Hdr/ Ad %IYL! e}΍'}P{-`\-(A@ _e:E d~a{DKǵ)sHG~܏R0"ZxAF)2&a[jPtOQBG9nE Nв؏(E٩A˩zzq x Dy^HmؖJ@b<,u (G@0ꐎ)ZSZIoȧJƐӴ{Pw;ZOl:>}a G ##(9Z@[QKX#ÏTrǿ #؉z(چI##}vr]PjmK C$߈):T >DeLl*6Q*H;(-||[([ڐPԪj % ԡDOKqg4ktÒ}zuI):Rl EgQYm=n[<'gO!/Тk1*j0H.ƤA%|n8"Eh%.I_jˣ,~ZS IQ'fAI6_|Z"EDs-BLj$u]CL6AI7)qϑb@VTb[IàJHc*pU iWJ< PJWr+Hy/F F?,cP4L\v~"3e?fӳ+rF=PTcW7/w bJ 0/>{y1nC9Rht=ݷL*Wl#"^OcWV?-TԳFbsjzިJp-T7п׼( 2Tɺ yB@w00 K@+Ń}?4"}#Z_OŒ$0FG 0whh'kͽ!`HcPPv#;2u@(Gw7#BwOfˆw' ˄5>!0#Ƃf0]CeA}@ tPa{QёodDဿJX!8! ^FD{F`` Nz@$ SU"`'?Cu!/ޞZ JoSˆ8%/H%*CP]w`萷kp/mW>0ž~a;I->4$Q){pZa 맔tF2' ѡƤl (D9Q䢚 v{[}!j"QztGTBޑOZ/SLEGtpF.` Zj+rz:ֿ}^l|CTU# PJ` ͉?F0v{G' +8 7VVU EW+T__BoRXCy0 QAυсRЖO*޲b43tǴz ': @ `W~9,authpSPO8^%^@/!U}pz xc;k"GaJu}÷ OZ UxGE~f9NH?j iM5P",jaB1E@71M@73@/f´Y 2f˙@`wZVۘ6 h#cĘngځ63f-hc؁v0L.t'J>=/]s>>wHn 0"Wn= _X+Z*>S@[ UL)"}Sq0JGd8%df@X¨8UEM0h=(/T ԧPk$t>0s?p!o\/\/\ƃm[x :xwIv-.Z2/XV+y@RUJZ Vj0jeFLQ*S30ve!xUA%Wh T^V y9JA!AoO 㰷$fM(wKH:ڬV"-)qڍ/\)Kw$hjB\ nG܃xК5I A@Xhi2ǖ?I)I<_@%R@@ Rsհ{ݍҼ1xrV8'Ks<T]xC<+/J̌☙~(Z&櫐?pL[* rt9bU( obd]6Ő+uG07Y_M 1B.jKAY%~)dC y5䮘cmC_p oU%cC~ NȻ! ##$n<.5)3y)_@oS16>*;?|ÄI% ~OmkʑMD ֣KAu[_7m%[a,GMXYI5ySgE>⇈ ^Ҿ1ڟLFw_Vny[ݖ~2qDJg1SrO7aM籯a-WJU\)#m+fjVU9 1=J_3DK&ͳ(gs1l5 5XQ5Nykm L{ܹMQfKF]n<{DK& XFwI[wH Z8qѾ: wEkCђIQ Cr`h[". 3,;Jљv -oO|=shM:g /aKaEK Vvj,SӏB܀?͗F;W'%w[8.Jz-jAK `/bВ1SZXri[KʯA6i\gY-di~h[,f:aJr7EDH6Ӳ9o-n *g,ۀϳq,;$m_[X MX`M/v/nǐgQڎYNOٳ"^@ ڴ|S1庻t{XYf*e5bI Z]v > U/yXsѴ1ӺJb5DK޷Z#(@VFu5](O?i !nb>ucck'ǤEim׭Q)EV,7/J3)j`G$l5(%k(K@C,5htYTEi! J6Gjt34*Z?qh bЖvB DTCesDWV5+ƽ7b}yiXdc7]^RIv֣H?q~jhiph nt aطE-&tht]p6w_bwǬccEV+NߣlQ96x4fAOjǃR<z+J]=Shd'jfw5{)fVgĘ8BfɂKav-4XH2x QSI59kqZOJ} .x#=֙)3V8{ʐ# }~ |oHGC<5il1,Xg5՘Vc"љD9;y(iv+,ԧXHGԳH*TgCbYAWgh;AIuF.;C3&ӍxbOt ;j9Yڶ͹mn;܈u|&X1x+ .wFr>;!:ysHa봜-{ P8߉E=^B>p.%T65>yKI;`0>+jO\GDž0%wyROwTy$Qzo|E'[}NW",6EzPsƣAφ]<l3wll5yz\ŎmG;Ʊj3Ad|c̻4q,r lwx]8yxgqg7Yϋ&Iqs=ǁs~L)EM).K9zv5eR= \to%P .A=<ƓDDqFgkhd$mDc#HMFGbtFW#S47FX4.6.xdD|mQԿmb'zw#bx$59 GG#E~!Q2'D&MYy0I""OEy%RDFvDvEEFDj#"ߎʏD؎r}H7l&~q{|lyK\w~Adk~1+Q_fHkCHTh=*IGqxB7Q-^urE :ᇢ'ďD!iGI8Hn R)_AD"FS('r)d~i1?sq@ E, ٴA;N!Env7ӁJQ2fYJDkɊN\,3Q͜#bȷpDc8U s *Vek9j Q[P`b/1D3CyEB#/wcB3qXq^ qbE\1_/WH(%}H[پo}8}0Hv#ۉqbxvN8NN')pg sJN<vҳkଥnXGs@u ͔ao'{jM*@(FOۀ6QYnCTh.'?080G;iT”4IYk3\'0' Ơ$~TVdo"{* T֣=;iHs8-ӰͰTޞa]hYK-( F  (4ն[RH P a|;\k2I }0̎R(4&,3`SJG_OmGc[Am/ S("(k[|K`$~!`YpBp3985x7=8TVϥv/ >Z>l-k-,TY=c|4'*> [MK +'_J&JaG`JpWp_`H6X!;u*B+/%9v4JI'M/!= 94[NrB6 5T*0ȩ  ܥѤFʝm͡ɡt!'4;4/r- &ádJ塕djZWAh]hCh3[>ս$ƻ+גС@Q*-0# -}/qۜPiq`F8'&;pS]W?!܉쐵PyB>Dy$  LJ'guq. ٟGF>WM8,df8HHƑ.5]j:Wuʨͨe>SP3:OˌɌ,B<$ ̷l];ܟo?Kbb:Qfs}"vWh!iC-RȌ/xqʌg 3t:Cg e3' |3#o]%xzs=oZ?7w{>ƪq O _FxBOQ_SNDDAnDyDD} y(x)9i<i: !Z:^ ^JTEh.J&ZOhKDz : QWl';({HLm񆉺#H4h(ocnw$MS"} 4Wg%C9=B)g/j+D5~hty4nޭxw]≶nG#h>{Aۃm ǂ$;?\]@_/r͞|dٔwҿtju mL'dordr:g'g$qzr^rartc'OL<-yFɋ&* K6䓫tX>`W{=ɫN k(TSX+7KN1yQ*Zw}XO 듅G+VM+뢍y֧.fyRd+SyEVfRDFD9*_PD\Vb k;08wzL!|H+ U3aBjpj c6UQ p}; 9|loO>|\`' jTS%^O*F <ļyyAґwCW]QB"GQz{{# lGYPUwX+{9?D@xXcyL%,9t8Uw4T9Nod^gT 4~rnʩq< ?s4~V jӊJ'LE_bVƷ,+c,ƌ8i_±V)y>8v*~89-.=p$QE(mrkg#ma6s U!_|:p))j(֍WqT }V P`o,o"-}f[<T' yE $}6L? Q|h6{&|#$=Yys),BG!DU >ͺui*Y fqy~MMUi)R%/.F4Ior+ f!cfރQ o4s;ΪRoĜuVz>/[-Od+=n̾OpT>7Hn͆$KPH}Ik,NSnW# ,w's=ΩC}!6E;.˼+q(ޡAx9KxF9oVpx5rq9-i4 p`kM~;9|KauR; b:h6T2,|+5hAc9$@r=*u$*\VklM8XՊO3_u0UWHZZRvfWgkGñP$kƀjhH^?r ؇uXٮFu(%ʹ9=FS w|r&'WI\|f_OqA4;'?.p5ȓ5'@קcJCW7O9o>_7|W˾/@z3# 3zF3`G ВѶ|Wu⮿ܒkg֗n-enW{4\gnLݳ@./J끒{@?=t|Y2ߩjh!d](p%^6wBJBI^N qN¯gI };Qi͜QFrf=b;׶7S۸_ ,ʢTYb])LoV(0K1p [ e Y:KP)"b yKk5n*> "ʰO4`._^#apT)p*3_/n_b,. L{eQ{b. JO"NÜS.w2=Lwl$ yX$[G0j#>P|Ǧ{s%]r$ħ rTp|W cv#`-a'1O_T&]-eyZ6y,{ L1KrBHd'p0 # X+̝Tr%_ĸ/yxcZ \9b0;AR ~Z23oND!d4W~p0p-Roށ\'!?| p$RE46}Uќq$XyE2`m2PܜNvQ8m-Իc݉˔_!?ك<8xz@>%-O<|;u]=-?_F ȯ!փz-@Q̾ {z c&@'s>x%m$/|ο=W+!kF-3x/5K BFn7 vuӁxZg+ uPu/{xUn5_~|s;>&Gղo|TM*~Z$#ڋsD."_~_b($CNj]E|C\".qA$~8zkEGq.ͫ\# D(y8LѢ\,&+tBD S$"֌N"SS+U.[mob,:QLuF K#ۉXE8"$"BKĕLϞ\oW_5z t؝ ,2d B`%pՈ¬nn1fv=cV &;Fz }x}  8"58 88tl1 jiOVk[;];T`qһZ^`c`0v ̰:9<`0   ̲fU5jzFB|xx0`3 6$ ډ`*30 wqvw`>88d܍eQ2$T_8XjoZx~)ry>&O%ǿ^}MO@&b] eMN[(tIqkbIci`?tDgQtF(sX(*X-E,ⰨX Sd̐a+ e?&+Gr9QNeGx>僮oC)AҾ/Modž'b-_5n|#Sqm;覷b;Zq[t]:NoXq:.wO(s'ޭcEWێ\Wvxx(qv;1 2\+sR=^~G̑9T|W /|/w1|Wp+|WpO .^\_Wp1|>x/|K+/wBn(LwSںC,+ĝbxR6R.[Ľb_!1s~o~<>/x?wx?|-WSE|ZgK9I|A"ʵr\/U\7ZrH5RE7r\q҈Zp )BP:c4zFZcF16llQc[2||^Ƙ//F?KKljlfj*cdsuugi)[{ͽle~b~"OOek33`~a~!24WW {Ig\5O'_џLVe WFjj&;VZ2UQm9ʯ2MyjN(Si*MvVT'EuVe !3TʒQRA*Q9*GT7MUw]Tʕa*_U HnX UGvWT?y*Q%2W P]?taO2}^kdO둅(oF"o#o#y,66ͽeo o Zvv,%K|G^Eh_wM, WN(H3Luu0e|ufi08 NI NEJ z$S%::eMG F84+Q^&zJP6Ё8"bxxzPJA9ՠԃFZ:A78 z@t4% ~[ 7-0p< vx^W[C ۪ީ@-4JHHQ,Q0D"PŢP ʢXʡXʣX* 9JB>4T(V:(V(րz(քCh +M9zBShBG_kVvbw,Gq$0N28+8+g.CzM&Q<@d™p!*N̠5O,DW$JGbTj=Z[ۉ\;Q\Lx7Q Dq@$L%D ?h'NR'cP,DK#]2gi~5Zp),fN&O#Ԝ(aZ)XYV* CgvvQdPٟPO*4! T =Bc1@DLL@p"}:&‘CtE"G}%`H_\%`Dz'/S8q_f#0gH,蓗%' 0`N#7d,),mhIXP/=Ȍ6X>[y%Y\Hژ-hdcF`F͌3$K~L/Y@rݨ KD",CY8I|5x tcnShкT!s*vb Ec N3|E˪A`L[q-,'BL c?FR0zet*TѩSEFJNު0UezVѩSMFZNVQhV m@ rBkJ<j AFVZx>~!^1G6D,CAOD3AKo) [.]D ̃8"F/".I0FaXL΋>>COׅxG ƀ- b X"! .5v`.h]Ѻ,u9+0WdЭĠ[yU1HWgCm: >t|1gaÐÈ{X$mՈ# 0{kڱ vc:oěc $ކc)bHK%fɳX*,u&K2`Q,z{$˜eŲfecgM`ٳXN,˝#g8I|$?)@ ")A#IMsh8 h ]$>"m8D[y}|1d,|7=z,T7,CLŬ a1ҿ o?ԏ!ρP-?|z!9E?ɏ;JU $6NԷBO0?1P^l.`Y37$G@!A-A$eMJy0dƒ$.M 4\JbSI؇|&QYyrc,%,եtmXxLDP@ OIG[kaa4-'",2̟dnU㝰/^PX(WRRﻄl"x1! 3˥(3 !dDqEIPe@IP|!(Y:jm^qt\$P%Ցů yM5c`"+qVs'FLԿtbQ/BV-r KĝTbMyJ̦7'><("W9NrߴvD7inz дoӃPrXQ^)kb}zF=Ol~RլґnAj!c:v_'bq׌ _/(YJVn5S?C|O[7m}Nn@󛆗.'>)q7iL |pjVg~O]|Af|L%D߉gix|=˱(c26&'])X1NM#nqQ^qW>bO* 8ebW*枴[܄W[0Vش˓ լϨ L_tͮaw uBl>xo픶۹^qjCcaW)X֠J kNڵ?|<'>G~br=3 ;w9LsF_x$iEɛ*2sD VS:(#;guYVNRgcvWΰKrJ%6/UkpաC784y"\YT,45pdT[J&u ahB#>Ϡ  G/KǃgY I e^V^kGo_oҕ^ËAo:E Y-ZXkqOmN%uukM{q%n֭77.U_pyA=&fX^|o<|2̪zzk-IVUy[@#%$)S\}egED #8ecDOcVHP;"Vp) 11"ʂ2t4m>k z8k:6OvzIo z(f>llqHlU}#g( ӭ&Y55~5cNHY}}|ǣo O>#`-~aO\K{k%>yJY>uG^?= gʳWU%DiEfk% %z*eJTW\0v+!'Bm{6gqr)Kk[/L\/Yޥ{y 6Sr$=֤ϦO"G%r;*53""#d7 1>kc߹MrwĥM&'UYR_x"k4eEY囦xᖆ>!_uhb 5 ]Ë4uE@3@YԤUu(ʒ2TAѿ1D'bf{k@r(|oĔQ/'?E;n(x+#-/mwj_}hӤ- a}xH#5HjxO|Av$q-U7 W|Є'.4lǥ]gFzvtѨusM&e496OyY_7ur|$]*_jQ}n^+FHj59\*SZ}ӭ^+UW JAPf WOz;)l&I+Z3RiZXy7zqd$'7< [-hw|xd=kev́nU ;/4}F7G4OˡɈʥO{ҭrmWJC_pM/*7pV8ttw9Ä)B䋗uBxǃ WgZ:>7yEh$ 㤼:/Z.hv[A˂,tŤ-#>\Wqy,qD JtV&^&c8sI@48_Dd';juB3]>I3wti]d}o*:%>:\<#N\ _@C,^$𛊶a+3XQC|CzޘdY\rBW< Pg̘=_g !vԳ ,i<9G=.-j~`տ=8t's q4ZhaӾe?S&WIQ#[6-)d?!׾˜l<3%3tޤۛk]o_[%i a_$1E]?u ibܣNubkwxAvkG5':=X_[8CV>uV #*ׄĪ{r#|+G6?{>.oCWǙkkn5꜎}Vit!)#I)7F]ʮUN\S#UQ?l-ϕ"V'%OXn{uC ;+z-K(Maz1[å`W_yPWb'#lɥOd;utCּRly1b>7$V"2 B*1~q'vS|8|[F2qmuԚ)050J,.XKͬ.]dXDyD;rI@ ٙ<@ G j9b"c~7VKI*pJpUWM{+nI)vk{cRy1YM4Lj4y+GܩJtu]Ჶ̑z7=j-Uw Y{D+8:}gkUy~ݰjw_BH5Ntlrȿ({@~&}3]ܢQ^{yf]š89MI^oD._n"`/9ʎ$LJdMQo3 DPRC(S v֜Y#.׌g;"꨹d/gslcGnBݛWIu}kk_(uxGY[$fSgαy},t[)k?/x~/rYbwn YH ǯĽҮ+~˛{>|S]CMtI7RvvΫGN?r؍;[6 wƶ&ۼ}A*Acnՠkļ<>ﳃR̬'0 endstream endobj 4392 0 obj [ 0[ 550] 3[ 550 550] 7[ 550 550] 22[ 550] 131[ 550] 133[ 550 550 550 550 550 550 550] 142[ 550 550 550 550 550] 148[ 550 550 550 550 550 550 550 550] 345[ 550] 347[ 550] 360[ 550] 383[ 550 550] ] endobj 4393 0 obj [ 550 0 0 0 0 0 0 0 550 550 0 0 550 0 0 0 0 0 0 0 0 0 0 0 0 0 550 0 0 0 0 0 0 550 0 0 550 550 0 0 0 0 0 0 0 0 0 0 0 0 0 550 0 0 0 0 0 0 0 0 0 0 0 0 0 550 0 550 550 550 550 550 550 550 0 0 550 550 550 550 550 0 550 550 550 550 550 550 550 550] endobj 4394 0 obj <<639893F5E2236A4DBFEEE91ECD97D987>] /Filter/FlateDecode/Length 8831>> stream x4uUeaNa]-*v'&bw+b `av]9v+y1k}q&'dL~P1~(Q1ݒ 3>Y̻Û|P1ł=O*VkbuQ9XbWzb3)6[Uly|OG~n׋}}fC N)vةoKn~a BŞ{-[Ak'):!}-bSn1~A-GY:+wUwU8|g,Nr NrN> ڶJ"|U KƁťuKl\Zu+U?{x99KUyp(^obo-UuEYZstS=ώS~~sSӎ*8˽u2lbnmv*>^dZu{Ӽ3tZabe:O-j)vڶCu;rv~:L-uQ;ݺY1r]xQbt*n۴G}-qtőxN|}nk,Z߽e__GZ|q-\ @_S ]\R_Cau\>ij6x~,>Ǡ6kmUrw>+nlp\F\Qk޲fqZ-8[nEr{-;+ ^.Z<^t.Us.:w%u+Ejm]t2+VZ{QlTwjƋJnbXZX{6#摵gώkzBcXfISa|Am U:؋Mqv~J][b\1db3xEbXRׅkYZ zHh-N֨׊N}8u)\xhaW Z9oz߻T?ԦsmyՊlkݭ6Ŭw \,ZNkMҶIUmˋ^5۶ͪmՒjS7lv"8أjضgɋ~U߶uUW)*hZne&n$G[k{j=KqG]Mcjl{V]gn(>tziv OruzNbzj}/>gD7\1Œ.cR (6KnfEm+{3*YCq}Ծu_Mڿc.:&:B}܎).,hDz]QK+G8_ŵKuT'U0t5yb;/PKs:oRܻ~u1p҄@lW{QA'm@g~)0)&dӠ FWL1-C7̌0faV̅90'c>̍y1X `a,(bXK`i,e X+V*UXkbmuе=Ѧ`cl [c l- Eol>;`G석 vnc셽?Ns/8`!8p#q18x1c0yOA8׼EOGKq6¹8a(.aR\qu W\kqnp܄0VƝv܋9wc c,ƒx1<“xxm^W"^Kxu7x]|1>Gs|/G|? ~Ɵ w_D#hcD1iMg(eD1jm`F"QHd$2m6Fhc1QF#ͨa$2QD"f$2݌`F"#(e1|F#Hd3`F"#f3 Qly⻯qFq͈it3݌nfC(e2:q`F0#QHd3*`F0#Q(W`F0#f3J|F0#XT-*RF)Q(e2JRF"\ѱ(e2J`F)fA7E>ϭG@son(F"#(W/(F"Qшb$26F cѱb$2ǃ(e$2RF)#Y3Jm6F0# |F #Yf1nF#f1dE"(e3/@f1E ̈b0(F Ȩa$+rm`FŨa1QfB)[n A3=?;0"Q^( @gL1=肮 ScLn3`^̍03f ctǜ `I,0?X c,ŰVA, rX+`Eêհ:րp`mu>aclM6G/l- `{v.`=>apA_CqG?8Gh3q: qN@ `Sqp68\p1܈p.+q5z ݸ7an-#1 qn O1܃{qxag_K| w?`pA8}q(E?qHcpqp"N@Sp58gut.D{| p).E!Wr\aW\p=np܈p'n܊[0 #qF܎p7NV܇`,CxQ<Sx sx/E ^kxoM}u=!>W[|;g___Ed059 Fkk:7I1q(T@"|Q_35F#b0(F#Qfd0E f0(F"|'˦`Fѿbd0(F`/6F_/`Fo#a1jX3^*Qшb$26FE#Ȉb$2Ռx[u3RFS#Hd$2b9ft3DF0Hd3ŋDF"Qm$2DFLQ(e2J1`F"Qʚhf[۾WyE1m׸FͿD)QHd4`F ft3mRF7(et3J݌RF7ftf`F0#f3(F0#`3`F0Uf3`F0#fJRF)(e2Jl~Q(e2JR֌1lfI2&;_QxZЊ61)& S 43a:L0#zbf̂Y1f91<a~,"Xaq,%2Xayz`eU&VXa-u.b#lM)6-%ۢ7Gl#vb7='b?p Cp(#G(cp8p"NASp*8g,sp."\!Kp).p%: q͸b$Fa4nw.܍{p/xc0!<'(xO)3|/%d}?7?'?E9a3| _d08xLsDbE"_z D1jUE#ѿfD1jUE7#ѿbD1jUE#ѿbD1jUE#ѿbD1jE"`d0R F`<D#Hdd02 F)#`d02 F#`d02 Fq`d02 F#Qd02 F#`D82 F#`d0Z F#`d0 F#`d02 F#Q`d02 F#`/ F'n2D#ɑ`d0 F#`d02 F#`d02E#`4.2 F@`d0: F#`d02 F#`(2 F#`d02F#`d02Eѿ_/"ѿ_/5m7t~G- jGh@;&EgL0%+t`Zt<3`F̄1 fls;\ `^̇(BXXKb),e,X+b%Xb-ձFX`]6D/lM)6[`Kl vDol>;`W석 n{`O셽~8@PG?Q8Xq`0NASp*N8g,sp."\!}R\qJ\:\07&܆q nHhw.܍{p/x`,CxQ<Sx sx/E ^kxoM%{xC| >g_?| w?_+~//Ѹ᳒kk `/2~-56FQшbd02m FѸ`D12QF"`D1j F#Qߨad02 Fѿ_Q_D1(F(lD1(F qbd0E#b0rF#ňbD1jU F#|gD1jpT-W_cihct3ɊFjhc16Fƈb-jmEƈb-jmEfT-jmE#hcD156FƈblO p׸2l>5G"#w(N=DF"#h\D1DF"#H]D15DF"#Ѹb$22DF"Ѹ(l$22DF"Ѹb$22DF"Ѹb$22DF"b$2DF"#Ȉ~1QDF"Hd$mѸax%\!JQRF)kkJGX^Vh¨ު55NhEtS3&dSbLScLnc&̈Y13flX1ǜ sc̋Xc,ŰJXK~-NJX+*X=VXkal6c+lM6G/l v{cG=v.aw쁽p>8a~苃q8q$ѮI8X 8'T A8gt3q…8| p).E!Wr\brոz܂1#pn[1pŝw.܃q?ħ3|5)ě;4[ Wx/>R/jXS]5FܢQ_02q F0Ԉb$25DF ;.Q:6FLȈb0(F QH]d0(F)#n55_M| $2RQFE#[/jF#nѿad0b(FŨa05F_d09F bT4qE Q`T-2 FhXd01QѨa1j5DFX $2 F#سjQ>@6F)`T-j5E#Xd0|F Qhct36No0[0j(F>[3F#_32mF jQèa/jmnsO/6F7qHd/j5DF#uψb/jmp7́#2WL#ňbD1Q(F"(e9E#Ѹ`ƈbMuLTa3`?;06IMuZЊvLI]1&]0E7LfL3bV̌Y0Aẃ0'Bb̏X bq,$X+c,"z` Uzbu&X`!6Ɩ 6;`[l^6c7 vƮ{`w=7~`Pp4@?8 p,8'`0N‰1gTq8g\0\02܃%qƕ &\07F[q Fn܆Ѹ܅{qAX<08<x<^x 4omwLJE[ ոÛS|O|X\4~o͜Y3Ebx 02qE kdk͈b59(F"#uQèa$2jmE"hc0݌EQhcD1QD"|55[;*5DF#ѸbD1JQDFѸbD12mF_0ŋ F_02}T@E&5RF#uQшb0jE0#Qèad0R(F H]35FHO,2mF"ψb-2mE>#`1(8XF"#ňbD1Q(F#|x F)ͭ22QF)Ky f$25dE#QhcT4DF#fd>E5u*"n(e1QDF#uhd0mljhd0mEHd0(F7#iFQjka!5 F"_45؜Κs\԰9E)S&ˏ/?lYRIъNh@ ScrLS Œ`zttͿ-9,a̋s`n̉0k (y?;;D{o =60 vk쉝;]1*v%FcYE+bޜOOfݙߜwX b X1 U3^ZXՌװ.zbl [b lim0m11+v l#v. s\ {bw쁽,pװ/fX#p80ʼn8 Gx<qCv55p*Ni8^Lp>9p ;R\U|t.Ÿn\+q95 WZ܊p=nƍ .7߁q'#iE1jG(E_ڗ:E1]D#ݩ5nFQb2JRF#hcD1mF#`/2QFҞQnD1jӛ'Sj*õl`j-%خv~ f}ppb-T'ZfrެZ[jgo6,xVֶء jlFD?\N?R)kaZ_^' _? endstream endobj xref 0 4395 0000000424 65535 f 0000000017 00000 n 0000000126 00000 n 0000000435 00000 n 0000000715 00000 n 0000001647 00000 n 0000001808 00000 n 0000002032 00000 n 0000005030 00000 n 0000005196 00000 n 0000005425 00000 n 0000005550 00000 n 0000005580 00000 n 0000005733 00000 n 0000005807 00000 n 0000006051 00000 n 0000006343 00000 n 0000009528 00000 n 0000009658 00000 n 0000009688 00000 n 0000009846 00000 n 0000009920 00000 n 0000010169 00000 n 0000010733 00000 n 0000016259 00000 n 0000016390 00000 n 0000016561 00000 n 0000016803 00000 n 0000016935 00000 n 0000017067 00000 n 0000017407 00000 n 0000017540 00000 n 0000018388 00000 n 0000018521 00000 n 0000018654 00000 n 0000019341 00000 n 0000019474 00000 n 0000019958 00000 n 0000021006 00000 n 0000021139 00000 n 0000021498 00000 n 0000021631 00000 n 0000022002 00000 n 0000022135 00000 n 0000022476 00000 n 0000022609 00000 n 0000022742 00000 n 0000022875 00000 n 0000023193 00000 n 0000023326 00000 n 0000023459 00000 n 0000023811 00000 n 0000023944 00000 n 0000024300 00000 n 0000024433 00000 n 0000024775 00000 n 0000024908 00000 n 0000025041 00000 n 0000025347 00000 n 0000025674 00000 n 0000025807 00000 n 0000025939 00000 n 0000026290 00000 n 0000026421 00000 n 0000026750 00000 n 0000027103 00000 n 0000027408 00000 n 0000027539 00000 n 0000027670 00000 n 0000028004 00000 n 0000028338 00000 n 0000028672 00000 n 0000029017 00000 n 0000029148 00000 n 0000029493 00000 n 0000029624 00000 n 0000029969 00000 n 0000030100 00000 n 0000030434 00000 n 0000030779 00000 n 0000030910 00000 n 0000031255 00000 n 0000031386 00000 n 0000031720 00000 n 0000032065 00000 n 0000032196 00000 n 0000032551 00000 n 0000032683 00000 n 0000033038 00000 n 0000033171 00000 n 0000033304 00000 n 0000033649 00000 n 0000033782 00000 n 0000033915 00000 n 0000034260 00000 n 0000034392 00000 n 0000034737 00000 n 0000039091 00000 n 0000039145 00000 n 0000039271 00000 n 0000039302 00000 n 0000039459 00000 n 0000039534 00000 n 0000039767 00000 n 0000039943 00000 n 0000040182 00000 n 0000048390 00000 n 0000048539 00000 n 0000048656 00000 n 0000048773 00000 n 0000048890 00000 n 0000049007 00000 n 0000049168 00000 n 0000049449 00000 n 0000052494 00000 n 0000052735 00000 n 0000054413 00000 n 0000054564 00000 n 0000054670 00000 n 0000054776 00000 n 0000054882 00000 n 0000054988 00000 n 0000055149 00000 n 0000055379 00000 n 0000055602 00000 n 0000064169 00000 n 0000065837 00000 n 0000072452 00000 n 0000073762 00000 n 0000073940 00000 n 0000074180 00000 n 0000080416 00000 n 0000081684 00000 n 0000088707 00000 n 0000089620 00000 n 0000094953 00000 n 0000095748 00000 n 0000096032 00000 n 0000097661 00000 n 0000097911 00000 n 0000100240 00000 n 0000100477 00000 n 0000100702 00000 n 0000100986 00000 n 0000102886 00000 n 0000103136 00000 n 0000105512 00000 n 0000105748 00000 n 0000105974 00000 n 0000106336 00000 n 0000108636 00000 n 0000118527 00000 n 0000120419 00000 n 0000120770 00000 n 0000123007 00000 n 0000123231 00000 n 0000123450 00000 n 0000123696 00000 n 0000125462 00000 n 0000140248 00000 n 0000140593 00000 n 0000145483 00000 n 0000145716 00000 n 0000145940 00000 n 0000146178 00000 n 0000146404 00000 n 0000152540 00000 n 0000153711 00000 n 0000153997 00000 n 0000156047 00000 n 0000156340 00000 n 0000158560 00000 n 0000158900 00000 n 0000161305 00000 n 0000175515 00000 n 0000175696 00000 n 0000175943 00000 n 0000176092 00000 n 0000176209 00000 n 0000176326 00000 n 0000176443 00000 n 0000176560 00000 n 0000176719 00000 n 0000177047 00000 n 0000180732 00000 n 0000180994 00000 n 0000182692 00000 n 0000182843 00000 n 0000182949 00000 n 0000183055 00000 n 0000183161 00000 n 0000183267 00000 n 0000183428 00000 n 0000183675 00000 n 0000183904 00000 n 0000201848 00000 n 0000202349 00000 n 0000208203 00000 n 0000208884 00000 n 0000227562 00000 n 0000228233 00000 n 0000228558 00000 n 0000232327 00000 n 0000232589 00000 n 0000235376 00000 n 0000235527 00000 n 0000235633 00000 n 0000235739 00000 n 0000235845 00000 n 0000235951 00000 n 0000236112 00000 n 0000236402 00000 n 0000237490 00000 n 0000237641 00000 n 0000237747 00000 n 0000237853 00000 n 0000237959 00000 n 0000238065 00000 n 0000238226 00000 n 0000238342 00000 n 0000238460 00000 n 0000238578 00000 n 0000238739 00000 n 0000238972 00000 n 0000239196 00000 n 0000239474 00000 n 0000239711 00000 n 0000239845 00000 n 0000239877 00000 n 0000240040 00000 n 0000240115 00000 n 0000240369 00000 n 0000240542 00000 n 0000240777 00000 n 0000240963 00000 n 0000241214 00000 n 0000241527 00000 n 0000241778 00000 n 0000242011 00000 n 0000242234 00000 n 0000242480 00000 n 0000242709 00000 n 0000247358 00000 n 0000248530 00000 n 0000249069 00000 n 0000260809 00000 n 0000265925 00000 n 0000266233 00000 n 0000268603 00000 n 0000268870 00000 n 0000271038 00000 n 0000271289 00000 n 0000271520 00000 n 0000273544 00000 n 0000275196 00000 n 0000275516 00000 n 0000278034 00000 n 0000278303 00000 n 0000281650 00000 n 0000281903 00000 n 0000282134 00000 n 0000284142 00000 n 0000285783 00000 n 0000292680 00000 n 0000292829 00000 n 0000292946 00000 n 0000293063 00000 n 0000293180 00000 n 0000293297 00000 n 0000293458 00000 n 0000293712 00000 n 0000295080 00000 n 0000295322 00000 n 0000295549 00000 n 0000295696 00000 n 0000295814 00000 n 0000295932 00000 n 0000296050 00000 n 0000296168 00000 n 0000296329 00000 n 0000296561 00000 n 0000296784 00000 n 0000298731 00000 n 0000298985 00000 n 0000300383 00000 n 0000300530 00000 n 0000300648 00000 n 0000300766 00000 n 0000300884 00000 n 0000301002 00000 n 0000301163 00000 n 0000301513 00000 n 0000302600 00000 n 0000302931 00000 n 0000304881 00000 n 0000305032 00000 n 0000305138 00000 n 0000305244 00000 n 0000305350 00000 n 0000305456 00000 n 0000305617 00000 n 0000305926 00000 n 0000306174 00000 n 0000306454 00000 n 0000307413 00000 n 0000307677 00000 n 0000310363 00000 n 0000310514 00000 n 0000310619 00000 n 0000310725 00000 n 0000310831 00000 n 0000310936 00000 n 0000311091 00000 n 0000311340 00000 n 0000311570 00000 n 0000317807 00000 n 0000318728 00000 n 0000321710 00000 n 0000322367 00000 n 0000323122 00000 n 0000323753 00000 n 0000324496 00000 n 0000325125 00000 n 0000328672 00000 n 0000329342 00000 n 0000334311 00000 n 0000335031 00000 n 0000338714 00000 n 0000339428 00000 n 0000344571 00000 n 0000345373 00000 n 0000347671 00000 n 0000348317 00000 n 0000348881 00000 n 0000349460 00000 n 0000350029 00000 n 0000350609 00000 n 0000350880 00000 n 0000351117 00000 n 0000351392 00000 n 0000351630 00000 n 0000351903 00000 n 0000353601 00000 n 0000353881 00000 n 0000355595 00000 n 0000357888 00000 n 0000358546 00000 n 0000359114 00000 n 0000359693 00000 n 0000360260 00000 n 0000360840 00000 n 0000366947 00000 n 0000367868 00000 n 0000370961 00000 n 0000371648 00000 n 0000372388 00000 n 0000373019 00000 n 0000373761 00000 n 0000374363 00000 n 0000374603 00000 n 0000375805 00000 n 0000376089 00000 n 0000378010 00000 n 0000378252 00000 n 0000379559 00000 n 0000385953 00000 n 0000386109 00000 n 0000392662 00000 n 0000392831 00000 n 0000392996 00000 n 0000393185 00000 n 0000393378 00000 n 0000393563 00000 n 0000393746 00000 n 0000393933 00000 n 0000399258 00000 n 0000405105 00000 n 0000405281 00000 n 0000405524 00000 n 0000405661 00000 n 0000405693 00000 n 0000405859 00000 n 0000405934 00000 n 0000406177 00000 n 0000413313 00000 n 0000413457 00000 n 0000413489 00000 n 0000413662 00000 n 0000413737 00000 n 0000413989 00000 n 0000414172 00000 n 0000414424 00000 n 0000422093 00000 n 0000429302 00000 n 0000432440 00000 n 0000438378 00000 n 0000446094 00000 n 0000446275 00000 n 0000446523 00000 n 0000454132 00000 n 0000461305 00000 n 0000461447 00000 n 0000461479 00000 n 0000461650 00000 n 0000461725 00000 n 0000461973 00000 n 0000467062 00000 n 0000472335 00000 n 0000472390 00000 n 0000477504 00000 n 0000481791 00000 n 0000486876 00000 n 0000492221 00000 n 0000497618 00000 n 0000502375 00000 n 0000507830 00000 n 0000513703 00000 n 0000518240 00000 n 0000524215 00000 n 0000529299 00000 n 0000534605 00000 n 0000539560 00000 n 0000544452 00000 n 0000547087 00000 n 0000000425 65535 f 0000000426 65535 f 0000000427 65535 f 0000000428 65535 f 0000000429 65535 f 0000000430 65535 f 0000000431 65535 f 0000000432 65535 f 0000000433 65535 f 0000000434 65535 f 0000000435 65535 f 0000000436 65535 f 0000000437 65535 f 0000000438 65535 f 0000000439 65535 f 0000000440 65535 f 0000000441 65535 f 0000000442 65535 f 0000000443 65535 f 0000000444 65535 f 0000000445 65535 f 0000000446 65535 f 0000000447 65535 f 0000000448 65535 f 0000000449 65535 f 0000000450 65535 f 0000000451 65535 f 0000000452 65535 f 0000000453 65535 f 0000000454 65535 f 0000000455 65535 f 0000000456 65535 f 0000000457 65535 f 0000000458 65535 f 0000000459 65535 f 0000000460 65535 f 0000000461 65535 f 0000000462 65535 f 0000000463 65535 f 0000000464 65535 f 0000000465 65535 f 0000000466 65535 f 0000000467 65535 f 0000000468 65535 f 0000000469 65535 f 0000000470 65535 f 0000000471 65535 f 0000000472 65535 f 0000000473 65535 f 0000000474 65535 f 0000000475 65535 f 0000000476 65535 f 0000000477 65535 f 0000000478 65535 f 0000000479 65535 f 0000000480 65535 f 0000000481 65535 f 0000000482 65535 f 0000000483 65535 f 0000000484 65535 f 0000000485 65535 f 0000000486 65535 f 0000000487 65535 f 0000000488 65535 f 0000000489 65535 f 0000000490 65535 f 0000000491 65535 f 0000000492 65535 f 0000000493 65535 f 0000000494 65535 f 0000000495 65535 f 0000000496 65535 f 0000000497 65535 f 0000000498 65535 f 0000000499 65535 f 0000000500 65535 f 0000000501 65535 f 0000000502 65535 f 0000000503 65535 f 0000000504 65535 f 0000000505 65535 f 0000000506 65535 f 0000000507 65535 f 0000000508 65535 f 0000000509 65535 f 0000000510 65535 f 0000000511 65535 f 0000000512 65535 f 0000000513 65535 f 0000000514 65535 f 0000000515 65535 f 0000000516 65535 f 0000000517 65535 f 0000000518 65535 f 0000000519 65535 f 0000000520 65535 f 0000000521 65535 f 0000000522 65535 f 0000000523 65535 f 0000000524 65535 f 0000000525 65535 f 0000000526 65535 f 0000000527 65535 f 0000000528 65535 f 0000000529 65535 f 0000000530 65535 f 0000000531 65535 f 0000000532 65535 f 0000000533 65535 f 0000000534 65535 f 0000000535 65535 f 0000000536 65535 f 0000000537 65535 f 0000000538 65535 f 0000000539 65535 f 0000000540 65535 f 0000000541 65535 f 0000000542 65535 f 0000000543 65535 f 0000000544 65535 f 0000000545 65535 f 0000000546 65535 f 0000000547 65535 f 0000000548 65535 f 0000000549 65535 f 0000000550 65535 f 0000000551 65535 f 0000000552 65535 f 0000000553 65535 f 0000000554 65535 f 0000000555 65535 f 0000000556 65535 f 0000000557 65535 f 0000000558 65535 f 0000000559 65535 f 0000000560 65535 f 0000000561 65535 f 0000000562 65535 f 0000000563 65535 f 0000000564 65535 f 0000000565 65535 f 0000000566 65535 f 0000000567 65535 f 0000000568 65535 f 0000000569 65535 f 0000000570 65535 f 0000000571 65535 f 0000000572 65535 f 0000000573 65535 f 0000000574 65535 f 0000000575 65535 f 0000000576 65535 f 0000000577 65535 f 0000000578 65535 f 0000000579 65535 f 0000000580 65535 f 0000000581 65535 f 0000000582 65535 f 0000000583 65535 f 0000000584 65535 f 0000000585 65535 f 0000000586 65535 f 0000000587 65535 f 0000000588 65535 f 0000000589 65535 f 0000000590 65535 f 0000000591 65535 f 0000000592 65535 f 0000000593 65535 f 0000000594 65535 f 0000000595 65535 f 0000000596 65535 f 0000000597 65535 f 0000000598 65535 f 0000000599 65535 f 0000000600 65535 f 0000000601 65535 f 0000000602 65535 f 0000000603 65535 f 0000000604 65535 f 0000000605 65535 f 0000000606 65535 f 0000000607 65535 f 0000000608 65535 f 0000000609 65535 f 0000000610 65535 f 0000000611 65535 f 0000000612 65535 f 0000000613 65535 f 0000000614 65535 f 0000000615 65535 f 0000000616 65535 f 0000000617 65535 f 0000000618 65535 f 0000000619 65535 f 0000000620 65535 f 0000000621 65535 f 0000000622 65535 f 0000000623 65535 f 0000000624 65535 f 0000000625 65535 f 0000000626 65535 f 0000000627 65535 f 0000000628 65535 f 0000000629 65535 f 0000000630 65535 f 0000000631 65535 f 0000000632 65535 f 0000000633 65535 f 0000000634 65535 f 0000000635 65535 f 0000000636 65535 f 0000000637 65535 f 0000000638 65535 f 0000000639 65535 f 0000000640 65535 f 0000000641 65535 f 0000000642 65535 f 0000000643 65535 f 0000000644 65535 f 0000000645 65535 f 0000000646 65535 f 0000000647 65535 f 0000000648 65535 f 0000000649 65535 f 0000000650 65535 f 0000000651 65535 f 0000000652 65535 f 0000000653 65535 f 0000000654 65535 f 0000000655 65535 f 0000000656 65535 f 0000000657 65535 f 0000000658 65535 f 0000000659 65535 f 0000000660 65535 f 0000000661 65535 f 0000000662 65535 f 0000000663 65535 f 0000000664 65535 f 0000000665 65535 f 0000000666 65535 f 0000000667 65535 f 0000000668 65535 f 0000000669 65535 f 0000000670 65535 f 0000000671 65535 f 0000000672 65535 f 0000000673 65535 f 0000000674 65535 f 0000000675 65535 f 0000000676 65535 f 0000000677 65535 f 0000000678 65535 f 0000000679 65535 f 0000000680 65535 f 0000000681 65535 f 0000000682 65535 f 0000000683 65535 f 0000000684 65535 f 0000000685 65535 f 0000000686 65535 f 0000000687 65535 f 0000000688 65535 f 0000000689 65535 f 0000000690 65535 f 0000000691 65535 f 0000000692 65535 f 0000000693 65535 f 0000000694 65535 f 0000000695 65535 f 0000000696 65535 f 0000000697 65535 f 0000000698 65535 f 0000000699 65535 f 0000000700 65535 f 0000000701 65535 f 0000000702 65535 f 0000000703 65535 f 0000000704 65535 f 0000000705 65535 f 0000000706 65535 f 0000000707 65535 f 0000000708 65535 f 0000000709 65535 f 0000000710 65535 f 0000000711 65535 f 0000000712 65535 f 0000000713 65535 f 0000000714 65535 f 0000000715 65535 f 0000000716 65535 f 0000000717 65535 f 0000000718 65535 f 0000000719 65535 f 0000000720 65535 f 0000000721 65535 f 0000000722 65535 f 0000000723 65535 f 0000000724 65535 f 0000000725 65535 f 0000000726 65535 f 0000000727 65535 f 0000000728 65535 f 0000000729 65535 f 0000000730 65535 f 0000000731 65535 f 0000000732 65535 f 0000000733 65535 f 0000000734 65535 f 0000000735 65535 f 0000000736 65535 f 0000000737 65535 f 0000000738 65535 f 0000000739 65535 f 0000000740 65535 f 0000000741 65535 f 0000000742 65535 f 0000000743 65535 f 0000000744 65535 f 0000000745 65535 f 0000000746 65535 f 0000000747 65535 f 0000000748 65535 f 0000000749 65535 f 0000000750 65535 f 0000000751 65535 f 0000000752 65535 f 0000000753 65535 f 0000000754 65535 f 0000000755 65535 f 0000000756 65535 f 0000000757 65535 f 0000000758 65535 f 0000000759 65535 f 0000000760 65535 f 0000000761 65535 f 0000000762 65535 f 0000000763 65535 f 0000000764 65535 f 0000000765 65535 f 0000000766 65535 f 0000000767 65535 f 0000000768 65535 f 0000000769 65535 f 0000000770 65535 f 0000000771 65535 f 0000000772 65535 f 0000000773 65535 f 0000000774 65535 f 0000000775 65535 f 0000000776 65535 f 0000000777 65535 f 0000000778 65535 f 0000000779 65535 f 0000000780 65535 f 0000000781 65535 f 0000000782 65535 f 0000000783 65535 f 0000000784 65535 f 0000000785 65535 f 0000000786 65535 f 0000000787 65535 f 0000000788 65535 f 0000000789 65535 f 0000000790 65535 f 0000000791 65535 f 0000000792 65535 f 0000000793 65535 f 0000000794 65535 f 0000000795 65535 f 0000000796 65535 f 0000000797 65535 f 0000000798 65535 f 0000000799 65535 f 0000000800 65535 f 0000000801 65535 f 0000000802 65535 f 0000000803 65535 f 0000000804 65535 f 0000000805 65535 f 0000000806 65535 f 0000000807 65535 f 0000000808 65535 f 0000000809 65535 f 0000000810 65535 f 0000000811 65535 f 0000000812 65535 f 0000000813 65535 f 0000000814 65535 f 0000000815 65535 f 0000000816 65535 f 0000000817 65535 f 0000000818 65535 f 0000000819 65535 f 0000000820 65535 f 0000000821 65535 f 0000000822 65535 f 0000000823 65535 f 0000000824 65535 f 0000000825 65535 f 0000000826 65535 f 0000000827 65535 f 0000000828 65535 f 0000000829 65535 f 0000000830 65535 f 0000000831 65535 f 0000000832 65535 f 0000000833 65535 f 0000000834 65535 f 0000000835 65535 f 0000000836 65535 f 0000000837 65535 f 0000000838 65535 f 0000000839 65535 f 0000000840 65535 f 0000000841 65535 f 0000000842 65535 f 0000000843 65535 f 0000000844 65535 f 0000000845 65535 f 0000000846 65535 f 0000000847 65535 f 0000000848 65535 f 0000000849 65535 f 0000000850 65535 f 0000000851 65535 f 0000000852 65535 f 0000000853 65535 f 0000000854 65535 f 0000000855 65535 f 0000000856 65535 f 0000000857 65535 f 0000000858 65535 f 0000000859 65535 f 0000000860 65535 f 0000000861 65535 f 0000000862 65535 f 0000000863 65535 f 0000000864 65535 f 0000000865 65535 f 0000000866 65535 f 0000000867 65535 f 0000000868 65535 f 0000000869 65535 f 0000000870 65535 f 0000000871 65535 f 0000000872 65535 f 0000000873 65535 f 0000000874 65535 f 0000000875 65535 f 0000000876 65535 f 0000000877 65535 f 0000000878 65535 f 0000000879 65535 f 0000000880 65535 f 0000000881 65535 f 0000000882 65535 f 0000000883 65535 f 0000000884 65535 f 0000000885 65535 f 0000000886 65535 f 0000000887 65535 f 0000000888 65535 f 0000000889 65535 f 0000000890 65535 f 0000000891 65535 f 0000000892 65535 f 0000000893 65535 f 0000000894 65535 f 0000000895 65535 f 0000000896 65535 f 0000000897 65535 f 0000000898 65535 f 0000000899 65535 f 0000000900 65535 f 0000000901 65535 f 0000000902 65535 f 0000000903 65535 f 0000000904 65535 f 0000000905 65535 f 0000000906 65535 f 0000000907 65535 f 0000000908 65535 f 0000000909 65535 f 0000000910 65535 f 0000000911 65535 f 0000000912 65535 f 0000000913 65535 f 0000000914 65535 f 0000000915 65535 f 0000000916 65535 f 0000000917 65535 f 0000000918 65535 f 0000000919 65535 f 0000000920 65535 f 0000000921 65535 f 0000000922 65535 f 0000000923 65535 f 0000000924 65535 f 0000000925 65535 f 0000000926 65535 f 0000000927 65535 f 0000000928 65535 f 0000000929 65535 f 0000000930 65535 f 0000000931 65535 f 0000000932 65535 f 0000000933 65535 f 0000000934 65535 f 0000000935 65535 f 0000000936 65535 f 0000000937 65535 f 0000000938 65535 f 0000000939 65535 f 0000000940 65535 f 0000000941 65535 f 0000000942 65535 f 0000000943 65535 f 0000000944 65535 f 0000000945 65535 f 0000000946 65535 f 0000000947 65535 f 0000000948 65535 f 0000000949 65535 f 0000000950 65535 f 0000000951 65535 f 0000000952 65535 f 0000000953 65535 f 0000000954 65535 f 0000000955 65535 f 0000000956 65535 f 0000000957 65535 f 0000000958 65535 f 0000000959 65535 f 0000000960 65535 f 0000000961 65535 f 0000000962 65535 f 0000000963 65535 f 0000000964 65535 f 0000000965 65535 f 0000000966 65535 f 0000000967 65535 f 0000000968 65535 f 0000000969 65535 f 0000000970 65535 f 0000000971 65535 f 0000000972 65535 f 0000000973 65535 f 0000000974 65535 f 0000000975 65535 f 0000000976 65535 f 0000000977 65535 f 0000000978 65535 f 0000000979 65535 f 0000000980 65535 f 0000000981 65535 f 0000000982 65535 f 0000000983 65535 f 0000000984 65535 f 0000000985 65535 f 0000000986 65535 f 0000000987 65535 f 0000000988 65535 f 0000000989 65535 f 0000000990 65535 f 0000000991 65535 f 0000000992 65535 f 0000000993 65535 f 0000000994 65535 f 0000000995 65535 f 0000000996 65535 f 0000000997 65535 f 0000000998 65535 f 0000000999 65535 f 0000001000 65535 f 0000001001 65535 f 0000001002 65535 f 0000001003 65535 f 0000001004 65535 f 0000001005 65535 f 0000001006 65535 f 0000001007 65535 f 0000001008 65535 f 0000001009 65535 f 0000001010 65535 f 0000001011 65535 f 0000001012 65535 f 0000001013 65535 f 0000001014 65535 f 0000001015 65535 f 0000001016 65535 f 0000001017 65535 f 0000001018 65535 f 0000001019 65535 f 0000001020 65535 f 0000001021 65535 f 0000001022 65535 f 0000001023 65535 f 0000001024 65535 f 0000001025 65535 f 0000001026 65535 f 0000001027 65535 f 0000001028 65535 f 0000001029 65535 f 0000001030 65535 f 0000001031 65535 f 0000001032 65535 f 0000001033 65535 f 0000001034 65535 f 0000001035 65535 f 0000001036 65535 f 0000001037 65535 f 0000001038 65535 f 0000001039 65535 f 0000001040 65535 f 0000001041 65535 f 0000001042 65535 f 0000001043 65535 f 0000001044 65535 f 0000001045 65535 f 0000001046 65535 f 0000001047 65535 f 0000001048 65535 f 0000001049 65535 f 0000001050 65535 f 0000001051 65535 f 0000001052 65535 f 0000001053 65535 f 0000001054 65535 f 0000001055 65535 f 0000001056 65535 f 0000001057 65535 f 0000001058 65535 f 0000001059 65535 f 0000001060 65535 f 0000001061 65535 f 0000001062 65535 f 0000001063 65535 f 0000001064 65535 f 0000001065 65535 f 0000001066 65535 f 0000001067 65535 f 0000001068 65535 f 0000001069 65535 f 0000001070 65535 f 0000001071 65535 f 0000001072 65535 f 0000001073 65535 f 0000001074 65535 f 0000001075 65535 f 0000001076 65535 f 0000001077 65535 f 0000001078 65535 f 0000001079 65535 f 0000001080 65535 f 0000001081 65535 f 0000001082 65535 f 0000001083 65535 f 0000001084 65535 f 0000001085 65535 f 0000001086 65535 f 0000001087 65535 f 0000001088 65535 f 0000001089 65535 f 0000001090 65535 f 0000001091 65535 f 0000001092 65535 f 0000001093 65535 f 0000001094 65535 f 0000001095 65535 f 0000001096 65535 f 0000001097 65535 f 0000001098 65535 f 0000001099 65535 f 0000001100 65535 f 0000001101 65535 f 0000001102 65535 f 0000001103 65535 f 0000001104 65535 f 0000001105 65535 f 0000001106 65535 f 0000001107 65535 f 0000001108 65535 f 0000001109 65535 f 0000001110 65535 f 0000001111 65535 f 0000001112 65535 f 0000001113 65535 f 0000001114 65535 f 0000001115 65535 f 0000001116 65535 f 0000001117 65535 f 0000001118 65535 f 0000001119 65535 f 0000001120 65535 f 0000001121 65535 f 0000001122 65535 f 0000001123 65535 f 0000001124 65535 f 0000001125 65535 f 0000001126 65535 f 0000001127 65535 f 0000001128 65535 f 0000001129 65535 f 0000001130 65535 f 0000001131 65535 f 0000001132 65535 f 0000001133 65535 f 0000001134 65535 f 0000001135 65535 f 0000001136 65535 f 0000001137 65535 f 0000001138 65535 f 0000001139 65535 f 0000001140 65535 f 0000001141 65535 f 0000001142 65535 f 0000001143 65535 f 0000001144 65535 f 0000001145 65535 f 0000001146 65535 f 0000001147 65535 f 0000001148 65535 f 0000001149 65535 f 0000001150 65535 f 0000001151 65535 f 0000001152 65535 f 0000001153 65535 f 0000001154 65535 f 0000001155 65535 f 0000001156 65535 f 0000001157 65535 f 0000001158 65535 f 0000001159 65535 f 0000001160 65535 f 0000001161 65535 f 0000001162 65535 f 0000001163 65535 f 0000001164 65535 f 0000001165 65535 f 0000001166 65535 f 0000001167 65535 f 0000001168 65535 f 0000001169 65535 f 0000001170 65535 f 0000001171 65535 f 0000001172 65535 f 0000001173 65535 f 0000001174 65535 f 0000001175 65535 f 0000001176 65535 f 0000001177 65535 f 0000001178 65535 f 0000001179 65535 f 0000001180 65535 f 0000001181 65535 f 0000001182 65535 f 0000001183 65535 f 0000001184 65535 f 0000001185 65535 f 0000001186 65535 f 0000001187 65535 f 0000001188 65535 f 0000001189 65535 f 0000001190 65535 f 0000001191 65535 f 0000001192 65535 f 0000001193 65535 f 0000001194 65535 f 0000001195 65535 f 0000001196 65535 f 0000001197 65535 f 0000001198 65535 f 0000001199 65535 f 0000001200 65535 f 0000001201 65535 f 0000001202 65535 f 0000001203 65535 f 0000001204 65535 f 0000001205 65535 f 0000001206 65535 f 0000001207 65535 f 0000001208 65535 f 0000001209 65535 f 0000001210 65535 f 0000001211 65535 f 0000001212 65535 f 0000001213 65535 f 0000001214 65535 f 0000001215 65535 f 0000001216 65535 f 0000001217 65535 f 0000001218 65535 f 0000001219 65535 f 0000001220 65535 f 0000001221 65535 f 0000001222 65535 f 0000001223 65535 f 0000001224 65535 f 0000001225 65535 f 0000001226 65535 f 0000001227 65535 f 0000001228 65535 f 0000001229 65535 f 0000001230 65535 f 0000001231 65535 f 0000001232 65535 f 0000001233 65535 f 0000001234 65535 f 0000001235 65535 f 0000001236 65535 f 0000001237 65535 f 0000001238 65535 f 0000001239 65535 f 0000001240 65535 f 0000001241 65535 f 0000001242 65535 f 0000001243 65535 f 0000001244 65535 f 0000001245 65535 f 0000001246 65535 f 0000001247 65535 f 0000001248 65535 f 0000001249 65535 f 0000001250 65535 f 0000001251 65535 f 0000001252 65535 f 0000001253 65535 f 0000001254 65535 f 0000001255 65535 f 0000001256 65535 f 0000001257 65535 f 0000001258 65535 f 0000001259 65535 f 0000001260 65535 f 0000001261 65535 f 0000001262 65535 f 0000001263 65535 f 0000001264 65535 f 0000001265 65535 f 0000001266 65535 f 0000001267 65535 f 0000001268 65535 f 0000001269 65535 f 0000001270 65535 f 0000001271 65535 f 0000001272 65535 f 0000001273 65535 f 0000001274 65535 f 0000001275 65535 f 0000001276 65535 f 0000001277 65535 f 0000001278 65535 f 0000001279 65535 f 0000001280 65535 f 0000001281 65535 f 0000001282 65535 f 0000001283 65535 f 0000001284 65535 f 0000001285 65535 f 0000001286 65535 f 0000001287 65535 f 0000001288 65535 f 0000001289 65535 f 0000001290 65535 f 0000001291 65535 f 0000001292 65535 f 0000001293 65535 f 0000001294 65535 f 0000001295 65535 f 0000001296 65535 f 0000001297 65535 f 0000001298 65535 f 0000001299 65535 f 0000001300 65535 f 0000001301 65535 f 0000001302 65535 f 0000001303 65535 f 0000001304 65535 f 0000001305 65535 f 0000001306 65535 f 0000001307 65535 f 0000001308 65535 f 0000001309 65535 f 0000001310 65535 f 0000001311 65535 f 0000001312 65535 f 0000001313 65535 f 0000001314 65535 f 0000001315 65535 f 0000001316 65535 f 0000001317 65535 f 0000001318 65535 f 0000001319 65535 f 0000001320 65535 f 0000001321 65535 f 0000001322 65535 f 0000001323 65535 f 0000001324 65535 f 0000001325 65535 f 0000001326 65535 f 0000001327 65535 f 0000001328 65535 f 0000001329 65535 f 0000001330 65535 f 0000001331 65535 f 0000001332 65535 f 0000001333 65535 f 0000001334 65535 f 0000001335 65535 f 0000001336 65535 f 0000001337 65535 f 0000001338 65535 f 0000001339 65535 f 0000001340 65535 f 0000001341 65535 f 0000001342 65535 f 0000001343 65535 f 0000001344 65535 f 0000001345 65535 f 0000001346 65535 f 0000001347 65535 f 0000001348 65535 f 0000001349 65535 f 0000001350 65535 f 0000001351 65535 f 0000001352 65535 f 0000001353 65535 f 0000001354 65535 f 0000001355 65535 f 0000001356 65535 f 0000001357 65535 f 0000001358 65535 f 0000001359 65535 f 0000001360 65535 f 0000001361 65535 f 0000001362 65535 f 0000001363 65535 f 0000001364 65535 f 0000001365 65535 f 0000001366 65535 f 0000001367 65535 f 0000001368 65535 f 0000001369 65535 f 0000001370 65535 f 0000001371 65535 f 0000001372 65535 f 0000001373 65535 f 0000001374 65535 f 0000001375 65535 f 0000001376 65535 f 0000001377 65535 f 0000001378 65535 f 0000001379 65535 f 0000001380 65535 f 0000001381 65535 f 0000001382 65535 f 0000001383 65535 f 0000001384 65535 f 0000001385 65535 f 0000001386 65535 f 0000001387 65535 f 0000001388 65535 f 0000001389 65535 f 0000001390 65535 f 0000001391 65535 f 0000001392 65535 f 0000001393 65535 f 0000001394 65535 f 0000001395 65535 f 0000001396 65535 f 0000001397 65535 f 0000001398 65535 f 0000001399 65535 f 0000001400 65535 f 0000001401 65535 f 0000001402 65535 f 0000001403 65535 f 0000001404 65535 f 0000001405 65535 f 0000001406 65535 f 0000001407 65535 f 0000001408 65535 f 0000001409 65535 f 0000001410 65535 f 0000001411 65535 f 0000001412 65535 f 0000001413 65535 f 0000001414 65535 f 0000001415 65535 f 0000001416 65535 f 0000001417 65535 f 0000001418 65535 f 0000001419 65535 f 0000001420 65535 f 0000001421 65535 f 0000001422 65535 f 0000001423 65535 f 0000001424 65535 f 0000001425 65535 f 0000001426 65535 f 0000001427 65535 f 0000001428 65535 f 0000001429 65535 f 0000001430 65535 f 0000001431 65535 f 0000001432 65535 f 0000001433 65535 f 0000001434 65535 f 0000001435 65535 f 0000001436 65535 f 0000001437 65535 f 0000001438 65535 f 0000001439 65535 f 0000001440 65535 f 0000001441 65535 f 0000001442 65535 f 0000001443 65535 f 0000001444 65535 f 0000001445 65535 f 0000001446 65535 f 0000001447 65535 f 0000001448 65535 f 0000001449 65535 f 0000001450 65535 f 0000001451 65535 f 0000001452 65535 f 0000001453 65535 f 0000001454 65535 f 0000001455 65535 f 0000001456 65535 f 0000001457 65535 f 0000001458 65535 f 0000001459 65535 f 0000001460 65535 f 0000001461 65535 f 0000001462 65535 f 0000001463 65535 f 0000001464 65535 f 0000001465 65535 f 0000001466 65535 f 0000001467 65535 f 0000001468 65535 f 0000001469 65535 f 0000001470 65535 f 0000001471 65535 f 0000001472 65535 f 0000001473 65535 f 0000001474 65535 f 0000001475 65535 f 0000001476 65535 f 0000001477 65535 f 0000001478 65535 f 0000001479 65535 f 0000001480 65535 f 0000001481 65535 f 0000001482 65535 f 0000001483 65535 f 0000001484 65535 f 0000001485 65535 f 0000001486 65535 f 0000001487 65535 f 0000001488 65535 f 0000001489 65535 f 0000001490 65535 f 0000001491 65535 f 0000001492 65535 f 0000001493 65535 f 0000001494 65535 f 0000001495 65535 f 0000001496 65535 f 0000001497 65535 f 0000001498 65535 f 0000001499 65535 f 0000001500 65535 f 0000001501 65535 f 0000001502 65535 f 0000001503 65535 f 0000001504 65535 f 0000001505 65535 f 0000001506 65535 f 0000001507 65535 f 0000001508 65535 f 0000001509 65535 f 0000001510 65535 f 0000001511 65535 f 0000001512 65535 f 0000001513 65535 f 0000001514 65535 f 0000001515 65535 f 0000001516 65535 f 0000001517 65535 f 0000001518 65535 f 0000001519 65535 f 0000001520 65535 f 0000001521 65535 f 0000001522 65535 f 0000001523 65535 f 0000001524 65535 f 0000001525 65535 f 0000001526 65535 f 0000001527 65535 f 0000001528 65535 f 0000001529 65535 f 0000001530 65535 f 0000001531 65535 f 0000001532 65535 f 0000001533 65535 f 0000001534 65535 f 0000001535 65535 f 0000001536 65535 f 0000001537 65535 f 0000001538 65535 f 0000001539 65535 f 0000001540 65535 f 0000001541 65535 f 0000001542 65535 f 0000001543 65535 f 0000001544 65535 f 0000001545 65535 f 0000001546 65535 f 0000001547 65535 f 0000001548 65535 f 0000001549 65535 f 0000001550 65535 f 0000001551 65535 f 0000001552 65535 f 0000001553 65535 f 0000001554 65535 f 0000001555 65535 f 0000001556 65535 f 0000001557 65535 f 0000001558 65535 f 0000001559 65535 f 0000001560 65535 f 0000001561 65535 f 0000001562 65535 f 0000001563 65535 f 0000001564 65535 f 0000001565 65535 f 0000001566 65535 f 0000001567 65535 f 0000001568 65535 f 0000001569 65535 f 0000001570 65535 f 0000001571 65535 f 0000001572 65535 f 0000001573 65535 f 0000001574 65535 f 0000001575 65535 f 0000001576 65535 f 0000001577 65535 f 0000001578 65535 f 0000001579 65535 f 0000001580 65535 f 0000001581 65535 f 0000001582 65535 f 0000001583 65535 f 0000001584 65535 f 0000001585 65535 f 0000001586 65535 f 0000001587 65535 f 0000001588 65535 f 0000001589 65535 f 0000001590 65535 f 0000001591 65535 f 0000001592 65535 f 0000001593 65535 f 0000001594 65535 f 0000001595 65535 f 0000001596 65535 f 0000001597 65535 f 0000001598 65535 f 0000001599 65535 f 0000001600 65535 f 0000001601 65535 f 0000001602 65535 f 0000001603 65535 f 0000001604 65535 f 0000001605 65535 f 0000001606 65535 f 0000001607 65535 f 0000001608 65535 f 0000001609 65535 f 0000001610 65535 f 0000001611 65535 f 0000001612 65535 f 0000001613 65535 f 0000001614 65535 f 0000001615 65535 f 0000001616 65535 f 0000001617 65535 f 0000001618 65535 f 0000001619 65535 f 0000001620 65535 f 0000001621 65535 f 0000001622 65535 f 0000001623 65535 f 0000001624 65535 f 0000001625 65535 f 0000001626 65535 f 0000001627 65535 f 0000001628 65535 f 0000001629 65535 f 0000001630 65535 f 0000001631 65535 f 0000001632 65535 f 0000001633 65535 f 0000001634 65535 f 0000001635 65535 f 0000001636 65535 f 0000001637 65535 f 0000001638 65535 f 0000001639 65535 f 0000001640 65535 f 0000001641 65535 f 0000001642 65535 f 0000001643 65535 f 0000001644 65535 f 0000001645 65535 f 0000001646 65535 f 0000001647 65535 f 0000001648 65535 f 0000001649 65535 f 0000001650 65535 f 0000001651 65535 f 0000001652 65535 f 0000001653 65535 f 0000001654 65535 f 0000001655 65535 f 0000001656 65535 f 0000001657 65535 f 0000001658 65535 f 0000001659 65535 f 0000001660 65535 f 0000001661 65535 f 0000001662 65535 f 0000001663 65535 f 0000001664 65535 f 0000001665 65535 f 0000001666 65535 f 0000001667 65535 f 0000001668 65535 f 0000001669 65535 f 0000001670 65535 f 0000001671 65535 f 0000001672 65535 f 0000001673 65535 f 0000001674 65535 f 0000001675 65535 f 0000001676 65535 f 0000001677 65535 f 0000001678 65535 f 0000001679 65535 f 0000001680 65535 f 0000001681 65535 f 0000001682 65535 f 0000001683 65535 f 0000001684 65535 f 0000001685 65535 f 0000001686 65535 f 0000001687 65535 f 0000001688 65535 f 0000001689 65535 f 0000001690 65535 f 0000001691 65535 f 0000001692 65535 f 0000001693 65535 f 0000001694 65535 f 0000001695 65535 f 0000001696 65535 f 0000001697 65535 f 0000001698 65535 f 0000001699 65535 f 0000001700 65535 f 0000001701 65535 f 0000001702 65535 f 0000001703 65535 f 0000001704 65535 f 0000001705 65535 f 0000001706 65535 f 0000001707 65535 f 0000001708 65535 f 0000001709 65535 f 0000001710 65535 f 0000001711 65535 f 0000001712 65535 f 0000001713 65535 f 0000001714 65535 f 0000001715 65535 f 0000001716 65535 f 0000001717 65535 f 0000001718 65535 f 0000001719 65535 f 0000001720 65535 f 0000001721 65535 f 0000001722 65535 f 0000001723 65535 f 0000001724 65535 f 0000001725 65535 f 0000001726 65535 f 0000001727 65535 f 0000001728 65535 f 0000001729 65535 f 0000001730 65535 f 0000001731 65535 f 0000001732 65535 f 0000001733 65535 f 0000001734 65535 f 0000001735 65535 f 0000001736 65535 f 0000001737 65535 f 0000001738 65535 f 0000001739 65535 f 0000001740 65535 f 0000001741 65535 f 0000001742 65535 f 0000001743 65535 f 0000001744 65535 f 0000001745 65535 f 0000001746 65535 f 0000001747 65535 f 0000001748 65535 f 0000001749 65535 f 0000001750 65535 f 0000001751 65535 f 0000001752 65535 f 0000001753 65535 f 0000001754 65535 f 0000001755 65535 f 0000001756 65535 f 0000001757 65535 f 0000001758 65535 f 0000001759 65535 f 0000001760 65535 f 0000001761 65535 f 0000001762 65535 f 0000001763 65535 f 0000001764 65535 f 0000001765 65535 f 0000001766 65535 f 0000001767 65535 f 0000001768 65535 f 0000001769 65535 f 0000001770 65535 f 0000001771 65535 f 0000001772 65535 f 0000001773 65535 f 0000001774 65535 f 0000001775 65535 f 0000001776 65535 f 0000001777 65535 f 0000001778 65535 f 0000001779 65535 f 0000001780 65535 f 0000001781 65535 f 0000001782 65535 f 0000001783 65535 f 0000001784 65535 f 0000001785 65535 f 0000001786 65535 f 0000001787 65535 f 0000001788 65535 f 0000001789 65535 f 0000001790 65535 f 0000001791 65535 f 0000001792 65535 f 0000001793 65535 f 0000001794 65535 f 0000001795 65535 f 0000001796 65535 f 0000001797 65535 f 0000001798 65535 f 0000001799 65535 f 0000001800 65535 f 0000001801 65535 f 0000001802 65535 f 0000001803 65535 f 0000001804 65535 f 0000001805 65535 f 0000001806 65535 f 0000001807 65535 f 0000001808 65535 f 0000001809 65535 f 0000001810 65535 f 0000001811 65535 f 0000001812 65535 f 0000001813 65535 f 0000001814 65535 f 0000001815 65535 f 0000001816 65535 f 0000001817 65535 f 0000001818 65535 f 0000001819 65535 f 0000001820 65535 f 0000001821 65535 f 0000001822 65535 f 0000001823 65535 f 0000001824 65535 f 0000001825 65535 f 0000001826 65535 f 0000001827 65535 f 0000001828 65535 f 0000001829 65535 f 0000001830 65535 f 0000001831 65535 f 0000001832 65535 f 0000001833 65535 f 0000001834 65535 f 0000001835 65535 f 0000001836 65535 f 0000001837 65535 f 0000001838 65535 f 0000001839 65535 f 0000001840 65535 f 0000001841 65535 f 0000001842 65535 f 0000001843 65535 f 0000001844 65535 f 0000001845 65535 f 0000001846 65535 f 0000001847 65535 f 0000001848 65535 f 0000001849 65535 f 0000001850 65535 f 0000001851 65535 f 0000001852 65535 f 0000001853 65535 f 0000001854 65535 f 0000001855 65535 f 0000001856 65535 f 0000001857 65535 f 0000001858 65535 f 0000001859 65535 f 0000001860 65535 f 0000001861 65535 f 0000001862 65535 f 0000001863 65535 f 0000001864 65535 f 0000001865 65535 f 0000001866 65535 f 0000001867 65535 f 0000001868 65535 f 0000001869 65535 f 0000001870 65535 f 0000001871 65535 f 0000001872 65535 f 0000001873 65535 f 0000001874 65535 f 0000001875 65535 f 0000001876 65535 f 0000001877 65535 f 0000001878 65535 f 0000001879 65535 f 0000001880 65535 f 0000001881 65535 f 0000001882 65535 f 0000001883 65535 f 0000001884 65535 f 0000001885 65535 f 0000001886 65535 f 0000001887 65535 f 0000001888 65535 f 0000001889 65535 f 0000001890 65535 f 0000001891 65535 f 0000001892 65535 f 0000001893 65535 f 0000001894 65535 f 0000001895 65535 f 0000001896 65535 f 0000001897 65535 f 0000001898 65535 f 0000001899 65535 f 0000001900 65535 f 0000001901 65535 f 0000001902 65535 f 0000001903 65535 f 0000001904 65535 f 0000001905 65535 f 0000001906 65535 f 0000001907 65535 f 0000001908 65535 f 0000001909 65535 f 0000001910 65535 f 0000001911 65535 f 0000001912 65535 f 0000001913 65535 f 0000001914 65535 f 0000001915 65535 f 0000001916 65535 f 0000001917 65535 f 0000001918 65535 f 0000001919 65535 f 0000001920 65535 f 0000001921 65535 f 0000001922 65535 f 0000001923 65535 f 0000001924 65535 f 0000001925 65535 f 0000001926 65535 f 0000001927 65535 f 0000001928 65535 f 0000001929 65535 f 0000001930 65535 f 0000001931 65535 f 0000001932 65535 f 0000001933 65535 f 0000001934 65535 f 0000001935 65535 f 0000001936 65535 f 0000001937 65535 f 0000001938 65535 f 0000001939 65535 f 0000001940 65535 f 0000001941 65535 f 0000001942 65535 f 0000001943 65535 f 0000001944 65535 f 0000001945 65535 f 0000001946 65535 f 0000001947 65535 f 0000001948 65535 f 0000001949 65535 f 0000001950 65535 f 0000001951 65535 f 0000001952 65535 f 0000001953 65535 f 0000001954 65535 f 0000001955 65535 f 0000001956 65535 f 0000001957 65535 f 0000001958 65535 f 0000001959 65535 f 0000001960 65535 f 0000001961 65535 f 0000001962 65535 f 0000001963 65535 f 0000001964 65535 f 0000001965 65535 f 0000001966 65535 f 0000001967 65535 f 0000001968 65535 f 0000001969 65535 f 0000001970 65535 f 0000001971 65535 f 0000001972 65535 f 0000001973 65535 f 0000001974 65535 f 0000001975 65535 f 0000001976 65535 f 0000001977 65535 f 0000001978 65535 f 0000001979 65535 f 0000001980 65535 f 0000001981 65535 f 0000001982 65535 f 0000001983 65535 f 0000001984 65535 f 0000001985 65535 f 0000001986 65535 f 0000001987 65535 f 0000001988 65535 f 0000001989 65535 f 0000001990 65535 f 0000001991 65535 f 0000001992 65535 f 0000001993 65535 f 0000001994 65535 f 0000001995 65535 f 0000001996 65535 f 0000001997 65535 f 0000001998 65535 f 0000001999 65535 f 0000002000 65535 f 0000002001 65535 f 0000002002 65535 f 0000002003 65535 f 0000002004 65535 f 0000002005 65535 f 0000002006 65535 f 0000002007 65535 f 0000002008 65535 f 0000002009 65535 f 0000002010 65535 f 0000002011 65535 f 0000002012 65535 f 0000002013 65535 f 0000002014 65535 f 0000002015 65535 f 0000002016 65535 f 0000002017 65535 f 0000002018 65535 f 0000002019 65535 f 0000002020 65535 f 0000002021 65535 f 0000002022 65535 f 0000002023 65535 f 0000002024 65535 f 0000002025 65535 f 0000002026 65535 f 0000002027 65535 f 0000002028 65535 f 0000002029 65535 f 0000002030 65535 f 0000002031 65535 f 0000002032 65535 f 0000002033 65535 f 0000002034 65535 f 0000002035 65535 f 0000002036 65535 f 0000002037 65535 f 0000002038 65535 f 0000002039 65535 f 0000002040 65535 f 0000002041 65535 f 0000002042 65535 f 0000002043 65535 f 0000002044 65535 f 0000002045 65535 f 0000002046 65535 f 0000002047 65535 f 0000002048 65535 f 0000002049 65535 f 0000002050 65535 f 0000002051 65535 f 0000002052 65535 f 0000002053 65535 f 0000002054 65535 f 0000002055 65535 f 0000002056 65535 f 0000002057 65535 f 0000002058 65535 f 0000002059 65535 f 0000002060 65535 f 0000002061 65535 f 0000002062 65535 f 0000002063 65535 f 0000002064 65535 f 0000002065 65535 f 0000002066 65535 f 0000002067 65535 f 0000002068 65535 f 0000002069 65535 f 0000002070 65535 f 0000002071 65535 f 0000002072 65535 f 0000002073 65535 f 0000002074 65535 f 0000002075 65535 f 0000002076 65535 f 0000002077 65535 f 0000002078 65535 f 0000002079 65535 f 0000002080 65535 f 0000002081 65535 f 0000002082 65535 f 0000002083 65535 f 0000002084 65535 f 0000002085 65535 f 0000002086 65535 f 0000002087 65535 f 0000002088 65535 f 0000002089 65535 f 0000002090 65535 f 0000002091 65535 f 0000002092 65535 f 0000002093 65535 f 0000002094 65535 f 0000002095 65535 f 0000002096 65535 f 0000002097 65535 f 0000002098 65535 f 0000002099 65535 f 0000002100 65535 f 0000002101 65535 f 0000002102 65535 f 0000002103 65535 f 0000002104 65535 f 0000002105 65535 f 0000002106 65535 f 0000002107 65535 f 0000002108 65535 f 0000002109 65535 f 0000002110 65535 f 0000002111 65535 f 0000002112 65535 f 0000002113 65535 f 0000002114 65535 f 0000002115 65535 f 0000002116 65535 f 0000002117 65535 f 0000002118 65535 f 0000002119 65535 f 0000002120 65535 f 0000002121 65535 f 0000002122 65535 f 0000002123 65535 f 0000002124 65535 f 0000002125 65535 f 0000002126 65535 f 0000002127 65535 f 0000002128 65535 f 0000002129 65535 f 0000002130 65535 f 0000002131 65535 f 0000002132 65535 f 0000002133 65535 f 0000002134 65535 f 0000002135 65535 f 0000002136 65535 f 0000002137 65535 f 0000002138 65535 f 0000002139 65535 f 0000002140 65535 f 0000002141 65535 f 0000002142 65535 f 0000002143 65535 f 0000002144 65535 f 0000002145 65535 f 0000002146 65535 f 0000002147 65535 f 0000002148 65535 f 0000002149 65535 f 0000002150 65535 f 0000002151 65535 f 0000002152 65535 f 0000002153 65535 f 0000002154 65535 f 0000002155 65535 f 0000002156 65535 f 0000002157 65535 f 0000002158 65535 f 0000002159 65535 f 0000002160 65535 f 0000002161 65535 f 0000002162 65535 f 0000002163 65535 f 0000002164 65535 f 0000002165 65535 f 0000002166 65535 f 0000002167 65535 f 0000002168 65535 f 0000002169 65535 f 0000002170 65535 f 0000002171 65535 f 0000002172 65535 f 0000002173 65535 f 0000002174 65535 f 0000002175 65535 f 0000002176 65535 f 0000002177 65535 f 0000002178 65535 f 0000002179 65535 f 0000002180 65535 f 0000002181 65535 f 0000002182 65535 f 0000002183 65535 f 0000002184 65535 f 0000002185 65535 f 0000002186 65535 f 0000002187 65535 f 0000002188 65535 f 0000002189 65535 f 0000002190 65535 f 0000002191 65535 f 0000002192 65535 f 0000002193 65535 f 0000002194 65535 f 0000002195 65535 f 0000002196 65535 f 0000002197 65535 f 0000002198 65535 f 0000002199 65535 f 0000002200 65535 f 0000002201 65535 f 0000002202 65535 f 0000002203 65535 f 0000002204 65535 f 0000002205 65535 f 0000002206 65535 f 0000002207 65535 f 0000002208 65535 f 0000002209 65535 f 0000002210 65535 f 0000002211 65535 f 0000002212 65535 f 0000002213 65535 f 0000002214 65535 f 0000002215 65535 f 0000002216 65535 f 0000002217 65535 f 0000002218 65535 f 0000002219 65535 f 0000002220 65535 f 0000002221 65535 f 0000002222 65535 f 0000002223 65535 f 0000002224 65535 f 0000002225 65535 f 0000002226 65535 f 0000002227 65535 f 0000002228 65535 f 0000002229 65535 f 0000002230 65535 f 0000002231 65535 f 0000002232 65535 f 0000002233 65535 f 0000002234 65535 f 0000002235 65535 f 0000002236 65535 f 0000002237 65535 f 0000002238 65535 f 0000002239 65535 f 0000002240 65535 f 0000002241 65535 f 0000002242 65535 f 0000002243 65535 f 0000002244 65535 f 0000002245 65535 f 0000002246 65535 f 0000002247 65535 f 0000002248 65535 f 0000002249 65535 f 0000002250 65535 f 0000002251 65535 f 0000002252 65535 f 0000002253 65535 f 0000002254 65535 f 0000002255 65535 f 0000002256 65535 f 0000002257 65535 f 0000002258 65535 f 0000002259 65535 f 0000002260 65535 f 0000002261 65535 f 0000002262 65535 f 0000002263 65535 f 0000002264 65535 f 0000002265 65535 f 0000002266 65535 f 0000002267 65535 f 0000002268 65535 f 0000002269 65535 f 0000002270 65535 f 0000002271 65535 f 0000002272 65535 f 0000002273 65535 f 0000002274 65535 f 0000002275 65535 f 0000002276 65535 f 0000002277 65535 f 0000002278 65535 f 0000002279 65535 f 0000002280 65535 f 0000002281 65535 f 0000002282 65535 f 0000002283 65535 f 0000002284 65535 f 0000002285 65535 f 0000002286 65535 f 0000002287 65535 f 0000002288 65535 f 0000002289 65535 f 0000002290 65535 f 0000002291 65535 f 0000002292 65535 f 0000002293 65535 f 0000002294 65535 f 0000002295 65535 f 0000002296 65535 f 0000002297 65535 f 0000002298 65535 f 0000002299 65535 f 0000002300 65535 f 0000002301 65535 f 0000002302 65535 f 0000002303 65535 f 0000002304 65535 f 0000002305 65535 f 0000002306 65535 f 0000002307 65535 f 0000002308 65535 f 0000002309 65535 f 0000002310 65535 f 0000002311 65535 f 0000002312 65535 f 0000002313 65535 f 0000002314 65535 f 0000002315 65535 f 0000002316 65535 f 0000002317 65535 f 0000002318 65535 f 0000002319 65535 f 0000002320 65535 f 0000002321 65535 f 0000002322 65535 f 0000002323 65535 f 0000002324 65535 f 0000002325 65535 f 0000002326 65535 f 0000002327 65535 f 0000002328 65535 f 0000002329 65535 f 0000002330 65535 f 0000002331 65535 f 0000002332 65535 f 0000002333 65535 f 0000002334 65535 f 0000002335 65535 f 0000002336 65535 f 0000002337 65535 f 0000002338 65535 f 0000002339 65535 f 0000002340 65535 f 0000002341 65535 f 0000002342 65535 f 0000002343 65535 f 0000002344 65535 f 0000002345 65535 f 0000002346 65535 f 0000002347 65535 f 0000002348 65535 f 0000002349 65535 f 0000002350 65535 f 0000002351 65535 f 0000002352 65535 f 0000002353 65535 f 0000002354 65535 f 0000002355 65535 f 0000002356 65535 f 0000002357 65535 f 0000002358 65535 f 0000002359 65535 f 0000002360 65535 f 0000002361 65535 f 0000002362 65535 f 0000002363 65535 f 0000002364 65535 f 0000002365 65535 f 0000002366 65535 f 0000002367 65535 f 0000002368 65535 f 0000002369 65535 f 0000002370 65535 f 0000002371 65535 f 0000002372 65535 f 0000002373 65535 f 0000002374 65535 f 0000002375 65535 f 0000002376 65535 f 0000002377 65535 f 0000002378 65535 f 0000002379 65535 f 0000002380 65535 f 0000002381 65535 f 0000002382 65535 f 0000002383 65535 f 0000002384 65535 f 0000002385 65535 f 0000002386 65535 f 0000002387 65535 f 0000002388 65535 f 0000002389 65535 f 0000002390 65535 f 0000002391 65535 f 0000002392 65535 f 0000002393 65535 f 0000002394 65535 f 0000002395 65535 f 0000002396 65535 f 0000002397 65535 f 0000002398 65535 f 0000002399 65535 f 0000002400 65535 f 0000002401 65535 f 0000002402 65535 f 0000002403 65535 f 0000002404 65535 f 0000002405 65535 f 0000002406 65535 f 0000002407 65535 f 0000002408 65535 f 0000002409 65535 f 0000002410 65535 f 0000002411 65535 f 0000002412 65535 f 0000002413 65535 f 0000002414 65535 f 0000002415 65535 f 0000002416 65535 f 0000002417 65535 f 0000002418 65535 f 0000002419 65535 f 0000002420 65535 f 0000002421 65535 f 0000002422 65535 f 0000002423 65535 f 0000002424 65535 f 0000002425 65535 f 0000002426 65535 f 0000002427 65535 f 0000002428 65535 f 0000002429 65535 f 0000002430 65535 f 0000002431 65535 f 0000002432 65535 f 0000002433 65535 f 0000002434 65535 f 0000002435 65535 f 0000002436 65535 f 0000002437 65535 f 0000002438 65535 f 0000002439 65535 f 0000002440 65535 f 0000002441 65535 f 0000002442 65535 f 0000002443 65535 f 0000002444 65535 f 0000002445 65535 f 0000002446 65535 f 0000002447 65535 f 0000002448 65535 f 0000002449 65535 f 0000002450 65535 f 0000002451 65535 f 0000002452 65535 f 0000002453 65535 f 0000002454 65535 f 0000002455 65535 f 0000002456 65535 f 0000002457 65535 f 0000002458 65535 f 0000002459 65535 f 0000002460 65535 f 0000002461 65535 f 0000002462 65535 f 0000002463 65535 f 0000002464 65535 f 0000002465 65535 f 0000002466 65535 f 0000002467 65535 f 0000002468 65535 f 0000002469 65535 f 0000002470 65535 f 0000002471 65535 f 0000002472 65535 f 0000002473 65535 f 0000002474 65535 f 0000002475 65535 f 0000002476 65535 f 0000002477 65535 f 0000002478 65535 f 0000002479 65535 f 0000002480 65535 f 0000002481 65535 f 0000002482 65535 f 0000002483 65535 f 0000002484 65535 f 0000002485 65535 f 0000002486 65535 f 0000002487 65535 f 0000002488 65535 f 0000002489 65535 f 0000002490 65535 f 0000002491 65535 f 0000002492 65535 f 0000002493 65535 f 0000002494 65535 f 0000002495 65535 f 0000002496 65535 f 0000002497 65535 f 0000002498 65535 f 0000002499 65535 f 0000002500 65535 f 0000002501 65535 f 0000002502 65535 f 0000002503 65535 f 0000002504 65535 f 0000002505 65535 f 0000002506 65535 f 0000002507 65535 f 0000002508 65535 f 0000002509 65535 f 0000002510 65535 f 0000002511 65535 f 0000002512 65535 f 0000002513 65535 f 0000002514 65535 f 0000002515 65535 f 0000002516 65535 f 0000002517 65535 f 0000002518 65535 f 0000002519 65535 f 0000002520 65535 f 0000002521 65535 f 0000002522 65535 f 0000002523 65535 f 0000002524 65535 f 0000002525 65535 f 0000002526 65535 f 0000002527 65535 f 0000002528 65535 f 0000002529 65535 f 0000002530 65535 f 0000002531 65535 f 0000002532 65535 f 0000002533 65535 f 0000002534 65535 f 0000002535 65535 f 0000002536 65535 f 0000002537 65535 f 0000002538 65535 f 0000002539 65535 f 0000002540 65535 f 0000002541 65535 f 0000002542 65535 f 0000002543 65535 f 0000002544 65535 f 0000002545 65535 f 0000002546 65535 f 0000002547 65535 f 0000002548 65535 f 0000002549 65535 f 0000002550 65535 f 0000002551 65535 f 0000002552 65535 f 0000002553 65535 f 0000002554 65535 f 0000002555 65535 f 0000002556 65535 f 0000002557 65535 f 0000002558 65535 f 0000002559 65535 f 0000002560 65535 f 0000002561 65535 f 0000002562 65535 f 0000002563 65535 f 0000002564 65535 f 0000002565 65535 f 0000002566 65535 f 0000002567 65535 f 0000002568 65535 f 0000002569 65535 f 0000002570 65535 f 0000002571 65535 f 0000002572 65535 f 0000002573 65535 f 0000002574 65535 f 0000002575 65535 f 0000002576 65535 f 0000002577 65535 f 0000002578 65535 f 0000002579 65535 f 0000002580 65535 f 0000002581 65535 f 0000002582 65535 f 0000002583 65535 f 0000002584 65535 f 0000002585 65535 f 0000002586 65535 f 0000002587 65535 f 0000002588 65535 f 0000002589 65535 f 0000002590 65535 f 0000002591 65535 f 0000002592 65535 f 0000002593 65535 f 0000002594 65535 f 0000002595 65535 f 0000002596 65535 f 0000002597 65535 f 0000002598 65535 f 0000002599 65535 f 0000002600 65535 f 0000002601 65535 f 0000002602 65535 f 0000002603 65535 f 0000002604 65535 f 0000002605 65535 f 0000002606 65535 f 0000002607 65535 f 0000002608 65535 f 0000002609 65535 f 0000002610 65535 f 0000002611 65535 f 0000002612 65535 f 0000002613 65535 f 0000002614 65535 f 0000002615 65535 f 0000002616 65535 f 0000002617 65535 f 0000002618 65535 f 0000002619 65535 f 0000002620 65535 f 0000002621 65535 f 0000002622 65535 f 0000002623 65535 f 0000002624 65535 f 0000002625 65535 f 0000002626 65535 f 0000002627 65535 f 0000002628 65535 f 0000002629 65535 f 0000002630 65535 f 0000002631 65535 f 0000002632 65535 f 0000002633 65535 f 0000002634 65535 f 0000002635 65535 f 0000002636 65535 f 0000002637 65535 f 0000002638 65535 f 0000002639 65535 f 0000002640 65535 f 0000002641 65535 f 0000002642 65535 f 0000002643 65535 f 0000002644 65535 f 0000002645 65535 f 0000002646 65535 f 0000002647 65535 f 0000002648 65535 f 0000002649 65535 f 0000002650 65535 f 0000002651 65535 f 0000002652 65535 f 0000002653 65535 f 0000002654 65535 f 0000002655 65535 f 0000002656 65535 f 0000002657 65535 f 0000002658 65535 f 0000002659 65535 f 0000002660 65535 f 0000002661 65535 f 0000002662 65535 f 0000002663 65535 f 0000002664 65535 f 0000002665 65535 f 0000002666 65535 f 0000002667 65535 f 0000002668 65535 f 0000002669 65535 f 0000002670 65535 f 0000002671 65535 f 0000002672 65535 f 0000002673 65535 f 0000002674 65535 f 0000002675 65535 f 0000002676 65535 f 0000002677 65535 f 0000002678 65535 f 0000002679 65535 f 0000002680 65535 f 0000002681 65535 f 0000002682 65535 f 0000002683 65535 f 0000002684 65535 f 0000002685 65535 f 0000002686 65535 f 0000002687 65535 f 0000002688 65535 f 0000002689 65535 f 0000002690 65535 f 0000002691 65535 f 0000002692 65535 f 0000002693 65535 f 0000002694 65535 f 0000002695 65535 f 0000002696 65535 f 0000002697 65535 f 0000002698 65535 f 0000002699 65535 f 0000002700 65535 f 0000002701 65535 f 0000002702 65535 f 0000002703 65535 f 0000002704 65535 f 0000002705 65535 f 0000002706 65535 f 0000002707 65535 f 0000002708 65535 f 0000002709 65535 f 0000002710 65535 f 0000002711 65535 f 0000002712 65535 f 0000002713 65535 f 0000002714 65535 f 0000002715 65535 f 0000002716 65535 f 0000002717 65535 f 0000002718 65535 f 0000002719 65535 f 0000002720 65535 f 0000002721 65535 f 0000002722 65535 f 0000002723 65535 f 0000002724 65535 f 0000002725 65535 f 0000002726 65535 f 0000002727 65535 f 0000002728 65535 f 0000002729 65535 f 0000002730 65535 f 0000002731 65535 f 0000002732 65535 f 0000002733 65535 f 0000002734 65535 f 0000002735 65535 f 0000002736 65535 f 0000002737 65535 f 0000002738 65535 f 0000002739 65535 f 0000002740 65535 f 0000002741 65535 f 0000002742 65535 f 0000002743 65535 f 0000002744 65535 f 0000002745 65535 f 0000002746 65535 f 0000002747 65535 f 0000002748 65535 f 0000002749 65535 f 0000002750 65535 f 0000002751 65535 f 0000002752 65535 f 0000002753 65535 f 0000002754 65535 f 0000002755 65535 f 0000002756 65535 f 0000002757 65535 f 0000002758 65535 f 0000002759 65535 f 0000002760 65535 f 0000002761 65535 f 0000002762 65535 f 0000002763 65535 f 0000002764 65535 f 0000002765 65535 f 0000002766 65535 f 0000002767 65535 f 0000002768 65535 f 0000002769 65535 f 0000002770 65535 f 0000002771 65535 f 0000002772 65535 f 0000002773 65535 f 0000002774 65535 f 0000002775 65535 f 0000002776 65535 f 0000002777 65535 f 0000002778 65535 f 0000002779 65535 f 0000002780 65535 f 0000002781 65535 f 0000002782 65535 f 0000002783 65535 f 0000002784 65535 f 0000002785 65535 f 0000002786 65535 f 0000002787 65535 f 0000002788 65535 f 0000002789 65535 f 0000002790 65535 f 0000002791 65535 f 0000002792 65535 f 0000002793 65535 f 0000002794 65535 f 0000002795 65535 f 0000002796 65535 f 0000002797 65535 f 0000002798 65535 f 0000002799 65535 f 0000002800 65535 f 0000002801 65535 f 0000002802 65535 f 0000002803 65535 f 0000002804 65535 f 0000002805 65535 f 0000002806 65535 f 0000002807 65535 f 0000002808 65535 f 0000002809 65535 f 0000002810 65535 f 0000002811 65535 f 0000002812 65535 f 0000002813 65535 f 0000002814 65535 f 0000002815 65535 f 0000002816 65535 f 0000002817 65535 f 0000002818 65535 f 0000002819 65535 f 0000002820 65535 f 0000002821 65535 f 0000002822 65535 f 0000002823 65535 f 0000002824 65535 f 0000002825 65535 f 0000002826 65535 f 0000002827 65535 f 0000002828 65535 f 0000002829 65535 f 0000002830 65535 f 0000002831 65535 f 0000002832 65535 f 0000002833 65535 f 0000002834 65535 f 0000002835 65535 f 0000002836 65535 f 0000002837 65535 f 0000002838 65535 f 0000002839 65535 f 0000002840 65535 f 0000002841 65535 f 0000002842 65535 f 0000002843 65535 f 0000002844 65535 f 0000002845 65535 f 0000002846 65535 f 0000002847 65535 f 0000002848 65535 f 0000002849 65535 f 0000002850 65535 f 0000002851 65535 f 0000002852 65535 f 0000002853 65535 f 0000002854 65535 f 0000002855 65535 f 0000002856 65535 f 0000002857 65535 f 0000002858 65535 f 0000002859 65535 f 0000002860 65535 f 0000002861 65535 f 0000002862 65535 f 0000002863 65535 f 0000002864 65535 f 0000002865 65535 f 0000002866 65535 f 0000002867 65535 f 0000002868 65535 f 0000002869 65535 f 0000002870 65535 f 0000002871 65535 f 0000002872 65535 f 0000002873 65535 f 0000002874 65535 f 0000002875 65535 f 0000002876 65535 f 0000002877 65535 f 0000002878 65535 f 0000002879 65535 f 0000002880 65535 f 0000002881 65535 f 0000002882 65535 f 0000002883 65535 f 0000002884 65535 f 0000002885 65535 f 0000002886 65535 f 0000002887 65535 f 0000002888 65535 f 0000002889 65535 f 0000002890 65535 f 0000002891 65535 f 0000002892 65535 f 0000002893 65535 f 0000002894 65535 f 0000002895 65535 f 0000002896 65535 f 0000002897 65535 f 0000002898 65535 f 0000002899 65535 f 0000002900 65535 f 0000002901 65535 f 0000002902 65535 f 0000002903 65535 f 0000002904 65535 f 0000002905 65535 f 0000002906 65535 f 0000002907 65535 f 0000002908 65535 f 0000002909 65535 f 0000002910 65535 f 0000002911 65535 f 0000002912 65535 f 0000002913 65535 f 0000002914 65535 f 0000002915 65535 f 0000002916 65535 f 0000002917 65535 f 0000002918 65535 f 0000002919 65535 f 0000002920 65535 f 0000002921 65535 f 0000002922 65535 f 0000002923 65535 f 0000002924 65535 f 0000002925 65535 f 0000002926 65535 f 0000002927 65535 f 0000002928 65535 f 0000002929 65535 f 0000002930 65535 f 0000002931 65535 f 0000002932 65535 f 0000002933 65535 f 0000002934 65535 f 0000002935 65535 f 0000002936 65535 f 0000002937 65535 f 0000002938 65535 f 0000002939 65535 f 0000002940 65535 f 0000002941 65535 f 0000002942 65535 f 0000002943 65535 f 0000002944 65535 f 0000002945 65535 f 0000002946 65535 f 0000002947 65535 f 0000002948 65535 f 0000002949 65535 f 0000002950 65535 f 0000002951 65535 f 0000002952 65535 f 0000002953 65535 f 0000002954 65535 f 0000002955 65535 f 0000002956 65535 f 0000002957 65535 f 0000002958 65535 f 0000002959 65535 f 0000002960 65535 f 0000002961 65535 f 0000002962 65535 f 0000002963 65535 f 0000002964 65535 f 0000002965 65535 f 0000002966 65535 f 0000002967 65535 f 0000002968 65535 f 0000002969 65535 f 0000002970 65535 f 0000002971 65535 f 0000002972 65535 f 0000002973 65535 f 0000002974 65535 f 0000002975 65535 f 0000002976 65535 f 0000002977 65535 f 0000002978 65535 f 0000002979 65535 f 0000002980 65535 f 0000002981 65535 f 0000002982 65535 f 0000002983 65535 f 0000002984 65535 f 0000002985 65535 f 0000002986 65535 f 0000002987 65535 f 0000002988 65535 f 0000002989 65535 f 0000002990 65535 f 0000002991 65535 f 0000002992 65535 f 0000002993 65535 f 0000002994 65535 f 0000002995 65535 f 0000002996 65535 f 0000002997 65535 f 0000002998 65535 f 0000002999 65535 f 0000003000 65535 f 0000003001 65535 f 0000003002 65535 f 0000003003 65535 f 0000003004 65535 f 0000003005 65535 f 0000003006 65535 f 0000003007 65535 f 0000003008 65535 f 0000003009 65535 f 0000003010 65535 f 0000003011 65535 f 0000003012 65535 f 0000003013 65535 f 0000003014 65535 f 0000003015 65535 f 0000003016 65535 f 0000003017 65535 f 0000003018 65535 f 0000003019 65535 f 0000003020 65535 f 0000003021 65535 f 0000003022 65535 f 0000003023 65535 f 0000003024 65535 f 0000003025 65535 f 0000003026 65535 f 0000003027 65535 f 0000003028 65535 f 0000003029 65535 f 0000003030 65535 f 0000003031 65535 f 0000003032 65535 f 0000003033 65535 f 0000003034 65535 f 0000003035 65535 f 0000003036 65535 f 0000003037 65535 f 0000003038 65535 f 0000003039 65535 f 0000003040 65535 f 0000003041 65535 f 0000003042 65535 f 0000003043 65535 f 0000003044 65535 f 0000003045 65535 f 0000003046 65535 f 0000003047 65535 f 0000003048 65535 f 0000003049 65535 f 0000003050 65535 f 0000003051 65535 f 0000003052 65535 f 0000003053 65535 f 0000003054 65535 f 0000003055 65535 f 0000003056 65535 f 0000003057 65535 f 0000003058 65535 f 0000003059 65535 f 0000003060 65535 f 0000003061 65535 f 0000003062 65535 f 0000003063 65535 f 0000003064 65535 f 0000003065 65535 f 0000003066 65535 f 0000003067 65535 f 0000003068 65535 f 0000003069 65535 f 0000003070 65535 f 0000003071 65535 f 0000003072 65535 f 0000003073 65535 f 0000003074 65535 f 0000003075 65535 f 0000003076 65535 f 0000003077 65535 f 0000003078 65535 f 0000003079 65535 f 0000003080 65535 f 0000003081 65535 f 0000003082 65535 f 0000003083 65535 f 0000003084 65535 f 0000003085 65535 f 0000003086 65535 f 0000003087 65535 f 0000003088 65535 f 0000003089 65535 f 0000003090 65535 f 0000003091 65535 f 0000003092 65535 f 0000003093 65535 f 0000003094 65535 f 0000003095 65535 f 0000003096 65535 f 0000003097 65535 f 0000003098 65535 f 0000003099 65535 f 0000003100 65535 f 0000003101 65535 f 0000003102 65535 f 0000003103 65535 f 0000003104 65535 f 0000003105 65535 f 0000003106 65535 f 0000003107 65535 f 0000003108 65535 f 0000003109 65535 f 0000003110 65535 f 0000003111 65535 f 0000003112 65535 f 0000003113 65535 f 0000003114 65535 f 0000003115 65535 f 0000003116 65535 f 0000003117 65535 f 0000003118 65535 f 0000003119 65535 f 0000003120 65535 f 0000003121 65535 f 0000003122 65535 f 0000003123 65535 f 0000003124 65535 f 0000003125 65535 f 0000003126 65535 f 0000003127 65535 f 0000003128 65535 f 0000003129 65535 f 0000003130 65535 f 0000003131 65535 f 0000003132 65535 f 0000003133 65535 f 0000003134 65535 f 0000003135 65535 f 0000003136 65535 f 0000003137 65535 f 0000003138 65535 f 0000003139 65535 f 0000003140 65535 f 0000003141 65535 f 0000003142 65535 f 0000003143 65535 f 0000003144 65535 f 0000003145 65535 f 0000003146 65535 f 0000003147 65535 f 0000003148 65535 f 0000003149 65535 f 0000003150 65535 f 0000003151 65535 f 0000003152 65535 f 0000003153 65535 f 0000003154 65535 f 0000003155 65535 f 0000003156 65535 f 0000003157 65535 f 0000003158 65535 f 0000003159 65535 f 0000003160 65535 f 0000003161 65535 f 0000003162 65535 f 0000003163 65535 f 0000003164 65535 f 0000003165 65535 f 0000003166 65535 f 0000003167 65535 f 0000003168 65535 f 0000003169 65535 f 0000003170 65535 f 0000003171 65535 f 0000003172 65535 f 0000003173 65535 f 0000003174 65535 f 0000003175 65535 f 0000003176 65535 f 0000003177 65535 f 0000003178 65535 f 0000003179 65535 f 0000003180 65535 f 0000003181 65535 f 0000003182 65535 f 0000003183 65535 f 0000003184 65535 f 0000003185 65535 f 0000003186 65535 f 0000003187 65535 f 0000003188 65535 f 0000003189 65535 f 0000003190 65535 f 0000003191 65535 f 0000003192 65535 f 0000003193 65535 f 0000003194 65535 f 0000003195 65535 f 0000003196 65535 f 0000003197 65535 f 0000003198 65535 f 0000003199 65535 f 0000003200 65535 f 0000003201 65535 f 0000003202 65535 f 0000003203 65535 f 0000003204 65535 f 0000003205 65535 f 0000003206 65535 f 0000003207 65535 f 0000003208 65535 f 0000003209 65535 f 0000003210 65535 f 0000003211 65535 f 0000003212 65535 f 0000003213 65535 f 0000003214 65535 f 0000003215 65535 f 0000003216 65535 f 0000003217 65535 f 0000003218 65535 f 0000003219 65535 f 0000003220 65535 f 0000003221 65535 f 0000003222 65535 f 0000003223 65535 f 0000003224 65535 f 0000003225 65535 f 0000003226 65535 f 0000003227 65535 f 0000003228 65535 f 0000003229 65535 f 0000003230 65535 f 0000003231 65535 f 0000003232 65535 f 0000003233 65535 f 0000003234 65535 f 0000003235 65535 f 0000003236 65535 f 0000003237 65535 f 0000003238 65535 f 0000003239 65535 f 0000003240 65535 f 0000003241 65535 f 0000003242 65535 f 0000003243 65535 f 0000003244 65535 f 0000003245 65535 f 0000003246 65535 f 0000003247 65535 f 0000003248 65535 f 0000003249 65535 f 0000003250 65535 f 0000003251 65535 f 0000003252 65535 f 0000003253 65535 f 0000003254 65535 f 0000003255 65535 f 0000003256 65535 f 0000003257 65535 f 0000003258 65535 f 0000003259 65535 f 0000003260 65535 f 0000003261 65535 f 0000003262 65535 f 0000003263 65535 f 0000003264 65535 f 0000003265 65535 f 0000003266 65535 f 0000003267 65535 f 0000003268 65535 f 0000003269 65535 f 0000003270 65535 f 0000003271 65535 f 0000003272 65535 f 0000003273 65535 f 0000003274 65535 f 0000003275 65535 f 0000003276 65535 f 0000003277 65535 f 0000003278 65535 f 0000003279 65535 f 0000003280 65535 f 0000003281 65535 f 0000003282 65535 f 0000003283 65535 f 0000003284 65535 f 0000003285 65535 f 0000003286 65535 f 0000003287 65535 f 0000003288 65535 f 0000003289 65535 f 0000003290 65535 f 0000003291 65535 f 0000003292 65535 f 0000003293 65535 f 0000003294 65535 f 0000003295 65535 f 0000003296 65535 f 0000003297 65535 f 0000003298 65535 f 0000003299 65535 f 0000003300 65535 f 0000003301 65535 f 0000003302 65535 f 0000003303 65535 f 0000003304 65535 f 0000003305 65535 f 0000003306 65535 f 0000003307 65535 f 0000003308 65535 f 0000003309 65535 f 0000003310 65535 f 0000003311 65535 f 0000003312 65535 f 0000003313 65535 f 0000003314 65535 f 0000003315 65535 f 0000003316 65535 f 0000003317 65535 f 0000003318 65535 f 0000003319 65535 f 0000003320 65535 f 0000003321 65535 f 0000003322 65535 f 0000003323 65535 f 0000003324 65535 f 0000003325 65535 f 0000003326 65535 f 0000003327 65535 f 0000003328 65535 f 0000003329 65535 f 0000003330 65535 f 0000003331 65535 f 0000003332 65535 f 0000003333 65535 f 0000003334 65535 f 0000003335 65535 f 0000003336 65535 f 0000003337 65535 f 0000003338 65535 f 0000003339 65535 f 0000003340 65535 f 0000003341 65535 f 0000003342 65535 f 0000003343 65535 f 0000003344 65535 f 0000003345 65535 f 0000003346 65535 f 0000003347 65535 f 0000003348 65535 f 0000003349 65535 f 0000003350 65535 f 0000003351 65535 f 0000003352 65535 f 0000003353 65535 f 0000003354 65535 f 0000003355 65535 f 0000003356 65535 f 0000003357 65535 f 0000003358 65535 f 0000003359 65535 f 0000003360 65535 f 0000003361 65535 f 0000003362 65535 f 0000003363 65535 f 0000003364 65535 f 0000003365 65535 f 0000003366 65535 f 0000003367 65535 f 0000003368 65535 f 0000003369 65535 f 0000003370 65535 f 0000003371 65535 f 0000003372 65535 f 0000003373 65535 f 0000003374 65535 f 0000003375 65535 f 0000003376 65535 f 0000003377 65535 f 0000003378 65535 f 0000003379 65535 f 0000003380 65535 f 0000003381 65535 f 0000003382 65535 f 0000003383 65535 f 0000003384 65535 f 0000003385 65535 f 0000003386 65535 f 0000003387 65535 f 0000003388 65535 f 0000003389 65535 f 0000003390 65535 f 0000003391 65535 f 0000003392 65535 f 0000003393 65535 f 0000003394 65535 f 0000003395 65535 f 0000003396 65535 f 0000003397 65535 f 0000003398 65535 f 0000003399 65535 f 0000003400 65535 f 0000003401 65535 f 0000003402 65535 f 0000003403 65535 f 0000003404 65535 f 0000003405 65535 f 0000003406 65535 f 0000003407 65535 f 0000003408 65535 f 0000003409 65535 f 0000003410 65535 f 0000003411 65535 f 0000003412 65535 f 0000003413 65535 f 0000003414 65535 f 0000003415 65535 f 0000003416 65535 f 0000003417 65535 f 0000003418 65535 f 0000003419 65535 f 0000003420 65535 f 0000003421 65535 f 0000003422 65535 f 0000003423 65535 f 0000003424 65535 f 0000003425 65535 f 0000003426 65535 f 0000003427 65535 f 0000003428 65535 f 0000003429 65535 f 0000003430 65535 f 0000003431 65535 f 0000003432 65535 f 0000003433 65535 f 0000003434 65535 f 0000003435 65535 f 0000003436 65535 f 0000003437 65535 f 0000003438 65535 f 0000003439 65535 f 0000003440 65535 f 0000003441 65535 f 0000003442 65535 f 0000003443 65535 f 0000003444 65535 f 0000003445 65535 f 0000003446 65535 f 0000003447 65535 f 0000003448 65535 f 0000003449 65535 f 0000003450 65535 f 0000003451 65535 f 0000003452 65535 f 0000003453 65535 f 0000003454 65535 f 0000003455 65535 f 0000003456 65535 f 0000003457 65535 f 0000003458 65535 f 0000003459 65535 f 0000003460 65535 f 0000003461 65535 f 0000003462 65535 f 0000003463 65535 f 0000003464 65535 f 0000003465 65535 f 0000003466 65535 f 0000003467 65535 f 0000003468 65535 f 0000003469 65535 f 0000003470 65535 f 0000003471 65535 f 0000003472 65535 f 0000003473 65535 f 0000003474 65535 f 0000003475 65535 f 0000003476 65535 f 0000003477 65535 f 0000003478 65535 f 0000003479 65535 f 0000003480 65535 f 0000003481 65535 f 0000003482 65535 f 0000003483 65535 f 0000003484 65535 f 0000003485 65535 f 0000003486 65535 f 0000003487 65535 f 0000003488 65535 f 0000003489 65535 f 0000003490 65535 f 0000003491 65535 f 0000003492 65535 f 0000003493 65535 f 0000003494 65535 f 0000003495 65535 f 0000003496 65535 f 0000003497 65535 f 0000003498 65535 f 0000003499 65535 f 0000003500 65535 f 0000003501 65535 f 0000003502 65535 f 0000003503 65535 f 0000003504 65535 f 0000003505 65535 f 0000003506 65535 f 0000003507 65535 f 0000003508 65535 f 0000003509 65535 f 0000003510 65535 f 0000003511 65535 f 0000003512 65535 f 0000003513 65535 f 0000003514 65535 f 0000003515 65535 f 0000003516 65535 f 0000003517 65535 f 0000003518 65535 f 0000003519 65535 f 0000003520 65535 f 0000003521 65535 f 0000003522 65535 f 0000003523 65535 f 0000003524 65535 f 0000003525 65535 f 0000003526 65535 f 0000003527 65535 f 0000003528 65535 f 0000003529 65535 f 0000003530 65535 f 0000003531 65535 f 0000003532 65535 f 0000003533 65535 f 0000003534 65535 f 0000003535 65535 f 0000003536 65535 f 0000003537 65535 f 0000003538 65535 f 0000003539 65535 f 0000003540 65535 f 0000003541 65535 f 0000003542 65535 f 0000003543 65535 f 0000003544 65535 f 0000003545 65535 f 0000003546 65535 f 0000003547 65535 f 0000003548 65535 f 0000003549 65535 f 0000003550 65535 f 0000003551 65535 f 0000003552 65535 f 0000003553 65535 f 0000003554 65535 f 0000003555 65535 f 0000003556 65535 f 0000003557 65535 f 0000003558 65535 f 0000003559 65535 f 0000003560 65535 f 0000003561 65535 f 0000003562 65535 f 0000003563 65535 f 0000003564 65535 f 0000003565 65535 f 0000003566 65535 f 0000003567 65535 f 0000003568 65535 f 0000003569 65535 f 0000003570 65535 f 0000003571 65535 f 0000003572 65535 f 0000003573 65535 f 0000003574 65535 f 0000003575 65535 f 0000003576 65535 f 0000003577 65535 f 0000003578 65535 f 0000003579 65535 f 0000003580 65535 f 0000003581 65535 f 0000003582 65535 f 0000003583 65535 f 0000003584 65535 f 0000003585 65535 f 0000003586 65535 f 0000003587 65535 f 0000003588 65535 f 0000003589 65535 f 0000003590 65535 f 0000003591 65535 f 0000003592 65535 f 0000003593 65535 f 0000003594 65535 f 0000003595 65535 f 0000003596 65535 f 0000003597 65535 f 0000003598 65535 f 0000003599 65535 f 0000003600 65535 f 0000003601 65535 f 0000003602 65535 f 0000003603 65535 f 0000003604 65535 f 0000003605 65535 f 0000003606 65535 f 0000003607 65535 f 0000003608 65535 f 0000003609 65535 f 0000003610 65535 f 0000003611 65535 f 0000003612 65535 f 0000003613 65535 f 0000003614 65535 f 0000003615 65535 f 0000003616 65535 f 0000003617 65535 f 0000003618 65535 f 0000003619 65535 f 0000003620 65535 f 0000003621 65535 f 0000003622 65535 f 0000003623 65535 f 0000003624 65535 f 0000003625 65535 f 0000003626 65535 f 0000003627 65535 f 0000003628 65535 f 0000003629 65535 f 0000003630 65535 f 0000003631 65535 f 0000003632 65535 f 0000003633 65535 f 0000003634 65535 f 0000003635 65535 f 0000003636 65535 f 0000003637 65535 f 0000003638 65535 f 0000003639 65535 f 0000003640 65535 f 0000003641 65535 f 0000003642 65535 f 0000003643 65535 f 0000003644 65535 f 0000003645 65535 f 0000003646 65535 f 0000003647 65535 f 0000003648 65535 f 0000003649 65535 f 0000003650 65535 f 0000003651 65535 f 0000003652 65535 f 0000003653 65535 f 0000003654 65535 f 0000003655 65535 f 0000003656 65535 f 0000003657 65535 f 0000003658 65535 f 0000003659 65535 f 0000003660 65535 f 0000003661 65535 f 0000003662 65535 f 0000003663 65535 f 0000003664 65535 f 0000003665 65535 f 0000003666 65535 f 0000003667 65535 f 0000003668 65535 f 0000003669 65535 f 0000003670 65535 f 0000003671 65535 f 0000003672 65535 f 0000003673 65535 f 0000003674 65535 f 0000003675 65535 f 0000003676 65535 f 0000003677 65535 f 0000003678 65535 f 0000003679 65535 f 0000003680 65535 f 0000003681 65535 f 0000003682 65535 f 0000003683 65535 f 0000003684 65535 f 0000003685 65535 f 0000003686 65535 f 0000003687 65535 f 0000003688 65535 f 0000003689 65535 f 0000003690 65535 f 0000003691 65535 f 0000003692 65535 f 0000003693 65535 f 0000003694 65535 f 0000003695 65535 f 0000003696 65535 f 0000003697 65535 f 0000003698 65535 f 0000003699 65535 f 0000003700 65535 f 0000003701 65535 f 0000003702 65535 f 0000003703 65535 f 0000003704 65535 f 0000003705 65535 f 0000003706 65535 f 0000003707 65535 f 0000003708 65535 f 0000003709 65535 f 0000003710 65535 f 0000003711 65535 f 0000003712 65535 f 0000003713 65535 f 0000003714 65535 f 0000003715 65535 f 0000003716 65535 f 0000003717 65535 f 0000003718 65535 f 0000003719 65535 f 0000003720 65535 f 0000003721 65535 f 0000003722 65535 f 0000003723 65535 f 0000003724 65535 f 0000003725 65535 f 0000003726 65535 f 0000003727 65535 f 0000003728 65535 f 0000003729 65535 f 0000003730 65535 f 0000003731 65535 f 0000003732 65535 f 0000003733 65535 f 0000003734 65535 f 0000003735 65535 f 0000003736 65535 f 0000003737 65535 f 0000003738 65535 f 0000003739 65535 f 0000003740 65535 f 0000003741 65535 f 0000003742 65535 f 0000003743 65535 f 0000003744 65535 f 0000003745 65535 f 0000003746 65535 f 0000003747 65535 f 0000003748 65535 f 0000003749 65535 f 0000003750 65535 f 0000003751 65535 f 0000003752 65535 f 0000003753 65535 f 0000003754 65535 f 0000003755 65535 f 0000003756 65535 f 0000003757 65535 f 0000003758 65535 f 0000003759 65535 f 0000003760 65535 f 0000003761 65535 f 0000003762 65535 f 0000003763 65535 f 0000003764 65535 f 0000003765 65535 f 0000003766 65535 f 0000003767 65535 f 0000003768 65535 f 0000003769 65535 f 0000003770 65535 f 0000003771 65535 f 0000003772 65535 f 0000003773 65535 f 0000003774 65535 f 0000003775 65535 f 0000003776 65535 f 0000003777 65535 f 0000003778 65535 f 0000003779 65535 f 0000003780 65535 f 0000003781 65535 f 0000003782 65535 f 0000003783 65535 f 0000003784 65535 f 0000003785 65535 f 0000003786 65535 f 0000003787 65535 f 0000003788 65535 f 0000003789 65535 f 0000003790 65535 f 0000003791 65535 f 0000003792 65535 f 0000003793 65535 f 0000003794 65535 f 0000003795 65535 f 0000003796 65535 f 0000003797 65535 f 0000003798 65535 f 0000003799 65535 f 0000003800 65535 f 0000003801 65535 f 0000003802 65535 f 0000003803 65535 f 0000003804 65535 f 0000003805 65535 f 0000003806 65535 f 0000003807 65535 f 0000003808 65535 f 0000003809 65535 f 0000003810 65535 f 0000003811 65535 f 0000003812 65535 f 0000003813 65535 f 0000003814 65535 f 0000003815 65535 f 0000003816 65535 f 0000003817 65535 f 0000003818 65535 f 0000003819 65535 f 0000003820 65535 f 0000003821 65535 f 0000003822 65535 f 0000003823 65535 f 0000003824 65535 f 0000003825 65535 f 0000003826 65535 f 0000003827 65535 f 0000003828 65535 f 0000003829 65535 f 0000003830 65535 f 0000003831 65535 f 0000003832 65535 f 0000003833 65535 f 0000003834 65535 f 0000003835 65535 f 0000003836 65535 f 0000003837 65535 f 0000003838 65535 f 0000003839 65535 f 0000003840 65535 f 0000003841 65535 f 0000003842 65535 f 0000003843 65535 f 0000003844 65535 f 0000003845 65535 f 0000003846 65535 f 0000003847 65535 f 0000003848 65535 f 0000003849 65535 f 0000003850 65535 f 0000003851 65535 f 0000003852 65535 f 0000003853 65535 f 0000003854 65535 f 0000003855 65535 f 0000003856 65535 f 0000003857 65535 f 0000003858 65535 f 0000003859 65535 f 0000003860 65535 f 0000003861 65535 f 0000003862 65535 f 0000003863 65535 f 0000003864 65535 f 0000003865 65535 f 0000003866 65535 f 0000003867 65535 f 0000003868 65535 f 0000003869 65535 f 0000003870 65535 f 0000003871 65535 f 0000003872 65535 f 0000003873 65535 f 0000003874 65535 f 0000003875 65535 f 0000003876 65535 f 0000003877 65535 f 0000003878 65535 f 0000003879 65535 f 0000003880 65535 f 0000003881 65535 f 0000003882 65535 f 0000003883 65535 f 0000003884 65535 f 0000003885 65535 f 0000003886 65535 f 0000003887 65535 f 0000003888 65535 f 0000003889 65535 f 0000003890 65535 f 0000003891 65535 f 0000003892 65535 f 0000003893 65535 f 0000003894 65535 f 0000003895 65535 f 0000003896 65535 f 0000003897 65535 f 0000003898 65535 f 0000003899 65535 f 0000003900 65535 f 0000003901 65535 f 0000003902 65535 f 0000003903 65535 f 0000003904 65535 f 0000003905 65535 f 0000003906 65535 f 0000003907 65535 f 0000003908 65535 f 0000003909 65535 f 0000003910 65535 f 0000003911 65535 f 0000003912 65535 f 0000003913 65535 f 0000003914 65535 f 0000003915 65535 f 0000003916 65535 f 0000003917 65535 f 0000003918 65535 f 0000003919 65535 f 0000003920 65535 f 0000003921 65535 f 0000003922 65535 f 0000003923 65535 f 0000003924 65535 f 0000003925 65535 f 0000003926 65535 f 0000003927 65535 f 0000003928 65535 f 0000003929 65535 f 0000003930 65535 f 0000003931 65535 f 0000003932 65535 f 0000003933 65535 f 0000003934 65535 f 0000003935 65535 f 0000003936 65535 f 0000003937 65535 f 0000003938 65535 f 0000003939 65535 f 0000003940 65535 f 0000003941 65535 f 0000003942 65535 f 0000003943 65535 f 0000003944 65535 f 0000003945 65535 f 0000003946 65535 f 0000003947 65535 f 0000003948 65535 f 0000003949 65535 f 0000003950 65535 f 0000003951 65535 f 0000003952 65535 f 0000003953 65535 f 0000003954 65535 f 0000003955 65535 f 0000003956 65535 f 0000003957 65535 f 0000003958 65535 f 0000003959 65535 f 0000003960 65535 f 0000003961 65535 f 0000003962 65535 f 0000003963 65535 f 0000003964 65535 f 0000003965 65535 f 0000003966 65535 f 0000003967 65535 f 0000003968 65535 f 0000003969 65535 f 0000003970 65535 f 0000003971 65535 f 0000003972 65535 f 0000003973 65535 f 0000003974 65535 f 0000003975 65535 f 0000003976 65535 f 0000003977 65535 f 0000003978 65535 f 0000003979 65535 f 0000003980 65535 f 0000003981 65535 f 0000003982 65535 f 0000003983 65535 f 0000003984 65535 f 0000003985 65535 f 0000003986 65535 f 0000003987 65535 f 0000003988 65535 f 0000003989 65535 f 0000003990 65535 f 0000003991 65535 f 0000003992 65535 f 0000003993 65535 f 0000003994 65535 f 0000003995 65535 f 0000003996 65535 f 0000003997 65535 f 0000003998 65535 f 0000003999 65535 f 0000004000 65535 f 0000004001 65535 f 0000004002 65535 f 0000004003 65535 f 0000004004 65535 f 0000004005 65535 f 0000004006 65535 f 0000004007 65535 f 0000004008 65535 f 0000004009 65535 f 0000004010 65535 f 0000004011 65535 f 0000004012 65535 f 0000004013 65535 f 0000004014 65535 f 0000004015 65535 f 0000004016 65535 f 0000004017 65535 f 0000004018 65535 f 0000004019 65535 f 0000004020 65535 f 0000004021 65535 f 0000004022 65535 f 0000004023 65535 f 0000004024 65535 f 0000004025 65535 f 0000004026 65535 f 0000004027 65535 f 0000004028 65535 f 0000004029 65535 f 0000004030 65535 f 0000004031 65535 f 0000004032 65535 f 0000004033 65535 f 0000004034 65535 f 0000004035 65535 f 0000004036 65535 f 0000004037 65535 f 0000004038 65535 f 0000004039 65535 f 0000004040 65535 f 0000004041 65535 f 0000004042 65535 f 0000004043 65535 f 0000004044 65535 f 0000004045 65535 f 0000004046 65535 f 0000004047 65535 f 0000004048 65535 f 0000004049 65535 f 0000004050 65535 f 0000004051 65535 f 0000004052 65535 f 0000004053 65535 f 0000004054 65535 f 0000004055 65535 f 0000004056 65535 f 0000004057 65535 f 0000004058 65535 f 0000004059 65535 f 0000004060 65535 f 0000004061 65535 f 0000004062 65535 f 0000004063 65535 f 0000004064 65535 f 0000004065 65535 f 0000004066 65535 f 0000004067 65535 f 0000004068 65535 f 0000004069 65535 f 0000004070 65535 f 0000004071 65535 f 0000004072 65535 f 0000004073 65535 f 0000004074 65535 f 0000004075 65535 f 0000004076 65535 f 0000004077 65535 f 0000004078 65535 f 0000004079 65535 f 0000004080 65535 f 0000004081 65535 f 0000004082 65535 f 0000004083 65535 f 0000004084 65535 f 0000004085 65535 f 0000004086 65535 f 0000004087 65535 f 0000004088 65535 f 0000004089 65535 f 0000004090 65535 f 0000004091 65535 f 0000004092 65535 f 0000004093 65535 f 0000004094 65535 f 0000004095 65535 f 0000004096 65535 f 0000004097 65535 f 0000004098 65535 f 0000004099 65535 f 0000004100 65535 f 0000004101 65535 f 0000004102 65535 f 0000004103 65535 f 0000004104 65535 f 0000004105 65535 f 0000004106 65535 f 0000004107 65535 f 0000004108 65535 f 0000004109 65535 f 0000004110 65535 f 0000004111 65535 f 0000004112 65535 f 0000004113 65535 f 0000004114 65535 f 0000004115 65535 f 0000004116 65535 f 0000004117 65535 f 0000004118 65535 f 0000004119 65535 f 0000004120 65535 f 0000004121 65535 f 0000004122 65535 f 0000004123 65535 f 0000004124 65535 f 0000004125 65535 f 0000004126 65535 f 0000004127 65535 f 0000004128 65535 f 0000004129 65535 f 0000004130 65535 f 0000004131 65535 f 0000004132 65535 f 0000004133 65535 f 0000004134 65535 f 0000004135 65535 f 0000004136 65535 f 0000004137 65535 f 0000004138 65535 f 0000004139 65535 f 0000004140 65535 f 0000004141 65535 f 0000004142 65535 f 0000004143 65535 f 0000004144 65535 f 0000004145 65535 f 0000004146 65535 f 0000004147 65535 f 0000004148 65535 f 0000004149 65535 f 0000004150 65535 f 0000004151 65535 f 0000004152 65535 f 0000004153 65535 f 0000004154 65535 f 0000004155 65535 f 0000004156 65535 f 0000004157 65535 f 0000004158 65535 f 0000004159 65535 f 0000004160 65535 f 0000004161 65535 f 0000004162 65535 f 0000004163 65535 f 0000004164 65535 f 0000004165 65535 f 0000004166 65535 f 0000004167 65535 f 0000004168 65535 f 0000004169 65535 f 0000004170 65535 f 0000004171 65535 f 0000004172 65535 f 0000004173 65535 f 0000004174 65535 f 0000004175 65535 f 0000004176 65535 f 0000004177 65535 f 0000004178 65535 f 0000004179 65535 f 0000004180 65535 f 0000004181 65535 f 0000004182 65535 f 0000004183 65535 f 0000004184 65535 f 0000004185 65535 f 0000004186 65535 f 0000004187 65535 f 0000004188 65535 f 0000004189 65535 f 0000004190 65535 f 0000004191 65535 f 0000004192 65535 f 0000004193 65535 f 0000004194 65535 f 0000004195 65535 f 0000004196 65535 f 0000004197 65535 f 0000004198 65535 f 0000004199 65535 f 0000004200 65535 f 0000004201 65535 f 0000004202 65535 f 0000004203 65535 f 0000004204 65535 f 0000004205 65535 f 0000004206 65535 f 0000004207 65535 f 0000004208 65535 f 0000004209 65535 f 0000004210 65535 f 0000004211 65535 f 0000004212 65535 f 0000004213 65535 f 0000004214 65535 f 0000004215 65535 f 0000004216 65535 f 0000004217 65535 f 0000004218 65535 f 0000004219 65535 f 0000004220 65535 f 0000004221 65535 f 0000004222 65535 f 0000004223 65535 f 0000004224 65535 f 0000004225 65535 f 0000004226 65535 f 0000004227 65535 f 0000004228 65535 f 0000004229 65535 f 0000004230 65535 f 0000004231 65535 f 0000004232 65535 f 0000004233 65535 f 0000004234 65535 f 0000004235 65535 f 0000004236 65535 f 0000004237 65535 f 0000004238 65535 f 0000004239 65535 f 0000004240 65535 f 0000004241 65535 f 0000004242 65535 f 0000004243 65535 f 0000004244 65535 f 0000004245 65535 f 0000004246 65535 f 0000004247 65535 f 0000004248 65535 f 0000004249 65535 f 0000004250 65535 f 0000004251 65535 f 0000004252 65535 f 0000004253 65535 f 0000004254 65535 f 0000004255 65535 f 0000004256 65535 f 0000004257 65535 f 0000004258 65535 f 0000004259 65535 f 0000004260 65535 f 0000004261 65535 f 0000004262 65535 f 0000004263 65535 f 0000004264 65535 f 0000004265 65535 f 0000004266 65535 f 0000004267 65535 f 0000004268 65535 f 0000004269 65535 f 0000004270 65535 f 0000004271 65535 f 0000004272 65535 f 0000004273 65535 f 0000004274 65535 f 0000004275 65535 f 0000004276 65535 f 0000004277 65535 f 0000004278 65535 f 0000004279 65535 f 0000004280 65535 f 0000004281 65535 f 0000004282 65535 f 0000004283 65535 f 0000004284 65535 f 0000004285 65535 f 0000004286 65535 f 0000004287 65535 f 0000004288 65535 f 0000004289 65535 f 0000004290 65535 f 0000004291 65535 f 0000004292 65535 f 0000004293 65535 f 0000004294 65535 f 0000004295 65535 f 0000004296 65535 f 0000004297 65535 f 0000004298 65535 f 0000004299 65535 f 0000004300 65535 f 0000004301 65535 f 0000004302 65535 f 0000004303 65535 f 0000004304 65535 f 0000004305 65535 f 0000004306 65535 f 0000004307 65535 f 0000004308 65535 f 0000004309 65535 f 0000004310 65535 f 0000004311 65535 f 0000004312 65535 f 0000004313 65535 f 0000004314 65535 f 0000004315 65535 f 0000004316 65535 f 0000004317 65535 f 0000004318 65535 f 0000004319 65535 f 0000004320 65535 f 0000004321 65535 f 0000004322 65535 f 0000004323 65535 f 0000004324 65535 f 0000004325 65535 f 0000004326 65535 f 0000004327 65535 f 0000004328 65535 f 0000004329 65535 f 0000004330 65535 f 0000004331 65535 f 0000004332 65535 f 0000004333 65535 f 0000004334 65535 f 0000004335 65535 f 0000004336 65535 f 0000004337 65535 f 0000004338 65535 f 0000004339 65535 f 0000004340 65535 f 0000004341 65535 f 0000004342 65535 f 0000004343 65535 f 0000004344 65535 f 0000004345 65535 f 0000004346 65535 f 0000004347 65535 f 0000004348 65535 f 0000004349 65535 f 0000004350 65535 f 0000004351 65535 f 0000004352 65535 f 0000004353 65535 f 0000004354 65535 f 0000004355 65535 f 0000004356 65535 f 0000004357 65535 f 0000004358 65535 f 0000004359 65535 f 0000000000 65535 f 0000607655 00000 n 0000608113 00000 n 0000674008 00000 n 0000674486 00000 n 0000674863 00000 n 0000675257 00000 n 0000731770 00000 n 0000732185 00000 n 0000732530 00000 n 0000732559 00000 n 0000809743 00000 n 0000810045 00000 n 0000822358 00000 n 0000822403 00000 n 0000822696 00000 n 0000822725 00000 n 0000822754 00000 n 0000848084 00000 n 0000848460 00000 n 0000887743 00000 n 0000887931 00000 n 0000888164 00000 n 0000888193 00000 n 0000888688 00000 n 0000935834 00000 n 0000936340 00000 n 0000936709 00000 n 0000937107 00000 n 0000975206 00000 n 0000975485 00000 n 0000975760 00000 n 0000976149 00000 n 0001012373 00000 n 0001012603 00000 n 0001012868 00000 n trailer <<639893F5E2236A4DBFEEE91ECD97D987>] >> startxref 1021906 %%EOF xref 0 0 trailer <<639893F5E2236A4DBFEEE91ECD97D987>] /Prev 1021906/XRefStm 1012868>> startxref 1109970 %%EOFlibdigidoc-3.10.5/doc/mit-license.txt0000664000372000037200000000216013560273131017012 0ustar travistravis The MIT License (MIT) [OSI Approved License] The MIT License (MIT) Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libdigidoc-3.10.5/doc/SK-CDD-PRG-GUIDE.docx0000664000372000037200000277240213560273131017124 0ustar travistravisPK!kw [Content_Types].xml (Ėn0ED'E&@S[l9Nв"#ix=J̯6wfՌW-k[ Sx5BbWo K5[!O'+R8>Zt<G,_faك-_k =H[s.GL۬B`He~ҷ\[Tu$m\D0yP>UܭI+;Zp$!WutQ+(nD*~柶o^v KHkbv!N/kF7чtq6No G{ֶH/ߌz"@zyw<I0yQc> z[BS1GV GI0I~g|bwm Y<`o= 4@w=M<I+w?Bl0CduNd} ' @6ߍPK!N _rels/.rels (j0 @ѽQN/c[ILj<]aGӓzsFu]U ^[x1xp f#I)ʃY*D i")c$qU~31jH[{=E~ f?3-޲]Tꓸ2j),l0/%b zʼn, /|f\Z?6!Y_o]APK!s>:|c)word/_rels/document.xml.rels (ZkO6>iUھ%Υ-t;MNB3N[&NYr~^'z#&]}K?\*vHIOFDNyX]Τ' nm[(I[0 GTI,R6up6~)~ďA>a*a3Q! #X6T.aǑ#Ҕc4>Y\l%hzs1nT)IhA#;*IݶFtE$Fu@t3Qc  7ɯJk>ZBp+v/]&V9qWGoi'ye"ZU~ݾ0ʶ Vn9 $ۋxZVec4jUzj8u\T#Y =fm4.Vvl0ٙgs虵@bTO0ѵ"j*? [hUǏglq} 0 $>A\hCϩԡhg SblGx5ϴ 18!u9ZP)2G٠6c?щ݄!w]b#z$m="HelKQ+S: W)1SdBUd18d YG\?bApNێ5!,!$.S-F{}^!S}>1Ìi'hꠡEm)>R|]m)^u.)xGE02ώOЧab拎wc4ZU3[H;azqS ro4y%!a"!"&#,%-WQ< f:+jhΌV&ɾt=ݻ萄PK!?9!word/document.xml}[oH♪"|(t LpFaղ4o"/.OoR6$qNض4,䥭/|u"Ȼ`zϼ.G㈶D@(bE&,[2x^VCS\A٬Yq7|Ld^Z[iw,Uڵl<o+ |Wm ^ ]m}PkFQBeg 4Dn4T 3%uD7ڏ̖4||)FI z-O)bR&.$Ͻǩ n8k&g( ez'HWȽQRLcR\5F1GhS QW8B?p<&¬1IQtkdIBr2D[,Hm_krTG4e"r|ޛ\(_Se11@hu#Iao29jw"GKI`H@QEQ U@qk_ʛQ)&0NS`,r,禓њwTV&HNm;a&)t@ZN,Q4la-2wˊ[pl?*2Ћ<4.D6cCM{kH2 4\ᘼn6 p9m Isḿ( 3ֱTOȃ%աq[bF)' &IQHG'8@) P[)IXt3xFd9dQ1y2j۝hTHUdtCف| A1~Rʟsu?##_0o߼ VȯdR/"IE~%i;vy2k|mqeS>/}[a{KJQ 3J}]VT)-Id~vMqyF|y׬3F\>⿸ p n+2_)2耠h"?.6TGm G)-hf UATH>UL],5t 3h*q &GK%cHGqkMB),Zր  ]*ڇuAT&/7+E =KK[DoV0Mڄ.΂̫܉zīW*HAf<r ueE}D;M7 icpVllc*GƼ+sfciFhȒ\o[,ÉڲC1jj tA_uGuGᰩd/ ;d,w&q0KwMFwf9%o&K2/~A#دxRtghCyGLjPڠΑja{eT+Y@w.݅y·m~Ck-(+ƫ ֥ P0Jq=yq䮤c ,@i2Sz4JX»3K@ (ʛK5#zi)n\B:}~_Űl+1Ê()Úۦ]6x(Ë וM=T1,YUHV&WՁ%W)2$يjV']AꤻheHۂ,.oN*T^4w] oD-;ˉz9殶uos~L8"zFqS%S#|R?Q\ 4dq;Y!/gOȓ\2ATe@qc\WՅy7eIב_w/pK"/z/~ycpMag"gtmaB"֚C@V:ړb_V^2~ZksKMBK.wk%5MIeETafUOeقTAsx S Wэ.6:5L} a2*DU 74wX n HxEDc_Aq#F5W*')jO7@!/]Š uqfOmrUEQia@RU/5+V7kN4ר9d<,clH+2yVCh˫341TQSbmI!+Ǩj՞\6͢K&XF楁<[6ECZ[Ҝ4y`c7HHSؘ5Y LŎ}Y@Wy5F vؾJMaOvDr_+J데/QҶ07ț1ZG!./z4[?igmy ð&}Ap8z)|u7GO-]2: Xl!k`]jO[(qO-,%r'q8I?YPB)sr(/,ܶ ,1>MQs %Uܫk΁Y[kQr CsW"1i"W+ W ar?\y*'Ysy-Y](T3+֭p'0DO(!eOkN`aȲU?~lY"߬w]פ\LCj54 @ݨ"a׊ {qڜJ ֠C2SDՁZg|3cЌ%\h)zLͽ0̐w{eɕyUU?'uC^AdлF>vޞ+51.Ћ%Cь+:4S,Ge"=]E3wD4SA grAO(mm,@ j ] ='jBKowDh3xGb%꜑c:M@cYhAh;<h:bz4]Q,C*`v:֚zf|X)K^l?upJEFvƞJhZlP^PGc+jɢ.^\^fZ3^,$|B_݆ >!Y~j.>-6*(њd9< h2*KnO8`}w gPxX//^4&<}(Xd&w-},Cht[QioN0scB݆;͍0^ Kbn.0|X|0'{i9FDf'?č ,Eiͫhfs,ja?@s*\G`r't9yP"8pT5LA >=Hd-y ~= |o1\HB梼0x3o`MGǝ-^kpY 8p;pکټ3,de8vL i/Oܯ旟~`nkY.OWt. 掚 Dd@ r纈. c4u 涇9!dS97Ud'̵f5wLrɨ<|Ȓ`qIvk=CK WuǶZs_6hWx:[SWP*Noq{{n [>{Ր1b|^>![&]8Q{ǻ*dD q,G~hY 'z&X2L0nnG"="spb@#ˋĀ܃tmp,K oX% ]5KܕD_·FefY yЦj;2wv, =&{)KVGjۣKɲj 6uM;KRS"=gKy^3CqB vy40&):mN,:lFAV N,~!‡onx쏘Rq~2cE,3, .g /\ P؜j0s Գ wleYM+f)2Du0Ⱦ,9B6 6:=Ȯ 1Y&V'JjV;}b5!jzVjh.97N(XCMVN6 g!U5 =@Uծ2ѡ8!d"I&)Xl:`-02,nՔu8?̃ٔNPs)5[u}%~ft*YnAL*VK#)8V c(L8b.2$?yb±l![93RoL;J~^iV:fns2K&t>0%;"R/z&Ԅ9ff ga|{DdW?KMwc)ydS򈢭ڎ984]509]NkDt(DQ8LQ8Dxl $gK3@互Z-;}\ߩlvOgNcbry m,f) c0|A0 QV ;0sw?gNl|eR6r,qkϑ59}MDs2~ģqR8 #z24z٩yM]ׄbrIOfPfS XwH6lȺ lLY3m g,,=Rl*W^&iJR'bR.{Vw~0KBdoWp<_8V+3 h&+A>Ҹ,\;s^?=@ XPx.`5^t]w֯hs"P$a`͘J-uA* y&];0I^{ia)j=ไԍbgR֓#a(Cm{&%EiL}P§lfrGT%4xq%U3߉< y[l(5vWjWPuzViSJq4lnJ1**hw^%sƜqaѤ?iO#Z,g-(IWUgzѿ7/pnTO[uk@ xsayBN,'I|,`#M&1 ˟8K{EٚKcIgaS4@A q=pui]\˪lq.!ڼ-̆+z]%MPh#zKEov( N+L=8 V65UWpksx*I^R*] }KCAT B~wwt͝s~j=t mن`SwqTaك~dPVI!v}$1AyJ/s(9~|yǙ6B>6Zb"̼qLwOð}s9p@9ȱN70{17͙B /"S=vq|?I U9q :`ao!|E;zd׵JnZ[iؚ,6cC#Yؚ5K$%qsfoVL : q#qc"n!6ORj} O!u/!^9+x)wAkJ7גl[y ]u|`i:ƬwQ.~̽}S[hNfbi$]N*]V_?mKGmYh{[?yAJ랅 LQE+06;oL;,fšxWwmyw*[jz /, #1Щx:oKTW,gwxA $cM勞χDY8]v0qr{.l=񠾜{,vdȟ`LgB֋{T E K==tCO2+ -ύhWt)Ϋ^'bEZqbD(e=/dX} kf[ Wg\(% Yq-LiL#)X@yAu.}O>*E!s<| pI 0G1l(",Vf4S ~/l/s$gPIe!ɠבxP9lqئ8v8IA-; $!?cr=TKʼ+g˲boyV{}&/Yt]2z*xFh*3p42Ǘiox<RVf<됤hߚ60"7x搛S%4\u:.×0&hF!E(\Yϳ+n?"cI:*,<@AH ym H@m[[߰lȒamoɼa(hoa.9GCl 0ܧh[e>U w;˰|N &hۛBc/mXϸNǛbэ+SWk^q4\(j‚hh#j&>`%O/PQa%%,P<".@H MF|S{,D>b@|o*|5eWh7BrsBOOط_̊=f[CZ C(4¢kw9<~Lz[ef_Y*׹:Y.kxoĒ>GcEGS&>-7#V @Bし=:$ I#6Mq@5uWPc# .oXp$}wRbr'l2r?z1\3' WFdwm/g7pȢcy(9M4$6S ^P *dGf^ G9 zyY*BbӇ~[~C:]\gN/h M\;dqؤf aIƿe#@ 73\l樦=r~H:T]'4Ei|]9wKBQZ@x5T!pD;^W$xÌ#Al!ful/([Q0c}x# ~kmRV ON@֑Kx?QeBwca<] GI!?4_꥓b"QJj,>]x'&F!y8L,'J)Nԃꜙ+)cNRN$^|fTd-%`MkTj\<_+)("DAx@œi2O\<,Hf`ÇfZ)gXx #̃9)=ʺ|Aԕrcku[ZQGVNUKN@cmxI``KI`dRD{eIy_SD7s}}4y7S:? u0şFro(;%.FgFh46"J0~X,dxB2ʂQKFQ0MUKv 8FV*!sQ.^(LW%R\f Ķ4$V~lE|B G3xͽ_1?WK2bxXNԾ}GFEFݝ3=%{LHv` lW!i`C#;r IMeHMde$.idI~|8ǮJ6sQH.ɂF$05'rPdC)ݨEb߸Ew"Q35C^E‗L[Nvg=pϳPfkhD*MTU/ '*Nbeɵ.8*TC&U/blyL!Oz39ifCE.4 B!*tBrD B,F{!m'{K.-KӇ]r4U׶4]R19ɜǦ2y|9[Ioz)A0 1ؚr[x<Ϥ1)+{_cRI (FR5c1tB4PX7267TpOXTI)YRs.Y1 1 Hb]W m#*ؖ 2f:%CQzY!AFo{V}KSY͞e\qz\'ɂ& 2]i[u^2D8֑,>񒢮 ]b\y\!m!ɺ$ڥXZT3T [ce!:64F)'S0UMXvQ%Fu4YiO]xWΈ6f5FyS=yg_0G-[mf죨$ ]W7 |y:WNVk! L=:#NBv2KׄH؄W>aGguN&Pƃ&Uqb?a>/ug!ݐk.EgK{]U+J)-:aƐtZb3|̃~}[nEUV*J[u$l9 k>+%)?@"omEPǐmf~}?LR?sr AÝ|~.Utw_?և?-ys?N$-z_r/&ޟ}/m'+(JQ?PoB*ߘ-g0Unٯ㿤1'X +Q{)gwC /6;hwnϨ?705 `桟iV%єMF.UWחK+P?0(C_P o(.*v`Y?zu ɀ;aZW݆_hlo_e^c-DMGIIKh^jO$Wg]_+.3: |!w[.?$>,Tf?ϟV9QSDKf3J+s·_>8Wg#j0y?w[{zga,)hHZ,9?}H_\ܓ- T%۶8av(l-LC@sL:Rp0f`6Jiy"٩=_0s ?4yӉB)h_ͫ%dǀчE|׬9$sƖDK7h~a?vN[C>DcMk[x}zD8wh|'h׶Fn&h=iS$GмP?Ek/u{vx )4db~aYG\T(tIdgxdwrhAú y7_T75UlE/ځx] ]trpH-"pw=i>qPu zA {UF X# *#A%@ze)^7޷xA8= 1.Ȯ}W ٩uwyJ(܈RIC(;-FJi1zoy N㩑{@ 6 ӄ `81 l!?6؟b%m '/md5* 7nM:7ٞ߷S/V<j=һWL؍&{vCFY%>xgt8 FxW|V>-+_.(\ gX@G-hXȝV]$u-3֘pɘiA'2xlNٜv:1Jac zG1`&l@oۘD-"E{^kB"3Z؃6ozp5,y: ٽ=L\,-;"pbm[ē7~:)i ),cU@̑= &83.jxsL\c muwt]DM:dQxi7kS xnCL3l[Tf[P\=p9ƉQb jt%« Hn(c{:z9imԂ*YQUrf#}HERѤߍuȄv2%4jY t=b٤Gqݞ M?4"**a < HzҢTh/uXFQ)|P-(99EIFuƘG%roEG$ͻÆ7lpa*AM#catVcZ*!~^v(& 4='M)C O;œ:)hAV+l] e5c[hdbvY,II6\V zΛ]5hg}8 ўYCm%a-7:;3dM 7QO]l&D<,86FH{QU7SZ7Y;`J]qIb~{g#QN nH6*D{V|uhIku=֔ҙ JL^1ȹR|'l1LAR5;KERĝ )ݞ}R^GȐe ]QJI6,9hA$p@s;,NNV22{j!D" 5w,QT$dV[t) dT9X: Md0qxGoC۲0QjRWEcGQ ՕaNy+G$֚+BWnPqM.r.Ѭxq)٢9ઽFQ i끴2:9MDon1W}Oo[=[9Ӭ"Ewڦ6̺k7C__ ti`?3hqƾtaVuͣsf j65o/;n.n4["Y%lХ@芽o7˜%␌NXd`5s̩<[+fhxIwdkTyt3php?QT^_*2w%naD}v2j'ug1vx1#Cfc\4{|5 ʔvt [jacSdT{} WQOg/b!') T .toWrn)Fq]buzm*WdsNZ@!^NdsAg["~;WCSw_ IlVYl,i5Ɉpj r {r}J]!C ߷bMzNK"l;l4 E4B}Lk *<=3E:Z<@cvZ#&̛nI\' B-etL~W[#Y)\> Ol2/RI^fLVauCf|v+ٟ^ iH̅=;5nd_E&Jwe GiW))GXWGRJX`izau[9x?TE[`c]/. )uk\r]VKQ)}FJP:a˳i0N9d2rd%a&$2iv&eiTmOW]5yN1Ʋ{X, FfQs`{p~|4GC|wTi=d4Ѣ45 StKAKPizI|GRM3iodLB)sjf[z1|[n!&yЄi5]k1 "^+쑵TXs'>wFm-z+Qx,J 8Q2-Ai7kfʗ9yQ\z~ "CyXoߥamωVmkK[uUUTOj KV /^]di4$Q>-{1ԧ`&YH%k17%w+1(ȫv3n{Np͂ nIVXirq,IϪvFkG<ߙ6*3k;m⾒n۳J-l&؏*S}dg۵t7^CSe#ՔSj:]63ϻCMZ#*TX1-QPT|Gs*R%0O R홁Z~eܴ0\x&i>afXҹ[47n7V`D{iD#-LV^[qw[])+jYctzh~^|v`| ŦTfyix9ԬPh-wCp`kZOHShXB aUQ9oJÈ}eGή*˪K o$0|Qwwff17GɃA&ʩOY9/RqDs[0m:YpGf@JEzGL_8h䕔(H9Hٗ vu RADVuЫK^nny{nyYu:ð >eKumȜ\YgA 6x Duu_4Ɯoe8_28D\0p2gQ͓ )qvxz"ͳN_~ev$!98p-8 RJąϑu'GɥãoE;qB \P; S};0*Dhz>`hϙC5uNfUѮM: ow.RMT6 _@;.Gsv6te5ߒDJBHVgMRf,G%Qq:L!x8ȿ\i;ӣ#zAGwϬ; uy<{`JHx0W!W܁9]n+rEϝDzd!_N[D<ˑ/)xpȯ+ӬS6 *}#o.$Evf* 4~3`'ϛ1{xGEXDK8Q)vᙊ@!CtsK ^Ů}#y [y?Eu\"V͋fǝ}w{M.qV3HdiG6 z(o.ouL 0[R_VtȬh\2G i+P;RYϷmg&β *ljK~ڸW78Q֤Ԁ 'ˊ9c+$DLy %G!,stжW _YŖWH+.g:µ>h| \TSZKlDc 2=`SԳ\:ydg93(&;pi ue~n.0\lۡ63GɚcX&_k 'OZi w Ry5Q~3|H5^ l"t#4.X^5zY،>ÀԶtwL+o-Y 0Θ:ғ <_mQ erfץhzV ՏCʒݪzpXH͌xF0: X}[Q} Xr5>Mҁ`l| ЏxֆXW4xuBv"RN'Xc0'pY_8y<]0`|:/޻2|kW7ՠ4Wry}Jm!w!b9OD*-Gc <}ݭ0]0ۀR>a1|pJ6~pb+UKאԝ%C0]J̛9eW$2x=s{=ky7+N?6ȯkqJ$ | Pj+1gatbՇVKʏkwx=v9HGB|w+`7ugvZQݟfaZgbev b0lr0#3y?) JARE6CKo/8m-m@ ">j}g:Hޠo@#Vb^vc%e4Ag mF=Zb>0 8B)HQdaZ.QǴe Qb9Ƭ* K'v%')滯e:ph įwlBK2Cp4 * 'WE_3Bݳ̃ęI Z]~W}y v#0(^YO")rܢe# =N٣rYNe f"Wd,JQE|v"]j1B_+3nzhvPuoHՈ}c3զO,F5~ga?'e .Fߙ֡P)uc"vџQEDCrxWҨi:( ;EW̥ལ86 sY72XRȺ'0w`ے(ic(_3.3In zEY;O/PK;|ڙk2е$*4|9_OF绛,B;@ZdS(gq&_IHd{}0D`WEpʳkc 8jdF[=R,iKcvł&JjV5}W=Ѻ $axJ͵PhZD*xdJr'6[wXH4I A`hCf++H6ZCSQl,Q鉇g/zBcQ_z-ïd veLN[+3[3%㡄؁ډ٫7wGIrhjy`H8^pU-8 ۧ`|= [=a-ac|8hm.`bJ6}㬵 |G {vB7Ai]"̷"ܮ"Fuh2 lbXsrF Sn1hpzg+B T;ݪ ~ Ng_ f(WG Ao森d,˯$w ppKl[!NZAV63q!0~S"> $P(4D 36JK垹ZnPG5$AtÓ'~}GSS(Dae|&^]ja>"EEl}OC!MUho>^šL!JG7JT+SqikU(ͪ g49>ŸCN*"ճUOj;~.&yF M ۵\m|AO V?Gc{*GѫSk\ĽoEԡG%Doa?NOu1&␌iV>2 `_?Ct*-ҙ乘uK…o؎ЃǞWo$S4Bvi@4 ajI2-o s7EYhF..τ88z74l9lskl0I쟡?/yCdZ/T3?#;Xko'.֏^j?XeH8& ȕ(¿ڼ[Ջe:j6wr\Bݘ2ZÅ ypwu^:؄_L~w"44ۧZZ-YESprZL^;I̶!]958dݏvȉDd(} ]~UwY32Ys6˙ c7:YX!l<*aartOh[2EsH|Ep#S})Ԝ5Er&ѣM0sԾb nJT?0TM /9z0a6mڔj-*2嘱yy(*b}6\?D Gxp`ҌV޲v_N>Y[/xYT`\IBz]\;7 WyXLMѯQ+W_>tGHvq\5>4ZBwO,5;kV[`m%<) ye5|0$~*WqԞbQ}`_?iTQqBJw!BrўG'9 opB)tJg1HFmG",fx`n B%iQ߳[Ru&;->sRdMh-d֏ J.Eތc(1:_QWgֹiINn{FG47m63D0 !IAudяoXPmć"2?=52aWM?z8 Ձ kZq+!GR~ Wr?M͈rb5nَ)M%})6?Yn?]xwB*R|\*cL)kgj,jZ+%w܌֑o?[Rd"ЏL&@q&)\.1 Y\0I@%{M%+ʚ-"TB7Zr9o MDqcvwor9 Qok6|[|ڌ?ڣLdRX37B_pyisd퐼=;#o h$,f(UY2#79 @4 :8a&7maG _Ql70J_l_`ңِ%`G$ ^Cܾɽz>YmDCPm5lfoYcPv6v(e8o2=Rgp3:w~{6Hp0 O'@"dόӪ]5AstZ6}TCQ2b(>@ ɭgaXR~1mkK9PН1,7"cLxtx#j,dfxt\s.=-?VڻPCp L^SHD%ġdV"XǪh*J)tF;L^b FMJ]]Bm4lퟶj)-ŜOy/1Lۈ%ӥn[Nf60| d)n Sk MvL㺺na4#V~X4b\&xEs})6CU<dut1h #%w~Vќo$e䂩@6/zzzor4g909p $F92qP(q+Jߛdžf>*V;F3XPN; SdSȠCIbrW]&׉?<‡؝J($ǿN! IJʐȊOpKU*٩x3(M=~j/g(Ѩw ;wsi2ym1PdcPw&D~J/U gJL~ HBSH $q7 PrΣv*D IW`_LJ,u|} ,t1 D^) | 9GCWPLt5WmտϯpIzY殁=]97@lrgsBWY1UdQRC7K?ILϣ\ȢԽ"8k÷[%KΦi.ۍ࢟c'Éml * }o)W_+DmtF$MO(q dI {_)NY!UZ aw1on{Fn B6PJ7z'f4K'B_h6_[܄ug(K)eC iʖ%Y񼽳>8WigHU9H9<5,u> cg3j{i>s$1KCW {oɽaG~]*Ԗ47x35"_e@Y12#Ɔ%zo S9غ\V@KRXu!pKCU7oNxC#.s`9W,7Z|M*7ߡH{~#`yO]ٚn=Wb7[[R8 &AsW{`iڗV=j0B眴 G(G9#Zmtk& _ZN }Cn OaZXWdTbDTɲY4d*\bbhQ$2 /Z=&%^BmdiAP{~8ٜM62Yp `5Ai*7H&:[mVw-D>R4z [BgWycנEы};oq)r,IayEz/l`OX#.lGHnoZz y<0?Ӛ0{mDTZOTS"^7+w:(|._@4LeN;1 '/QxAa>vb:ߏnJ>V7mH^_ܔWf-E)1ʘ?HheRQJC0jT}Cu}n&-+={?cY%Ă"w 2 rdߺaaҕG.CWbsf/V_BomkguCw51,+1<= ʢ}23D n,e2LJ1%%e/v'{/ Jy[֔ l)#Q=)Zc\dݐn@VuK_d}E0)!UPɀZm#򜠿Wk%F=܍Kr_W8i#Ybߜi5Ӄ{ IB{ 9Ztd=TęQ)m Oi.fU1VΦ' :5eFYaT*[PXvuBȍ]Qe>%mG N@DzN- 70P֢b҄d9GU8Z@6YćT8` (o{z/ypZw7kŸ/)oGutGY^Ir;`Aj]a$eޖGHпK}"TlIl+"qɋA YF?{t3vq‰e##czB⊔ W9Oy@ֿIeqm}fKOAF}y*L ͵v;`;T/K`![p~y1RcAAuPn@6h4"nLjz."i:b[RzA$S~)~]z"m`TyW.[@$MYR0 kcG&mʭP){^15G\SBy%XJh g̭/ɅA_mX˻WDɁnKmEu^O:\' ڨ=24qV $i客 פUaW'b}M Kф4]3n2k6_I>'kp  cv..ZWn15x^lvҊ΂}3]M6D:_騍lR4Au| `12 T Za) :j=Ńa ce}ПaԘQ.fnoJܟhQ͝u#Q y#u5R\M>P,z@ܗeEPX"rkezk|EqD1$֥BߘZ&<2tiÙ(eD^9Dau{E_%#mr%)2%B),54 [_.̔nhob X.J&1[{ o2L#[ .K^wVC/P٧n:?_S7+L[Oec^z)~7L䖣sk}BYZQ=CMjV%\'W[\ǥHd&Lm8'/ &DY0Kzz'%j@r#n+Kˆa}2G$yc$eI\(o|~ˈ~O1Wop}l.XjO(1gbPzuB6K?bRQkbM\Ձ~{_D 3)L%h![` s=.!0 VyL/=y~JPrGf\Ke|BYd][G18X/"vƄ."9;e3 VN^~6"GD4D06ŔG1HϖyEydG}<z]qb˴3V"`:h[ ۔sqT票|M:@iz7uaPR$ϛ?;^j$Wwmi+Q KX^d3A.4V+ ?hl\D.e)E?I!/vwx3oX}:[)}k cHNÉU1`Czfyz ~!G=0PaL J,ՙCN4GA\^?[aqj;Fr:Rx_UdgdN Pj,k .QnE~@%zr|8Z_"oP{G].T-Fgj! F)mOv/ì[]0CmSMU{™ipߒ`CGyP2KC[)9K%pù'a#Y_^D,Y.k`-K(#jj#n\*py.,|+0gQ-6do $@AL֐Г}RD&!/}EQUwQ^h'6>{X/g` _33ua|d;4Y䫟6Z?mb@RB*-6R_`#6WK> Du]A(vN!-o]=ܠw('rߞ1PH8Fo1̍"_ls򃥎V JR-T8 @W 8Zf`(( qי@lO382|W0uӄ+vjm+_ۖ mfzh~$M s>=,}g(+?6B(KS?lgPV "gqZ;p|>`R B(%@h/]ڂ%w RGqJuh:!%ji>HR ^wI([.`NP%V'!U^Y"NW %kOtBA|i hԿU+0^ۃXt*;)l >OCbv i hhs tm%6F!|C/X{[ex-]^޽X |(jle>&&3]4#E@_%uc_c_ϓ^yo˞DU]1mHrئ9 Ob!P ~V@wO9~=qD+Xj:XUr|6߫`0% ̒K ΰG)CB+B^+DHԎ2'B0obi ӂd9"lUaJ![dk0ƮmX85wX!/H7 6P| 2zzV7֍j`,Ǐ;Cy|)*{KyLA#Fzo6Jٲg㒯*La&EH4y;SX̻_|ၼ%DŽCx9ؤtG2fOXp;kZ}|kΆX6b(L@?|#/vBe&>kOfx\;Lp>PiW |$a$ЋܳOe:1[{4 }jcw850χXkfKB?cCP,ב( m׾K%H>@]ӛxY0+h$p y&^ڃ]aw4j%Y؁fo6Pl +e1+P]5 B;k!"zײz֞ѹ0QMWI. ̈z`3kJ/mquL}e[R N:H3 f *.BdcH=1:"HŒ!Fd#Cd@/g eg6)OyՇ)F~$)L?vw\\>55!ߢo 5ƽt_5`y +wG\ {!zeBVtXb /7ɪZt)Xٓ1hÇ,uW[~B4kuZ ?tfIK[e  $c*,ޏh `uUX 셀%8{!r{.Ge%όn$Ʃf]Ͼ/ڂ(F1pP:k4,5avp7svŤxs0C=`7b&a:BM(>#VtR:CaWOL ﮏO'_R "黁\MdJ*E/m3EUQp@Aᷫ]=B\R&O}D9Fz]NlaCOBW02[2e:U^ .Bl:*ߐaF&VzQ`D+˫F^]15RrM!& ʰ=^OVFd`󰤉_ K4278yUHnA ]NTkAg'=z:NPN<&xpсg[#7p7e!Y:ý oк/d-JÔ*pJ~Uĸ5^_KԔ4VH/r>13Mc( at$3 _Bk<' @!70sm\yDMN<;4/0dyU(\!/*_O;oa#PBg[~fDppe'X*~ABco]a;Wַ8KcgJnA+"7uG*>/x#mהPYN}%hM ()NM3:="(7c{9kD{4]fC茯1Gݯk|NVh޿F5!N)vj[>BST+,)q< rlU|JϪdO*޶E@)}FsPJ]ɂ6pt }V\d1^J C2Q_K~(J_GaD 2>|s[8>SIR{AV5([-6i}.PoQedPb-l̊GJb2ԭ[>4|.C }lPx3 e+aH)V+m&K\z"ݿ-F0,8Qf&MҒaY!8;I ~cUPpQ3}/w}p@FOjx K1`~7yrӣò]c-;:A=-EI_mq-ia?ACo0Rh50d:ӹx5n ţY l* e{|kSt3="0ּ֐9tyZ5i+覣y{{x`CbМ(%n@MۙI 0t*S5y%/s.o9D-Yێc= rWkS@"9sor 'o,1Db!9&YӅ! [=)#:-/MUid8/<p7M8RؓfqJSȱa5Y(XW=7887ʁ"} B`TIۣQfF—|YмLYu^]K&Y)kq۪ v>l]&9J>~Y>8י`:Z67eZ9lso# RŅ ]MeRhm/tM.QH3Ǻ׉AXQ@'#|Iѹ>:sV2M%`w ;8Ŋ%tHYH"@K~8C<и.CT|- )ZSȅ{*2ΜB ,FN>[BWSowڶ%%LeNz6-ړ;]cI_Vh~_3MrH.W˭uw8{baaLЅ@{_bȹ{-8Q/i*m-nm#jf5z1zZ5޾Z&hV^r ]Xgj7ӮqI$4 x=*rVƗ)*(.+w#0#5ͅC]}DpHk#X>kc\Cǻ#$Nȹ3+C)ߣ1jO<-9.Pz`bXQyrɘOGI;c/|$Om9MUe &~]TdFbFIvH}ojˏmί'LHۯAVg $ ^WPUH1E_$P{w]_qPM/?Zv,3oqFfېvO11qEs8) dxƫr)ӗ ʢvإ1R@SXl>ϙa)zEҧhu/p:\RŤ 3mqbti SQm i4)C&Lep>g\\|tgK`Y1 M&?3G\\.RFXRB*SƇ3Z:L{YkV_^B.^ JoCUWmMY%Le'd/| 2_2Ԯ cl^7t4qi!nLԈ19_YO>c[ Ƴ U얇%.v):e,]7Z/c"*N+T;>^gyTb[eG 2y+x6sA|Nտ+pnePӬ/PgW~\)XcMusI|݌oT9}@'W d'Sm:jN14K$O# ϕ&.6c~٢^ַQt^CEN_ߙ܆G`,f*^C8<'7m/;9џJj>&oz??TyN;m ȟxߤ0P#FƇ/;{OD11fJ6v &}nx~P`6Luw;\ɖ̅c܇>˷sfYd! #cy ^)3C\P[c;="qt|QSdrO(4 wU*X66 B* 2&\5j M-Bj/yYϲM\LτwYCa *&a"퓼 &zmXdN{H[@M ;S=JRfN&>&CρF#Rfob"l`ȎhGjL!rrʀyoIhy\({$h.7gQ́L|#X,wsڿ${8[2>8;K{72ͻڠ/c8kRcۅKg8ݿ?$~m=;:ΐ"{>K~ ^<qQ? eW|4k@dq>SCw"n%<.];Rg6cNjZWֻ Ӆ%5;HӈYfwG".𪏄^ kM',]1ӋwRFIG4ɗ?<z6#W@tZ^7š;=}Azʝb>:S`{ ˎؙ|l+Jn3+z"[2U Ώr:=Ӆͽ5s-{71CI~?FY&so*J WO'D>~tݨ,bQ4aR$@Qn~\PȤJhx~nᨸk0hՋ2HƉREޭꍿZ(gz'6,n* :vz|ƻ̺HR1tifӚqEF9uFwhp2 a[i#*쮤ؼuhZo&_զFB@xt[) fF{ܵ'W#{FMLD L>EΉg2;q|(dL`wi=V{sɉ]5wDm!܅t1ěom t̙cb2eM_h6Y6%)y̔vdbT̋>P1$x-4񉡱w8d-5!ϳh+0]wZUhtK$:jEI$_i2< [lg^o$[9{5C ն{;hH61 s]M 6TnK;l9e $H |YÖ#I΢q54w3O`ч^[~:A2kt>\txƊrT4 Sí 8)xd}CYpIs e{].=.8}R ?ClO#iA+^gټa[&dчfLT1sst ek&ڻoKdIv]L5B˜ vlZ|YO tw:Gi CPI'G.nkk~s;GE/.{ڦM/;z'94a{-]_]cxq5N]HM}+EkǍTxcb쪵 )e@z*1Է٭;?He{Y_?Uy= y۽{a#Ϙ^B[q<O װFYyR~o⿗mj $&dXk,+ HSX5'_PYq=kTs'wi?@-X i #*c߃}^ED0a]c$i.e<%=;n)e5hS.L * #Z"5eRpp} ^ d"^Q*H?k6K;E%]p5ih6tw~S*JV@k3| Ô, 0u2F!vD|F,󇱅"//qlM Hag64I訁!j+7r;&%C 1ߎ_([P e7.R, OGjgf e=Sx䔔[÷ϵ&5w8~ܭb*~"Z~BÅRy#t>ecўk'ֶx{~+z&vQ"x9=|Te=yreDȬ9 y[Dïx6;z%M ?JAY +) bB*o(hflOE;uk m@}Ir+ein@_oŁTgsI{Vh:+\3SN.pC3p_`{?$vx驹̆) mӓ9pSq‘NV@:JV$w`2¥NdrΙ^oBe{1<~.I[+q/49|hԸ?U [b|6{?N/ㆌ/r*{o&$<ȮOD !9zu)ITo8^_B yF)6{`׬U=GC$fP,c8E=XȼHiѸg 1~˵y ZlZ$`L֤+({tv0Icn E{O&'3g"X$mIdy+eݾ>b C]υ(5 !uψ:BbOZՋ ӫaz${8äA%R-ڴQ}҆j/i*K,a4,N.fƂlET{թZ H[Hc?_XPǝِf$. WރŴa_щ{¢rNnx"QKi~lgj0@d>V->֕h`'7Hi\2.'u{O^ky3r%93.X2oꠟKq)ZsS]OgRt7 8qC+VFW㡦zD~dX?_o9TG!rT,t5t8,Iw`il腉e&:Lm/?M~5:sU,򩚀[#]P/a%rOҭF4 F"d =q:T='=߾I]:$6\̋vrfy2~G5-Zԣ灌zw)8O;?NYBH^rE9&,ѳ'`e((UN] Q{rl]{<Y„! (R5if3ܪZyT1%q.@uVOhi߾oD}=SoAWJq=]O77obeӻTG02ABX=bxn'BhSU]UBW}K2\1PHe&\q9*̥fR6Ԧ=I@z5/ CT>6#ORJd_gԎYDچCܔDKq 㢪s# %m Bj~W`|,m֫#Ȭ$9]D1ỆzαSx8 Z5\/E'%SItҕQbW)9I1aE`gCp/H2o[[c]9G W;xpxwz"vl;}ZGMȭt4ޚ$tXְalYEȆBt6RS~m1"basu!=jjiQc4pNjJ "'[cL!ZS|_EtvQ0I9Aʠ#͊~D7E{_[èh (l= ,<- ckqcE|'wE343c5}#< Evm=L\t![KU i#ER*[,a\SYm60fYͤjeDy$9VB'U6za? /|cjC->-Rp3 /˝΢r9_{#CӑӒߚiMod:}|͵Ħe (MiH|PAˌZ7wRA GEHق`Yy! {<%\==H?W5H_S֋eiw< mUǗyɼ[{/Wy68Kd6;3*TDzkjrJ`oþȃ {S$]L8r-dۊp (E;wsRkrΚo2=%L1#6μ^m p#87ŋVO<^2@puO=΁h9Gׂ{R)'Zغ.N])֔% b,Ty'QgMB`'z@ {[ErO *Mv1D4EF 7܅~;4q Y~ה};"rQ:_ C9DyWF7B 8˘u=͎>8}ED`>a͘(l t0 ״MH1i^Pdy]iE.z7ʜ2jr 0 dn k@b& ԕ 4 %g>*4!zGg| EB/yqQc$x(Ι i?%_a%83ҳ*ߞ NoOlb?A.q Ȃ)4XeVJ.0{ mlPfE2-8ij WK6 !OJPSkV䶴y̷\IOZ%c[29B@;/%EIeMvc# %<x#]ZHE֪j6wW)֢™Z;BS(,p#n;g;'Jq Z!WCJUK7,ZQyFňari{Q@H 5xyvP@ ,pz$oNw⋞nE4{&\`3Ѥԑ8w~7 -6".CNy|YA"^Tϔ}|(²-yV6A5{ `{9_^+c~V-qtR0w*m ]K׮Z0JByhGAlRb[ [g4-]}O}b.4eoeR005ʽ0O8c)` Bvt礝/2MΒwx臂mWh|4=c^dMcd˾ KaGw[0[{",ovꂍ)̝xK;Dc#[rUW2>ݺ+*AI٭<~dn=fTnGNmIc\I}EL0'Y݂ʒ+'eMmɽ#Q]dc q;MJ G!d͟:,냞nz *hvӟJWPSv<0N=A% uSn\x~ Fo_0D-~-\rEh…cK9K&(SY_'Q*Xn+un j NE#M>ehMPe V XćFdLDrxP..~QC\@x.J2e. @G !y 1sGH/v(ӆ1;8{qsw}NH+2:#`SO>*E?ߏxÛv#nv$:C*钅۱;E9jW9߯vO'x?@)0GXi*L%Jip5/]pZ]ו/3'_*4ˍ);p/ XujloD({3L=|uN3wΘ+^j"~H) .d1^xCq$s L4/\M7wX%pO/wl"6 '8QCy}[.!?#١D^[J/q uɥfpI,+F1Y􏼅$Ni]`O0Y鉇wBy fI~mbNAW_)T$+Ve-gY7z-!Y!m FE n dG:c>Fz,N-Æu? !9#EPtͯZƼRhZtYPٱ P)HoϚQ{tSB@aA0kNYڪI/ \.ގ:B*RcACj!USu[|V1r#E[YG蚄;L`['#u/9WͅseӃVeR#dWz/9N#LI0p9akTvY"Xe!tfn, |B"8s")O6S.UbhU}2IиE6M60~W-'Mpq`8t(=41׀񶽳cRrf Cc6*ǰ{!a5Fͤ70?qj~f"h]r͕}z)Itˑݬ[ j`{T}b*,=^Ʃ fzR>\a=8J.xtJKsA;O<|2b"&'PoP2YS٢p+q;xiBD#zb.|O*Z?u,* qT\I5^` LpگʾVg7OaO;Y!gc-x'Wc ҹPĕ~ Fk}1O )> HQZꤴm7 !bWYN&UώAcw$٘\N0sۉjJaflv->V4;ԝJ7aBH; (Ѫ@#WN)nnr0#zĺSTMSH$H qˊ2S c%7>:Jc'q1e\ Ŏl r6D?TP22]]' oA)ڦyDu+i! Z_ԃ# 5n{vlܫNch.M%x_lf t^~?TZ0 h+2iXCKgj7 쾸(yH3k˿ 7+ɝoKBH́>~Y34;a5(V׫ g$>|1?"tGSd|P&d  _ ܟ844Ɗ,I/"TEw1n V 8DimX6b{2ӽhܰkQjR`%:wfx V4En!M,1+DA X Ua?sBBaP2oeύME%uD8(݆<1cꞕ a濎Y8:YMoe2ɧpGi (_y6)@]JVNj}rAS^Sr]U7O']~kyJrWR%[06u\Xp:Jgց_Vh7HedcDsA#DPqW>ph9F :D&nUWӍ<`dKϪz210E,͒53ac3˅nU.쐋;$`(b5^75Ŀ&HǪ$)Ƅ}iKUM؅|@2Dm4)sKx7W=T=q{ßp|=_kێX=:a ( F?yˤ=;;1pEo}plGPi:/ek,BeJڞbn9AVb ]99",c"pm@}:o<0!_u@=n&V¿{b _~Xd I~Oz 29n!]!hw| <0Q?(00ǀ 0ǶRx/ o gO*I0Fx7q0rq)V+G|==*6|D+%٤$|VLk)+m2V;~^R8mu,Ivc, @:;r]}Vɺ,O}F`K_؏&K+B=۴k&=2QH͡F(߿8:tvxʍEV;B0r:4 i^S͇uW1?[KV^DB h:i^||e^f-=1rΞxD}o- f4wL1Xu147%*X95&Yџ6sGq|P}]ejs|zx8 #@ KfzyI;J .ad6OgsʷLϿۥk:9 lƁ/WҐuNQ }4,rtA*YE9N]5ߠNpn !26Lmn`j$cœvi{thzRW43A1^K-Wfyӹ:7v3$൸(z`7tɐÃǐeܑ@v7wvVhD6lOTSw]-#% IuFi#)7CFLfb͍ɥU MzTWMTm,r1 t!砿)]'N4ag&timߟ}jی'c^sI*8 `uv x)wm9 r?:q}IyVfG Q d|`mYZ(8ް1ȱ+)*@}ѱ/#TKC:>`ߗMndvoW2q(0B?ݩkM`Lp-Ŀ.FK?I&<فb/~Hz!M}TpBrJEėS{+|Ih۰g LL]@HyxO NmM޷+⯘v"zX)voM[z/K{+YͰq~)h.f_+ a%p}\[ jrXmr˥yGq BDU t&cK$*6@0"1LXD|Be+喭6%"&]y , rlfK?E{r'ǰm^\J3e#b{3%6 2~!Ww4Lp/-T`d.h@TͯȔF)Agvf;˃ |odUpyg¾{ Dk(cJjP{)BW5WVv o COUStZ4)_Fυܖ--5S4--c[]SAk,o)${QuTT.4JJor>QJKFNF >Y !_ j [Wn࣯\bÖikM!dLmk|^KHa+IǿeT _~&]61`)D3RD7[ LweT,AO߁eHT )f6eR/!Jӳw&{*8#ޭ{S4jZ >NV{"^oZfr? f g L3HbT1j^{_3S> y*]~E]P68O~*iQ);*+1!TPXn_\;ilR28 OdB)eF l\Z剷荍4eTE!eMe͗! ϸWnব&4ykgx>kt-սE'U%GOM5Tpi^H;tx)9"l(]u9uL< ~H0؞(ζG[UOqTы6Cl K`щ=}MLaoc7hSšAq_s DW EhX'/<0]'b0/F}Q8Vp4{|R]iP1iBZI/Q}asR5 _ybg=/"J^4/F͸7;@֘c/{8K$]LDhm ez;)Z۔> |&L+bw+~d_ &A&hQJ3 F!|z &΃c)db{+ y\ e´|<:H"yBєA M(6`f/Uts8ׁY )oE9ߛOOQ},iz,]4º5_%xi^N }c! t/ɟFQl43n PrKw[EJ1R8\?o(˦xf+",zJmǍ;"j+h/-Y{Z=5W~glI$6.ZusxlwKp>MJrOhKŅʣPݟid\`;G6!y1 qc ;mLoOTdkf*$1TJ!^y Z0r3|c/"-7xÞ{FwnWeQ[3& snpEj%շ*@G +rmg !*#}A0 iߞP }riJem~V2N:L k97wlR]@YA32hTvT$ DKWRba᤮ҎT]vG :&S]j,foyqdWݬ]ֳ!]ȚF7f-ml5l(8L|nl0mx VJYMOdahrnin8nD}Ւ#i p _/=wJk ӈFF`)WLjxVD{3P3u(֔__jq803xzi/ TW sPx/@*Zh24%ѿ,!m>))'bUi d{ 1M g-i*C;1ބcK1(w-?,BYk`ؔi f@J&C,sulq)ljr.)+fMcчJ׌ȶ fy-^G%% Vp@,?};'G4ĕ 0'x{!:lmDk}:5/3'S`݋!8v xY?#I?-r -+ro!ߵ\ BZFC}3=g0R "G^ 9ZYS[Io v~L?ɗVz0)k.s 5-`7B7/ <"ۖа봚K E>8>yz>(ӹ1|wȘ SN?l#CnuxN$ګkYK*8~;Q*[$ M!TH'1.r~>nB sEY"8))H8Á洽fU}B  1_u87-r6Մ'1}%G<&KoEY&y6:Y؄&l͗#Wg!w!N')@*w X=?+8SwvcFk 2ʝ_;g1mN[?%Sy'H4%y='QH`Dا}K4Z\7us52M*Kx5"rmUOy.@\V5ƃU#U m,@GV֛b3GR 7h/rLuF4;i黁y>r7Ko'OjAY9cO|qP9\50x |q,^l&99- djx[NcSbCGԥ P`n͋6ZYT }'@co:^m<-\ 4!6(C3|؊`c^#ߔ|c.ǭd*'@}V܇b\}]da"(fx;>2Td>" l NG 5+rk8ٍ]llam]ִpb !w׭CEv+}em,$Pwl)k^F&R[QrGx*jXĎ|zOÅ-3{D'tG J#e>O}~bXG!L>XsG]-0`n!P`.vN@ϙ'6νB ο:k ,hb`Q9s*q||S@p(yŷj:ӣW|SSCM@>k}OܑL>Hyۉ_*d6󗁊(G lv pzK*/wNnf?bBB@%ڿ{7!SCo;r43pѩ7lW!ZAzrФ~24IMy0Uu͜%πoTAÍ st^cНtRDUvٿj RU\͂Z ,#i:Ƣ:-0iT(x#2qGK\l< y uYND=k'h`yķS,@q4@_1X5?I2X,* 4:2v`ln$! T64 Yy?QŎP**z:֭=US 2v\ YTAj7 Ow. & eu}==%eLKdhQMqk' rߞvq(g3Ғh[!rLQ  z} gC<љ|G4t!(<!v3> w9:Ri^W-牨'ֱ{5Z!ˀrQpO4LxWygû "|1)f4gC+bw9FeWyf@ iH6aF&g>U-XeP9bvG!?\ƴ";gg z;4U"AlHWAn*-Gi{w$#gx=뙙e\B yLVTă9g3 }^]FׂpۥrR2H\㊿8ع xY12E؆*,>&d$5cOq fBDjA"2't~ܚbÎY ԟz[F=O-&QIcy)`F-gPHN]Ln1ʮ^?c9T!Dl.7#|c{ʁp܋I' r7S2rj =ލ\I} 5..Lm|4`j^hnᆕR"C?nWBl{ri=@t@N-eJO{~mag443^Moo#T-r♝xo;)>uzĥъ9G/l{!$ew@6!RЀb%gv3Ї wZB45"NIFC.E 6SZ|-PO 1"pu' 7d٭,lzi]s2"w*%Qc'Vu>Bo__@~6/߉bmoEni"2kK.B\Hy ,ΐkm;7+vl(1z_ ]"^kM`]QIc]h_B9bg~EJʔ+V ʔN/]8ٺKk.1c%Zp{? uM򵐝1qpؙɗnkVr{\n,{EBz7t"TZT\+j'Dūx $Հ/͏E"\!!9OR;(z[ǐCԷu}pU{eδE@C| "/ߓr5f5j0ii׿ԕbuk#V1%b{ a(pGRdRf3(M#0vV֖msnM2aEPxy۳5B%A}5%-1lMgx(< - S47ӧ_N iGbTXa,K+Tt*imY =7JRw_qkA)_GZ麴tdaX͡ɳ,vލkkMOh?ŲOp ~ B5&^#Z%x~={|IwPL{[#' L->A>)"sio1M~r`m`>',Vyi%oHC *?+%+Rޘ0nS\ނ0LW ̞@vJ 1I!08J}=nQfK8J6}&1j*RZIxYE@5W*[?Gի-ƢG8VxxOx.U[B+t3xz0:1cjcH<'xFGQpL-qqp.x}6}vVEpϫdwJ: {mӰ{C*_W~P4Eb1$hPCw2sՈ AwFq$y]Gmj0oL!űp= i_W|8_Gx廅]Wǜ5^6dW@86p!#(Sq.!b!)ZjJ?$,Uy轴x0ę~Ri҂ u3W#(b{>ӆLDLF>#AXy/&\W1i/U50h+xj":$~z#Э פȼIX1|"Q^ %HqK>C#z% |$LY@1vu<vXߟNg+J~2rVZN)oy ݄%xx,>+t`x) \؆?}\\mHh/C6_EP;0PgvBZ0xo\գf}4)CՍt شr,1 A{dgwwcaQP|`50hJɤH4l:&Gxp檎f/1IU{u?9WٜlIN־(,bMO_jܭvItdKÏ,$IYΫ&6VezxK%WJs$vs~P}pɁ[a}21;4_@K'=衔(FLN8'$P SS#T9XRVE?H h+/-,IJūۘo^8NKz&&b i"厠蔛.ރ#тXYg@$I؂?fja]j6瘅WČh~UFNPNDa49,Zz@,ŃIpl5)ۏzƐ-_(kZbI/1UW x>zc=S??ĞȖ#_̌ iRlLX|rks} o/w<4cq༭s] T춠m/MQҞHVlj|+5'* ]Zz4|M#lW w#6J m2%R/KfmթL.1 C7,C?qBW.ey#:u}(?c4pSjVtt*J. [ _ E4 q(u_ۜt)8_/t7יɦ`ۘKU4*u OQїFŷ,: i>`q*J>=c ֪c Iנb\zZ6ܸ*黎J^ nfioqdIӀ.D+J. Ni- ?3JÿmoMi^*{jaUǎfO'T8Ï OCC)Dt_zxuelFRKlfDz4{6wA#2{xvHJR}ߺjNCG<\#~]5Iɖ}Z: *9Hx=D]DEUs۷x_ ̴[D-]> a^˱ ʣy2my0+bF]ơKЙ`nGpBE$ o!69eHh-•uV7L֛(., @d3@)IGkB?33\Duę\@Q=T]@K_+dq -D_.`IQq>@&l%8o8`3giZ| ]:cU`LJ110O[&&M6ʳ?{1>"B3F1=%EɿOۊd,EkT?q:<嬠!f>>؍I& P&1  EN"N'?[aI7iJq!`<j7wW%?ǀL#xutb5ܢwxe,3} {lvM ][rɇ)6{_F߁E0 EB%ǀd:vY#L\ 5- nypBjp!2Jk=pџ@=f3BIPGtm"( )c4C_9)ߞ ~vp\E tII !J0X1W5Nh TN;q{K2wU&M[2jCaq$_5 0wS,xWߛYlfJ1YAfqSgUb xRyHVGa}(h+hk/_z{rshޖ 4$!@aq"'ih&iL\AbMX蝳}π40[qScRAUE0&){r 1UX/rZݟ*Qb!zu?'Kb6˼IM (C绀񝖾'GO$ P2ܡbO OdD4~0?q7w\Hyˆ{"*VqO9?QV4|l]'3.ͲzxGʑDa 69o,860Hz#̳BhK[L[z nGvWEX/  W^[qTخU(Z#okAǂ`GH1\0qxC^$B-xͣO-οΞ؆d=ªS7 yێ;LW .{G ` ޿Ӵ07/>Jі͜pg!n:1r lY&Ό.0RUo?'3G+( Mx$a}A߉\>m'`W[}8D *6G{_d(ib,sZQ7TA A=c/4Lo(˚ OaJyfw<t^ /Uhx'ၐEmkol];&7S\MQm Y#'?T Шnp0dʡȷG5gR;h2uqE#KN^4\S˚N7'!||z N`m<ѣgz}׫ 0X?v3<gOh}=v\=݌x[bS6ܺ4"zy'OeL])SpS%zy*/L qzN e _i,o Iʇo|nywc9-h]m:.84 =Nd9}u킉G%M`# 7GǝD=c$:>p3u{ Wۧm3un掗MzoXG~sk7NNc4dB_: 2^?%v{(<Ӯgr7n|,*$ Y–:F4Pe:4H)1@n=X䢿ǿ- |-Uy2m. U栞l> L׎Xb(ޱ6#uw @+͗ MW6&{(!)@px7KEiE=<~yKZa&dJ; 7Ԩ꺂̠EO+R;p8xW]m %$<ډ;4nV6q"51)fTc9+!@d#_~} ^]'oAZ{ִ&t s Όl @z\gYr/[U>v}H熱SY V} Z+!J[qCq "`ޏTeB78H8UAXG^E(X1p,_|_yUQ,LE~k?3(5WXb@NCr0`19={3==wRIkT*'FtXfc\mDBEnICv3[}=̵LkdfG6-8`A53Ǡ&Ga$HcIvdG}v0J1(ֈ>xb$ %Ұ)vsD [|.p?P1=x U.1-M<=.FIFD*޷ (<69'g.[po-D—nhUH@1jodF+&5L y>Fj/, >2YyW֥{~(g3j&V|vd~Ȯ¹V,>/GニZ;ҥK)$tU,(WkE8%;ՠ6dF /JT&ŏS H=y":χ=o;݊ϖ6:AnwdF;Z[G+=uk :')r2RndOpYśå}H~tC܊|1VI)SSTbHaM5@n ƍЅA >DS˅F+xQBO;['̪G .pnNђ^0/;o]P+Ag ~ϖ= w8;oX]=#b;@{pŁ]/N5 >T,qx;K5A Lk:)ݧ,ӶpUك HVajT*P ]{R y>@NnI\a<0kqzGz|dm?K:@sV1/dɲ*ۻZN+reñ?md}®gmXEr)_SOG0m*}yz44Zg-M,cn` ._ /.-4 kv.PIl˓̣pu$N.3a4ky,fdD.mHfܖ.f1mm}y+Z=]XW$C?hί[XͲQU2DZ2G5ܧ50iq6\vflQGw* %^/vMSE* [[vj oaW! /M@,Tw 3b +J_KWxaViӿ"3H;Bbhl& P :- } p<,f }@;eyk}]J濟>VIDa1L>@ >oM}O|Yp! a雫?A)\w1:J|'o8E]"H|[gKHi";g6;8d9!X:l,9]^/! 'k{xtugPo"k ajYT.ZAJxA|"I :`/ s*v`Vnۯǁ7)_DՑ}7續S \ 0yxCnYb@z"2hX{y"W#2Ǣ1ÍὩ.^ω/FUaP= ;SR?M_> x> z9t9p /j@N2iL-;wd*:b~=~E |sPQ86uָKIQgl4yC9SBϓDs#?F@آhTN1.qZ$2Y&bFO.6JC"_[aރze: Rf:%#ϑ(n&5WƠALg`I -%k!lO2p2"|3rĄ6~\tQ~0YBg70V]Y"QXn5Z,鬡n:0mAi dE2 Li 5f6`xWW](tO˼78ߕ#m s:N1#3uK{\;m\y}tv<)#ia PQ?vh'-`f)z5&ARԴNĻED J;R_Nm^ r.WHFvZft(NiRB : WTqX-8E*y\>!ʒƒZV7z j`G ;7<1 Aggpbvs`6_ED^«WV4kyM_{(}6g<<{^4МmOYbو͘!qXi#sP{6F?O(a4=!h yI^tm{7]Ȓr`nabm.=_^* LFSW!S8@l" '<]+m쀔q`b9E,pҝ&*<$O: QftH1gHMhR F}gE1@mhV /s),ŹTjkPo0&K=)l )Ga!Wr؄nDufWMrȭZ-|g LqMlwo1}dsN%%&jXSTS+BHKWEKϙu>.Cl #|O}H̯y뷆0."9 u vZY $/i-`mߙٷ/(S،΅fyvtLs;b1}kx,bǖs4 fFThɐq/,A^yMgbMpqQzf*@b"r@]{7 hKD'p{㖠[b7MF@TP|HH$oK˔7^}} ^ݶԅ_Z:G 58 aqABֺ6S2^{c*"X. " w+k ҲʿF~GZ6tWjY`c uh}hA=񱚔~)j>_o@͆zL~5V덎6&W=^,31:rꓻw`(C(uxYn)%NI|Q4A:6d἗j&n2 Z"߫8YopPw Q}+ग़S*+ wyjo&Tnau!zjE}-wuȀl5NA$U}/6w֞\ 57-:&ѯ̢:6Ⱦo8Fz򗞓D^uh:3Y ַܶ:ʛ] DW:uC+'EFDt%9$\!ae" ƴ">_?Cgw[?Tm28 ċf2`"\:\$B@ kA5HK=M3`#rPX P TB5 NK+@WȎP9]q lg4{U.ZA-*f`Eq4yQ{.G腽fPVoAvm+{SC~_k*#d">?x Z^r IhП4Q(%:><%Qxv_!dB y]]L٭PC\,G,!?RZZcNs1x;{Mo_f.^4;%sWl'nM5# 5#MaJI)_Y1QvoeWMgJ)r6Sk }; QQy.6Ί/t'8 (Eܺ{I5Pч ~β-YrLq5E_yv'& &@=\/ A!i4}" NOTߗ~ܒoߓ@JWC{#M!NՒI1j}80(w7|B{L (&w5P.ę{:}2]x;rI7reAK~Ћdc6&gF}dԄS'kA:~$*yk9RH+^% -h=r/3@SfA[v88bq 2] o_7~F-ռj )>HA 7`?MNӫҊHV`'K8ڈDa/&I]e}]cN/L/FFKɲڑ+!դ׌BҚݰJ, #6keBKLANDg6Ch [̓oi78NE$c cVCES+|X#;@\v/0rH$"@~Ȃ G9Z9j"]/BđBxGϹZx<u?FW kUApaTBfR܍X@;('F 2DF%Iגvf %_wҀ hgm6VJm_hKd `UΩweIFha#ScY>}*,!yc_Q,` pljk2W*q0pdUqe$R6h~h$$ŇM+^'cz]Cf(I&ܔW!3[wQe_l:7z]}E,_1 a/tu }PMA1jʂ>ex]my8Lqcv~$0 豲&1O1eW3daQ&-{/ڿӢM3وt㬮sT,J^@k0wQNtx\/ge⧩p͑!zY އHࠐTIbH?Zw@Ö}Iwq陥/;A:F ;~_DSsfTm1i*"p+!6Fh"1O{If30)[]˜UE+*H*LvqI "J"$磛YrM%L-Fo_j堟zZ7^|w2NFNӱFZ! +ŕh[ %nA/r můCV_tӍpAK9B,r5pN?KK3n&6Y-, k)%՛z箴%.j@"JS@ec:ζăqPJH` }J!(n~@&Vap*2[ cK|Z(KpcSҞU?}i}J0}g½ ,`F dF3BOr(O§GnhP}/_~R8v唀xm,l -1d{bڦ \~* ~R[ħ>WyM<1;XBqDӃv[yC7*$M9mԗ#FKvֽ޺(2E#l֟z§rYZfXae.@Q'n{;1axi\#= A]nSvX"^)GJ\M:.뤧]>{cXVwDFCtD'?5%o\d9T?Gգp>|_"ШjKoI,`ۣݧ*S8edNVDɏa5ؾsҺk!Cmb5GF8 T%ys;uʑ:AuƮ:A, ],tu+E7Ca: Q,7@(F-M_./Xv g߂Vos$6醭7jzϊah>.\%xH8u{pU}1Β<*ZUIaöo)R!6 dl>i ,.WĈ+:ڵ+:j;8 ]'sHs"bI'Y7o0U+Dzu&8~]b|G=(!w*Z/2mB HH&tн~b)R399sUEIɢS֯WG ^ r8u@ QdZFw,wEdÃB։'4<F0GP@}#CGu~?A0/%ퟄѓɁ2vi#\l5di^>uE`';뒿ԋ`5ERҖ]rs9$˖RAxjYB!NEg9Qx&[JȏtUgA"F#D2`Zrzh6>[rޅ˼~Iߑ6v٥*|e2oAw/o}]y3l5 *^v#]xuh^7[]/;exszv1!>!J sčCT#.I5`ҷ:)+[1 *dp.(Tn#< DV˃&vut xnX>^>JݸM`~NK@1|=K%ΗX{4&ZJui=2w`laEfc:He{VҠie]-S6<֎ȝU aWx 'Gz>*M+rٳbWs d3_R 9&mNA B9er F_IKe!IɧG "ʁտN Uz sw/u42KW_|=_DK!Z:A_]è@]!`pQ{GU&&Tʩ-`Ñy} 5ku#̏tm-a>}o沙`+ɦ‰d3zi e-BUӦtq9j|*H ْخhy%>u|m28#IԹ|%7#/Q{LRvsQe񴹣C2#(oU"J#j:r1z_4sawH:!r~, L@@3ָ^?5&Cl^z, 5,t>+ȭ`=\ӕcqk]0<~/+aE*z(a{|(LjtV;^xmA_4iEGviy~I6lƋup\gںc+`h6k9卙*HeN/Xzݛזtݹ%d7gv`Mo${qojK9t|}Մ)i#Y埭tfi% ۉj5.^w ،)v:Tbp Y踹3(c\յ7- 1C>\Nyo6X<@LH`YE$~%R*5 CƏMQzo,FCpBQ:\ 0w- ^oSsyBR۩Gsl5_CXt~/%XDBa͐=ĻaA3GGNt?}DlM\Mi +r]/ѹ澁ѡWXaO,?sx JM2i 9E7s,"+\]~9}UO^b_ }z8`&abj0N2艡Veqjږ_UP^6Z,'3:w=Uw о`o0V M4މ5\^/q,mQ=3Luq~X mǗ voPXbd<|Wgz߂Z;:ަ{6t&i3!Aw&֩H[GUk+Ja:cwJ }03^%:`?F? QHQ kx2y򉵹wZPИʮD͓ kAZrx%+H,D)e(D5]wg^P#(3R Mtȿ0m'{?oڢ׬_? &o:@ =oej8mv.<?\ahTOמe*ou/w)s\:K@n.iDG&$3L&9jEDNjf{ 5U>q5Jk}(_zO< uY>QX؄ZoWZ@hAVvs19ۏWX-tyl> m8 COƧo ' @3G"C| x#(Gĥ{s-!DQ$0rɾ5G;Ԭ Xko_0pC55^pMG($8.lC ; G'^r-zVwȉ&CWԛ+73:_1l>p ܅5[ ~K/.> Hd~HwBg\<0=^Rmӑr10В[>#M}KykodXABNlNzx"j.᭾{ۭٞ̄H6,FXO# 0مrGМX%F<`E8oE9\ܜ"WבPJ=\wPw_E!]{ _Ign,V&V9ᜃPi$tk瑊'p[tϣo䱨}Xi Mp Ӥ֐V`xDB ۽w82k/,q0(δA#@%R(-{#KTĵb,ruS^ 5v@ F3]pҌ.>AH|gJ-shkS?Y9ڬ(kvؚ?h phAC=XoGե#ofH~mV+A]Lm73)5Ggøa,Mq+HRGj׆u~R d6]?sW~[!N95s%|oNkFIw]ldpɃ m <  9WX>;@h+#@R% AR tp՞&T@z謮m`hD#>Bya!06d 2#;߲ {=7 ?\AEE>Nro^”ʬ{m] C@7$]%~a V/3W0f%,3 eT6QXt߉̱g*sA__. 8Jl+G}eAaWoܡ/ff'w·"Ap9 أ(z4\&}ma&<ƣ(R`e[@f)\Ei?5̟B#嘿zN E6:c7GюO`\/OMGjŰpT\eYʧeC?.MxdF4c-E3vԘ/ !_lcqt x<~X (B ^~{YD2׳$zpD[PPiorQ6Z! f-3@~F̖έhċ40-sL_dT_}z^wǾ/k!dYTjvveZS29cx!^CtyV:h"+۩t[ds3ߋH(0R@<~s;nD{YW6#NxM}\B &Я-E &06r7"EBA_MP ËS+\Pgv3=mk l~jӃ||tT(ZH&P_;bhb4BW&Z[g=fmo~q&pՂ eE WeS+oyYV£EpB E -:gWK;p65*Ҫ#^(+/t>}4ux^MciX1adlkeTJkA㪾cl6Bo)uѨatP$:Cceֈ4+cg7j5fj<.wŽH>n}=Sqqj +|ئmR!xPUG rǡ&l[A_EǻPj_eQn,X,Ti~<3+_% HPvR={ 9%,ewCPER<4d۱YQ^i b.NWaynh2m\ kWU~4#z% q7˃2Lǟ\+s IJIsXϦ5B@O8E SY->dν`^Ji[@G="q_짳1}i7:m7y= }0y6+u;)}I>4{i [ŀ1j3%Ԙya*m}61v@|*/CۚaŶ3IHZ5䕧 /UcUG -%Xߙx/Dܨ: Ɵ! ):p<#K|("®qɈ)_!O 31Op9d|SaAZcisbe3~f~-I MCS 7ZYqZ$WZ:⛎BRqkKd5K.fg${Mfo0gVAp36  }~F mOheQO : >׏k&QI k+V8W*™B9TT#"~ŔX=BT}ON+3HU3Ȑ Gb%TX V{؏;{Cya34cYiʃHQwwbzT ](Mz(opQrIضl2Aϳ, c ʮ6yq,̭bd肾p 朜VBt jBmcw}6^{Zi,?-w$o[hs陱ᮋw*cfL Y[<V$E Rn+GCLk#VuA)uuێ+J1cܿ V- nǕ/ F\TQSrn)KP4v*4Uv~tKf(Q-×Hب ~\8n0\!k顿[UqƳn,#K8~_/"ǰc~RG r0fsوwz"~"gch;o8wpbx>`ګ% 2s3|_9A-MOc9.!BT=6;3 7*`]Xi%}3,K㛇c9W* ?r䡶mPW$ŝuA7Cgһjkh<aKeERsۺvGyD|wXPq꩔+_AYXA*m:x_N_Ti)L DZq]wJHhw~LnCq/Fpܚc+s@&@76|lgQ-ԓz>/k;bݨdV-{3K׷M!)]Q ,!9ٜ?F]aEH\籓4=mp]MD #dtn֎sEC6&GY)V?'Ըq0Z\$/lz5SA—ٴ5ş$01 ox8c$%ӌx D-u‹~Tɴf,Ӡ2_=;eg+Ȝ(n݉AiLt?G_–ZV:3TlW>O=5?m++=e) `ho)s;+©e6z ^M xȨ:NɁ}oZZPGQ0Dj9@] T\-<@IA ްxpK3wl:% Q@{P{Ŗ"a=D#ԄS£`xoԯڑu*G1@s, l8`ܟ]0>!avƫj?ʪINByOQ"݁mѣZ| T8UݐdwX]1gҳ1YIYu;WK̆ bR0*#~;rI#Kbeb G?+u4_{,پIzf%ên(>?:hn Z̅c߆61%;_CnW~e+H&y+"Ce zh;EnE*Kw xG9;eS,=khܧ =oxRvCNL,7Ei`uziQv:kP}{ |ur hć*(O"M :Tїpf+Ő is#J㮸ko-0wa0!ܒC&KhZ"8v'9Q@ lڙُl ߟfuFxv*UdK:sX cXķwݘ?D_C&+Saݠ,<= ʂR}MXshEJL@-7f NpDɻy,o< v*-OLm(*,p2ˇ>ɞĝWKc"U`Ng7nk_PR.F5ulbANK9qg9sTUϬi&/UQE6 T=wGgQ{c~O̅ XFW" xV9(1bλslqKtq:Ƶ]L,HٞPFK\ִuyAlm K夤H%rYn6JSzC*ug5ij4 EK B(f$VR٨p ہ80~GBd5zvU4Pr4/ ..7"/kf@Jq`4@/Asu;C>}2]ܔ@c¸QwEqL Vt_mүGS@X0TZ^Y֐Vھ5Iu/bY3*Glܫg. %䄑劣i̳ _~kywaH.E~f>1!|FTi0ʷ}_ ? M)AN%LX䐯:XLu(9i@٫ ,cI]P!fzj:r"̈́1`:"<xq-𚰆h/Ix)}Y]g|5ZyqM > -7ŵ-Rե?fɚᕧj}>gތ7 >cdzI5'vs!e:{d:xi>gd7HA9oցt6NXMw6N dtv|aYf׸^ڔnKsYPDžz!/1@{(#T&kEA.Bvyg9(LT%F!l5;yL8 e')NӹDmV+te8> .17o y@mrh:*M\rT$@ qyv>"RևuF!Y'G V8弇ݻKX{4tc?퐜QAIᱳ;R$Pb:2)mC>%Zf ov.p^7*Ț5ԑ7~D$ Y'9c4l[3F.?.!??ÉXTqt>3-`H3`fK<o`Vt(𩕼u.:QT{tgPfFFe~hi+#_>?Æ1jgَʠVZLt=RpE3HMhUbɱ5; UjMN!1[nHr|"ciͲ>]tL.l 5,X28yW,t:2Fc-TQs ~։BlpgOI5o?@&$=W4ߑuQgӫLyI(!kWNVS1BsȢ Ŕf0YڥQcej=(iSڑ}~\]>㲬}^t^A%r  D, +hu 𕒾(̗"XR5j 'ȴu Un L:_U~gf[Yၣsfy5DHNH-W +  )67r3O$TLI\1M[nTXv"-aX.|pjdmC>1UW.לӐ/T%BRU7 n9Dz.靯]F]l:QOO'iG8- fR(݉K.zfQ[ځau`2*( K9K5&ߦ_MA&Ħ{A+I0ǁ]^%HCECQ\OV11*^0zU#KzPLTLv53:z]Š)h-p{OW`qϽۦG;GL WM_K">| p㍤xӡ\2ZZ0$qSYU:0/K;#L'_G?/@.kNK$ZM3tJbO'?wor_ }# qLo~[bm.,::o瓗=N";^vߵꋿ֏v)ck~ _,o%QWy"$($m[_Vb!YY!K}Yr$L,ޱu"d'A?hB oͷZa_4Hh$V'kT+&ͭ_Zyb!TŰ+@oS,0[2ߜ8k wi4BA,S˶lm6i23)N[] u^Ii|Dz,@ P'> 4M24]e2`.gߟ^މ'en_A^FrkdI-z(31Mc>tD93<%Tw'K[XeSF7ס(CBlnhmiF)U4y.Q*f q98 +Lr|ucG>MMzfxdJj~'!X6%>mP/ad]rP X_o ōZ1LH|TXe VбQtfE[(.Pt*$}zd bvҲFn@g :zStU4[3C=Fpu;Qj` Mgp%|89),VakhTHGf V\~FW`$!^V=r7Xq%,݈Gتs"r+ֽ[jϺ>Ʈh,ϴ<^PAAuM~A|`d{k#duWwjӯ2{¢c[_X[)y^ȅ/-->dڵqC5B8%~'[nƦ 9y>̖>50&ң4STߡXLX房_}?0H%1io.bigXWIKg9|*,H=h򱻢Uyt%1Su('M7e$'7/3TU8Bc hbakd2߀.CizxW'UDKam3n !2z1b"[e e֢?dt+r@X9%[,K+V eO U-VbscO/7#'mwWɰ #Uu|ާNخ]66zcR_+*v`>d~[={)+ c_Mƽ>ao<V^г_pL70ewLU¹Z;-ASeGCʠk+xe1~dJGګ[nV&ET k]C"0#Mȗi@RU6 K+x_cxK>>B )q|b|ΈY.CRxɡ ԰%Ч!_B2Ny+H\^IR?Y^\\' )s%߼Ddז%0Mnpyx+_M"zEt!|ny `[/7 eiK=C)%fDz/;8T[ՒK^d-hb8k^AZ5ȣ# AJyCWeּGm .#..qD&1A;%z;7=a@r$d"ȾV9ٿmbxո -\'⡣_񬇆z)f4"r2y^ҧ )NyQ9` QYPb-‹FwQ?JLjKu/ڒi]QQY {:ͪk1[ɭ(̃_;Rc]gaȮ;n~Krnv!w>G=?O;q:xce)W\,'=}xʸ5M[q."0 t}0-O4IߧYK!7RF}Y# =diH9M$ma`1j7>7] 849Wy9dg^'01oOI)|(˨IKpao)9w1|NwTrENaKOp2iyOjJXQ{m}fbéI$Y<=.F.";r|aA92I _Bũ>PZ^c}Y'%n _As߉GlG$ [٘ےNr8$F /Y ^,:R{m%Յb4M,,qAK :DFZهILg"`*@x!~x-lF󎑏!s`pqQ7a`qE 4J\5 +ѵK62g;y(` 'X GtaەlrakKz]B^V<2F_}瞄Mm`,Rn/3$`Jrb>b o]Npl=@b:xΘ/e?;NPn.'aj/a:IC YGX1`~"Nr )奻F 7]^}n DNRhoa} 3t(},hNͼ}hI Ҵ#ZlW_Ė'YâI!2.(S1VJHkհT:bO;DScTJ V<}fn#s|Xx/օ!j[ 0cx:z"0T[hU3GYݱs\`6(l$]y]P' edI&yJ\$wϼKZLR jƴ=?p#âtk:O{(/9o|YuJK5r_fg}Gamz GyH4,U :*j x ǰW(:voI341P k,ƙMCjϷ_/y9#叱U=M&}4|.WhjvLm,N tw%\~oM!u)~1^3dx=l ?n9OF;%bn*ϝ|txwɒ<<d:}Vzn}$ݾo;Չ օF@qC7!DRSxq:̌76,iaQ_^ X̚zxX宕m_/dON:Eon2LTRb=4d<ѮE'/|HDVXEU+"7IPMz?ת~ݳwu4%Ŭ);nЍj|g<1/O! z3G-[=0^1TxsUb~rEվ%hsx=Yb ;?朁ji~( lrض#p##xn TZ1BxԻ{]hC$G]KWⷍpkޱm%#ibat,m,IPT#fm (G̮l)x;J3 ]4Mۗeռf*PfuRt2|ZϢʨ̎^X.2,ZJ nf$4iI7"h>WQeؙVЂuTNFDwq J{܁BJ߈~Y)<.8 99e@%+j6heS3Ez] (;Օlާld8/ ]*cJ5@ f/g% Wv~uh /׵:"csͺ~x^}<i$zyJv}7O˓o9Ajv[C]XGwC =u>N#xt˸i3 ׽J ﮔrF.u02fJ&!$ xk4| xOnwJIC5pqzS<&ֹ֛iցԊ'0m9D:@Hzۑ/\%o޽c^$AÛe,߰=e?!]ԎšXߎ6{`p}eWrz|]}i>4!|q* "1ر`AmY(0AG:P,l¬?#Ӵ]/ NƕhVQp-`nYpuH^\>{Xk3X 'Hwex3N3?%.Sm^ʦyE${NajI* biʲ1ײo%a[Wś+t"bD8ui#WN]o쁿,Q[ Z,w\hZj ݩQFkZg8ϑKbBFR|}k茏uyݷ0&Dau]jQH뜉֪78w4cY*3GͼG?IH>I*7rJ HC֫1P^CBG);"7)^%`^ GjGOߏȊ6}S@dApU/j{ԯl9X:v&%4Xy3qr=X-}ztݐ[M~ŴD|,W(ŕK$=6;g$+~#R:q}' @)g4/<^Amx;|H!Df`qG z;6`@v+E?A⫙+-k% Ͽ|C$cɺ[$ь/T%ߤ&5>)\;Kt5:+nLUo8ÙrH**^Fni"!%E*5Q $Za8|p6$f+̃vVO})Hۦ4OImĚ˺a*,*ɳ^ e>}mYv9?uHmBݱ%!$۪B=->&ͬHQ6mU [|_iDr`P360O~칯j5J $2- EBcӡ RM7^Gv|96dZ8?` od`Sk=t IdR3gdW|K)dfpv)L ݅{܎fV/IF2M;*˓I ' O6dֱwY+;tAer/qtQ]۵)%sr s 7&s^a1q^ 7~s&~_7lz&|a Pޱ@`5")gbL7FNV,ۛ0:v*@ qqP&8MwCUqW^DM/87wyztJA"6*"ٛ/`6q,N/ce![:X|К#o@noa<0VAۻa,iǵ Dv/5\~`{˾yq`} noH?;!Pج=3z'7LՕ۷  6W#v@Oou^3yDz촋f$sO@M,)VWp5 |teNEbSXL;Ҷ%(ސn݃1?xK] K^X4mvKRU\)8W${(hVJ;sko[7d&ڵ2MkG)%*kZ p# ZԔuj+JtJy<8@kc5GҫGXGaNѯ+sv2AhN)^{KeI(ߌa%q&ڍ#VOX}AP"O~.ne)Z˛݄8PD*p.$pViA. -W.c>FmYDetn:9X]ڝ>"F'[L|4TEOkjŵYxxϮ~E@vk7%oȱpc[)L=+4Щ_NIcdp 4xѶ4dy%%N()d#6\3Fdnhݱ+g!::HoQh话%MP*0x&lC 8qo'q u7ؽe:|]nԣ̚m &i9[#jeBbzuZ-R" %ޅуHL/ZU}O+^ taZ=cӿMs?{~>CW4c,d_9"ژiö_L.c=Oi>q#lL1 SoVz$V!ȑ&m; J[XD%mF])x%Sp+4^{0߾Glm`"4)n_PgsGF!d/bM/=& @(XX,1팕H|5$*W:".ו]:&nvP,a_&5~֟)d%LU`%Fu #9"c] ѯE9N@wuRrMOߪ.Wœ7[y>~f]W8^;т| I~C1m}uV`sEG01תjX\;) *;qp_Vۃ iRs;LT>I%:RcѾ*&Xq*-E" f,[k aE&JVP#%E3"ʮ6O8,pi7K?e,]&1,A̔Vsq/s:O.n]MaVR;KP/ڏF%l ՎR%wwuuhFxe<ĺ5(-8t_xI~^iiw%kohU爂 (q-҃V)dM;e!a^2Ƿ-RԅL4;^G-|iF٘jf0 ~̗YYU֨"\ '"~DؾuBsK&|F&u\JWsj_ :4b/z*;8< b/hD!RZvV#tOП5 $ݦ0Myi0%4qL."nG;|@nsc"UA``#qu >2;Ly-=-Ć'ivx*ۦ30_\v)mr>-*'5K:O pk./KobŲ4j6̶#H.L&@iGi7gs @2}_աnV_Yq|x&|R3d$B)>ƃ_ם{ߩ ҤYID6y;6*<[zg` !˓&G-*"<>;m6B!mD RjV=$7K3WıNz  YxpmN{T#lUEPH_/>gt$xPytRxeɛ~xvR\>l'dp˝6 ^nݩo[|}p:f Q|1|d+e<"%[O#ubkF)vJ5q6HwЉأf/ HHgS크#򲽵^vB4Ϋy-`ɖ BAeHQһ} EcDxzZFШ18'>2 "+wtK)6x0,)jbT՟[QQЁhRo|%e940P<&71 nnt73P<4c*̯M}d;!!ֺg^mhuϗr2 rZVʩ$dז..gNQ'yarI ΢6u?s=tRK<\LbO{3PҞ0YfyH;3sQfdYR/8XMh{ f1 g9Ly\8ސrBo#nmK:Xtr;Ù{If,Lej(uspO]>ug<Cn7g)i^i'lJv2^ vx3 yk0δy]p[ZX̴QJD ` @R8 ])!tbmʲ@t,*TàV:uR^"/@eZ} KkLZ%.DTj6: yvOy۹+rr,; Wf|L/j(2a_iL8mp _ךj*~I4bRP 8kV֡Z[;.23 0UG |l49%Eav{2k Dg|#Q4PVB Tړ-%Պyk v^ZqVޥj24D_ U)ymf 'U(ۥp)#ִdH6+9FU[wڃ k3K'1l6ދCl=`I %{NsPWB1ex:hKTvۦsz8hd_P88+#xǔ8h{&pm` <O_N'/L):?Ey6aU^k%M*Oh0is^l;=ȶpwiIs,ծ@#0TĤƧs䳨ۇOD )pǪ*{jJzs-pk6R܉DK!v1[5⼹UGgo"1fJ <sV(hOd==@ĩ;p ܂Aq!23d j 0l _7Neky_զ(|O{n;tUQ(D/[+ٓ@=a9 p'DXNz2z0؁myrNP+u}ggN͙f[ܵl=i:+FyRJ͞l@ `. KǮcK=s ߿~;&>YL}2GYƒO+ms7jnhb O`nlW9tF pP`v-%!Yg sògc֍(:eQK1M8Xߢ)Kz,?]H]J?StJִBCE(%KW5$.@׻_?h-𦎞)gJifoR'D*7llqMe S@ JQWJ65ֹH|%RGS8EDkS?*KR|œ/M;:}*y؅p@WJe^spAZ*%6p ~ |zʍmҺJPtmh꘮@J>~~Se/ .zuu 5/$ǦmqIxkˇWW\+g-2^rJ>u}[$˷n]?*LJ{/n1[=r1c'Ԗ_7;W覭_%9x [(g^"}r?L=?*~)7ٷCշxǴ,/UZU3v~U_>*Xa62~Gْn(P>eY-?A xdK}לEtu9Ϗ>$?__ IavYt^2 k-(׬sq?2<<\~RT>}{ucE?5IqaQ1ׅ~y_ǯm4~hBm[?wǫ[".Z E{VvCXl)ߨoV}_7DK~Ck> #/p߁FQq!ϯ>Mv+X\v'C[;|Q;kF?b!J|9*hÑsa̸xPkʷjA4.|+ i WbNKvUfD7<ڞ/>5ٔwPUTn|u4wiTmt#JꎢhF*bENSgԼxƚۧ3X$x^Tp#]ӝ#uOvHQu=+7f3HmHhA"t5+FurJ.B;V~q6\/=9@.tbLL6+.88ugi Rk߾t7Ǻ:mŶAIw|aB_dɭTȟ T~fLCOn{Zj+ҿ")m[-`Vz)T ¸GP,:~NswsSG{M3LSnc0'? 9윴 H|2vٱL{- :ujVNK [F +]dk#&?ܥnv0MsR |i#t哎ij3+>^eNS?cUmZKqFȝ:H)Ί8hvz} s\}}x5j1 ԢԾcH|^ˇo܊35׫8z;rMN(l>9"?Mx6ܠIrK-tCwKYȨ#dwE(1xe\ZWU`Ͼ."x)}RZ~r4:E!ey_6-c(GV7 8  $~`&!!B|< wC~W~1Mdݺ/*XyL"8A c }y8ޞUT]܎K}:|+,޾m@ax7ӛ]sO&]؄6QAD(Κ\`/5bͿX;c!I5?/>.(c pny6mbOx7qBjO3kj ٺjQ5itn Ӂޗ&)lknSd橞UYJBbg>{YMHB~mY?^K/室% "ȼ5VV)@r?;g͢HQjfZ%r"ZYNPk\gc춱q0$nn{[RXqzbA1)hnt军{&fNZkXt8)&TʻǷ|ZyXmybMyB!PHı,B,re wjY/Db(lop{LMyO(P Hg0:\ˀ<1l)j 6DR'|@4r<u;FVmޏ?Si|;~O[.s|wF3E7]K~4h7yǑXa;T O12@@WzWe.cOP7-VfJM:Jb$Fֺa Zr5ȆU6Z/*9;t [/5vs^Ϧ"f5ѐ$DŽEKjKe%+iԪR?qlpԻ[g;n}©uܲ)X`Yfc6ֲido4ke0-iz3j.N[pLu4ٌ.W|H'QD*\"8F)41(A ]4,ǠށAQ' JK bPg8D?#_A ^$q}t.utA{f64}]1XS_~zhBs͐34U,J>um]F֎1  eWϖR{b/hK*Е"R/A,X!`U+$| TۯvYa85BH`Za$`2kRqgtQVW Y$iј fttU]J OA(ԍ4ۅ{\"X? -uzw5XK Z Nwg+Ϻ[O㇧To^TNA_ S_VeBK8s% fۭ> /ŷ/PjѩKx~s>3J|&>OskbT$`J:Ф}X1S+`HJE zY E92hCCGU|Q8\DJ)MS۫ FKQ etTko?ťǴE&10fiDt+Bxb+MCapю= WlkÖn+fj%LǤ7N^!(.q% YT/cpg+ijMg.Gb[p9D0dSY4Ô/htzo,d1UJ)~rbX`tZg!B|zej9~#hdc)|Opp@>8'|]BmO;L:H&Z)Y.fD1)"&U53˰)+\.ǎElCCˑmoM%ekW ;#{ZnU=eTvUMZn6mkҞi]F{k2#O▪=uZlhPNʛݾudvU2Hg'}PBE>h-,!_݄|Gz@3ȇ1$c؇gp? 9Iiʆ՜<ՙ,S\#QGlݗuߎReH'>]#eYp}^t{Ԁ|Ԁ|Ya ؼ'<\&DyD0TZ4GzVc(3o1lMbZ[dCbX+al/#D Z6"jv[Mki(mn`={pXmBnmw2urHT]W=t(TT@ZLlԑDmnmC}4[lc bqo5 q;׀| GL\8Q0B_6XQAb\"(A[S E m+wܹ,moXUs!tZ2pE;t\;+}ŘrJ{2$l}1&F[ie\&L3)eC348q/Ê1 6xNrP% FMSJ-p]dYz#ՈHǃY `ʳ-QVzaRx&3D -}1MZS:6RiykV]7vfc`2/ jp_vXFuZa,+] w"mEY66GN56h˽Epk}n0B(_r{vor{TkfBB&V?<&e?D?GO^Vy3=ncNi;GNjDw0%S؃L^5; D ߄syE{F5':n#ŨS ]>)>zewmFo9 ff- d\Ba`T#)%&h[% avt 8xD"eXֺUxVq#BZ +>3&Vƒ[]j^g(^8dƩENKtJ^LfT-hS)NI%CՌ-Q(1TBecg8k$D,pHVbB)œqXEc1#_{[ѷ1c0Hw{" W< Y ӑ-] $yS剢,FEgO {kl/ g2~[\37W`36ÕFia!94A3C$E$)>m<m4ʲÎ@ZB2)V>OlDjmQo,b_mq էkչ7-ϷjpӚRUt4YfLڷUe\r (cV^v\KZ<4Qsٻf,椱E<ؠѺ> eX)Je&a]5~f+{QSc(l°6(5,r3+{Ϊg>oeҥqn^_l利>0Q /<+oE{,o6_U;= ^y+WWn-DFZ~ '0wI0 bә" 5 80 L-¡K-3ƘZá.՚+Kq ]Yճ%Ep0{a ەܮv,z[`.4Q,m3K,>VKa̸Lwk$]r+۝`p\ˣZr2b˄OVyWmRciFT.FEk~׮dhjSpp]2OU"˯%Ѷժ,ɜ= Y=R"ЅǘtΑ0 0&rB f4߰L&\6gp_VQ.Vo3HdN#0taa.BVkXe4ڀ,Yyl[>3² v>nrخ,#|tV1 GGe=!,wݨμu{;/QA@Mck޲5S3mpHx 6-̨E yjdÑItˆEvm%•E> <DW5 gt<3v0[LFZd݅/+8HEN:fQ5ݵASf̴LgN( iw!OD ̤ۢ?vo 6Qvkr'۰9{d¾JKT,ݲ+烶~5s2xl1fIqm^D56ǧHvEqE֊OghڎYJF6P(v\.$\z uX$Lշ+FB IFh+T7ە-96DGdFEչ> ƀ6ȕO ($=M!phZ15rÃ%ޑbjxYaCfPYP`]ɭw ]݅y^3)T)Ϩc1?q(' y&HKC$$ Dn.i9J'`,kbgC%G즙-1Odcx`L' :ZCc3TZӔbc[^{Z Cb~%y2;IH52lEy][tD~[W.9q!L4X4Ѹ;/K ou&U0mCb4תtwjӱ?.vݾe{")&حjUSnF9f.Ydr_aԝ^N}i|b= |^ wzNL{J(/!vQ<▙f,v+0h.{}g,%*nʛsw 𺞡E:Kz-J'`,|1+\,S#i͈(@@{@yEg{h ɐzUKl'͠(dFB؏EG8N!-Cz{8EF׭7"+L{"vAgLdvu'wT|]Y)RDZ̿A6;}/{ IYnAOAyod `ʹFBH?%─=}}v0Q 7ލ2 70SXQ)X _euUE[xWW QxW~PX%?8I'X%*!č sU8'g\ֽd. lp5jXNޟ_hrx|AR߉K%~ u?=q}1؀̑IB/^_$ NH/^˵u(~cH_6S~%-ogűJH,VWv+#V{$ '5yy{&iыmz\`;5zV w$(9`ӳ H m [#(f`X։8+Ӂ1l)t#B J@T>3%|c)fIJ;@xA@s)ƞюPT%b rɀﺯOh_M %2oqw`~Lj-9l)IGmE`A /Uz+L$lj&xVΕ@%Gq RoM2,yf O )]^e$FudCQDeirH- +ϖ=ç~{tCm r?BL*>xbx HbCuW Dq| ^{DC*CTnqtw_߯V"pX y%0 gP(:[@~ի@5#J =Ʒ$ aMbQ5a~K9q\9i'"W*IryxXP!0X( 'C^=ǫLAґ bQq5ĥ ?Aظ䠦~J!qP.M\EAh[+{{\(,&mϞ6< h8GM}or$7S ?6%(>`+}x>7{y (K98hlZN=R2eSx t#lpj YAGB@"?_Q2%ȕ<N rLThjֶ@r,Ow PL7J,A`+,NO֋$Mt?uu*\c&cH1|i*ӏ}߫:R{.t"y`>yx6QF^/Om(ܞ\Q5מڣn71lגֻBw-x=uλvx;5Q|0h_#pnr`6@z[XM%_{rOгH):\'$m/jWS}פ⼸n~Ҍ4z9u9 xP[ C}\o r>FPsOn›p): !_9)h2kw!1fǪ趵ӽ"J>I 㹍;mD80Aw<73@.iPL\bjP֭"Жa4Qn]խ">n$%AQ= xşv aXzIVxM&ӗ5Wumun@A yZU/P~|s& v}K/h_? _`%6|חJ@d"`Ngeܙ2wE^k'Oօ\YŎF$!:@1FZK9ldOV~ W:8˞ H@X}q`8Y۱~p3.~z˺FxԱ֪J tSM aڑQDE&(U- Ik^j>mEwN\7 DQ/;/pW@pO :FI}sP.0 Ͻj$;ƍe9 mO7O"='!lzѴhkTVj؏`({&1 uF8% jpE(ly:(>?/Of~CEi-}:$ik?n^:lC8!yV8oW!oQ3ԬVf(j.ՙ[쒖ofWW_Ipfft7W3πcp?is tRu|<-^&)W;K yyW̏\eIհC3/Lct}1±L"^kR5{d~WXfgN˯trj~S\ݫ:Tq~*Pon߿Y`zfa}P^ <~a}HYߣoߥyMj~{ԼjLQ E@aq UC/{k]]BGsȸ0'Q/NFa$<<˦pkMbڴNƽWbxlP WoP E6}`琽8}{BB!օG !sՎAN'th [>O%]" [x[ȵiv$zRݷnŷ638ֱIFG/CP:S|(|o]<f nAHY.W\q:=oi93*_1ef+_ʋR|VwOn^CvS^l-'P{ѥnեB֟A$"Zr[:/ Pf?\x^6Cf[YOp6j\=g|p]zC_)D=:$C;G$ }MČ` 6KJ8_= }1dk<@ -tD^*m:tVF]")8^_Ll< =F=jm7b]B/cg̾Q0#{TFd^ęUUTTF?hz)@kT ^m灮5]^VӀHޓ6-iݛKep~)s-[¤ۺP&ۭmwբwZVi\Mzt4ָ i gagE=*f_jV Azg{I"l$u^ Z۰!csMʛZ]*ɛ9j{og/sjEph*AXaC]i4:2aU + Y!k lf/J?0 9B)N<2cVP'27A6渗o>N#ԃ}@î^|ߍ~}"Th;Kv'l |'l [;a;6x~pojN͐|6nяJPah.F@k(蝲)۝)[{ulCV@S ilOm^xmZF8KՇ} -{2 K@Cwvmw,9woG dxMG0OgO?[ ~TچPGXRum?wleTvm%wvmwvma>`P{|O?u~!m:}-{Gϣm}^9zvmwvmwvm_6'aޛT'~i t!mm Yc(#oh]y藴>Hzmwvmϒsm~GYC!#,G uѕݞi}>N۾f)eסa?wIם}/Ӷ{o۝i۝=KΝ6 HDs`躏֕=?)DˁAoEafdns$Mgߝi۝i۝iKYxnZWFnT?mk iۇb ABZvdm?wIN] 靶i۝i[{umeɠvo~^*, fòtϗ+<%xun`(H>Ȼn/N]OskFkj_j5dEԾh8q}g1Okù[1pw|x_@lEr4Q[BeS+'9M&G'\YEPbYl=xi6wԿtyym|{Ilx7.)< 2"yGv<"X]`@$}SUhiGn6MRϵ]j4uc?= H=0ggt \.7cA-FK p̾VZJ&qT.J&V0}-_L Y;?E10!m8m+`!kA@`ݾ⢘uO$mAo uoDS J8ZahEg>4Fc( Zyؕ $Ȧ%5`;QIcC3X F8vs\R$ʠCke{ίڮ'"Y(4ݎ}q% hݹ,@ڕӬ䜻kRtt!~>bҢw6J˯oㅯvT۵I]rѢ~B\ۭ^]OQ`Kl:nJ3 )YOu0RaD$9RVPD jƈuZ}nNAbn68%*rB%_/vUw(\"6/oʇӉ$Ds5xXF>? nT&熿a?7ik?5\7!%jxܤh/q!/=6E,i@fi*/\IV~ cowkT;.#F$LF}H2pT*Lw :;ݣbZE)t~#P1|mMy9;|ïeOXC( ;Ā ; -ms[/tUҋ&[B#.gv!}hZ :K{MQiEM,v}옛Y%N逖1^DOh0ͧ{,c9PcE<67Σ-ϜKO(B߭#BŪ븦 i o"6na6]:!kDۃnVR)4OfLNjxx\k|#W=Z豏r_LSV5G{AA>&cpoZ'0` jTPlɮC10cXhoݍ&S mzp8р8mv$wɦ1H[# XN6iTF~y8BotF6 ?`'chLF Zד&ҠQutv򥲥 w1C'=jwQ_)ةXJA"s"`G8NV>2za`D|BȕeҨJ 4$`^څN 8 g.nU_!삵,M%Se!RPVw 4:dž`$F%ljS1f5崄! 'l&7pùV'2{Gx "G@-4>zr"Mz#bClцqD_ׅ /jt0g5Z&seFpzxS1%Z=DhKW+ z0 ,Ŏz :*GmXR Y/^Wd Cf̯(vOZNDpHȱlt2>!zQ4rle-p WD ;rQ]bG".3v˵1髫4^b~f/mw+U\!A[QPNSOhhVdГ4BC $?:b,ɸQjwug(4" r"LH)xkfAGҭ8mciȑaμ Q=cxN4P/s y|I&zp(#; 泓 1P2WRw͞ՃlĻNŲX8sh.v`>79(z+'I?rڑmIRI Pܶ}Z'D"=$o2 dZNdN wJ"jo 9;vN~lIsoi$sFHotモ((XQ fJ+QRi/e.xm oLn$D{uab=Td(KUC3u؁L;d*U#p.aA'd\B&-{ňSg̷@&_"r~\-GRdţ9ώ }!Тqfo2](Aeg0՘SpP1e;\ϷYw7E"@jȻ-,Hw@P⨻6Pb֯XQе< zMoAd̺ Ri+&~6 b^T g [5qdlO dI@񑏞] I^I` D2plVj:pHUHp2b"ʪ zioF{s`BX꧌րTؼOʪ˄JmVf8V9ױ-8wImb2ia eZdv`Q6,皸1qÂ֦:6ej'dls^t B퐣OۭQQߞpoSȊl7b%K. y  W f(dc<&dNux/uޘrҶx[zdg@lA)Xڎѣ̀LD='Az=?ƽ:dt4hi#y1ܜ3otdo2RYZQh<-/VZI?>exòaqHp>,ޡe/~ TccK4$F ҙ'7C #6XUS}jUf)f -8#3pp䭪Mx؈" 7c> Ӂl ew4 )eCS]O ^f[xP$TQ\yB`;_k36Eڝv椕`|0#B= r39Z.7GZ[ҞfaUdUOÀ9PG+B߫N]7msd/Z5a*p'Z*\37=p3tl ̏?ؕ]}#w^.%'49Fy"wuW =bԂF8ԼC |g9s=bANb/mF$SΒG4Ed*@&a B!z[/8͗@sl8im[Nԓ!;yYx1Ƈ;P<4EoAIHx!CY!WUkVmKn5D&uE4a!c5fF"٪}[~mޛɵi#P[B=TpТu ܬոsl,UFsBt+ lێxS\GO7s>  W4s]#NUVM,(=,zsK4ngO@@VSЛwEl{rJxW)RO ]8 B {.V0T٭MʘtP $}M&DIwy!7lT eز ۰0nr4:f&S$eEF$4SfM4(n~b sIȠRkShBPʞe ])%6KlNaIo4o)D *͡E9HH0[0s_9۪[ #Yk]`Rͬ8t GbQ߸XQt8)\& t"#`DlxයLtE1Zҟ7:},yCEv9nK`8| U)f &Ri0cbN%Vk9::{iY,tF-G}eY%SYvm&Tv,e/h)1f=u1 0&REV-LMd]k疼/7hXU2^G>*z6KךɞK4d'ȧkCe?j4+h=b4 KQ:W9G6ҏ]LSRՓTT:vu PD} _xwtOxcgapAJni_ZF^A_< P RYLЏT^Ps"IAՎMKhx]0&S5߬ibE['E2k>9)&xBo\_R\L*4-{#M ^ŽiCJo][vGIt0FωmtJw @đ]'Fua2KY 6_acsX'0@DUJW\B,>m<`-?nb>̣*' CA(2:#Dj6qUy u)[^^yF 못ͰDLf!B+j` f!BHlDFGaAHu5NbG33} Da;;u*!v?NO2rߜ )T$,DsW_3c򘖳4,C4INdlk,oH)\aQlCNˉ+H#AZd)$=2QL1>Wu!ᾃ ݁.GKa섗~ˈ K+Or >lpͦx{xo;jHQW !%Xe,❿ ~EWFLk-(b><+ %lyvr߀fh㈑EoN2r֤~O}k. SYb#Y-W$"'gy[~wƞ?}xhTQb7>"~ڱSPe+5W!`cIˀ1>ic=Kn9BtEU}ގm,Jx|#StB9S5f/<4HI4pi(*L_JUĽׅ%K߱yY1s4o!!83}DfJ ޮ%LHG+K$C˺$l|Ulܲ lnv?1gY[ܓ:lNey Hn>ݘ܄b0.(xIeipS)Cu7q%#(ӆ4j/C|36;z+}_Fo΁tFHј `9v4ِqd zt 7;eBwCI;ߢ*:`${0A/@?H5;9fBO"IK] If#3x&_ȓFÛK6޼{6o,\<Wʋ΍GM (~\_nHD"F'`D|DN/02.YڞLI9е1mFz;-E4| =WJsl0sٓaDf^:$6@Mf-FD#ʧw# |"AZ|kAe_(j_5HkihnʽUE[^2gQe^/ߐˡH"K#D[sav/k<`#g}7v@[4;*dYb b\t=I{`_ f1 })TZӠvmcOEϳDvahqc7odo+ag5X̬+0Ծ=ZxEkHO?eq:B=oԠ:t?7jp7IXjpX@96RV.DM (cD&H m֏LĐ.˄yM@ f]0800 sԉ(f9w駾^;+yC Df2V0-x])i,͓>[Chc?>r9dӠ'4>񅎱S obu4z<m$&p@|ua_Bշn{$eퟤE! VzߤqH -Ѐukz{E&Ѱqp x<Z^q vCC^{Qoc`w#*L~_Y??.,sH"`w3Ony&a10EnS`yFL4XMlq|SUUrS`pmh5?pU%qz(7O `qI="[.?  J> &&]T߮2-mnj@/{vaS"=_t~Mqvfa:Aw+RuVHff"@>fcm:]3FS6ưPv۽_߀0\ R҃ż7,b[7A01!\fy{t/Uù8E3>$O^gLvW3A%3 eb戀ք/H|h\X#KDk2sPqjIq|Ut!|.d~̺X.iD~33[8i yR5UtpB- R^yH뢾Ko (Yrd¡\,tQkTگKɿ'K[e#Tcip3MPcdߧn+?MW715u40<:)dR|}9/)~n5hTIGQz"e.nM.,d묯(Gec"?~QɖpT`0fڹUq)@'ϏŸ*1`15Ix3naۍKzicf/%[V> E5Z6Kɞ5^|fƀY94Ǧ_DIy@.rxݭ1Ǹ6QVGh%?z:-%_bz}EG~`T1\oRW\Zj7-db*j*;*]a2c'7<ٜOixzB]>H/Rͻ5b.ad,YwyHX ].o>cc!AjTSe Y';b?ew ;beɳ6CqܤoVh^1ɉRӇ0q;?G/ESAx Qa7R>3̟ 6Sj@NJey󰀰1XlkLqP)L`cCTRaVðfNRz׾km *Zu}֬,-w֯B> Tu/go3vY59֏+bЏn蕋j9w̕MK7E _j8zr( HДQYMv1H{«p%W)7d}ncYU]RS˵&YX[50R' HY":HUg|&޲61LMiwD١(Tyݪ?[{kXC%3s8:,xdkh+cK*w 2Lr\vz/8]_+ EtG=7pޒԽj 9m=as@&c[ߑ1C1˂>^ S Q2 2euC|: X] n*yn=nR/R\X"VoHץ+] p~f%9Uk\[J̦/יQ>/͗M9iEt2kɣ"Q%Z`ySz z~iԪ@Ww z{ xºbÌRtiK{_ߦT|jI/Q2_W`aPs,=1Dsc+P㮭&A0er/0_Yak~xUw ,|{v%*柴 Q;̪ۛI}_Q'bk#(8!W'5W_X9Y wFK{:2ǚyiҺKMKzp$HXۈ]I}{j߇Uw\0xC(34%ybqZT2( ! G73No1hWSؒ=uҭ"Pm/dBvr"jsS^93ы29X8.\ G6Xo&Ij <\~Kh7q|ۆl|rCm% Kzz46}ǚVS<0ĸVJ"Գ734:T~fT)1ɣ)6Q|QPD~ W`WFT9Kj9gRkϘPP$ʽ,LE)4|9(+=7拷{ķkr;b'U2=ՀO7y)^:\9ʴԗ-@O:O9ĀjqKtre>5˜(oz<Tֽ҅=i) 0S\1u{r_&Ǥ o*kzp(NW5!<<( ٶTU U=>fYMCuóv݇_#H}phX5xeKYG'E'RR_yoKwKLqѾ!{P_Ji ykY/KS]WJB/ `B5ބ"l4btGֿA /=/GWxܫ9Xq)sK/-5-H^m/) >7jΆ`oG4G9Rwr ;IB?=0KP]H}ߦK_Fȯ-6%wG3/z)"FJA ojNM60o 9~k.u H՛~q΢m%ش\U2VƗBhߝ-QdDT)s`64dt]hxh:N3?E [۾}g,WXjQ}\{AyqTsMEWv#ױĪ$?- a~Ow"'&zf @UUYU%cl2QcxkFgʦm-߾0ؗD؀b٠- >g/6. \r?\Xu'y+KxL,J=D˻8}!8e*-]X* ~>i׭.z-[A >>b˺f x=<⪺o*Y oUS7 w,0x dS\;d\ҫF~'ګ/Wciuݲ {Fn;͂^m@q] t_ƎLNV v:,&dc,!N ]4`LZpah-9o u =hw JpGИQ.t>L)5U]k.۬`mr}އTowW &g"T'dY|\ CܳC.FPϩ6ޒJ{/K2-+S%^ArȖ h 4wY8B GdRCrHKwgイGΒ]`k>A8,yrMU;m*:BhJTFDe&0؝T)jW4d x 62^6׾o#Sީ_gUj;~m܂#igƺvQ t^G;m~ }e0!!Ǿ$Ϟ(2&5<{#ÂmAw8|50hհ&=kgN~vϠE'eQOj]Dv 1qף84z*nbܛ]hj尲Eu@%'p;?fgiŵ,ը&qȥC@UkjSl_`?:kX#Jp IUõJ8};;އ9ͣ/Q| AfiM VA~J[ypH{qzƋ7s'Z!a)yW3_N`[0D._V6-R?1'qtż x]OD(?t!kJ&Jvc 'IiqrХ3?ÎK ߆[78bսKm;_5Tk]7A>#n#5lGKswFrhU KRWK0I:,, 43{ Dy[fFn>ZJx.vHo{i@ =|Ac9׮a5opkE^8qq#t_|mG듁{G9E?jƯK{qMOto\KĢ7W.O>>Uy WU{?$]q%wZ%5p81DDB"JџlN $\mb~(01`pR6~O"#.%KѻTRjkHj}1$6<,ݴo3OyXi%ǰBXD†~}uJRg*Fw'n^*a&:=KΎXzĈ(e9?{NsaxP?Gyי`e A)P#-|\AX~3z0.|ʳ=2A_pfϨ j򤫥U)cNFpfyOI&&t,eq'DmwGjOJj.|t}uZ=;r;/yyyR)` y ߟm0,pUL&IOjܡ gC U:G 2wl[-ΒĂo +Z>LRIpYahN+f;_P\$0e"Z)~4%G^B!O/D_CMH@,Wsz;-WMFe4@|]AtZxA/>5B1 .oR ;{:{`WcI cYcLsS[JvJ{-$M;V7HX-e[Α oDt[fTJ5d*M򞢡Fu۽`ϛ:$pHzi+yրMfRGe6B1eZFr{udX8>gcNޥwuz=__94Ys?F+w#t}3yZȼ0#ieR'O|b8Q&q^ޖ8 QEZeh-!G 0{nt.>^r8z85a@S*ިzƎҷG6'=>fix"XY.sruAWm z}_0YTV}>7*oW2&|G.+Ww=N_cPJ y)@*= S?,tӲUV7E]$? LC6QTZGZb^ <);^\igGeqH|o*AQeijWtqTRX$FȓꙪ4u֜ 1Գ=K@~+K5mgy &-*G2&"ݤ0 9/n@b*@{0tƬ;Pn1@w`F'HNAwJ KA=PsН5Axw<- Q,V\nSﯧTЭ,P Sn4j 8}%ߠ -~2w-)IY̲iG+=-@>??NME?8 L!_Pբ|),?zdUP2?,}ݿ%4z, ;[[b"LC*@c"DV j2sUN5l U%Gk!Z$ 'Oۚdb[dB?JQ s ׋uE/%bu x(no4ssbF<`yZÏ-gB%Nνz#a"I/6}&p4\)44B17ZТ$O-7 '8t%"P$ "!v!yOx}wڃ Y:/إ?E}{Ϫ}>rS#>z$r}Q]5Nخ#}ŕyD졿;X[a&m\H7gb S& \%;\f%`4죤)gKjt%LDH4Qbò9[O9ρ٫`Qb]ٶaeeVaW0C^H=aFylCf$"IpWK9l{9.`?unY ,T\*= [f,p`fvW3?Ruq|_i], {frtp&%II2ƹ+:.07tuŦ}@ZYj#ar/v Uر G~u&oqhy< ,8 C6oLm9[k ipp6SM_?7p%6㫈}i.cY\IdInJpiUO/~S #7o g{FLNSX{s/l mh՛ݶw\3 kHRG~zgzQ/:VҒI|P`o d?xgpKD814,ZWARϴ7ZZyW7tN פ[T{.RcƐq~?mK`VbK;r~զTb"S>2ifa1ʼYA-Ύ ^>5ߨOG:#:OJ=Y0TyYJQ]m{HW\J¥^ 㓞! _l ag8OpW X:R8 ^9E/ 4^}yMR1BWD (WrXHZݾCU߳͡ O^=)^JAV׿U~^iyҙ/?lvC3|83iX6a>Ό #d bag-!F< va-E*)Z5m6{B/ SP^ 8E_K|7"c+1=#+CdAˈi6B4fh)/~y:+ M[mt?V+_l>Lk%5Dtpz#ɿ\=ԁoZgwK;;PU{Qε-{]}{qt7Z25.otn%w.cNQ?UhF+l~{Q%{:nV0<9 Ek~)ǬU݇Xasbfx.%eJ1ˤSg܃G:5(mIbev|ڑP\fso[(j y(x}=zY+~_Y@k|߾@1P vaGcK"}|cflp!iD[ i:oX0}<ʚuݵDsI?Y>\ nOUĕJubT)aF o׳,|jeFlc5wKX=AN}{oHnT~9nT/0.+ósxϿ8qlK }O1z-xwڇwD]3uaZ!*σ/91#9C'^~{XCC׶fU$梥.p @kAsn"9.:ng\QWw־\)!f e|^sηG"V9Adſ>opIR s{fzS|yoDhi0Cmv@+ s!Zs/BYI!s8Nc6٪^0YWe bfndn.4!b8a?)Ey-hM.~eڞz_|}ǖL@xX{a?f6RBeeFdE%e4~>gsՐاݟ{~ݐ->15HٝpZLik&0u#XdLc΅2|r-^繾a@+@&MP [k`G7>@O?LT0N1SlϿJ)<GMChbM̿ !/?q e3%+B'tlK ڻ6)ic|6r T(("FY9_$qxK1}IF,Mp|T f-Gʼ%AВߜJPO9^f(JaHa T߼Ģ Y{LݻOWIAv[bx迦Ӿ2+#'<(o@3}?XW6nd# -+X+ ѹ\]ZI3r30Kֶ$in6 $i:-i߱UW-fFbCٽ7$6rYL܄3:էp8nyfu1;QF+/5{>lF`n!p)P+߈TH3و}YdWFQ'ٜa| A xC0y{*ukq6PpGA5{:~:Q8rsP8 cW+%q8HFt$$WCoMI~׆O8'Z4hwAxb*t*dXYߛߦ#{:h"rZsdh=;R _,}n{hFI tl3-5Ȕ1ӻvoZzwYu[AČM}PW.1 ȍү@ ӵB6.9/8 x^U8!rgapM28~&ƍ%g;Iإ>efMufpj~r;c8~*oH/Nm?zǬ@:R'o{na: -Dg|S4LqcTZB2UݎyB0u)uya.FZ~ɞi4R,!O/b~b7;Wжǹa)VōT7Ҟg<; p>rn7jӒ9(vC!1J'_0"gŝk.X>fAl/@j$1!Y_5Y0?on45 yʇE5d7.Jۏs4a YHB(o6iv+`@փE;nri&i|'C7p9S5OW;|=;NF{qfrx]ʷs9AR5NC*h*Kv}+'$ق p; skiRq\u1*)22kG*8m%%KOBw#[MVvWBKSݱ<XKX A_U |_iWb;B~wNSǮޑ"W:h0`Mi'%Go!\A?Hc*z{sRVXߎ\~|GS*: P0WH;i!M>ٌ-sn0tdzCvc5Q]@V7u+c7_c q:\X/` R_|W(8_NUްY&u͵DsO -9Q8^UFzVg I+D${~LkyDdZYFdleZT ޫKq网 RRrFKi%a4Loу4 JcS<"4!m{aL @jPA}"ѯp/@m'bײO*1|'W'@/Ӟe)/6]Z<_ݫH8<-MVo`mY-UÐpڿ4HMlsur2_ESb@df_߬P:$oHͻ%X`ٱ ՄI|CڲJkC}^ٴ<+ڦp>{}#~zGZ:DaffL)Q<Mo+Z ^Uxk, \ÿb_wTŲ~2$ׄ;w`M(\#qR!Cocf8wEPӢIhvm]Jk9A\ˏGome<5N5b1طԳl]l2ҔS~Eov؈oDl9$" 7=xR>S? %/C=VP꾋WB̈́YR{D^J?llsߝAMLrtdhFuNḰEIR^ψ=3 8hG_Ri_۫e2Wx’h9(dFK{YPvě2 pW:c T@tfXI {PwDfGbҢwt߁񔮹(~&au!6DM𪀌]153-t^3ZoAu¾T=üI(/kqZfӎYYTI _ZYT6oĹ%Vp'sw)c{Dš_ [ƓS`@0SIh5UDh;ol*`xDuVbtbIsg=`Yp~ ȊEBZZW@JskO4/6Y[QY7:9Sk]Qh;ONIjAT? G/Ƒ=ky1iI5O.[2칔(ܰ>iX8[^&Ox^C@cyoH;SŇ=ӭ;%XS AFdءh^C6jmat+*Ead]+("ԔZ[;U2D\  zev~!wÀ5\Q`un\<,j}YNJy ܫ%åh1;|H3ǎ0!ھ:6O%:05a*\h\U͞Ľ7{7`[Rzר}G WӬhIN$'>::0#ɵLu3lQ?{)̟ޝWY)|-!Z qxxi/:jEI|_¦u@[a*ti *Q3fȈLydo]4w`p#pt<`BejL 2A$reѐq !-K,=MTf۬`AxGcG"9*y^kbȝX'/HUA_=ODZJľhI^ Q{ݘ (~InX y$a \'S n6! Kl*呿96p'u~P[bڼ$9WeeBe,sLH|1u&Zw-\TO~0z'?6 9)h|!;r=Mt1#~4Wx(KȚm5 #at 2}>r%~於4~5͸F3HEbYBRr?8'''_c#oxZ5_+1f'&͏rx[m;ӄ+^U1)8{]9GE7IY%ZyEQt2} j4FRS䫊]\Nr=#-\-kdm=lS $Apvo.Vl9ؾ94D!'vc[nNA!A>UIS"~)'~3k3 SzQ$?}:9B.E8 叅BP-d~6fK7j'W>>TD{D뙙aQ7ExIճ/~8a)Et,*4>(bT 2H]%pRx_GP]?ZW+񶻬#W-ICmf0vo{w%er[o&GԎZRJP`%Zrm A&a@țl0GL jopM%JYoc@dA.T~O\NUwE $I :e8Ax(|IlO7#" h7nW(ON=)$Г|]Lʺ|*qAI1,Z/@fs䒿*W  ?Ft.`eumU! htx;!!w*nΙۼ1@(p]A|(_ βI#1|>77f峳>p| F;_ iI|J\ GM0Z!xh<;~#bFْ:{(\~C$Kݫ,FųH˻pHrS>.l_zA6Xt8~URyg"^.%ȹyw7!Nȧ4Fkho8(2ې^TaP?)R4reeR47P:1`4y};A FTt+o_ u5dg7fl0ԄZ{= H,w5TˎiU.BZz]Cvqɢ' ||ճےًQ#&抪p{8Ȫ[_5~H/䊔)I$1]ݖPrF D5o,۱}#E;(m!Zo_ER.RfēZmЏЎxߡKx^pxDȎyIu*گY.jqQ>1]`.: ׿Km־r_kml猪rJO 'wۖTab>>X}Jc>ӡ/<aY_itXI5ŷZ)0)JWU qGw)u ƥ/ײXiMouA͋BS(k|(ΓVet%K$CZ5_)I&5_n4;={)9>:U6 ;kgF*3z~3DbFuR؍:QiKXo@0d Tzڋ\ 1Mn ]L1ZPVԙӃhg(vhǃw pArRq)έT(0sx^n J:)2lS=#]:8G Aޒh9}L_}OPQ=?)/U" qD;3WEDPioUO ]C*h/DI$ځ` p>챉zf?[}߀6qaSqa%jkͩJ ju6>˯^XK#I"cQ\,G_KFIED G"wRŴ#˛2X08僫nf*WpH*dUhnt!*[۞7q~ L8 W JqoD@CN淿KTkv\-c,[B $0&.Rg;V]|Z2VGsEiO>1z2 n¯&5Oo}"wlz|X̭QmYmMѝVRGL)c 8 # >k-aД}l(A1Dx+k2!e,D[çϘ&'dNv}:GT#{llo'msL*Qqۭ=>Y5=P8'46cH=83m.̅'0҅?%ϸ,foAć޺ۂ w +3y`z?QMKm$5zxI׿˥ﻩ1ZM< `[3Y?|U-E p#M18"Ԝ/F[PW-J%ӝ v].)* o*t" sGы=0G'f|t\>hqlYy'7JMuA&-FΏ2 g|ȝŞl.k ]ܗk`m3L :H{e !<Y>LU߸E#2D?Ψ\Po q!ǁ1ƌQ>VpHM}QDND{[i7%C?j#ZmZsIEy\x}ÿjd8IzvMYR])8&FUBڇ6* 6-J'݁l;&6.T£O[eV:|SV7zQ ^a2 xPP-"d+tZ1xyї=b۰%E?tK5hhe*eJPa `}È"Uŭ'Wd_:R :dVIm{T;,Q{g?ө\J74]W5R{\<yx`KQuZ^bOHߌnC0ꗂ!yrA]#|9aQ'6y%eˋ\Zl-4u¢HF̥!WpE*|fv-_<[P"үI2cc"{FD2oĖ,$!e;;֌1~%$,XoHx/TIXG7B6m5 l )c4䙳7ь?<_gbr6h9JGYq6c-7҂dqkIsZ&d3v۟)]b.. ϼẚԖkQ~\Br1zԦX,hAq6D>RsǼ~aA}:-[*C/^GRT̹_xq :ʵ1'-vyIc*jF> Lϐ{MS΄sv2E&<뫊@U86xE+ 櫜n}KY0_ǡGYkac+ѴI_.FY#c4;C&lf9P㉮,hhkJ^#uGy*D*-}ff T(WC\zL/0ȟ,uR5kjςK89zI=ׁ`]|c>>H,q< } o,wn{pO^D^L.A%ˠB.e%%N;v<qX'BE)F艩)NvwyH7KkqdtDhO3OXkXujS aьA+9¦<a,Ÿ+{Oؚn}xqD#SʗggAUcƑuׄ MuO2ُ쌪hy]l>O#f}j߿C;k 6k=D[rE J@5\%^Va% `m>d t+*u>R|1ie'ˆ~Dra,8'(N}JAE I>/oRY((sajCXžq+g9(`}I3:~`IAX]?떈oE88Id6:?4Koƪy5V̍S }aFfIn͂$; S>C! K;S@44 ɜr+=bTwD[NY yGWk7۔W]½7`[zQ3W5 ! ^더s5mEe58K>Xlz ˄'% 5䣸C`$: )O^FBt KZ@1vX2eθX9nm}3"ͻ"Ϣ0f{)xHޫ 2aІSa\ ϧ^d\~xYP7 W:RO [&ۄho1=6nzr))rz_@ Z8-W2XQǯD}?sS_r: X1XR?|O5ʄfs]|2 +KMӔy+e"1=+'?0rwlDJdI]=J98z߰}x]mMI4w ˿i`:`;|.t`e%9!%`8gTOǷiKJ8v][5P,ɃЍ7-,0`d-'G|q:Y0a*lNV64\NT-&Z9GWN Uq Lbu3'e.8uId#_ѵ,ͦ(Y`}Dٯ5B.R4ʹL$!l4QdU^jϊNߘJC Pn TSFiU V\[}OLkg"XVo}䂎m0LEDŽ46D+5b"rY|od zFFbl~l }.L*9S )- ɺaqi>>$UZ~FblߵuƧeK%5gӷJbD_  #IXʖ9uΕ5ƹ G%ս+AMRuPm!=fA[R٬s4i?k^ŽY[̶pAG '}U ph#ۉ*z1 ț҆A51,~^g+B{B͑0s'+9Z("鑡 <9)ZX'ۜQpjA4; W{!1(] BDf%%`3hi}Fw6H>Rq~7)f\9KTN}B$GssJlN8A *Ń_)7B){bBzNUk_ɍ H3 \[yJWr d ^d@3G=8*/=bu3FZ}p0٧ }ekEO+0\Mƃhg:OǎyE"@rR.΀Ym̥Nᛮeu^.xYV/O~f>ǯGD6*ʻ"}2&WN# 2#jdؘlStSZ;|vwW\ECzm<9ɚMV]`:\ϻڐRnHB)GՒiBm%=C 2T#9Q/*ڦUiyԭ4Y<ɪHZa1O\J.$Ή7Ң"و\!ܰ ?ܵ_d?rͯX=<QyOoRrΧ_"c3j-W 7jbeKy jDjN89[OB2 '4!r:ٜM%V*1_1qtwk/}۶=(Z"*YGjS{3 0r@RXi GƝؤNtXE?P^)iML'_~A%JV8n/ u>_Ko{n7c$Wi9AJ)2XGj2Dy7C9 sxg坳XԪ3xv\4HV) Р:Yxyɇ(@Ѐ֍sPkz" 'Ok3B1߲lyk7m/lևo+QmwCEp0u0xow+9\j_KL/$tS7vSq+tHjW]>)W/+;6pұDO&Lkwqg 2f滈τ)(&} ^ڠW[+do0׃7"VXOH:$gBWZ{VcK(FlY'Y qȺ'0ok(˞y %f^ƀdv.U/24FvP NdhvLl㩂 R~ 2+,6â) ^cg06"EXl>70t1+$~q9GwFݪ1 ͼ~a"bϰM@6#-XD/βsb[,-=:'vz ~Q]MVkO Xo;Q~W\dMq]2,ġ>x̚32=bS*L}Ho$ҌN_-1r|EMj2.y-2"H4NKF[ ;z&h+~d_:8Λ87=n& ,D2GEG^\)r{.x\i4\'#O30rĄg^0M8LLMiuwƬZLjIxRk/SAavy/\L*Vi>]V] )m̔!Mr8V 1Wo&\TdGgX/WH!hiJ,sn. iv6EJ Q aҺpaFoȉ1կ_Q `n4L=4cבo1v^AdY}h%52%N}q"7ey@O? H@yFvv2@_ntt`ܰͪ\@74^$͜kR./~"ȳ#+ GM^j^]t_MypY#t-BEv YAJrdEiMWϫ]ҰȩC6m<{H&-͛7`xZ9|'Ӳg(rY2 -q4S3@0wþRvHdKQœ[s^{cGĬ-yRw9B ]Df,D]ơU}HM)&;}M1eVߘ^vwɟO{%vUtHs%  H(FӺ4)U̢A|A;Ƈ @f扆$*Uqsʍ/SdPnErP$Jl!QqRXJΙG_6XYE%R0mIO #^@ql^{gT duRz:~y 6K "J&D`HwH$}UѯʖCyډj9QqyO?h7ó~JG m#Biz)JYt_>28hQX2Iu1Hk)ͩ} CC GI1z;fskL<{`o_xպO|І+T8q`S;BpggCjwЁ3ȳ̅&ۺbH;I7¸n*#0)G~o4y:Kr-~&u ~1=LbaA´f .zdHjQ<`fQRͿNX\uvaY#$*&{AΆq&XƩ А0m^+}e$Ώ^PnЛ_x`R]XldY:ߝί/+_L09&\w L299s{LڑwaI)0Oel+-)Al7R^X >(DxDr&<}{`&g)q;]%3 }Mde_h>gzIiY–oULEVXFՔu,F"IڲLYV]%q]P_i50;NG_vwKK?Q3-[U%]L5^g4%,+bnƓj+Lag6pHr(t&hL6GyOűG $k&&Qa!?- !Z'ܻ:.,1wE;F}0f$]m`IW@r"" B u@l~亍Z)b% 7u3/R!8ۖ)DžoaoBV% T;XR:e8Å^)&Tɳ5C$s]E|$:'!c_*Pڲ\u+流%Dz0?81"']TaͺwD1͓U+Ym3/-!l+3 G}TQ~_\us&0nϱ.,bzZo7\߿}G9i+i`sfpzgIq?x"#a%߅uayu2!m'1|cw 8H +W[FK٦NȐx8xװ)-+Gʢ|u]^+_yo?~{>^FAFQ;&;ɖLA NC 6)8H4xkSr/q[tX  p`C ̶UAN䌏x`;p- Fn *E?tw);8s0dv`1n` (i  ؚA8s,PRZ8`I``V~  REE+4L1iy嶇!6\[vH3 >2>ѷyEw &KB/qSZ&la5,J>|N&ơk@ " %Q ~  IN7: oDBn ~^㍵gհ@yew^U"iZ~YR?|N FpN? IS d8~_ $S"iVb,;[ 锤/Ki4'Ͽ`v`qa 5!Y9z@ˣ'(U!`JUw8$mdFL Gz)A\yڽ=_ mdQXy3ŏX(D l?'v"f|< }bCDK7J~ijE>9`< $M fD4a)0 #7 {~S.%%qF|5Jvd.G0#9ྜྷMN,!e%ޑ_EipyoVπ W2\cិ~:}=_S! FyQ *;xR L81!%~BiMٮ0JSJ(io:|ɱWvƿ@kǙ P?2tv(H߷(j;ܗla= :gp` $O0`.|hI/]w;7h'߀4ɿ[錨Uh.}F|]B=AVDTN'30%bGJ?.ZYQa2D:Y>{pȞMI7u-rx4ap颲NJ*F}ۀ%_| }xr}Ij&u&a.dؐU-DÓf  w}\9=+.eR2{Ë\ W !PD!y+o()*P"]}M>❗P:;l.9S6Ehsrϒ|%aܚil +זfo4rCdJ](A*?;O&̾ ߙ(e]SQbݹl ?cV~Hf1."yRޮǫ{(])xrLM(sl嗃O9,u*J_0|;X*rӯ0ʶ5qD!+;Vv ; )zmQK±lJqkݜ FC𾝶7PޯT~vy*p>t SH拾Pv:,7}co z@:U2Il?c=J;p\A6ȼ!hzUT"(ihIMhu%>l DY_9 \-̸E HGکBMX%iľ1/6d?/UacBz]!h;nL&s&}NĊQ&F]$FC!=y1ȽLv{86bϣF5=MT @-04`Cg>=b /ќ`b; nAM{eHe'9Fd9.`<۞%qp'W#֡f#n͍F"1_{n79p4WjO摾1;?ìGl?'J8>p;*NmnJȿR[e_PmѥٻS-)7+4e)auƤ`|ޟˆ!Nqbb*Y5T<k=G)2`{eB{芖,/X?R6VmD'RքxkTƸXw$ֈ* ahc.6Q33vvd]0Kc̎vœ}EC3J9'|H[( kK$8ߒ˝ t}8 }jrֿ!΄pm?#+yNI\gN TBOXʏJLKC9m3tyIy7n̗]Qk_BX/ @WƎYJ0B,p9W[yuFښׯi.`Cw+Ҙ^%CpD>/,T Eo,Ц0v*reFH>p1[{(6'5HRy128:2D#Z{쩽6N`]J,VőkbYHHwpFcASNrN-ԇ^$'P#hSt)vE叡ni2#5 ~/S||t$W@:7 h|)^]c\W ɝ[ k=}%J.ī+(zU $+% \ZQO< "]WyYsKRqnB2ǟ1Ō})^ zwwq| ?Z)DJ Bj|"9ճt/W&/Xt0r"tX~<~/cfE P/6} Hׅ/cU|   {fxA/sVWE\A2sW\-Ćv,%Gn?I5zt&vsV| rl6}Zœķ!LTv|+Ő_œxmI/G_yYLW[]LZ1,FBQ|/gS61 lA1(_HFyچ*섚,(b8CyX~&Y5c.|JzZ!TF5"vO95 yۼ:QѶ*c;0ip#jbO$^3g?vt6@U>VEbXSV:]5/}]$PBUKA8r"%($VpH03]:Oʸ<8?޷R"P\j 0p;#oyOQZEWިYydvYhh < )ifAR7.VU6.s> w"L<-'T1ůB, LWפC$k3>k|uu04x|WtS|6"(%2Fb{V`0PVu3FBT泖ܦw>a-OX, 9!' @ [oEqp. |v+(P(0>v0f;':nl3LN#H-Bn¤}Ah5зU{}:v9[Mzs=Hԥ4\$ZaN8[eEV8y) jS6`? 1)4hWq!ConL,K1?[,,Z7z] BہAU.8ak1DSEz#[[9 I(yT(fzX[G{I 5MvI{1I uh.VN/9+Oi[`6e_F*] 1~8usu`DJn\l MΨ^eGobBm@c)w5Ov[ޠ2h> o$*/tnF?h3(wYn":؍PBR73,λgS 5Ƚ!Fl$%f0У-1*v?kӱ Bn;-߁ -!fOG9QʵlR解5/2 "y扬6.T %BmWhRtDA?"#  STfC¨=P5.N/[(;$FEGKk _x !(LnhSH}0؆JJ:FMV7U2fmY04Ov͎|^9KK-\XEH7<yؿX :`(Z[ dЦ6*}5K#[ƭ_P"cb=XJsHMC m4S>:V:H,n\(`qsxf~N?E](pA4lέ)>S׷Lz'Vy)՞Q٩c3naӿύaOlhߦ~&#^FSZWQcFW["PjHm .ĩ*`S-'UqQY+:EjgPz&yX}< ͲT{ (fF XkT pޑk{=!l ?{˜}$4d=[hwezP}2C +ЛBNa Ґjj%ϻ/4TD7Q3Ȟ &cem4f6`a]#:şD$م0' EoGb9WJ@/ޢIS^B0=wI )&8`ݣ3EÏ\)yecS{?5 ܲ !4v^ɔτu@Sj|Іv4-☙zu(>hZ4HX0J{SkFAȢi>jF.V3 ʺ-* lNP9;/ /xI SL%xjS_:9?[Y ߠcel鋱py|!̳ŞaԽ,)`1Y6mX#ڷ=}|lX۰Cm3Y!uʵ0r?y;3R#CF觑ncJx=݉,u+R2|+t[eK\ ~]vTݹU{#kQ{mKx (dC`cv"Kn@$UYˑ 3l}t &&zFw~;$/^7`Re{"KS8"5/M*x%s1"Y5"bHL$N( 7)2B9CzKh [8֪{|6W;'~+4F@B[GKڒb){ xd_x2 |ɪ'"1{*j)?h f JY[nS񮆖 Q:Yiy)eimFU2;q )vvyp/]XJ]d+ΝnRT1u&BE2W +S~C=zuCAEu1c}$y1YH/-iV*D+mf?CM{f9Ly-Vw:)OI^P oEJT(gy`Y@pVSȯ<12;cThrK1 =4xsde5^H0Z3:tPc"D`Scfe!/!2wK\ٱq h7xӷYdC(1t3_R@@<z/cK@Ü ՋtRYd\RާSoΐ&='kp;bbǃz++:#ϾnZBfukf9kO ׳!SMZ%w[Uj 8cw@|f*iðw=ĭQF"&'0vBq|ޭjyHckԄdc)M@CU^IU 1{L+x TWa4s_nÄʌ}|y&r)݇bŰ \9P= a/!eI݋ ʓ{/_C[2D)< ܪJ1#5y7cmI!@xH)בqN-sAւ`- J[ lmG{[q2Cp=acaKUcҭ8KhdXhS~ԬyDHodG:Wi.ˍp >gXmLf7njj_9hpY{^S-j 6l;(6[HVSxք\ìXw)%W19Gan&:"⌂ϗ۳nWIpQSgڸ=kFoR,s-S` HA5qoQt'2)+2CwGoQFYGM Eh͑v^MgxH9fF#_0.V؋0[FP>t.3RϕԷO~zj68QՅ)>츜5oT 8-2֗^;5V.KQadA&H=x榛q KHT1ۘ $;z;܉Rǖt 6zYѝ=zm'c|LF<*뼿&_@goۯboZ L[s ij?uITxu:3v8/MJT- }t~AFs^}wcy u(\bW}0z%i_KEyOTC4DDJf~% ?֨rݭ[%ZEm94eM܁{hu R*X]s(01aLyޘnz 1z28U@S }Ɣ/,M85>+-" M3Paފ=.`'(({͊H !H)uk u5į!]( )3(1 ܭ&)TxPs#+!hZZ5tϲD-n6aL.z xjS q,-N=:wmݼ?vT[a&xX{"`b kSN_jAUbF*IͿ["]7қ KLCʟ^ۂ]iS|5 ٯ/,)^DhCc hGfXnD1 6.TVg~ҤpҋD>ǵ1qfUQWXvX x7̄Gx+}q;::Z3Em\++kU]hrt)꨿Ijd+>/wt2\nk8 m]{ܺ"\PT3= zWhN9>n%2'Mg~ᯑ*@ޭE]`?`S@= w(:/~}<\A̟UMhv8؄5~_DVB1I;= s,4Z?"K׫=rL=gˌ}9sڤ!vWM3o'Y%٦v@q^֚AgDi {Ra-JIYjiJ¡-)qj U lDȢ?gO_S_ }&' 2Cz팫?bY3쥹wwoﲃ:,iQ 3=YUQXMNI V(6!skz={Ӳm&a}sfN:2)RFCDJ52l2o u z[er68vn$E`3{E&!txua<_z'gTpVO46G8 'iMQrn |?Xs[-и;mEzăζ_x]o.HA-W2k&s!p⃡||@Z^Nh7#( 3v/*׍ZLj|ܰfM2.oneH?C{d8Hlfvji.JnEPyT h'7$cD-9N5iBT79LBF7Txl#yVm[׳qxXtݴ. 0Ӵ5+KҶ /C8Y+‹~p_l29' 1o/gL9 aqޑ0E_,(cr房g8( 8Ap$R:Ə%?xI"Aw*l*D0x[5 =¡^XBw_"g[oa0gYz9u&qfty3v#VՋ5.d"e.KsN6hNBO/kN5b l /z?Lu X}Knjht_ Wk<=7Ė,V1RWB+|;T]ui.L;'di1}0̊ 'nT-n)Dr 䡜A@R}mL.4W.ɀar>EВRKg*D/{+b#[4葾eF ^oE_D%C}#@S@O^ZW`Zs..4꧹\zzZ5n:~S@>P&4_f .3Ӷb%džLb?DY3"d) sǖZ![qL֌ Kd<8a'DȬ),(RqTόhH`P os#g|UiW}xg-1ʱq/U\x/Ay9})2p*rVV* _JUrt]XK 7p"-,c3^Bm]o325$?O^:7n/pMvLJ^38OJ>AU 48ȅܡ<9<@D'Zki,##jȋFU%?ٕ;Gԯ'vDپ. nP-XD^;^hiGi$~jn~!EFmп|̃֔;9)[q0TG ,[I ),c!b-%[ lsbq$/W|Ae_rskmW>%_w(ϸX5I$c:Hy09J Pp~XJE_TۙhHpT#3Ktj e4SYO;~l [lAr7LŨi9?ۋ$y2\Gڏ9y+2e6#5h X|x2W;z ҽ 0x{Zl#G8|<ɻqݸJȲa^ ??̆S%^=ZTlD6|u"*yw ќx N}E,`G cƃs="@1⇒|TS9xG& 2/ja/UW% >\=vwJC]mӞ|/_/? Ǿ±]>^Ö+h{ ~a`-A{!DtBwQ-°L=Qº,>}za` >1aSBaW8aʅoNf&d^Y+my98_ͯߤݷiMcd0[@/J^)ĬG8?ca2Y }8)#ym۬tu3/3y'T'Y|ڄ#HFnrv+un.H5=]@5ecizN-9J=nd)y .jYÿh֐1yk8E(@SFDO=e׬>B{I9G$Ry=c e=ѠfpQQf$ih`SLX/{~C+ٞ9u͠~=X/<' Rt*2pH/u׭jG F`8z.xX=m,Q/ \`ҩP};sF* mKSj3̚y}|3łx0{O 0wt8>cLU_]~\lL2[{oM&݇=`aODI2>G2Kʃwcu(}P˹<<.QO*(Oq87Xcr$|4GW5!4SnŖ:jrRw -dpfA Jbfwvjq̊s^*&f f.և]h߫I;} =@(dٱGgWy^mo-V>"Ul i\Qm1-[ '9Ym aQdd EVZb&F~\=2]`wh`6 a<-pO6 ӂgxE(Ye[N:PC6F*WLxIXz vg-c_Tp?: jP@G&|0G a@8Po@Ҷ?K3!"yYV ?p.>Mc- .xyQ{zn¡<_W\NÒZ,6LT,ș&̀#7*Z>4lr령Hy! P9}BEM4>}J9{)*i}_@.Pܠ$Y~0bAby NGX4羿 ns3tbD'=n|ٽ|EC)FR bγՅ_CP™[@⢌4C_>N^0HwH91_1^2T u ~B kтDw[JnA<4CHʺ H7 yyofj zT!#r[/"ЕDwM 2EϒmES/Ҙ ۏ55U&m3N! v Gpi8y>w [+~ؕ|7= =~"e%s }EeuV;_>vX ƿRP;<ŵzh- M^;v0zζ'-<6?hDM'lhIXXxYܚA*zw% Se `v^&K~DgnUK.Phq8G̑=lge`\iwޫQIW/K-@g-B}18>c%-7zzk[ڙ^#(h)@rO?H ͟"8ϐ$Ɨ97JF. 5ce1F̘<1J.T_X=3[ɪ( mM o A MH{艅966QG7 /s_S:'T2\ֻK.Q7ahBrajVΏ\&r*%vO_ ;%d3ߋ ygzrHgdҟ :$V#$e]TnP,DF]Hz8nMdsAY)!ENK9`_J|`< =id#=Vĉy~0)ǁ?妣BL 4L`2ч5ک83n`tY^Em>K2KMRgֶRtKx}߿9>\9K50K1~F30T8}'*LlR1LپmSД2e*X%lYlq ycV?",ڊ6 Ӟ2rSy@j.GI N9w;C!JZP;AZ ^NL0 S3Z-&|@~EMЦCu,GwGfp<|=(BZ ]Y( Vt%2m!x[0MQ1_*b%>J$njB@߽`d.΢HmqUx nGTK-&94uYy'^v~p"-r+jwC毭"u%*ivؓA>>S(?Di&v͡}).[b' [&ƭq/ߤO'@,hraydŎ8  dd NۘaUIнcfqb'YbRhdKC+&}JԊ~:8)~Z"Fp0(msp] >}wj2e>>lmh1f͇/$~X˓\((K̶s\s[6ኚ}3#:rCM)}-UV<53^OEأ]f'OuP~ /I>l 88 A溩l3v;)Ƀ do,:#p{c,d}zMO֛Xjn]2T^굨pC&50T5p|x}r@y])'Xc:yMuL/ 0-zr+ZGbmSD]=qHwʾJ [x)sF4}HI -\-pJ,GjvKu mSEsn&~/A]W5j2~y8A"~s$nZ!m׷YANoeJŽa3:Bi%DJ|XR^Nv I4+̩'(l\;7:FA}py7k_Df渚.MG҅em͂E4`kIln)`\Mu{oQ'Z>mn pk.L3bSG˴|YM 36qpRf"oe24 K`vLwﵳ=M7nwOd:6xXR:09Sd̎ґ܀}XHk굆eHA4DrT\^.DTpD$0l9g[bMjɯM f;E8•fy'jJ>pB\DJ6eKM.pRg\%ٶ"mgN`oلfw7j0ӆKl{G>Ps>y7{{.nÀ8@&08'{$dg!DJ@M>Aԉ4D/W5\Y"a2PL<~JŔ܃ ԕZdd:*Pe^=> Xfs9M&2ܭ e?;h,ÔbH䀰j~qïl;O'$g^}R4'%6ZOf,}qޑMeebyq\ _O #ł>7GwC)JnۓB5ʼn1 obY:+Ywt?Zs\rHsD[^%Zg;SaVs>\rgI=2$\93?n@+=L}`e+z,? ˷j%cn!j'(cg-^c|GOW Vx$ UyH1꩙-ǖ#!wWnSSs5s:QM倿va]^!+g^13T=HX*cx2d\E0=iyE_{|\`>DY 5Vj{r0bVgeaD}cm@K+l ZmeKVsx [/{N7xD QU[qΨ xUN%f^u6kxX, gM е_%1vL9p_D^/a^Zޛ1~Bb:OE䤰9O[dBrWo۴FlZW7=}ؤ;wAY%&ToW \:;X$?gnn-J]%Mjs#JIV TDbKsĘ;$h:B ݲ|n0%,I`By+%1B[#uvLJ]*8-%!ĵmM_ח4!<)!(aN]~P vJn h2Қ*Ƞ[N ՟'v!~KҘ4q IWUgSCNoA ,FpupZ)дMpKwAwQ~C5)^xj֕7޸,/|TXri=>>e:!V.We}Nȭ4IH~px'gRhL7Sl O2CG;C|lUkJSͳWƻ~>Oڬ_); ,zj urxP̯#w{{P2B Y/ }FZ UqD{>1h^foӰw$gp$=vvjMk_XuG(#*U/`bR:k%'D 0=~1]gj%CΥ%C>=؂d>/ 6,\5 /*6 suǭ)ݍsY~q!$ޒ("&n;Ψ!w.d ~ Iڟ5Ꙭ3Z͗z\_>m aBUK6!|gtz t?y -lKfХmuQ'_ޗ-}{]÷XT^cVGtF:gU%xtaQe6YR5apyQ%iqj/)e%NڝF4 MoKO{Dv1 @W:n"R[,1KecP*ׇdk߂j=I&D?tiܰbA?s3;R#S&WF>et+ñ`bkҬ" تOؕ&w͹BoǢZ<.V҃l*I5sOn#YjddND2Ko!nj7ĚKCm !Sa+ㆺ}KEbiT°U¹Yw 8$4n<@`e QVi 'ܺ3-Y2af(mE k1UlMUXh:]]~+8k! Yp6]!;`ސ@_)U^ynQ ܖgqN !gI@TJkH<$&_&IXFЛ!Ņ#gˎf؈@gygo<ԝ'3_*HB F ?RS [4Scm ^݉Pf  9$( *W3OAr,QȜeATP3Jޢ/`# ۜe8rM6?~,FwHA6X8sH8Za7}EZ|۱4^LA'<#e.ok@Df#lR>5>DGJdqiӋvoG;sm%Wi)dE^gnl9Jj+0 6J}G,5@/GcKHb$0b %>_jnk7i"\E eAFGsZ.6_̹:r-y#M5"|SV58fyg]DdtIBЋT'FNL)6}>ǣiV{ utWНWw3?LCU &c%8&l2eT=^AUՃڈyT;? \hOҡKq XfTd^NY4|/õSãϷLѩ9SEt(5: kH#/QRЍ_W}Z>}ni'k@A^-%EJև6vαU)G% K8Գo;D"nYs{g~T\m2p<.V:'¤bk6=q8^+k:z1Y4Z$`x4qm=KE&_pzsK4jN+W_-^lOܛ7KerW mt,nK^=?U{6h4`au00tSfU{,p%Uj':{y<G^-nI^&9Mm|j.eQӪt) s Z)ksc4 ŏeFt3O3!7i* dop,3iQ1?.Y*j2ׁtjBn=6lѸ{ksnc+ij6m#u-$"6#M( 7?,%Og4 $)W/,@脲.yiul~I͵1 υi+-}¸DJLFv}ړ|l+Iw\GM,[]GI?f>n Mak:Xi܁Ό -Z8n'ԳZAe|3UgҺ8{ޤG›rSՓLG)y@h''N&'՝f`Rv.ԉ?a=R lgZ.O.](*Й=X"'7^zQ6XOBs""6u.eD[tOܩavoxlqޛ6 Tnh@כ_-b㲡hӾ_^%wLP`2:<}_ϺAyc8_{ou@YyGlu*,̭ǖ4We/W,|tK) m{㦣tcH~ #t,_mi'?}YJ_9:JNu3Or< 櫾UuZF6" bd*'Db\G46L?or];^e*)`+.TDuG2KpWL. W-.V2I˔7JY$Fh:d+ }WT~Cd}򢰏(4^ӝ5u V Of`ȅur}y9'UۦR KAx~" dr5e9}3n*;iž5R%S}՜&w cs|#لYWLwkmA8i}=/W@qQ>2iUb˲-q6&UQ{D. aЃX!1y_Eϱ5sFsv+ }?N| - uʷ9kv Pn ȓØFm~>yUE!o4TT@59Nv_3 8~g#9t4nqT(V';Aïwf] iH҃ q,n+"Ɓ[*^TϨ?ځ7Lk'ՏODxbX>ãj7M`kpêBJvQۂv6/ӹGM$d`w(>i5Pos`O*>w?ljdbR3 j-fm=9)5,s#^"1ޛ;4d>kSkcf=$aJ`\Ou t\Ϻx 3AKMYmiܻ>RkVZ2j>V)2JbGUky-J;D@8nOJ kAma]&{v8]EP7Ug @OY:46)4$$!|;ϩ2#30A5a=$~lv?#!f4AwϾQdIkt1!*O8]bͼ&bsg!bO}V }s="xdkTBaBN(ڎRm àɀ +B`n껼߇*'.W]eF!G,6^CCX^*̋XV0_Y j1D}NA7B,_~$8Y2/6^]q˽hrnh#/(P g ؅*GP ZXOȏN-[x=%&a~qɟydއB\G @L o8(؝BJdKFk,b 'ΐ@^>Q5gUߔi G6`SʛS+u-A{e+qEK`U3:fGD E7&{fZ{JEawv4.@OO5,N'--@8+Ƥ'uE=C 왐j,=qR BN;2R1Nz3(-Rd>1 v~v{z]8%oO?#f1~0wEVAԄde!-I0_E)$/51 ؖn$NM{eOD3 SI|T3}Q2,c>K;dv! e%D8N $]>Hn P8x:ߪEƇJ\e2û/Տ•;=YIrR5VHT^,lYvj8gHHcҾSApPW\&>Z (p!nh ގcȥf!a"V=Vcqĉ_n`Y"tHN+أbetwtF"/cKkөcP$[BĽ&Dey^QNSF8G0 jv4tiTMv6wlR}| aA 2@;&iN/-b3:V) 'd(SGA}TL b]v}X\9NMT@W "F5D#WR7{ठYoqmi9ɴ~TML}۾0k.H~CyWtfHEPsboCJwWvJ=-mH>X؋!t (B-V#(DëBM_{$ $whCH FE|悒od|~,pRnTߐVzMq OZ]$yjH6i);))s{綁g|ڻR B)/Z|p9`XrL?Ui %4g ?v*aGyAWXv;h] VwbnQ*>ɮנ,~BkhY^AJygLNjI"#ה]V'G5% ?u yݑ-g!ũɁ!7:GCr4(3&  쩦5 ^˚DǞX3*w =o{܁\^ ;WRܛRU_1BYft`Wn"95&c /G,y KPDCvIi?ءQ+JӍH~1yK񐳝Yit]Tg6}tc@ؘCS 7* >FYB~!,E]zT?b(PAh~2q?d҆<9>6I2tcCECǂOz*sl͈l`ML1x=\ `  yF7i%V۵qV4=ҹ=PJ81KYV5k*{Y.Zz[z"72[-w@ZL˦(\#1ls1 4DcScdX)9CtV>ڧ9E8HR`ڐ͚a;'&qS黂܆.`r8,νsJ]x2^[{2uOG_fC^{uVa tRJzdS^&A$7Klt&鼭@;xu+R"DgBۀ (x Vߑf>h2:=3ᔊ:c'fQ{z xK\9Jf]UpG73S1o9V;x 3گA)A,ƌ(OO`\W~@ !xjZҟ`SBGy,ዧ&kN\ U|:+[6}:ZܨT/| hJ`z&wI=\ gPIu&\ Y~wI B;d,^ &ؑꧧq6Dy$u = >#+d{Y`tlpC=$6 42T~M &$ ?>}|GEUv屵0kE_L]&ڢ&p}^ dƭjoYT$}l} _I]}1}kGn# 4UBV\1ZA#E)ԋbܨ'8 ٤hfU7bݍڈ!"s?_ވ$0?<4"xGu8{*pUH&MM-Dmˣ'zD$췶UTL:5)+e0ͷ(OP㕐|eX(*Loה= IWY|2y1a'[ECаETLtJ;Hp),< F=]AND8xvCxK &P®PN1YiR;_6a9*L&ݴVQ&w>|p{~u~!43b>ܛDݳ9Ьw~WL ~mw *}q=@JKORykwًęyNogyu:%S/a<7<0W5w"5/™F;]MmϣCoaf#/6ϷoQB}t΁ V8U"qNCK%\$l㩩%Ev*~J< ^GH5z7ߜ#2Wa1;Lmawǯ8yݏTa4<]d*@)H˼@nEu)2*ryۤm/#3C=uzbUV6oI:M߯p*\}.~ GӯqaޥSƖc? IHSP녀ZeJ/aG[&I~{g[N~-<{B?htZ$y|~gN 4O\FI3A'&,9y@~QjiB3n]_"&ሞD pG'|1NND$X`Yb(K:3`9<]iN$ةoyMx)떽$9ҜqX7"Sas7 z܃AF)`+* u/*)/@{rzס>k(R‹pv## E\9Sd?Fjޘ#>KeNOɛCMNk)4' e !V}|t,d HOGmrz 9l~3V> &q*59B 7?lNןF.{XݳV,kUwMq4$bۻ}ZSIG=jiMڔGL7dߴA Kes*JUTrQ:m'@X+}dž?IHE3aߗwq0;y3SƑ]:݃{A0B{iYGqHCAF/Dvo}fǪa3:X] gړ !{R1kQ?bq!]\:ao,]D)._/^'AqeI/G-X}9쭮NJ7OzLk{U]O$qX!?- 0Jߐ7ZEL?6?dP u.bPښ5%95Nu9k.a/3 (MI$BT$c v/(Z;j^PD\̤*fʲo !ݫڄ2h/Vi۶n''m IVC=2Ew{28ؤ]9(PyŎ;L=zq(U.J^wƤO7 hALnMx4&g1$čr.ZvMa_lmxr=$87EwXȠ, hgQEԞEդسNe]$'|}l, ![`1:ݶ6;02ml"1D =봐Wɱ3q9b{X^ʍVn(&e53,5TV ,b 0H6ybq^b'mh6Xq`rҡӥ2 iE~.|boL}3(g3дJ]GD6v1|5J\x5j^JGҺ0Tu0"7:jX:7NR F%+LB'rn6']0 n@*ۋ:ܾx U1oΫPZr":EXI$)Kx3$2aW^\qrΧ\x+`poǑGZrg܎Ou/]{%Y%Z3F/4 v񄙚%eK(7" hFPM3q +H 4yjM8T[ k`b?ơwS1)VQ\Ն &>33CYg&uxm2}*3fkƌ*N T:g1+Vq5++S9{6|]HF$($ #/F$[C {>d ɻʌP%;j/Fb@Q*Vn3Ct'AlvC7Nv^.o3j]Mxh|:&=;:#="kƳqcʫq," HiڲmtUj~69-<&(%(g-xE0R攝R0Jl%C+tw@n2/q+PKtQ8R>PMmsqNcC>fa6O<$|'q2W7~X S_{Dp'! d"!|Tazd 8? Hd(:]~  nv ռ̚]\heqҬJִXTmM֒h&vukrڨ&c^QR:e˜)d6,Eq)G.uYw N+z +@iPj2 Yo"M-Z*+{`eSwII=L 0L@h`Ī4H4W%hΏ8A 2%p" pڛX q۱|p̝ܿއ+  3GPC[x@/kx5<`Vn hXm\G\]1,ˉH Fiš[w%ͦh.Q:W]^M.`l-(fC#C܅fb$EQO 82WkCᕳw2\OY!{zʖu'r9?I=87nDv!qi&Ҵ85KxB0, 8 ,Rx1qWmzÿ!t틛u`M ]*}ȃ] INi&[|Kf 7a E>5+R`pynfE@ n`*pUз|椫H(nB@ _ y'2ɎAU:9^3>Uʎ~;s}뾠O֪@\ *>1e}b֬xJ|B?'I7 !7 CꍄbE͔>(O_@8L.N&0<dUh?:SɁ*{*ᦧsoeLS"NX$ٰr׭NJ0 Ɠe3L`gEGNTֈ͸j]fǥb7sl'o晽Bhu{جֻ@ L1a 5PV=\W&a_bQ9p4SGAF1/ aQ?t9}3U*IOKљ-(pr > -͒SHC2R@]6\7wHbͺ^V3IU#d*j4JJFc!Vs;ǜ "1i7KHils(din7,2̥"l֏DЍcl뽷ud!t]GFU eJ61.ChMK'VAh'[\qDjkċCx>B]1g-HFQ)~U ґSTlO|JKW V(L#0z$1S!̪P*^tAxTi8MmbST;ƷSn, n:r޶Z0er}Xi )ej&M| Dy^O]W+QԠ*5?Lঁm-.Dl ܝ WsSgIC}:$ob} ~2Z*C1,b  ;y_c,>;:۵,͒~DK_Bϸx)8W dyp|߄>xw Ã8PMÿ8} wAe'B\oSے4 v(#{ii0f-PuZUxpD5`a{#wJ:LeX՝sT8T=z)E >i Y\vcAz/>*Ow^- A<[S1<[I/nN,0-𗅇0'zMH7eVF,4T$( "M/`;|94Q?6|'"׮ӏ?f͉1>t}?qo;hxTk7$H_>N?aSaN؆2_N\m_ EpxҸx=B'@8,_PÉ/4A)u\J8N*EÕ9o8#e[f/( Z9n!@Nµ [Q+*Tɍv<R3xEºudK؅%c7r.Wiv]U*k 9t4gٚ8a29!\Ώ odi/9v nvh?ֲWp \\"'D=nUٺ:0l!~*SR@]Ǘrϫq}3 U&5|p_(׫3 9#;Cpq BwKBFI41h@a9'Z z`ΰ;Q?F@#U(k?*:- OK[DfEW˒f y PxƷ0ӷ 29{ |.ų=lbu8 ^JÞէAw]n_޾r1vlzܷ V4۫Cըj`"'P/W +S-y8>`uI}lW [bɺ8{\ԏ{) \t ѻD)PRw/G+-*):\IA.ZG>1sP/8˱1T{xu\;9A6 62WH<_Ui4#ԜQ C/0&%M 6rFXA&ca+64_>,w׏BUl4ɣV _ǘ{B&ħ_E!(Dvv(hB1r)XVD<+Vp!LhEK3BY:OaXU"UÆJm=pN *8]rM?޷-qjQf\O^'Kgg2xysGkr0I}cN u%r =f_h7O)?>pRzpRVNQ*k$7ō0+w? ckE]>Ɵ݊h^]VYjw[Cr跞 ߠr5n:gͧQឲvc?MbV`2b`wyv8ْj̲U)@uWGt MœA-BRmu|:b^Oy dn(4$x =و*8E d.=E_@rSqj:Ra|J@ nMvbK\jiiχ]7sgv`8Ka4Z4ayc5[p@Z臭gN~\ćթt w%kb*OR6fhv,αitIR%!3A#BfD,2iؐ SeJbL(Ø)5h "%E1)L5z Ü(/+ճeŅ@I*k8X઺;;0T )1$!h*0 ΈGyZR+ X ى%ak߳W[5emkAif糵wpџZZ?tJ?ΛPsF Lkv\sVC'm{RQ7P"s]56BvQJmx}~iKY4\4g_JQwĄytf3+ ΁xDh'*?;ҁ*ݘCs]Vdo;bwWQAQU@@k+keYkeV<1**d1u3@.y1mtbfn$S9|U$(6eܺGOʗ9#v o2Opu|G5n>3x^9<$Xn-;w+w'ֆWCm6/~ύh[Sfؗ?T-_D[>[,[>&NΖ &hBU罱|8  lF$NP\9V8*~HTui`R{WL*2WԀ.=7SK8Վx;/g^!qNvr! lens:u&wpp< bۘ'dmˎPu}k2^<9Uv`ҘX]( y&;h9cN|L5E8ֺwgWa'o~8R<wH"m\o@rkkZh$IIcUbiVt"]_MgBkʼnԱ:LVc1LiQ/S@S>4 l2aaaHǘWRi20uTiJQBgWx]]o&IPWsܩiJ$504EL0A ?]"K7M7,ߨ .YwW[g츓a|a'vZ` V\@s(l{y˽Qxe)Xuk&R㐮n|S5KPB[h#T\/]vZؙAz+/hhl3JKc @aMG(1C)*-s`LقSu`:[oq)4:eM4qM:sS.٢k%IH &v6f1CYEӐwKTK)dCy2A"[CȺ)Fۀieѣڧq YnPÏp+%'LVK#>GC:$oB7v ɪ \N6Oas׈xRa.Y )`\N$wtɬ; MΖ7-^>lA?F?o平}<|+[ƴx[}W`idН+5qx*d]Ǜú"pjb@J+ nA 7é`gN/ʗp7iXZJ>7p7(̲|Qo;[wo÷g'ꓳq`@#jFF2DN9}u8U 5obey [DE gɜ܀(fYJK穮 YVՓi Ųu-jTH6^6Dӻd UsQ* ZBXG| ׅnsHɄżs-`~(9wCm` B`8VNu7ĉʴ(̏蠁KL. Fi]n"¤ Sn=yB_q<&~S/EGq"M0?`35{?8l+PB}]v Y=y6? VV'H$:AJZ{bY_/ kbLKJRf,3<0νw76"0 CpP fsANq%,}Zd0N0*ۣؐZX5w)A;eN.zA da!>T1P_A~XG>I-|:#EOߜZ4^Z4|}AsJSFE)W(PQ<"/'}/M\_JMn&zi뀍w]GÊWvET4 \N VNhHC *ݘLPu}ET|2'G]I.l/B /vʺQob8=.a ~"8(O7C%R`kM5nИ+2#0޼ui _ p5c-R{4`2$#d+n0D ,]eQR9N;iۻnI'o _U";笏KDh7=a3o`9[גevS,<+er@<=>Ƒp#ǵi3>ߚ:-"}&R`"TPBqZ o&%5űP:h7p,pO4v6R1 ˭ >Dƒ()ژFAyzga̸~{zԵo rUz#4q A0xE4f⭉y,vnGZ;cwE*h-,#EVNV0 Oئ~{Oꮫ*'uw}ȅ4:cCh/HH+tcH1Q$"KXu);B \C{l3LI2t:B$de5Q(s99&O=㳽PKfq#ejgC 2k ݳe,29jk-#Wf#~ߧEmIK9Z Ԫ?O}s nq;՟NN_kCz:ig?Ox3|öoG+c#/)y٘{A y&䙐y!XEF{SI)f7R:.L38pܒ`80u;>5=OE 9]d;|v748&mzެmW@ElK*T;VB6f&Ǫrج|9[|adI{ػE7VA%Xdn06̻@&-oq1ɞ{?_`0b" [ \&ʜ _ dC޻UUPUfjA Nީ`_' zgs7ZQmʹ?0qnAS-4bB졏S>X$D|t_KWa#jlL!oEЦzuzZZg`4˓dCB*'0GKVdShɬZ'G0+~:;AUbX"EPHa|crcVk &;D X#\enqvދ+Z$it &)np,N}:O`F@ l#v7;RZ_WOڑy,6ab9􁣛b`9 # 7ƘT( t@k뭅-.b'߼yfR?hHP/o+?6ۡGE=.$UsxyrvV[)9a`0lq#}dp%NÒheBXxm@Qw1¥\F`"n<ۻL!n:e|Dvtr}X_bYQ]+z+yW*E3np g[ ccM( j8* ݎ]bWE1/=N+s\ Omtyu]wk[tzuk7Mq^pѭnnƓB(&º]S1 U[hkj78ܩO lvJyn۝у{,Μ]qC=te]BA}۩7m]+)!tIah/rH;mTx*һIhl锻8h G q]wbcgn xbǸzpv0W\ ᚧ"DS9syƉqc%8c$:y t>Mt>M_w Z%ޭoNrt7DIV)X7b 3 mX=&`aqkI̭HV jq)5uƛΔ9c[צEGP%eҼw"Ye&/W%j$]#HځДz HDC Qhd~h:ZXƭ6[GlIA>sڿg10c=w_0;(MPmb=t煇g{#tO6=mnl36zܩC>Tpޡ#TROs৺X4]{t7D}$!:!hUu6П6?i~ӞC} h[)bKlU,҈֢]3`KLn͌Aرs_ŬVʆ8Yb>OێUĭs3aM j ]eLnY2pQ$|)ZHmd1@Jsc@ֶ=r߫ZA HWіR%vp)ӫ9=` -po/~E VrC[3\P5?6ҋ| 4Ztd ǡtG s]C-w%5G-6+F-ƭZ^ܗ\<)Vhr)6;C[o밨]SόG[[q}Ajz~ HV5w &d;y!fj$- cqj{\;I 8jəK 2c!#~7~j/.e߳ 1ʈcd<,CȭڏU\E^AO(A$Fk7X{sq:~70unr"CEj&n̼kIqd[W>/{_GY7@9dt#)EuA5mJ&re˥Yynn; WF5l4{4gqP0n1`2B NdA۰S}Cx>(ʳDGPNW6[aЯ6Z; 7UㇼE~.wڜؐ9RfaE2DE az=@^W43i]s5'ʾGO]@ x85?lHx`bd0Pl:\4pvG塷 ͇@A_qh˝uUZ W5  `e#m;}k@zz[ j<&Uj8zE'ìC;v\x+V VlXkF8z?W?V~ ǜ?黵O6r\q8qkK>9pO6C V ZN-c7̒g綗@[V|սj:0(FwJ23%<ߪII,]̯k#φmϮגH Mʣ+qv&0w0LpVP cˎkiX3CЏjpBoAʛhƮTnt- Jddab$7lUqCOkM&؃߇hPd4vORoΫ$$~߉j0:m~owM3@ct jИV (~<i/7G* z},Ke?klPy 8WmM^@FnZ4#Bz(ݘ@Bq}+iŲQ:֣ 󫒮{rhsyOOҡͶb[3(ERn`qziB^bIpE-p,0MHH+1Z*AH*H@A J ('*s|9!P!0AsOJʪ5g>]SYER-~\g"F(TGॿtX'׃3?1dK ]+3T<@ܷ4 ?y=oQX[#<ϋ#]O q4&\ wcP(~ Lo2BhŨ*~! ]EBew@lp< ?|0c?M<ߪ•x 8bO$>7E%I!bPܑy tSMa,< r ]U+I*[,!ap= /b׎FݐN̴mt${bEqᲜ+b \p:Dqc_=( Q~zٷM*D"̘)B4Fp\өv| Y^Q|#Ŧe)?>]MLj=-R^Nk+4* ]K ~o;ĵ8 Ӛ]tHʂHQG[E;"Ȕ2L BEՖmG=Pi|@PZ^t=喥Wnn"E'tM6w|E.bNx kp?_J\u/W["jSij0IiI(%" C1?#0Iy3,U Zl3^Y$ͻ1]f+$_X9-@UpU-f/o@75}(ӓnhnȡAIL'x.xW6^#=0FoWU\Te q'3p$al8Z^Eqh LKSSIb ([J˲|U*Pmm_R"<ӯ{KPDO@pCIxBp6rơY%l_? ~!L duWS0NwCO$mء_zMA^PWy0ˡ̈́՗@JE/tCD9ˇpglr^>C5^(ka| \?j33Kn\LD tHcP_)f.NZy,;.YCJ bgƅO^ltZpeagp*ɜDU̯|3lջ[ay [{@| 0!)IoCO*<WwRLaテLk8Ѭ`x?4p!7 |kVe {WnWO7'iua|\KEGTZ4ܗ=bX!$ǝ$`2(wRx 1 H;@J;%_6dl{Qbl~\N=vw|ns//=t-X%$BS؅ 釚 ${Ih>& yX= FY1Qp[rTsw]3֕2_ GMqBR_yxiT*fЪCšc5G#<]r>iIo pfK!xqA,W=׽ѫ{fU Oq F4 B੢43 L 70MV:n@ӋI wc*a:Ź b=2t׵]%Ķ=HOؔEJ\@&Q߀{Ƨ̽V۳tԻi#^\wMOy8'"^fG?̻C<`a3a]Ywfn)lb0sB[;${gp#Wx,TjX4*<[ۛE^tmJZG˟V8Ib@X}'trK_/1:y3(ZCIdೇp_^fGj#3=|E"@#D"5@aSh)+/ JF_%o`|/Wa¯c s}`Ye7NVW4|B BvJ{A)=0_U$N0*>{ތ=(P9{e5sD=t%lTc3I(qHgOM|@~Mr[Դ@B~M}{Ir%^//qYY}:BxUȋ%[e»x=s}Y 2 2We` Y)r-i\&uzGp(T.8FGwCa #PЍYZf4~ы:BŰ}lq7To 20[Em.v]zXe@jA1'aBZE_mwQӋb묬;Z-(  z-ЪVIHX%{89)fZt#R{I"1@.mhdrĚiqMu,quܜ\b4Epx4xOiɗFQp ,r6>#"3f5CLdn$#b$2j"$V[ƼNj}J8nUeWyR W^حoF5i>C|*9 6&qGuݰp“~JOktje)##aHʆ{r5SM5Y8;O,ww.Y-J8pDZojyXI(Ec ) "cTј!{!cbnE_XٺgXT lӀ4w bDdAt3aL:b̬4Ïkm5lז$'sl 2Ow!qPjzxXZws (nwշ͎'H7 tcҝ%N{v$3K;mk޳d=6hJIm;y%݃c-@fk[˽wdGo 7ڶŘ)݀ "i[Nx&b}V)69 f z`G+V2o ,1Uln;)$ c\;7pB0XCof7ZXntq7\`G;iow,vފD 8b*NUlmqv_+b8VƁ; 6g[,[Eˈ.S%^X5!FDfK3Zqw~3dwD#{KGΎ։F2K&7E@F[PG6f}H?SabaNxTigeb*怆 z7#b-|c8+3g|c6vkSReUj8&+TvzưXVX\Д#)k,sjWݞhRMؤ{z%6Ӏv2ڪ PHZfJgMK@uPM`8)Rm;6aj .r}EgGTLpv:JcK-wδ*@NcE]viu"v1 QSl4gjl:)!Ձ&uόR,v@(B5RZxo6"abBxlJ&pn<%m3)ofoC,9\T^Gh6;geNhSFifOLn2dN].3:Q s46$g$Vl},|VDqZܯVE/Ȩ}+ A g)PY*%UԂ,,l1m1cvv>8 Gw24a{&)ɯbԟbhŇYHY3)A6xksz1&,|3!Qt:.v,LqlX'{f]M hFϦ.d*Tu=)=@UZmoIА8ۇ8/"wKSoõV xe**kׅ)Nb8!t,7/ )wKŶ[nEAOe-#ev\8%-X W|U&\=6@'V}H#5ԸԸc'jIWJ-rQF2SutMwl E 7hv%(uYO4 3a﷽Wg;E蓅&6r3Yb׺[Ri Ueael1ָ#D崵;}fFw:qoĒ 1^_UHMdCJ^ R9ih $sސ0;PSrFslHq>r̖o%U-lJ4guhEaIFPz}!= rakjlB@ryv'$Kr/+Z5CNڵ$p?焸WAiK-d?~ܗyh/Dqb?e %7-!%%w! {9=>x{ǭXC_IG~jtKn@!ͣxh #$ݚ[H4qP],r43gtYx*lt RCۡrMҵim{rJF:܌cG A2$(O詵cvvԻ.7r$ܱ;RxY4m-!-`\qrƧ//VT^ڦbn5F)?G ɶql̩t48uP Af>C*+v SI}[sM3B_bU#[{0niUlCE8npwmPbwPx^ncDƇoӶmvhUM| ڳQϛMG7qh.Zx;unquG/Z1C⡼+f`ڑnS^ /U/IY_q|Rp.l% CZC.8coIKu||*ch lŔ޷_zU;d/1[c s|C2|/l7!^ksB%o*TK Y  @R4Pā BP $ 1B㹨 c)fHt&YގM4D|4^P Ko`a#UwŬtc4t5۳Yo*%ई6 9Vi)n4JvjO$.6y磋,;Ʈx1Cs< &L x6i:XیD= FXaCJ:)[tEh/V+VS.9T wb Q0 1ERX8p[Gb v ~ 0 ;`Z7δYc"5h‰Ec yUĎOD쁂X\*<1Z~tZVտZmڜiC$>VQVźCV}M]w4WkGLGd[Fvv r(}2Iv Q}y y!g,fB^Х|CƼ&7F}3HPVb&q41$SP'1- |Oq( AafR14A3c$A&X6 c^au 8aۙE'Ā l$CyeogztO1Q!l4=4"Q* M 1g/!S(@ nR6!]]X{?@naa `v۟ߕk0l3|;3KпzfW6>W1UW>yW;MbߡU ,b فlI Wb/%v-#u{R/tۋN> IW49[o1Zf{&:ch}IW]՛旷ޝHSvx㧫<F y!h]ݞod 7ڧމzfI0 qstߚ` V{U v)xs.';K*,= og^^ ,|3*UG8Q/0sEMS VUޢO'yT{cG HXA7ŹN0qrvn"7@Bcs@p.C"u!99XJb)y057蔩8A)3i R44ve;HS[$MYz_[^=P h~x%]ݭھk'b҉/fKls;t]MG+:wYj4c{?>mxՖ^OnSu݇'SWyye\MmQ8 '8:>`O7M>7ͷ/qaLS WKTj$n'Q[-QeUW";@U-Q\:[ObNZ!I,+JR7.qLwLyw/ _u}/ E_ Ͼ`}W/GE(0)u.0w.Tpe"*!^wRrT&$%vG̕+m1L_!eH~fp/K`(ZΑ<3 ׅ%׹%$]e+_)q P p|%6W| ~bI+*&-,; z뙎_0 w'_h_)LG 9sIP=|XEAL! )("T3d9!ig#߽nh@=wH]J>:ӧx>3OCLB4P zP zQŵv%#yiO,i"N;iïWɍ~{6Yz܍&#w498fο@nWƶ/QoMMF''BWa@2.O>?|w8 ss~/4=I&3xsaa|nߎn>6\>7mīQ/;{UDEt~dw=g Bu;v3 !Zq kUU<_oh$ w|s QbMH xz?8bNO)v꼕apxsf{9mx¬7o3n&no.qNPKa K_(GA  6K~2|N}\;iRT%FO} gF\5%B\"-$E;jTWp bmYq/4UaEWWeqGA)D,..V->{T;G^=_0ly;}f|RNn:-|c[k93}:ό60u\9{wHIW_Ge۝ɫY̺xz"Gffь UهI9r0{9 Wm!\*t6s8|u`NbO/i r*fK=Guž&=)՝kVO;հ7|9l35]"TyT~b~?g85v݅dArؔm} Zu|vo~*mus/f3UIos_v3c{ǽX7ߜֈ;W]ooԚxe|t5 ь|p{:n0Sg2l$\i Twʀ6>g[תy-b%TffX̎:˯[Le12ڐpY~0ꯋgψnscrw%4Ǫ]En;RǑ-9N nnR0t9BY,&f7Y P2.?f @k0:?'$2y jP$ 0jͬn@. /Z46n=z~WPK BE{ pEty}|K'^ډNwז%}] ĭ6fXZbY lEaɟjpWpU=(KV2'r gD }N,ǜȩ"d.{Ȏ3"_VP7)F?p~F^PIHu\j5c-2־vUSP%X?^5˸ j49ٰ?z К߿sBǣQ%nwi-PtQLc)r~u@Zzc'V=Dkdo];RςI^patoh=ު"$)$b] ʕWZ\̉XˇqӷȮBMzbr]]we8Ezl[muեiQ/'2ӢD#1X\mјZU*ٮxeџBJQDV֭Wyd82a\V(RsQv1'y&QJY;7+ٙ8x +=ݬۮb8t CzCV؄zJ!A $8РNQ=^Kn8TC֙vH6\ Ըȓ٫N")c q)& y 7ya5m;ð.-_ؠYGh±*Fg- ƤaaH)uM GyfWj8" 0#iIu,MQ:bhXSz;Sz̀~ )C݄IT%0`ʴ uèW502i\~fW }7N 覝Qʃ n`D| AK1K+ݻ l/?(8H'x8NV&MKnB%ߎK6nZڰNJؖl`xUY+&ɴ4S3M"m`H/U AIF9{{9Tv2R憵Sb8}JkԒ RFjhqK&v4w-svlp:7.Z~ڑ9dX+"P~nbɩ뎀$sZ0a8K*۱EK(nA*+T^/\@lF˱ҧV1~^f!"Y)^n8R*f$!sqJ:~'%_|=5As"4xtY-\[8* 74pi9TN= fmll(y̞cPϻ#&E4:{^6Dc-ya] U̾#G8bPGQdFY؛ ,\rT=ViS_b:*":&yHIC~pR-^[GE6sw AZEI,d4"d0T0i[sQ,1CSacƙ'-԰~d=4!)0+lfN5!) )Qikp ZKyrz|Nx,ʱ#וw*,#9%Jbt\&$KiHlA$sLD0uiZ1t2BKۑkеSK-ǁjh&Y|q;L6" nSQt%6b0fz,ME:s$ߚMph=Ng2Ma>F^yBf/=!o H("&b k#dNA!11eR^M{FKɳCbxhFY![Wa-c}r=Ȓ{YZF@ʢ.- xZ64H n TdIS5$b,DՕx ^N&&FQρa](7lZ-cN4S7d{lЦaBґaG0ϔ2_YYB#/k!rg~y>C3Bs;7XK31Jo6[;p.eDa9w\˓ iAo->0H HIa4&\MGQ7I3 ogn&1Ishxk`Hs;rlXUa;UŤKMc9Ax^/sews#lvЦ唴#q,u(Ȣ(;{aF+-` =Sn fs{J4W(b2P\"E1p k+#eAQz6AWmdmlYدW0eY51FeS$1.?\}srij rLtgVVȿ87^0TW^2Mv?4O(>GDmdD_ 6C>~hBeBm:uZ/$=ߨ7*ETc0|$1Fo1*(S[̒4g$}RjBU%":kI\?kF[]1f(bc;V pd: *[ZxW*A ׽J;n- ٧v}ۇ4;t;7&Nvc|?swq6 죔yÐTA)I⒦ ,B7P "WOA;9996*[cFLbF Q*KٗmHLgPZ\8ZiVL+W"2PӃ!rs:aM"FM$=>&!!\TM֭!J[߂*,wJǾ"1VAx10W#;kMΤ?[gAhd5޽kBh^ BTL!E䊮*|bBEI„G\-Wڷ]q8ꯂ%!Ƭ͚G{@{`i8PI6g7t?4!ܨyij)8ۍp:`@hHu]ll,j؃©Y.Ћq:.xSFi(p,BۿgݛɘSglQ 8 qs64( Qe=RG#?=I"<9qz 7.HpZ‘:b $ή$y{# nq>QfUZԲM2E1z>x]88&fQx2c)oI/q1`u=ڠ;ghѯ@@1+ ~:.A>WٳFA肥ZY+ggu/`$GX@씽hOO- fuHepPq48=5`JJ5PeuJ`6.N(vJwh\T؅40-7lSl鸨Ŀ3ٿP]}D =jt@.W^iʡQܨ1hV+Sy# &`&~;DuͿa"C<+R#Ĺȶ !(|&b>S􄭝^u#Nv$:DZák ^2 };t'g&^,5 7n҄O6 Ea#ib>1qEgЀy:QYk> a("Fl5&#T/2UZĻOx͔Xt եB8عDMkEi{6<`t#U{dSpH*tY˳<ƣ$<z;947(a'Q6"i^#@_Ǡ?C~ꪅ:M%C/ף]^(303ʔ>}R,=~hP=7ފLD p%a).gC'݌\in+̕sݟVwt 0 odM*3M..ݧ̽-:ZkvKmY"o7VzTo0{_8e\C{[öe[NĔv:7 :#Үavu ^~D.`}Cg]*cV̠Qb϶E@4#$b$)kH.Q;T'(oG0Bq]e `GzFx8nҼ,%K$S Au} 71/}ky[g50'ÛPHQ }?z ]Ԁdᬭ9̻,{`I/zMO,ld$8 "6sl9Ml'hzAX݅' ǾϨ7jpdZ&jV(ws)$T~ [FO\B!H"z P!Og@?vu khkLr:U6{L8C4PktenLS9='U1F 9Z w'ͩ]W8ufY4 FWq=-~U}OY4|%ޔCgם}5z~:F˦4hTsj:ǰS?^m/’~F>xZhW>Ep$i0xފX ο0@">;s3_'t .!hnqĭQD)FrlƱGS,vѳ~ZA4`QGH1zw[ nX#$,Z/k:gZ$$3W`:5bkVnk)ʼn|~1H"D9"FHg‹1:(B(n<^}fq9J=F{|4+8 &hkGgbtKMPUQRbxA L{8ꥫ@.9w o7hVXÂ=|a-#*̦>G}k$`xα![Cuڕ dV"n^Ӡ׮I*7#kk[-cuh8{WgHt9*(2dܞX[*; IY6U*ʹi^,V<ǹtVԃN2lng#y1B^)g`mת66>(Xz@X^` o&g?ɲv^s%3ÿ}nJDĽ7k G0πQFҗWU6$k5|eW=.zz0ou_0%( o7m3o )&y^ӓ=:,(r!l>~mŇo5ĬOwW\ut~*y?&gljg5Wv?(1Duu?8%͊$QI/u2{}T<+ۙhG!#k7zdPgKEux)* QEpiAt 5fj|h/DޣZ9J9 4=Wwϱ+trÓ6|g60_GXd1B |oի!|Rے8VUKIңe %\kzS_ .<~?{r_A+O!0zTU8iy/A!Y+uCtո}K+ʃZ%ȷ݇|0qNj¸2 N)Z.WLPګ(Vl4Sm\ǯ&dRU@ 83>V5S4-˱Y[pBBXBiɂ)<${,9E3ܛIcތ؃}a`Lc旓EҋMWI}K+wkfAOs(]6N 8 ?*Jw/]ۀN. ˩XugUd  ӧ:ey}G'xW,ӆ$a~ש4 $}3GU|300Jo\T-O( xo\%~p3߫4LPD'Rf[wCѨGq5^x射 .|<΋F&T#]J1S²)t W08v(tN Wy (Vd~Wj]Z彤6/hluG5q@IqUm̞?qwgfVͫr\xOغ7ki~,o^G Ps~^ղs+>֫HY8:j?-̋KF|%_2CW2_rT_yQz ?ws톗ya_ yb%np5}}R++r`ޥQMخPW UMS@,K @Ov!PB.F=}yuCR IۊĒk%|?ΗPW5ïP1D@hD]+p^4>Mdh2cT߅ˆw2]tS-طz>AA.FQ~e7x@`XչLX #*]*&sO_n| LCZDT Xyqڧ< ~, ޽Nsbk0ga0&JHOը. /T.=_S!h"Llh~ Sh.H,{Kw i}Iv}'yw {]oIO%PAL{BO(I<NjL n@>>\m}/0@'`Dr e8;A#QI߄go^Ew|l[ΈMƟov\&iJwT >3ת&Օrto *^8L#Pit{RU䉗̵kZ = (ښ-"Sku5/C1~x:O+ѸWQ';QG 9c TAhf*vB?猟s柉d7ރ'#汷ڝ;6u;c~тw 8;Hܽ i گuROJ4cyo 0 q5W pPG9VL-r"Xe6'pxsJ?Bi^5VE?y&Sgt猯SwdJqL\>EieO/&*_q ߶X;mWc! /bZ P_^˘2s'!>#X/5891gKc5ǡϟ Es ;b81?ޒk/r7JPx\<86^u c@7 -}w/XQ^me u܁~9WAq#v (ԨH8A݆묏;GZ8/ړ|> YxG82EC/;Q!"~FDA9s bC\#"ɑߤ# "!3M91޸~MίdGcC)"#Π!9] @eÉY bS q |ye|TUr(u*XwSWvk%m7@>)MI4NA s eX1dB6nXiZ~N{V\=>݆ʧ1?a( wYx 'kb J$g@$ VjZ:xJjaB쮵ЕQzvjnRV)~>P鏟v?C%e(д}%:Dž_̥.܅o}$xը]YDb?s?E=nBlMD wԿkxh}WD'JJyAho#a 6FˏB8П'a4)t6O2bW\e,JKz^qє,J>Cuš?$^j-UgV es{ 3#yߕB,)u8_KshV̞*Oi_#tk{?s`Џq;C1 ` Dpyw\ēMLn~o\e8ZP)ʋ}_?wQ AP|h0y-9 e9bY (Mn :ˉ}xp<#ɫH~O#{loenESc>MdHwtb4GȚ4V^?؏q} Nga{K󣀥C .=Qt|ӀhAbphmO@Юc\Pqdm sǮB,c:T}aeߍ8Ie]/%1u cۿ/I5i2\ƶ;F`I5(3F#Cga a(OhoA $NKW;4rA#>E*[.y^'h+7mӂo"/}BpwZo!'?fP{ 砙S2Mwd#u M<5`DBoO;ha#NJH}' `Y>|RɠoL5;q9Vl^F$ ۬KYf398{Q18iXt kz)0S}aevhٟ7NQU iIȽR H9yE(ܺSy4@Cc9w @ڎ!p?mm3uᕺJ5B]9BHskoF9?;\K1ϑ }3fʝ&q U*+CS3/?M?hC~AG..f^W| 724H({~(b#Qk{pW~z5)=漺M8 rGg.(4s> e0Kk?;q?01T}1cނ3D )4Y={qD=cYcD 5X: :Bl&mq( =qgNgt},E,J8bC0nxQiע~?qD^ޛs^?q[AI῎ ($2NOY XkgOf>@k~/2~_wp?'rvu/)&W C*"ފ~&");߿"R,˼CfxGopeUKY+ߖܼ '5`6E\E leڛjQ6=(p ]QMfXC4ýU@D`*R2 ds] F8NBp_r N~EQC?*33u3.`[p~Nu F p$Gq'au^I3A%Gbuqqy/$ Gఘ^ʭxt0R?2jx?'y ]B2A52P|lŃeY1E 8bXP̆C+)YA!Tm|D:[ڼϧ~P.b$ +\i2~{BOV4i+Ɂ ZnOGjrx1n7%h۫ D'}/ͦ/'v7#o2}dq; 7gqĽCV=(VCȠ5V}KFgjNO:KYzylhMK\ȱpόUzPAK8_l'5@pK-0vihQL,:*k AsJ\L#Wg#sJ1mX0m H|79"k/Z1+~drŌ|l̢%`#c蹔rhkf1:א#7zx[|2.:fVvvT$SAk4[k*ҍ:p1oɴL)c'5DcLjK/m$ԼM_L$FEtIAT^+]6\it:EH9#976L2D.U=lhCbduG~"[8jS]=]郑& KD6bn-Ϫ"K3j8i>EQ\'I6Ib%mw1# BrUx\g LvѾ^,ށ:q@[mrH?zB{v&M(K6-(:v9ZڰOkvhÉ3F^29& /Fe1uDrm<6jl 1QB' )wߙ(¶ (v>+>+FO *Pq;|FNrV؈e |C m]?]svt-e26ynTV=~_ gh45($Da 0N;tv73[Pݸي|H ? hTN *@t մPen0lrG<;Ec|%Xc[PabZ]`"`m#F" K(3c,A AC1G16XFݚ ,X6?O7a4UPHn5cn.I}G ~Z.ǘZ.T=yOd!sVJNqWjLzٙx{4ڍ7ymg92M2fХ,7"v`) H!>']@::Mx ~6`>C'^"bj5WtH-1v&LH`lHUp[J6(7`vpqȦ JU@!h"l QZCE,RUUih{)mIf[ަK;JJG'6&ޱH5b_\il&U&52" v. %Yä; gǽ{rKm| BEdd5Β]w6C,j^ ӂ zmo],y ]8.yQiv_+$y88c2c-]4GKVH&̌:"yg?Re;lrv^N@YmjVd# AD8B(a6S_lc­_8.6FIxf/u4Nà,P \iȗ}oDmz=fD_bAڲ!͏{l|y۱Ū<rQk,SsiOmr4(#lN);Sߵda-$#eN]߼3tq^R {~V1b1Дi7ٔZP(/.\,U?.+4HOu rj# (1#4'}J%i61" >B}ꈏ~8&εnѣV+:(֛n_qY@H}<P,M Hi*4OV:]M&|߿t?#mOUFUβZs}psEϘ{vƒ%Fa6D۹UܽJfAxgEėߺ5xO"s'*:ֽzXrɒp#wۈ<)"i%lv&R]""$-e40>g {`>&^~秠 QL?n/;y~wRNV׭2 b9qnqf[7ˊbۥ> ]+.}32Kr^PQ_:h&aw0nei.9zXaUSKU-}Arw"|fW`N3V6[e^ew]B@@ad1 F::Q7P$Mv~"5s} (hBT&g+e<:-"DܧSYWc:u^qNC_[)x4wueBM17_RC xq3lÚ V$eÃt0 X-Y *NSNF_17EXG't_+ o%:]V͉u=FPkBͲ)kg Q~h_H.\NjkZ=*<pRC ˵ DUxZ8p$ʖ3~eW+>t CK)%)-h`yυf%QM&Lzxp-Ga"ѿEA㗒qf=75JKƩ9)PY&+# vq=x9JAJ#_*#2#xKc "-e$hZO4)rLv&^hB+Ah&E-Qs4#SS=+(im2V/HdKIRTWV'.:GsccKqGMf# nJ_ @swxs;oyp6\f D߃nJ@Vfb7PS.8ķ;QD0\}C5*-sn಴*/W0 oE3ǤfҠ1Q"taē^ѣӀ;tAPu/J-GtHynSX9S1/Yr%?Wݽ <,o"gNg}1 ڳ XY'mR ?׻Ƿt7*l3DvJMDQVs/{ xp7|/R~Wi% oFdMO?wU.q!.}8tP/qRΫix'sŨ{=ONV9w I!@|k't]Rp1qYUXq;2)/4S5-c2]+7wI7v?=[ͨ$\κww=oJLXiΰn-tĥ*\ɱ/H?ex:۟.UcŪ>,IPH_1)e4 *4 g_D>gո) \Za@*fn֟,Z/ B|)>m2 b;ՈlXDc?a;eD*-NY&,N.O>4N7ȗ\ >I݋v!~Q8'ݯBG<: eQb;t^QuGXs~ _iXe`h?e*Šn=v{\ @EjY >cx) blWo̟[yږϛfPCh(9G [Jsj,n'K ~_ϦvX\xZ86z{[H=ʰvntg[#^Y2s̸3%|l֏f]5'fZ\e 1;H4#rqA{zE0T6_o AGrܔH9'_BCn]{4e?@q ,:擮aPlȞxe TVPp5TjfqE<]u'cR`B,f˜ᢡ|m_T8Fߔ߮UL`Ve iBsHSũ*,ܔz@"孷MBJ;*R ϸ#Xnj+tW)8+7Kȉh362M7Ǧ">&qWߛԾ&O2j&HVjȈ W/{6찱|5_wVU!d vC}dy{\LY@Հ4-1vMGuw57aa]of~ɺ7o AڌY1@yh2EaBbd}3͇17Ѽ #භKV!e3$ߌXJu/7lt0LuV,l={'+ǿskJ>*|!wtif{K͞~F3D1۲I@U!bF#FpU[ -+? y"^fBTU$P }l]'ATP;h1S- o\`)1[ W'9;h,B${GN\ɜ7| WzO0O촄  An0 8)'gLq#%AՆ h)Z8qU$< !Ϩk8a+IxgJ8 ^vi|C͢$ph;3KZyk"QU6 ۃ)`"9t(߰tb6əX ښXqmG&r CjE]c:=Cû#{,yBlv(&b(c`-y% 5+4U9h:d_z*FDLV۠4ߗ9U^q;9|.2ܺq@.wuvz6Z]zCahѽ|;+F'p'`sOxCn>lSgY,^\id~@yr+}0 7Vrh48AW xV5ѩHZG !}JyL{Qnx9BgUMVvNÒ4+vkL:]T^<%R GA͊fSryؗQ/Fّ.,w}X$M)ny39}|ΰ!?(C*[-9Ozn*gh: WQݭ͓A- :'>gS.W3|KGvRg@Ġ=CNPw r5pr|Wk_{o.{H۫#M(U @<Ŧlѧ$f/_}c'7H5O@ "4۔iU`V,0cWד8Mw[Vo/Bxsk'ܔ:1?/Zhv|Vhv(GW ,²Ch|4I%uoUpT;L$P7Gmـy5Pm(i r KSBR> uCÌ8$5 b ] 58i+MaJu1 4ɔ\o /FӶH)eH)g$/ȭ̦^Xr&v Alϖ0cCnqEij;A/O]i.+4ZXf1 =N0zƶ+)ۯrןH|TcJc򰖲L/L/^_=`7ݥBggdW:yW@5ӐS̓pzE#D&t C?Wei2T$'N3QZ__`wu<ҤfWfR6|^>C؊I)w@e.Y}WW% @ ;ٕg IHYjAy ָqyl]änWm4z4mGQ& x-91-{'f{I \j][NڇO+"aK!WgړvB?ջ=o1Yd _?ulw7U6+8Թh/m|I69n-"L3M>(N=d#=890Z)~B)6mhM%gA&0?C67'EԞz2pu1i%)H7k!i2緗Z Pvt=Wy+ZǦ3E֖q_%W 0uɃ9HQi¾[2LroNď70|y(7 V|݂OMB&t4 䉽ꛖBٖL>zP_GԨN+af@p8=mC差n#6_W.b`_ tϤ\4Ϻ!H+5k+]eH&Ӈ36>xT/M F]/[`8@?Ⲑc˩Wݐ]]E BP-8+yR1}p OTNn'Zǒ2Fra\:ﶗbZ AzN.rkS3~ßckO}h)x>码NcT{ذ~0|}Q>FỬxFY$ȳDM82Gs&}tBJ)?rZ[h_vik Fq@lq%ɋP k/MJ,Jz656}i:^/^#^ MoN{=$ Y΀'5,o]3(@7Rw>3]!Q%TBbXψt'|B縹rz/e4tHNiE~>1|,P5gI Gъ]yn˱%j6g\^=[R&'{r :uQ. A(ETK8#$\YkTb*pBT(국p!޳˅uL̩nLBGx;>~Mݬ46f#Ju.N6-Y!8Jq.v&sR=qD q}o~~&E ۢ CF]*EoYp=`08e]vѴMU3(N1f65uipTp}"0e ](JLGL"mx-v~]?H3(?5BGS.|崴Kc3h vz1ꚣ;`v|;L&\csG(!,,=QT_ 'Fo 0!kCM_ZS`h}W x:̱(0O4IeIcK.a9׊-%HK+ KygotrVC~ʌim1Q!HA!ECi*W|^v@d24 T ~#;#-B.p}8lդBƀȏxڃO.bψ2R:-`יQ}h ÌC+(AD&Eo!vvجFԎ=Hu*(NU!`힓杻u4C~hFl 2Ca[5@U:plcmֈ0gqӴ^H|Wz)SwLJ{UAmsY'<>h| Mizj-(81 q4z_]$cVREK.% R:yD> d{3&Ҁ[Ņ \̸YrZZ,DNx{{ KY|L8o2;"Tr^^È5|&k#kh_5 HGa5iN+lj>Ru>r"^n0imPW{VPEnK"+1&֟uH^CIΏmjmI][-6 adupsCÍT$ zxt'5@O#qS@s8pk Dt{Ah|a&Q' ȸ>9 ̗g*,Y;ajJR5>6G,9:ƛ zƭm7Mu~]*z$ocf '/e\?߹`"OUQrC/p7F%S[eO2ENHelj ͪmNZwl҈%kyrpL׀e\΍F(sˆWr9V& ZIWn5_NdWsUiJ#sv61޴]ר˿]iv\(ͷNڃ*S@lA&4Q:>Z6=;t8 IsK8mKbNآRU w^ȍdx4u zK)7M~6APhV>$.vG\a 5T!PtC!P'9UTy$()KVRTUlc Л,xC9y3j m' ]mxk^Mh' 5O)\ٚX4wZ'mm1}e((n;#K nASh"ز|om. +Oey*M`C ءV\Pyp'6@bF,ZHP|G#~\WziGBt#RޱXbSʬY1 j.~-LNx:UDImORBli!`Ew8fV쥪3#Jی%D괿Lqa~ĢtwlPJL}$T)RB_,;jᗶTȻPbEfdnu'~FL,7g1Wr^vxAf,LFF#W$xoNEʈNDtˆt#R,ځ^ZN$ӓ3L=|*gc~6-LyWۨ$5:YU$ζ6uGz>[ 2 (G| bAҟ_pb m.xk?2↶Aq}?.'Y0$"{ʓT#>5.9F)[峂;)6 ɀmWX9 ^}u +竗WUߤkfUkR P̐b?8رGj?$+ 8WC jå;y.EA[ڲs~Yb4E0d."&,'1k*:vŠ+T*<;_;hH+ya))2\Rl"{kIW} Z`3úOE4ƑjM*+eHCY|FL N&g, Md+෬'+|{@m6-s VSc>BoD.t` I'F.mFn3Q3 v\?뀮owe' @.6JY3H^FNkw?횬7 =x: t x l EeS`,HEeJQEAM|)&a/b7ߣ+!it мQYǹ?\S3ģI8;3C |?F\_aI\ȑi%!'JijlS: ~9JsY>| 浿gD \\}by-J7PtZ|^rt) e{xb^._a;GeÀ6Щ )Z֭`{E/ rEJnZպQD~"|x÷ҌqGE,[/њ_EEQ?pZCX?Y"LԾª2LGF_(=M2,Z.#R!vY dB+*8r58_Уm9 qQEn;l&J`4?dTelzV~ P+/ @gіR V ]h{W?(Pe_!5)jK̺q~Yd,s˗4:'FlVQXC56N/T7/]M̚މq@>})YIr7Hԩ*H@t7Qzlte B qq:W}y^'$Ypd7q@znԲh؉ЃD`X9hԁ4A7WNjc`;KtUer\a,wsP95hSv|{(y܅n)f!odlջ~ޅpLK?j5c2׸Ϙ2Wo˨;z'⢹oPF>rI3!"Vfzgy[cDնpI zJSS/b ^L! ޯcS,'}HFp UHmTnoU^f3-T>dRhC1/~ Ƒq6P8by>9LY%”{Se`m8=i_Ck8΃^űJ_<a@\`@QfT1I-:t|Χ%&^)8H\p]#_[QM` qs'DMf;Pp #>'B/Ճ%}5:٫Gx14%qֽ ){u  +c &c1}Tw;G-Ͼl~(N`SoJӓ6ucdwBXz!>hk{+DC=*׌M~SFVl&ψgl1N/>%Ɩ,͋8G%'!yJkUН4ٛ*IcY ;A(m}evO) 8"[AY +sC(5 ^ s[Nrͭ)ч? _o-";7왨 E{rYh9fFP$1(ڈ_Gax8t;~UCqdc/:+^^F&8r nhu77JšY;ƧЩm{]8 2[E+zC)1bI qx{/m0d 4ToZ-y7RLb{^qo^@xcSÏ_ ޻`V2 8@Q ƿRgah0d[{y1. >ZϻQ_M#jUb2w9,o\&G,u|mH@DXi2]+ݒ~G|mu"rkc벙%lrA]ݮfHtSŕ[iJѬ:ZD1&a8hHq7{ IøϛGIBDjJ3Rm?lgKtS Q̀`jT/is_f-R.@e}l- 1'*CI=m6,2hxI}+j/oa%XgO^߯TELޤNV.dF Rۂ|7ܒ2%5і.v3Ǒvz{j:4@Tkg:/ɱSiֆ]sfә<\ 99ˏ\OηK{4"_Jdf;ZcL0[g_VOa8eOSȉ驴l^'=+㞒g~:%ӌD $}gL_iXԺ Ԩ#+לK M?ջQo%nCJdzP@hzZ\##* =x~tY)y?Edq9kL#aIcHEhr ]w0#U})\ it'2xFsR'`;ETNA`{YӡO*1FB#o?~x , vCJY{y(X ԨatP &r9?.Bt-8x% OI&=g'{p* 8=yBT9kMX]+(BF\}6.w\8ǡU".@V0O.Ȑr: d%X63A& ;ub+H&cDwÎt;__cm,#[b'm陁\;׺ % ~\@FL-*|u{_uG(9KrQ}iK3I+~ ţE,c=El-󑢏}[W.PlcvZ;1)dK},}K+N Y :ߖ SBrB~mN^~YvOl|}M(<`}Zy$+0 p8Ze2hLS㴕.>m*REZt1g++"ؖ L/,,EhtIb<\Vv b |)C {tZ^6ev?rp6J2Gk*0u[+j9n_d0؆]l`IH҅lᷮ~P Fy'0ąC]ZkӵYڎ>TkXG2JԽgkF (pe ƹgEȳAKH>(HN2^+\Eh~|ye=ǂ̹CdYiBîԷr_ ak-_f *ۗ9ը ,c&d`&aiVxQu{v/{UPQTGQw=$tXN إ̝ωp˒/\(SZSD#~l"_/;Eꖔƫ[_S7r QJB6KS|Xm;[HɴO H;{M%wjrotٴAJb'}&iY0+䚪dW[_MOK~+}Ž'UoUL!we۠6F:S0&k5'c/>@K3,j;ݯA$"/a'X݇gƲ4-ÿrY&^A1Da>rXb!x(Ӈ"O%; UX~aCPqO (TYX\@cBR:KFN<} {Pӵp|R:E=F%sćA!Z½}͠0/~ s8mTJ*sXt'HacEV.]՝Uj gB{~>A>WǤ>4A~lv1Ihs(WSjm CXS&dK8f&Lc2M=Ub|"!x+XE*z_`+ [N0Px$^­6h#~}5qL=aZ3|R8J?QFQp' t`>?R>^,d+,"e_3bSopV-i"s6P5Żm,B|_0!M |wZhyw(KHͅ)]l{}_qOqA-qZFxq{tl*-9r9@3oVu/ʮCc|＀.r cy_-xj /MCKƸmc({8j{D6\ ߯16k:x$4I0[ ia"K#ۘ?$'' XK)|౼NPyh}ۚ `Ay$íRC'z]0 TTZB;e->nJrbv˂jh.]_Ng׍l1J'oD퇜4*{\|cVtn \ o'yVkX޳eV-|Z{߇[4C&F>.԰}59,k#̿I )GWYJIϫJ04y8[V Lk(!pqfO)hPd'b ꪉЂ h˳"[H*>8skobKSZ5y?=]B}P9v2K{5ltu]y<mZG H2OrDpxPZ@*`L y4sb!Ǿ^FCS"cr^7Kʰ,¨2`ފ7 : k:=\ƈ%`AwA;u10Kys.9g3pK ! ixL$fUy X(-]rO><Ԉ/+1 6m ]_ rLk3nEVt\MsW3AV4;JL{azxk7t.gp#ݓ}VQ(C1)T 9Ȃ ; v2ٖDY(@:4 {M ?5<8Evc:q6'  wεAД[X݇ M?{ԣLveO4 I+ ޱG-g7%+}RGwj轉^fS QuӼ{| 3µ̬]]Y5doNxUɠHؙkD}Y`5=0J<[BM~ ױs)8 z/N{ӎAj6/t5`} a =g[Nw*Ƚ+Q oZ!8ivA`93N$x&i$# &!R_UAH:n gѳ@}D-=C,W{jj(+PěnWZާn7:8E&zU.>W>drRYplLXIR69|3$de#fDy~h0;/w iPyң%:"/R?#;}+> ui+}~E瑫7$V4o@/x(9Isvdu}L8h;vJ bZ)㯸vR3*12T:rÑ󧍹[$n+ DU Mkx鄩@EQVi h ݁/i5z"Eby{R-0/z%P6>`,}bu.aݹwEe׳CߦIQvθ'n2wO~ <'Mb`OmVt#RP I:M)8v& 'EַयP{y?}zFR $F #JS .!NYNN.7}m!XV%Ȋ+>xPr2~ \S`}%ʢUE~lgscM=*ң@ҥ,y_ɨ,.c`~Q!7' KqVWxfj,mh Y >77Vw9Z;L㨥R5?Iޣ+TZ]9-ɼ18׺CrUu֠qے|3JuHjPځZ42]]lbFd~Y<GZj oƈ|GUy}ʏ{El^{*BmLIQ@Ѕ'1J0[_l!yK3SeDiI?G.dzVemI;sY4{xits&jO<;_iqB`{I/hYd2$;~PzJ3B?%k15A[VOkGӰUiLvGq4v”%NZ^;,UŐBnqrtWyڨ}t>o>|s4V~Ѽklh4e]AQt) g!q93;H,Js>ֽZ؊/~$W;}E+r;ӿ[>$Í 3? ]Gi/aVS ^''zG#փ1~~m]ʆIYcJ(+C`)hBEә~{()"2u+;7皀7~f ƍ_TցTYwdz0i0V !LŃ^P񌂟3ih˳M&蛙=y"PV7|ZB+W%0A= Rs :$/',?hD8z!uGߞ9ư eDfبYH}{9$k:-N쑨(XªMKV#7C͒-µdanqAQw8z-o3m,4m+aD0T}.ɛs:T]픝a38L>n0D118jzU f72Fh0E[e5at1"q^fd"I8S_k}Q!P,E !J*K9 ,jTP"&8WF8W솗XRl4V AiId y;M,W)hA}4Sh9 !}AB}G4*$Hb:;7e@-gg_Y3`7)?a6"BouXh򠛆~fćfzDZێ!Co |Q(m2AЃ⋰GH}R &On@k2ZN:He18)R^_)t;8 /Jw`a6j}ȶ`v,gח$6{mHԸяM"iepaJNE{ yo)lnm@'BA#L?%kuC5 C +i-F,}hOYٰrBGQZ]0nTeWv1>㨨$:vL <>edJiP?k- R[l{`K]ɑeL$KGϴ8dOrBcR_ս{'ڤ5XiAWse (Yg68D' L+,Q՗ˡ>K9̩IdCyD( DS@ +-4Zrc<'mU,Z5J_OneloC[2[#L>`YI‬1w[SKj[x~RxĬte1Ҿ9>^j%lrUI֌N Bu0x}2y~ !y+hiC2Ŀ3G̃hZ ^8Z\ǰ= WQVP,xtK= 'N{eە WlԘ-5C20/XSgD vv϶OwfrD1 &ųyz%ԲT}puH t͕` GdykA[׹h4])B H&wa5о?Y=jO-n^R&{A].y=se:N?Ts7QAS-Gi_C3L)jMD=!3 >,iZ%'`tx(I.@Jf&g Jr0C<CD넒Gy\=2OM<۫EWWxf$e}r/>6-sO"c4PhgbI{shO{=(X=xBe;NR\j.n^04vKl=r:}LܝSʯGWmlZf!KDcw+֑+z뙌cӴjQOzaJ-|N7uI/X_$^=͌<KEDI mcVg|n| 8z nmB_Cz _>W vߎ$ܪ!1FABҀ/AWyci:~Wj\0Ct3Pj :P| >0i@Wko!Q(F5HQ` ҁZ ځ(!Z )n@q6G%)HdBYfQ* Sq\(-^bprL(-Z, ߿[+'lҗ -xm̪3ɱ% IgF"R#',gIV)rM~ H8j]233ox2xTK05h?[ׂ~\!{.a~W pvTˀބH⅜6=}I&D8 ̼*EU5ݺG&BUꙐ` +'_?veUEQ.t¶]<azRT;Z,Ϭŝo%zuF. 擨|DaҖiTr4B`D{\maUy &Qmq;輣7Vg?B ӥgyߗuf1Z@u&wk*d ^uueg=n qih;4> asecEb=ǧJ d%oB)hE&堔P>+U;߶(:<-GGs=8mlQ >#yLDay45;<(ȡ@5!Ph(d gC`w-Tx.r %yF$f_Er.@kf N0Dx#(s[>zDNhBlI{`,Pq93$ #٬iFB!U nny奕Zۻ>tL^7&Y,6 _CeM;09 #2LEd=ҕm=u:q~lGsCC|Cz9:*c2˰۹,\jmglwaĒ[JEpK˿W$˧_ϫguD>c4NӿfqfP1 /~YĿ]뿿I5ƛzk+V%yQ|>GqӻxuLv܎~\Ov|v^VC;m _wE_`8NwE{˧ڨ_$%v4#eaUzOg˴鑱ې:[Kc1y)$@$w^=;fg{:~ċQg]$ܢUɉ ژ<|qϞux 9PAfqf9+C.JO3]3č"@Gu薶3#̏z@=4elޛxyZ6,9s%YAO/$fJ rcp4RxJvDl{D%bxvYe$a8ft顳f(ɗD(i2[G&mˢzK"a = L$|{ ^Q`'R= wڟrkwt/VF8`4C5.`']ʨ/IW z@062bɑkDh)Gq/=hj}6 n ?՟A ~ߺiW=ʂ]23Zۏ5:P7˼q#٩سPWp!D] u>#.Ca٧ZG ,>u} D.zzJg fT`FwM| d̕CvR O;PNh'g n~[U+9m[uC[Է&~ྦྷ_1}Շa޶͜1_s0ճ_o֟&\Z9S_jZ򽬵.n([wUq[7kƁ`LVyF E[[teFN`!*#!7"~vKmx"-w:ze>M'έK!f $O΢͠5 q.xұqRVIDLq9C=0,wB A v]ݽ7qG7Ûl{3Y`f`.D 2='=鞡zG\ 56EOq yctZ @gơBmz-`Ѿ<椔)D8rE(̉Z&_21wN=fP.m;R& 2eRW4J^"+[cr;9+`ė-JM*+gה!P Fmh Q632x=UyU8ץV97>A]qf'u@ ^gU'F1@'DGLy?ay6;Z~N,-;UruYIh.m=yWΪd{ylȊ YMOaP ^-Q׊ro2rG_j{e Ҟ{Šg,6g43O}Sz^[~}V,k;Գ&oup4e-W䍑&B{xa ?:!zDkz@PBp[ًgo(]ά'Vȑ~R(AJ]hʹr).74jӼxO @Svy~VS%[5'> c3g@}I Bw((M1+cc_39m G610x 0LGR@$h0,WZ=48K8S86irPn}= 4>BÖ5 v -A1cxщHdSts΢qB8CoCT- ,/iaR̄Lk^u>$F<7LRtN RH6+Fn_.%S6Z9ޞ`|@ɟD8_[0ۍXWc]}C>| GKZSd9CqGߖlnTҬC[m>aεZؐٻ/d 0 ;nq+W$_IZ2O~ KԾiBCtixGfe}{t[q/0ZEs+k 1yUG}SתZQh@1Ih`FfʈȬHx@rt0 3fs-㵾U)jYP6V۵`.-Y{o#Æ s"!vz3a&WaqMcT< ݌:3xi2& ہ^j`,e{ +X2ӟY;m#I\$} O6HOOQ-d-}:m< "P߁'d d>Ox[%{Dov_޸; MRCE~ Yi!V@GFhEE2N7jY-i#(Ҕ4!M AYNZ{WNfSI)Q?73Mq]=&O'1}&/ٓ7PW ')!D}_[__/>5XXuN5+4P3jE9z(T7(Q&=d3)C6V @˒xJ($Y2+;taK%n lg_|)4ЊzBWTxVG+%j^cj9l7m`jIqQՠ2ШQV$gz>iBYsv $ {1o^5>H[ծvr7O~m|T߇w< oŹ/r;'ޚ7^v/}gQ`7n{_1jx8ѓvћ[W 6ѥ&cƕ7!tk.e"w1BI6EZFŚ+J`(¬R/# 4#+Hk5[{q72i ir_^׿ic1a;֗"0Jӏ|E]~#s90s3*dP5:fZ8{&|dy˼8myǗ|r%v)Xp]t% WkJž t4Z\D\Ȳ7?J++4TgTl~Z/U ѩѿW:ɖ0/rXsz>95Rt'ZN<G d.$6/%An A̷rب[δE_8S})1\k@S4%3ДMɸYP4[*R O\B3dNLm|׺t_Z%NYm*MVזɢ8 9|&JUV@]^H-|(gnRϝ[g2^V]򓉤ldA9p,{뾶0 2"2.5X3kkz\MiҌ:y٤_׏po}<~07q.~{cuaDo+"iŒ~@;+F(jhh?ye +/I甇߭xߟ7!' *o'#}C|k}ܴ?907s307GN;Kw{wՇ~]%TvXnVNY}86?i&(76"ispެl9O'JB3|*q8pUPh2VKh,FaTŋ}`o1V7Y3b"+~83p3dprr1O Ft'&$ގ*[}Lɼ )8 EKl͸klƳY:<Òf ӌr]pI'y\YnT@  4XNN, [ RK 5( \cBL<[V-B}39k3eq%{>HSQMSD+lZ%Wk<2lGSG ^˂CL=7p[jIJ>0 I5D.*taeg9@} gvbئS}_,o>%xᕃak9v2$=а+gשZjڵ|uvSNQϙQ;bF?L9կ[;Gt04= |0)]eyM/7AHBJn,tJnjT9BO~LB8OB; \ךwXv6fx Qi-LBR=8MS굄MM~F:GakKAX\&BᵤvnKJ3k՘$G f{ U<\`>uNwXI̝L&膊M{Olk~5t+(02ޑz\()_( GaOKWWԠQ0R!O"m>/߆> FB +@d8d%MNL;[FaKUFT Yd a 8ԮD󑖪zno,iF'UnQ(#VXlry5MgmT!օ˄}d}ji,qVߝ9M"FQPh8*-9  Z+RgR ~)Űu{id}$tR|(O(z %}u[& GsJ=MߍAץTҎ܊.g7cց v<ƲEz\M:}ѹj>bjFBX_59]H*~3eagw y$"b*DE;{! v1ٗ%`zQrziL]9o[,J2d@*mC}^?ѷ^gtw`weL4 6zWdL4ɇFoNX?.bH`v!_yYAgiZ&L%ؚؚo%xN+p>(Y zTc`G樚,TYe&ɔ#x+tA0.qFXSr p#miMBN'_%{zE(I'bC9֫=dۅqHQӨ"3o S]E}#m<AN7܄4.vg'T֣S3t<[NMyؔKLy%ȚȚ/iC/2p1/ؘKLB!(eSb(lĻ}f&JR PLv\D e6"+S a;32-Ņ"qGL CVa\@ħɖ*[ w,񡼤\ =zi9ȁ'+;.pxBfe{{҆F9Kڐ67&l嘎&1'o&|I0l`K2vL lE:9qVԤ*V /;Ge &WR~Mv07a@Xq 5d:o¢^TG,a0lIXanjQ4mUA.訙6Jzf8 OJRQD#n$cC_vGI7;l# [ީ~&r;?vN"NON\Cdz\3/,.149qmiYGkUdD6(ʙ8MEV$mk;hM `[5=3)y 0Mmw` jJPzAK)Y9b#,hl sWQu-p 5CMԭ펂 %U&1,3pGngX\E̖p鮑X%@4Vt!t_|IԳK:.iOڤ:*u D1Nl0@2\ϳ ٞd{ zO 1g{^ixg1@2 (d^"x&38i@(j\\C:Q,0F BR.fq_ )L'5/xU%X/,%Y2+Њ؝:gL.3gcERB5z'{eN˱qbNW UUO9u<6`+Geid# Yg]&Bmsviws'--ldq5؍wy~[o녒J O 7 &!__:zAѿ*1 7q5FtkU@_*8Lf#n&K bsPϋ yI(`y@@z5v\\5̳TϻOxrVوE}L;;SwT­]GDQq4l)iՇ fɥrӄaU$2lŅL8ݭO̊ZdOT-{'YHEe|ΚEΎ*oIzKZLD=_cKƎ K6:\Tv;,.tBcz ..$PG=*} rYOE_ACaWI& ĿDys8*A#3  P 32U6m87ď"Z߅xE?뽧H/o}lPE5; a})}P''EfmM*h?~($"_H"8mGWET8Z+RE}N7I5^3B#dKLOQ[{x)|:=K:8 ۰rY} SW봥N\H>jʊlV@L|Y؈@@\q/F~`OF:4J(pt-K5UDgs{kS꒻& @KL;fI/ٍeTlO6's* 9/K"/ QrA!$fH1lXG!4T ڪ2hU-T"g3F|n)% QHM,gi?FF̰JGlYV|D:W@YbsT.WRC.GiR}*γ5I6+\Z8l )Z 8E'Ȑ*9[ yѝ/|'+38Ex%!#/zu{}@"8B@@: 7K'"m(jVk9P:MR΄;D$aQ,.w=69,=s!vM*b9;VICπ NJ (,Q`P*߷PO3b"RWcDeۓ<-Ī]PYU n+&*obP#>!AGy?Nm%-b'./%Qbgb??H#p/A瞨F{j o%Daz)EKd7Ӛ}C$GGC<[[cF 6mv8p[a7uO졉_R@{NwRR?ҋ 0IYJ*`F'&2&I<#Qv2iJt\6TٞpYṰ(n2b9%u%BP#討g[,56sY1qjř9\0}`*8c]6 6JIZģ}!ߚe tX˰rG˛ l.z}b5K-D2ɊY 鞩<[7E8:`υeXq_*XN>[t3sբTp\d))A3Sdri-\FS Ԁ/& Uu412; r*A?Z-t.9JmQM^?[rD/9Vs%GG/B<2l.ڴ5gYas^~=6IEzrLRC&'E^Tsު,F3,"oH#o1ِ=sڷu'4TpVRI9/U~FAn O&,f^]D6f^@:E9 *7nזRm/U-GL~Xb^ْɥcdn50$9+W BfGlf&/Ju);Zh{y0dƓ+> yTjl[Ri,u)k<+\J6LȿvRriBY DeE'BԻo67r\ a!K{!4z8ѧ wzIN 9l}ph4nː$C% l / 2Ƃ ο%o s߭uvd3˘3JQۄSl jzĦ6B4\Jm%ɩ2"p-x]Ree<4sUFZ~hT\ȦK Ap9!8b=VkXд2ژX YXi gjBNF!ދnV0”5O-mkN:cIKj[ѤT MV0%jLgf?^ydAF`t.ȜN 2LzE9"DVyE}kӔ|_~aa&%2uxD9k飹m>>Z1G>~A*3%#%`9(t ],A(OˑJ*n\yʲsRg sh9e\%52BPf8]zO\7*W\c\ltzANa7kR`2{!Kv[ _^&noFeeTK16_\a;LU2)QŹF]S oMIVNahkR+WHm*#alLH\/~=}>X{Ռ \X*2!~¬JA%Xw_kIrXxXkKa +>(gNA/)dKh;͑KdU{6jhj $撧6m>My'cawX_\[Jz1jڮKk\ h$jh&+CW0#%76m*NMnJYvȏ̲tS,_kU23>d+L{Mrȷ4Vϻ +E4n%Ė&*1Ͽs/F 1|us8 iK;/8ErwO~68Dz% 1-mǸvۿ(nW=աwGHX!U%Fe;q躄 +R m6ڛ 7 0sZL_$#y \ӫf0JoRJXj'^zcMםٵ(eAk[h8 iJUKzK3/aWgC=|p 3.Utc!4x1aIs G8A[%+0֘Ĭ f2V dT V/,-OA͜<; od^9i'^:BVPƒ=+(VP AXR7l0uZ/9([Z$jk޲dĆ:gݍ:tJZi(hdRdyeHaӬN-M@AVS&-K- Fb(YO̬cҺPcVegÜs2@߭gJ =u¶9: q{VlaC cH!Ci~CiXa 7D_.0+p9sϒQiJfPl2W1M%+Vٵ& *tsõlYąQ JE&Xl#S/b0-yV\E!~i5r=3v2W >B`7]z/ϩުc/yY i*l^ I1 euqz0 V:JߵmNꇡʉY7 7^_P(7'/3 >`QzZ=G 2U=7?֧[pyeWaJIpE'A‹~pDq-xo>7ÌZ'6RTu-b/dP1J7P26tF:;I9r/T]e3ձSlT|##X\lCQ9eAI4LX[$ZqUI4<rR5 s]֓zš2oO na,~4\oDs"P Vȩ us~M惭~}q-!Ɍ;0$eSw`'ќm_0anVak0Ԏ]~Á <:VG8p/ɏ=p 5XՋV6g (X WƢ2(mw#ovT|YU aMN:I{ Jŗ$M Wܨ,[41룢>Nf3mg۾/\:*a zrI7[de+/VHGv.Y{ħds+2n;tR-*ң 7L r0 ]H5R.ѰN^z JkNVʇ7zU"Gg^nSZ#[K@oo'\JU5TÔ7ϺܾѝK% b8 gxJދD{q*Q l|pʁ2C9PN/: Ŭ^*(-׫D{ 8!Q&OufRRhX32zY/Ӻ],)&ܼPl)ooN+̚il  t+MGOJͥ.+j¾e>9ǼFvz{˵NEL%\\Ziw jϛB9349c`2:8@(g_q( `i@GHC9Cqmh n+S +6W4snFںkUN񌴜iVSe'd8I=gɶᦝɒLIi8vVWLn*3aiAWS /豹g ?%j"8%PĜ  " h|KxSqgGQGFa䒴x=_{{xmҵ}J2RyȠ*o7> EVT?'t{ߺ>_9@[iV 4x^eBRʶ81J@ LkpZjnX>~vjjãa:}5!It &$(i "9$K@Ԕ@Ikp~$c <!D G >|>bݕm)0//IazvC"v8lg^/ /wݣa<9 I\9s8Ǘ#n9 ȜzvfPOZRr3D{;Y17Ja0>]V\} OwM*_XdjW$yJ$J)SfAdqXS # !=,̰uY ߝEdYe䌥fTˡ¶7uB;3'fww$JBg3teo'ԫW竰V?1Umu.1EGBGAPL p}s7DVEڌSQ$$'QJ}a#/b8T8|@ sjme_sE% ЭM{>1{a[ѝ4!x0mp?/ F 8 {:-",KpZ;-P8IOp>F2H.TS,Bp?"INҔL|CO\hY6&/ ?\qY,+4{7cX`rȸY}\udRuJЋ=b8Kɬ 3*cݙ+C˒ (Ębn G](4n?3gQz6p7I , L= 4RhEV !1u1BR'p`aI _](;G0#4FTv+{tC m;K/a ulMVB訷?2\tNh`8NTmH4 0̠RqQ9eꩧ`l`襶NC#%u!e(.`R`q 21}?C>Ow̕~|(n}Nwۺ|K@Hk>oؙko_\;~&$Gs0 cV~XI0]ʧ+hYw,މz.zO3; d oCU~k3nڤC_ xp* ?NK<mCᑶm SJX0]v.ȃI3O]Gxn> Ar=@1#5?-C(7)I,&(з^qvՋ Dh&!  Idp^HLb,(`“SSKfi9};,i!Kr+r"uw7u'puXvo8PMKՀ\g#0]˴' j\DadŒ5gJSwNϾRY_w:56xo`fPG ̟̬ #8``25` aB\O`iP'#Ҵ.|L$23ߋ$B;"a]x:bxw=g}Ը :uK?dΐ{cO@k+xƒ^%spcūaxJD[yb ܁`GRkn a 1;mgDEꯄ ^⁳ y/Hj ?:>{h-ع#6żfqb|$ ߖ؋GMӁ=4Z\pcQs 7lK=0Фdn[C,|^ K5Rݑ{Jв }Qߖ>YbX*oO,Jny|ᮤҁ%7B;]-•Tb{17/́k Z` &{3v_b4'^H:}lBK8vnG{Mnލъ6jɴB;>9f󐗇Zl"Co텄vywԵo"a<_nT8۾L22Co O<Pp{;ߎ,AwTs$_4|FhcfѴաpHp7M$\He.-:6#ȸ$n uf!I$Ͱ\]物Nho|EJ"#AT8/a ?-ba|c%^:g̃ˍ;j\ sX'PO͌QVl7%w 'e dt >/ɁEEx/Ñ ܴIxX ԝCȪ;l47K4gn`?"AQ7&ezN!֙}ܬfh|*a)p*p]yǽɔĉHbM~Xɂ@9SH4Jr7T`U/G:d9Ԝ7Wީ3X\.#:Ӣ9gfѰ,lHzvnCmm_49^{=t[koX{е\İ|a? #pRoȠQ L㝔C KǗ&^)|p'Fc W<<@6me}/(z4AΚM߼ͺ,ryGwE."x%ˑȣ>M~X4][<÷ ͐$av-=fxJ,$T7I*s=O_:ɸ; 8O_Npͧ.o<Ո l^E´aKċmd܇/2٩ zB D~ *O~X_p% @9[ydg)"G%o ]6o*WR_C4ѿ3c]_Aj(rdD߁$P-C:pB00rU%QC,£Y]zgcT 4p<{E:}?>?Hr,K4uE՟$4 ?3T]H|2S߁2IZhe5!1M# 8Bۤ!vT<Rl4Aid=FP;*i Jy`zqE ݋ E2#YXh?  \b,w%$ a$a&kC`5(fSSG6*{Bw^.e:P%PgE92<)hs/G,O2\c 7ɄM\. Z6K+Ў~ h]&.(j/xVs$sm6 7Q wS@)IbdgeyvUʧEkk.$2D522>H3LQ"u.~dY`85ìhOnn xnYx%Յ WH RM﬈'nk+ =,29EVfOkk`ެG Kz=Rcc}P=>`2,EpZh~]cɟѭyc ]Doq[N؁&wof7on`AIn%Q%'C^|djUIRHJr EVj/Ib`u| \Ռt -YSdhhJ2(VixLzUpֻQ<ޕNfZmu림~M6^ IHuR*Q*}SNҥ4\.YCs:ÙfZms|9M$J^xPޙ@*%$$nT@T,B܇uT%֮bq`b} ׶8pX\({ۼgu)++'d6IkOv0D,JdVrE1$('g%dﶒk;Ŋdt%3 "[bA;%pN*U%kNrD"c?-98`;fg8T?h地;.$6aY5ljI5l$TA@٢gڎ^eIe YfqZ WtKa*Ug-X?mX1)aty_*U{ LX׊FG ƓIA*c%td`s7KRv]'r2~yl*z6(\6p Eh .k kƋNeO!?JΖ,E;n@3 j#!BhK 8)CuuE7SSS~s$n.D@wml|~vsqx'So<DЖb¸m]MPQˀLp5[XUnK;1`UD[KA(]2;?4; Xzަ:f"1mYi3Vaы1/{',l1EF+ BNG|}[*rjRp`gțA#En ߛL$jyY{ejۻ<=F2ݞoġjIGqHz]wr Nd87hw8(슺zl Gc"MtT>5{,-*qK*yJ3as! }<5ZS4zmC4 LˌUmxEɼnAOI+\Yj ]IgtD2,Ш09LvF9G:\3j:!em 1[Lh\7S/K$8z1/ʏLn8%C4EE,U75?}$vI u` [N<9IAˍ}iYrE%$L 1D'_xMw[W4%_#y ޒvS0}CĄ6RY?ڊ 7h%mZ?E}I hNEq_LɈ:_FYG]%)O8/c\aգ \x%mu9YJ~N7R>&0ٞE f}hE!pj1V6"}Dqx!$٪cMbqAP%zCEMp5zL)Ë-mUqRzaCWxس&P\B) u %+H?_ޓbLT^Ue*80u]!B$5Jjzե\:c;?UY5A)62Tf+?ѸOLJЅYVŬ!bAYl ;Ji>r⭕#q񲓴"EaI |VQTl FUM.q&m2Dž>YEFR]ˎ K#3}5+# ~jڂ"k"o(t۾Tf&|0:V$܋! GJ̇8av EOo-Q}H˸j!k I\%d>_=2KiW~ށ{Sx2g$vGP~/6u>;xpY4}PlaMṡRj9jH5)>#g<,[Ia^Ƴ(*+l8l$xff"V5aGPI;4"ҟn_0RuIяM n)nAͻ " r!dT[l5=x~5ɛ/ m'TYc)5e1ض~>Uq:O!o$pY"ZǟA8jhe4q}p SF˲trOAh0󋚦I+tT9m)6?9sҏJ#ݨgNzt.GE5^c"S,p$ gY8?88^rGdi}f_6<2IX$W%#B[L`Kj1 8r΄D^pUR~LU 3 &ۂ{B̙(gJVk9|冊bH`qeoxj 2:}{{cLB+jӢy]L)kCşm[:3 ʀmb E69 C94ѣ?L%CS aRڵ(v ~|83%P`= *4S̰ 9"[1 }ym[2b6$ d Unے*BņDYd"lHWeflhdZkc8D*?'; %$_Ÿ$}W}r:Z]/J37L5 f[I -12,b9.Dvʳd5.m W*2dZ _}o",8]Z#ċQH`9N>/4`-$ /O7dBEFY@Uݼab<ӭD7`{by(14 4A,W~1򼁕 Q4TޕmHkNB!f_ @OTғvpE'D9%0Y"bWBnGoY8 HT 3wYD-@[tȢjoYL`|%D _*΋:?&zA3mrpBo}튋 Q(y!h}AfLulԜONE^T$Xʔ.kۻ(oH=gxpySTivxXWN3x.wI0ZJ|1brI'5PpJ @ązXV,*e -$-{I'bH eA-Ig+ۗbn='Xx?49M`rcufLNDJ9WUT*1%zpy *3\]L*rw Q!|лYM4]MS#Weݰ\PH%=SZtYu6~bR½)̛zn1PA6kZ$PJ%!Pg,,GpzPdo {!1U Ͱ;J/Ɨن|MIjY50ە[L| b)!YRl$cQ]QQ?Ocֹ_!(WgA*Q.gv,[OݰU^Mf9v4 ,[ۼ4 lf YOYԩ]ӎz'2ڪƂL~K[qUe}Qnm~=-Hg;ױ#(N+nutAP-AG,ӑJ(>Vef94wbꅚByCdXϷ!iy<]% (讹q~ò] S~smI[x汿ɺ|H Wj=Q $$.KGO.5듺MhX~ZwaX,Hw/֥e/m\mc|%dsӮOepHiv;&񐥸-2{{vص4Pݵs{۹>-#\wȌTTzrU(<Ȱl;֚MG VAa`zj11O,[yՐ[btUj[ޒ }ڢ4dQyK;wjzYe}c&HBi'&kf"㢞$k!奂( :GW48dX=|sq41zc !x= f(_ u7E.f}|sAX 7H%X3(Cz'>0WbUTmI3r1h P?o:ۜ\}\Ҕt^ ^FyĞ{0lݐbݹ{O {~{#;8w~g0U4 aVm ,A3 㽺 2@;#24S UEGaɩQfo?@vߣQa` h/GTZ*hlI=tc #[ zWKh2cPqewOa~+¤z*[7F[(rP@yZT%#4#V$݀V!Y!}$L|(1yK9zJq?>A2:`}$"丧+z\R}92]ˮ\2o0,[x@WNxo*q8ƍ)̋\ack] d]\X&))j pٻ0a=Y`օj.jI7SFhNE}.6\mjwI&ܑdoo;3006 r-9w!\,TQHt }<5Eҙ*ۏ({tarSl/h+VyM;L55K9.M^Mp5[SsySS4je4 ?Z 6 őK~Ws M1֙ E^l3DV,;T>,;-W]ړxPCv}mں :&#UӐ%SUI tW I¹|JI@npW4 ]Ou%\~ڠ2Fi ţTE\m-t!.r N+ٰL%u m4 v ~O翓5 ŢV*=*,.669``:}_h+.w/~KG$MqG Öd rpx`>֡ |CvU.] -۶ "V:Q<1`۩J/mo^Q*\aZ/h=VWdG4JWMeTy.k9v*T#; YalCA֐i[,g"BuYĔPBW{zws"Wq+RZC&"YC DWvcyὕu%a{ǦM/ሊ(*V+p~*便 p ."p6S̟EjD4rlgP[p:yJVF]祾[HX'PhO7 oØ I}RM]TH hhkR=r'wRqa櫺2y X8(bl/mx]+.l("XzOw #XzH $Z$7!Dvi$h|N?t[T{7R,/jL(Bv9H/ؤi{Ţ*}u9)E7yXOɋ 4V0&yhT57{FXT؈ E)%v-$+| @ϹLMf_@r/vyp-B~2=6-1%C0KEV0oI,YƵrwJHDM~_pSoˌ|` K.|ëH^/6.|+\3*{+|Fla-~_8Q8ZbC }&fq'0kp{_) ж?X0_{/ "0L[%MvT5.AVk#$T%{;@|i{T-;x e$:Č)WE*D_}Dq8j2 $5 ԗ"s8TQr )8RL :S3bfXPKWB_19lضcۻO?~54~)9/[dzn)~z@ d#`E0FGxIqX#1q%6 ;qs5"8R|䛌CxL['ǖ46c#127-Ƥo {_&AfF4V8|x|.3f+` BUcu ЫYib!{72%A$4,yMFD$ا%gP "9MZtLka n*#Q?x  ?R򟭦`|]Q'Plh*TVzO,K*\Kkfc5 h9|> q:AUyG3ME 6꓏Zd;Љ;弌KMlqCW)Œg ))wLfF˼BMT#kN+PLDQ^N4*꼅R[̀\L{]&Ǜ7n?];w7o?2/ `3o}1ܑ?.b-+ەYȜw%6r(ڕkM%K,rvGlXA@nR#3$( I?kFHv Ȗޘ%vZ,~|-w&gx7˺\xÉ:VAR` 7}#*,^8bn,AhPD ],%Y$ӟk 3/<֪ڒj.ʦߤŸpE EMm,J=?χVD>?udFD o_Pay->,Df -Xp$ ]_RЋfy!"/Yj65G&I;Y9+'.U @B`Đ(\$rx*28DLj1Bb#`+dZRɬJ-ITzvv7=!*zZ{ilܪ)^b|yŒEiܓM-ّNvaw[@i,[u%LA:ƉUMgv,6.( Glߌsýpnot^|Iwo_6%$n/рd!`d(J3aq#T%Xx`4SbYM<z:Ga @~7k<)L62$]6|T>غ Tf|Xs VEͪb-\>/&Xb(;SJEs 9Ur*Ց'/+~9I|{UuFz0+?z X\_4k_&G`˞$H%,?~a! DO}G(^Wy/?Z-XC<1^ś"rdOzQ0$DT؊6#iC]);'m+˺ZF)vkb}#ZJ!I*/-&YMgkRs=m/$굽K ^_/C5D^B\)VdB1Bs@`>9 ה|@B$9phv>X=ɟ$gYEEfm(Yw`fJ^n.ie}ZG6qC!i# u#,>=o዗0@i(K+ɟgX=annޮqJDZѴtww\jKB ̄]K0[奕dzTT" }־܃ $UQLSgp&CK 7=FCmU? ߪa*Bs}}Z)\LKGTT)qn?o:%BTh./ju3Zn6;r2b 4ףp :;BMU~Ib| !I^꼙MLw+*_F|o<͹(ځKbk;moSL~)Ns6^欤fفw#Q8|Ng;I,/.>tם1[,RDWX"]U.`! dv^ hrpm(AQ<#&Iek0Mޔ,Ξhj~̞+0kɢMF%O@m'Z_M( =$ãx6< 3d2? _} nd2Ƥت&L#vujOWR./1)Y<+Zb &OOQR`.ti)e!'mHɴ J1 \ڤYxD.4 ևd<.I&a"dp{;ə* M`JeF|~lxHlv)Km=zXPK~ΣcjsȐxT鶪*.8x@35don$E Ej;` cMox˷Dr:*B{uu!>muu.߸/䆀ᔋL\5,cKvH2{^X`fqXrh(;]n =d.(d, ez`THX<H Y pE+@_縉a<>f8$#b 3jhE.*붶^ET{ 99 G&CwtɟRK*/RuF4G 2L-ou&m1B{Te5VHr1Yq@͢Z<6 klȪS}d-U`wU]E"sR ?GU_} i1b!KZ%Y/M$AM>8ub' 9l벪 **Y]u&b7}"sD"Qc.,`tgnq-QܩvnVNyWjc#IFd\fMu[=NXe`7&LvKm>;{a_mR}쳄FIՔEA%ZS4I3[sZ[l` Ӫin5\-I;&S9@Xv{I%&w/|juK=+j ٤p@/IŸPF&Bl$ %[i}j$Ӵ%UbiEX4Mє7V:NULnpa2)OyG`$)SuDtȆ_w|c|:.?ٞHXuoYN~ωM_Q jirl  ,[ ^&i}*t|f 58[UolϖeeiUM m~; !'P^H8GҬf/6)Ҍ\jȒ6ٕm:x{'SZm&z|Zk-Tcglr{wi;=h)@WjiWYpWo CP]FF|&.SCR}^ݸ4D<ݒ؟3 Jmdݣ?d^Q IR޷-\ (yK%/@phdzс"QU& A:͓' `Qps?'e X%nM%4'r5nqPߧ}%l>␤9ٙNyK@Dy ' tYy!ȕ{Sa]1򔁻C/ihKW@p5mq񧢭({dːں/To>qxQeah9ۯ5 ܻY7 cz am5uY'E9V܏v^~j1dY쳋05Ezy\Gt,=U>e0B*J؃<[$>98/R"1]M/ [}@:ݮCYE˷׿8|}zttA).rz*tdHjc|+w)Zᲅ" &-!\Cp:;y!K!~3,r]q# P9%u-&wb g=Dy{7L˜)fMc ]ei EEύ QikBY,ʷ-CPg>DWEH bE{k@JL*z1 |']`LzHq Qe> k.ZG`PQs}|Xׁ&%a]L fu$<T1s&6-HϫŽ"8[vP8N 9hȊ'Y zpΈͳ.n?|A]#Hb(F<-ͻ>xJGx$q5T2<˦:ή pDig7i3^p $ lpG@V5k&JZG&XbH nd֊/fќi?&x )#J=[ >֪6d=*u?'?) 9bMe* 0l+H_}."@OB.<:77>rn!19:[InI:tC局 i3Cr )ДՐI0`Y VbXdVzv~opvXۇi#VBR2I;M>iyGf!a}*1k " fPWyCYPK-(1L(e߲EZ{壪Tt4׮Sp Ҹ!K MOu90#!pfvŒ0Yz!>_voY}A EAG"B]] ]4u :S TnN}B 063 o K3\Ͽ\tZ@t&x}a@0>KFPEq kzBRP 4hgdRn<'psg!wU&i\ܠztk{ VVƮ˖*y|%r)2"Wk^M"q`PTY3v=&#ݢICL_ɧ;fe}?DzYwFT&uٲQCM e2ڗP6+Һ;ɒHE LiyYI?<@sQRDݳu?7nxZҘQV.*r[ \ قg6Ό6U[}O֗"TL$2< *rk*xdWkLdrRM(Ġ [F53S}W0v3x9,E^Ȅj iPq[xcn [-ϬH@lRu .$3 s_[߯^2+PS=T S%EX'K~,q.}VOsEMm2S*OpA'wX]ԏ4 DL)%ID+v2'v5|"R<#,q/\' ͂{gե+<Yr6NC~EѶ-yu%8m4Lq9z,GTaAٶ.磨[rR|ٕY `q}i"»g)|!)rxӧTP_JqA'Mc0J>X˟(jq ]ҨMHj&CKOG=?#;K΍l#[dTDLw.IQ0ԟ7G){a(">xuK7Lɇ oiE J,0J4`Zcm4-9vE0I6*~ϑ4.MT5Kjw1X v @gP|F5% !A> e8`gv .=M0M15 @ǝT:EB# | (z!FI_T~AK(a., QnL^CVYPI29t(RЍ[, v6h:%q7Gj-9<~X9؎KrJl{[CN b 6Tvf}+EB0hNi+Ys팒ӂCQBR+8|Jt4U(Lmcbj%^ΥnJŌdG[(#Hb$V^(2\)"x˞B=>DZ8wUTTE]\[v㝁BT[xY'2feBD|l/I@KB CPЃ_m'PYh)C4S#A~:AEw'&&qvh&-@dmHOqLOF"n=t荄NG^c'^h-2P1kY3X/"erx$Q}:d`Y& 3 FCt/\?%k[.Y!=n&7TR}ln" 2Z6sVR@;PsgOv}4lMCuBsf"I"'Ť~ȁ~zCKU0$9?##LV2TV#R72LGBx!M}-NC(b/dW6GH 0 ClQRxkiܢZpҤ*'ZR>O@; `b3ea3qs1zqqQ؟2ST({mA'F Q XeIfQ.9>n,,Ow݆TmS,+hzڗPv2NS,.2Pea7N6_:Yn|V ݐw]1Be2#GᴂZ"b]Zw,5)ooVd|_+-e16oF l&> 6o'g5ۯn7 -ވ>!I~F:J630 Eq8-W'rο4<l9"S o-1Tț.cRk:i֓vw%& AI?”dtV$`}*S73V2^\KE;YUF\uIJ'}nOI+qfH4w=7joR\K;S=5b<<}+Xvjh)3EIix/U4$ۮ  9l2K:yPFEμ}( sZύ[2o;nz,jeܚWX+0SOc:l XJ ͝߃72{L+/GcGUmQ?voʫ/S Q TRXCYs+ K=EQ[Nr.g*r %L ]Sn"wى=[H9dKo2oxXF$gɉ /Ņg &;|Ɣsv7$rMLΪIfHsk@xnmZetZ&RD[؆H7X>vmRm]~Xz!ä.9 &JuZD$N2tz8!z\PMSf(RF\uFo[ŹagX"98!P:%*0{ ܒ#(]0#1N @jWv}'`@Ἐ#h'Z*t=Cb1Nb@1)OE64ڍ~-e;z.I6hz,z- Â[XH܍Zp"Y<+u{;K#l Cƥ2#9o,7 B.$Ds2=*t7ҿP"қ"fM!N+I KQe|BO nT1G҈QdlBcE ɤ 8LR!|%^BNwuk-0mGF)ݚ^{Fi,&ãDl޴4<. $慦[ưxd nj+ҷ]dCN.)PH;Vy[֡)Sqy\7${yujM=b:aSUYSj]rLG[ij ybKfX8Z&&C{K$%ZJ~[rk!ۧdnq`޶Ju ;m]5!V|Lӌ$ n`rnbI'b(_޾1umj*BVj:k]8a؀UԞWw$4 mX ]OG>+Hd~[k%O|+zȄY8^6P?wKjBAiX%"NlO1$Ե2na\vqn?­6kNiuK$W\!Qb2`ІxC&,m}6x)X^tՔ~䄋iOU%_<íjUXP`ь@\Ұ{Do Æ׍cqa =GbI>)%p=&@'+ܵ4Y]J@7yV*R'rZVfe3 ٞ /v:#B n3 "3*5 ̄JB)3ky^TAWTs!:e![abpGp*Yufly# XAMțPuMTrIߩMO:u&(/2y |Aboac[ Dx*eW|`^S#/> FB)>iu"2DZgABi9]LƯ$  `}ȚفDiMܝ>< ҋtmZ9%'XC@P[b@ G#ذ~Ivm>D>5 HR3CMZFh7{H1pO19蓮Py T"2yA7 sT"nb;h;ҴPzU[)&ňŧ6GDl| {J- %q@1Ϸ,;s l ؐϐGk`ǐF aGB5uUCPW1G|GU6NU7 lV!f.6m5pd#QBX^DKoLjŗ`]"X%B5l.e$F7pnFݰUͰy n9܎xq 3<% hO؎4񉒟 0n($0J':N2D(I3u|~ an1@.r!͆EziCMfxa Or,#^̫0}BQ b nZ/nѧHY#I*]77?oZ+b]M.bZs==!d,[SH e & 7Bf)y~X}W?NbGF P ܦ; Y횙{\LC$YDʄ+2M(1TU i894v?Tn"i \=GȩCN!~hC \|B<"Vl S1Ѡ՜v:j_8ڑ%Y 5x(*.>+tR dh-#F M]6q!oxJ̲Jʶ3n\&- ytrH(oiB JVƼ$\߯#I;ȕKod4N 7:\VuЅ!G"4iq$Р7Ws&EJ iMUbU0P5[FpChIk~ˆ+&Ti;"ַYXl[y94x:gc`w :#)WX/= 6eW_uV V?> yojs^ANKWAf"驪Z%`Bb*6~ +zzÅڦH9} .1 ] q溆.fhHe- sAVHP' oݏYr(r:Mn#ۯI"x- E_#%p;1 BO{[!ݏ}ACu$عr^ ",S- f y|r!px38K.:Bbs¾6(p3Vv_Z9\K) &B!wCЂ' QL> {(Ep)A77#:Tڦ|C'i#s@PM|a -PtC󇢛=ʈPe߃P8b"=ve5 p8Q-`&,vmt<x'-U9'=l#ywӧ'VJ0|qJ@ !zڮB(sƋ9}wsNMP}u bQheuaT sM6ԉ9~O_kfq>uF!іy\%iL ON'xZWPOq5e&2 Ecg#0%B}o$]oͿq9pF3f- bi%;nKwUG])CjFxSz0 ӑ,G Ut#oUa'2Ou:ntLtg:т`l Ʋp7[AOdͱsD=<!ɡe ߣJʟn''\^B߶s/9O)F ?$]v`+˶ L9),W;)Lw@ya58Lu*?gʲO: 9\jk̯ 9 `XZYV`EF<{fϭA6Z0 ffehU0mh#>q$AO:†CȋWݲŰl^o&?@^F]* g=PG8>{ܤ l J"怫2eGq1IW˾lb("Z!vGh7&<7[Btquyy#$4ôCstϠAȱlC@bOI[TKt4Xn䳊+95JjTZt-@sz UgG*sR_B y~ Ɍev$\8(ݸT l@'MqаOn(?$)ѵbhXdtwHmTXLm }IEe"gMt'^giإ]qJ8J%2 #T[l# nRb"ჭ4eN-T>ɰ0龊FoT+}`0Lilŵ+ѓ *e|-=du|1L8x!'oORf"3cA &r I/{`X4ٴ,9u̩QS/gdTPr QI\GnWHFT.r(6n \^'ozO fkC$ŕE脖H' T4aU uYrgbfUBp],)\dJn*ᇟ~|w'8[R%4n[sd~ GܧGHqlkg OnXӕ5L;tṿE#8^tUqE'+X_eo޾{\m͟Hmr+EtW\L7_>&Eņۊf6rvd @j[ qhxLVw=ˆ95V PL&w }rPj:\lVUA*gr=i>~ 4q _%g5-Ajzb \NgAa8"Hϴzf̟M7b6'((mr~|kcMcG5㜅7fq~7FK?iyӍb38@6Py&g(Wg*.x:dJui::eGKxy;T6K@-uHǸH,ZU"H<2l0hVȺ^f.V׸gCR}?\ *lJ#Tڀ*5]A-t8*$\om#=!R@QLt(>۬hUݢxD◛տFɫBPlk'4p=]XCNϐ6DMwpۯ1nIy35Mi054d϶ LW6 - ?XL5FU-&4p~sƀBVm %otDJ32v N2J^\ TcuZ4X>"5d\[1**43u4q( D)]DȨbt,o?!õlYMGV4{E1NZDqD'A8j=#jV;ɺMwļN ɺSd)nKfe<9UknD4dj9JCc%JCB:T+G Jme(&Ɔ9WzsJ[_bY5ۺ#(5r#&*{Rc,jጉzbDnG>Os2Q.vST-JjGdq™m/ĩ0fGϊ_HykBxa9 $~hEu )Et0R{nl"v7RF:ۡ4|ld瑝\FʞN@y^ԬO h\7lfpg 2, `fi²l0c)yA!oHq*`[ ͨ[V̍B[;;4˒5T+>oZW^ӏא_|4R 4z:fupj 4tIB -TZVn c S)'t-dΘe!_R"п :bKqDCJދr8F-w}Q nc?@pxװ_{K\7l.o}XML }i jMRat&BRN]?̍fF=].hh4TMm$Ta;J=.'~zEMp+D~2[59,ݙ/ HqVg˖7}:}qGk*oL"! S$ R??SG?W_2yNb'&IdݸA<{\c14I%EZƶRѤXKG +g "H S9e.ՔhAπPRw€=htt(ZL0h+J1 hcpl`Y|vl~i;aZ ,H߶:Km0 RP]z"b`IRO ;bA'1#_J.?:Ms GI~G/~; ze_݅_qL&}\ cA\"޳%2&GnT|iGtV>@O'_'t)5 1=<\S]*(bZWV.Qz_$jb(֚5^U$YJs.R2*΀67uxGq b|f2>h__T@ŗ?K04@Oo#GkՈ7L Ը9!:,{jOt%K{J Bk DEm(?7Cu Kg{dȦj!%*mV4hU )Wr@)43K^mֳ# A`b9{ޟF:[4P:S_jV4 λ2(EgOBBUo)2Vu&z߾}m?{/&fʽsSv p8}DdD\qpT;ǥ݌ʕ~~^jf8#B2٠y(ߙ*o2 ѓb"9ʾI}l4֯/H$~.ڣ~A˅(deX<'c_|11u!eDLXZe u(<$p|g7I!d tUq5^$4HvѶ/WܠV 5VTR2xa W@||wM蠯(JoQsR>"q9ɚrQ0xrz{?C*1([Pf$EdYULʳԑt,ҚٔhQ!]Įpztv]۝Q1|!F(L&Ojjia\_~unEt P.*=ߚ119o)齗p}[U?`ʺɚ{iLǐwP~zٕzv庥rˆ\'͕: , V=ۺ}+ڒ,fToGeUr]wp`Òx:jD.%|I5spT0tYL]O>r1y*'B>#7- oZV&a,y?q f!B;KJsB'J!=`}^SBN=12I}ky$VeK:1p#s:s:II4ED,Yu$w?91oI2B/1HM"TM%م#+H>(嵒Efv&JYȪ5S^͆K9X!35$ںVSFّ~#j FOAA$-ZDk<]}Kl&ï?kLa1_dުp>i9+dԊ|TaHH98pYv\w~ a3s ly%ھ +r샣m%Y$:FjF6a9r DØndEɂXd`-y_S<8!SINd02j4aي8aʼn(@0ȁ%hP09]eWwmQ(+˫e|,vJ(#4q-gA*Hu^Q<+hM2409ɚt-p}Ln ×Q*LG ZA'jElA@M__|(#z1\2[jhz3"5*'`4 TUѩY\Rh5&4`?q# RQ·E4QT/+!f+ @`L(;nN&sy+۫ l]h-0kB%B[]̷Zo_?#10jxlo@hT"W1=1x;BX 37;Id %5[ئ?FdeJh+P/-b\2ʊ%(e5WW'OUQ&`E˭P9n@̃QX$4^(/U|XszK>tTg}.xi@a (܄INvVb|_Z@3W&gG6BL B0wfC8O~8dɏ8!P#&G\ڈe 1'g -O yCRx, ΊXMrH)?\)=O7h:j¾*' bqhX9abYwaa,-g{طDتeZh Dک".. hQ軃A æͬ&Ri_ZMh6 V.gPeH0mmq+':+I@BzPtastrQjb 6yEn; 'sJ'ܻ67LY6D" xӚ{a1כRϧ _0HGw0z{**xyd .c9}]{kt.~ǙMƥzP#\^J,9\bҾ,`qu\Q#?3&y)DP3n+il%XŸvRzSJ,AQb ؜p7໎c^/Ĭ n L8_bꮈ2SU/ I3p+bG6cq֝ZȋhJ,qW ?O8~{8/\0L[!6D$o L$ (72lx8{"]_HwFC2YG%M 2MFP rY-f_ܦEOIr~gdx4rKe'`ZгgA| b@L]P,8{}eֈ}v֪(*kYK;&ؘ9}A; zu1|I5 ܠu[іm# WW hr{J#{\A}+4{sۚH0]Qp\@geU=zߑ:/~wzr˼*z[7'ʳW 1L~`ɱ שe֨Y+xEL٫72נ>0ܬ9|C  8?ޠ/)u@N6Zrq}UX~rUQID]f{"F ׼gZ`%Utl6ž$3JG試ֆH]Pl+e+ E5kTEF%@It'vG&ļ@ 1\K"D l״k'I6=S^C# M|x~p.ZI F2]>Tt $S%_CFmU:萫KV'8|O(YG6 }i{d^Ed_* RY : .θ2'nϣ8 +m9.AI! 77l;Z8Nhλ(\Er+#L"yN) G{b{kGIda2 A;o&s-eEHcᢻ=ΞI4gr z-MŴ_W}VVBt0^|A]K^m^A?fnTE<'lI*Chb#O6%Ӡf^C24Q pSYyugsbTߤl76"nZc4Ny 4 ~.{ذu3GJZgi򚦯42T84W2e:ի!r֍p+"č$!xW&U4UZ|y:ѴnѴ13GZmվ/ tзv7 .J54YA NK{m: S|[r,?HaKa*ֱb+U.RIU>h탌U4YEQ _ A*8.'itxtD54LI;6|e["+* 21fi|0 xjF(ez$ؚǢ9jPl+Ic›&bt2MJQ\/ُ믯e(f)[{y1FF.Z44(a8ƪ'<8Cj<FkX/puXY0~7JwereXU62VWO) <^tZ/1&< N~(=͹Żl o-nһ_ԸtIZL}.-WԨMҸ2#2#;>[&>?ZeT ~|g,[a}5֝Q tHi OR h`'nNK%l݁xQVHxihUԶ}K9)=xReSGj;$ӥSXwywԵlCEž#6KL `ɹ̅%RPڸZ0R}^0t6)wG8[߮,nȶhaiuCrr!.t`M#Ď{؆p`'|B Ӧ 6+X#T9F`h,B UeZ=i*XRpU .}0 Gnꔠ*,`\eOns"z|DC]Hxw(&-&.yo՝AIV:F DD%^?[@ :M8_ g!1s(C a XW:d,F=tFdC'$K@K路NsbX"RTRJXBej]!acE4X ]1ۧ q<#'!Ϲ Κk`ۆ + +bǡP$l^T352NWK&PR]%#JvMA{H3cP@齀 T݃1{R0"Zƣ4T‰ n j@lLeJPyQ+r?eسL:Ĺͽ`ap?"-}ԌPEMp_;r98d]]T*AD`wDC?sX8K[pPbt{['^LUZ[ VQ@i2DZy. d o({rJ'Ss;e#fч'?J35WRdɬGCpW(,f ڌM!4[4ʉxi-_j?! ָ;R6[G p˳\ƪ⊺hlGaH,RHu᪯d ?X`ʯCZ 3ښc?{ 4aq9bOж8EREIjzU %#~w  bFCXAT`vRܼw}/۬Q43f{,A `>g=|A,9KKTa. bd<9Ж-o$ɓT}m_&~P)k~US l֧lKsA: gJ< ^$EוZGAS$є \Ħ1['l5lyؚv4g 'FPMQ.@Zxl \]NQ"~jNm],̍۶SeWIQN$Eؐī8z6߾ ʊm2&kb7P4ږWxqEЬ;hm]' Y:2$A*׮'m82l%`+{+zszD 'E%&Ւܖmcr* AS޷]/!al)`+Gm,JG"/ԑ($izd&D n 0Fsijt{L06\S` V_}Q՟%طVE y4)ZrDLWQtM%@5kVSzOZ}pY|Ȃ#8'V%bs"#-z;wQGbaWD14Muj/EQꡔݯ'b;)]bSr3Qe6u6 zB pdHE%fgUyI^F w |("zjK+V6gSɌKO Q9J 9ܲEb1W꽶L<jR OGL(9/g?cOИ͠2L ;NDhX<]u(o-b#E=[+9`Prd HγOLD9 <:"Rճ$BtJCG~W Ԙ|W87hw-daMVpo"c㧢)m3؆d& H(-ǹ:.P-O<$P6u?`2n<6]Gy k"؃5 [,8|WU4u`Ry=3գ=d$d<, pu'2mM].8H/*"f0E@mtB[r4~LܛqWsO\KmizXa{KyBq1T{wwCZ͏ 6>W,K(̓#˾?jju2ϫ!?W9JW]%ԊZD먵)?ľV(aQp"@*gP}mpU7JNJo{_<^ }HcCϫE>K冞* } ~ǿ۶kU|0Zviw)B48t"3ʡU:8eu.mI:IrMiohz EffJ*),uYwX8*pb*Qpt3G׳aof^} L1WҘDb ¾ gpK"g:tK]^ɇ9}mrS)kR/݁eF??f0 [ЎQU@n T%rx4kύҴ4}bwiGg^O޽scW-u鳻gD\dYLv.yi w}$BSs"OGr0~dTuݳ]e(De$s^^d=ҏ&&>/>ޅkc`L[>8{ g"'-)g{'*6NHqcuT|eN|!ԃtYIt"_㺁0}1#8̣ kp_BXb:%`u95TR$ V\E], Ve:|$5<\Zu8&҃qG7ySIdV1 ÏM?t9UT QTѧ`x OlR3tTv,'\e̱0> '^ZI,۴mCUΨyS_wP%G.&.sڃeCM&A֛[;[uhz;rzDGP]@͟/srІc3Hy]`IGs$E Z ꖿA"_ ڙ64_-&+2Tp[B(]MziSΜ$A s0y:&^D9쫆3Ex`( CDBp6-T$jٛ[bZDŽ WyOOmMM0(1MM5d+i>R^աVvqy Aۑ7eA9+{hhuTU #gIRS K*+j*8*iZ.hb3%Q,p(L _%oC`]DkϢl7=>;#s|`EU&%xAwō?^F[_h;C{j6Ԛ;<XO s8 a]jڒ'L+T#~|9|ȇU q߾}tuA`UPt}c]o5.~=g%9{\>p*k6W Yxk>ՄF^E } Dù9{f.(T2gEǣ<I̓pqOp܂e;|F(N+f=]MT4Rr CTcƫvċ'}?3ۘ&p6`Vkϻ#%uvl; m{cπ4ѝΦMz@x5bw1Ĕs%dFՐ^{+i{_?}œ*鼢ήFoC[EY#D_zn*NBVg۪4tSpK RKg?WJ`711rM[CMhc/Tr|m~Dәl7(֕Tq\ۧ¤3mkTu)&KRbZRNTƤó$QԘ=-Gq =اc-[rwn=9%F!,L>HN9i$fOS<%hw[㛫иMн{i_ w`i+1AN',,1V~9︆ɬ[LL;Њg#Yl{= Շ.<rۖ rC ۏ CXɧ Aw&}'+" r3NJ ߯u9EP^5_q`,~ 9{y$&gr2A̜{b՟OTxTűDWgvAVoG*貪k Jؔ(.fe!܈hE<:~ǍEiq l5dE,yQ6dÓYUWZ9nW!͍χ)/snYMCdIjr.(W;L:C=mӐiN J k-=yڰsvtD-:Gt>{\ Zlzóٳםe밧cʷ` O;c9UGCy?|ŋvso)w^|ȤɕkVlQma׀U'dmym\gq>?jM ۽ˑ *]VI=M{Amm낫H@IQLI@m1hI PAXګ#'n9mGapR_A1 <ҪAa=f b]I38?ћ2 >턟$ ~)]ptu589Mۏқd)'CP7Q}:or2 9>;t6T$1\yy3̕xQufRbm5:Y=SyE@?Q~>EhQ]+[F>6avl2͛*tWEQzi(w{`*MBGӂZ,]%=K[lYP[-;~>>6><O'.AŘ=ve㛃x1{XvsڵFN)dXZk'&oX<֚],-ʫGEn}x29t݃LN]y} S*D=1fZj+/LghTu7ĵ燯TTZ|] ˉ.X=%L$vnpAe)=ExJ'ODd U@m+KgEc+OSk,C~ bI1Ӱa ҨƝԔ4et';A?I}>^Þv/2eHv]3G.$o{xe$Btu+i2_6J7>"@ ;qZ@(t6c.DG:WIVoe!HYWr*C/*!; "뿴 ”ޢ_TE*ܠDL,c`9{ۯ8aV~Ѩhb[ .nkа_ g+Dk `FOGseu U1@eS]-MsT/۰ jctWv*ev!:iNlB梆@ҞFHn1_&,SHcy%`GQ? >;P+;X)GG2$>*6#".^pZՠbn[ k :/E~*} .qy;z9eUUvDKrDlk\D'6?u5;sZDi0/zEy>;l5]q_'-bʎkNmeUFrX*qd|s!X[K31qǞl>.}JBwah ĪL@iЄ:p#1qd j@(|QAXJ(4dHќ7ĿuV&ӓU' Uepit ypEb#V'l*7qstU46^oH/#?@p srt;HD-am:U:=SLmk.1=>Z-ͫ?/_H#A] H@z0wj0"bfb¨jin Qsww-[xQ$tl5㦢x/{kt1hob!SŕwJ)Z&OS$/:/ Dza90(VI,ka,}v!e 'pEzՠ!3tBthTbDBYC>[l˗_Dyz,ZpeK1.,eb6zd.9Wf{dI69ޫmz(ѐ,n(ǽ za |eWcDl%ě_@M~A1lN:/.3 Xb2 JcqwcKѓnbzP0n<~&¨@5uI*'g}%ek0e#\IWMf,"HI1̋X0AHd- 5]"SJUe>!U펞>$+I!z5,W!d#FfYݫ]+k{z wo岢z ,Q^G0Bܶw#*N%IA>X ^fλ7t~,a::!7v4731 &|:D+hbbgbuOg%KSgyٿL5 ]bۡU!(4}}cxi.^-Hש= eb?{AR͸i4s(\ni1@ n\32yot'k< q}>$C1_JgL3Tuj1d{F&dI)'$>LUдT֡ɒu;FJ_op6C]x;һOδCehǩ8ky@Z&EO2nIUܣ"Yn^I.J\HA ϥ5`@?@de(Pɧ>`,]y-?@Q3DHɼK?;!ފ8-kb)Dı(ieOLZxT41+q/7A.7}(gj{\mY=uSJ0Hm>e'4+ :Y<WcPf=oPCx{ {v7 ;tY$ z! 8fwIcwS xpƍGwbڵ,%Ec9ӝPHf(?q=ll><ծZ:n*4u:<jh/`~qUO1D_WѺOdO 5"Ûhn!]DFD?^2ۇI ~ b}BlWhre3G~ 6y>ůq=%y&ij(ܴpv%y[}Aldh&jsJcW2AF8y7){Kurۂw9-G1tNI|VXѸ 4ZMX H9Ka&,z"1WVMUv֘Bc1r遥&%]Vep(`U;y1d|c](## xLBsv+y PW>%Ez권piVa"Nw#eH(܊ u/ %ODښ>!y^Mt2܋ )'} V { =~19\ `o=@f@n$&YX5ygnhDžfNsnCh("ҟϻyk ere:Q" E>F J3C#Pf@/b\Kk"?.2kj4jǍ=2"`B \]ٍPB&!FQVu_!i}e-d\!; ohCʪ1m.8.n;sj]K7O&9#e̊"2KG@op v䟳+h&KB A_Iz f6@eS,{U du";Zdkf]*YpT;O[h:u2 t]:1( $ׇtG5gex& zy ͹m8 =֛ߺ< =ֹ3anܜq9lqu.[tAxYsۼvGW;ݓPB I0gC0(-UEe|LDK`!ADJyv[t|Yߊ*5;+Mx&w RLaxwKȾzL@'ԐV~x7gJ? 7O[;djXsm h PuJC2oGz˫3^djY[V㨼!D@q͓$3F^-H%Ht~<˦?xOeZ7!yn|U0y)?Q?ff5Tp,UÙǔzhy?$ :BA´L+ȠBU2Mų7>~4'NH+`HCAz O:a>Fh!9Xxʱ׌+٠^CQ q(2]R,DUD U=&:}\H:A;Qб}Pr*([l;D=fs8 0A!J#6253́߁H0:Ju@uZ*]][/y{F09)oN"O]>6⾛! < iGنT@oV.Qvaïx圝{ir8Yh{䧩 s鎪{Z4ӧx<*.bZȮW+l,<)K NřFo \E4]bM ֞+Xt&7E C4qFo^c>[osJ=埐XDm:,TK-HHsjm҄omKZAY$O\SU!ſ.d?9RCGJ#-0DiаJfOzOń3k^i0tBc~fo9gP)w'{x C/qnHl*^-Y3vaVFi*\;kIޘ%bV") v$sѮ 1"z{bD.mcM2}p)*"էqt[iBlsmndSJW7fQUtB_ijх4'i𣧌4#XW;ע"W_zI;C4,z on^S&Cn:5jJ'QX`\%W6' KdIA"d,©!+mi5 UQpt`?/t )pdV\t$sVDyvlfY*Fn0U ӬdS߀1GOSGBCL5"4bzl;1_,O PKT? mf ~TiHN aD~h)ڦHp|2>di!0Ŧ ^zcU7mR< MG01D:ƶ[EԐu/AU GsaeI'8VsăK 1`m$Hl>f))2aRos!]P-a<^Go3.mtIwBV4] Ñvm1pĢ2{@T-e\څdt&!ziw-Ԭ?C(֤?g/xҏW>5"Mײ"B|'%Lы5#PCK7v; }-+̌*īFPW52bIM(7rJkȜC "do#EdrL^OG5Z(Ua JfT{8:PkFг;v dÌNsbtV Cv rZfy#59z ]cPE09(kN?linM#3<$!Ѳ>U4r,MFJx.,Χ2_~U K+T%)!-RB_/&oݷ=޾}8 +@eۆ4uB:fb9b<9$.i7&<vT`5h0 lFw އaJ晪[jw= {oZE>sjf!r"D~W~,&D=K3qma5//q.ϑFzۖJn Vw}6TwӸ[Q uc(KhaS$ vc. E1PVB1wPih(B-U-Y%B}ymbېO?X=“ xw ?ɣw3X"ߞ#X*[>ڬ nmj/NjӉW>*(U}tiK rpZ:_oA(ݮS8&HOp7?"BJH"P* :3[Ɉ^>VNbީ?!l|y(Nr0[\;nztNﵙ4RtQXy.=Yy|<ghh^ī]zYitX>c^O,3H"_U<#!bdK*UWэ)Q G7)xL~ V49vg%ϐEK""%BLrP Lg]~ Hˆ%f4eP)ކ' JMa40[լ됧h4VyL"ZQCLKKpOn$5ƶB(=eyn+y?Hg_45y )8+[0ÓdoKUG>Br`NgÒ$~o7NSϰ a7KefAa%;:S}c_ٖ̆;8ڒ4$~T:O4"w皈k9 \3hc67+WA͜͜a'P l}#zv_E"||:k4Wf7^fղ&xٌx2EZ|f g GU2ޡE UO2 ](Y0Hgcw ÁpD;P׭wAot2!~l6P7 bwzPt?PwEJE%uNpKȖ%dNpE(RZg 2?q[]Uߟo:Lqd> vE7 ) CּTj+<wAqՉUA*+/¡ތlp +X+G=1phԈ&Є*牌ߨD-Y̍Q5MA_6$3C"{wLtC{9WY GVζz,GVOvkGESYAA˷4QHH{?E:.zs&ak`©x[}CQ)L 5 -`^{o+-e{ﯰHdJ>ֶ66}7FL6KJ7t=e'æ>q7(?[LAX*5`FQ@_dzD71sl-Z@{iAvtiAn2]Ȏ0 t5>x6C)LB\Y8L.2^1T){p"P_ R^?K8qϑx.HB,`yQ v D@dyܐ{SLB ;E ZI&1~mtuLKD@ L45)߻$41ݠ) ͣdq9Ǹf|7aɼ?-"!`BjG:^̽ԩϳC11+iONu'< ncw,vWOLCZ #a%IUӑlo'v p" 0tO kr}Hi|2 ]}HX1Nf\~c9aszZ!OS}U3v==}h}h|"VuM&r È62|~*"Bm*}tAxF'#+)CvISLWH@`2%{8fp `}y"(, %muBYJlCP+a`XE]Kl9oDd {ql601Չگc`)$ 9Rc2@w^eTuxNc7^yk\kaKʞ"C?D s+G5#1bW\| <%WO&2*=(?BP"<-e38\dz_! 3գ#ʀ屎|޷!7:-Gnt)sizv4PtyYUe'Eɍ<[RN@ tFXu8glT` 2i=Cd|'TMAQ6`t]GA3 A6se*2 vҚr߁w*&CHLG[e;&utU햰QtSXJC֏k%P1!\Ķϯ5ߔM. wýdƌ"J )48]\f)RFowy/}:K,o7_I7 XN 31̥_`*"ѣƤ;geU/삒fX@NyVɶ/e(?EࡉV=^[erhSH&IU[B3R聆NDEU P(AԀ{'^{8'H$cyi|>^sZa>]%K;wUK/w\8/)v At.)D[i|!j/zݷǑk_ո0 .m8턫 ePJJ(UU6iu~ddb!%$LJɈ8[xm|W([2 T2=; 2ש}c -?9ِߤ4lv?! KD{S&KHj~ Yb% T Wx̛$X}0.@tJӚWZz`&Jd\UH4t,"?Ս Y]܏<)T|Kռ@)+4#CUgOe1Iӡr·Y]G\G֙q &oGc4.sZW/X͘3hOXhuT^=fudS/'vq;ULf흕{ [@W!4vb[2r0w`̠ hr do=nZ :xLрvt^]{)FFޮaiDe#T]@l,t0~`M(<%3ڤhY^lXWm5pҴ)7+q$5S )MZNj7&t[5%^>(3sG5ޫ<Rj S/4dG[^&OUvj=%Xt5i8>rBY4^l5|izWs͟I`QQkf|U] GM!UFh0Lh٤D+`g"|bOuC X*qu#\}2KUch/9gr^AS~.C+HJDxHb*y?lo>~4T?JaGy}1@: LP[B6;Q2EzeCIrN.i2fc5fAGFu}J}L%17`GI/,~DJ~oK3]l9gb&rF ̸'igt!1OWbCZ6Ul TN;܄Okżyw?ΨON[+dtb܈tʟbZZ|!x~b9qR}b{=Jގ'go$U&ːAF኏>,5I7YOK&X .x" bT&mu6I&/JfP=`P$lBNs Pf;feO % dkުdZm}%ݞc'i(aW:ik/MOF ӏo F<:O.W˪E_DM  RYL7y|Gs@ ~X'/~,P0 fka^eyB"k^#l2Ao<`Ȼ>b2F 4ߓOw?wil?C>/=Z׋Y@mm*xV? O}c0 |\Vd6v #Tgȟ'޹'&q7 ј cԧB34ie+=UHYWx9se8f_ߒ7uYS4t:hFW؅KiP35 4,܊}˭^ Mz_DIfNBtH1[쫅)R tiIhPu5 NV4,Ave IrE;tyM_\5 rMثᡘ=5%_]r.;{`Se*V#?8j-2N^őEl؜F<^L0JL8E&I'iiE)QEjxb;}OQGf&M'nE;q2)STG5O?GӀ;k4ܒ<ޅPVoދѿ>,H*ˊ$1,*?2 a;w`E#A2S|HvL|{5A ~} ؃X>2`8X>\φ448隇w k~0Ih{g8F#@%ŚcP\UGf]n'rg>x z3|SI{!X[NGYSTx x5;6mIEbUkfM;JYV \s@>bUӚ\w[|w|>%dzń͵>b,M )"-9%ЗIad?ab=jB'ZX2f7).]zN W{WO>-Jo70EO(UďRd邗"p%;:UdgńHƈ;0U(f}HsƋd3&_Elz_GN !N%DzX-fԹԑXd?7L I,#k$**O% Y~.6[䒄J.x%/!4wKڮ|*r::ˈ S=YF_C7L!ه/ʇ ՐݺifzV-6m~fq4Xҁ+0:E/tKx͏.&UEYͨ X谙sa$p[7t{ sb{x +&i ۡU)oB!M`^ÕwMwŅ ]LCZfKӣ/4Ddye9aNNO65WQR2ҌndSUrd^3oz ¹z!RMY2&62_ۥktPD\CU *A8#7c4c q+;)2Nđ;NSC6f8yzG*yϥ4|7 Q.Xh\GlCRV5t dqP T}*iD){7iJY$jI^B<30% `}׵zsR1)tWրnWndݙvvN/$c-N5h.[2em;,>6P b7ٯDv B6eE"n%Iy7\C9E-d:\,j4~L0ŋUS!2FKfX#IÏirJYM8Skӌ}N߾WbmAʈz^4˅uW^ɹ4G?s n7-kOc@pB;-&K FuUumi=$+.f-/7  OR^aJ/N;xh!eʗ4/қ9cyJ 4j9$wT:7!8 gx7FMUrD;l4Ex!^+p֣u֧$f xWO<ddҞ$NPjE8% OyKWbU.@m%,EE6R\LǺ wͶ慭=+, 1؊s%^S oC<ߥ +hKgg?q`VQi:2qM&i{t XnΗV(*`)±>wAӮqGT{)A8󄪡); i h2 Q&;8e<q1 NJsRRB_ъD?+űkZ̥/*|xԦ珣I,hoKKN 7yi`ZL6`rU%4 %#ZYn1ȱxvDIGo{dS~шFzZ,"D| ULB&õj.z:0m P!{B)P*Ğp5EzC}N7'ŕuq5UQshpuق!lsA6^6tÔ4ѬV3Ggf{;] (ڣo u۷<':ub\oBVZ+I;YXtRH;H9x_"nJ;EJ/K\U8EcW if8w,~mSOBm\>q =Ŀ'ڬ @͓A\emlzvhC_S9aSpmv^fvkܳQcB2dǹ,SlEMNI<ɩy(g")~u2P =\c_L6U8 *,bo2 y ^ \|"h>9GP`Ab/3XۏzOD:`P ? 醯7GB}8ղ*Lߎ)m*Os!jwJAtb  #6 mOG9991d̅kJ-7ׂ4K4K^xf÷9IW/29W[x412<$$uLGC8%ZW=*L8?:'37؋$ J̎]/.J4頵CLYUMw[۰vج 8̴np6K?29)ҮۖLmZBa ѺX4]xw~2C0UӃ"-\DhNU\Cy@y`9r욂)+j Ko%i`L$_D[Sf'xGJ]ZU@+:X"g)q.@5V&[Y<)1IevA\w**4XLf蠎 Yi 1W9Ik9pO_AY8{]?-L:ao6c q`AHܳYP ̌Y-4ݚ%K^[㟫lWwְVm}n,y?ڞz϶uiMmOed*R;g,-?rx>l۞}< "RЄCX;_]Tf*wŮLT'Ja m}h{}Ѭ ?/UD~JTT{G+=˟8GX񪬺 Aee' gN_Gۻ U22sw8'2tJNJ#pB?^\ d<ʲJ.a* j|j(r5/~`v4j 0G6kYYeJ3H~28J<{BNHU]DeInŅiI˫ |PTU@d۾:'=>5!|=)1GK tOn┴*@f!-=-y(o*;MgJyӜW` R]3ݝXuD K;iFIJ/(҅,n> ۚb۲,y\U%4UX(d0{Tbzi5Z> " ?a}~qux4']ILZO$ sm1'E ke WM֍^s5YK"2PkQEà 6\d;p_=Ü9pl̢ɿg\rT8Cż&Kru) h""`xG[P~OOCt< *"mٸ u~} ͹P!b-Fz!6dbˍ'ު@d.L<OtFӁ**:T[BM:m!Cmb fN?DMs3_q3y T>YUw1Ptp>`@qP]q-ǵ!i|8<M}+s&9Ԁ+\3m`5іѩ:Fx85Vt]QIʁ}'k4ϱeDLz/Gm){&.Aȷ}`9M 8 *!* 2'{ IIBKl(; 4aQA4̆ o t'H]0 W .!(Ȳ,Հ<=p.I-{<եs{?^w:\BeLu+W~_m/mI<" $gTm:PXAUl~Qa+%r(V4\+\4-d!wKqm'(WoΕagD„+VJ^ &6 2VFko7m+n+aGfH_rPBqP$-QV-@'* t| R~X}blt\R 9SZϰt医ٗÝj*dW>\j;bR8ӧvp"D!bhe2,] `hCe^z\KeQdP9lUٯN+zKAB Ʃ*-dB4譟Pmta#d@ @vp'/@8Q1>"M771t[)Zh'e7I$D{BٌD5\?J_j[)-_I8bz8i{wIk'䖐z)2tעmYغOU^kraU:G-f6Q,BbK9iԎ%Z9IAqs!t4er}@?ȄrJa!q'i1]S #.sJs e Ų;u.X#2&r3e8f9'uj Qtm$cd vZӭL=MJJi\|!eŠN] k$iբ9nǘubC%ز'iŒHuIsW<|k,R˓N%_ȕe ÒͯWy\zS}+]q6rbkG52tW?TLGۢKuTNs/-0aXn h\}spV)7@-f|ڻ$G7oV܄`]Ww9sdP֜m 8¢d'𰕉t톮* eQ_&6?$8D(+Q\y[Cdq=h! 0 d$-uQ "c:OyJOpV!W7]uܼK w:Wzq$) Ϝ y#qaSpdzơffg[M;Ln"B/n97oSR)F9,ιOd5][~m˓XkZL׮ԢtVj: t-׶Sefy5kZ"4 ;[(4L~}f@e:ܪ# {I7U  ĤeYt4Ӥaۑ7d ,q`imޡ|G*(oX}c|O MO}gދKOX~9R٣z1Co9f]`/dZ и}d0!sDzׯ_( &p^ZY AtQDf&-Θ6Z.|1\̯ }WէkE2&rXpcy q9* e83&MOM|`}(yulNZ/;[8qr_+d:Ų"$bQ<ƼwnH́.űz盩ۛOp6+֝Dc{'MW\ً)?Viey 6in~Em0-$7W[jm66QOcbWI/4f]xb.3Uͣm_8*JtXOGcMPP:VGn4:Lg"~P~ gǧeQWAp_0_ItO[y_}<ԁ垉Gܦ a=5fbyiY3=O3b;"1v@K*1bgz8_k5MאS(R*> }ٴ1L0G oT'N3cM:6HZVzs=*=K&#W>l'1ZaW8KΦiCc0}מWlCM(Ž>nNKϚL#R4UX߄ɛ"Xx6N'Y r|&.-[t$=%;#bNd *YLcO@ H%.|gLcZ>qL*"s_1-#'NhDW3TT$d*߰dG៻&aʾʒS.N Yqu 1~B"ɟq.GuBeSYai>%-,Sqda`_OF"%Ң%Frn +l(TܺdweG@1U=EI٥ &eEMW̯3FNr μt[v;'wj(^({lR|F [7|VI X&aˬEI=Od˲.+_.s \s$\.I܅]Nbk ̄˲F2;&D B[Lꉩ#L)<1aIaTCς($- cb(> {VuĀbdH""G}]K-#/&bK[buZw&[naSN@U0rCIj_ `AJPQ2;6Øoht/iMԞEY AQ4r ۛ¥ur^6UMSE"[A8cb[zB@7]D0Y>c"TS"y5Wpb~+cڛ߈|͉MP5_,QImJlpty# &$!:5WcN;4QH;e$%y'?IW!^ ;T ݔw8{j ӑIShēn=(HC"Y1͑K25/* ] "qwٚ[Vq1$Ţծ9~% ?^3Yv]}(ɖZ@ɥ gz]2:Vfi& C/Kd|N$4=րEzI:i+ =c l)8M+,vGn8\]Sw.:@vͥ P:O.5l:WD3rG\2;&1 J[.fЙCiaitہnz'%j+ʻ܄Ձ4!Z0q@d X)/!Lb&c o)(q^$gwJb[s0^F|@/Kf&(UM(:Ȏ%G8_cEh|Kav^ۓ`a<=rkC^X Pj!)ST`NOfE49yG>;MtiNC j3p"cI}$L$.J+i9եuiy,҅]7$V^ߖ*jy.8}*2 4162NEtN"aQ ?>2n! v-X0ZIYOz>$ssO +HMGX%z{FX0 z 7$DזV͉/F@kÇ4"7l")ϗM}&4YA.O̼(9Qdfv8p&TQ&_9&הxRG-׬Őj!|A90yeESr .V}V3I1sIo([{h2m{Rh*)aUZ;lbI/ʢt*@Ab6 ܕ96>S:Hk?wYWO\ Q,mY]Gʗb LyY'P${eAbh(_uE2.-%AlӐ-0A!c~e F?H7r,8k{CrHQx&#arղ$U9ނl aj :P{45Eq=Z"RM'uZ,݈%ZDSg>peDZd0RA9J\~D~_4bB*3 {%6ĹW i9#zSt/" Zr"LxQ]dkal%P"NEVUI]cr.2,h8wW/.r%ސ*)H"M wqQ)R)9vM9ڒ+[U)DаyU]N/1dtKN@\71DC{016}xSXt0)p d[3obJT1T G  ocEnHپ~ wV_{E\JbW5=9*5gDӘ@bs/ ".- NXMTl̠:]QEɥ hxLhY1LW; )E6m/gqdڎ\yi5P4:$Jq%*ݓgAẽEz#^=Qitm婕2tH x2#+xk 6Icmd:adi.OesGc l[DH-$ N#0d dqay&9*B*d1F @H?TtnJ:AOHv@o1@:I~WCPF%Qw'%};@ޝ07hŢ4"&c@Qƍ ˏYf*$j|=Fia0# 㤏MFUL{{u5g4e+U'?P=X7W;ǻ!:ŐeɗK6J t@ԦGWH]6~;5H&%[)%h,gdoۼ W X" x.oAlw\mDYŘTt5n;GrLd~ULټ^^K~y{_tapO4nZ0 >k qx|"/xd@Xd,%RM-AQnG%F&kD76q<^D`c%{ Slb4QT%ǰj̟'? YvҒn(h"9)!ʒpt;ݛҜs_7!d'Ռ|KpG"='5F7mB=)܁@T虙6ηOm;!K-1<$˕7xTҐ6 3b^ e(.2T]:ߙ%|odž1y~˺4kbF=#NKz//LNPȎs&=zb:|STꡢIJH-J5]!wo64XdQC}A@>歹F0fq$ Gs]XH~QBnu0E6H3uSϽȺ_-"Vi-Owߖ%Vvê1\g`-QM3*$MzcmY1> eT 9H:r?/kH:Ii=!%㊠?!H%.jQ}G̟]:R_vF.u&`Y-Rof"8夌0('uDaۙlBTnԑ_WBe4{~ <_=I JKqׅ9"a§xm+XGӢDPma7S) h-zV;%- I-$в/Q(F;upz"baQeQ,Ї#D2ZZG(R=Qr 2M̲~A76fj?6_&~'ocJ0UM=rlb=ցA0R5Ѫ㩎i78;XuWr)nK3p?h  R#d/_](*y;Ш)=@cU v4ȡ 2ߡO.<+pDcD eh"&ʐ?AiǙ`ԫWXQ-4GeFOҊ#Yi, 1wpmdeGC%Db+lb4w卢ڥha`FY`1̻*+ȀVQ"L逵”GTJƽL fȰx Y&jXUAo!iH%9 i-YWr{] YGo_gz~  7Ēօn(XiƘ; 5 %ZjdCeTg$zh;pwg˪v$5aט?Yw"DE?]3iJ;>7 j+ru:qRcfFeygKhSl~Z&%BgAp@.!H2,*`PlCeˊ jdH'h &aɋ-huZN4w)"TIҥtN{ѳAx N*vLWи{29#:O#%28kI @PnX;b =IKڇ{Nӹc%iޛ- o6 j1e;5,r(ܒXs"Ó1,$=LT$OT<%q29tEX0M竤0X.p`\ X٥|JPQZUyy10A>?2X='<}.c5 o2G_9qzͧׄ_[}%]_ksd_i҂$<,+ {LdKS,hX|X<2O)Zθj\ p<'N8f5'{Q^HrFmÚg7mFڷ3 I5VF}"ؒg7hANJps jЪʦ Hr)*<_#}OAJ$YE0+W甴-Ĉ/w X'6'Gr_&I8d8TNkʂd, fX zmز HN-46˼9JM媊C@=Jj1jy0bt3:YmE2`;0mMv#ޒ% %/'1Ta =Ksk2ⷧI8~~'1ih&#q0l:㠶ꮹwajI|'C/#;b"6`ԣ":Sɦ8ɺrS)8g!Xww_ю\dJ!Om;rC)?TWΆ˙1__|oGl[ESս40ZLึ9*ڥ ɝrH'Kets>!A(dGcgO ĊW?Z/O_Xdܵ<&Soτ>]GE%SaNevuqvhNκe2r8AT@lg2J꺊n7LFa_Oˆ0xz~J(ʱ&ـ'{m B=^R%cPx'R]SBP?X1nH`Zr'!;td#!K$mSE!٘dp'Ѕ F Uߟ N L C o'wcEMEŨ8Jr\r)fL?XiBK^us-5陳Zn4y0M|e#|kUQ)/'#l2Ig=1Ƿ/~;MT1g~F>&fmN|ܴ~ZdXdG?oήQ0#>O("u0gzJڎ$eN9B-Ycv!v{:5PzcqdۿHn`!e)7/E6aDL+ \wt b+ofpojBt+8FDOG)At ؎k=t`pq`ʅ96l?F)Tt-XECEؚlLlk䭧#AJ0y=y99bOy)n) -;QI|rO*Y& QI-+.U7*H"*&3c˚#Xj-3yؗp!Q$ct4cv+7兖\@=%xKmJ@hS᳋ x2Q#^ d[_9cѷ'Lz,CCQRɵe̟] r}E: yRMB8d+QKbטa[  .Ln#$k~,\y#O{J-cf`Ҋ^NJ࿿ٔlw6`Cs/'Oђ- ?Lj%K]gDH]-Ud8 EA W]#IĒ͆|ʚy #E6lXð(P֦Dj2$E(\X2Ox _OH 5$]W rVtpY֨@ۃ TM{>y}lQ}ُ#Аxƒ 7D_QhjšRZӝ)d,t2)s`gEQ5MT7 f a-_ߴK3M hbXCW/`BN\jEf)cydP-X̂nϗ`]oY9'x$dȮYC_]Ko tc 91?'Z [֖gZt 2pL~xyS2A06m4VV!@a肃9q'1X.cߏ _W-#_y^q8 j%|' $sאDYRxLb̙OrtIq;Vj8OwQl1+RHjIBD]g'M>k\X%NW@fl$뛕÷˓_ qUSCFomq>S%Q<8lѺEx$3._\Kp= aΉ>[\ׯm LY +G R7> .l-s)| W-&L/霼)s#Ӣo0"M2%vdP+l,w &JR`E'RU >F@McLކ5PnBO؅oRA1P7 G,P$-hB1' Ԭ)% LUQט5!eZY*.wB*#/XdDv[ƇbwW胴fALu,{$$º :',c98k4 ݁/csLWEGe2BeQiRG91{&IUfR$A⸦ hQzKcJt1%519[[tވ4^lGGl<0lI􌂵̰7Ojɖ$nȧ9N~|,ѳ! ڵ H+.!I5|CPbD֑*rDKkDZC蘞_!TwR;rȠ @4Ԛ+.$^7:idx(󍂹_mw<;W$OM*& 󌲯i'ܴ*ɡȴ6*Cᔴ1XFOI1$ 6/DI|%$a H1/Й*izrRj Ktŷ?P<@\+t?ɉ[HbPY(DW&~+ XGQ-+̥PEq(IK_ ={ɻ&-6/sz{ 2|J/'[Q0fk"ݼ~c-D5X'ԓH5%d^f'CcR(@'0/Kf$YgelWOޓ/\YZ}!\Mc

$@+KM,ixm^e/S:ж{09ds~r>-9<0eא\gWs z49-ArsyA_߼1OԫyJa9{ʩ/ cgɩPj 悈F:`oYO"WVb.B/{A\hQ`fˁ N0ej0v9Q2b̾8wd;~ڤފꪢ#4{FD?xV _U "C6v3UE&jiXES% y]hX-?j^HbȘ=05XM.W\ofUNޅAP&~2ۙ\#\UYwՓ7{D"h9ؙMZ2@: c*'#m{rXH# "";FKW 'OcɌDJ)ɭO{Z%gS' c` rh#)7R[UB%6TCU$Tjh_k ؖ˨\[b AVTEԔbߍ{ hԵ%}PZFj*ap$>mGwlEGMyW<- `2Z٦ wѲ9 hص,qB7ST%{}vHW~ܑCtU]FEՠ{ٱ-F]RԓwڱK$*#N;Xʺq\8F)jAԩ$Еe "H;`G?JJ{~TI[5^q3M+"QAlʒe^[ Ҭk[ 0|ǁ8>+Ίn^X1S ZfIgC917Z%S4 ۪G Ɂ=$p_yzs]*|r["g,ke#b5/_"Bn]b(U6i ,W^qa0RlE;, 5֏x]qGЍU4j]xAr4͢V] _Y%гP"uOP,6Ҵ#k1/U<ć$6ǣi2>@**KHg|0ͮbb顤I4:Pʦ %s1  ?ww9HR=.c:6tX ^k$Hr4Ua0z/s]m6$^cÑlY :H)YY:nMgq&]c1xuciQԒ}l@`.b?ba|?$LM]6:е.gQT, `6LciӹiC,GēW}rH b­ Ǚ؎G۶ayzzcvBE #`mվ^OW@ q(R E@9Q8TU旙M}l<{nHipٞ$8Rʒ v&FlGA#޵KyycмQ-#SqI#Z2ɺۺ>00qi⨎/<ٮ.kⰍt^iLݵCXo[ϑ ۇE2%(V9e}[mIQc3eċHb)1{h{mdd ʵ6 9皚joN?(yp H=gZY%S1qFޛ6=˅`1$iYBUN{%zDؤ08rtIsI/`phM}0'`Z<k]!`;GeKI-ĵd\xB ۑf`ů%U╲/?o%wOW<۪՚&W$2wgwiLC$ӢUe4)!8Y@ɍ %Us5U$K{e[,]<$mʴmIbѤt$Hq-j}^@єh$N}v* $'@{+]sb*\WӖ'oIuy9}TUd}߄(ϐLCxA =h$lIľm>hf!*J1]lę[tQl7:Gʛk(nK~KW3u;[ެ__FvjBz$y@zBH:󛒞9$VT,Q%Sdo*=6R]3?٣ۑۢ_IXk 9=`d×:hF3JB<#.YLϱp7NuHZ9oa$i #(Xyp% ]!%5@#GL)S#dMIgFH79 ԝR3L mؕm0 joz3'w=S&jaIjk2roJ0_nߔ65}kkHr^L-J}:> ojkhlÂTJ:> =nZykmXkT#[\˵@ڰX;}ò2MkkVzZ>06u|@:jAo;\ӷ60ݾmsJ h F}P^0 ^/mW}kz`ayYwfҧ^/msCl3)w#mQ6tQMڰb̶=SdmZy`bJ<VYjZy`mX`kFdmZy`o6nZӷVMF~Sk@nZy`oj<[7殫[\kzViyVVrU@!V:B&͋fsKeZ*2Ŧ M^(6UDL2Ŧ *s^lj ijg*MͳQŦ٨.MͳQ^Ŧ٨BSUgCnꚺ<rlͳQŦ٨JBSUg5FUjg*MͳgY} MJlTty6Pg*AMͳQŦPgCm:<wy6Pg.65Fu]h.Mͳ5fMu^R避^/qpU(p$H&>U^3Fz'Ze[NYsuO'p7>zg]Suu_t^>)Ke43myog{,<;TRu;lnU9{TCxg/٪hqb W)N ޷}C5QF<0;=>aGn aαpNgo:ũf0&%7rWn2%̕ZIT}Ž&*6z x ´gyqt0[1^ &FIHJwwi>arHgjrZT)ygQzK!ktQLEm *0.q2I_=w4]9]8} < jV?z`͕{IzCG.LN 1CPyW}MNIql$WN Mg>,O45z]5J!:(0=IF<4G <ьLʷ NXN`1X`ldMk ?09^re l[0"3~D6eO:,5 ̤<ٽT0RtlJ֬ T զmh'G/{\Ͽ/ׇ/%_wʼZlVAf٪}@M5Ģg0.g9c`\"bubP<71qȎ,Pd]sln DNz^xIvar/{A]9~&(Y<(cٜYg$XU =H4YA&ϡGMl8fq9 p.a&UA n7#۪ct4\'?gÖ9ET|+@=HC4UgK`Yf\)2wgGb}qOeC4qT.Ǩ$yΉ>X9Ut%~۩ %QKdC,b$ݑ =g@^{c&ᕛʽhK}o9Z u8}iB6KItuU=C)댽ƉQMy}I#7ɚ#{82qJDѭK+=;ȗ|YaEu ޏ{]&/g{H⸆sȊk=TLb4kKfE\ c^Pdd3#8B*yb8Ad=r=%-5]?ذc)vml0f+B#Ǝ> U5[ԋ+/|V\A RZkPRlLk*6S<[L*j]`3Zwt&w*镪`gZBviWmi3m2?>VN*bcgjl%oq LHզ&ju^iQ4I$ |qsӬ= I*JqW5l1kƋV=2%MK$FÍ 9aZQW?_:x/HNF@YD&oMTn 6Wh]}g.ݑq,|Sz~zvGv;Yٲ"[Z5?jQqVS~ Stv&"Du$wTnĉ.XCV/*኉D"E@T$ٝyR5C|v/z}j),L ҲݼsPJvrMrN㏥ɚ[ )+%l"Yb*]H|+b}a%"k|BJǓ5qz{V/카{T 4f~awҟM7tO9~Ty|>{v6k{Ud'eD/ZvaEƼGU|reɕF߭ڪ.U?]tYl ]cGjkKB3l [蹡kRw#Xܛԥt,v@R$k0n& ඗پdO.B栨oi0 S3[#LHv\Ql![MX m5y64ș-0C[G:RJ1џ?oJq ޾IQ9iڡNcfseZ u;r%k/Y߼$ _zhY8ͪչƳ!Q`R]y22`Tä^خӇv}G$sT}<;R|;SR3( V0?9dފVKU s.e=<\NpRSC劶*;Mp|q~W"lD|Tf&=b~ 0[Ow_)*?Ӑuo88Wo~WESNywRYI y쳦Ir$y4臿hNQl&))Ep)/ُ@a aIGɒ\{D,jɅp}; WY?z}onxW)4CI1HV|SfGOŔ5ڪzb+^mӹ2eCM'WOt kX{\gI,I ϩrbJ.]*uۘnКy3߸XEz̝Jп 6 4]~i,e}?HT ||;IRIofVm;-:Ԋ*䚚S`Կ3T*AW k#o4\<6jY ] 5~S=o6AsS8hi:%yQ6l ͦ Y4C!im '&֢+<Ǝ[OłXrefF8S4]Ȅ 2ͯS 2fx: @ )tV^/x!\(d2( v}L0I>%Ecpn:+rm!6tXldMzET0A7Pd`E,_!%=l%Uہ)cSdLkctЅMcmQha#WEdHq8U@AZS2j^N'/rOOs8YTDKWELKs* MZ>e6Go(G>W퓹)ozaz=[C r!RiVׂtho ѿ1XtQ&}Q @* g^I`r|  ,K @ I BX"e]~MC*xˣ<–@Oz+ncAg==Čdag;f.vM-Iicd5-YsڿWTb؆#1eNYh&co+9=24ǻm8(kr#* 7%bp/`puq6o.#@#[}r$A j$cB_,o!a-($[(Ug!:S " Tm$Aeܔ5YeF~:7s{CL׬(%;]UϷ'cgGF@lB-bgep7!@\q+8.~d2>}"S:\"KVFR4æ7r $>`J=#8 vճF Ƙk',p>@'|zDWmPtA"7(Z8q?VO,)PꀒGR#Hxgظ.xqz(nJ 2}QPr]Gle)SGxt}VٲGVO1MVAS׳<ȏ8ک}0UxMz ::BWli9>P =yE3yiZ7!!`xdkPX⦃"~Sfg)|%BUI5ѯr]Irt=zDesͳ}eė pU(tE}ppIH2/WS'1 /^`NI@ ƒlsh4|m^/nЈ& `ҍ`XG8GC3:AIeb?&FOqmSi82< Bcx@ s8}FwP!ġ*X C^!bGvH攄yo>16~u cT aŁ.{gO@ňÖ̬9f<9?yR$EShޮa#g%1| Ⱥs|h.2xa^[T<4X4Q"$Dl=ˉmȢ+uh:S/$˔'kV.[ix,]?BÁJҝ\Ng]X|L&LX/@fӀ00saDe$q\a G@8pȩB~ny*&dz)/T:a"yBsL呏Wv!Ïi.q4vU)* 5Ǧq$6JgzH:Lg*lo's$ <&oa,_٬6TDJgc vdAbO2'i8 'A{wɅhXipDž-V w=ms]GM on;p$c\\\.xlyO2 dht `ҍ/KHNhN!\` 1t 9(S.cR0A'[Gк%|ǐ!PR;8O?wNpI eXd}oP6KGKITG*5J% v N:1$8=94R"aiXa3G`qd2\!k5 TrI2Fcbzq9A`yLeRM19N~Dȱu̒:OiM~'E8A/Λw ;pL/W5IB_> ˈ|CE !kԓW»/nq^ 8g0Xc"݇:]FWgg5_ldȆ-<)`l0E{{\.{=2  V RމE4I7pȖXdxHK7t"Lis6`w 8BMkMa5 W2j/xE =+X`n}v*1?%8MDa67 Vh.!`aa8xpZ-+8- }ݥp-o>:b;ϝpqz RE.Z-__[céi, WllMd=Rs|13"ME}Ny SB|ƀ<y` 1p Sh ʕ# G&\\m~ yQH2>C"@ )4mڀ ^эnHAf? v}L0 jK޽ ?h.012R;&_aiYQ-MfX&4aV3Xd+l=01'Wٿ&ᝓ9n|R]Ɠ>9ˑd_ɑDxˢ2@N27؉`'Z|`0m6rRxD,9][Mg0=TpAP6lB%zF4 EW4 (*Byq{dbost;/կ,fȤW&?ٻcf#F5&)1e]~aˎ*2Fi|qkqIG4aR4V_d2,)zHU\n)_Iy~#|.o4cwv~yא&ÿKZV%,4%BcKIm{fKRe[mYxw<˛jXªV]Ҍ/~ kr3D-.]^Vrp$ `ב J6ɃǦu\\.x} +2.@ `+phC|~\ӑŦْookw@pkohm19D_VXw"\kG]6d.HBÍ=Wz[KPq/EpV++Px Z*}߷'pnȪ\9*7@W"#R(EEӄB(iQLuftڦx1N SN y:SI4֣3(&x@㎤T?]|px$ߡ" ETQDH@qYblx*F2HI*|"l“%}%˷3)o+E)Y f38O<m&H4Ds-K䑤bVᔹ%u[=~0tǡfI?:!H0#?C1 畇}~pΟ$<@ux<M}/biJ~$hMB4{Ŷ!ZqWgmU["}<;ԼGPW}3|SSVuq z:e $iAgJ54D}Syt2HhBwsVB<70 (U[Vr%}*)NgI<$Yv$_g}N_g4Vʏ@Aι3ySLvÓ dȾeFȼe,ΎH;ߙq3c*Ut &d*:8B5xyP@ PÍx.RY /!B49ӑ*>b*cQϜIe י3CŸ|;9;^nNqJ@ n _u!'-/rʷ7xח}4OMYʉ3*&O^y ܊x$;(!ӊ_هW@yݿym '?yDNN88$zX$xj{w=_$}V؟^|x%HdxŞ En$w/WV̋_GwFWM¿@ZMn/gIGt ltL@6xpk۩‚PFV8*KrNH/ϟ$w^L)rJ8,:[!xƢ͏?d'}DAC6g(‹W 4eCQ4T7pž"K q{:%oeIM%qQ[56ltfU>񍷜%QFFeGhHI3|F(Oɜ$3NnnM|zڢ2K~2_n٣p5CB_:=贶K! ՅI$  "KҊ[&%%K"Sߗqr%g#ŏ׻I0bgoR DfEFRBjoR"8uV;a.N}Kv*>3;(W!s韼9 l6;77~00,$'xF?4 B^ (J0L!VP GlaeE_./J;>h,EA uMTԌԵ߰p7jhߠ7Wي.6D-"'sIX)Ѷ6 P[,GQ(G 5g9d#aRR-ܺ8ZFy4iSQv[-2y|b?coJVT|&w9av S%J'~o2\%Ut)# %8sB3srj5 lIwmַÉ0Ǒ= |1s$^⇁ +MvXH.gҔ?e#xş*kTqnOLԃQmI6e ,p(xb?`l @ZM8TXx1$8QQ⓿7}ә:ۯ0BBr%aJ?!N"H7~(b@]sw3ZD ]12Ʒ~)M-Ė X&+DG$q'Uչq?_j\!:`10K mU'_ 2!^OWGx"kHX;{8mь#!*o{u9a7() Ds/G5PU łP\:@=-+LmB4f jhL6'țU S e[w4*ӆj,12Mػbm]A޶rHZm%KψHY0#3,,ZT 6"\7nl(yZ',|.jT0s|BFc"Zb%J]a_OXHBr<x1*4E_{>aEqP%o$q0yx#}DhK4+vwC'=~yALv6q*^(Ų\,ˆbiE2Z1ދ <.CDҙ ߖ*j1~y S/2OR`>g6(%[EBuꯘLi\hb=-8K NO ٬QZVaaӑ@_ m(rh#H1=R?]gHu >8;* { 5NX]7kaBo?:-.sl> YVZ0Q.s_LPܴǩT D29OlϘ-vd7I& 納pdx{bk67"!h"dpJ 2U %"fBBڟI*k$X3 moe7[/RUAS]:Idl1QJ;?T$ }xiE)SaB,B MWْwڶNN+Z$&{DaO /&^@5.3֖El#&ŧ08b9mAANk#|CeE:V8 g*o 1pwi[d3brP|{:h35apMچef%ġ nOZ<. & '~޼Huw" h8\Y/Sf9qF/J e_ZQʽG!2uU(hӻ$vu= qǦwlJď#AI#TPESŲY6pM_ĈZq"RfY@ #RL_NbLLeXIa1M&Ơ];&'D{|$&C*$<2ɈH HU f UN6+HQ'i:L  S_Bٚv?")>nC#HsH6x>og[Yd8&&Ro+ntJo%^HY"@1 a1NCUl,mݧ iȑ|FqL;f] t_ovx %Ɋn[TMפ@R]&8 MY: Im&8d)dۡהGWMnZe.^@'qR=EdH}j!JFN1u:\'O)Ą9 1!AXk|Ke}t|v~5vkӸt)qcm[@}̖u\[qh`IHG`} o$0Wv W8NuQsmǍ` `v0Md9BĨ#`۱y )&6B]p%a4HsH]cƂMUdx#4u%;-@kdQvL%M"k":;簪 Ljy${+wʆNMBjUmwB=jM1ݺ;@@#hʺUcsԿ1nZc&\)hT_pI/XBIҝ%e.6NnÈo~T_vcۧ?bYu\Ɂ#3JyfYt㍼L*3+kSQ#1D wnƺYx\N4-EٴbP}<оnoyF >O0Ϲϖ{…k Us@KU.|,GaN™p&rW˱Q2ђKl_+OtkDx-JRb&ƌB/Ǵr"/c w{"=8%pʂ{C4MΉ1ތZ<gX%)" Qth<p_HxakS3I?PvLgC#2w3ꟷˤX1j3d6*f#Ndo߉S "drGyv 24k.ʧ\qKDەz>g\m$VF߬ Z[Yu !Y(sg7Y6H;eeeSԵ..ߢYDDzVdX@$U ʯ3Vt{h5_F?Y4_S]#Һ.MY "驊[W{dt]Yf..^[5͋e΅ڪ fJ\kUy*cH:nCKaQWYJ~)"T5IK5s,X%*GTlmL7&guVzΡ 9xf]}dȮ4aT&n AΣDYE!C]tT#(C6fU -x,kZmVmۣYV9Il@9Ro\ ~PN}av7E{ڿg]4&6b?\ײᱨ"Qej<\&#Rx`iz@;SnkkUw_h29RS:Ζjo:NG6 AQ]y )[י".luB0 Teڡ(](ij ,@':NHU2bAFhљ'1B;l2ȁ6Of`A"|4*~ JFX?XKEs&[|ڭ:xGle b]s.A 4Oa]ۄ~xum_\ S}/> F]K`cB;K\@SpdUx\S>"ij7pן_g75"*}^ಜVDPu]xݕug}WT_#lֳ e`*O.wH}`ҶzZ @R ,w;Ғtq e*srrpT\ٔE..:x7{Ԃ@XC9kկ 2³=ҳS4{PqMV`ْnpmj6LR~Kخ98ʏ7Xͯ,Lm9^œ$*!CѸV`:TYld$PSnFϧ]BkXvK/lT+D@VkTG./,"ώXśQ?8B VYΏ0zűJaBSBt|n \!)%_Z],޿{N(2Y le6ɱ1TS5>b8@N&,3aS|)$8՗`b[@aq¢*-kt{Q UXƐGiu0;o$6Ż[rŚL+)#ŢQݾ'c?H G Q WO4l m㘴W]KwJEB.SU]c=G ~9ZЏXT"HAGe R{*OMYNTRL? X~A@JZ~eo Xפ* pz8  \S+<ߩqѠGK1nS!oqR-(}ܡi<0RSBIYCD9遞1.9VE& ZOa38Ҟ^{vZi~ @?6Зˈ"2=5#ܹr=JzWV{5&ܻf/'_N90*AXg۳"C!4_D"Bysp)'SULN\U#^88,Zp F$ŖTm?Ga2TkMkF#ِxjH܊Dya "dT$(AKԻ'I8BK5$d:юlaq󬷚ևqpT^[2DZ 5 ePj_BWC++?/JLM8*ѮܭkF8?U 0ǀfb0 DDZqb`5ڀmgKE1u*?ڊeHy8]x"2궸jn%k|6,k,+.P(jkq[(X􈺅$E&epSL-DqG^|Vb:St'cCZ 2%u%7.Z[ޢ7 T\GHsHrAr͢r/9)Yo2jmCdzvp#H(j*+A AN6B 8s3`eWZc5 $P6Q ,MM.EYM8:57 dL~Q/sj.JH쳓T@BumY?A&}V1l!#=tET=Ƅ)״ P۲֔tƇ/~,+'2Z1ua:*ρhpUH׸`bmHF k(b{AXOD&\tp(UHy@+CTtne(+-O\dvRЮ:*:6WSmMqz!La а E7U$ heE~{ࠍXh_'j&Ѱg=([{m!yzVɒtW0-?ā?̿p+~ ,U4`[Lˑ?u duYPEt<} u8;aJ?coM QxoWdCFC,z WCDeC{P zVa͑Lh;0%޹Ejm$Fj,7q &9T*>X6zF6L<u7l٣olpvƬ2ӻn!L+@1]xtj*v" щfZ ~PEcM*Gch: /jBœZo%9D)M;u>^1䀝L`Lu/* Kzm K N) [ž y{< I&j* iPF KA`GOh/;,xp$bʋ<e2jJ*3{i{">&.Ρ$IMcQ_fݛVۜG4iU~|l$\fak޾{f:u!d%Nȳ$kdCY$vgρjȶ U%LMrBޛ([̏$ GXx=B/ ΋e"Iw^L8ɣl@|!`I'IװAy->뎰2Cw>ۭ>NCޏS30G55}:o=(ǜyO[RBuoN "lh0d\J F" KJNQ4X_o|/\,N0Q cr؂3/ /&TYF+b/9"]/ 1ɝ@Od&0اƠ0oěOU[E<#nSc ܑ)f! ̺SASsi$хl(,Yyy|M4vQ+u# 4n+sQT)뙇C(tͨqxkNQ#[YuBP8+/mO ,,ɖ -A= ˴MD5Qv>kؾ\?Hٖlf?<,"w)*h;F/l O7v?/]#$# h<`(/h̻J684zV[叾^@UDnxa0qe;ZۭA_Y;π "ḺcFr gϕHQ׈w,=I6RH~P }!!MP;hQ\Ѱ*o<ʂ ELps}O%zdZP=, n ArD ":DMn@tH҂ Iʻ}nj9?޲?D 2T*DmV==~LiH7#A\JLj90.' $~?j9* [|\-;]sQ20Au1=hOرs h&&8ݶaM XwK|( LYLur/獡4Tvx*<=RI#J]5l>w ؜6E詔cx۩h~j  tkU/wV.Kyk¯g\;|s\5@4r$0J;#3$buN /.kIz1grOr>)9>Y7l\F-*"0f7sJ`+mTJn̉5 Hzl7GuRʦaYOB IRs&*ﺒ5~["!#򬡐ARA5 fIq2@viT +CVL1s\_:J\4VGD4[RN`%@]~9VP@FMKw%7l8Ae]<OwJ8j#~ye9J0@ ?:S,R7pDDWS|dW5f_ޒfs@QXl[ᇁ~PRKWQBTb,=/5w XiڀX')d[t}M$o%4})H$;i?D"L$S/gH6!N$nuLt=FAɢJh3\heSh4لSA3ezv `U0zJ"`)O0n A}u%=0#6nf>U݃ڇ\0S\>{r<-*)Ap@o??Kt(#BC[ < -2`00pÏ9-B|)b~+4C't3]楻i<=떫7{"ʕT2Pε`'ɺ .\u=ӐߗNvZBl/V썂e2d(O-Q4`E۲ʴmYHE!u,ZnxVT+b`u_zY]"!c\:^ lĢKI4lx+m7ghr~PK!1&word/header2.xmlWn6}/][/r8kN6$M Z-&R%!)ri.Z̙pbR } |D\,Wi*RKO'rTy`-x]&C?Ӻ*XAV%+9׭Dm9R0 J&Մ|W+,wh}h~XnV׌p$\,FeDôOY:߼5fT,>`EZm7}%=̬h:̨͹ V9ɉ̗Vz!js*>+bw-`X,pQ[jP/!:!CTqI~x!5j()BNS~2bneZei$gTJ"s\M|}\.t;dLyZє2׏gnV:_CjL9jFpz4qo#~.9ǜMpDJ&8 içv6>'_39c5εP]I&I(O ?9^A0ba=S7 ? !o{2JXȸTlΔ}2@S`_^BFG@iĝaiO1%m01CNrQaHUb$PLcAs/,oX~o<ՙgVZ(F!jzM;w<8' CB@ O5sj"snKT%p=w y)4&0[^ͺً6)&Ap{qj2ZJK@;<]дeL V2mx3(CZȤP9 7Q ؠrw9Wyv`"Ç_vuv{2-?4n9qd.ݝh W3 jFV;s)ZY}|dYp:+yLE l:~ ]PK!=Ҥword/footer3.xmlUKs0wQ/!l 8vL=g! i$YrfR'怤}|.Z..©L92NП˳9`Bp=r.Όrx'Ircd캚zP2Q"NzWj WXMHA UbGvK6[yv fHV8 Y!.:&nd[Rnꈮp\L((z+,:ǧ`1Ʃ,o#1^옔CYq}ÿPb+h4~VȬr,$Ys}eTݱ5°p+|&({ @ci - ϛa[e~x{fx[ &˱in<aqee  Z aBը@?vJ?jq_aWf:UI.M֏'h*V w t8Lgi@yN;80e os}xޖ$q`9){ƦQӚޙhښmދzV7?0YNPK!4|\1word/endnotes.xmln0+ MT[ҮrݶbeмEi?ݻ,7VI8TmL^G YGUJ P<&{nDzJ8n=D(U$wNGoY%c) 3>d`ܯ$f 0n-KQKZ+tf`$ui#kī(#;wIiT"F:$:j_]$!d \&ox@\行Йwݹ"vU:^׃%C,Ԉ> svJ$jH9p53@okoh:Fd64{ju(~韘q5hY#OM7ЧWKᨛUyJ0*kI\*1/PK![ D word/footnotes.xmlVKs0wA qIF4wۉqro]I+3TR!.FG"f|_#mI&8 j|? ! j\B#QJs9"1HHQ*v_Rj D.&$Lʉ_ur^ tI {a3;v{BuKj_{uIe)"E3 N}jgq]`Aql/K 3eXOXP\̢R8+JoRf=܄H\1$ʈ -ɮm_ee@ mLbvG='.V0v$]*@zM5c)|}Ư'l"۫tPK!Hword/_rels/header1.xml.relsj1 Bh.C %,):۳ll'4oM Cҏ>}jgq]`]ӂ 8 %\ ΁I2Վf,u(O.fQ)L7)cnB$RdeDm_ee@ m/0N{GO\aIT(&KEܛk  u)|}Ư'l"۫tPK!ZbQword/footer2.xmlX[o0~e/CIBЬ0q*msex$e(;NH(K<|9D\Oc$Lb ۛY4B4D e4?XXS/y2coY2qd%%`EbQDl-ي `)U.}8HZ)9?t`̹$MVX]&}SLU8ʘcʸY4)-S;.}pB?̍$g6c QZBag$EnGuO\ 64rXZ'ȌcġR&$F2n60l8lk>G]-q]o؁a ߫L@@ Lyn,E}y65Ќڭ;np$X g(iC5BHiUZ?zk;NF4д]x!]ކ8vG* U1&X4 %d #<13TVS&cr-"$K쾸6`|sy.h{b$Tknm489 *  'eEeuxSx9`3٦T36X(%1$%rl.2崧ݥ(s% loOVoTl'aԻv>"N 6fn0_Vhy:)enϾ$H\nV(N޸=I f+>\O+zqfa{l$` תh}G3،uԛ> _PK!0C)word/theme/theme1.xmlYKoGWwŎ -Pqwf UpT*z(Ro=Tm@~T- zcTߏ/^3tDA}۞22J >5( 6CNd tY9?C K-j>^eb bj mg>9]NNkl^-Sn ~},t)cZ{ʳʆ;faKvi (6NP6l.t-e|zPh2Z@x) Cή8ߘ& U)eWFe;\`Md}up<kxN˅%- I_TS 1x㋧ɽ''~9+8 TϿWn,~ Te೯ѳo>2Oc"urx 9x=~ib' %Nq*'ѱpmb{^߱>XQj[=Y MWI.eG.ٝv)4-mhD,5$! =>"AvR˯{\B)jctIl]1eRmfjsbKl$Tf.Yn NqkXE.%'·.D:$n@tKݫz3{lHȅ9/#w8uLH E1ʩ+D!8Y[X~umߤ,AXJp'la^1M^ָΝI8 ٷݝl;r|^o.w]F:G[*Ѕ҈=# BPZ%/ZWr4[SPpbQ4DBS d_vY-ye>S+9 Guk=MI=ϝ1u',m^x0ѯ*Kөڬc-7W~զpMA 7>oD eK1 @l1Yec,9g ]rqo|dGWWKRȘ?Y|pdh̔4p)L>DCPK!) 0word/embeddings/oleObject1.binZ U>~ 5^0o " Uk0`LmGdc+IjL4Ԕ*TܽO{gbs;?|g?Ϲ<@k&E7ym)|/l >3%$WapErU"W\erBA~r sr k~kɿsH3͜%1` ˜ o@6JOLDc5gEJJMnNt=}p_#eKrt' P>;C Iw[44ǒ#W|?5Cry+k:ygg7{K${ 軰ϧw%VbǕzɞ>: }p1p,CJ;@?Y0evF\ou>ճgtֽ6{d'v|d iLBME?O&ka(m#f558v)=w12~`趾Ƨ^@O`3M-X;Wt:l+pn=jg^h7=-+)iT=!$IZ=2O"8ɓJ `'ނ&25}4-y\vqLei lTAdFex #y6%ȌCUt_&hV3f| F"䀵-(xSAu/[0ͩcxOOHQ=:[W1TbSSOLw ` |sŕ.KD liԑ!,f4?ES.Fj"l`AE.i!{DLQt+ FB\̓}u4a:1IT"/#QI E/F'|%v.mE-T$%V[0j[q9*1s%z-Jh(O+}#>8n)K(˩O>{еweFhkϢ"DNZ6Mh UG [I+oo§eDsiN?4q2hU/8$x?pzZFw/c=hS4s'FoЪ[H<ժy.lJȓO/-JqVntcUbj~1`Xr/ZPw3uuPGؚ$ʕf$BMH4,gهzM:]4YDZݛGЯgҐ3xTN%W',) b_HJ:_QTW JVR5K\ظ[!v-mf+>l{%=$Q)a0Lycbn;^0J=˯/=u%qc)MW#t,|˻Q:6ZJ+jy/ l}} cnI>gPֈ" BKv&}p^16ٙ45(ƵǔkR2y,tBv\w ֧.փ7/zbs$g'yv*Qw6ЉIʒcqy&L4nesFEۻ?JXY.?F,"urn7ͰApi}Ė=G&%C~cwfW)eHqֱTI$Y7`h.Jjx w_׹A@F=W<1uzJ:D&Ӵ7qVjSE.ަ# @D]׌R4 Kѓp9ԀP]R_])]9k-@Dg{bf;Ӆc:<0"D<*C{F-T0xi'ġ=/QH@]Vaf#1H<{U}$/>uNT&Xȑ#˖-k׮݌3&L`E-]54{Y?AUiРA)Io;6c>/Z<M81K//PwMjws)Q\MuQbb.G3գL@RVQD( )H%RX:DC/Nʖi&*DHChl[+5Бq2%^R6Y.Tb+D4!8ߝ:뎌it褘2aKxʋ/?rqF7 In ,Ӎ  f ei](ilR >QVaMY`}ׯS!Լ꫿b[jj*=tJK^"ȸڥLӠ":&m1:! F)!s<%<5Dk)ߖݔ)Q}$+}We;N%TAa<%&e hꆓsT;  *KEן<;y뫫o|uo#$|))JAـvhZ;R͛%#8I*A΢,%RJ_ 4^Q1}QP<-K4ֈ\)*BtQ} I!2J%2$`riCRIRkzGӰQכuk-tc.Dҝ+Y֯~_8YPhMq/kIv54lTo_S~=a?s_XDY@E~CaJ?x7Ip\UU%m&7&48"pAʅzh)Q&0^m6}:13mvJfRmqк@a :6Р2O0AZ*}<}EB^L/$iAނrN*D h%2IKlaX4g{2} SqFGjhSn2A.]ęlFΠ{~xٛ~ܱcGil-F0ߌl~ А3\=.J{ؚP*#We02S1; QY[*ܭ-)Ep&CaM֮ftP"JCSPU mI-u{!Jvj_d3.*Et7-Ѻ\uIi'O9YSSW#9fG^_s1BZ>@mR-PBpp$, EPUTzDO7֛2KB"ї4`!Xc Ph;Zt&ND| GC\iZGh-t8uY, l~st*d4R 4(>6HK uڲe%h [<$JB!;TBLƢmh 鬪hybW_{A'k`mNpV{N0k*9ruM$߉%<؅S!hP M=iNfqHki &/+ke0(OhȩGm@tR|ַtU|:n8۱Aۣ ?ʒ:QJ4RK\ B%;<0)HRjQ%)H^#҄BCok2'{TS-S;ɳH w$%I^~mYI@j7HJn)Fw 8q+Vے]v@zϪqE '.>Z`sWϟv-gơMwMQ0k1_2"vWeQLѻ4U#fR>Ŏ , ".$/ a'yӡ@$H*,_ p_m\pd\XK5&'rt鬭Nz#2~w^:24\}Dhkpɰ6Wh>sU?U Ux܃o}sX?VDlwؿVTTܚ t֟**'y /  GSI*w1 liB^";]^'e.He cآ,E@QFzXAGVMyPn2vcN1Q@N&-h5b$7OK= 4G1ⶦTtaUxqfoLdQ1y'j"7h }ڟq;\mCGe-VEu((u:~aCT'A݉S*חx- ńx#B*ZeٞRN58'`%:mPoK&=]>VPbֳ%$jWD Gb&rO@ZdZ;yMz;3{kz@ی{lK13އIf tҠNK 4l Cʶ62"^r3ycy7dRQ:yhN΋w(.]9&r1wo܁«#U;9˾َjtԇ Ob(rcC&萖G7hkwGYG^rGm=ӥ%L'UxiM͡!P+d1wƴՆ{ "o{S:ON!9M$4HÞ!hnuu4=M&xt}pWBFZ+EَFia;vHIo$k/jo*QSfvy!tUU4&%3wlØ "蓥Oxc1+7WV Ksr3/H&6lӡo,SܥVߜ?|6G?:<u]_h9ńg4jS *C^4S2h*8k[Ώ8e$D-_8H%4C%ӅN4P1n&Y92ic:nSBwb: wϴU]vRDZVO{T#Cjnj79=#9SJZ'x0-SZRFZrF);Y @'haO5zڥh 9|f3L2w8DǡoY9)O()AƇ"TW?qg ܈i=|GH^,"C9i01P xWƏGC9J>e=6+ -knyѬR-Q@@_Þ*KK,nbivEЖ0]JrNeffddd.Kjf.S;gdd&wLbt%#KFJ H>sMQiqlv~8I|_Fgz@3ed@ )9NIFo\K` {gT@\7vTye1h:߂ ;vl>a@S%ыꡄmE(9ftY:kt,Q1ze7:A27enMIb梧Oc6qfHs52*USS'2cuaJ.Leb2Ŕ;92Ft+\;>۠gޣStn%5s;€ bv;³;w4C)l&A?Ӳ: }_BKƋ?g VYkA1evt7~R9ȆN'"c7Չd99KtzXs-qڅWYbG!Nl8j8TWlOJ'1ݳQ?mm̔%)aS\F-u`msluJ4KJ(t4dbH\ɧzhcwM.(*&Ѿ}|}5yZL5U|)ID|ENWlIT\r赾"5>qr_^?a5 8g#dحP'@WUNF(ɑMԇ+e4J+ey U4SSS (*QNѳ.#_>C҄\-i{Q)EI]¥M( Şg t:S4Cw^PS3lm Q~vԩk׮;wa.bo}ӔxެG$܁|1li_,۹s'PR ~ѧa즇uڜl>>%U)l솥(yySjz͡wJ,\6'C$K葹r'BSNע֖bktmAG'.Em )rgOOE_o w18ʦJ\=d=vvD!et-u2:䨌n x*Jta@[F\t8 ~*"@7FKAP!X1DžkER>[y[[xVkMՉOx-tRН^lۉm߾;dF"hxA Z򐞜)I\Fk:7u LG|!ܶVH*ztJ9UGlg,:)=$9џ^3&m΀JYlOw@y.^\h8 R4uN)T $0r&()GN!@לޜx w]b{hPFVI+*ObzGq^(Lr'!i& 4h+ftSP4S[bB[T*@.shA-!C'(ȱ8bozUQ ץBiN28F2lC}N$GÞ*ԹODy]|Lrꑬ~ Cg )Pyr.HG|\!qЉb%¥9I\hGs(!eAm}2xT%,t YJj/:mKd#Rҳu)SܖݙLż0)++Co:8rNt]w2m'z ?HHD BKԠ`c:5؝lT$$zt98'a҂T|!Aq:/dv;2!?%P]2$1 @!}FeN<2(e,۲e #ܸq# 2#*5+S8qqӧ˭D`曟|I:Dž悌#q;0-s\̵0@K# 2ǵ4\#$q-60-s\K#1@K" WgG?D*d]S'KH`C@yv*y8͇WX,Zb,D(p\N1qQ7X+dҏw ].] ?…-;w%cbX0X9. Pm9w"Cllf@%&Zk$|?K* 2Qzd8VZ' 2T~ܦF؅"bV$ֆ 'Nп89BtRӗ_tUpŎMBJV,.JsN*g|l/Xf3E}Ż.3a @?ogqGv(+*5iZ hn9߄̊rɄ͛ s8pRduZw#,Y^( paّ#۱6J<ҥŁ,pFeq|}7pl9,-)#)X'dmUaNUlwWO˞j3⃈ %y 緂 J%yqS`9e׌ogچ |՞lHaNJBAh๖)_3ږvEˣ<ّoHz`qJȘlZ!L[d*Q 2Q˖ZYҎ2|(B1t˦T2c4Pm lw}`IQV,_^\+m[c_g\dݺ\lZі-EBN-K7 }i`RQ U [GLزR7b0JbVSUaQF H_*匵s5W=w﹠CkޚLԸbUCJ^XԻJ5vH'S\r bUorqbܚP0h20' XgM{zs|P>ErABT=3FU p.h7c"W =Q*Oa!FEWj'QVXuytڅ[~!B{CwW U{y0:12~yr͊%S0߫;==rN?Q*n+Jw6:՚-pjKno~ Ŭ~U$"@wd@6AJwBFω+*ޙo4644ީmȁ|YLeRD 1$ۜ ,7uȞQm@L l*Wa1TTVLHDK |X8+! $obih7TaW#Z(7"8piƂ+󍂋{6x・'ˬǿO16v9azR yRZ :իB09<, O>5ms05paeJ(J8_1#lcvҦ}Xs̄klj}|[;pAx'i ߰)cXhJϾǂ- m%۰aÂЀӱfV"֪5p{ .{x#MǚZX=֬IXo7ZCb#QCv@ ha:F"l3}t}=.־,Sqg#2ȁ+ݻw0sYM'gBiFASH9`I#H b0@"4HَqFW4s#egGr_o#П x1;HU߬Is?F"`m%ڮŹg@!>;p.fHWMp#gЗU#͚847` 2%ٹ@"'ߌ@E@ eY8yꩧ6j2V3"СC3<;l:XuTpȲe.ܸ up 7t-H@^;Q[{̙ dH۳g2qH{qq93++ĉo>AK#w-\p-]7!98T|[qx5J[P]]ݩך6sv߬kbZ=q@\?7\sW\2t=nPqcOUKpS^dM@jIoK0{]qŲ[Gio۽k$eby k[SsV7ma+Xkn4=fC|UˮrYd?WR)T۰~ )eIuE8/tongMA -S|yLjR88RRSI^AɬUόzUx^^L--G09!9W{bpxܿkJM)!xlN@ck|5wTEau*V2~l "`ǡ5㦬-235m.5NvSV́ҩ9y%"bqY|VM1e2yHgF.Z4قg]3]zO?-[{1s`{W=DH!#T9[DaHZ:M@AET P0w*2>5,+g?5zuXU^ ]~kχ,X#_U4)Xn͸5G% Y}< ݠ5`{vIvӢWUU=t>jvcW^Uի6sʖn%ȈAU`evђGA:/<ͿZZv+neKos{ԍr.1Mj|o/- jM,-rEٲ +wlj\{ׅV{ol=ٟ ˴VV(X֪ݤ k|Av%FR[ 6ώZ!63&*Jה J["rEȗ߷6˟=i wA}~6|>L̊f  =!'l]l,oo$9[V55X7z/df8G, wlȂf5]s*G!6l>}.Ҵ[݌%c6dM*&5.nVo" ͘3ll3f*V[뿭,F´2>_^2x!dϞwfꡥÝ GlA8u;IN&K@i"`\HW|்zCo+/qblg:)rDc!(L(5al+yYm1!Mobgl̺sD1y,E FؾK;ʝGO6V?MբbmT^'n{XpY{3 EKn9\Z lKW3Dt@9Pf{f6oJ?Egòh3"ՠr"a̿hilryFq{ rM]6\`~ tϛ nZ O(ٞ7?(7O˙?@eNL^ڿwgO-hxCm2[cRh@\oU>KяK8 #ԇ,&[h.9[4on9=G- >a &|T|wd֭0ah/{` Νl[5飇Y޷_G>}-^8r\p'gٻwl]~~~2]eVZAU%LѼxݔ9y+9\o!@,ώ4_5łw\4rXߊEKr]kA!ڵ;rH=b.<9?E4Xm#WM:vضmې{z|ly4xGߏ/{_q>,۹kqsYgA{ÇgţM@vmtղC $۷Omt*J01f;"i/NƠ%I#Z3Z\/#D 8*}F otq2k.0@"@W3֠g8#hZ~;0qY,5ɍgDT8zbFm Ch~m½`F&j\[0:FC[`Թ.1#w(&Ԕa7z=eʔ4O"`F;dK_b_|ݠAm߾%i:yien#$!ya_"tqh6{\A #Њ>8}[)q1#6x'" B.01BhAXS9q+.FLH4[}UyByY?\`[Do淢EjFE3HʳsQ%{ O$c0WsS PjL\Æ=QImĨeYMC 4btCCck5IYy k0Τ͇ukkȥmj[=d#D@wݻwCJG'Onʻ\r}}C}0_zɓB[䥓 I='h=ڥ>ܭ멊}͠VjN#sUm$:MQFtO8 =Rveҡ;t>܊ GEum+Qg䫥eL~Ǝ 5IZ'\qhLZ 9SB EeÒ'm߳AW+9_CuVRtVn*ͧZPBZ7g'-+&>_eA@`W\5q jݗX,.~8I܀ 5(0mSթshwG=Yqi:exaԓkݟ'29z:[+͘dFqg݃L vSP|@@ ~ᇪb駟~뭷6g\m@[qN?'j"c=ړ{W<; /q&Wݹs'c0wVz{?* [nM07 u>.ˍT@2 hqÇ%3<3ĉgaƝvi&Lhb/~wtKF 6ċ$0@C *$8z soiSNo~3i[o4~==_{}a3w`Zy'>7VWѣ;Npın)H1x*QF ^PQVRz8/ r;F 6A|PĚ6QoVċ[\2t蒠I~$ЊK&%5{kB7#%%J`=6Sj4|y` ƀ {rk[‰ x`Ff([Ix*fݗL(+-/@s*3[l&,Nhnm;~DVSwݑo Ɣ-іӖ6dJ&! V1~u33>xF 3n1E>=P:uQbvhq١…b>}KDA$g<|t_ٶ5` nOp9W]/ppqws+ HX/K#@%ѕs'P ^ήb {FkpWak TWj!uS yU5/zIM@`ya+r#(fsq J`8\VxP}z5WnSfcb0b^ $.W~ .ͥdYa%T8#R]͇QhyX2\.z&ɕ9Ѕ 3̋TC9*^nRCnt b` ~ő/Ыϵ_?l5›oPΦ3ZB[Ir(\΅m ,DUse46I(}_p]}JQeC(6ҽ" Ĉ 쏋Ɍ.225 pż!C֖hBLq~Xs:.z_Ccrf-3% ecmbE\0J]Q W? 1K0ym_텀$LRʬ޾҄w&K FF&<(I\u\ sek!VVx̧fQ&RtQPn8l5e 5~w4+#;6vol;AP$gXS3ki)0#@KXke0dQ0VȄ]yYrrl+ejSA^J* ~`g#MKK7V̜"Id9fN=sRN^Jw` ,Bwqǎ=^>ȣK?S:[]9?9dG3=rr><<^j h WQNwx740Z-`ywfrXĩ-:{J"4uرɓe|`é߿fSkK9~gv=zPLXa:X2H/ ˪PO%aXLRR[~Yu{U>὿|cO>|ֿ}ђƌR!յ(r+anQVXDnuS`mSC>ܬM{JUA\^ze}ѭ1@B!  ےirرoM(D#Ж; {̭܀_Š][0` uyW_ߺ:sr0/q /w`Z`0$4yzu õ3@6OIZ-pY#FC;Lv1bn#4IeZ#Mi.eF \0b pq#xI.mc eXGbB>Fh qMA2@#1@SP96M.0` pZkg(#U/cBhRc0Ffݑa䂌#r5˯ne#(s`Ks?@ }2`%Ì@[G@}vi[$|\bٛ{$qfq/#X0%@!h2s\bٛ{$qfq/#X0%@!h2s\bٛ{$qfq/#X0%@!h2s\bٛ{$qfq/#X0%@!h2s\bٛ{$qfq/#X/DsaIENDB`PK!) 0word/embeddings/oleObject2.binZ U>~ 5^0o " Uk0`LmGdc+IjL4Ԕ*TܽO{gbs;?|g?Ϲ<@k&E7ym)|/l >3%$WapErU"W\erBA~r sr k~kɿsH3͜%1` ˜ o@6JOLDc5gEJJMnNt=}p_#eKrt' P>;C Iw[44ǒ#W|?5Cry+k:ygg7{K${ 軰ϧw%VbǕzɞ>: }p1p,CJ;@?Y0evF\ou>ճgtֽ6{d'v|d iLBME?O&ka(m#f558v)=w12~`趾Ƨ^@O`3M-X;Wt:l+pn=jg^h7=-+)iT=!$IZ=2O"8ɓJ `'ނ&25}4-y\vqLei lTAdFex #y6%ȌCUt_&hV3f| F"䀵-(xSAu/[0ͩcxOOHQ=:[W1TbSSOLw ` |sŕ.KD liԑ!,f4?ES.Fj"l`AE.i!{DLQt+ FB\̓}u4a:1IT"/#QI E/F'|%v.mE-T$%V[0j[q9*1s%z-Jh(O+}#>8n)K(˩O>{еweFhkϢ"DNZ6Mh UG [I+oo§eDsiN?4q2hU/8$x?pzZFw/c=hS4s'FoЪ[H<ժy.lJȓO/-JqVntcUbj~1`Xr/ZPw3uuPGؚ$ʕf$BMH4,gهzM:]4YDZݛGЯgҐ3xTN%W',) b_HJ:_QTW JVR5K\ظ[!v-mf+>l{%=$Q)a0Lycbn;^0J=˯/=u%qc)MW#t,|˻Q:6ZJ+jy/ l}} cnI>gPֈ" BKv&}p^16ٙ45(ƵǔkR2y,tBv\w ֧.փ7/zbs$g'yv*Qw6ЉIʒcqy&L4nesFEۻ?JXY.?F,"urn7ͰApi}Ė=G&%C~cwfW)eHqֱTI$Y7`h.Jjx w_׹A@F=W<1uzJ:D&Ӵ7qVjSE.ަ# @D]׌R4 Kѓp9ԀP]R_])]9k-@Dg{bf;Ӆc:<0"D<*C{F-T0xi'ġ=/EѶ:ZritGVx<[׬5̧%M7%2rf-|3VRˆsRTYRi/ʪ6LCs{oduNm_em+`btִ#/Bd#3J>uhyu.yrt^op[cnZ#e?|FK iuolEt޵wr(/bsh9Mi_#o>~ !uJU֢Uk{߱ښZ d; '`]6l;oAnFnE䟌[p>u,mz]Rf9Xi۔PuAqe0V9frzu /&[ux+m79WnY3%a9Cqy*’ʈ!ǝ=WPOtn@F5G4KYC4KP-}>yZV6T+:rcoFB$樈d<“[p>5%2~ng[~QzeŞq_|Ī~i9GXa7a~dӬ8밵?ǝ>ˋf'm1GZƄ#($0xpy-t芬/ӹwaFZ=| J6<]ߑhs/ȷk֦$myko{u@9;jc2fUx!VxVwU Inuc 0f_rε,?P+Ib9 .i-~aH>@+yV7pVw5mU'fV2@ˋA;̲0LW?|:k^&74.Ov]޶uo{=P'l䋫n3 -p=vG.-8q]|Q:v9q[ݤ&~CƄx$cu {1U)OC!X( e,{\Ymf/feqì2q?M?IrZU ׄk|nUpھ\-2E [y-q0;,{?W "grh_)?O;PTYuUZݥĞ47mӟ.,? ăcr|(ݕq#co8>U1{%U$63˞$"BkOkV̼*Y aO,jg+NbR6[kΪo5[}VUM' 2M߂2IC-ca5^;V'+s!ee]=^jݯ^ix;5c-ߴ[9kզmA,{#cMwYx۵q^^?e5(V(|XUq\څ?OQUgXKaQ;1ec?&m؝߫BrʻN[ߨcPf5qXͤ:aAwqCwiY[(4{0=_އ :rUWI#-.2DUVEIeI{3\0 T+?ڪ[MV<;hODwRg2\d|v˕=P=1%wM)<Ú>{k<*2~iiÐC-3}>N a{[ GEndٔzo= [8Eݻ~;8EJDaSvqj5XmV,sܾV}uC-]bB[m[_۲^Q&+Ey#[0IDK8w8?~UaO&bvEvqCw'J0~_X K)>y}/mPw,,/m822c-gӧbMҔ}kHQ`{_eN((n +hxPneJ}+16 0io˝ò&;͵DmZ퍺ueɘ-͍lV!YªVcˏVU4S .$LK~~[T ۗВ'KQW}oܴN&D.(B{(Hi2+˥|J6 r=T^c:DZ(Wz.VE',+0NLMWreҺ HZnjF.(A&a*eWۣBAw} a' l:DfgQ,^9:빮lVe Y_cMG8XGYy@+a㡛Uִ*l ZN8c,l+N;р],8 +I fG+`n7)Oeo=v)PTUe<{dBeJ)X>5%N:]SQc(cpwZP"wRFTʸSL7n~5(3K?6cy܁V_3~)秎@pb \3X +~]~;>aՍ=otk5 '.amw=-ƭN8Њ'Bf魜YUg]ZƲ]6P8M3+R-Cd!A֐2c]BH)I(mqv**FWRεGm&dlcݪPE*Li oS~jDQ߱_Z!JZ:, چEm^l ^fc[ֹʗçc!'(jP$"ܨZ'5(mńT\!CCֶhcWWPMAX钏YQq,cAo~>U(Fr⁞ 돽b=E^["Xd`CqΧZW2&Eu_箘q&):*2 SFBMDQ[4n^8Ui"27Dʑcw+i;*%|C1jsq\[YKcw"Q݁ V.](*VC^@Sg"k*lD+ "UAj"r #XՄj<v+AWqcgd>28囨1"ф"kX=DzņA\m ߢOr[ G< +Icv?OC~<׏I5dae*#Xi L-ܼ=u{w20] 6v:fg]rv]?ڙꎑBhRsq SnR\d=Q"뼦nxU/YSW\{ʌEMTq!V;[ɣ\"0NP+K>~Gm|{J١ v i21=$%/[KvQ֩:qgB%;Fd'{/H\0e%0 LߞQVA>X.4VL[ڿ,zeL|I!V2qA p!iVѤbV쨃~.D[TϚJQ_`8բ2@AĸA9+DP@kZkx 4+W]|\VmRʸyBVơ֐,~479nh{v/B1fZE0  4.[VDD?G}2:ш5;ЄG/m;!(&'KLp %[Tkl-+=g%YF )T,j3Ս3i6`iY,p M$-J)`<{ +xfQ qVvBr)bܼG6lGrQ1Y9"tIҹ[},~^{XʹX)%ow9su~ك!-N<j)g3Bp󦣔Zy奞D'\ع\h*VÍ+K?R& H?; d"ژz@zxή}֮pşnG+}DQPѲːÙSmG[gْwesٲؒ9wM/޿׾`\ޣ'IsE_Ob;O#σŖ|͖͘a+gL3_f|V|VzVxa&5dS޴_ZA)@0=\儩ǯoϸkw-^[Ǹ|d[-OkJȮş\F3 ki'C*flvU 2]yN&b4@.\ЦԪvc=ꅘW+&pc/98|5BVU|f5\WJVtCVwU2vEF|GV,盛{/g1\d`9;FvO #FZ>_Q垶Rլb=,ji,xf Yh`h[ָu[9%[9[oL>[fdYՂNJ9|*/|hZ I\T.>v a-i1ZdMIV)VG_1u~*sA SOSP 32PC}j*EQ,Go+ TP@JXBCwFcY_+mc KwF(`|Z,=g'?{Yf8׶3K_nK%ΜPU;qiBYˆқ*Ž/#@/{7_s"l&o뚬HrIԜ2L16;O㷖6v1̗m.8eu&='|L\mB"IQ)KJT q,@]|HӿO}z%v]O,{M6Jd/D ]_߹[NQeMxSڿ*cQT󻥨΢BibY!{T3v?4`楰}lWRRLlXZj6+N~7UR\\;.+y)IఌVe\qSؔ]@v([SYG>ƠN}telCbOl|E:WTQHQ+q7U!*-RTb(kfQZ*N:aI[ V5nK(Ƴ Y8EQ4 b YQخܲ/5Q+WU(AՃ*zW@R\E0weK G.΂揦^-E㈓""ZT2u(YE%9dn:ʺp7SEЕʐAUʱvϩb7rڣwø7+Vp,+BM5-MTu"*lWҾ++?Tk|'կ)W,)'шJ `M`u Nr2]Rr"Xfؕ gYAO(4Z`gq!F˾@'uqc76> TW: Z jI|Yܵedy#TNt|4qc M OmS¯qQѿbxV=}G6S |nCN=t0u9+?l{ ,k4 8(ZSnmͯ2?~SQg5m'PP_H&EDJB$`FӧraK qV2!k{a%썩kەp\ *we3%_KQ{.ZKFЭ( Wz<.]4I2s#;un/-E{8on)}x%as!ma<؊iku[uwE&V)Q+NQBiQ]{g^=`~ P{]+$lCO+&r~_u]ޟˢ|QBqRmSTYT^y>z@\iJ!]*:TzY#>v라_ZR="dZG$|pd;nfs#EPîq#,kC,T&cn~z%NP")N^4+Q)*iIDɇ~cF!ҤZ'%o,:U3'.Z!S}uQR&׺ @p}U͜rQ9܈M PSBl!RDaRJjjB$%URxdocTF9N_Gw(FC+nK:82Lݹ[(@'5(*FW ]+ǕSuwEXs\(ZE{`O0gSz=c^_kJPحyOZXLk~=ʶ9u% V^u!aUlT/TM f ;u GK87 v ܳ6ۚfo1f -ԷK/JFNΏ[ -:pR-NuF j!]žgaHA+@EUı=:1 BYKԿW|v/X#I9Qm2Ҿv}= #U>cXYjV մUp C`,X'<%:'yb,p=SJ ك/K4hmFZ M{>{nζ1C (\ wq'voԠh}n>OUVJXTXq<;( <`NQ (L ~[v-E p~x0ϣ'6C}{٢o߽Pb΃|lgӷ`VՅ)eڣߗ!]nجM<Qֹ5W?eZJQb iO5љѨHG \Er}9zE)|v7ہ_B9 %7=*VzQGAM,[C k ^ 'hlo8TQGg`;([s3K#kMK9VpS_dt, TJe~8N=Eݕ!\wA KOoTP:^QDŽH%>w\3u6Ͳώ8@C{@=Υ_TkVXKN`ՙl֋7wE3ocqoCnOfbϾޛ}%{IV,}f#MV.~V̛ kMk;QwBǢhVJ4Ҙş} t;L#-Q+jENЦIo E2 P5NHmWUQ!l.:1ŹFޱ/xV|e/xň(=K^׼-_-ceXi?xtae;0pz{lޜ[lܩ6[0jQϢ2z vm5{%4'~L0n HJNA~h'Z!䂌gJ~ƢZEiu{)8{)cV[ҢYM!M;vI0Ӟ}} {)]=t3#PB פZ]]K%.$W$/K8| Цe<=_uXL)/rIC OʒSl95PooYm!m Ewq:oSO*8𓋋.BR$zssQZ17Ve[sBF\:iI;QQ,f=sຕr4wb[o޺_HtN)؊nbbD!|mTW5ȍ>ÁߝlJq7yGTg}<~lMIGY #0UaWK *UA<]!P-c5J÷pL,*G-~9_Q4))SOQ)lI& g%7ͱS*V:kڻ`#l 1WUS:X=dɬrS&dC[7ɣ[<6P;*Z67P\|Y:F(#8դ(q"ҹv"*"='"}R V8oH^W@EGtECia$nM~-g,+MEun΢zZw%5;瞛1V}%5n$ i͘pS1,6O#MVHsD U`s*^#g.QGjj)Io U4 /zldQE7)UC(%u #~D0MH:÷["b`َ!Ǘ* ](*X2&u, Z*cwdv&u!i4|+V}.\U17@9^ JlJ0G͋}MˉJD/>FHcDe)GOʢh'mx(%s>47ůu.4XQb8z Iᓊ')s8"8Ę]-Ҭ-\]#:2aY)u(jwU873ГXXMʰPXZihHgA`q8aj鲪lj"=U0nA6Sn4Q_olT+E呅 āW%s#HP=G=8kHVYHݕ,~ c },_3~(꼙m4:h8  조|Ǎgo3z]-z7u Wmt쌲%1{Y |1 ׅF:6̀RW!EKRu+Q3]H>YEt3{UhcZEB ;:b`6l0 7u9 A犰]Q7B1h(U" K-aW QI kBh)*TjVYT.fsV҂ B[ܮ.#~u롨}+!kUAkLi5\J-O9-* I2VTm=E S q.~*sOB"ס0ҿE-$O.E-Mj׆踱#zQ9~ERThEb.ȆWV)j|,#TvELE XK;bOr>jg-s̖n闢G%?AZ>-qY_XA;E=6DmWԭEQ6SQˈRWJԴ+Aţf^KElJ_sT Ze `SlQ%_[ n ߆SUts8Ue ؇SnHXkU ȆOk*+A3OxZdvQ7>eV̶/f> ҟ^ω~Ϯ̔vB.RY/o ??Q^_!b+h҈RXgQTqܠ?N!gMN0UmJxroԤXԜaW|{fjhA) ƗʹK+-rBKДSTZ:A~kDQ  _ 69gٲwIwm/?vrOm#whJ=8v~jϕG`~>`u*FG8QGWq]5ӈCZӶ|ŃK_էp(/R"m*_WIQg#"ZJxM ?yoM#L50m\Oї.ܪg6З`L ,eļI.%[]xPZTicRt5 <4@b5d';.Å| |aZҤuX:6'*1B-.2jr &nWMBeG)K8?)v6EQ+ȤyjvөZ&c?*}!a '\eאq%2-G >'Ucu̡7*+$j /"c%)ayO"pΧjˇNғ RUB +)0ϔD=!#Ba (~++HNx:*)?.2[$9rFS !-XD(j8Ɣ~D;K'xh'"!3GIF1l\m'5X4<{ J?Uf9dUyޣ!jj(U EOW<[ "@V#qyQ◽ p@X(J [Q=m %JL$ ORY*!S7ownWN??k:Aĸ^o7FAXQx.JU"ZymНB\bnB蕊nBy #~qTPTg5B_x-a+L=#2=9|9 *i}F'z#]^),ˁ!GGrL|ܞe R*R4Ye_G!@UR_Im YE_Z n>Tzk gQ'V.r5p 'Mԥl|L&+y%бGDWTϾbf;Y:f}wYujDpV* Kl8 [yHxii10*مHM| L~m;lIH$%DOs_? 1ь8'6v)'C{{IޮI_G.Jl~#JC<^SK #/P8"z. Hإ`)mˈVDdgsӊ"s[,O`N6YrP=^'v+80±;M`ǥ33gl;7;f]JZʼṡ1f?I!J[\21o} )x4sCVQÉ6iSRTV{ȗ2 -@x;"hIa\WC4VDZ˱"xCzMqrXr}޿Y1޵nγI'S8K*T`*.'h5oTez͟Gֿ*ZJ*W7\cd(bhW%EU@cdZZbrNt쁏seT&ɇtAy4mFҠ )6"ʠHwփ.T ).MSj޾v  ?u=*mqs!9o=uG2[ODQ]7UZ휢 ˅yH)veG}5/UxmxDA=`ys:=U걒woTTҧ*%6-M ohRF_*sEf>Qѥ$V 6eP}빮|sW6Q*r`MYaBIQLD ,p 4Uot-nsͲO캊YTnk,S0iZjtlg|ՊuAҍ_ǒnW~HEʿSS"Э8g\6w` 05_[J]y9/O]K:VTo%.R܀񻰛ߋ`#cz'9++DVuO?r׺.w+J!tSp[vxWRwjhutY^^Nj"!|ʛ7GSiYTw.+B(=cJ|17s7hu@ɱ)i8Zhݢ"GEU0{ nvñmU'zî ;E+k "cG +jWլcrfBQUHF \}ƙtj{nζI!{.RV)lHY7o>gT˥F /"MyM$ឰ[/@TAՃ2"e$΢*~E<"bS%H4 ɲ~)Oē*> RW+ӆjJQ7fMT<*nZ~v.,o5DPP8rEE{"8,Վ.%=ɺ+ڼarJQTϺKQVx :?>|A@m'B;0tG|Rrqcʺqs(2JOQ>L˗'R 7%>(iɨ~ ٴyWjTE )S kQL>pG6_Qo*,F4zi2T8'瓍5:מ?1f7ۗuRZğ|Ilh;a7d^)sB)d<_QPWzTFW;fZfe;'fsɋHҡǕiyH?z%O#Iۮ|jX5FBv.3[Qi W,+\&j"Q9x* "pYmԜ& *VhOoYzNQ]L b Qu:vNѯ#(IvEbkP.E,9{&%w_`EWT]lK[X(RZPZvmqEr@]q"$?PuPz* 0hukPT8瘧~S.\k54-#E-Z}zR?/]O~a܀@U:vH4ߝwTw|T?,*Ǫ~ih:2%P)~k~sOJ ͠kvSofhsMl^R^?)PNQGGͅӴkHO:w5R4g'P2,vQu؀Q#A~c)j=x ۋ"lbXV¦O^+V`Q}<ϲ&Ra8EeC"S 2єJ`qe^9.+9CҭKU8N:z=BmcIJRk}.6)bFo]TG-eSoɶ4Ċ M('7łn~6EHj`~Z$lb訠zjt^]ı{}>M=Q(Ǩ^e۝, ca?x*9WMq IX-&BݯPS"?RZn=N؞˿Ұe鼎]K{1Yvk?>_Q'ے7v=ͺR' l' 3^e!<|SGn76V>?jMϏ7E~C썧9^TqP YWZްH%淵B-ٙJTII໖:!!7:6G_/!YM' i烒t]wBʟ Kxd2t:o]o_Fԍ~Hنz74}]j0u,'QH&NBW.Դ]}]~R$$z?R}jYn0os~JvU`VMƕ8U('r0vw|j# oEB|} k[lgy= nT7m ,笣YVlNa LS5>u i/~*Ҕ5D)qϕ_~ $ uMT%!JLaYPoY.KsN#6v'أחz([o-?pf[2~M&cקr9a;VH7hΫ⯭YOup5kZ&Ll [\JPTVѧt.s\m wμ( ruk ?%sa@ҸhIQeڕ`)Rzw4{ȗBҧEEJLqyTcflzepKCABBCB`0WcU pWTgOH (ҘѮ\O.}/r&zt[}CI1,0uk]FQK!ĖAH):]]QURXL<}S_8ըwC;?p&8 EaQac^A O]JRaQ:v DM>'osJ1OyE0ǖ:"PXn> xe8J},`%Ɇ*r8%8'q'Lm+VA bٔ'=ˡ lx*%)SBc!J+v[@ uį2Jkswa!$?B=&3&VeBP'_b_}0 $&n$P$ï2O,-$/z;OO q@f?p5fߤ))j M4W-k3^fu}2[Y7G3_corUW۫\a/=~xؔM_}=Tګ>N*:zF^x솿gؔ8k(oWOɱ7Q:Z#lk^WnV֓QXvoF\Ϛz$ N]h8XmQZ@L )O 7+ 4镧 v,4EGMʹ,*mmZ cv͹vek > /:M.>!xr{=O=?ڦ?2^{aCCuN?^"{Kl thK|䣗iOޟ~zN[AUHKQlsZ"RYJ& B6XñiFxo ,Z26OXlcB|# 27JZ /rGxиXǥj6l wWo'o=l M*A͍mRh5 dh1Ɖ6qWB׹cpLϑqC]Dg']m52pn-VF&ofBVlrJtO3SbulfxF[ēʏ6X}M'WpdC7cPkgc(U߄RCʊpMG|}>jҷm 3xe5!H;M!kF7 ׼T])S85&L7,ڞ~Mװyl\!k|]W1l@66ҥuEʩզ; ]s:=gMv |ԅ鲱pH& *O:#qٕ!|T!*8*GOdJCSmrFeJW#vxBէ[C)y|5rRzէv5DtX;;hG{5Uz08Ls{S箿EHkA@.b"vB^gU+%qx׍Mwj3!!OFd`(bܑ07g5u~/N|* ),cԖGz8AYv{hvO&Gr~m_w NupoHuCM*Yb %QZGS`m%+ q,;V.ɚO'p8fzs3M;P* `׹}Ezee0.Su}c|QiwWf\w8&ڟ2FtUn"IREz(rmj.~0zH[ZD{K2,`7 UDW%[Ӓ:,(p_eEYkPR Ez;/.#(ؚ;VK ڬdRu1>*VX¹ {5M(j"< `6)WʺdR# ʣ5/|-ǥ~Gw6|sұWATUcrt퇰>5z(KLE;VB Q@e.ˤZ?kjT\6rE!om(R=  sNJ'~Q0Y tfƪ,(dtb*2KPRAnulODjh2\:Mߒp,am[twK)>}ΉE%r-7uk]7_tx]s. Bg:HU5kxzJ8(>:@.?U' Z_uNʵSE R=; dWح5FGh{nG=}]o*Aɯoa,F:L%.o[@5Ӛ$@eGB~2K2 ÔQk_%XJBc޹{>EoyEUM7k#t @%^& }*zS`'`{-'3nG`i6EFTm<ߣGI *>GKbKrT\^Qr]ea]HcG%Ju&&~]^_J"s<))8EJJ[`)aRTemV.HB~"nuK=t\].b~;{bBJ.Bf&eW_D-sm3:*ҦFwJ{6Ҫu1Z( Z个ަf_Y,^ w8J>gkS5YpJI@<*-|7ףw_&ΜOl4 i>YH5ݤUNugނ)~YƲËFy. p}iq+W@e1-'Dˍ*Wѕ(w)kJԷIۂF)iȇII١j ڱi~dm ^>w~2S _4TE{ %._iTYSR !$D$"d` rueEy?\ =ЍIvWu)S6UU*Dv_ Z~. AJF`d2{ZzpzíUWܷF ^{(E]hI9øGrO\HWRTݥly2WTUuJJO2~Q;d "2vp~k՜c >x"jbE۵_nY6[n)ہF[ql?'Ks`azXJm"I}rP-8'>wܖ'THJcӮߗu% MSQgFZ=[lUI˼OF޲% $)er뫒#/p˦q[E-,KAmyFK+‡tnҌmU$@Y!]ݿVfUV[h'EjZxma'B/+r$E=HgK(?6|QxJ][G>gIcd));XP)*L>Na@VA;:Ir3UVF-Ԥ,~WFp+;YJ~(h״4;KT&~)j#J* {Q]hd^xBǸny?--sUl*SPEpUL> z˔ʵ>QMє?aWL$(+ h=ZTBiu2 "b9Isqy0MBH(S S[/I#=i/cZ{ `$͓gI;mlzZEꂮ|SY u[؇ X,m`K/XLN s LWȗBwB%$}Pp5j_Hŋ6,GU s_F,u d>0Ksqe(aU%*Tswq?;SEܰ/߷kn$/gTG4. 8-^ n_B@Wh( je♼HYA ˶`Q zEDBh3}?Z~&.+^t4~^ ; ݒ}cǦylGT;סOVՉ5cTGKȆkB/ىmJ+uo^T(op#&CtUcSp}V*~M;.t涆ISN]",wP֬7ݩ?kc\Lp!ETFz'Unf&ڦJ_|M4ߊ0(rx2dqe Ti]%C"rzhn/knoA@Ka~+ܕR4dVXChEkfdrکXmlZ2am`Tײ ØhjTAʯ\6XջJҶT67iToժ5xh":x@u 6"^JBs{xUn-yKZu<_<vsŸHĮpzp\Wdƛ|=Nt> 5V"RT= M$]_حG\БpX{(4a#҈Z8~hvKZhZQ:=nػE']wM[metFGduw6@W%SyLu؂cǶ}p<`SmDO%)VV^U(\CQ/4@%B~ǞIENDB`PK !/{::word/media/image10.pngPNG  IHDR۷QsRGB9IDATx^} |U$V@Z1S?T?TϢKpGqE-Rpo+j"A*hE $C,֬w}wf}%%O2w̙ss{]^3`PaJ2F, Ƞ}'}Zem\ ㎻K;Ϸge 1 Pt&VǫÛnLLCgȗcX1du7঒}ّGr̝;w.\N9xtP+,CuC&=ŊItSsYC!C Nkj-Tj6LQ2~2UB? u|9e.J|Z+>jZLi2= Ps5?fj SX[@ Vd}:W{qڳ%=@Av. QSikHCK8MVc}PX_TWoݪ PPg9{CSCCA<.$2AlBU'څ֛AW^^>f`L s9믿ԆAd }n\)ME!e^9xzYSSOYJlCoRSѓBA< ̵<=l솛*̙ЎYE[ $h_B6AAROH $GQ F@NX>P%&_M=z#kh#8ӱngozG(Se[v IMv9'(| TOlTk&r2T^ ou|2LFO YE XW&hazMҎݧmE }ۢޭ CV7CueayUc[j[I(_g'uvBFA4 11h;eD 7~GyWw}1:G @ACM744BgaV /MWWWѷo,U(70G{4 `6(jIy Z)Oln[bzzAo tD鎪Q_.aL!,:ٴG2)cUA*!g#u%h0o˜-ڊ23,A,Ɔ*ͱ.Ãnzܵm$;f]$^\tҢ/- .*]y'q^-e88:?;XeeehsΒpNTcN9=pʉsR:Kxr I@RpjI֛aYAn R^jEJ%p1RQBd9b؄*5CʫP4Х)53f17m:b:bVU,ÙVgѳЛP-=zPmVnkjN9 |hG6)?~ ;$ٻhBh wfvs=rNTQdCu=NN{eaJpڴA2=(Kmu:sF0PI;0<(e5*[s4_R#b"6ؐ ԶLYF.R> ҢF^L Q4:V0b f*jaڑj%i&h5Ѳcmt "_nwܢmJJVaQmᘙ*J TI N&y2vGL'e`=‚y7 m3<7^OчVr';e]{m'p3J(edd:NTG qLm,3M>>B6+u+LAbD1Xv"x2o6:)'⌎ЎLS<%ch:܂JAr _EǃUxP9'/(,(Tn* ZASNt :g 鴼Nj7-7D+2tc4U%l^i(>3SكTJnT(E0@p 0.Pᶫt$Eی_͕ ȁ|8. -,gnKʄ6L>uILH'ODhn-' Q_ڹf{ĕÆ +((on"5JyGW;z2uzmG xHGRUezb/1x(z? ˨"iqs#5Aʧ]Oy}Yu*vICV 㰯~zAGSXCչCFNG+c&칝N993s:[:[-H#&]۬[;++!Z9|17SnFحNJVNGh43#1ʂp5~`/B|^ų#_ |5uZB7ré"蓵=uOO&g즒:=nOU!ch.^fUٳjwlKZ&+}nx2H}!'s]ofn̜Cr)KNf\{,ݷ?(wHD2B>칢E.044oч0h4uj.o;Kߡ/>5)OV佐DyRzE*1.cX4蘝b*҈LſRtF{%Y-c^nӋΣJI,bs94&Ԇ"C;3 .&J;{t;)[n;vv`;tޱ[=8{ݣGV<;T t-B:9Nc1o~W,,3rq!E'C+,jgٵԚ}`_mzt7[R4}F86hUe-j`Ѻ[ ֪<.Nʔ԰+&HYj&Nh1Hvk,/詊&aRF9F=汪k2ؐrqǗÎ;#rD45KNݺvڭcnp}H#8̆b.\v8EBC-n KW ZmB?3͝***]8hSg+3ʳq2 ו`ey|ι[wy⹺kopRVsαVl̉#IB'Bx'CXO/~7w=?ߴK/~NTA\Myzdo`|ކlfXZhq(U@Ɔ$-Q22`d9YkC!FjwNh17=i)seTR"@³ 9/+̞={\vфI?=p>bq=N\̋GW2aW؎?J_]~ݻx=̜ҏy8UcOa 0 hGR`W0mlft)XĻiaJTbe(¬3e@vBɑvK+ƈlútPTc{J9miz ,mLtn]g՝l.ՁomoOv8 }go{ J L;['p<sHዿLq7oqTe:6s<qXu|7% ]RrAFP=RqޞtTUmM!(ڴ[&%Vp<;9;f3Չ>Sh)=?y_I%I^)nÕRJ[޼&fҒj-t,e΍W`4DCX&e[afW#$!ԯ7i}/4&m!2e:F-~8IMz.S﹁Ay*T::nذb'2ꥃHe:hBiNUI*P6ACHuzeVuT*[1ZT@[Xe4o^J%,<F?, L~'%ꊌEZ*~F )CխT;He> őGR4C C_?*1m{=#>VQƌHZF`62ߕAgCo¢ŴUQ'B;BO\.ߘzs] KU)Ta)* F7J6Tój75#"Q<:.o2U#J pR~rx҈L[ sOJ.RB_Ok}@fn k%G7t<1:SX&psdJdX1rXAbRǯYسyXMxI>cZ aaTO!hHq,~rVNp b2]yq]|rGf&;e:? FZ{UߐMFI'ȳy\Fh%>J`׀(֭[i8q^^{-.EMaA ?~ܸqQ4qդk^hsuA ..G}~dk3 @ @'ڠL@@3l|Am4g8m7 МV4a0QYh6 E |.oʳ#]s OJ;)rPAّJ_cVjqͿƟI/5' %eӀAp\B@qq?!}@b8W3ZYoZ(PdA;Jy_`lA`-5Fv@39U`ԨZcA hGLu(Rk {PX-G4.ƤD9f@y3ndɪe2hMDތߟg&57t$E|:jsGΝ }C}섄ȩY8bk] KU>m$y_k>d F.|u)dH>Ḇ}dkl=(>PpY2kѡ'_iWȮ֧p];% NC}Sԙ%0+Ѝ<ѾPr:&zAXc1^T(XCE@-QW0JaT!h'd /PO8DoK{lukX81E IA$q]7BF˗UU1{d Fns@j2]fZ2QByWx; 6wH X:(&&VN,)pL)/q\`9 :XHɈGTԺPH ԑj>kFAf~[NʮgֳeOYV6ڨ3y.2_ DOV >mHB!ES# }ASX f:Qf "G;o$ XNYz3ۙXm}V^% 6ydڳL) GʜU=xQJp-jUck&M~.Z&N?"x*$ Z|h$ ȚIU5UTiη>#!??qݑk_} 굁z'ƟXÀ EA_^^V'`=/Z絲An.h]ci4SۦmmFZZ}'Ǒw3Y& Aքݴe`PB[A*Pq A@o5q@sT|BiM+@Nqed8OrA `g @A h3d `Ho3SfcA"gG-^pA gG p-4 :15מ=nH[4I[[a@D@Ҝe iE8.UcA >4; `H;ŸgӮ{A@zyxA 68#1wGkuV wG{/6m:jt?u]j-Z@TTT`qx S.w-Toڵ륗^Yڡhr8&yyy|38=z|waFE ''g޽pmgje{E&WIZUP^j@{[3{XC|5Ou5&b`K6 %*Ҍ_lI]EK(m]3M*VrQ08O.\PV9ǑXȗE >7Zp|BKq{[z zPTZZ4@0=!9W{,/[]Pec|"> hX~nXϥC&zeTP M " Mj&8ż1rҴ@Cfvd`7m\X+-ʟYJdT/%!_eӬʭ!qB'Zuׇ =4淅܍oPo-]xvlo"vP0|$O meNuG IҊfX]*"*JsA/#ZXucEG99c.5WlZ#ڷې8+ܛQQDfȏtͶp6 iFΟ%!#EVYɛ8ybI* &RPFy3? jhhgo|26~T锚ڃz_r 'USvN#.ʈAy Vs*F<6}?FQ쑫_KzV.xKoG"Z<}ɒyAo*ۀ8Au1-U^UlH>`;g룶SD쯬 ϙ:ŅĶ Eʈ۞^jmVm , y*4/d2oNԣO_Y8>m^*>O$yi̝w.T {J߀1+"Lg!5U9fvocÐZij73%S@v &5|SLg> WV.[7M05wnyvrLUŷ7hêYh+ieBM>cՄ79EAQs s<{sLYg̝oV)Raí6 *_#e9㢥o]ҋd0%J`*ոHJ]d<^N{r,pX/7Zg ˆ86D^>ۺ̒wwJ Mob:dm̹wLuSX /cb^AQew7")Z\x7?gd+m톣=qds%;*^=|mv䢱UsxE PF 4PwJμfDrΖ2%|cvڪeotB ~7{ p= bMn;pHztܾn[lB@Ll䗠%OpeFݶeR?܎"BAy9R<}mL -}tA8|iwW|\anb_pAr 6Zp9UT\HP䒿&Xɤ5# @q4e9=:tسgϑG( &0}QG5}Z^xݻwO>btCoߏ/mijO8|Rv@GRݻwK',@׿ur1Εq\3 @qx̛sH˪)Q `h`yAZwTA |w㺔馴A p-].'HDA =q`!mcA!f ~'i5Ǚ[A+A ,4ώ4Kd0}Uw"Q `0FRo!A `4"ʚGoF9A`U\8A P*)//ߴi&ׯߴiӚm= 6AbN… mۆ:Dq BeL3LA!q[nz gU !]KoCvs0p.@D@anO0V NWT4|/{-t?hB ǫ*gM/A Hoc76s ofVHkl@n:]@`~>guݠd")be42W]hd.EfL6#oK4u~@FPYY ?GqSNmɻ\rCCcCS}_k=mUR͉)$e tڹkw^=zz>74J)۽mtoh{9ÓO>S %ְ䩏@K8o?WBiCs_R{_]n]P(SlТqCT%bI"8&5-#ri7_I׼.Ё+?¾>R20&;}T |}SCk|جߔa|`pe,O*rcQUqNzLI?~,QSzjRnΰ{T8qLwϟf˦Αim]T>Z V %K r8/@z8Y>^MfZ:f#4e 4C Q{nDFC2 ~y/kEEE/NʟO+.{0 /~wӬی9@k"X֗;Վw~kν{w|{pwnWfYz5;ƴe0$ m%i,;?{4r WFf2*~?d{쏶zQ ~mHV ncӒ`7(&?v8;EhQi<2_L}Em 70?.p ~qU{ՙ@*yB<U6 j4[`T$%[#=_Mv'ͯ -*LR?0elϛ3T+-_6i`UAy΀ E z='^)#p|g&.B㍶3kث_`ufg;4r; ;|Y'Zl|E8i(K_[]?P2Q!be!k D *6@ iGڦ #a#[JQ=nK[sǎ9:M> ._^2MțQ2mr{._rpCzj,f,?Ҏ_Xʬ(4m͊N$j`$MˑTޖ9R,n-Тaו Y6vN΄PޖXMbɄͣ]*?8P_z@|̲=;~4=wH&/)ު+,{–=$'(nR,P <ՎUH1aUVY M?6Oӊ7.} _V>ʫ1t ČEU톨U@'I fؙ8\bVS4~$gHB3SPD26Npm>M3$}l^iƒ0\U1O^(7׻-jl޹?F+;AeĊpQ]xpuTH0a"*UZIjmS8/WuᔖY ^H(z G!Zt8L+Bj3OoMli+R.`sa!!kE%tiӮ 崨Jt8G7ףK}:4?|a˥^^-wa) VG-_dRZU44q3  )+ l92dFkR^`O am4YHˍ(uY9,^FX`؄o׺ G Q\iquڧ /=[wuV"eVM%籇jzK TQI9),-i(~2\y>Xb[RCrJS]`f oNGoC$xnvg~sȮݛupt߶ ro Ub#u;EKI+Ǿ}ңun %[K+&Ľ72Edq\MM_ZvK/m72ͫong';bĈ@Af1Z|[!:8 rmllL=v{5 %|# CNǕ ~O cA 6&8,A! 7 s*n8mo{ 4@qҠk DZ<l7 m8еQGf D"H"YA HL1Z A8-qb0 s_5Hat18%U# ` ّ `H㒁i0 ǙkP:a0 p!4 !` Xu !`NFA vh2pmeA De.@09 @r0&W# ` C`(b0$C@5"  `LWE $ `$jD Ap\`(b0$qIՈ4tQ `HHs BIENDB`PK!8word/media/image1.emf?3M 8 p;&:thfh'$&sX:4Hΰ rZ`/›`sruWswnߩruvT:?<I[vSg+N_e_t_:οOD??i/QS/Jǿ=y\{?l짮O_hG'x!SzI74?95ߙ=-omo^t&?eͯmrvin?ʶ_5omf٤Mi~U?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,_ԏۦY?iEm|Q?nf,[oMrq4jl~mneM:>$eu:nhrW2?5H>|Ç>|Ç>|Çׄ󡄏ΕwQ?{>>:v}=~nL ^>Rti! pAz RŘdr"mgh4J%bQhϹÿX@^ϘaHeƺFrrPyڏWb+U޶y;=8r7 /xeח UbvʠG ]NP`XN 񈔄s }|$|eF l#O9bGd]F ǿtkL ]Hږ>FGm/l:!_NTv[,wY JUӉ_=#Yҹc/qO^b` LPUʣpbC6/%G(0S+ @Xy)][bY(QXW||Q׼п.E՞F.fQ87/F Q>JV^g<L2׫U_Ͷ }+Gkl/V]E`R'>Nd.Ŀܳ\1rh8Bvp8#9N_WűłGcGˎBf1K+LE.&H=bP%߮uu݇\!G]bXM@1xDQudpKPyM^ܯ_Y=B_>4gdQ\,9%h^~-St~c6 17:UbSrF,LY(@_!67\>_,xls/ PTO*tlk|IsM?/l6T|37 "&m l6Bkb)':&hOųzqg5g/.>Nk̦h?G)LdSqf|˲6sbon:ucv''fs%!_)иO.fFs1]]..Lpޮ+r݀|Na~8  |K1JRW2ŏ39vx@Kl{2褽>-Q/)cxctԿl<`%/E9VSc>a,!PF 6g}אp 3&¸_P;]F䨗q9F2?ꅗw;E*R>@O&nxk'/mhQʹ\G7v׷ 2]iרgS !L#(пPE:P61"F Xݩ_a)o=u1tŜ0psf n;z=62m{r|(\ /7ȵ2;{!'P8ikoW~Gпt6ҟ>] o`P LtuBxDNeu8xп'FHn=( ۔4y]SP\ͱ ]L,=]O!d:¦h~׋f =p7~CˁD0oke+odbyhBq 2K<7,͆m0-rⴉ\߫gV5!ƹ̺t&oPO&i|z<7I9-ZLl e=? > |Mѧ\>}St/fCV_S/((%";UNBJN25~9+Pbv/FڿG?@m1zq&0y%1t/W<?GmLobz$i(\K!ƿ>t+m^&x- O'Fg<]&N(;sQxW)a/H&a[U|I|Xۂȿx8m&oL\tU)Ж4-#1ݬ=(ZGdW񕂇/j]\.\Bt(?(ܮOTRi]k̰3h0ݮ1ZTLNjg,o3*~}G++gb(Vxn8\.o+tYL r֤uQfr|y`Z>E#'{#ͽaQЍz4A=|:: k35xCvKTB|pܓoxgsomh  uiarpw[uk΋,[VaFW>*4O'nefO#s>pĿt:bѭZ@  8fo1ȱW=/(v (%KWhտ݋e$H\8Ş˗.Gdyji E*_*V-;]ߕ/SI1aXKJ 5Bk8{; _&Ŀ`&9g&Y,K [|~'.PtB?3mw<̮HY#pԇ $yPY lpg{a}Ɣ/Ÿ]SV4&>u)>/a%&\k"|MԹ:zXz!#9u6 1[ܙu}" >nYyyjuT.ȁ+W "Udf6An?'7_6Y޿Z<Ƴl5&riH +γ=1,=0_C2ԁg?'7ۅ!3eO_k1gOyF*W9ci_̐Q_P5@ո\ jc =þhnN.ˇA$d (WK9ƿL:!d!kbÉ]:293&HbCaϭ𳷋I2rWKĿ[aI JЎz1Хpj(bh0Dreqr3ba3Of`(vEvz^xl.sY YY߮~X7Q?xߠlȹmٹxdl0 \M[1^dAd@IN"Õ,/c#\azY6Ga@5r,rwzE7 dLD>f7,1m,MV\t1NM :2Ű_l3Z_/ىe,4Lװ֣|yNwsФvC{<^^讱umVxO˥'aɉvrG%fMl\޿Z_Fg5[1ь:* AG bܮ'wdBx q+bֱA. kBүVnWk /۹)Јf$(x?wHQZJG3u"xv\ҹ?Tm3z cB=G1Va`7[Ow[P:ڣOPYsnWjm]\\r, d5GZdv^:፧+*F]H`>v:h` z ~Fļ8}U:[F~S(&R_W/tȜu> ;Xq+)W‹GK9O/m1V(_P_meb_"X_|[a%t빌ypѮ'FP*R:[AoG~ ́r x {4 djo}1̻ƛǙۅ h - ٓd1/ż4 :D0 .ۃ/k|XƾvJC%FNA"e v>VfWRʉG Y?hPlT~ҧ`r%_rB(YMB-ٹ0~<_5ڿ6ńgWK^12'p6Kg+~ƨ/x,W3 h.;CO˼o\h [&xJ@F._ͤlWsȍLm2d/WˋʥŹuڷ0K%X Qǿ2W ׇT"!W%JT#w;@MЄ62ʨG&\*r1_-U.gEU+4!b֌\0lFp\ 0Ǘ 20 io"3â0+:'7޿<$ȿüp#HzjitW9P܌2LDC'O4Pnx ^]՛P>Vt1_m %NbZKͳ));_W>G>I4MN5]W,׿a- 33lxku^k{(VxW bTo/Gdx.&Í]WKĿ@// brĿ\/&|ek’$}u%@5͸\Π> ~>Ͻ}pKg|MyW i_?'+SF|eb."9|>]]W]X|i?T.AP_J gU7ǰS'oÀd:&CagZS+~LnD׾^L'W#c:MfzNOd}"C:7t\cQX[:v21HT}P}|(YA7,l=tܛHzŻ\+]޿%Ϧ"GAY|ore˗Gu/Fj@D/Σ/jPʝ"zjcW x$k ?Q1U}CychL\A6ʅΟ8I?SS[yjcDWJЗozMi xt"vRA<޿Z%k}ԉa{e"%W486l;iɵoDjSOP3Z%.C6r #:~@1*'fGW j>mQ[bO9FGL 8G*z Wۃ#dl YyqR]s1_m Q_Pwfؕ{D>y7L*Ky* AĿp3p'߇ST4L?qIs<1zS%yji 5Lh^= ?#pdO2_WU5Yzy^/M\ON^FMR ';us;vspJAYk?fc#{X4gXOyz(ֽgtowjy~I>wNɷ'%Ώfki \v8گp \j WX \ bZXi`<+6b޿ƿxzb6uVD98I4&%P%e_%e,@+.#A^%Q avxji"^fcerؿy=ಱ*SsrdB/s[eM+vn|[er wxia+T?(>>Rпl81bE%hY -ZSz.pԪ Syz G5==a@=KVT_&:zyMZ'`W hsA(6P@% Z15,PKb%eq.^ P.bzj]Aq"ݭ hz*VBg,O @gT:Vi9-|} 4* Cc4~1SX \%X-<-CXSv+.TWcrGV+b3/Q;,*-)*-)U2%[Z<3KbШ޿8^"Կ)2+WJX#LSĈſ4\W|š5| ^K\OR=9:*kTi,Ըz,VJؿVhQa;Ѱ SXpMQ.*@˃@y.h."CkA3תa=8O(a]bi&[e';OpsQ+'hRRΪ%h+K|Wa@¿zm /0 be?Qh.VNA\_KO%jS:pieb.V&]V/d Fk)0;W+&#*[2/SH~z9ʒQ,NA+UucҹA/UZRl,N`Njx<ƠUو٠b~(CX9b%p;l<PY \+K…U}8}|$-V8XFHƿ,v_St+AsD.T/ck~Laf$^V_#ϽVT_&%2|,Ȕi7c\*;,<΁9kI b~_}D}| _dQ e<)e䱲6T:XjzQDq"pٹQfN5fjG(eA>Ug!"U+4\̳X(K h: _k/ 1>>Rti)\"hj"V^o1V^S/Et\#aJ4/S+i_Ϋ>>Lqҙ+_H6P/(R]r*ʋFJfQX_ )/6[ _1XT8Nn,R4SPT_K|܀|޿ZBf3&(1ԋ@TSiX@m%V,cF %EA񕢣?962*|& NXR^U%Wh,F>Wiz",,vn"&qj`e?\0e.%'gHBF*˳JKE%hvE~uQ_YWZLk襠9a\ Pv ׏ ҿeO :_mp"&. gy[m9yV\ةYp( CEjv:*\R޿e _,~/J,v^ @[zJbȒ8כ"CeIiyceosQ*K_be#u#EP(SJ9`SE+[EicXIn6{zAla޿i%i|/{u(\B/vbyVFJY|LkYeW.K懽ZBQy(aoU?YW TA.VVaR nƎVotŞ,rWK;"nTi\be55.FY1$8UemT2tQɗ_V]~ e6pDt^SʕyRJܪcsL)wʗR.׮+iEQʪbvnWW.5Wr@<)sm{P&ЊB3`)zsKW5n1Hby%ݸ_4ENW\/^\ʥn1a^']QlҼ㼅JR\&>dEy~5\bz̈Pv1"kn50Suj"8nsx;8x%Yf/Dϯ>_ _X)Z,͙h]ҍ턙؆µ(EUIMtNUWӌ %%7Dݪ͕+]|bef|6~v=`n4>C9E-wt5yA:No@ܤ\GəYflA_ɡWO6KV E3 :r=n! KVmNc.5e??oJ 7ͯ.:Pzle֢-hzHJf2rk /WVXqa些Zo\thNjE+_zTD{ed]V2X,%b)ݴ~ v{6.Mjr*Q󫏪W\y,j17b\MX96A: t58.z^"O F[Ndrq,%9E{VMhe,3K[W6懣OWUTDI\\z14c#D-Vڽc~v˔WO6@Uï)a5crtIb23VMrElQtk\Ksn/ē}k_K,2m1s]Syk9*}tM]tc/#2Ksyn%#M,%U1ݤhңWOW;t G)zn-b\[ʲJg%et_)_Qns:Y}'B"QrU%蠛IO t+._"ϯ_ _=nWĐ*+ѪbZE\D+;ƟD+͈{=Z=cuoM yF1hynk&+h"ů+&L7-ƲRzׅV^,nr-E?Qi_2D_\Z5\y"F4=/vt3b8E_ʴrkR/+#)fL+=OKF+/WUYVN$Q4^J9GXeNn 2WO׫fm"*($Dsa RN=(_/xPI[E4K6E_6HnO yXWD1ϯ>_(bړo_?yEmUhXPs#^D1ϯ>m.׏R=_USH̥rϯ>m*W^QmU`Pr/sWU믟]Ub߉ an*r'_W^vHyȲs/5!T"K"-f(;įkx~5#52Ie_qa~S󫏪Oh7Yb(/5?4)S3לּQtU8CV~?^$_?7QL/y[(ʿC!=+?lUe`WW__ 2Ub\mSW#O/rë^byQ,ϛkt+ C9"e6}Mb=Z=sugyq\ZQLEttW__{5NǮ/ϯm._rڰ\b˔_Tns zks)_%[y~ZzGل\M)LU袘Ť)WO3_AxM_^aՒ\m&fʟ+)+~zK(e:SDϯ>m.C_r AB1+ty~Qns Y#-=X*Q󫏪_=ʔ83ebg"_zzKF/3J*M=(_Zʫ\zK 6׀ F#t?3vVCp^"SLi%N</$_3et?^돥Iur2QqG(Eϵ2\ϓ8|.%w0^kp}lȯvs{bd2 8Xt*Dzݴɡkf}"(f$2(fyvZEan=*^7NW5s"x*ҜYIzt(5Z$q\.nMNk|'#q٬V+{br,jUP^IuZ`\6Ci@1I-VRn"u~?efY[,'g&?>>n|7y1[lŚtHד {Ǵa8W5Ks*'C$ x<. $d@d$xmWNpy<^KrƶtM %r>D,SIp@=iߡcJo<|$S-^Vr&tɹ;a^落i@ JU/7Wqj=])֜_0L ׫v9@#q ^Z_A??idJ1uj%*l5+mx*7W_ׯӠȯ<̯/U_e+=b~ \&uTP"e]CDh߻nN'a0녚8c8M_Ҕ/lN6G~}rAuL~F~$_4`E\OW%Ht#F{xԊ/ia,P)xo`P@&TXz! |F.& 3@n-'<>_B FV9towi4/ b'0SޤYn`Emv]Esq܄3+uf]__< 7| K1SbMz уoFYR΅_F߂mk/jzl / ^\R蓮jվ1aIZ"\gNٴA7F"۰yz9ѣ\Zj0š/ACy`I]˯~UkA5(RQ%JSy$$/U#/\_Kʜ '9j_"G?@Ҝ Q05KrW:u~=3ׯԠ__cƢ(J֨!m_݊~$GM\d -I!/ȍ(9ExX7˅4|)_~fL0z%Ub}*~Mk\n7lgQ]6 E l<#f={S{R_G$_/j\!/%)p"=s>4?J-/&c R *VշUǓfxmfOhVP^I_W8K͕ǀmE=0?>>'~E'b~\jyQr|y>E#oPGN?PݨGQ.!-&Fdj߳-Qx>|Q+9^<¿v:;>]q ^Tr yi FEa?p֍z_-nY1FpZ_MRP8h/X` l{D#~z<FuFC6HFV/}x5]"ozeP/D 9W ^*>xy~QTNb~)s!w6'Я }Vm\_LTLG6h@sA[ĐZas2}LۛA#1CT-x9v( =2-޺]˺Mo=(_&"Zq~/tHP7 ğJ#0^J~DKl)9XxA71Bo(rǰTmP,[K.<:塼P\eTveO4c\H;$ro.jtAHjlue:X><.w Bj{{;c mJ G  j ^3_ ]l_[v?JQiMA6=k㙞RA&ؓ+}Ҿ?/_,ϯJ /ׂ%BˁW7blXb@L/Vl(믌_pNΒGNAZ,P5xWc&룬+- -o|B='.~0gӯ|Z^<+9d!F͕H_I2>Yn3T9Φcl Ƴ>0>cg7E0bZ#] V%my?Fs%tхbW*)S뙑 K̆/:#\rIb{D?"[Ǿ*MK41T/}f(꣪-!,fƴy^FNPr2[lN's99]?Ot^L`az$Bԣ ,5tm[Go7~7 ˨˘>Ζ6_#l$Qm(m+ft1.L =zD -qQDvƵ]13&s~6#k:2_Mq(WsW<%y  7MD30bg6'lƺ-=F|~$WW(ʣJ/-g\l1%<*Gt2A̿*s@9q1GUmѽul| H5U~evKs/l"mk[S)~% X#JbJP~Lt懚ogk Q-+EYbRW};-Ŝ2Amb&k-ce\._xU<" g=][Hj']̹ljmtr%r>O;xJ"F썮Ha>v: )T%|~fdh f=A NN_1 J-u~}СBh6nx>oW'ްR-']?'K/}jB<+=Jn1Vb¯x&k yrԣo^L]Ҙ/0d7dUE!Y7W Mǥ63J ǀǰ,€vW FNMxqvA51vQؖ+ړ]HˤWOU/E@db')޸1PQǃj HD3r=~]N$]Ltm""6J?S19DK_PBD*(#hY[O53RA8M߮}"/AntO.&rJ_=Nԇ'm7 @B(F1\znKo;#]~=a؄0`sIWOeqlJ%ʎc^FW*6JZR\M0_ /Q:l5> J2"K\*b_}&De(C#O[p{ZGQGvVS*$WJS~-hZnV }9YH4J&vzϑϵ<ɂېb_}2+$aH_\&2q^M3xk GGFY3aWVX,VpKE1֛ӏ It1~yebc:&˓d~orwxb%y~Q`RPf4`?v&owE0E+e+G_=_+"WbzLi'Ϧ8%^cu9.b&N9*S%BY-(V*Q5һd8Xޫv0 (.6p|Ϟ2,c0?/K<\ bGW4Bd=ƕ|A+Y3wī*_K-KWO%ͥJ+U"ݤ;n#1!"En[nuWl/|<>̲}E~Y_}/72(+,⏢"Źc"IW+"C9vX.*~%xwǝ)ݩ|:ҝd=~tRT,DrN3Op8< EN#v|g2 ,"fVsM2+/Ɩ ]GwI9C\G5JIJo};aI_}#+0>qYd~1*d`4Q/$$"߷tͣ(G}DOu$%?^$yKOY_tE."% ~n$7)6sBsćNoK8YF2.rچE>r:frB_UnALr[woֈu*,qc =춼wr֒>Z<$?Kt))~m* 7I$gh:+IRȷFo7͊hOt;˪~X-8Ptd|vUegNS\4 ^{W2yNUZ-% ØcScGro@4_gxJYp΁Ղ? ؟fMxO~7_}Vik&zI] 1*4{C*N<W|Ҹ$SAz9_ .CXl1-h$ }|DĻ]+]-ϯ>/h,*ZF+ArL)/=JVaE: hH }qJ)WWj2xɣbrqNch.2ͯ(}e51Rę4[qqo+TD1ϯ>/K!ߕ`Lߺ`f?U'WI-0U=z*m&6ZIV+󫧒  oD)S=TtA1ϯ>JFurs ZJT;9e7ۭ?^$/!DiWZ)x5]D/5-p4ʫ Yye+2asL}b_}Y/Dsf8{(I>^&b4Zy~_y/ǒF}*fQ~I9-OǞg5Ie0bC(?WO\q F,ypdvG|ܾ?9a?~⻑Glb.+oz|:dh:+Ig_S0e1qdOz&7#Y<:*J^e\߬xEB'x,%7"F$*4Vf$"#Vv;H T8/qJWS$-Jed?S}$)k ̌9ph(JqS!_#kXy;VIhK"nDy1Jwˋ񕾢u^i~x_Cx>7y p=Т;%+~x5n~@$#_K˚pXUWvH48PpŠÕ \$@E@M|#JZPkkY畆5_~nglVKE+J6z_+xe@0#ɓ3{낯ݒѠQ [ڈE!=Ud4+[(*=^SER#tp\xǹݎK/ABJ_:4V`FJcIqꞤU@:h-X&fvfd_i6 (FT㠉++{O=!-pqx7rec% \"_0.\JQ[,4~F'-%f.@sJv:C4c`wm$ @% ࢱX}E2i^dbiFnbD Yh=t\ԅvKAfBL륯hWk,1<2iͷ=8Qpsb?˯J 5M|R/jWT1qe_m!}*(D̟&\mIn #A#җ+Mp=+ \c.qwKg]"zfCt|O)H_2{((w 5}Y:uK<8Pw6a(`axorPRi7_$/_bJЈ:K; I+;Oڜ x)0%@4gd,WϵhXx!UPKT@pBiD7(ΓF6 GL ƅzO_:4竍t_)3Axw{j HMOHi6] <#t:}ߢ!Bp\Hqb6Ӿ>yE7T.1]\_^hJ/RRk5ApnYB/ԯJ(IF|pQh;]/ _nfg?o⽞J8\kwU#B-e@1 ޴pJP/~~;=*q|_E"FԬbt# . V PHG%-`N];/=XB'Η8m]K"6k$zt>КNpIW@@Uջ{S/~[XUo E1 %{7 @m얝'K[\P C4nP.?9q:tt_07iyB/R.\? %M~u.{飹( >Tȱ*z|KkXqvav^Jk#;n$evi`.+79Iwt4ǟIpKUщYW")DVIAk/Ӹb9ivюȔ6:YYUBy1Ě]xo0\M*ЁoPKiP_o"դ;_N%-sp%xL4p7XL%a'ƻZޭ 13po/&} œ,vT%Љi 16tk(Mrzb&\E&n%œVwydU;q/?||]Ve\KgV NuBwdh҆Z(-ˡRI}[WwJ8\wRftnۿ|br22=4$|xgIp}A[$uhaT8ICұe;E &0{$\-;}5w,Q e4oטsr>_N/qL!ӻݺ%!e4zRn/$QF%0w\DNb3yoJ8\kL0Р `\Kn˷K~\Q8QT&_vMW|_Okv#}.bp#Ny3Io+ &>`ٳ˛h/b_%N/8MNsd*Xݺ9֗N }tdMJ u_>5Ph.co(ЉqWE5 ].nf "KnD|#8<ӠW5 /pLBp6˺E$җ+M. 3tCޫv:M/_,* _'OJfH/M8\: :bd1hw༛`-Z,'@q_vȑ>׼vsMwKdW _cלCIdGnp]Nl@WB)=$/f?hXz2a0\_ŧQgpŴ|ݖof,M&^9vT&q;,7Љ| ;FZր-h7qdésgx\n[4yۇrm ʓ^v:Fy[/bᐮHyաKrfe7a7/=3nۍQFnID`⩍:vS]=hG$1ַP4bnvT:q5 NhF-nY-$n&n.Fs3n_^ʝ8\k9O(S_^e7]V}L2Z 1 %ĸxfŠ0܀󹠉gWC/q4Fau&c:vth.nt5߯'Ӹ{"\Yk7ڍv _ 1r~)LAn vsLgnW__N/8 ?iڢn^yFJuB^}LZVz6vAݰXⷅ_EO. ߾.¥Rv^)T657Zn |U!_JaK^nʓtؒ,ӵ|F@3F4v'k˲XW䫏VWўnEi҈E,n7@n 1;sN%_?7qk!0;'-=ny?/\F&;6Z[MͰr/vĉ|7+hO Kb̲k1kmگ˝B'W Uu-p<@i#um4nmn/{I//Cg\zY"tkn^b|w 8_pw_X?nw%n<-Ɏ+fv܄FxγF met^eٍVvr"F|&^_eN/y[p9,M%eYhR-,p_/b_N/ubn%h)b54bީv ejNWry|a_eau 4bxϲᑦhe o/ ڊZĉ篐PMYlhķQ5nIEL']fz-b7/q,V_%NmL\ JN&Fn-WhYv#/_N떼n1kbI˻w&]n,-) _[z*qp_w9ݒ>[DVA5]nHndnTչ yMPRzJzc4#[ ?+ͶDV8I~6oH3ѕŸњ,It}"5,VUzj1t3vYvC.9*tp_O? J%wn Pnotm4n7_HehDW$}Q<1rW:ikIAgF[r-VU$zװ+MB1i&;Fۍ?X"bsSUz N^\K\mӳnw\n,_hʝ8\ 2O^||Fti1 f7_.b2'W_B^ei1Ox,JD职I:/- ,WXb/7 8_rɫ62JhxOME*qp_/q"y!D6IkCFcKX~"/  {ƹikeYI /fG$Aq?N矿ռyГ6#fwZX/b_%N./I2Ǔҽĉy+x '=iCX?/I>E5>ݒͿ1Grlw/}Cɪ*wp_O<i( %\.<ž P's?0߃}Qb_%Ng)_qLK%AwH:Cb_N眿n9yœҡ|1_._Y&<b|7%A7!gWN^'v?0CON?O`+ PX2 EYU& -E*qp_|Bye,֤bMjx<+u^fpu~e>u gCkKdW7_^e17YL/>U~ 3{,~*tp_v-_W@ߵ>YXU=I~_Gc\%dBaR/Љ/=m@h&_4_N._S+se[ϑiV+eW+/xqs=hMW/q\` _ȠŔ/b_NǞɋ6f1OĄ2/-bW z~^޽uX/ZW<r Y=Y*q|=_G)3]dKȄ2}YUzi_n?{nJ8\׃_x GX]t_4_`puu;=m?- vI_"J$_^cV޽r5xߌ guڶUr3/G|eYЉb8}}:f fISɩӝ};]֝$SfpUv%wl6G2suJ!"yx& xѻ1}9Ѹ}z̤;-&r0t*\Ng:ގR"w6w-SbTJ$ LfK%#I{r6wf}C(u}zO/dW8#LH^zmPl5VND꧕1nH^^{>b<3g}3t4.[N 劙L&Wmc1#ic1#~Ŗp8a)g⼴}"ܼbIޓC2syY]GSĩ<\qci^k?<zʫ/ |I7^ԧL'YI> 'N֥ ?2'y{I` .>Y_. x Ο;e@v.W?dY@v\x_&zt9g/̅`&x .]ԅEBߜ9wgΜ¹'ʵJpY&YNڇLb >b>jZڄ~p`;{yΝ}|ݧOӺN>ǏX,sy3gggsR{uY=g^-E> s\:ϓwE+^Pp8K8}uUC2G>xY,NRx\D\& _NٳG1s?n/^wz<OFww7s> ?/EZ.+N })JWӓDU#D39) ?˾{|$EXf܂yOGAu.X{1P&T^/_| ,e sq5ub Yv\NiV z j9=-H߁}-}h>~'31L+EpNn]Dj^,D$#9%{!;Acǣ[ S>SY,,q%ٳܛ9Q,>LP?>MdZX)[H,{W89ypuELL JJ=} -is{N]Û'_8Wr#uO{cu|B6ppt%Ȝasv;8s,:tDO.R\?| .=7%nI;061wr5ӫDDE%!99(+)E]]NOO:}X ={ztrzy Xb-B=y* (8' 󆭭+vrCjj>1^R@u,r1{Y;;x1)!l|na wüU7lpQ Z 3/`W~ɪX\cOn%=(Ra}lc9"$i?B,$' )6qHLLFNv+jP N9M&[ Kx,I^}o18_i:m2ڞ'.!9~ e {v;x ` g 88;0КO|`!E?@7-t]{s GMG-wƑ@s5ع+nڍ; !8ы~ۏ+5&jC ŗ 0\%: ]Aƥ Ý1[r;\Һ#]Kַ[;ޑ{DG#6"1`; t9FV.>ɳxJt(%m(A Mh͟^֍'prOR+A 0r 88v7gPl g${!<NI1hƞ^eRv-['lf;a]Xo] љhVɓEZY8;}@eKlR^ǪMgU˘bWbcV:d`܃sO8шxfr"bH$c"4lA7ԻO]8JQ\T&iJ]щN:z8Oσxa#zɓrt% 7P|?ZZWl+hpK06x碢G0:D>O_Ow)}Ɇ;ݡ-6oi vmh6d36zb'Xy`?VY{5,]giźՅ^:ua5`a1"kƂ]K` d!hy"s++ ]چs5pBhD&|‘x(D]XB*SE? (FKQ4:Һ6e"!ɥۇ*x([MDQC=CΠ8S` OPkpnGX ݣ;VۉicU ܢa퓃Qpa lSr#ۻOiG񾽴a;ykݻٻkEK+6aXsVXo%V>Xj.!(n4c ,L`9] 0 Xѓ ׄ*8&mLyac)`Kv#&Tx!'}f,XrZ6R2󑔞RatSV4¾f$!(>JُЬFxĖ-v?|RW3'7(>0j`,gX8F 6k* m2o *B8GbvlsF&Cw`bB`plDbv2wu2Y-ؼ}f/ߊMąxf BKF9o NJ>HcHYIXL__.t5g-x'CsA0A3kKAz;"; [hw:61pKIHO(AP` G4V4A߇DʠKN@Q44#8pMGPw46>)p G@J5|Qld5L2AcێA3A' Z?Zo괭X랇M>X 8DfD؅d=*=ԋڃ]̌iH?q\Lh|rlܰvۅ/N\'ޞ5K\1:<_ޔtuQJ\D^eq%kUB} Ͼ{1h2RسwLn&%`g58bc$l 4$77wC8&$$!.)i.*EbFq9{p:{v mGދh;zΔ*#&uOH\|TH-~1 /*C;8g91N1E=0 ^9 #JOcs6Un#Wyb{ St6ه`{6X;c2FGbmM5Bl1fwŻKwc}$f:Fa6_o ޙXdvd}^]L6CE'ys #e 5d MR/gpZ{F+vqޞ0GDZEvf{Ji)#`0D'ϸ˟օq V&c\bb,iX읇~y[ !( B tZl gKl~;6n"ˋi]Jk`-7u9^z{&f؍VX+ ӌ@9_Y;(,RluKAفsFWØT1Rj. h..;Eӂŕmt쓻q+<­neW{)ML!]:y 0.r-_]~! -A9AD"hִ~6IhǮcTFbg)6;F?)$,c 2dY-Jfzm8q̤T(QfvJz-&?F]@qZ#Gq`Zh:9X$β:zFZD^C4͕k_-w=~x~w˓xE QW|  &[7z͑31txZ?fv ܃ZzVL>f.\oo{/~˻݊ɳmlo G0 2|сn.s6ok@嗢[Gw >S S,E-v`}_/+f+Kr9cSZڰ9CȵcVÊ+8 i FxTA+]'OR-}e_ `mIZ-F A=6r^pH?a $V+ҷ %pFIH1ǠP2QIOHa/ЂuXF9ʪPf}:3'hN~/Y({ѕҐw1Z6>&kmmv 5LH&q4~yݟ1fRs+b6w=b7#ug8ҬÐ0m<_-뷙fL ,4VQL ?3ກV[߿>29b"WXז0cc-xũ2t ƌOfH`npMFpK?^'Y} < U]t"2Ra]lo̰jګrx'#n#<*a Oc]]]kDXYYaɒ%Xt) Ύ :vՆ帠L/9 &2ݔ8ug8y uG]vlMZxwǩƽd,]`\w4BY;06xE>q?.Tzg ck s͑gN윹 _i&aْ)-&M,c!w=ޏo[&s9瀴MAX8c޻1f$q갷n8ػTF! ݝlS(>:Q y/ tG#1,*keZ36E7ckVck|Fd-"dT\:bSX{bQ;N5j>s<x3O>X oVu0f]Fi/JM>KFv37?ڌxTh+QZ@k*3}lB:V&:|"p?姰dE_A40IAsPhbd"ʐ ǽL@Hh$74 5ehkC[aZѽ9nƈbǖpl[凢ZHjEm`  (H&w|o)'(FxۭB:%{QVWS͝fHBɺ2%>_`%J#38}˸G|WLZj9NͱM nAeb1ޢOʦ!(BM\o3o6Lwy6}GiSÊ Infx '-4Xtl;MՃ㽒\@YE)ޟ5'B04V[ )V?YZL6z!èI*G1)"tZp"aY9E*v{rѕ]"T;`(˭@c5p>)v`uu-'y1t!~Li#)Aꖊ2Gƈ};I'`;+F}#ǔ%7ф Rc7&M Oki'K.w$J1[u)g5ÝWm^Lݕ !XZ9, 34HHLCX Y8ÃvƬd|cƌ?L5մBM_sRP/Tۃ"tmCq;::(q>ĤX7o&Νɓø╗C`]z5BpDDTQphF}-;t  2 ̭6ݨM)G^x6Ё&+AcmE]cjr#5G%N0UFd!݇6\Z3.~YLFo2n@4KG.҂#qNۉJ0.EtE|$P'Ny@ b_`.t!8CܪNUQs;n{ g&p22"5@^"2İ_ţO>o9)h@kS ғr|ԳL`a9gz Q[IQ OM+ KBk6ax兡4C I74O$iY۳rUVWz?I 9V :CSTV2 {؍„d3A>|-Mh?̦L">̛9EpL{~Rڃ 5)矅 ۇptŔVt%W jxKE[]=jsȑ#A3KjI.T+**h~́X2g fio7;p0 1x3xa7o-<-̝3 o2F0G>rD&_]HCf^!&yҤ`8|H !vg\jسYqYȤHFCU3-<=̒sH3ݱ>0fΚ+3]Sc+JH?X_<<Y\f\*!JN/afE 5(/gE\J>Z^+ W1?d=[`*QHfIR3]Qh(_t{b-~_ľC`2(4FZr WEn^+0 YJ9OrWOd0m<`&'M c8&2L$Jf12D^s^}ML1ؼi-\;6`ެI8@P93w7G,^4Qa$qsTlh֛xDZeoQ~lf7G #^'EBy65hIHΡeid٪ښq+O =u. lbu8BCE O)B\{ßxaؘ=&SV\[R?bjjev@n;&D碔'%>>̧䣺 5 ![qn_YJzr%e7oL2e1Q2>yTi,Ñ )[ZN2~,5GKyrƚc*Ƹ#]ٻܗkIc6wbkD;#0SQST!112GLLҐ iQ&OœO?'S&`Xd>VXX+%(no+V\XQ^N6(BQ^6ҒQP#_yQ-%c*wa?cz<$찢( Ij$'͈'ϭ# ܏ -ѕh61\mc[Ml">ށoy U";n7¢bCbfqJd+9$, cJ oh6q\yU-^yY3٤{ՑwCQRXt^e躙V1ۤUuh+!섲26tUt4`A>`e'fRfG^rvUS1q6Ipʾ=; Cp73@*DD$!j銔fv׿)xDEꑪzL./XByа(˩faYJ*Ct?% WǾں& =S,*u]qC-横1li9vw`F-l0$fԭ]g !1mc;;#yߌo7zS7$3aO}f,5wY16@޶ fPH-Y u6;if/,gp]"2hŤ}0b G~*Xֿ6<&Y&1mM]s{܍\ m;*'eQ>$`.V`eZl-"Yt~c.;;?JobK#ʫÏc̼׌NH?Ǹjňt}T^e)y+K]b|t \[V>9]\Oey3J?M+;jLϣ_h*CK`*v 7<xv)錮StaNr' G^ۍ'g"rɸʧzY2I8l02p 5Zj<]J]M@[;ʘAKJKcO=_2l(˴e&+f^w2?-7o}BR5Sh9d8Dtg>VT|1Y,:m۰q+/Q:#4[J R~A}?l,)ƍos5s[qŒYC-o 7=5=V$*`2qe QOvQ\ xIO{_r)sBSڱ‹A^ j6Rigvr{tiԇP M_3HZ0HӞ<ހL,YZ1ǎw`' TP@ڙY쓸_[oĘocX`.mZ0eX)*0'^ &ZL휜쐡ی[ `#6m`]t#aAx걇Ak~GWaO~{t\ȚItٜXum&Kn$pV_{-ZXj{"@_xSz ,q6xR;y 3`Er괙(5RH{W'rr d;:: D_`͂ ?kV'yZ":8-E@jYsOmeDfboE1=bZ# l e0MQ! VpJu dѼ 04yr3n?Ĭ%%!=3tlձ$+KLjX>͂Y}$KX󸤊TcAm'fv`\̰5 viW^ QL)MfP/pUc? cPCeJLJ3'FBC pn%ˑU Tj偛n w\6 eۑpֻ0j{xf7r )P*U jOWF [ww.>g,,wd+7nPK%Y3%r59d3h3U>g~ Zya˂`evkSA&:,( 1$ON vbo=ǴSXVӃK4cI/(gi$A)4Y%)ғ̤QU[w4ܕ uOC1q$[X=<>v)eaniMXF2r f ߖrƸHO:~XO MYj8tT T+MMIB_8~xcMe4z\YKV{Sg1koa(Y^]ܢoƜxv e6b*3`MFd((k_Th`x <3ǨsS6).N1hHΆ;$BjP%E55u_\ &j,epI@RM9S+՚D)^!#*;ٻ MhUCFSȫ$ t `e >PV)ܷVgGA02.rJM_+z!xg 6%rTO:0X4FM * p!㡭T(tȊg? Y)ajV¬i\L&}ǀ[ndձl֭߈In<9xVoqU1`%)m&_M?{5~~\cnszcԁ@xmP|&=J2q1}z͌H(cAbupmv3a {,͔"$+r؋U>!j0V36XBńK*Jvm;tŽ٣STVwfsr\R@:иJ++[~aYYsbgP;xKӉ|^e^ړO<vlft Duou}6l wOc47od-sR ʘy55mso} ۶m3c͜-7IS1vd(lvEYU=%4.#xmVdVJe\|XAQ*4J&?bU*b(DÝ6oƄAmb;'r$LuF [R%e$H* HWFΛ_l=); ·rȆMrbJD̛͑ldm>H4*SV ;66Jr0>jҗϫS*ʚFdpܪ\W)drat>lMXr\,mXo|`ȡ=>.G=dա|MIW_n &gΚ߱,]PT "91qc:3tCEhe+VaݶpGX\wq ޛ>[6K&Bt\O 6q( YS{̝qXq,gs𢏌IkfPl%8șQeg`cƕS\b@Y, $jxH,9pᙕJfyXО5Y,B28qz [vG`N d$2oD$AƄ% ?H7@JJ1EBfrTJPD{lp1med}@Ueekyuy<-^D|5פI /Ykgxyq6E,5[F5Jk[0,66ʼ| 􅿟׿b8~"&\)~w1f$,XXFu0Iwij/6aɚuʱl&uf;ģ b8jTP@&`LA6M̃|]h /XEXP:ƙ>Z&ZM!|k,|J`nE!# > Vlx-Qǰ؋ `>X\\:956s$ۃo4R3i PajΜCy93f\J6y1f)7H^s-3c2*DSR !5xLK5vv0Y{dK1J$tP=K@s_e%u cyDHJWK_';wks(O$((^fYLx͌ضVi?rXl`/pv( Q8EdJCت~)(L*I)f.pqNeDWS2nvğ=öD<̞)Kx/ch`/.~!Z+:H-g9G.6Gq|=i|D#N8eHY-@xV {ui%L8/uB2C- l pcՈliBhY7pL]R@H^0u7cMvIYxe"=U*5n m;mVg3f@o~2ꜫXw+nIc&ՆO$%;q#UQIOO7#]F|-nsk eìKB챃W^M+1ُɶEI4ge"`r,Ԉ6-]X91T\ol o"s9+5M [-R'cK<k^ŝGM!fjp/]U|'ϸ Ga޺xd^al0 a.ң Jcb2u0\(s?wR6>mIf]5,g٫JRbJdkJa-ukzRf^)XqI {)܌%IGj!tnsg 1:+|,}X/W7/cI*:"9U#vK. le{?due!.R壍 5O{ќn`)@)1ο0*FTȣ7'\]Z!1k\s1KpNRARƫ1YJND|&s[0Vi1`&Q~'x}+j0סtK8ҍ}>)GV[ڵ>=EscƶTyv0݁$9-x9r!dUXe֑"mrYH?j$7ΌL@'LS vV禍DV^k #1e"Nsa}}L CgCU L7\K17k~n&ȣOpuqF'Kq$('EW^\*8˕ENl0iwD"5.ZI#=RQ|0[ЦҲ 8qܣK($աE[*b^+%N9ͻ_tàwҩ-pu2Ϭ<ONڱƷKݪܹYX~rm!N.[mܗ^]sU7ߛfh#+WKM}=ͣ\&9nǞ#Ͼpf`{JLolULW} ?O{ְ9S \.mxw8?ǜ MP8)Lf1Trr[YkzǍ_lE8;ntsZJ2zJ"P H3ffi%沈 %GLd kn?|d9U30:#boRC+ccm!ܩ{`"Lk}U]];l /Hy~(#6tpe{ 5!pL5j2|rQVq=X|4 IH]d tUM.Y3,4Z[u_}P8Up^|c,^~cQĞz)ZT|\4~dwMQlb#٩;^yo;kS( D+w8e,ԆVXG{ a%η#H$.*QWJ潖U` W^k%Ȃ:i4uR[2oƃO2bBUUC |v d f(ni"5u3O#x}X+q=ƽ7 ^yTRJtȠ:z|_XI 2;60c,ES,?V<{1}\7F,9ti(E{)L燽`f[|}Xr#O-ZF~¬W<[qIR&Z) :يdQT8PYǞzISߟmā:ЄI\)yҝ?|pr2@% IR.O3KR%3zuO)6$)`DIȊlwzIkbÏfq0U-DMUVQr:*a"ZEџvssdvGlg{v{\$11aϵ'ՖsxFsU(c2Wi9-KԶa&bFBfҏⰽ<"J"1+_'-RK?fWmC|k<&nӝ'uO9N.<=6[*f-SWοQ*@^nQH~<"9$8"L_}@Љ4l΢kEa˂@))2%<**؂$0vg7(Α.Ľ?)"Rn靔P@6K+kV,̴bAZ@XXNu۷ۛKYH04FuE.&8"B.CNB5K%l"{ؓ߻`C ~\әVqu|z3P{z()Ն~)͔yw.c۩>{2jL8q,]rDdr^{ijЊ3o8YjzЋ=!R]6Ɗ)skLI>Z.Y9O 8]%rAಞgL}r_֍!lt$Tv/]k6lVp/; nZ.HI<k&!Mr>|D*Ȭ='{FfV谳&1,MQ_,pyHITg/2YJD:):YU`R%X w(n>Zi{Mr~cmJ=̦u IVLZX2M@&ɭ;" $J{MIGЏAz{Y/TP"Suak&c)**8Jq,W,U+WP|[(/@7S2? K7yʙ-k)|^[f#AȅyURTʣj""}\pyLXzr(S=9>%v|s r>! 8drIs1lr2ಧJBܗ| ̋41n X˝P Nj̜=n3Ͻ_Z\j&)ʂ))P\٧4Q~O9;65'L5#50e&^djT?Ayҵ1k"Sn͌-S~aHbV8Iڮs=f۹CTe)V&)`x-D"q^^bBMYխ|@qb\č d](. 5]ճ3Hkzb]}Lg" @ψ^? ؼm;ۛV$CjλlŦpZHP:frضn6/]`~Sd[n):Irtba_oenml\*wZ~%# ),T֦¯ G\h ;y7<O8j weqE6Zi>nBC5_=qf>?~&WIl{ <`PexIƸGJ,ܥˍf9K:Z\?f\O65G-zT,%@jE[P%plzKQ䜫!} 8l>s٬|`ZPs="G0g`غeP@`cS"*E uo΅6L{vsiF1T3HI5iBB)IV|EX_ۛ66MQ)|ZΟbJFr1oE.5UJ:CVǓ #:77`D ߬3EM5ȼ*ٱۀKThڟJN*׾ ~_1XH+EI*U-Ah!dvu4+i5Y"w5b.ŒG TR*6$\E7_)$*BSe1-*WvMuIY.ɶ{]''?/>.p弇,lSk#*~KTG:`g0ynRmx( } -9 &W,]EWX6n\@dE 2P"Ó8=VTO8Q:P* U]R|umܶ K1_?5(=!רQU8y6-6CS,YEERk򍓙47GU\^i[Y"/Zgj鰗_Ì {7Q;E (j>/ZϤP]mQ*`Ɏ!2nůe\LEQ$~Lx1KV[e"݊W̥xK{TܥlQ@: X"p/`Z9griSΟCeCXCr99r5#x~ē1׳2 A. ?Dž"x\ ;Gtfbl²ib 5-X7ޙ{X9{9c?# fmZY#sDFyx<)$Qn#zЪe;gcpL"!d* x-្%Q%A$= ko"UP̵{7@"744Ouꋖ~2}ֿXyRzE;l^›+20̀slɫOF־=m}I9,z?+7P$r f|EYס`dpnwBĄx0v`]ݚmCNfjp9Kb8%7_HNN1#BnΕ 'r S8t%eyZJ2.b46TrjT_VS3Lq'W/qpJT=aV>QÍWuMmkeTHger{.ڷk%UQS'{Iu4g7g\lr&-K.fgT@"Yn4qe#3ŕ 3ƒ=9oW!$y 9O{@둻(\~-"\(Qm7-"1PZʞ]CGqHp\8މӣr* >dkXO@&ICc'j|f߅Da O~s(Baj;F2k7X86/~E hlɯǍ.JLMCay`@UĻo{c'cXI-0+`U5ojB^nQVNⲇ{X$^ [ d^iy W~?>RB YiB4(XRj]՞'JVHKn2RKl:’57#=+4K).L{b^H.ɝ|L=t39©Crhqh3`ٸVq6<1?B;)G22%v =ad7pخ |v۠3 .qj'{ y B:4ʮ2ɔWdIag̡'s bBVlVSZc}-*d+ŒE!ZB;M,zRO1׼L_]g@Ի))1lT &ͽLS(^쾲b+ՒGj9fٛty%[OJyKvcDP(@t PGa"5^$'}rox0F%>ld0YmbT L|߻ S OkspX< AJ5-xUl>VOmf='pVĭn>hNok%T!LߏQOF08h-kp\T ##D,'hD{h%.69i7I$=KCS/*B덷)7hklNY-vj*6_f]Few)ޒkMVLN̿:`r#ɳ`(c3Fk @vpQQKaћ+8ėkwK@ ~Z9=)2'u`XWB ;>l/vD8 ƾ9mє \!)6eb0iɕaiՌꩯR{v+_Y+W|c#xCuq6fZT3njKzI`:ŕ-^ w { /D4ul \3 [2T~J&dtq]ȋHT&PnQ-kb.)j.*iۖϒ<拂 VzX:! YDyoYA aÀV3c _Xܲf+B ͚^.r̼`Y\rmw6/e\]dY,HWĭcp %phĉ%V\,X3!#vǕFtIe2z_Ęe-GOpQN2ۙtX} a^mt*]*)QJI-JJKQ% ,Z!y \8{'ORWMue$39&!e= .~Pf<E5щ\ !+qAtTS՜+Cj9$,\ʺQ^B@fsCoƋ|=y,#QʭqD?a]<n1[ 5.J(mQ|>tYJW]1X"Qċq֞.}.VEChS8Mb`/o;pd)tmcqYb9Y;Y>%".*sʅ4KnSl( Y: W ?Ww%J͆y6AbZ.~Zye5 ?}&O; ȡH!?NIa6ѿup 1H ~Bx"|$ (^FD#$ yT,-'8k(O|m cͿiRuj̞("S9+ƾ6oQ/[nՑjS@_3)Z(c bELp/KKQ|%'ToO*|Egb\Y:HYL@',RU1:T"R(ܢ~QoSY8WZ},`_mL #]U?Pwpn3G;P' WWOEi)ȶ2MޝlۣX JFxZI쯴I`&!hPd'L". `OF2[٘0NҡYkp>&*  O{/~Fn,S%8ӝY-@}9 \Hξ7XL6zxHMh zkfi&K3.ilbm_)撥œJV eiU[%zN=xO[Mwi憚>4LNK_wuC e4dE?n&wf`gH*jI.<,mZ`VV+?sMe"OYiިmi?P2L 2WQmc65#CԔdeSB-}2$BHM9SDfMbp3/OC2/%ߴqܨ' ؚ#$5ӵa/ۚSZ"t{8N>Fڭ%5-dj͢{\&;vigq9nNz̀AŒVÈm8 ϲrO]"(:9iAZ hZ~5aClڐ{(#@`4B`"K4X#}/RIG4KmP=kLe,ʹP;n,9VT!{ŌkA-.CR͠6{oP:/- 2-"OqݽqEȌ+'ߥ1Gͽ7w\{寘@պmIKasI%gLňḑeurXϝN(˝.46s0K]3L" k%+}']9T""W'k]@e5P`V6)@ʊ{y3DX(gؒ)%n ~Ifqsa9Wky^GcىQsFykJiFPuXC9d#) !Lt$3P,+)i< 5#M=pݚ5j*A$_cj>ep[Ô_0s52 @=;m. g&B73=ƑZhq0$ AXKK .n W&>1ca\\4nF' CS|`<5?2]C8ԑ\{xrLh9kPN>fMqXhѹ;Km\@" ;ʲfBz] &m]p͝YYĨjoI(8-7(tbPH&RC1,@K*-G,Y8we&^B;%:BEo$"㋜~i$Mb>e,5J>|e`_aH%S/XbM(vhp^`KVK[34KtG úT\a#3^ "i#(fЬc9.@MR L 8/8-iJ`jUQ\} 5cy(|"W/K RMKCe"ё±錻Db+)V3ɾ+(>+1f9.p0;Dn=q$s1ZfT-*'-'/K,Δoeie.;q&Ljak{2^PԪ&`i9oQ =-|n2Y>Es%աEsDDL|\FCI$ KܝTj%S%wGE#p+.uV&%W.JCFzz , \]} 11~GWqYпLLn&g=J;^oJ^Y¯RT6G<+a$fNdKv%1X[®E`-+eO !gQ &R $šR84er&8eLYJeʫ~EKEgNXtmr0^T&ZB4\4Y0e&pi,.}\Կ>`W?y/`}L*ɚiIPQ[.wCV \%"6&S{^E''VIEl#awܤJNұGG&C`ҞK@euD{(!+Y,ڑr"MAKUYsT+Fdԉ-Z:eVtFmbOMm*,œYT[T(@pYvJYn@5}2eY)8C ڢVJP+r@__O<4';3CnY&-ꠌqJ)[X$#>EH'(VR'ףʂ( S|loYPVQEs%Ũ{&BQR Y, Z*X͕_hR|&NC?T Q(p-zю \`&e~&46${֭dVSc tE=ttqҊ'ib5~TT;?JaY#&d$h09v(v_Sk2=%L?7`].4®K@럹OsdAQJj+AK(2UdG5^WG}o ?}ځ~aEi譮nrו/b-}^C*Kѡy'@W*dAt*^Mz*sɖC5>j"e꺎qhA"k[~,{StեL6'" $?Z*dhl%,j+7!I $PI& Y% kM=FCʁj\=Fo)k[Ie2lӁ<lj";ˡc9>=2?O{3:ir5L 4)E4I-@%ZgGP.XkTd},8 jYjWYbO|_ߟTb@S[5?_c-֬rZA#FrjS>& iEL i(K,E4,'U,듀^cا+TO(+%%@٥VP2LX!{Nן4.Ϻ,B_tOQ 엷05 N;G)F% RS}P*K|%k,TSX/X<ڕX,ZӘnJNMvNC4eՁǿ`W0?5_b+ 8|IENDB`PK!Fgf,word/media/image4.emf}M+I^MuuMW~p1XfR+ma=k .x bx腖qC^ ;0 0x4xPb %G?ݧSqO:72'ND^u:?d3cm{v::N:h ot:^ދrΧہ:n+' n_Cjc&?E Ώ:?꼋{~_v~ v.WYo{|_Kw~6Q~` ʽ]nw7_|ś7o>OH>& {sSoC{w3'~S#ӧx}gM??}N 4g[쯶~uOO_~ko˧ϩշvk~ĺI{I3O?5B~o:~u֍~1p#spݨ$Ws+Ut]Q:C]s _5]Wv uEc_ Q/TW4麢3g+Pu99?<Zud:f᭴rX,ZifE2q./ӇrxZiRr,et?, E!Υ컑5]O[oNoy};Y?<RhHۄp *%L g\HMqpˡp8x)2T>tb1Ke5LH4`rTvfN Oٖ`G蠐`4GS—vz+Á) I; hB/uJ*—T/P¹"xKaœP_/) ^0O_znhzԽ9-DZoB9gn2f.$PځqFƧ!W5I_oV&7T .z'~s6PuV`l.DWc4#9pP$l, n_aLd|` q;Q*th5lF'`X^c fmz2 _Rz <I{ctX3d!+(5 pMfaa}N_>/`EFm#]N&c2E"E-8bp!9mQ&rxMM4 L EwF&5$} M-W뽫( gY1ژݢ #,M<gz]ŧ}يf̢o22E mv@_8pxD #:Z T0g!9n1"?!|2Wa/nTϽGcL_'q1?KOOt؛)Y 5kwgNi fd{ iV HTߗO #q12iLq1PrKP~ȳxk2¸Ab|Ը;.es= 󎳈=oÍlf)0AP̵E,b$ tO/Fakclyd >1em~saYy_,RBlߣœo7#5>]$F*CP_|jb7_e80̦1c1O!NSd FC(!"љZ節BÌhp9{2CD ^mўVK5%B,|C{7JKȀ/Gw (./. 2l&ۀa4V+Ɨ"$V!CAȺ9t=2dS&ivo]l/ 5KB-)^F"8:SL&'Uq!{Ddn69PS4."|V/ݓodEk$}~H 4=gtjk "*8d$cq́0J_Ek_KB&%v5em^e|87fzr4(d)}E߃p^\8o-a,i?&Pզ…oٳ`NK7xA(.Ìe5Z$q^ x\7VO 4aoΆEinb`Ck6eP泄Ɓ C<ﹴY3Lckn )_\~GYk&%,Ia >V _ Uaؙvl/~މ dar`8}ZQsҥNW>﹖i eaw2fKgKlוr}^=32؎(O?zx >ĥGI"=>FM.jo+/91U=ooNl>7-"CT 4(c+l/V 1eKlx^ݔpUHl2uKvj :K9Ñ 2WQ|?9kK4_\K@ PfM372r IMlxE@dχidM%]|ِ[P.s͓^ $NTo 0G-> Dήñ{,㦽 ;X 8 b*4_Q%18`{;ۍl! Ah[ly-> W_UVp)"Ks8Qrde64_e}4-w!q(3|Y.xgpk‹_Nϱ૒Ew/[ ^-Q`g|/v/B&3joe/cϕث ?]f >yO S '/, Kj|1B1.03|EH;)xD#oR_mx+,xw۾ ҷng [y->k㯜f:+sŧY"%6_.Klլ>0%"[_Gwfp>H_GDno~lbCli+e:R,-> ׊FuB/Ϻ,X.=`l8 YR>N}`JD>(/_mF(s6{٣&|go4H;)ru⧔&m^jd Sx-_hJN1R2ZS"q:/a<%9#C3ͫx/df[|d5LbdaO/{Ynv6`"[|/)/éKdfަ5VCŧAU_/P\1ER/(skgа-> r—˖pk4ffZd24_<_E>y9y?*.^{ 3ڐzidĆ],y'3l>2¿e[|/rc؎6%.#f|hܦQR*bcaKP=(|5l}>l9 nf-jpp1dH_+ʝ/)Y.ŋmWB7NVb͌U 2RdS"qF\>X@} ){eer if JBGlu08{cCw3Ũ}=/2SlK&_ەBFSV09&d!b m}/////#Y|ݐ6 ]i8_h fKa Kp[`|]U8W='JB (sn9/_AF( #X85[<;Vb3g;MKl>lx _'ȍ+NSfK"PXt}<ЂҚL &7/-}nI2/,tKl|W# %̀_+U}/)YpEX|zgE.݁H];_) Nrw]{Hdaj/,; 8^\_Aqer(<[ְ2]i^;XYވa/,k;3FVA:ڲmV$kjK`_R*ԇpa~1t2ޥ 8YmE"y&01tgPnpC>b cownf|I}Q= l]ݐS_M㏜%[UĖkk$aB zEٞZ&/)  sƸg1]˴KoqHתY|7@'0 T|9I3BM( zEC%EKW@GK0.s,JAe}`JD" ̆ )ICT2K/)Dt7T4s6KVQ+q,dApVVc 9wmhջopլ޵Dx+KU 9~_]?ogJ+J+J+J+J+J+;o{|wjˇMA50[Kukb_F~f~yתTd[)Y_^(zضJQ/xMG=#] YBRCxw3'[w>5]7OO?S^*iO_=4g[쯶v՗OSݫo[S`+I{ US#CJUgcw17m][ֵum][ֵuԵR(?w8G34u`7`վʵbwj=lq׺LiK!}Fۗ%,;FgK,w>ož9ɿVd޾fTe0p^_uUɵ B.m׃`9o苋[ 5 kkAUf}gRF n* ?,>;p뚑26b>|`zУ7} >3[ ˁ0u}]slAb4Eע[fb毲V3szmòNCxS2Er< R@imMʺt\`|r!jG"!k0pf5{샥 Hm9 Bp1p] hbME _yE7~ :XndbDD{|f4Osדs;ypTc/o>.q6@03Q{iڻm2@CCf}+E}o(Ł]HTj)ŋ@F KFcj),3C4 QHS"qXjwo[bp8j[ S"qi%FŎ6uue) AD.n%HxA!klX \D7n^&j_,46PkHJN_ v vzݐtK_0z`O_Ko9,_]p/Aa4U_q ##)'/PuxoPcP!tM J_y_H!pȅ4\ b &i-r(0^ #_R/Y}`JD"3s?."B(%ZO_ _&^ڙh_/"Ȇ6%*c k|)_N2+K7T,!pHR0'.vFuoNqV[PNC 3I9?v`xiU_R6+ _ 槞(:ߜ+/`EFm#]N&c2E"E-8bp!9mQ&rxMM4 L EwF&5$} M-W뽫( gY1ژݢ #,M<gz]ŧ}يf̢o22E mv@_8pxD #:Z T0g!9n1"?!|2Wa/nTϽGcL_'q1?KOOt؛)Y 5kwgNi fd{ iV HTߗO #q12iLq1PrKP~ȳxk2¸Ab|Ը;.es= 󎳈=oÍlf)0AP̵E,b$ tO/Fakclyd >1em~saYy_,RBlߣœo7#5>]$F*CP_|jb7_e80̦1c1O!NSd FC(!"љZ節BÌhp9{2CD ^mўVK5%B,|C{7JKȀ/Gw (./. 2l&ۀa4V+Ɨ"$V!CAȺ9t=2dS&ivo]l/ 5KB-)^F"8:SL&'Uq!{Ddn69PS4."|V/ݓodEk$}~H 4=gtjk "*8d$cq́0J_Ek_KB&%v5em^e|87fzr4(d)}E߃p^\8o-a,i?&Pզ…oٳ`NK7xA(.Ìe5Z$q^ x\7VO 4aoΆEinb`Ck6eP泄Ɓ C<ﹴY3Lckn )_\~GYk&%,Ia >V _ Uaؙvl/~މ dar`8}ZQsҥNW>﹖i eaw2fKgKlוr}^=32؎(O?zx >ĥGI"=>FM.jo+/91U=ooNl>7-"CT 4(c+l/V 1eKlx^ݔpUHl2uKvj :K9Ñ 2WQ|?9kK4_\K@ PfM372r IMlxE@dχidM%]|ِ[P.s͓^ $NTo 0G-> Dήñ{,㦽 ;X 8 b*4_Q%18`{;ۍl! Ah[ly-> W_UVp)"Ks8Qrde64_e}4-w!q(3|Y.xgpk‹_Nϱ૒Ew/[ ^-Q`g|/v/B&3joe/cϕث ?]f >yO S '/, Kj|1B1.03|EH;)xD#oR_mx+,xw۾ ҷng [y->k㯜f:+sŧY"%6_.Klլ>0%"[_Gwfp>H_GDno~lbCli+e:R,-> ׊FuB/Ϻ,X.=`l8 YR>N}`JD>(/_mF(s6{٣&|go4H;)ru⧔&m^jd Sx-_hJN1R2ZS"q:/a<%9#C3ͫx/df[|d5LbdaO/{Ynv6`"[|/)/éKdfަ5VCŧAU_/P\1ER/(skgа-> r—˖pk4ffZd24_<_E>y9y?*.^{ 3ڐzidĆ],y'3l>2¿e[|/rc؎6%.#f|hܦQR*bcaKP=(|5l}>l9 nf-jpp1dH_+ʝ/)Y.ŋmWB7NVb͌U 2RdS"qF\>X@} ){eer if JBGlu08{cCw3Ũ}=/2SlK&_ەBFSV09&d!b m}/////#Y|ݐ6 ]i8_h fKa Kp[`|]U8W='JB (sn9/_AF( #X85[<;Vb3g;MKl>lx _'ȍ+NSfK"PXt}<ЂҚL &7/-}nI2/,tKl|W# %̀_+U}/)YpEX|zgE.݁H];_) Nrw]{Hdaj/,; 8^\_Aqer(<[ְ2]i^;XYވa/,k;3FVA:ڲmV$kjK`_R*ԇpa~1t2ޥ 8YmE"y&01tgPnpC>b cownf|I}Q= l]ݐS_M㏜%[UĖkk$aB zEٞZ&/)  sƸg1]˴KoqHתY|7@'0 T|9I3BM( zEC%EKW@GK0.s,JAe}`JD" ̆ )ICT2K/)Dt7T4s6KVQ+q,dApVVc 9wmhջopլ޵Dx+KU 9~_]?ogJ+J+J+J+J+J+畏:7ow:[3k| ~PK!edword/media/image5.emf}=$Iv^i# k[ԭul7@bՠdC9EE`(k:)A\z*b "!CH ""`-E-^Dȟ٩|::+/{O..."ȟ?'޿xr?{X?佋/.;w\ ߟ\?k*œPů ?5R|r\cO]yQ/9 ѿ~?O?}ɟw'sτtH&=3a密84ֈmn>\ _ze_tXXUO?txxxx'zy^W({4REaA+}XoվBI]C}rD*h=Wr|s>?kZqԭP+w=ŗ^+W^+heG SWh_W#z]| y_z~y_aT>W+hoG+h WAG_/PVKSV/WR^ܩѻ{t23wS^F^ygJv2]+Db~gG"%ϖL2$L2$L2$L2$L2$L2$L2$oN*KOH]ׂ,6qKT'YJkq %Hr5_. 2_[߈gr7Ir&c<&c{bl .!gz#)jj?{iЏX./Cޭya ' vKAՁMWbuHݞ& (Ox,$Z5%C"!!i B[5HF$` 2$0vpDxjZR]dgTِCMuVͳ[ːxFSu@8f"S-S BYE IJ; CA` B}2>$JY 'wV QG~𘹸e}49/_2)@0նLf ~,=Iy fxC`@GɌ ` ?s.kX VO rW{>(o7vRأ%+BjQ(.ma c1_j\OsmɚYU Rfϓ>֡+;qr]`l`YϾB4b-`ȼ'S~¼Р1$v_{彥QUplT%`-CxхctqGFMΒ-m>{tv(37j}Z^4E(."QffpTA Nd=u@,$~M& D5/psɛa}]QEDB"T5Rr:8G$,?< pgp2!c[G`  -+` Jw"nVsYA4~p0dÃ1J[,qQȳ!}f1x /fy  /)RzC,=VkJ u`ug .RqTv[2Te-n$ã^asj+ nS$ Q6P2<5nUp'!0K#[ jx> A5:jo)h$Ai+N#Jyy9c2e0F);n,:H!$arP[mm ؼMf8y4PXM4.Vę_U|s~ŗ4[5V̑ly oU8)5,k[;!RZ.RoQ8 ދ"X~0蛵>++wzÍB#PS;șyQkg##fXx @l8K5{-0~O2D>9&-?Ց4ey@h roRH *ݭ $[ ʮ4 jX~2yQ 6ƕc[Ja—$~x/+. X56ygkQ<V,MȲwxQ63A co Y@McRIC˥e4/~ޱ4021Y2, Qw,[G}Z`C|-:d$F.cۣD ʷ|̒0l\XGJviDDqަʷ͖OsC !ӸW6(Y  #sC&a ɢA@:ad9yȍ*^EiydN3xPp^q~ x/^#~P$Q d0ՄOf~KkV nqoteFn)idZr@LѾݳ뚦Ty1T)& 2z'[]vc5dd.쁋Kfi: ,A1N^ x{X^up,  i\:x8C_!,a+ ?L<$ *k\bYH Wtw5K}3#K,lϹa%v0)ULáJkyRZ6*2aacӅp|VX)jR ؿAY6~s2L:ȑ",lv=|#?d%h/LyfpB175\]y]~cgufmI QEzХBF_gsK=вL\W)KKY~pΦ_Af-.j!XtW,]~1Z4\dYg[!L*,уamFrE`-Dh&*d .*A"QOCX.X"LcńaW˪F^  1b N+%ji=(0\C3Fg yXMV}J!FaH&Yg!, L~ x!E1xJq3|T'dazu>CYGHєr)< 'DLA{ HBB妑%Y #AfčEqA;;bXd-{5X:n~+9Bd=ZqraF=軴L[Z ~PYOƘ s%EU*?~o$.:<=6-rYæI Fv5H("c-/?^VH%"1D[bVIm JBu%|\ aՅ\["VdXG0Ay^}qW͉m(FTu=6RbY{mYwC,ulX2[鮳]1Op!M1EԳ$ڋmKl [EV@-K DC q6h£p^ 6M[8 q * +=xުIABHJL"^ N,O֖uTBΩn!lJ4Y~mgG أNgxwx)/ oxhi_ڰ'䦁 l4܊8AE³ ;vpy8B YK {PK <& 2H 2{(] })ML>JXqŒR6,xE(e!8 2F=x'|d;,égku{t'\.\78qynt5&Mx׬&%_%/gdJԠ.XEW0Th-6<}?NA RG|UXf9<:Dy+V )zV abv*HY)j9+ku]['Q"^3CX8qY0P—gXuȱ?+{lq HhAgWh7khP@c!F_$ |e ؤ"Omyl( ~"N:H\Z; e(i ^A(+HiFHilD 1#ɽԡc:/LbbGN-#aIřSǾFs`V {Mmj*} xG`Wf ˩_.QP z:>8h,=Q_cm3G&fAN-{W$ 1[_xn1.)Edfsbnb9;mk텺K_!ugi?2<2WVi\ V@tPwNpCOw,1Pu-?졌xV2W˅dKYCLlc` z"y 2;4-&_w*<$1l9## 8 ݰ$K,m>v6eZ{τ &Kb˄|nqyj>/2T~o 磔(IIT?[VRc>(Ҥ_\Sd^0ѱOX/>$cC,1IjfjU猘We8 SVY3c ^*_MB#+R}{}Py]emڶSne "i npıN!&{+=[7uN$Nɮ׼mӟ AKb ?$I%JܒմrHx TH}Keoc8#'lHȴY{Ϳ28%s`l+'Yiܫ]SqSGwd鰇Dwx.-i7!P|H+B<<[sf7zu%푛{,J#g/t;?%YZJ蝚O i-K; R.*#vųȮ%O\:T0?^+؃;bKI]y*>Y{: yߩ|^T` XTJ<|*LxUN %U3k;rɠBLqs|iKo9{e 2@jt9PvL"VK,q`gGЏsa^ϱVҥ,^,qg.h IAr;ILH}g_FZl 1ݯ51x2HbCdʯÙiM54G8Yߗ"Mv1^#[qwm!q?.IO,A<)C~X#p>ۮ3!/d !Hx@"2Gl챫%-ك*kVԿ0fM${LdOj-A 8 s c %K%^z,u"h `.H| 2d1@^ҍ!^g4(!v-l B 1pS`Sc,7V,p?1@vTVu8`bkb!S䝑)Zx[m'ˁ A .Dck̀_Fwt|?6PO tCXv"ˑ_CpJcWS[sdÃlG;vSiX/X9LR iΛm'$Kփ7CC#/>a"2#=zԱ5)ãeda^$I>C@{lu.CyˤnGxNtKx .GEZ*q˜97HkM\`50p=9}LICn$&yo+VCŰuMAFL) &8Pd׭WZmEYҠt;`ќq*>K-8ցu!A=[t(4g2d5ʸ7&8zmOR_cP9xg~3M+=U@KaD$N˲d$>x 3ܗ=^-Ä r)2E_ψV Lm+ \P=9|)m~`: '!tEQͷKMP@Bo*^V89LzL뀠[,Fj.C^TP/eqBO^#luiB͏Oo4)eN߃ Xv<0 JC:Q9&/yc0ߺ,sʰ\xAi䏰G?2 l`#M ^5^eHPYtb.v7Le`K(6Ҹ΄`un5K}#"uEȬy 6]M:puGč lEq\Ĝ30 0Dh`3s 0` aKiPG,ԣ{2"BS Cu'x7M3aG+|g;qwV*BdI&dI&dI&dI&dI&dI&dI&dI&dI&dI&d{~~ޅ?NP7O߯u~S_꿏.M<c<ʟ?'Cy?eC?= Ϛ;'_jXFFԬ/OFp'/HE_e_tX־K?T?TOm~xnE?Xqh¨/:ЧުM';Q"҇ԡb_}EOz9R9?W}uCtH]vB;z_A/Fwc}>WP6OU?V]_>BvWP ]A?V}+]c(\ˎsw'~aWAc]]u_:Xs |_A;_ؗ?C?w/|ޗ/GňgNyP_ _yH^te-_7pŌ_ϣyH_/<7WD(?B>{/FGP|Tdʏ/1}!8S> * }9CXG/WjաB=}z?@V*OY_1F.MAT+AދjeG.%^ɧ(OW]|6_YqjI&dI&dI&dI&dI&dI&dI&Iը"KOH]ׂ,6qKT'YJkq %Hr5_Op,KȜn%xz@5Yb3!Mݱ2Й:nXG $Jw ^\?SH$$9QHtn-&O"kH&HWq?!& ]H|$H2Ŵ8OpX $6h \6 kuQr`!dSf;zC6-du([y!q٭́ AFA @Kq>H x,>p.8$PTTPPTЩ{ouwُ[Ϻ^oߺU]_mw5px7>;_a!cBg7>9$vn;e4Q{e~CO b3$ lv805 0v[APt :G!aFlͱ#sk|0PN|l^̂X}ܾ!` RkRI ݭ|S{3CZ{ 4J Ӗhj䁆KNx itx~ۇCQƄDOa}m`EXK0GWC}n7:N!FQoںBk.ǐ[ct}'k"O߅ە *N jX6njtwvSz&g]KdHhZA*&fj8N(yDKtoPo^ Fe!$vH{s L$&Tp [x~ImBۻi(k̰M` \|`l(.,Hiy-V )dJ|?14@1*a<4˜d9G:"hcV]7bv' L$g|*Ab%o1㰱l=r8kjp|ɝx,'|K}ܯ_d Jo:iC%gv+%T?%jZaF!A,qWr&C{i#n)1 coT.KT@H_6$t~aVqKA="AH%LHv0"q\ JY_-sj<j?%NI ZS0E,R0o!j*vx/Z $a?O@1[zNQGxIq1$0"c!cmlLc-8dBA@ݥ+ -YQ+}&.Ǯ&`ۈ4= )N)N@^.=c;^NG@,襋Lpk[o 2É Iݒt8:{߮?.cRiľjXMc=I۵=dpFZe~oa8 HZAf1u1l|R;鼱CC` 0٠hX#]c`dXK̊šA) m{#/pk!d #8DG}%fL``'HQ)GAg6 (.gك٤ci?h-)r0(BeO[2껙 QW`o=d @ 9%2ba:8rNEF~1{LE@`V9pEHA 3 ,i5f8s!,y^P)ϡZs,Zkͱ\+gw[<d3Z0ci)s?!/5qY:3k4cx}V{ FK{45xOt_bªW49kZ|JrSps7vbҔ) Q)"fXjfpTn'4 H1 ɯjj˸GagEeL;O)=7f%9wȿEDBS]91E D#I۸]͊5B x#11A"pop\3aKMu߹PN]9J- }.Ab@0< JŅ:Έ=R 'F` $D l~޼|yFK1d2$U( ?uw¨_XCؐi$s(,BAK,gpo y@%t ?5~=%џB"0{#\sT禱Q`PT?6UЌ-Ⱀ=R Q15' w̟$CLߟ$ cX[0bdX11u=[$wT{6:tAr- %$< 꺂R]ʬ$¹`O#CSWόuabM0ܨ g!e 0l7}]{<~t!6'g)9h( -c00?ad~>%A"Z]L۷f~k`XM~o&k)CV2I@ =K˪qIvs}x0lL\9@Rʟ$sq$aۭ괵cݛg]3ыE=TZB`V&zK3cL6;j3_<^o:D`^7z%NV.z h\aYW+0v>Z\EL阇MD ¨L8նߛ3WI˪ms0qU#%ڇh_֘daJɐW`O!a2>nJb=UgX'51Itsirbخͬ[Kq/K*NgL5o {\TAa 8cž-x.7BaC(%~&߬p}l3VZf_F|l9JCWϔ01H &(' GX KDƈ#Rm|,1r!'(G٠q=g$8W!.%$_jN!K'c؁Amq3cDHm>QAv,Y[>@BvE)6)$ md鼷s}B ,a#g R52`"GG#`͗23xX]3trs5Mq厖eNoQpg{҇6uY0:+g5-#f}>@!Bd>ޫE'rWIjsƗ;e>sƪm0q[Rr1)6uYf[G9h*8V)R:EƸ ߋSYkXqOD&痬^Q,tݪ/ܵÜٖ3P7Ei/pvѲ8VG_mzzim MBVب,s 9|K$޸3v5ܻ&^tv$|T TD;^,%CZBC"ˇ.,ܼ< xWiD5ۗ/(> ųRg3CZ:5%,]9k8TԹڶ*"_i{Qs&jޥڌ;Q#F on,~g嚀c_mNm ijw v]A& ïFKmu\Mw&T8B!Dݑw];:}Z v%L²#hgwu(in[îɥ-}F R9Aڳҹ. t+6}ɔLLP?3Mjv0r}.X,W~xz Aڣol_5D@'Xj/2iǻG FZa^}K$0z|2k\iH!* ؖ;B$VC62Dٍ)}3^}ŋ G9(ՁVm+G0W!H3쨩 ;#(HpM| @WRipKb+ӻA`#,t3dX̢E^W'̳w7{ŒS]ufi:,aML}..`. Q#]D̝mDx))pvhb#y燵]v8Ħ@l j,,-L}k[HoLk )$~8y7]C 0.N|""I3km+s\"Y _% $g!'-&m}"{g鹊\(^:gYQCPS4z_ƙC_HKA!;"BVa{dbRn!T($PT)b2yI0!?hJ_/LHPniݖ4CzK`mJ,Q0= iJ *:I&n,t7BrGzyCȣOO{9NP$\%pն|g`=hYEv!<i8V%0jOBgӨ&C F0UTKJI-[ f_۵1;R~=5(WڢVé4E(T]+-Iul2F+s/GIMI/]$Jy䇨 $ n/dH! t}e.JEEچM>.,? '0ə/K`Y%H ⢂yȝ"Q !KI,Q SHh#fmg:@@bV*f=80RCƅ~!0+:`J4Q@B'd  S~@ c,gV(Whi;ybYGѕ:L# =y% Y(QPvKYHz[yX\))>G$Da>ac(߼׃ˢ׳|[[?Va@G8؃ԥ%s6~pYLALܢtFC0L'.Xphz]>ux{'nLpc:3ɩ(}yH(4a3ӏ )*E$fN kLJLzW#,]2k)ʑ!.UZ8Y9Q$(XGlPc jkK_a2dYXdxٖ(A%R4yT眂`?uɑB!71 Eܳ$>cKZe,wUTh-OA6}ZNC =R`*TGXe#QWc[,8cXu| [ ebN,űJqWz^YoTU&yq gXTdRgxM Puh۟- {kAЊAz0 !7x@#AM:/A*rCls Eߊ yɔ |"vI@uCm=)tJ障0_8^2H|4g,>c͝$2is0_\ $@6z8,eq樣ds.=L=&w0Yje,|wMVix)4Ga3(Ȧ{YlvEA3)'l>4+WOD1[c或Ş1ԡ(u-l~˵u1Un#N/EA VIyI`,<ĭd)KA&p]u J:'6@+sz}nx/PBuPuTnk2mx.GMkWhFdVN 0XRB14.m6Dy$$#=uLS87Ri¼)YͪbW; A :nyBُvc֩7#3[H+XY/$>LLdBE` bJlnAxdf.8AsO[i}Xn6gvAX(%ϳe­K/`t)^`c  |΁"QFҦI|7.+5n.wG7ћ"ݭ_"}hP<2a- qv1;rdBO<'װȂp7!qTpґ%- 4v5?M& 5v>}1%Ѭ\HIS|B KGpݚ8::ƪ쐠~o0OTa<搰KDՐ1w.әDXG Ϊ> ~`=6 p{D (d:_]d?WG[~H99ЎH{|)FF*lVq?oom;Xu`(txO>z,aE7R1r<>d 3,#uo#G"Kb>2vK k蘈EwXs+x3 )4uxHjm(>X$S\:wI]ڢ:&LȬ|22֌4Ei`n>E4m0mi5٠~%*{SYpt`)£kzf?{ YCLm &#*BufHpzdϮD13=,<<^:{ mă??%a6:ig>1;!; 3`|@S-Zk>jF< c4Nn 1i!>{5Yժm]__>Qa.6m>ڍF iwq51V!3s;@l2'O5cSزCZ_ac~'K'U䙜{jlY2{䚎bq1"K,ݺO*6\cz8_m5v5}芯/G+B7jaFcfw1踿0)?=T?uOmz*ա`8|*LrU_  wk:d[1wfs|C馩7p\a/Æx:2v[cwv:]1I"tWϴ4n_z޺fZ+h>w[Jd؛2GA #܁<ʈ^3l+eD633kԳ%$?ٳn?}>ȃ(a8fv/_ʁ,D33\*[Y2{sÄ!A8FuuhCzKXmmc ib G"w]lp(@{q NȔÞi]3fgI}Y2 1uGKGw" 0̉+&й(@zju*kB>9pd\ 1 21pSfud3mqR,pB1@K;c U U+,m..+PX݂6e~6&-8M9$71T؁(q )_3nfO\aGx_ЅO !Dk˯9NU=]xHibr|N;wڎ=$fPaͦΚ<븭 _KpE#,1߶=#9\K;)-Dž{4.Z~Ej3ImL'ㅺb[n$%]{l|}9/u3z:!/wBlsNKG@3dh5IoLpxnOj%tw q˞.J/P|I $$v*-Y<aǏeB2E/?ψ6Lm; /~|5zNC t匘ۇo}W05L+a -~/QpI39!*(:-]u:䄾~o _4w9n_m 5(0,ya=\sw˅lpQf&GJos|á6lrmw[//'+οK;noWr ߺG~{η^|7:?svnW?~;??~7>;Lrߋܹ"Mϋ)>ilm|?M2͖n'.w>sy{s 2SJB}Y X\V e@I{vb]<[4K̼5Xi}ޗ>}Tfzn\%},WA}^y휆3Փqy/#}yo<ςp'vp췛q{.i~eQN,|ney_EE~7}F5_,~{佬_7\Vy}w޻r>s%{cbKaa`Sh?0o}&S}3g!$e$Ϝ; ʼǿu$/"?<=;lv>Da=ޘCt{<%Y^F:?uY_8'5>OjnӏwdllB=aI òGA&]0)͛Т2Q[l~C0׏tX@P m H;<âYI=Wj)*Zo M_ЀDTD"hc:E8,B//V3)ETBw )6VB܊BaeUBV4GPBMhI4PCe̯d)Ogd &!˥,YR4tT|U///6rhM#iy:V1HdJ✾,X8JMB{BPs( cASf=NY!?rnnP=Y'.4&|)Y:&E@B_4](윧/JUR cʘ*qtZ) ‹ q諫+*,eVeJUv+xs-u# Dq`MT^({^EhCꋆ@ĸ- ),qTNR$pQr>`ij"Ѩ,̒ի[|x,OQ(ئ*d1ET&WՆMs?l-# dČD\Pr>w8,K&_]T$cQw ^zT. !>1,,R2ȟNw*7H!n F(}ի ohTD.}rଣi NuT0CV,EZӄ1 տ>6ΫL)rۤÏbP*˂ JO|j@e -a^_OqZ8]9JLA|nn4†bKomU*)žBTes2dMOA?CǨPbvu4ɩLʦr7El'ӳG ^e d#Tj.,(eJEpu!)wKhJYl::v[Y)T_'RR,@h W$&Yq~eca82]W`(eJz G6%C/~8Xډnv<%F_+SUW%)YVe/| E\^oar@FWlô95T{^SfU~K'gW$_&Yw+䣃Jx.JYS)[2}NJ*(b+=1[c%xv3KO)NE]4]OdZULC6)W0 # 8R@&_hpfB),: +)%wJ*g:k7dE|<+N'M˵c5bl(,JY/gIQ(g6DĢqh˧8'TC <y,j S1qظ%Ǫ -t%;;>B]JU/X5QyV/[>]F.u}|9B劲]yU俨(\Fpa|,ԮǶ DԭjZ>]"-t:8dl+Nws ;0<x'Y4h@.Q^A#|!OLA_E |q7VA|ŚLӻ' g.r-@hVB?!`*/+.W(>+s,DE֙({)+||5OʸFG)򼜻aAwЬTYL+꿮]$7/k4Jqq}s...h ѸƇKRϣJzM~fȁ"^ڬرq l #4(tlYЄ:J٩:"K{[DT UM<'b >J'jb$Z, 1T}6c/f-e؊;&‰s)Q>GBH_e9 :S C?CsƎm!U&]|zWvoW~=']PZfӒ;QQ%t!T_j 5m$ GeSח?䙢3CPظ޳- ıeH{W^\ o(q,AyH 9[_{2aԪ\ +~%n S2fN= eP}sPazpV" Ȳ텭x1ZT]F?@L=&_տVyR,EeG^$Ɛ/>@݆II,lT0ɢ`@JfW"JQa\ӳDdJPZȶRx `.ohKV_[d Y&OI.~#,bSD\-JW?c~oY.д[We^o/.:0IRq+3rRʊBJ='Juq1wgs5_ksWW"&b0j a-2}ʻ?R*'pP6~9}`@jH/nË% Gl D"MK"X y ^'K ,T^y]t0N۸)q t&E6v ݃~Pʢc(ˈU`Y)l$Ơqh+#GW(M}0)r}Ċn8f);N,Y|l|1u Uj Lʢ=~-'kp.B!۷.<‘MKQmYJ1GQc&+^E)i_n*VRVDVS8DFĖ,edi=f*kSG(#SV_k%O\\\;ATZύ7TYWy(LFdζוEc+ yx/Rm^NeQuxʲ z'T)UU<6Zĕ7 KAk#sp f)ç߿*:KaT|QyIL_3lW!VXr-3?Z(xz9SMņp2AH q2KWZȽ)1BgAA MXFY; e4lFAH@V*=|-7E%QgIK*4ekj-W,MLmОb~䄟>'ZCڻnwASP:_27Z-F#kۊBàk]o4H-tyN*_NLݶdeTeo0gr čqv&UyXLqS$;#q`=3N8A>Nɚ%2l:f d1Zá:Dp[^~4)*VbеZWu ;`0R5 *laCDE{%qlȍ+dK=i^bS0fshP}M>.u8jM`hѢE-ZhѢEEnՏ_v>~O^|/[{s}WRᅭewxLW[_$A&gm|Y-4I4p7l7yI?}o^|.ylާaϼ#YNʲlR;^<-4si}ޗ>}VFg> ,&Cd/"gNC[TOOedDvy,Nx'+;}pY;M5B'4K|? (oI dI^l O9p?{\;:ar~Wu_\Cٯ~kۃϪJk1W; vvN}nhgYSbyoԉҼ7>+M<=yZ"yMޛ!;qIFN˝,'y;Gu(:w{8a1w}}yL-ZhѢE-ZhѢE-ZhaZmw*1mNOŁ/|>ϢfO'n4w @vֲ>? >H|>JcZTZX7ƯK- ~E3d!s嚠m{.[VTH|*EAQ>T}'at7{f8,o{/[Xi:fG>/B^wPea{^V|,_5ɯ .Jք$fp<~,|bŅٰA:i$#tguҀG/_,lMZ6+2f; 8E zCZ{N,#$K)Ћk"Oȓpp:LvD` %N?򊵠4䮤IG1U{p JCӝo60Eq! _PbS6\^_oϠEMe HS}1B{  pKwaU c`ij"Ѩ,̒ի[|x,OQl r͔d1ET&WՆMs?l-# dČD\Pr>ϖ'Y&%+Muq1[_H -zX:đ;yib*ȃB"e;*ctr3xv_SyKaByjnǛ<U6ôq4zCu|e*c!r+T"-VVSiBLl g  jUEÏbP*˂ JO|j@e ;&nzGUʉ\Vf2 ܸvwQF6[r~nRYO*ːy_Bpfrƃ/1*1ݧijx@e(Mr*S@*v0B(WhYH:, {:JGAg)8a.9\]9cCʠݒd!>Z)RDV@ F&Sx2׎g Ec} 1b+[-?"wC)SU8. ,4}26Nt[)YH0_%Bk4%˪eO-gF,)"38؇is>ֿpe:xp碔5A*SWkIqR/F۽Y0+/.XB]}l7㹤ԚD]E{Tⴻ*_^Q-(Cdd Œ6S©QGb%"K j7%p.ΫȰHӚELlScna2!LYFM{E +)>rde 6rW}$ϊ)eyϙ2|-'4V_ˆF͐5iyf"4'*ucMJP2x.D`C); }KSE$+6oP_Rqr!4̩VhI,?_LEjH_CU|͔=>TZm}0"=Ž#mōg6j~?*T"ʢr\_zWT*/{6 a{3JQT{(W̳[yt2z\]r@"HW"üs#tڥQ%REQ*gR%]lRWѷ<ל+tQ(G_EZuhB NylaHDڵ,ҢHꋃMFYʶlp7S\ѮC|Nle.4z)w8AUg}}mAǺ\\k={p&b)īo*:)R}E˩"}C=ʢK$\dB§hׯ_CYp`4x"˹ktW KŴ)En~#?FD/iq8|{h|ؘ|i+uf';EECRV2X'?$k:PJqAƇyXcy"&hSt")O5_"0+ qCk#=Q_bv~RH^Zl"8c y$Us:084h+Ye"Z(صGwX}*n lv'Г{n5n6-UBKPF q{4Z6u}C):3kKJ=ˋ: J[dw`x\/{w@_+Y+'-8v@S_YOK{j΍eCUp}U'%o ȊLAG,h-*`foe^%8zrQV3 Zք $+8V0J"_isؽp'*RE!}e*.Ƨdh 6ɹÕQi,Cb%)ݒ`̇oE߲p@`& k,w!U(:݇uV}2B@}5n bTjɲ* aQ2qhyk4EgH0e螇 ^m25V\4M 0Nj\:Y%ѻ8XGXh(Yat-w}/5|OVL>HqHP4ŪaN`QY)hg8bURXgKy.K_ܸ1$y#."l Q :%S`? R6{> = '@Y Gn%,K^؊I>: eT +qodcU*n'e"_\vENa "dO1mıJ,ʊ )A4d}%@E{*Y[e==h OD5l+p򆦽dH^M_Y Uk򔑔;K;)6ET٢)qS1Mkx}U½x.W1#',4sd^c|_~ {w&+K0WV8W(SN߮kpmV' -d/֒m>̍j,q`wxy!+v21ZM7ۤ9|+͂g\^sdQ\<3+Kqu-rn^o /3V0jr G[>)}RHi] \^6.{oo@YҐ>}/@$d9,aYO7eC/D v./K:n]kRvL`l&kh4Ofjcf:<)WSo_t= sjwn!)N nngPN2\^,G5n3yJ兜0//oYe1.(ab'٢d)eJ\H}W2OE[&Ls=9,2qRf*X {K1J֯f-R4>;ύYZb2|[2F%.We[E8{)vb%%G ; 2>9]i瞟s1Tl'sg))-5>+tVDhdyeuRFaTPdrSZh{&\k🼤BSƜre8,GNSֽp!D8F 0 Z`< G┾|W|)@J 2Ţ,b#>W42jN#:Ƒu2(RU_"7 \F,ĽZY-gOŕZ$FwL#a/O%GhJ̎l?5˃Zܠ3$)>`:uW6ߧQNY 6H-SԩS|r^h]5iv4.#^%sem468o(4 ʼqF#8-paԢ-L(d$*mK.QF]^x&PqJHmgRq7Lk3nn3d4IX"s6soVZHi ڨ^z8j3KHb)ϫj(]uePSh[(Y3J6DyQd>@Zܸr@Z%63i6ՇlR7si-ZhѢE-ZhQ_t:ß;'{ l%wWٿ]PK !   word/media/image8.pngPNG  IHDR65$sRGB pHYs.> IDAThCY tTyMYI$(AV"p՞TGED shRV"0⬓Oa3E ˢ0gB]w"͜ȶl|>-$n̤ⲆtE6BްC!Tk9 sp}6UUb(ķ)(,[[=IuJahGJ( ?6ņHMz^իY2.y?j݄[`__\†(pp{}ZML$,UbDNm@_Hֵ'4Ë:b0|׵q-FpoIMCS#x6ٚja@l,ZlyIVe`C5RBdUsiyzGiߐ`ZL!J:,llzCznJJ&t1?.I#t_!R<[Fe[gbLhW_`0cSaJbZ|F3II rv$Ǿ/6LcJ omZ(LUG;y7@-]ݠ.}>,R{K$i^]lޢ9Z4 xugFYYQwnت3L}AY+߇L <(IXT5ʼntvH= c57Bq4ʑWI(FoI?D}"L2>VghEvlNUʹovn>/gl`qG$t3B!Uٹ$wIKݿ?XZgW9y[ Sso_uU{ lAi\M ^jRqCI]u%P!3Oosn; ކ+cԋ5?nջ`|Fs6V,6n º¿3zf.\`0[7kktټgqGb,2+7*ٍ&!%jL٢SSh`ٗ~3~')Ōa?ڹs 7篇+p1s,Z?uPc%L%RXH=<pE|N8^xܨ^:/*{]Ͳ$zZ oFκ%G^5bs$:s7GiJks#= I( BqAէ4{0JQA{ݵ_k$niD֎ vh~_ywd\6֡fPROE9ؿVd)y<|!tv kaBS`DbksY*@;$/Pw~|^=Z_._qPbu#Dc4{;X"Xp9q5G XI~zZ*zEX@ΑO^ zEܔ 3܍8 MI^}uPI?!A&cxScyā=ctц1hsє|phz˹g'# FOx읜9^*b%߇KdFA}aέI#b֖%aXVI3ziSd~y:F:d=ֺPn y+ aj奴wJ3T} FIm307xO* $w+T5ZD%~QFK#t~hCa IVqtȯ %W T2=R|cF˧<} |Qi`Z~*|*!zFv9 eiZc3Kx:q+NgmBأ%IM,{j|J m-pz~۴}bqJp@ĕאcpJGSi=9jX^5Bj=/uk$+g_q]V@L$32ɬG0V?"I ~E- !Sa-z 9:$03- ^ /YbGWxu9rEJji q lgցlqu9fŠ)oYnQ*4K}8Ad35—,!ɚ5WtexkPפP|JmC 1̙ЍИcឹT(ښ.Fg.][;E`i 3_PyEXS!p> >sNxIYzU!5'պ9(3.Y,2wDb9cxh!DHSџiEQF>;.rber"2n}_ MTX`AvƀF1"|v|x)LD͒SDCYELrMqzq:f= HFT-q._4ak :/+UL-0 G('zi#?2ibƉ?}gh؎ҥ vWDekP (aOUJRC)! I ti͋8)@zHs 6U BF .2p%}s R ĪXDVk'ULf٣1:aHtƩN@> ?8 sO_<F,mɧSqcI bׇmwRGPwGEb><:W(myefoJiPK!b|>^word/settings.xml]`>1_yH#΀UEbuv[n|}ؒ~Avc#X|9%!uxx|+ ?>}z{w{F}/Or+\} Ony<^??<-f%^ կ1-?|5W^}y~{_ݽoď/oos^>>Nߠy yX_xz~x7O/~>~ۛ~?O}ޯ_=޾~ʽ_>noox;W~oa/oӯkO_f=:ݼH^xۛoєo#uw/+@V}G~?CѠo߼Ə7xi QoEOWOOM|nwݛw7U dooB;Dŧi_^˟^{{g}~RoG*FW?}xs?.^iC=޽}/Sfaqb /h+MßOnI>8)+;'ZdVqxn^)ȚcωIN>˟hAm8P5;юmMLuU Iɝ-~I9񜜓xN*c{vsjm|0"s'' }m6lh.G[*䎁Po!1y,AZ>X3זBrt,1̺\ƛ+~y`j)zt>!E)߭@`Vpys)ɫ"S--!)@&&bkkJ{I))U/%Bu>[PC3.z9idENUxknKG:@Qd=z |V9+~7Ŏ8i%xxhA*Bh[nbe%h;FAS\sN37RH~,~M n-Z)oA+m<c:yrGrI3 Isb/׽Wc/g櫤CTp1r}00#'.1{ӜnkRHyPos|> #ua\U#{wM#VnGB'? 39DńtuSXFd"oh ys㳳gd:_Y'тR6&Ѷ:e>>g=Mhϐk{^’؄ef%.kq₸}}NJh߮.ѶhBG= "v3ۄ$Z`~t%H-ͲT=G>ߦ»y`Y5#rVSϲ i)ff6|$4UVߪQÞ;;>n O )F; M '| \cbe`i|VP@5MxhG4;'+nÄ_W垬 砫$tp/A0iD_\^Jg<ݸIy#@{@NLkn½7c[J{J@S<'GnIܛaK)c; Gyby}2T-I\m<5%\|ܗs \XƱqY-Tq7'1rdp?yXĎaIx A5etޣ <lG+Yݭ\<ƓxMHs`)ۃ &f)9->r%79ļ}Ps?}\ ٘OB)[]:~ZSnGk胚^Xţ˱,\UQVxxpz\g/.Y=, k>E vXQ,F{;9vxW [F%(o-W7ܖYB#ni+Vi櫤y;x 5[Ǝ{[{#W"2]r̽@QZak^k }+g ’ s$M:oӺN銳mY K&YYB^hWLwWV1i+`~p2b\R$rxIr;M vZ:xOj;N%r&vMi[i=BgX?=tquqMB"ub_EXcګaOdXxd4RiOI^bwFI#wjR찋LNGtT9Q(hęmD:Y9|;kY ]@s vj@ͮwE1ߖU_iXxHv0χqK=MTTeU/w坳F[wԕv#ɭrQjr-:cxIއyZtĩ%1 9&HgsSDb}b)ܯ x?G9yƜ#kTVrM:Ph',`3Y iA*e2o eNw m9|XrϖyMg@?b 3@,V-]\^g2-ADv-qlP6$NOss b<D5㋉ O||9|<(epO#}\iA*?\cs @Gmg,e"ZmY͵,o*=k\~q#;4=^3dr%;D;OH]#jHY#59)< < }tL mQGgR!vSGh㜏Ď~DGBVt>ܸ Zڑ/@^D䂂ɏU۠9zyܕd8ßsgLe<1B߹Rm%q>Tv'N6z`o xT$_%!z犢bN Ǖ~2Jgb+'!ɯ}A*hSKJ~$(.ngyFrt#w K#Z`?g@APf9G3y#Hu~@D: I>k9Uom*X+[ >V Ͽ\N^, i8ǟWibLW9(G3q#,o[ں*t^>.Hk^ORnL&\K-NpO0HdpXtZuvY\3(i:ܫk2>,V1,zy\>,%qNDT<3Rb|N6,O 7Rb**AYG-H+r7rTVy\z]H֮xvT}|p ,uf 2 'Ve;rq?YI\SU`V?ev17A T"XEU[Ɂk "kDԞ'k=Vp;E&?.U *6K`=? 0D<ĪU^]dpO l{J.$RuOˈQd(dCkHnGVub;=E:%:Eˉ'j$k2śi[0 |94wcj'&n{B^yydRyuBvOBnB#~ }l㹆66}Xh#]By Öo訑+R:;j| o:bY{vEv(4#'1 GYvl7܎*N g AT߄فaIAD8쌑I<qZ;Sz;sr̝Н.FļଗK K@\L . gՅJkɮlB\Ye@WqeݴvqD6Z}1g2ŚQdt]qf<.c{ 3&B̝I!D5 e!CU7.G<I+u;6y[ "ېTjf"g,;o{vǂ}~]N rs@DFn9= ,vӝg*ZyfHQ C?Wx%t+%ze]}F)WbV]Յq 53Ta}"g(t=L 1F" '~G_jyk>r 2|۩nU| |5C 1]_e"طkل5AXYhu2[sk&<~Rxfy"YفteǺCrĹ/z@* NV(t5j!<wpNi|gL^K]xK'>,sTq%D~~ĸOӹ jLKl\Cb&4yZq]!>rD nm|Znuᒢ@xSwzW (5պ~BĚ#?kسN5 ֺS~|6%Qq&N[Ճy}rmeG> '\bU ,_Uw[E8\wlNje (DE%&do&kGjC"KdrSap`SṭgqdroU|Es܄A3?WG <OZuZHy5 /oL O-B *{} RD4cU<֤CK ߠsop 5x+A55\L ;P<;dq ݼR\򸦧]M<S5A.i8Qxc # "4,'y krtW`g *>Em-Q f㵂? 2ywE*OAaщkfS> վmkLD}3A&+ qDoB~gDib^x^9vv8'5LL?w0xfQ1q3X9yS Wd ;gɼrU)4~uWVR@NDx.+9 H{ ,g^دRtOcCZ 8'q>>;W^5M|u&||]<泈\j3~ſpʼn^_D_3HV9JK?UD,KPȥ*bz  l9amVTLmJ0O.ZNk-gQ**L!G1,\<Y Ѷ(,] yr%jQն!]:G9J2Ċ5[ 9 .;aY-q'5@iu2\l:מ^Lykn5I k*{&Ago˧X? 2YE>oѣ&r> 㑟 (&oA 8asP窉ZbZqךUkg.>z/"u.v&l<"2EJV\c? "*tyDb*r'AĩMx4d ~M9Bw NKmMi+&fH+$S"2{Oa7ou?Þ{@&Gj GADM%vZ-ws{AFLܟn6G ^?Bq@OL'AHGě&|֏*@GbLB=9z(v3OOK<^8MT''qMyBtQ#_!㭾A ^n-,G@WuLh;e7U@< r>bIAfV3SQRcF G}ΥIc mGϬA K}zA9JתDx yڝWTzq*< <җe~jg\$4L `2 2g4!Ǝ&ϴ!crrY5En]]|Pc+ϩ"Z1 nq9|Ybb 3G@x0T}v z2%^p-A*FJMxnOm6π\ƃzPE5@ĹwKHTyݼ kҹy}Ђ,??R]3x<Dd܌?21FQAGG"GO"tt>ڽ(㧣=f fDDcpY laC]SD}mu38S<6pK lq&+A/]ב]W1;ԽN)uM<'yؖ5#Ȼg)Zv??vt:}Bloa/H= Ab-ʓڲwxgڍ_ݵмv x@qL ֶؽ=-=['$q&9,^"$0&g:nL% q^]-q[0{@ 1ڂ=ZpJ׹*ӂn72GPϹRQWE{! bD5P-z%b-&uK ORy$)s Ҹs%Ә\wKA Td lvB g2th (;))ke]ܹl]gVF̯ [b4%b9-,N3>6Aqb4x_ي'+[mOw0"NmϵpbjQ;|2r dpuM;Rl C|^TfCP<\"@:@Dml+N̕og XBTǭăGڞ%EIQEd׶j#Nܹ *JxMx.HVh[țx&BT쀖yC|L`r`knQ3{,Zxutqjvy,KX@^N1k݉N MMw< D{j= иzި3ZOFۻ!)l ƫ;@=` ˰E n$ gp CBFԷi;D},SY3\Dƶߙ) [s3ڲt^}-ADܹŝ[! Eo+T^ĺ-=1eJ"syHrzp&$n [,$õh{b=I|Z\[XwZ4=vcyuߣ A)_-e&Y[ b|OY]$qmydr&\OYUjnӂL܄2={˻K$nTS#snc$g\X,D_B9lxp^éspOeGbQLzS{1Uhe'G"L^Ӌ NX=}Q# "*@D~|>DXFGa/Px5HWWeDѹ H"z v;4giEH' SngA:q,cy4 $ﳬNo辜EF D MxV{p ;LÚ{ʂcw2מ@ E|r ;lU$|81<:{ΉvbY g ŴMx.py^&X5HQC":؉M%D9Xkk4I S';wqrAD vqzX|׹F "&>C 9; bGsD׹j+iyRycr&ܳ=boiiR䵗 [#.A2[#C!)D2 ?9u1YbuR*j r4[c,q  Irt1D:ĊpȡMȱH>HW'yDLG=ƑDqd1 d Q>‰XQ r{ZlQ6çD>J F5׽x Hucυ$! ҹGfŝB(P E9p_h6ڊќ) 57J Ym= ͮ#J $1x DL݈\}3\FO<R}أ=鼒drʀ*t᪐BVP> ՎW͎ͦBgn*t{"Hb0Hv njFhO3Vi⩟301l\P)9U/x:H敶c84'.LṠcûCVh+? yT=4rHy ILD7<r2( xV22y4i.G""N 1ݞ89Rf| s榵F}]+ޱq>:7 w[Y\o£IF+@DV&\ܿ3m9Y {d3O)b8y egt8wzt[- |츥"j@jaz)­Qs i3Z` "sK*E(Ncܚi96'd-)N)E DgJRdS fN2'qm BAK=sY=q "Ձ_aA!Sd@D<~e?<&cMI{d%G :{0_jވ佟g {NA, q YU ,Ii%5n7n"t=wMq̪&p;&50yD !~Bidk>,No6_ܼ,3 ϝxF)<#D}n#@7@,֝;@%=D^wLEjٳK"m+:LVG%.U#E5= @x<0a(, }?Y0xv l?a~;4C91md556+= ]d;_*Y]xx y\UΧK}>}Nox~ۏw}dss]_>|r_{f=r,^skkZZz}->p~7_տ}綾Ewo\A?>pr<=ϧ3v八/|w\Wח7==\_ݞg^}s?~[Ho~~(ϵz~??OW|?O/0{Ssm ?\z}:_.LO_PK!{ս"lword/styles.xml][s8~?U?6eٓdg癒hԒTϯ?ɗD @ݍ;_,YY'L66Jޞ~:u"HA&۳0?/?x9/0In(?yo]ަ.(.ȾthQLJz{mE9¤@da (I~sJACmY tzcz JJ2@hm4Oo@gH)PEȌ@$.I`t_fSF~_?4)Ag7 1||NwayH /\^mOArʿ۳09Hhm ;ߐ62=ٗ[nԁ \cQt%^Y~ <ݧ,J3 nճp]Em0%6>L~m+$1&=$&CI_+Һ=!auӃ5Q c}wwC#cX#gѝ.GQ a!ӠFI:HYpL9΍^R"砓QrpG͗ #ke92@~ }ZްtՕkI?qfA"%8Nm7LR,}Z͂eڧ, U@&c6& ?µAZ>!q-W AuZj7=>aK55e_ $`!:Zi}ѹ/X2nkMs?(Cao!Fm|<Я,,1+WWsYS渽fIs5'5oN5k +Mr/RA4O*o$Eeeg)Iqҹl셈Ψ)^I4)kG73ZPaW [˖Y~_;n%yؑ;Zt8欶RжDj&IMB6))5mk&m$8F//r $5 cEI+&aBu+E+HXQEƊ*df*7STTlUb" cEI+HXQEƊj+[)HXQEƊ*0VT/:(XLQ6*RQT$U$a" cEI+HHQV*R1VT$oWTmUb"cEI+HXQEƊ*0VT խUb" cEI+*btPTmUb"cEI+HXQEƊ*0VT խUb" cEI4'du{YOdigv1KjOJM /rGzDu(Eg颅F͛wS]!5м@|[Sȩ D)y&Igk ^5apdt^ҥ,`8*7rOQZ3E7h&Td4#M>U&qd(LRĊcQ1tASSEOMAF5#jsk wJ~ V|ˑu WOBo$C ;9>pi3}7Q/arwe=@ S\ApCDk\6B ,› oxy;Yn_ {{,@_Ƴ.Gq]c9Y9r>O8i_XQJ9 GO9vO~9]_C%q#pgCV`E! $W%]G&Eє=XE.`Z(m٘GęMU?Qc,Rw ra6n[IyvWPAi J+ 6 /»H]eلt+:JL /j*cOZŇh>[h^!?Y@ a*%bYQ|,e%(Ha_a2 AV1lm:!*!sHXs( mddt%hn" -o%Qg>F($6MVkBDD&Or( .{H%>vsf؅Wv>D>%RߓNVv>\㶙M>SNAMXGuD59ʄja+zr_̫U׺fIϖNrA}hE{&(,3y[-mj.qsgnqb^yk* ̋*\MN:W"Śv8O frAٌ%i3kWy^vOTS|V@l.fѢJIziBd^σ_G-)|%fx&2-x˘hbD0xQ--(V.b5h+ %>[J܏{Xy RNA+_>z SPbn)(~J_%b')IbyJ(k U*b=٢dKbg!:Os+3vOfcV (a)>?L <IM)>]O1)~:!:O;(3bOW1pXc`PbWY8?XWngB[' 'b"OxW@EXs$>=.m[.wSFOS0H+>x  r:s|~_p.~5vLۆ{^E'rĻ_k`톋pQ#nm߇[*qln;u]PW/sbi8vApG\T\QRGpxW34ʛ3Puu@5r[`kaK@X>C)q:" O*$O{\672ͳTufS7U1m)?٭4-6SoXOԵyM| T%2,8BQV1}dAECPf˙jOZzIZmp@6ϡ>ԟ4E Zd$U=[D?L,yQ*Z4C2tY&[ds""rd)4#TY951[{j<;S_oRxhY4rXHE?[%_̃[Y7\B\l xzW2[) u@7ﳚ3)}]}1dr3jx07<e}ءxD чrJwQwƩbU.g7QR@ye:H*gNpQߤm$F mBx #ҳp5l ɰ>ئ 7.-NqluJf"XbQ>emnFz4P=kJo躊ޱbҡDm_rndցrg2@Xb1]h$QBdrZiX GH#:TÌTb{}<9jCs?ʦiJ'kFJ\,]L὎.RcQS@Ia!E |~v#GI(37Hԧ]%) Z߼û*dIO:5;dB@cFR1$A[ثء&Z#Y&Oؘլ`2os2ڸ+_Uó$p.Zfi۳]R`mk74M* Fs8-:̸._duyGIUg3 Vx9l5BX 9YtL$(]f-Vh[b1#f\/jgF9uʿs/A;?SPoMǥ`!o螙c +{ SydmkJ{^4K;+Լvmmq}~uqu#DGU >w#scv[QPsTKmq*+jz8ËX83dtX%jts:tyPdeL˴H~+,>ހd`[-nw:sZjTOM ahء b4ֽOU੓^ +Y%qz2)mtWuaA8\ dw!徥l:oxE`[e-ILMCy%?µ4\(7.0-/V+w_d*y BXMeЯK$j$9%yƈ^f͸aٳ5'`_Di"y^ߌdžR/рE|fK[`ŃRUĸ:h-Hb{na_PS4kÔ8,%/>YsO'9_l0ޕt! )x.8$NF|U:%H<&D[]JEvLic3Χ(ye a :.^ٲNFfo*!^w2 3uxƯܮ)p((dpHA >AH=V\]|E{*ҵӿ__PK!69U(customXml/itemProps1.xml $( Ok0 ~{ܴ)KBc]]GI lgl}9wxOH;:-S hm8^/Ia1Xcx*hD>X׀DC~9|Oe,mRjlV~o mϡa֊ >쾋GYN-[a/>.=!ͺ,ۍggW:Z|F-Cx %S 87Y=9}D$ H2Dc#4Y %^lsr.9}q#omg$7w9,|/ nk'6O߶vc^ 郅R;Q*D%$DzBJm*$D!p6?&n4R^3ڹ1HIlKa|\$ %K:MV+2qLb?"a/c7Ը׺I[bxcWxLT7UeۯWUXZm:F[X̏K[fap&?#}l980Ndz8K1\}&S9^F+*1~YEL(zɹRf5 +c",=Py| &a|ov䬭m:և_&:{󳿵$:ut{t==;0 uV0'µ#`O7 fDvi00I@NC^eı"`} vKI3N4{j܋T6fq܋mDYjW{%̵q{i^0NW{ \q8)wILEHF+]i U[\)F].A{lSVplUK `r.ĽACċ4K `ˑa xQrcq2;l98YXH`i[Y')fı[Ub vo34 #Sڡ 3H' Ax -[6ͣek!uëcU1$1=˩vNq!!"1!-V(n!(aaBZ1NWieƹCZq ??m,C*Y QkCZCd]ڱ@ 3=jWfqe8ՂWfq3ն !-kZ[ALI` -[Ƿ8ځm.5][l(`4$z5PH{lf{RCc4N HcNbG_ʔN.yD00WG6GKnU:2>7WTJW$JP^Ntxz@hqR+] _P`] &WuMzHH Q:[ }so[ 0ʻu< m#c\=3ͣAtrEC:Нj\?Aٖo1{oiN/ű{vd?>RUDƒo0k[sj'/'eأe]؏nÔFzG?,loShmt2sD%MR^<{h) @(+u1wA-D 慾l[>$msƯmϖ6ځ g)vzsY1u~v2%s zlcTc`?lGikUv}دꦏX ]H߅&(x c-aKkِPCa:]%Êk4dm*&l+dGa޶'W::Ss?@u 望qF +X`*1w_RV*c}GaK$)@`KИ~퇉J"M6ҕcХ p(iZiC/iYcVa>kYIiC/uYcP|(DM]+ICcuĐʂ$L#&,d XpID UVKD"Kjdtln3 +d+3YYNrg8+‹,"ʪ81P"DVdEQұ/\moCrUWrC8hT6^si+/pQ~mQZQ17'Ik68)88ў0՗ G9@Q]IUub\<-k"N\9`|Voa)\|Fc`G0JLʜiar<$la8aO8N02ha))9aiTd1?LxJW k^-j^xkbYu ,b.N8KV>I:Ӫ]D2uIB2{V0%.>xD:OT M028w1lAƹ<i`C87Mlk$8^$jƹP ia, A/V+ ;45R;귒<-HFAQ6g9fs"XE|КZĪ{BVieUzBV!{+䕒*zJ^i`넼E9ōUP┼"d68 `Q%Pc焄~xwz$;'xu(|5 PX>̫w1<1k PXc,n!бnL,CBA)//͹>35׸MϬl|;lW 4l jOU5DB`q bTm$8%ƹGB(>Ƃv"%1bHcF`.蕱*. !UONizQϚ#qV  <*n@X0AXpk n*!TjAdaM)ce‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚i5}b$4'eu b*c}NrL.^(G (G(GfqP 娻B9j&lQv" Ka/3X-dA%z*!j` ,, Հ:UH$J`$ θg?k\@. J!>x#q04Dv yaKqH.s&ԔaP3gAMAMɃi!ApF Ԕl1h,tm":X(.s`!uϿ*DS-OwXf묰ffq ll7#h.*ED,^hlȃYV߳7Y |-hdG >ڊkP2Z`A!: D6 .Md"-0*%-G_He'oCK.ȩVSWq)ɫCC.)9ض+@@h}ّvKQB X]*˷&BBPs  53+lr-l9Ps^vyVdfCdj)MՀf.I1%_pcq"YkSxykΘCoBg\.BtB$el.Y5Tbdlo/Mz0`@"@FR T,D0`ʊ ,},}ׅ, ` iqK_X"  BH&g1ILzmzةةfSqf`̀-7;,nF]CA*`SΨiHK0dZ)liԔJY$6Jh7#sGq⟿1ڜtωXbUIf{Fcb㵖#*;!T4ٲ* !)ŋȪ,JL0IzJ^)7n:[u_x [OZ=ce>yV;ksrx{M;?t"o~)=s؏|"u!N/kw w'7P#6a`Az">H+2q} ~FI7Nwj\Z2Ѳʮ G7a #GNsz6r:`*:>R^ЇG]LQ=ZGA._9 hi%ZP0/]gS! >3~m{td!ѳXgg YM*?;O9d=1106ѵ*W\uG,.$_]Bi k|_0~@Z6$ThEv4L'Wr~:`[d?ÁK+dGa޶'oѫOܧPշ1}wNr=p7u;1߯}ʶr鋠qCYQwGE_4ǡi,E!ԎA4"ΈTR,aّ7YC)ҙPG`͡_)u(>)m_(M"EoM"Eo0M"EoDizCE(QFv(.Xuv84Kőw(Nq#MsoSPI(M$`d,QFQizC 4dCHDp0MowjG)zC}6Lqh)#8BLHZ?xh?ͪv1?Al]~KΤ-sك淫u;4Jg(ܩFOr(Fm0J-_QjrH])ӕDHt%ShjYՖi/:<'S+DT!ki0{5{TݖE{/˴dۖhpm{u]`PK!t?9z(customXml/_rels/item1.xml.rels (ϱ0 hoPK)t;JGILcXji߾+t(QE]1hjP >N~j.G{J D60o,W0H9X)ctl'_uݓ|P=;6w#w Ev d*yB1ߪ kPK!\(customXml/item1.xml $( I /-JN-VNIM.IM .IUq pԋQR %bJ 9yVIJ%%Vzy@ (]??--39%?475DL?)3)'3?( jUч{Ǝ PK!_0 word/webSettings.xmlo6#yi0ݱD> I,%qFKDKE_#Ǭi:gfvUzW?߿9[TEQW*kg/_|&;{u]f{TI<]vd>oYhJ\tcs1/˺\/,/jƄ(GJ}~/CUݶɊ$|^K#mS7uS/MSrW7b'̗Mݳ0mElKeq+&n˓/Y A$l"1Xx9W3!n/ի E;gfYssꮫΧxjRw[J6/l,/NzQa5au'?]΃) 0AiH\2`YiAGmD JC ~\iHa 8dcc48 "xureYQCH[kIq8DY6zhL.@!z15m2/Vwzh0QߊSm4q|.,4^Hy>j4"7CБ,)8<6o᠏GR8D~F2pԍ8$h'B8B+#mĮ)"pHC @CjBpD&dԳ+9̠#Bp0z5sWl?: @vH>G-=4i ЛD5z=39 |&4o~pUSk"UO@24 a'<6ͪGpRS:i-<":6NZAёWB\UsR&bx0;vv^ [CwRxD/J"j!!c Fm@drNwƒ肶W2xxzC)Gcߤ` \+G\G1xw r.ΐƒβJ.PؖL5~~1|Kz]#kL"OaOl"ƣ<$ >^@ջbx0^CC4&ΉaS@ސe!uƥly^Ù > x(جZ֫ɫUi-$xuMݼjҥ'+~Ӣ(4Mv.$}/PK!9word/fontTable.xmlKo@H|6%R5h獳WxwMCΙ|$.|J+0~uu](a+3kOf샇iha! g]޵L3toeR!6B!gkα4߿`s3١~ :Lf08"?ŤFx5v|N#ȐDke5̍ ?!xL$ om͸EXJ3 SvvQ .XdWm%W4qW΁s'"17f( 鐇=BKl mQ5|YMHHHotRQV)b@D,gH8tH L?ajS_ֲYKqg$rΆU.|rDz?vr)9RPYY)A($ \G2VjӺ*U^?QfuS}zTo?2 n<#@O$/![u7|xMσ&=GC/>VdOݫ/L%Z!^MZy2ڢͫܤY|lFڭ};I)Sm ❤&'VڥDzC fr;PK!7AޚadocProps/core.xml (Mn0FzNҢ*JVl(RA,' 6X@OYtiϛN",U€ /T g# y2%X^* W /5LuYL$*P(u;%_%.2,ÍЯz#:*F@p 9akAfC[9# iDbO:nQ7?'oTMVMOfKM.^+okR|vd3c'.c-tYV/4i%c'j,'OY& !wvPz0ϭ*l}wǩm| N@ۡ/PK!KLdocProps/app.xml (ԙQo0'; C5*mS+Nb 0ݬ٧SBnÕ;r;tⱮ=ff3upSВ4ۥ{q1w Xw]3.k6rͻ"]R8R._ɸvq ]7Ǵ9BbV){COn;}9﫟5蝮_PK!edword/media/image9.emf}=$Iv^i# k[ԭul7@bՠdC9EE`(k:)A\z*b "!CH ""`-E-^Dȟ٩|::+/{O..."ȟ?'޿xr?{X?佋/.;w\ ߟ\?k*œPů ?5R|r\cO]yQ/9 ѿ~?O?}ɟw'sτtH&=3a密84ֈmn>\ _ze_tXXUO?txxxx'zy^W({4REaA+}XoվBI]C}rD*h=Wr|s>?kZqԭP+w=ŗ^+W^+heG SWh_W#z]| y_z~y_aT>W+hoG+h WAG_/PVKSV/WR^ܩѻ{t23wS^F^ygJv2]+Db~gG"%ϖL2$L2$L2$L2$L2$L2$L2$oN*KOH]ׂ,6qKT'YJkq %Hr5_. 2_[߈gr7Ir&c<&c{bl .!gz#)jj?{iЏX./Cޭya ' vKAՁMWbuHݞ& (Ox,$Z5%C"!!i B[5HF$` 2$0vpDxjZR]dgTِCMuVͳ[ːxFSu@8f"S-S BYE IJ; CA` B}2>$JY 'wV QG~𘹸e}49/_2)@0նLf ~,=Iy fxC`@GɌ ` ?s.kX VO rW{>(o7vRأ%+BjQ(.ma c1_j\OsmɚYU Rfϓ>֡+;qr]`l`YϾB4b-`ȼ'S~¼Р1$v_{彥QUplT%`-CxхctqGFMΒ-m>{tv(37j}Z^4E(."QffpTA Nd=u@,$~M& D5/psɛa}]QEDB"T5Rr:8G$,?< pgp2!c[G`  -+` Jw"nVsYA4~p0dÃ1J[,qQȳ!}f1x /fy  /)RzC,=VkJ u`ug .RqTv[2Te-n$ã^asj+ nS$ Q6P2<5nUp'!0K#[ jx> A5:jo)h$Ai+N#Jyy9c2e0F);n,:H!$arP[mm ؼMf8y4PXM4.Vę_U|s~ŗ4[5V̑ly oU8)5,k[;!RZ.RoQ8 ދ"X~0蛵>++wzÍB#PS;șyQkg##fXx @l8K5{-0~O2D>9&-?Ց4ey@h roRH *ݭ $[ ʮ4 jX~2yQ 6ƕc[Ja—$~x/+. X56ygkQ<V,MȲwxQ63A co Y@McRIC˥e4/~ޱ4021Y2, Qw,[G}Z`C|-:d$F.cۣD ʷ|̒0l\XGJviDDqަʷ͖OsC !ӸW6(Y  #sC&a ɢA@:ad9yȍ*^EiydN3xPp^q~ x/^#~P$Q d0ՄOf~KkV nqoteFn)idZr@LѾݳ뚦Ty1T)& 2z'[]vc5dd.쁋Kfi: ,A1N^ x{X^up,  i\:x8C_!,a+ ?L<$ *k\bYH Wtw5K}3#K,lϹa%v0)ULáJkyRZ6*2aacӅp|VX)jR ؿAY6~s2L:ȑ",lv=|#?d%h/LyfpB175\]y]~cgufmI QEzХBF_gsK=вL\W)KKY~pΦ_Af-.j!XtW,]~1Z4\dYg[!L*,уamFrE`-Dh&*d .*A"QOCX.X"LcńaW˪F^  1b N+%ji=(0\C3Fg yXMV}J!FaH&Yg!, L~ x!E1xJq3|T'dazu>CYGHєr)< 'DLA{ HBB妑%Y #AfčEqA;;bXd-{5X:n~+9Bd=ZqraF=軴L[Z ~PYOƘ s%EU*?~o$.:<=6-rYæI Fv5H("c-/?^VH%"1D[bVIm JBu%|\ aՅ\["VdXG0Ay^}qW͉m(FTu=6RbY{mYwC,ulX2[鮳]1Op!M1EԳ$ڋmKl [EV@-K DC q6h£p^ 6M[8 q * +=xުIABHJL"^ N,O֖uTBΩn!lJ4Y~mgG أNgxwx)/ oxhi_ڰ'䦁 l4܊8AE³ ;vpy8B YK {PK <& 2H 2{(] })ML>JXqŒR6,xE(e!8 2F=x'|d;,égku{t'\.\78qynt5&Mx׬&%_%/gdJԠ.XEW0Th-6<}?NA RG|UXf9<:Dy+V )zV abv*HY)j9+ku]['Q"^3CX8qY0P—gXuȱ?+{lq HhAgWh7khP@c!F_$ |e ؤ"Omyl( ~"N:H\Z; e(i ^A(+HiFHilD 1#ɽԡc:/LbbGN-#aIřSǾFs`V {Mmj*} xG`Wf ˩_.QP z:>8h,=Q_cm3G&fAN-{W$ 1[_xn1.)Edfsbnb9;mk텺K_!ugi?2<2WVi\ V@tPwNpCOw,1Pu-?졌xV2W˅dKYCLlc` z"y 2;4-&_w*<$1l9## 8 ݰ$K,m>v6eZ{τ &Kb˄|nqyj>/2T~o 磔(IIT?[VRc>(Ҥ_\Sd^0ѱOX/>$cC,1IjfjU猘We8 SVY3c ^*_MB#+R}{}Py]emڶSne "i npıN!&{+=[7uN$Nɮ׼mӟ AKb ?$I%JܒմrHx TH}Keoc8#'lHȴY{Ϳ28%s`l+'Yiܫ]SqSGwd鰇Dwx.-i7!P|H+B<<[sf7zu%푛{,J#g/t;?%YZJ蝚O i-K; R.*#vųȮ%O\:T0?^+؃;bKI]y*>Y{: yߩ|^T` XTJ<|*LxUN %U3k;rɠBLqs|iKo9{e 2@jt9PvL"VK,q`gGЏsa^ϱVҥ,^,qg.h IAr;ILH}g_FZl 1ݯ51x2HbCdʯÙiM54G8Yߗ"Mv1^#[qwm!q?.IO,A<)C~X#p>ۮ3!/d !Hx@"2Gl챫%-ك*kVԿ0fM${LdOj-A 8 s c %K%^z,u"h `.H| 2d1@^ҍ!^g4(!v-l B 1pS`Sc,7V,p?1@vTVu8`bkb!S䝑)Zx[m'ˁ A .Dck̀_Fwt|?6PO tCXv"ˑ_CpJcWS[sdÃlG;vSiX/X9LR iΛm'$Kփ7CC#/>a"2#=zԱ5)ãeda^$I>C@{lu.CyˤnGxNtKx .GEZ*q˜97HkM\`50p=9}LICn$&yo+VCŰuMAFL) &8Pd׭WZmEYҠt;`ќq*>K-8ցu!A=[t(4g2d5ʸ7&8zmOR_cP9xg~3M+=U@KaD$N˲d$>x 3ܗ=^-Ä r)2E_ψV Lm+ \P=9|)m~`: '!tEQͷKMP@Bo*^V89LzL뀠[,Fj.C^TP/eqBO^#luiB͏Oo4)eN߃ Xv<0 JC:Q9&/yc0ߺ,sʰ\xAi䏰G?2 l`#M ^5^eHPYtb.v7Le`K(6Ҹ΄`un5K}#"uEȬy 6]M:puGč lEq\Ĝ30 0Dh`3s 0` aKiPG,ԣ{2"BS Cu'x7M3aG+|g;qwV*BdI&dI&dI&dI&dI&dI&dI&dI&dI&dI&d{~~ޅ?NP7O߯u~S_꿏.M<c<ʟ?'Cy?eC?= Ϛ;'_jXFFԬ/OFp'/HE_e_tX־K?T?TOm~xnE?Xqh¨/:ЧުM';Q"҇ԡb_}EOz9R9?W}uCtH]vB;z_A/Fwc}>WP6OU?V]_>BvWP ]A?V}+]c(\ˎsw'~aWAc]]u_:Xs |_A;_ؗ?C?w/|ޗ/GňgNyP_ _yH^te-_7pŌ_ϣyH_/<7WD(?B>{/FGP|Tdʏ/1}!8S> * }9CXG/WjաB=}z?@V*OY_1F.MAT+AދjeG.%^ɧ(OW]|6_YqjI&dI&dI&dI&dI&dI&dI&Iը"KOH]ׂ,6qKT'YJkq %Hr5_Op,KȜn%xz@5Yb3!Mݱ2Й:nXG $Jw ^\?SH$$9QHtn-&O"kH&HWq?!& ]H|$H2Ŵ8OpX $6h \6 kuQr`!dSf;zC6-du([y!q٭́ AFA @Kq>H x,>p.8$PTTPPTЩ{ouwُ[Ϻ^oߺU]_mw5px7>;_a!cBg7>9$vn;e4Q{e~CO b3$ lv805 0v[APt :G!aFlͱ#sk|0PN|l^̂X}ܾ!` RkRI ݭ|S{3CZ{ 4J Ӗhj䁆KNx itx~ۇCQƄDOa}m`EXK0GWC}n7:N!FQoںBk.ǐ[ct}'k"O߅ە *N jX6njtwvSz&g]KdHhZA*&fj8N(yDKtoPo^ Fe!$vH{s L$&Tp [x~ImBۻi(k̰M` \|`l(.,Hiy-V )dJ|?14@1*a<4˜d9G:"hcV]7bv' L$g|*Ab%o1㰱l=r8kjp|ɝx,'|K}ܯ_d Jo:iC%gv+%T?%jZaF!A,qWr&C{i#n)1 coT.KT@H_6$t~aVqKA="AH%LHv0"q\ JY_-sj<j?%NI ZS0E,R0o!j*vx/Z $a?O@1[zNQGxIq1$0"c!cmlLc-8dBA@ݥ+ -YQ+}&.Ǯ&`ۈ4= )N)N@^.=c;^NG@,襋Lpk[o 2É Iݒt8:{߮?.cRiľjXMc=I۵=dpFZe~oa8 HZAf1u1l|R;鼱CC` 0٠hX#]c`dXK̊šA) m{#/pk!d #8DG}%fL``'HQ)GAg6 (.gك٤ci?h-)r0(BeO[2껙 QW`o=d @ 9%2ba:8rNEF~1{LE@`V9pEHA 3 ,i5f8s!,y^P)ϡZs,Zkͱ\+gw[<d3Z0ci)s?!/5qY:3k4cx}V{ FK{45xOt_bªW49kZ|JrSps7vbҔ) Q)"fXjfpTn'4 H1 ɯjj˸GagEeL;O)=7f%9wȿEDBS]91E D#I۸]͊5B x#11A"pop\3aKMu߹PN]9J- }.Ab@0< JŅ:Έ=R 'F` $D l~޼|yFK1d2$U( ?uw¨_XCؐi$s(,BAK,gpo y@%t ?5~=%џB"0{#\sT禱Q`PT?6UЌ-Ⱀ=R Q15' w̟$CLߟ$ cX[0bdX11u=[$wT{6:tAr- %$< 꺂R]ʬ$¹`O#CSWόuabM0ܨ g!e 0l7}]{<~t!6'g)9h( -c00?ad~>%A"Z]L۷f~k`XM~o&k)CV2I@ =K˪qIvs}x0lL\9@Rʟ$sq$aۭ괵cݛg]3ыE=TZB`V&zK3cL6;j3_<^o:D`^7z%NV.z h\aYW+0v>Z\EL阇MD ¨L8նߛ3WI˪ms0qU#%ڇh_֘daJɐW`O!a2>nJb=UgX'51Itsirbخͬ[Kq/K*NgL5o {\TAa 8cž-x.7BaC(%~&߬p}l3VZf_F|l9JCWϔ01H &(' GX KDƈ#Rm|,1r!'(G٠q=g$8W!.%$_jN!K'c؁Amq3cDHm>QAv,Y[>@BvE)6)$ md鼷s}B ,a#g R52`"GG#`͗23xX]3trs5Mq厖eNoQpg{҇6uY0:+g5-#f}>@!Bd>ޫE'rWIjsƗ;e>sƪm0q[Rr1)6uYf[G9h*8V)R:EƸ ߋSYkXqOD&痬^Q,tݪ/ܵÜٖ3P7Ei/pvѲ8VG_mzzim MBVب,s 9|K$޸3v5ܻ&^tv$|T TD;^,%CZBC"ˇ.,ܼ< xWiD5ۗ/(> ųRg3CZ:5%,]9k8TԹڶ*"_i{Qs&jޥڌ;Q#F on,~g嚀c_mNm ijw v]A& ïFKmu\Mw&T8B!Dݑw];:}Z v%L²#hgwu(in[îɥ-}F R9Aڳҹ. t+6}ɔLLP?3Mjv0r}.X,W~xz Aڣol_5D@'Xj/2iǻG FZa^}K$0z|2k\iH!* ؖ;B$VC62Dٍ)}3^}ŋ G9(ՁVm+G0W!H3쨩 ;#(HpM| @WRipKb+ӻA`#,t3dX̢E^W'̳w7{ŒS]ufi:,aML}..`. Q#]D̝mDx))pvhb#y燵]v8Ħ@l j,,-L}k[HoLk )$~8y7]C 0.N|""I3km+s\"Y _% $g!'-&m}"{g鹊\(^:gYQCPS4z_ƙC_HKA!;"BVa{dbRn!T($PT)b2yI0!?hJ_/LHPniݖ4CzK`mJ,Q0= iJ *:I&n,t7BrGzyCȣOO{9NP$\%pն|g`=hYEv!<i8V%0jOBgӨ&C F0UTKJI-[ f_۵1;R~=5(WڢVé4E(T]+-Iul2F+s/GIMI/]$Jy䇨 $ n/dH! t}e.JEEچM>.,? '0ə/K`Y%H ⢂yȝ"Q !KI,Q SHh#fmg:@@bV*f=80RCƅ~!0+:`J4Q@B'd  S~@ c,gV(Whi;ybYGѕ:L# =y% Y(QPvKYHz[yX\))>G$Da>ac(߼׃ˢ׳|[[?Va@G8؃ԥ%s6~pYLALܢtFC0L'.Xphz]>ux{'nLpc:3ɩ(}yH(4a3ӏ )*E$fN kLJLzW#,]2k)ʑ!.UZ8Y9Q$(XGlPc jkK_a2dYXdxٖ(A%R4yT眂`?uɑB!71 Eܳ$>cKZe,wUTh-OA6}ZNC =R`*TGXe#QWc[,8cXu| [ ebN,űJqWz^YoTU&yq gXTdRgxM Puh۟- {kAЊAz0 !7x@#AM:/A*rCls Eߊ yɔ |"vI@uCm=)tJ障0_8^2H|4g,>c͝$2is0_\ $@6z8,eq樣ds.=L=&w0Yje,|wMVix)4Ga3(Ȧ{YlvEA3)'l>4+WOD1[c或Ş1ԡ(u-l~˵u1Un#N/EA VIyI`,<ĭd)KA&p]u J:'6@+sz}nx/PBuPuTnk2mx.GMkWhFdVN 0XRB14.m6Dy$$#=uLS87Ri¼)YͪbW; A :nyBُvc֩7#3[H+XY/$>LLdBE` bJlnAxdf.8AsO[i}Xn6gvAX(%ϳe­K/`t)^`c  |΁"QFҦI|7.+5n.wG7ћ"ݭ_"}hP<2a- qv1;rdBO<'װȂp7!qTpґ%- 4v5?M& 5v>}1%Ѭ\HIS|B KGpݚ8::ƪ쐠~o0OTa<搰KDՐ1w.әDXG Ϊ> ~`=6 p{D (d:_]d?WG[~H99ЎH{|)FF*lVq?oom;Xu`(txO>z,aE7R1r<>d 3,#uo#G"Kb>2vK k蘈EwXs+x3 )4uxHjm(>X$S\:wI]ڢ:&LȬ|22֌4Ei`n>E4m0mi5٠~%*{SYpt`)£kzf?{ YCLm &#*BufHpzdϮD13=,<<^:{ mă??%a6:ig>1;!; 3`|@S-Zk>jF< c4Nn 1i!>{5Yժm]__>Qa.6m>ڍF iwq51V!3s;@l2'O5cSزCZ_ac~'K'U䙜{jlY2{䚎bq1"K,ݺO*6\cz8_m5v5}芯/G+B7jaFcfw1踿0)?=T?uOmz*ա`8|*LrU_  wk:d[1wfs|C馩7p\a/Æx:2v[cwv:]1I"tWϴ4n_z޺fZ+h>w[Jd؛2GA #܁<ʈ^3l+eD633kԳ%$?ٳn?}>ȃ(a8fv/_ʁ,D33\*[Y2{sÄ!A8FuuhCzKXmmc ib G"w]lp(@{q NȔÞi]3fgI}Y2 1uGKGw" 0̉+&й(@zju*kB>9pd\ 1 21pSfud3mqR,pB1@K;c U U+,m..+PX݂6e~6&-8M9$71T؁(q )_3nfO\aGx_ЅO !Dk˯9NU=]xHibr|N;wڎ=$fPaͦΚ<븭 _KpE#,1߶=#9\K;)-Dž{4.Z~Ej3ImL'ㅺb[n$%]{l|}9/u3z:!/wBlsNKG@3dh5IoLpxnOj%tw q˞.J/P|I $$v*-Y<aǏeB2E/?ψ6Lm; /~|5zNC t匘ۇo}W05L+a -~/QpI39!*(:-]u:䄾~o _4w9n_m 5(0,ya=\sw˅lpQf&GJos|á6l$eu:nhrW2?5H>|Ç>|Ç>|Çׄ󡄏ΕwQ?{>>:v}=~nL ^>Rti! pAz RŘdr"mgh4J%bQhϹÿX@^ϘaHeƺFrrPyڏWb+U޶y;=8r7 /xeח UbvʠG ]NP`XN 񈔄s }|$|eF l#O9bGd]F ǿtkL ]Hږ>FGm/l:!_NTv[,wY JUӉ_=#Yҹc/qO^b` LPUʣpbC6/%G(0S+ @Xy)][bY(QXW||Q׼п.E՞F.fQ87/F Q>JV^g<L2׫U_Ͷ }+Gkl/V]E`R'>Nd.Ŀܳ\1rh8Bvp8#9N_WűłGcGˎBf1K+LE.&H=bP%߮uu݇\!G]bXM@1xDQudpKPyM^ܯ_Y=B_>4gdQ\,9%h^~-St~c6 17:UbSrF,LY(@_!67\>_,xls/ PTO*tlk|IsM?/l6T|37 "&m l6Bkb)':&hOųzqg5g/.>Nk̦h?G)LdSqf|˲6sbon:ucv''fs%!_)иO.fFs1]]..Lpޮ+r݀|Na~8  |K1JRW2ŏ39vx@Kl{2褽>-Q/)cxctԿl<`%/E9VSc>a,!PF 6g}אp 3&¸_P;]F䨗q9F2?ꅗw;E*R>@O&nxk'/mhQʹ\G7v׷ 2]iרgS !L#(пPE:P61"F Xݩ_a)o=u1tŜ0psf n;z=62m{r|(\ /7ȵ2;{!'P8ikoW~Gпt6ҟ>] o`P LtuBxDNeu8xп'FHn=( ۔4y]SP\ͱ ]L,=]O!d:¦h~׋f =p7~CˁD0oke+odbyhBq 2K<7,͆m0-rⴉ\߫gV5!ƹ̺t&oPO&i|z<7I9-ZLl e=? > |Mѧ\>}St/fCV_S/((%";UNBJN25~9+Pbv/FڿG?@m1zq&0y%1t/W<?GmLobz$i(\K!ƿ>t+m^&x- O'Fg<]&N(;sQxW)a/H&a[U|I|Xۂȿx8m&oL\tU)Ж4-#1ݬ=(ZGdW񕂇/j]\.\Bt(?(ܮOTRi]k̰3h0ݮ1ZTLNjg,o3*~}G++gb(Vxn8\.o+tYL r֤uQfr|y`Z>E#'{#ͽaQЍz4A=|:: k35xCvKTB|pܓoxgsomh  uiarpw[uk΋,[VaFW>*4O'nefO#s>pĿt:bѭZ@  8fo1ȱW=/(v (%KWhտ݋e$H\8Ş˗.Gdyji E*_*V-;]ߕ/SI1aXKJ 5Bk8{; _&Ŀ`&9g&Y,K [|~'.PtB?3mw<̮HY#pԇ $yPY lpg{a}Ɣ/Ÿ]SV4&>u)>/a%&\k"|MԹ:zXz!#9u6 1[ܙu}" >nYyyjuT.ȁ+W "Udf6An?'7_6Y޿Z<Ƴl5&riH +γ=1,=0_C2ԁg?'7ۅ!3eO_k1gOyF*W9ci_̐Q_P5@ո\ jc =þhnN.ˇA$d (WK9ƿL:!d!kbÉ]:293&HbCaϭ𳷋I2rWKĿ[aI JЎz1Хpj(bh0Dreqr3ba3Of`(vEvz^xl.sY YY߮~X7Q?xߠlȹmٹxdl0 \M[1^dAd@IN"Õ,/c#\azY6Ga@5r,rwzE7 dLD>f7,1m,MV\t1NM :2Ű_l3Z_/ىe,4Lװ֣|yNwsФvC{<^^讱umVxO˥'aɉvrG%fMl\޿Z_Fg5[1ь:* AG bܮ'wdBx q+bֱA. kBүVnWk /۹)Јf$(x?wHQZJG3u"xv\ҹ?Tm3z cB=G1Va`7[Ow[P:ڣOPYsnWjm]\\r, d5GZdv^:፧+*F]H`>v:h` z ~Fļ8}U:[F~S(&R_W/tȜu> ;Xq+)W‹GK9O/m1V(_P_meb_"X_|[a%t빌ypѮ'FP*R:[AoG~ ́r x {4 djo}1̻ƛǙۅ h - ٓd1/ż4 :D0 .ۃ/k|XƾvJC%FNA"e v>VfWRʉG Y?hPlT~ҧ`r%_rB(YMB-ٹ0~<_5ڿ6ńgWK^12'p6Kg+~ƨ/x,W3 h.;CO˼o\h [&xJ@F._ͤlWsȍLm2d/WˋʥŹuڷ0K%X Qǿ2W ׇT"!W%JT#w;@MЄ62ʨG&\*r1_-U.gEU+4!b֌\0lFp\ 0Ǘ 20 io"3â0+:'7޿<$ȿüp#HzjitW9P܌2LDC'O4Pnx ^]՛P>Vt1_m %NbZKͳ));_W>G>I4MN5]W,׿a- 33lxku^k{(VxW bTo/Gdx.&Í]WKĿ@// brĿ\/&|ek’$}u%@5͸\Π> ~>Ͻ}pKg|MyW i_?'+SF|eb."9|>]]W]X|i?T.AP_J gU7ǰS'oÀd:&CagZS+~LnD׾^L'W#c:MfzNOd}"C:7t\cQX[:v21HT}P}|(YA7,l=tܛHzŻ\+]޿%Ϧ"GAY|ore˗Gu/Fj@D/Σ/jPʝ"zjcW x$k ?Q1U}CychL\A6ʅΟ8I?SS[yjcDWJЗozMi xt"vRA<޿Z%k}ԉa{e"%W486l;iɵoDjSOP3Z%.C6r #:~@1*'fGW j>mQ[bO9FGL 8G*z Wۃ#dl YyqR]s1_m Q_Pwfؕ{D>y7L*Ky* AĿp3p'߇ST4L?qIs<1zS%yji 5Lh^= ?#pdO2_WU5Yzy^/M\ON^FMR ';us;vspJAYk?fc#{X4gXOyz(ֽgtowjy~I>wNɷ'%Ώfki \v8گp \j WX \ bZXi`<+6b޿ƿxzb6uVD98I4&%P%e_%e,@+.#A^%Q avxji"^fcerؿy=ಱ*SsrdB/s[eM+vn|[er wxia+T?(>>Rпl81bE%hY -ZSz.pԪ Syz G5==a@=KVT_&:zyMZ'`W hsA(6P@% Z15,PKb%eq.^ P.bzj]Aq"ݭ hz*VBg,O @gT:Vi9-|} 4* Cc4~1SX \%X-<-CXSv+.TWcrGV+b3/Q;,*-)*-)U2%[Z<3KbШ޿8^"Կ)2+WJX#LSĈſ4\W|š5| ^K\OR=9:*kTi,Ըz,VJؿVhQa;Ѱ SXpMQ.*@˃@y.h."CkA3תa=8O(a]bi&[e';OpsQ+'hRRΪ%h+K|Wa@¿zm /0 be?Qh.VNA\_KO%jS:pieb.V&]V/d Fk)0;W+&#*[2/SH~z9ʒQ,NA+UucҹA/UZRl,N`Njx<ƠUو٠b~(CX9b%p;l<PY \+K…U}8}|$-V8XFHƿ,v_St+AsD.T/ck~Laf$^V_#ϽVT_&%2|,Ȕi7c\*;,<΁9kI b~_}D}| _dQ e<)e䱲6T:XjzQDq"pٹQfN5fjG(eA>Ug!"U+4\̳X(K h: _k/ 1>>Rti)\"hj"V^o1V^S/Et\#aJ4/S+i_Ϋ>>Lqҙ+_H6P/(R]r*ʋFJfQX_ )/6[ _1XT8Nn,R4SPT_K|܀|޿ZBf3&(1ԋ@TSiX@m%V,cF %EA񕢣?962*|& NXR^U%Wh,F>Wiz",,vn"&qj`e?\0e.%'gHBF*˳JKE%hvE~uQ_YWZLk襠9a\ Pv ׏ ҿeO :_mp"&. gy[m9yV\ةYp( CEjv:*\R޿e _,~/J,v^ @[zJbȒ8כ"CeIiyceosQ*K_be#u#EP(SJ9`SE+[EicXIn6{zAla޿i%i|/{u(\B/vbyVFJY|LkYeW.K懽ZBQy(aoU?YW TA.VVaR nƎVotŞ,rWK;"nTi\be55.FY1$8UemT2tQɗ_V]~ e6pDt^SʕyRJܪcsL)wʗR.׮+iEQʪbvnWW.5Wr@<)sm{P&ЊB3`)zsKW5n1Hby%ݸ_4ENW\/^\ʥn1a^']QlҼ㼅JR\&>dEy~5\bz̈Pv1"kn50Suj"8nsx;8x%Yf/Dϯ>_ _X)Z,͙h]ҍ턙؆µ(EUIMtNUWӌ %%7Dݪ͕+]|bef|6~v=`n4>C9E-wt5yA:No@ܤ\GəYflA_ɡWO6KV E3 :r=n! KVmNc.5e??oJ 7ͯ.:Pzle֢-hzHJf2rk /WVXqa些Zo\thNjE+_zTD{ed]V2X,%b)ݴ~ v{6.Mjr*Q󫏪W\y,j17b\MX96A: t58.z^"O F[Ndrq,%9E{VMhe,3K[W6懣OWUTDI\\z14c#D-Vڽc~v˔WO6@Uï)a5crtIb23VMrElQtk\Ksn/ē}k_K,2m1s]Syk9*}tM]tc/#2Ksyn%#M,%U1ݤhңWOW;t G)zn-b\[ʲJg%et_)_Qns:Y}'B"QrU%蠛IO t+._"ϯ_ _=nWĐ*+ѪbZE\D+;ƟD+͈{=Z=cuoM yF1hynk&+h"ů+&L7-ƲRzׅV^,nr-E?Qi_2D_\Z5\y"F4=/vt3b8E_ʴrkR/+#)fL+=OKF+/WUYVN$Q4^J9GXeNn 2WO׫fm"*($Dsa RN=(_/xPI[E4K6E_6HnO yXWD1ϯ>_(bړo_?yEmUhXPs#^D1ϯ>m.׏R=_USH̥rϯ>m*W^QmU`Pr/sWU믟]Ub߉ an*r'_W^vHyȲs/5!T"K"-f(;įkx~5#52Ie_qa~S󫏪Oh7Yb(/5?4)S3לּQtU8CV~?^$_?7QL/y[(ʿC!=+?lUe`WW__ 2Ub\mSW#O/rë^byQ,ϛkt+ C9"e6}Mb=Z=sugyq\ZQLEttW__{5NǮ/ϯm._rڰ\b˔_Tns zks)_%[y~ZzGل\M)LU袘Ť)WO3_AxM_^aՒ\m&fʟ+)+~zK(e:SDϯ>m.C_r AB1+ty~Qns Y#-=X*Q󫏪_=ʔ83ebg"_zzKF/3J*M=(_Zʫ\zK 6׀ F#t?3vVCp^"SLi%N</$_3et?^돥Iur2QqG(Eϵ2\ϓ8|.%w0^kp}lȯvs{bd2 8Xt*Dzݴɡkf}"(f$2(fyvZEan=*^7NW5s"x*ҜYIzt(5Z$q\.nMNk|'#q٬V+{br,jUP^IuZ`\6Ci@1I-VRn"u~?efY[,'g&?>>n|7y1[lŚtHד {Ǵa8W5Ks*'C$ x<. $d@d$xmWNpy<^KrƶtM %r>D,SIp@=iߡcJo<|$S-^Vr&tɹ;a^落i@ JU/7Wqj=])֜_0L ׫v9@#q ^Z_A??idJ1uj%*l5+mx*7W_ׯӠȯ<̯/U_e+=b~ \&uTP"e]CDh߻nN'a0녚8c8M_Ҕ/lN6G~}rAuL~F~$_4`E\OW%Ht#F{xԊ/ia,P)xo`P@&TXz! |F.& 3@n-'<>_B FV9towi4/ b'0SޤYn`Emv]Esq܄3+uf]__< 7| K1SbMz уoFYR΅_F߂mk/jzl / ^\R蓮jվ1aIZ"\gNٴA7F"۰yz9ѣ\Zj0š/ACy`I]˯~UkA5(RQ%JSy$$/U#/\_Kʜ '9j_"G?@Ҝ Q05KrW:u~=3ׯԠ__cƢ(J֨!m_݊~$GM\d -I!/ȍ(9ExX7˅4|)_~fL0z%Ub}*~Mk\n7lgQ]6 E l<#f={S{R_G$_/j\!/%)p"=s>4?J-/&c R *VշUǓfxmfOhVP^I_W8K͕ǀmE=0?>>'~E'b~\jyQr|y>E#oPGN?PݨGQ.!-&Fdj߳-Qx>|Q+9^<¿v:;>]q ^Tr yi FEa?p֍z_-nY1FpZ_MRP8h/X` l{D#~z<FuFC6HFV/}x5]"ozeP/D 9W ^*>xy~QTNb~)s!w6'Я }Vm\_LTLG6h@sA[ĐZas2}LۛA#1CT-x9v( =2-޺]˺Mo=(_&"Zq~/tHP7 ğJ#0^J~DKl)9XxA71Bo(rǰTmP,[K.<:塼P\eTveO4c\H;$ro.jtAHjlue:X><.w Bj{{;c mJ G  j ^3_ ]l_[v?JQiMA6=k㙞RA&ؓ+}Ҿ?/_,ϯJ /ׂ%BˁW7blXb@L/Vl(믌_pNΒGNAZ,P5xWc&룬+- -o|B='.~0gӯ|Z^<+9d!F͕H_I2>Yn3T9Φcl Ƴ>0>cg7E0bZ#] V%my?Fs%tхbW*)S뙑 K̆/:#\rIb{D?"[Ǿ*MK41T/}f(꣪-!,fƴy^FNPr2[lN's99]?Ot^L`az$Bԣ ,5tm[Go7~7 ˨˘>Ζ6_#l$Qm(m+ft1.L =zD -qQDvƵ]13&s~6#k:2_Mq(WsW<%y  7MD30bg6'lƺ-=F|~$WW(ʣJ/-g\l1%<*Gt2A̿*s@9q1GUmѽul| H5U~evKs/l"mk[S)~% X#JbJP~Lt懚ogk Q-+EYbRW};-Ŝ2Amb&k-ce\._xU<" g=][Hj']̹ljmtr%r>O;xJ"F썮Ha>v: )T%|~fdh f=A NN_1 J-u~}СBh6nx>oW'ްR-']?'K/}jB<+=Jn1Vb¯x&k yrԣo^L]Ҙ/0d7dUE!Y7W Mǥ63J ǀǰ,€vW FNMxqvA51vQؖ+ړ]HˤWOU/E@db')޸1PQǃj HD3r=~]N$]Ltm""6J?S19DK_PBD*(#hY[O53RA8M߮}"/AntO.&rJ_=Nԇ'm7 @B(F1\znKo;#]~=a؄0`sIWOeqlJ%ʎc^FW*6JZR\M0_ /Q:l5> J2"K\*b_}&De(C#O[p{ZGQGvVS*$WJS~-hZnV }9YH4J&vzϑϵ<ɂېb_}2+$aH_\&2q^M3xk GGFY3aWVX,VpKE1֛ӏ It1~yebc:&˓d~orwxb%y~Q`RPf4`?v&owE0E+e+G_=_+"WbzLi'Ϧ8%^cu9.b&N9*S%BY-(V*Q5һd8Xޫv0 (.6p|Ϟ2,c0?/K<\ bGW4Bd=ƕ|A+Y3wī*_K-KWO%ͥJ+U"ݤ;n#1!"En[nuWl/|<>̲}E~Y_}/72(+,⏢"Źc"IW+"C9vX.*~%xwǝ)ݩ|:ҝd=~tRT,DrN3Op8< EN#v|g2 ,"fVsM2+/Ɩ ]GwI9C\G5JIJo};aI_}#+0>qYd~1*d`4Q/$$"߷tͣ(G}DOu$%?^$yKOY_tE."% ~n$7)6sBsćNoK8YF2.rچE>r:frB_UnALr[woֈu*,qc =춼wr֒>Z<$?Kt))~m* 7I$gh:+IRȷFo7͊hOt;˪~X-8Ptd|vUegNS\4 ^{W2yNUZ-% ØcScGro@4_gxJYp΁Ղ? ؟fMxO~7_}Vik&zI] 1*4{C*N<W|Ҹ$SAz9_ .CXl1-h$ }|DĻ]+]-ϯ>/h,*ZF+ArL)/=JVaE: hH }qJ)WWj2xɣbrqNch.2ͯ(}e51Rę4[qqo+TD1ϯ>/K!ߕ`Lߺ`f?U'WI-0U=z*m&6ZIV+󫧒  oD)S=TtA1ϯ>JFurs ZJT;9e7ۭ?^$/!DiWZ)x5]D/5-p4ʫ Yye+2asL}b_}Y/Dsf8{(I>^&b4Zy~_y/ǒF}*fQ~I9-OǞg5Ie0bC(?WO\q F,ypdvG|ܾ?9a?~⻑Glb.+oz|:dh:+Ig_S0e1qdOz&7#Y<:*J^e\߬xEB'x,%7"F$*4Vf$"#Vv;H T8/qJWS$-Jed?S}$)k ̌9ph(JqS!_#kXy;VIhK"nDy1Jwˋ񕾢u^i~x_Cx>7y p=Т;%+~x5n~@$#_K˚pXUWvH48PpŠÕ \$@E@M|#JZPkkY畆5_~nglVKE+J6z_+xe@0#ɓ3{낯ݒѠQ [ڈE!=Ud4+[(*=^SER#tp\xǹݎK/ABJ_:4V`FJcIqꞤU@:h-X&fvfd_i6 (FT㠉++{O=!-pqx7rec% \"_0.\JQ[,4~F'-%f.@sJv:C4c`wm$ @% ࢱX}E2i^dbiFnbD Yh=t\ԅvKAfBL륯hWk,1<2iͷ=8Qpsb?˯J 5M|R/jWT1qe_m!}*(D̟&\mIn #A#җ+Mp=+ \c.qwKg]"zfCt|O)H_2{((w 5}Y:uK<8Pw6a(`axorPRi7_$/_bJЈ:K; I+;Oڜ x)0%@4gd,WϵhXx!UPKT@pBiD7(ΓF6 GL ƅzO_:4竍t_)3Axw{j HMOHi6] <#t:}ߢ!Bp\Hqb6Ӿ>yE7T.1]\_^hJ/RRk5ApnYB/ԯJ(IF|pQh;]/ _nfg?o⽞J8\kwU#B-e@1 ޴pJP/~~;=*q|_E"FԬbt# . V PHG%-`N];/=XB'Η8m]K"6k$zt>КNpIW@@Uջ{S/~[XUo E1 %{7 @m얝'K[\P C4nP.?9q:tt_07iyB/R.\? %M~u.{飹( >Tȱ*z|KkXqvav^Jk#;n$evi`.+79Iwt4ǟIpKUщYW")DVIAk/Ӹb9ivюȔ6:YYUBy1Ě]xo0\M*ЁoPKiP_o"դ;_N%-sp%xL4p7XL%a'ƻZޭ 13po/&} œ,vT%Љi 16tk(Mrzb&\E&n%œVwydU;q/?||]Ve\KgV NuBwdh҆Z(-ˡRI}[WwJ8\wRftnۿ|br22=4$|xgIp}A[$uhaT8ICұe;E &0{$\-;}5w,Q e4oטsr>_N/qL!ӻݺ%!e4zRn/$QF%0w\DNb3yoJ8\kL0Р `\Kn˷K~\Q8QT&_vMW|_Okv#}.bp#Ny3Io+ &>`ٳ˛h/b_%N/8MNsd*Xݺ9֗N }tdMJ u_>5Ph.co(ЉqWE5 ].nf "KnD|#8<ӠW5 /pLBp6˺E$җ+M. 3tCޫv:M/_,* _'OJfH/M8\: :bd1hw༛`-Z,'@q_vȑ>׼vsMwKdW _cלCIdGnp]Nl@WB)=$/f?hXz2a0\_ŧQgpŴ|ݖof,M&^9vT&q;,7Љ| ;FZր-h7qdésgx\n[4yۇrm ʓ^v:Fy[/bᐮHyաKrfe7a7/=3nۍQFnID`⩍:vS]=hG$1ַP4bnvT:q5 NhF-nY-$n&n.Fs3n_^ʝ8\k9O(S_^e7]V}L2Z 1 %ĸxfŠ0܀󹠉gWC/q4Fau&c:vth.nt5߯'Ӹ{"\Yk7ڍv _ 1r~)LAn vsLgnW__N/8 ?iڢn^yFJuB^}LZVz6vAݰXⷅ_EO. ߾.¥Rv^)T657Zn |U!_JaK^nʓtؒ,ӵ|F@3F4v'k˲XW䫏VWўnEi҈E,n7@n 1;sN%_?7qk!0;'-=ny?/\F&;6Z[MͰr/vĉ|7+hO Kb̲k1kmگ˝B'W Uu-p<@i#um4nmn/{I//Cg\zY"tkn^b|w 8_pw_X?nw%n<-Ɏ+fv܄FxγF met^eٍVvr"F|&^_eN/y[p9,M%eYhR-,p_/b_N/ubn%h)b54bީv ejNWry|a_eau 4bxϲᑦhe o/ ڊZĉ篐PMYlhķQ5nIEL']fz-b7/q,V_%NmL\ JN&Fn-WhYv#/_N떼n1kbI˻w&]n,-) _[z*qp_w9ݒ>[DVA5]nHndnTչ yMPRzJzc4#[ ?+ͶDV8I~6oH3ѕŸњ,It}"5,VUzj1t3vYvC.9*tp_O? J%wn Pnotm4n7_HehDW$}Q<1rW:ikIAgF[r-VU$zװ+MB1i&;Fۍ?X"bsSUz N^\K\mӳnw\n,_hʝ8\ 2O^||Fti1 f7_.b2'W_B^ei1Ox,JD职I:/- ,WXb/7 8_rɫ62JhxOME*qp_/q"y!D6IkCFcKX~"/  {ƹikeYI /fG$Aq?N矿ռyГ6#fwZX/b_%N./I2Ǔҽĉy+x '=iCX?/I>E5>ݒͿ1Grlw/}Cɪ*wp_O<i( %\.<ž P's?0߃}Qb_%Ng)_qLK%AwH:Cb_N眿n9yœҡ|1_._Y&<b|7%A7!gWN^'v?0CON?O`+ PX2 EYU& -E*qp_|Bye,֤bMjx<+u^fpu~e>u gCkKdW7_^e17YL/>U~ 3{,~*tp_v-_W@ߵ>YXU=I~_Gc\%dBaR/Љ/=m@h&_4_N._S+se[ϑiV+eW+/xqs=hMW/q\` _ȠŔ/b_NǞɋ6f1OĄ2/-bW z~^޽uX/ZW<r Y=Y*q|=_G)3]dKȄ2}YUzi_n?{nJ8\׃_x GX]t_4_`puu;=m?- vI_"J$_^cV޽r5xߌ guڶUr3/G|eYЉb8}}:f fISɩӝ};]֝$SfpUv%wl6G2suJ!"yx& xѻ1}9Ѹ}z̤;-&r0t*\Ng:ގR"w6w-SbTJ$ LfK%#I{r6wf}C(u}zO/dW8#LH^zmPl5VND꧕1nH^^{>b<3g}3t4.[N 劙L&Wmc1#ic1#~Ŗp8a)g⼴}"ܼbIޓC2syY]GSĩ<\qci^k?<zʫ/ |I7^ԧL'YI> 'N֥ ?2'y{I` .>Y_. x Ο;e@v.W?dY@v\x_&zt9g/̅`&x .]ԅEBߜ9wgΜ¹'ʵJpY&YNڇLb >b>jZڄ~p`;{yΝ}|ݧOӺN>ǏX,sy3gggsR{uY=g^-E> s\:ϓwE+^Pp8K8}uUC2G>xY,NRx\D\& _NٳG1s?n/^wz<OFww7s> ?/EZ.+N })JWӓDU#D39) ?˾{|$EXf܂yOGAu.X{1P&T^/_| ,e sq5ub Yv\NiV z j9=-H߁}-}h>~'31L+EpNn]Dj^,D$#9%{!;Acǣ[ S>SY,,q%ٳܛ9Q,>LP?>MdZX)[H,{W89ypuELL JJ=} -is{N]Û'_8Wr#uO{cu|B6ppt%Ȝasv;8s,:tDO.R\?| .=7%nI;061wr5ӫDDE%!99(+)E]]NOO:}X ={ztrzy Xb-B=y* (8' 󆭭+vrCjj>1^R@u,r1{Y;;x1)!l|na wüU7lpQ Z 3/`W~ɪX\cOn%=(Ra}lc9"$i?B,$' )6qHLLFNv+jP N9M&[ Kx,I^}o18_i:m2ڞ'.!9~ e {v;x ` g 88;0КO|`!E?@7-t]{s GMG-wƑ@s5ع+nڍ; !8ы~ۏ+5&jC ŗ 0\%: ]Aƥ Ý1[r;\Һ#]Kַ[;ޑ{DG#6"1`; t9FV.>ɳxJt(%m(A Mh͟^֍'prOR+A 0r 88v7gPl g${!<NI1hƞ^eRv-['lf;a]Xo] љhVɓEZY8;}@eKlR^ǪMgU˘bWbcV:d`܃sO8шxfr"bH$c"4lA7ԻO]8JQ\T&iJ]щN:z8Oσxa#zɓrt% 7P|?ZZWl+hpK06x碢G0:D>O_Ow)}Ɇ;ݡ-6oi vmh6d36zb'Xy`?VY{5,]giźՅ^:ua5`a1"kƂ]K` d!hy"s++ ]چs5pBhD&|‘x(D]XB*SE? (FKQ4:Һ6e"!ɥۇ*x([MDQC=CΠ8S` OPkpnGX ݣ;VۉicU ܢa퓃Qpa lSr#ۻOiG񾽴a;ykݻٻkEK+6aXsVXo%V>Xj.!(n4c ,L`9] 0 Xѓ ׄ*8&mLyac)`Kv#&Tx!'}f,XrZ6R2󑔞RatSV4¾f$!(>JُЬFxĖ-v?|RW3'7(>0j`,gX8F 6k* m2o *B8GbvlsF&Cw`bB`plDbv2wu2Y-ؼ}f/ߊMąxf BKF9o NJ>HcHYIXL__.t5g-x'CsA0A3kKAz;"; [hw:61pKIHO(AP` G4V4A߇DʠKN@Q44#8pMGPw46>)p G@J5|Qld5L2AcێA3A' Z?Zo괭X랇M>X 8DfD؅d=*=ԋڃ]̌iH?q\Lh|rlܰvۅ/N\'ޞ5K\1:<_ޔtuQJ\D^eq%kUB} Ͼ{1h2RسwLn&%`g58bc$l 4$77wC8&$$!.)i.*EbFq9{p:{v mGދh;zΔ*#&uOH\|TH-~1 /*C;8g91N1E=0 ^9 #JOcs6Un#Wyb{ St6ه`{6X;c2FGbmM5Bl1fwŻKwc}$f:Fa6_o ޙXdvd}^]L6CE'ys #e 5d MR/gpZ{F+vqޞ0GDZEvf{Ji)#`0D'ϸ˟օq V&c\bb,iX읇~y[ !( B tZl gKl~;6n"ˋi]Jk`-7u9^z{&f؍VX+ ӌ@9_Y;(,RluKAفsFWØT1Rj. h..;Eӂŕmt쓻q+<­neW{)ML!]:y 0.r-_]~! -A9AD"hִ~6IhǮcTFbg)6;F?)$,c 2dY-Jfzm8q̤T(QfvJz-&?F]@qZ#Gq`Zh:9X$β:zFZD^C4͕k_-w=~x~w˓xE QW|  &[7z͑31txZ?fv ܃ZzVL>f.\oo{/~˻݊ɳmlo G0 2|сn.s6ok@嗢[Gw >S S,E-v`}_/+f+Kr9cSZڰ9CȵcVÊ+8 i FxTA+]'OR-}e_ `mIZ-F A=6r^pH?a $V+ҷ %pFIH1ǠP2QIOHa/ЂuXF9ʪPf}:3'hN~/Y({ѕҐw1Z6>&kmmv 5LH&q4~yݟ1fRs+b6w=b7#ug8ҬÐ0m<_-뷙fL ,4VQL ?3ກV[߿>29b"WXז0cc-xũ2t ƌOfH`npMFpK?^'Y} < U]t"2Ra]lo̰jګrx'#n#<*a Oc]]]kDXYYaɒ%Xt) Ύ :vՆ帠L/9 &2ݔ8ug8y uG]vlMZxwǩƽd,]`\w4BY;06xE>q?.Tzg ck s͑gN윹 _i&aْ)-&M,c!w=ޏo[&s9瀴MAX8c޻1f$q갷n8ػTF! ݝlS(>:Q y/ tG#1,*keZ36E7ckVck|Fd-"dT\:bSX{bQ;N5j>s<x3O>X oVu0f]Fi/JM>KFv37?ڌxTh+QZ@k*3}lB:V&:|"p?姰dE_A40IAsPhbd"ʐ ǽL@Hh$74 5ehkC[aZѽ9nƈbǖpl[凢ZHjEm`  (H&w|o)'(FxۭB:%{QVWS͝fHBɺ2%>_`%J#38}˸G|WLZj9NͱM nAeb1ޢOʦ!(BM\o3o6Lwy6}GiSÊ Infx '-4Xtl;MՃ㽒\@YE)ޟ5'B04V[ )V?YZL6z!èI*G1)"tZp"aY9E*v{rѕ]"T;`(˭@c5p>)v`uu-'y1t!~Li#)Aꖊ2Gƈ};I'`;+F}#ǔ%7ф Rc7&M Oki'K.w$J1[u)g5ÝWm^Lݕ !XZ9, 34HHLCX Y8ÃvƬd|cƌ?L5մBM_sRP/Tۃ"tmCq;::(q>ĤX7o&Νɓø╗C`]z5BpDDTQphF}-;t  2 ̭6ݨM)G^x6Ё&+AcmE]cjr#5G%N0UFd!݇6\Z3.~YLFo2n@4KG.҂#qNۉJ0.EtE|$P'Ny@ b_`.t!8CܪNUQs;n{ g&p22"5@^"2İ_ţO>o9)h@kS ғr|ԳL`a9gz Q[IQ OM+ KBk6ax兡4C I74O$iY۳rUVWz?I 9V :CSTV2 {؍„d3A>|-Mh?̦L">̛9EpL{~Rڃ 5)矅 ۇptŔVt%W jxKE[]=jsȑ#A3KjI.T+**h~́X2g fio7;p0 1x3xa7o-<-̝3 o2F0G>rD&_]HCf^!&yҤ`8|H !vg\jسYqYȤHFCU3-<=̒sH3ݱ>0fΚ+3]Sc+JH?X_<<Y\f\*!JN/afE 5(/gE\J>Z^+ W1?d=[`*QHfIR3]Qh(_t{b-~_ľC`2(4FZr WEn^+0 YJ9OrWOd0m<`&'M c8&2L$Jf12D^s^}ML1ؼi-\;6`ެI8@P93w7G,^4Qa$qsTlh֛xDZeoQ~lf7G #^'EBy65hIHΡeid٪ښq+O =u. lbu8BCE O)B\{ßxaؘ=&SV\[R?bjjev@n;&D碔'%>>̧䣺 5 ![qn_YJzr%e7oL2e1Q2>yTi,Ñ )[ZN2~,5GKyrƚc*Ƹ#]ٻܗkIc6wbkD;#0SQST!112GLLҐ iQ&OœO?'S&`Xd>VXX+%(no+V\XQ^N6(BQ^6ҒQP#_yQ-%c*wa?cz<$찢( Ij$'͈'ϭ# ܏ -ѕh61\mc[Ml">ށoy U";n7¢bCbfqJd+9$, cJ oh6q\yU-^yY3٤{ՑwCQRXt^e躙V1ۤUuh+!섲26tUt4`A>`e'fRfG^rvUS1q6Ipʾ=; Cp73@*DD$!j銔fv׿)xDEꑪzL./XByа(˩faYJ*Ct?% WǾں& =S,*u]qC-横1li9vw`F-l0$fԭ]g !1mc;;#yߌo7zS7$3aO}f,5wY16@޶ fPH-Y u6;if/,gp]"2hŤ}0b G~*Xֿ6<&Y&1mM]s{܍\ m;*'eQ>$`.V`eZl-"Yt~c.;;?JobK#ʫÏc̼׌NH?Ǹjňt}T^e)y+K]b|t \[V>9]\Oey3J?M+;jLϣ_h*CK`*v 7<xv)錮StaNr' G^ۍ'g"rɸʧzY2I8l02p 5Zj<]J]M@[;ʘAKJKcO=_2l(˴e&+f^w2?-7o}BR5Sh9d8Dtg>VT|1Y,:m۰q+/Q:#4[J R~A}?l,)ƍos5s[qŒYC-o 7=5=V$*`2qe QOvQ\ xIO{_r)sBSڱ‹A^ j6Rigvr{tiԇP M_3HZ0HӞ<ހL,YZ1ǎw`' TP@ڙY쓸_[oĘocX`.mZ0eX)*0'^ &ZL휜쐡ی[ `#6m`]t#aAx걇Ak~GWaO~{t\ȚItٜXum&Kn$pV_{-ZXj{"@_xSz ,q6xR;y 3`Er괙(5RH{W'rr d;:: D_`͂ ?kV'yZ":8-E@jYsOmeDfboE1=bZ# l e0MQ! VpJu dѼ 04yr3n?Ĭ%%!=3tlձ$+KLjX>͂Y}$KX󸤊TcAm'fv`\̰5 viW^ QL)MfP/pUc? cPCeJLJ3'FBC pn%ˑU Tj偛n w\6 eۑpֻ0j{xf7r )P*U jOWF [ww.>g,,wd+7nPK%Y3%r59d3h3U>g~ Zya˂`evkSA&:,( 1$ON vbo=ǴSXVӃK4cI/(gi$A)4Y%)ғ̤QU[w4ܕ uOC1q$[X=<>v)eaniMXF2r f ߖrƸHO:~XO MYj8tT T+MMIB_8~xcMe4z\YKV{Sg1koa(Y^]ܢoƜxv e6b*3`MFd((k_Th`x <3ǨsS6).N1hHΆ;$BjP%E55u_\ &j,epI@RM9S+՚D)^!#*;ٻ MhUCFSȫ$ t `e >PV)ܷVgGA02.rJM_+z!xg 6%rTO:0X4FM * p!㡭T(tȊg? Y)ajV¬i\L&}ǀ[ndձl֭߈In<9xVoqU1`%)m&_M?{5~~\cnszcԁ@xmP|&=J2q1}z͌H(cAbupmv3a {,͔"$+r؋U>!j0V36XBńK*Jvm;tŽ٣STVwfsr\R@:иJ++[~aYYsbgP;xKӉ|^e^ړO<vlft Duou}6l wOc47od-sR ʘy55mso} ۶m3c͜-7IS1vd(lvEYU=%4.#xmVdVJe\|XAQ*4J&?bU*b(DÝ6oƄAmb;'r$LuF [R%e$H* HWFΛ_l=); ·rȆMrbJD̛͑ldm>H4*SV ;66Jr0>jҗϫS*ʚFdpܪ\W)drat>lMXr\,mXo|`ȡ=>.G=dա|MIW_n &gΚ߱,]PT "91qc:3tCEhe+VaݶpGX\wq ޛ>[6K&Bt\O 6q( YS{̝qXq,gs𢏌IkfPl%8șQeg`cƕS\b@Y, $jxH,9pᙕJfyXО5Y,B28qz [vG`N d$2oD$AƄ% ?H7@JJ1EBfrTJPD{lp1med}@Ueekyuy<-^D|5פI /Ykgxyq6E,5[F5Jk[0,66ʼ| 􅿟׿b8~"&\)~w1f$,XXFu0Iwij/6aɚuʱl&uf;ģ b8jTP@&`LA6M̃|]h /XEXP:ƙ>Z&ZM!|k,|J`nE!# > Vlx-Qǰ؋ `>X\\:956s$ۃo4R3i PajΜCy93f\J6y1f)7H^s-3c2*DSR !5xLK5vv0Y{dK1J$tP=K@s_e%u cyDHJWK_';wks(O$((^fYLx͌ضVi?rXl`/pv( Q8EdJCت~)(L*I)f.pqNeDWS2nvğ=öD<̞)Kx/ch`/.~!Z+:H-g9G.6Gq|=i|D#N8eHY-@xV {ui%L8/uB2C- l pcՈliBhY7pL]R@H^0u7cMvIYxe"=U*5n m;mVg3f@o~2ꜫXw+nIc&ՆO$%;q#UQIOO7#]F|-nsk eìKB챃W^M+1ُɶEI4ge"`r,Ԉ6-]X91T\ol o"s9+5M [-R'cK<k^ŝGM!fjp/]U|'ϸ Ga޺xd^al0 a.ң Jcb2u0\(s?wR6>mIf]5,g٫JRbJdkJa-ukzRf^)XqI {)܌%IGj!tnsg 1:+|,}X/W7/cI*:"9U#vK. le{?due!.R壍 5O{ќn`)@)1ο0*FTȣ7'\]Z!1k\s1KpNRARƫ1YJND|&s[0Vi1`&Q~'x}+j0סtK8ҍ}>)GV[ڵ>=EscƶTyv0݁$9-x9r!dUXe֑"mrYH?j$7ΌL@'LS vV禍DV^k #1e"Nsa}}L CgCU L7\K17k~n&ȣOpuqF'Kq$('EW^\*8˕ENl0iwD"5.ZI#=RQ|0[ЦҲ 8qܣK($աE[*b^+%N9ͻ_tàwҩ-pu2Ϭ<ONڱƷKݪܹYX~rm!N.[mܗ^]sU7ߛfh#+WKM}=ͣ\&9nǞ#Ͼpf`{JLolULW} ?O{ְ9S \.mxw8?ǜ MP8)Lf1Trr[YkzǍ_lE8;ntsZJ2zJ"P H3ffi%沈 %GLd kn?|d9U30:#boRC+ccm!ܩ{`"Lk}U]];l /Hy~(#6tpe{ 5!pL5j2|rQVq=X|4 IH]d tUM.Y3,4Z[u_}P8Up^|c,^~cQĞz)ZT|\4~dwMQlb#٩;^yo;kS( D+w8e,ԆVXG{ a%η#H$.*QWJ潖U` W^k%Ȃ:i4uR[2oƃO2bBUUC |v d f(ni"5u3O#x}X+q=ƽ7 ^yTRJtȠ:z|_XI 2;60c,ES,?V<{1}\7F,9ti(E{)L燽`f[|}Xr#O-ZF~¬W<[qIR&Z) :يdQT8PYǞzISߟmā:ЄI\)yҝ?|pr2@% IR.O3KR%3zuO)6$)`DIȊlwzIkbÏfq0U-DMUVQr:*a"ZEџvssdvGlg{v{\$11aϵ'ՖsxFsU(c2Wi9-KԶa&bFBfҏⰽ<"J"1+_'-RK?fWmC|k<&nӝ'uO9N.<=6[*f-SWοQ*@^nQH~<"9$8"L_}@Љ4l΢kEa˂@))2%<**؂$0vg7(Α.Ľ?)"Rn靔P@6K+kV,̴bAZ@XXNu۷ۛKYH04FuE.&8"B.CNB5K%l"{ؓ߻`C ~\әVqu|z3P{z()Ն~)͔yw.c۩>{2jL8q,]rDdr^{ijЊ3o8YjzЋ=!R]6Ɗ)skLI>Z.Y9O 8]%rAಞgL}r_֍!lt$Tv/]k6lVp/; nZ.HI<k&!Mr>|D*Ȭ='{FfV谳&1,MQ_,pyHITg/2YJD:):YU`R%X w(n>Zi{Mr~cmJ=̦u IVLZX2M@&ɭ;" $J{MIGЏAz{Y/TP"Suak&c)**8Jq,W,U+WP|[(/@7S2? K7yʙ-k)|^[f#AȅyURTʣj""}\pyLXzr(S=9>%v|s r>! 8drIs1lr2ಧJBܗ| ̋41n X˝P Nj̜=n3Ͻ_Z\j&)ʂ))P\٧4Q~O9;65'L5#50e&^djT?Ayҵ1k"Sn͌-S~aHbV8Iڮs=f۹CTe)V&)`x-D"q^^bBMYխ|@qb\č d](. 5]ճ3Hkzb]}Lg" @ψ^? ؼm;ۛV$CjλlŦpZHP:frضn6/]`~Sd[n):Irtba_oenml\*wZ~%# ),T֦¯ G\h ;y7<O8j weqE6Zi>nBC5_=qf>?~&WIl{ <`PexIƸGJ,ܥˍf9K:Z\?f\O65G-zT,%@jE[P%plzKQ䜫!} 8l>s٬|`ZPs="G0g`غeP@`cS"*E uo΅6L{vsiF1T3HI5iBB)IV|EX_ۛ66MQ)|ZΟbJFr1oE.5UJ:CVǓ #:77`D ߬3EM5ȼ*ٱۀKThڟJN*׾ ~_1XH+EI*U-Ah!dvu4+i5Y"w5b.ŒG TR*6$\E7_)$*BSe1-*WvMuIY.ɶ{]''?/>.p弇,lSk#*~KTG:`g0ynRmx( } -9 &W,]EWX6n\@dE 2P"Ó8=VTO8Q:P* U]R|umܶ K1_?5(=!רQU8y6-6CS,YEERk򍓙47GU\^i[Y"/Zgj鰗_Ì {7Q;E (j>/ZϤP]mQ*`Ɏ!2nůe\LEQ$~Lx1KV[e"݊W̥xK{TܥlQ@: X"p/`Z9griSΟCeCXCr99r5#x~ē1׳2 A. ?Dž"x\ ;Gtfbl²ib 5-X7ޙ{X9{9c?# fmZY#sDFyx<)$Qn#zЪe;gcpL"!d* x-្%Q%A$= ko"UP̵{7@"744Ouꋖ~2}ֿXyRzE;l^›+20̀slɫOF־=m}I9,z?+7P$r f|EYס`dpnwBĄx0v`]ݚmCNfjp9Kb8%7_HNN1#BnΕ 'r S8t%eyZJ2.b46TrjT_VS3Lq'W/qpJT=aV>QÍWuMmkeTHger{.ڷk%UQS'{Iu4g7g\lr&-K.fgT@"Yn4qe#3ŕ 3ƒ=9oW!$y 9O{@둻(\~-"\(Qm7-"1PZʞ]CGqHp\8މӣr* >dkXO@&ICc'j|f߅Da O~s(Baj;F2k7X86/~E hlɯǍ.JLMCay`@UĻo{c'cXI-0+`U5ojB^nQVNⲇ{X$^ [ d^iy W~?>RB YiB4(XRj]՞'JVHKn2RKl:’57#=+4K).L{b^H.ɝ|L=t39©Crhqh3`ٸVq6<1?B;)G22%v =ad7pخ |v۠3 .qj'{ y B:4ʮ2ɔWdIag̡'s bBVlVSZc}-*d+ŒE!ZB;M,zRO1׼L_]g@Ի))1lT &ͽLS(^쾲b+ՒGj9fٛty%[OJyKvcDP(@t PGa"5^$'}rox0F%>ld0YmbT L|߻ S OkspX< AJ5-xUl>VOmf='pVĭn>hNok%T!LߏQOF08h-kp\T ##D,'hD{h%.69i7I$=KCS/*B덷)7hklNY-vj*6_f]Few)ޒkMVLN̿:`r#ɳ`(c3Fk @vpQQKaћ+8ėkwK@ ~Z9=)2'u`XWB ;>l/vD8 ƾ9mє \!)6eb0iɕaiՌꩯR{v+_Y+W|c#xCuq6fZT3njKzI`:ŕ-^ w { /D4ul \3 [2T~J&dtq]ȋHT&PnQ-kb.)j.*iۖϒ<拂 VzX:! YDyoYA aÀV3c _Xܲf+B ͚^.r̼`Y\rmw6/e\]dY,HWĭcp %phĉ%V\,X3!#vǕFtIe2z_Ęe-GOpQN2ۙtX} a^mt*]*)QJI-JJKQ% ,Z!y \8{'ORWMue$39&!e= .~Pf<E5щ\ !+qAtTS՜+Cj9$,\ʺQ^B@fsCoƋ|=y,#QʭqD?a]<n1[ 5.J(mQ|>tYJW]1X"Qċq֞.}.VEChS8Mb`/o;pd)tmcqYb9Y;Y>%".*sʅ4KnSl( Y: W ?Ww%J͆y6AbZ.~Zye5 ?}&O; ȡH!?NIa6ѿup 1H ~Bx"|$ (^FD#$ yT,-'8k(O|m cͿiRuj̞("S9+ƾ6oQ/[nՑjS@_3)Z(c bELp/KKQ|%'ToO*|Egb\Y:HYL@',RU1:T"R(ܢ~QoSY8WZ},`_mL #]U?Pwpn3G;P' WWOEi)ȶ2MޝlۣX JFxZI쯴I`&!hPd'L". `OF2[٘0NҡYkp>&*  O{/~Fn,S%8ӝY-@}9 \Hξ7XL6zxHMh zkfi&K3.ilbm_)撥œJV eiU[%zN=xO[Mwi憚>4LNK_wuC e4dE?n&wf`gH*jI.<,mZ`VV+?sMe"OYiިmi?P2L 2WQmc65#CԔdeSB-}2$BHM9SDfMbp3/OC2/%ߴqܨ' ؚ#$5ӵa/ۚSZ"t{8N>Fڭ%5-dj͢{\&;vigq9nNz̀AŒVÈm8 ϲrO]"(:9iAZ hZ~5aClڐ{(#@`4B`"K4X#}/RIG4KmP=kLe,ʹP;n,9VT!{ŌkA-.CR͠6{oP:/- 2-"OqݽqEȌ+'ߥ1Gͽ7w\{寘@պmIKasI%gLňḑeurXϝN(˝.46s0K]3L" k%+}']9T""W'k]@e5P`V6)@ʊ{y3DX(gؒ)%n ~Ifqsa9Wky^GcىQsFykJiFPuXC9d#) !Lt$3P,+)i< 5#M=pݚ5j*A$_cj>ep[Ô_0s52 @=;m. g&B73=ƑZhq0$ AXKK .n W&>1ca\\4nF' CS|`<5?2]C8ԑ\{xrLh9kPN>fMqXhѹ;Km\@" ;ʲfBz] &m]p͝YYĨjoI(8-7(tbPH&RC1,@K*-G,Y8we&^B;%:BEo$"㋜~i$Mb>e,5J>|e`_aH%S/XbM(vhp^`KVK[34KtG úT\a#3^ "i#(fЬc9.@MR L 8/8-iJ`jUQ\} 5cy(|"W/K RMKCe"ё±錻Db+)V3ɾ+(>+1f9.p0;Dn=q$s1ZfT-*'-'/K,Δoeie.;q&Ljak{2^PԪ&`i9oQ =-|n2Y>Es%աEsDDL|\FCI$ KܝTj%S%wGE#p+.uV&%W.JCFzz , \]} 11~GWqYпLLn&g=J;^oJ^Y¯RT6G<+a$fNdKv%1X[®E`-+eO !gQ &R $šR84er&8eLYJeʫ~EKEgNXtmr0^T&ZB4\4Y0e&pi,.}\Կ>`W?y/`}L*ɚiIPQ[.wCV \%"6&S{^E''VIEl#awܤJNұGG&C`ҞK@euD{(!+Y,ڑr"MAKUYsT+Fdԉ-Z:eVtFmbOMm*,œYT[T(@pYvJYn@5}2eY)8C ڢVJP+r@__O<4';3CnY&-ꠌqJ)[X$#>EH'(VR'ףʂ( S|loYPVQEs%Ũ{&BQR Y, Z*X͕_hR|&NC?T Q(p-zю \`&e~&46${֭dVSc tE=ttqҊ'ib5~TT;?JaY#&d$h09v(v_Sk2=%L?7`].4®K@럹OsdAQJj+AK(2UdG5^WG}o ?}ځ~aEi譮nrו/b-}^C*Kѡy'@W*dAt*^Mz*sɖC5>j"e꺎qhA"k[~,{StեL6'" $?Z*dhl%,j+7!I $PI& Y% kM=FCʁj\=Fo)k[Ie2lӁ<lj";ˡc9>=2?O{3:ir5L 4)E4I-@%ZgGP.XkTd},8 jYjWYbO|_ߟTb@S[5?_c-֬rZA#FrjS>& iEL i(K,E4,'U,듀^cا+TO(+%%@٥VP2LX!{Nן4.Ϻ,B_tOQ 엷05 N;G)F% RS}P*K|%k,TSX/X<ڕX,ZӘnJNMvNC4eՁǿ`W0?5_b+ 8|IENDB`PK !3tjjword/media/image12.pngPNG  IHDRIsRGBgAMA a pHYsodjPIDATx^UյQQQA`F_/K'//1B0~g̽1FEŮ (ذ!Hg瞙Aط9gko hfZ'bEѶ:ZritGVx<[׬5̧%M7%2rf-|3VRˆsRTYRi/ʪ6LCs{oduNm_em+`btִ#/Bd#3J>uhyu.yrt^op[cnZ#e?|FK iuolEt޵wr(/bsh9Mi_#o>~ !uJU֢Uk{߱ښZ d; '`]6l;oAnFnE䟌[p>u,mz]Rf9Xi۔PuAqe0V9frzu /&[ux+m79WnY3%a9Cqy*’ʈ!ǝ=WPOtn@F5G4KYC4KP-}>yZV6T+:rcoFB$樈d<“[p>5%2~ng[~QzeŞq_|Ī~i9GXa7a~dӬ8밵?ǝ>ˋf'm1GZƄ#($0xpy-t芬/ӹwaFZ=| J6<]ߑhs/ȷk֦$myko{u@9;jc2fUx!VxVwU Inuc 0f_rε,?P+Ib9 .i-~aH>@+yV7pVw5mU'fV2@ˋA;̲0LW?|:k^&74.Ov]޶uo{=P'l䋫n3 -p=vG.-8q]|Q:v9q[ݤ&~CƄx$cu {1U)OC!X( e,{\Ymf/feqì2q?M?IrZU ׄk|nUpھ\-2E [y-q0;,{?W "grh_)?O;PTYuUZݥĞ47mӟ.,? ăcr|(ݕq#co8>U1{%U$63˞$"BkOkV̼*Y aO,jg+NbR6[kΪo5[}VUM' 2M߂2IC-ca5^;V'+s!ee]=^jݯ^ix;5c-ߴ[9kզmA,{#cMwYx۵q^^?e5(V(|XUq\څ?OQUgXKaQ;1ec?&m؝߫BrʻN[ߨcPf5qXͤ:aAwqCwiY[(4{0=_އ :rUWI#-.2DUVEIeI{3\0 T+?ڪ[MV<;hODwRg2\d|v˕=P=1%wM)<Ú>{k<*2~iiÐC-3}>N a{[ GEndٔzo= [8Eݻ~;8EJDaSvqj5XmV,sܾV}uC-]bB[m[_۲^Q&+Ey#[0IDK8w8?~UaO&bvEvqCw'J0~_X K)>y}/mPw,,/m822c-gӧbMҔ}kHQ`{_eN((n +hxPneJ}+16 0io˝ò&;͵DmZ퍺ueɘ-͍lV!YªVcˏVU4S .$LK~~[T ۗВ'KQW}oܴN&D.(B{(Hi2+˥|J6 r=T^c:DZ(Wz.VE',+0NLMWreҺ HZnjF.(A&a*eWۣBAw} a' l:DfgQ,^9:빮lVe Y_cMG8XGYy@+a㡛Uִ*l ZN8c,l+N;р],8 +I fG+`n7)Oeo=v)PTUe<{dBeJ)X>5%N:]SQc(cpwZP"wRFTʸSL7n~5(3K?6cy܁V_3~)秎@pb \3X +~]~;>aՍ=otk5 '.amw=-ƭN8Њ'Bf魜YUg]ZƲ]6P8M3+R-Cd!A֐2c]BH)I(mqv**FWRεGm&dlcݪPE*Li oS~jDQ߱_Z!JZ:, چEm^l ^fc[ֹʗçc!'(jP$"ܨZ'5(mńT\!CCֶhcWWPMAX钏YQq,cAo~>U(Fr⁞ 돽b=E^["Xd`CqΧZW2&Eu_箘q&):*2 SFBMDQ[4n^8Ui"27Dʑcw+i;*%|C1jsq\[YKcw"Q݁ V.](*VC^@Sg"k*lD+ "UAj"r #XՄj<v+AWqcgd>28囨1"ф"kX=DzņA\m ߢOr[ G< +Icv?OC~<׏I5dae*#Xi L-ܼ=u{w20] 6v:fg]rv]?ڙꎑBhRsq SnR\d=Q"뼦nxU/YSW\{ʌEMTq!V;[ɣ\"0NP+K>~Gm|{J١ v i21=$%/[KvQ֩:qgB%;Fd'{/H\0e%0 LߞQVA>X.4VL[ڿ,zeL|I!V2qA p!iVѤbV쨃~.D[TϚJQ_`8բ2@AĸA9+DP@kZkx 4+W]|\VmRʸyBVơ֐,~479nh{v/B1fZE0  4.[VDD?G}2:ш5;ЄG/m;!(&'KLp %[Tkl-+=g%YF )T,j3Ս3i6`iY,p M$-J)`<{ +xfQ qVvBr)bܼG6lGrQ1Y9"tIҹ[},~^{XʹX)%ow9su~ك!-N<j)g3Bp󦣔Zy奞D'\ع\h*VÍ+K?R& H?; d"ژz@zxή}֮pşnG+}DQPѲːÙSmG[gْwesٲؒ9wM/޿׾`\ޣ'IsE_Ob;O#σŖ|͖͘a+gL3_f|V|VzVxa&5dS޴_ZA)@0=\儩ǯoϸkw-^[Ǹ|d[-OkJȮş\F3 ki'C*flvU 2]yN&b4@.\ЦԪvc=ꅘW+&pc/98|5BVU|f5\WJVtCVwU2vEF|GV,盛{/g1\d`9;FvO #FZ>_Q垶Rլb=,ji,xf Yh`h[ָu[9%[9[oL>[fdYՂNJ9|*/|hZ I\T.>v a-i1ZdMIV)VG_1u~*sA SOSP 32PC}j*EQ,Go+ TP@JXBCwFcY_+mc KwF(`|Z,=g'?{Yf8׶3K_nK%ΜPU;qiBYˆқ*Ž/#@/{7_s"l&o뚬HrIԜ2L16;O㷖6v1̗m.8eu&='|L\mB"IQ)KJT q,@]|HӿO}z%v]O,{M6Jd/D ]_߹[NQeMxSڿ*cQT󻥨΢BibY!{T3v?4`楰}lWRRLlXZj6+N~7UR\\;.+y)IఌVe\qSؔ]@v([SYG>ƠN}telCbOl|E:WTQHQ+q7U!*-RTb(kfQZ*N:aI[ V5nK(Ƴ Y8EQ4 b YQخܲ/5Q+WU(AՃ*zW@R\E0weK G.΂揦^-E㈓""ZT2u(YE%9dn:ʺp7SEЕʐAUʱvϩb7rڣwø7+Vp,+BM5-MTu"*lWҾ++?Tk|'կ)W,)'шJ `M`u Nr2]Rr"Xfؕ gYAO(4Z`gq!F˾@'uqc76> TW: Z jI|Yܵedy#TNt|4qc M OmS¯qQѿbxV=}G6S |nCN=t0u9+?l{ ,k4 8(ZSnmͯ2?~SQg5m'PP_H&EDJB$`FӧraK qV2!k{a%썩kەp\ *we3%_KQ{.ZKFЭ( Wz<.]4I2s#;un/-E{8on)}x%as!ma<؊iku[uwE&V)Q+NQBiQ]{g^=`~ P{]+$lCO+&r~_u]ޟˢ|QBqRmSTYT^y>z@\iJ!]*:TzY#>v라_ZR="dZG$|pd;nfs#EPîq#,kC,T&cn~z%NP")N^4+Q)*iIDɇ~cF!ҤZ'%o,:U3'.Z!S}uQR&׺ @p}U͜rQ9܈M PSBl!RDaRJjjB$%URxdocTF9N_Gw(FC+nK:82Lݹ[(@'5(*FW ]+ǕSuwEXs\(ZE{`O0gSz=c^_kJPحyOZXLk~=ʶ9u% V^u!aUlT/TM f ;u GK87 v ܳ6ۚfo1f -ԷK/JFNΏ[ -:pR-NuF j!]žgaHA+@EUı=:1 BYKԿW|v/X#I9Qm2Ҿv}= #U>cXYjV մUp C`,X'<%:'yb,p=SJ ك/K4hmFZ M{>{nζ1C (\ wq'voԠh}n>OUVJXTXq<;( <`NQ (L ~[v-E p~x0ϣ'6C}{٢o߽Pb΃|lgӷ`VՅ)eڣߗ!]nجM<Qֹ5W?eZJQb iO5љѨHG \Er}9zE)|v7ہ_B9 %7=*VzQGAM,[C k ^ 'hlo8TQGg`;([s3K#kMK9VpS_dt, TJe~8N=Eݕ!\wA KOoTP:^QDŽH%>w\3u6Ͳώ8@C{@=Υ_TkVXKN`ՙl֋7wE3ocqoCnOfbϾޛ}%{IV,}f#MV.~V̛ kMk;QwBǢhVJ4Ҙş} t;L#-Q+jENЦIo E2 P5NHmWUQ!l.:1ŹFޱ/xV|e/xň(=K^׼-_-ceXi?xtae;0pz{lޜ[lܩ6[0jQϢ2z vm5{%4'~L0n HJNA~h'Z!䂌gJ~ƢZEiu{)8{)cV[ҢYM!M;vI0Ӟ}} {)]=t3#PB פZ]]K%.$W$/K8| Цe<=_uXL)/rIC OʒSl95PooYm!m Ewq:oSO*8𓋋.BR$zssQZ17Ve[sBF\:iI;QQ,f=sຕr4wb[o޺_HtN)؊nbbD!|mTW5ȍ>ÁߝlJq7yGTg}<~lMIGY #0UaWK *UA<]!P-c5J÷pL,*G-~9_Q4))SOQ)lI& g%7ͱS*V:kڻ`#l 1WUS:X=dɬrS&dC[7ɣ[<6P;*Z67P\|Y:F(#8դ(q"ҹv"*"='"}R V8oH^W@EGtECia$nM~-g,+MEun΢zZw%5;瞛1V}%5n$ i͘pS1,6O#MVHsD U`s*^#g.QGjj)Io U4 /zldQE7)UC(%u #~D0MH:÷["b`َ!Ǘ* ](*X2&u, Z*cwdv&u!i4|+V}.\U17@9^ JlJ0G͋}MˉJD/>FHcDe)GOʢh'mx(%s>47ůu.4XQb8z Iᓊ')s8"8Ę]-Ҭ-\]#:2aY)u(jwU873ГXXMʰPXZihHgA`q8aj鲪lj"=U0nA6Sn4Q_olT+E呅 āW%s#HP=G=8kHVYHݕ,~ c },_3~(꼙m4:h8  조|Ǎgo3z]-z7u Wmt쌲%1{Y |1 ׅF:6̀RW!EKRu+Q3]H>YEt3{UhcZEB ;:b`6l0 7u9 A犰]Q7B1h(U" K-aW QI kBh)*TjVYT.fsV҂ B[ܮ.#~u롨}+!kUAkLi5\J-O9-* I2VTm=E S q.~*sOB"ס0ҿE-$O.E-Mj׆踱#zQ9~ERThEb.ȆWV)j|,#TvELE XK;bOr>jg-s̖n闢G%?AZ>-qY_XA;E=6DmWԭEQ6SQˈRWJԴ+Aţf^KElJ_sT Ze `SlQ%_[ n ߆SUts8Ue ؇SnHXkU ȆOk*+A3OxZdvQ7>eV̶/f> ҟ^ω~Ϯ̔vB.RY/o ??Q^_!b+h҈RXgQTqܠ?N!gMN0UmJxroԤXԜaW|{fjhA) ƗʹK+-rBKДSTZ:A~kDQ  _ 69gٲwIwm/?vrOm#whJ=8v~jϕG`~>`u*FG8QGWq]5ӈCZӶ|ŃK_էp(/R"m*_WIQg#"ZJxM ?yoM#L50m\Oї.ܪg6З`L ,eļI.%[]xPZTicRt5 <4@b5d';.Å| |aZҤuX:6'*1B-.2jr &nWMBeG)K8?)v6EQ+ȤyjvөZ&c?*}!a '\eאq%2-G >'Ucu̡7*+$j /"c%)ayO"pΧjˇNғ RUB +)0ϔD=!#Ba (~++HNx:*)?.2[$9rFS !-XD(j8Ɣ~D;K'xh'"!3GIF1l\m'5X4<{ J?Uf9dUyޣ!jj(U EOW<[ "@V#qyQ◽ p@X(J [Q=m %JL$ ORY*!S7ownWN??k:Aĸ^o7FAXQx.JU"ZymНB\bnB蕊nBy #~qTPTg5B_x-a+L=#2=9|9 *i}F'z#]^),ˁ!GGrL|ܞe R*R4Ye_G!@UR_Im YE_Z n>Tzk gQ'V.r5p 'Mԥl|L&+y%бGDWTϾbf;Y:f}wYujDpV* Kl8 [yHxii10*مHM| L~m;lIH$%DOs_? 1ь8'6v)'C{{IޮI_G.Jl~#JC<^SK #/P8"z. Hإ`)mˈVDdgsӊ"s[,O`N6YrP=^'v+80±;M`ǥ33gl;7;f]JZʼṡ1f?I!J[\21o} )x4sCVQÉ6iSRTV{ȗ2 -@x;"hIa\WC4VDZ˱"xCzMqrXr}޿Y1޵nγI'S8K*T`*.'h5oTez͟Gֿ*ZJ*W7\cd(bhW%EU@cdZZbrNt쁏seT&ɇtAy4mFҠ )6"ʠHwփ.T ).MSj޾v  ?u=*mqs!9o=uG2[ODQ]7UZ휢 ˅yH)veG}5/UxmxDA=`ys:=U걒woTTҧ*%6-M ohRF_*sEf>Qѥ$V 6eP}빮|sW6Q*r`MYaBIQLD ,p 4Uot-nsͲO캊YTnk,S0iZjtlg|ՊuAҍ_ǒnW~HEʿSS"Э8g\6w` 05_[J]y9/O]K:VTo%.R܀񻰛ߋ`#cz'9++DVuO?r׺.w+J!tSp[vxWRwjhutY^^Nj"!|ʛ7GSiYTw.+B(=cJ|17s7hu@ɱ)i8Zhݢ"GEU0{ nvñmU'zî ;E+k "cG +jWլcrfBQUHF \}ƙtj{nζI!{.RV)lHY7o>gT˥F /"MyM$ឰ[/@TAՃ2"e$΢*~E<"bS%H4 ɲ~)Oē*> RW+ӆjJQ7fMT<*nZ~v.,o5DPP8rEE{"8,Վ.%=ɺ+ڼarJQTϺKQVx :?>|A@m'B;0tG|Rrqcʺqs(2JOQ>L˗'R 7%>(iɨ~ ٴyWjTE )S kQL>pG6_Qo*,F4zi2T8'瓍5:מ?1f7ۗuRZğ|Ilh;a7d^)sB)d<_QPWzTFW;fZfe;'fsɋHҡǕiyH?z%O#Iۮ|jX5FBv.3[Qi W,+\&j"Q9x* "pYmԜ& *VhOoYzNQ]L b Qu:vNѯ#(IvEbkP.E,9{&%w_`EWT]lK[X(RZPZvmqEr@]q"$?PuPz* 0hukPT8瘧~S.\k54-#E-Z}zR?/]O~a܀@U:vH4ߝwTw|T?,*Ǫ~ih:2%P)~k~sOJ ͠kvSofhsMl^R^?)PNQGGͅӴkHO:w5R4g'P2,vQu؀Q#A~c)j=x ۋ"lbXV¦O^+V`Q}<ϲ&Ra8EeC"S 2єJ`qe^9.+9CҭKU8N:z=BmcIJRk}.6)bFo]TG-eSoɶ4Ċ M('7łn~6EHj`~Z$lb訠zjt^]ı{}>M=Q(Ǩ^e۝, ca?x*9WMq IX-&BݯPS"?RZn=N؞˿Ұe鼎]K{1Yvk?>_Q'ے7v=ͺR' l' 3^e!<|SGn76V>?jMϏ7E~C썧9^TqP YWZްH%淵B-ٙJTII໖:!!7:6G_/!YM' i烒t]wBʟ Kxd2t:o]o_Fԍ~Hنz74}]j0u,'QH&NBW.Դ]}]~R$$z?R}jYn0os~JvU`VMƕ8U('r0vw|j# oEB|} k[lgy= nT7m ,笣YVlNa LS5>u i/~*Ҕ5D)qϕ_~ $ uMT%!JLaYPoY.KsN#6v'أחz([o-?pf[2~M&cקr9a;VH7hΫ⯭YOup5kZ&Ll [\JPTVѧt.s\m wμ( ruk ?%sa@ҸhIQeڕ`)Rzw4{ȗBҧEEJLqyTcflzepKCABBCB`0WcU pWTgOH (ҘѮ\O.}/r&zt[}CI1,0uk]FQK!ĖAH):]]QURXL<}S_8ըwC;?p&8 EaQac^A O]JRaQ:v DM>'osJ1OyE0ǖ:"PXn> xe8J},`%Ɇ*r8%8'q'Lm+VA bٔ'=ˡ lx*%)SBc!J+v[@ uį2Jkswa!$?B=&3&VeBP'_b_}0 $&n$P$ï2O,-$/z;OO q@f?p5fߤ))j M4W-k3^fu}2[Y7G3_corUW۫\a/=~xؔM_}=Tګ>N*:zF^x솿gؔ8k(oWOɱ7Q:Z#lk^WnV֓QXvoF\Ϛz$ N]h8XmQZ@L )O 7+ 4镧 v,4EGMʹ,*mmZ cv͹vek > /:M.>!xr{=O=?ڦ?2^{aCCuN?^"{Kl thK|䣗iOޟ~zN[AUHKQlsZ"RYJ& B6XñiFxo ,Z26OXlcB|# 27JZ /rGxиXǥj6l wWo'o=l M*A͍mRh5 dh1Ɖ6qWB׹cpLϑqC]Dg']m52pn-VF&ofBVlrJtO3SbulfxF[ēʏ6X}M'WpdC7cPkgc(U߄RCʊpMG|}>jҷm 3xe5!H;M!kF7 ׼T])S85&L7,ڞ~Mװyl\!k|]W1l@66ҥuEʩզ; ]s:=gMv |ԅ鲱pH& *O:#qٕ!|T!*8*GOdJCSmrFeJW#vxBէ[C)y|5rRzէv5DtX;;hG{5Uz08Ls{S箿EHkA@.b"vB^gU+%qx׍Mwj3!!OFd`(bܑ07g5u~/N|* ),cԖGz8AYv{hvO&Gr~m_w NupoHuCM*Yb %QZGS`m%+ q,;V.ɚO'p8fzs3M;P* `׹}Ezee0.Su}c|QiwWf\w8&ڟ2FtUn"IREz(rmj.~0zH[ZD{K2,`7 UDW%[Ӓ:,(p_eEYkPR Ez;/.#(ؚ;VK ڬdRu1>*VX¹ {5M(j"< `6)WʺdR# ʣ5/|-ǥ~Gw6|sұWATUcrt퇰>5z(KLE;VB Q@e.ˤZ?kjT\6rE!om(R=  sNJ'~Q0Y tfƪ,(dtb*2KPRAnulODjh2\:Mߒp,am[twK)>}ΉE%r-7uk]7_tx]s. Bg:HU5kxzJ8(>:@.?U' Z_uNʵSE R=; dWح5FGh{nG=}]o*Aɯoa,F:L%.o[@5Ӛ$@eGB~2K2 ÔQk_%XJBc޹{>EoyEUM7k#t @%^& }*zS`'`{-'3nG`i6EFTm<ߣGI *>GKbKrT\^Qr]ea]HcG%Ju&&~]^_J"s<))8EJJ[`)aRTemV.HB~"nuK=t\].b~;{bBJ.Bf&eW_D-sm3:*ҦFwJ{6Ҫu1Z( Z个ަf_Y,^ w8J>gkS5YpJI@<*-|7ףw_&ΜOl4 i>YH5ݤUNugނ)~YƲËFy. p}iq+W@e1-'Dˍ*Wѕ(w)kJԷIۂF)iȇII١j ڱi~dm ^>w~2S _4TE{ %._iTYSR !$D$"d` rueEy?\ =ЍIvWu)S6UU*Dv_ Z~. AJF`d2{ZzpzíUWܷF ^{(E]hI9øGrO\HWRTݥly2WTUuJJO2~Q;d "2vp~k՜c >x"jbE۵_nY6[n)ہF[ql?'Ks`azXJm"I}rP-8'>wܖ'THJcӮߗu% MSQgFZ=[lUI˼OF޲% $)er뫒#/p˦q[E-,KAmyFK+‡tnҌmU$@Y!]ݿVfUV[h'EjZxma'B/+r$E=HgK(?6|QxJ][G>gIcd));XP)*L>Na@VA;:Ir3UVF-Ԥ,~WFp+;YJ~(h״4;KT&~)j#J* {Q]hd^xBǸny?--sUl*SPEpUL> z˔ʵ>QMє?aWL$(+ h=ZTBiu2 "b9Isqy0MBH(S S[/I#=i/cZ{ `$͓gI;mlzZEꂮ|SY u[؇ X,m`K/XLN s LWȗBwB%$}Pp5j_Hŋ6,GU s_F,u d>0Ksqe(aU%*Tswq?;SEܰ/߷kn$/gTG4. 8-^ n_B@Wh( je♼HYA ˶`Q zEDBh3}?Z~&.+^t4~^ ; ݒ}cǦylGT;סOVՉ5cTGKȆkB/ىmJ+uo^T(op#&CtUcSp}V*~M;.t涆ISN]",wP֬7ݩ?kc\Lp!ETFz'Unf&ڦJ_|M4ߊ0(rx2dqe Ti]%C"rzhn/knoA@Ka~+ܕR4dVXChEkfdrکXmlZ2am`Tײ ØhjTAʯ\6XջJҶT67iToժ5xh":x@u 6"^JBs{xUn-yKZu<_<vsŸHĮpzp\Wdƛ|=Nt> 5V"RT= M$]_حG\БpX{(4a#҈Z8~hvKZhZQ:=nػE']wM[metFGduw6@W%SyLu؂cǶ}p<`SmDO%)VV^U(\CQ/4@%B~ǞIENDB`PK!sΖG7word/media/image10.emf}M+I^uwU{10wyy˻*01xs/,0cd,ZE{!Fx3~ma0 F`ͪU9Jqs"#$t*ҍJEF9'"3#_t:O?7oNEov>rmw[//'+οK;noWr ߺG~{η^|7:?svnW?~;??~7>;Lrߋܹ"Mϋ)>ilm|?M2͖n'.w>sy{s 2SJB}Y X\V e@I{vb]<[4K̼5Xi}ޗ>}Tfzn\%},WA}^y휆3Փqy/#}yo<ςp'vp췛q{.i~eQN,|ney_EE~7}F5_,~{佬_7\Vy}w޻r>s%{cbKaa`Sh?0o}&S}3g!$e$Ϝ; ʼǿu$/"?<=;lv>Da=ޘCt{<%Y^F:?uY_8'5>OjnӏwdllB=aI òGA&]0)͛Т2Q[l~C0׏tX@P m H;<âYI=Wj)*Zo M_ЀDTD"hc:E8,B//V3)ETBw )6VB܊BaeUBV4GPBMhI4PCe̯d)Ogd &!˥,YR4tT|U///6rhM#iy:V1HdJ✾,X8JMB{BPs( cASf=NY!?rnnP=Y'.4&|)Y:&E@B_4](윧/JUR cʘ*qtZ) ‹ q諫+*,eVeJUv+xs-u# Dq`MT^({^EhCꋆ@ĸ- ),qTNR$pQr>`ij"Ѩ,̒ի[|x,OQ(ئ*d1ET&WՆMs?l-# dČD\Pr>w8,K&_]T$cQw ^zT. !>1,,R2ȟNw*7H!n F(}ի ohTD.}rଣi NuT0CV,EZӄ1 տ>6ΫL)rۤÏbP*˂ JO|j@e -a^_OqZ8]9JLA|nn4†bKomU*)žBTes2dMOA?CǨPbvu4ɩLʦr7El'ӳG ^e d#Tj.,(eJEpu!)wKhJYl::v[Y)T_'RR,@h W$&Yq~eca82]W`(eJz G6%C/~8Xډnv<%F_+SUW%)YVe/| E\^oar@FWlô95T{^SfU~K'gW$_&Yw+䣃Jx.JYS)[2}NJ*(b+=1[c%xv3KO)NE]4]OdZULC6)W0 # 8R@&_hpfB),: +)%wJ*g:k7dE|<+N'M˵c5bl(,JY/gIQ(g6DĢqh˧8'TC <y,j S1qظ%Ǫ -t%;;>B]JU/X5QyV/[>]F.u}|9B劲]yU俨(\Fpa|,ԮǶ DԭjZ>]"-t:8dl+Nws ;0<x'Y4h@.Q^A#|!OLA_E |q7VA|ŚLӻ' g.r-@hVB?!`*/+.W(>+s,DE֙({)+||5OʸFG)򼜻aAwЬTYL+꿮]$7/k4Jqq}s...h ѸƇKRϣJzM~fȁ"^ڬرq l #4(tlYЄ:J٩:"K{[DT UM<'b >J'jb$Z, 1T}6c/f-e؊;&‰s)Q>GBH_e9 :S C?CsƎm!U&]|zWvoW~=']PZfӒ;QQ%t!T_j 5m$ GeSח?䙢3CPظ޳- ıeH{W^\ o(q,AyH 9[_{2aԪ\ +~%n S2fN= eP}sPazpV" Ȳ텭x1ZT]F?@L=&_տVyR,EeG^$Ɛ/>@݆II,lT0ɢ`@JfW"JQa\ӳDdJPZȶRx `.ohKV_[d Y&OI.~#,bSD\-JW?c~oY.д[We^o/.:0IRq+3rRʊBJ='Juq1wgs5_ksWW"&b0j a-2}ʻ?R*'pP6~9}`@jH/nË% Gl D"MK"X y ^'K ,T^y]t0N۸)q t&E6v ݃~Pʢc(ˈU`Y)l$Ơqh+#GW(M}0)r}Ċn8f);N,Y|l|1u Uj Lʢ=~-'kp.B!۷.<‘MKQmYJ1GQc&+^E)i_n*VRVDVS8DFĖ,edi=f*kSG(#SV_k%O\\\;ATZύ7TYWy(LFdζוEc+ yx/Rm^NeQuxʲ z'T)UU<6Zĕ7 KAk#sp f)ç߿*:KaT|QyIL_3lW!VXr-3?Z(xz9SMņp2AH q2KWZȽ)1BgAA MXFY; e4lFAH@V*=|-7E%QgIK*4ekj-W,MLmОb~䄟>'ZCڻnwASP:_27Z-F#kۊBàk]o4H-tyN*_NLݶdeTeo0gr čqv&UyXLqS$;#q`=3N8A>Nɚ%2l:f d1Zá:Dp[^~4)*VbеZWu ;`0R5 *laCDE{%qlȍ+dK=i^bS0fshP}M>.u8jM`hѢE-ZhѢEEnՏ_v>~O^|/[{s}WRᅭewxLW[_$A&gm|Y-4I4p7l7yI?}o^|.ylާaϼ#YNʲlR;^<-4si}ޗ>}VFg> ,&Cd/"gNC[TOOedDvy,Nx'+;}pY;M5B'4K|? (oI dI^l O9p?{\;:ar~Wu_\Cٯ~kۃϪJk1W; vvN}nhgYSbyoԉҼ7>+M<=yZ"yMޛ!;qIFN˝,'y;Gu(:w{8a1w}}yL-ZhѢE-ZhѢE-ZhaZmw*1mNOŁ/|>ϢfO'n4w @vֲ>? >H|>JcZTZX7ƯK- ~E3d!s嚠m{.[VTH|*EAQ>T}'at7{f8,o{/[Xi:fG>/B^wPea{^V|,_5ɯ .Jք$fp<~,|bŅٰA:i$#tguҀG/_,lMZ6+2f; 8E zCZ{N,#$K)Ћk"Oȓpp:LvD` %N?򊵠4䮤IG1U{p JCӝo60Eq! _PbS6\^_oϠEMe HS}1B{  pKwaU c`ij"Ѩ,̒ի[|x,OQl r͔d1ET&WՆMs?l-# dČD\Pr>ϖ'Y&%+Muq1[_H -zX:đ;yib*ȃB"e;*ctr3xv_SyKaByjnǛ<U6ôq4zCu|e*c!r+T"-VVSiBLl g  jUEÏbP*˂ JO|j@e ;&nzGUʉ\Vf2 ܸvwQF6[r~nRYO*ːy_Bpfrƃ/1*1ݧijx@e(Mr*S@*v0B(WhYH:, {:JGAg)8a.9\]9cCʠݒd!>Z)RDV@ F&Sx2׎g Ec} 1b+[-?"wC)SU8. ,4}26Nt[)YH0_%Bk4%˪eO-gF,)"38؇is>ֿpe:xp碔5A*SWkIqR/F۽Y0+/.XB]}l7㹤ԚD]E{Tⴻ*_^Q-(Cdd Œ6S©QGb%"K j7%p.ΫȰHӚELlScna2!LYFM{E +)>rde 6rW}$ϊ)eyϙ2|-'4V_ˆF͐5iyf"4'*ucMJP2x.D`C); }KSE$+6oP_Rqr!4̩VhI,?_LEjH_CU|͔=>TZm}0"=Ž#mōg6j~?*T"ʢr\_zWT*/{6 a{3JQT{(W̳[yt2z\]r@"HW"üs#tڥQ%REQ*gR%]lRWѷ<ל+tQ(G_EZuhB NylaHDڵ,ҢHꋃMFYʶlp7S\ѮC|Nle.4z)w8AUg}}mAǺ\\k={p&b)īo*:)R}E˩"}C=ʢK$\dB§hׯ_CYp`4x"˹ktW KŴ)En~#?FD/iq8|{h|ؘ|i+uf';EECRV2X'?$k:PJqAƇyXcy"&hSt")O5_"0+ qCk#=Q_bv~RH^Zl"8c y$Us:084h+Ye"Z(صGwX}*n lv'Г{n5n6-UBKPF q{4Z6u}C):3kKJ=ˋ: J[dw`x\/{w@_+Y+'-8v@S_YOK{j΍eCUp}U'%o ȊLAG,h-*`foe^%8zrQV3 Zք $+8V0J"_isؽp'*RE!}e*.Ƨdh 6ɹÕQi,Cb%)ݒ`̇oE߲p@`& k,w!U(:݇uV}2B@}5n bTjɲ* aQ2qhyk4EgH0e螇 ^m25V\4M 0Nj\:Y%ѻ8XGXh(Yat-w}/5|OVL>HqHP4ŪaN`QY)hg8bURXgKy.K_ܸ1$y#."l Q :%S`? R6{> = '@Y Gn%,K^؊I>: eT +qodcU*n'e"_\vENa "dO1mıJ,ʊ )A4d}%@E{*Y[e==h OD5l+p򆦽dH^M_Y Uk򔑔;K;)6ET٢)qS1Mkx}U½x.W1#',4sd^c|_~ {w&+K0WV8W(SN߮kpmV' -d/֒m>̍j,q`wxy!+v21ZM7ۤ9|+͂g\^sdQ\<3+Kqu-rn^o /3V0jr G[>)}RHi] \^6.{oo@YҐ>}/@$d9,aYO7eC/D v./K:n]kRvL`l&kh4Ofjcf:<)WSo_t= sjwn!)N nngPN2\^,G5n3yJ兜0//oYe1.(ab'٢d)eJ\H}W2OE[&Ls=9,2qRf*X {K1J֯f-R4>;ύYZb2|[2F%.We[E8{)vb%%G ; 2>9]i瞟s1Tl'sg))-5>+tVDhdyeuRFaTPdrSZh{&\k🼤BSƜre8,GNSֽp!D8F 0 Z`< G┾|W|)@J 2Ţ,b#>W42jN#:Ƒu2(RU_"7 \F,ĽZY-gOŕZ$FwL#a/O%GhJ̎l?5˃Zܠ3$)>`:uW6ߧQNY 6H-SԩS|r^h]5iv4.#^%sem468o(4 ʼqF#8-paԢ-L(d$*mK.QF]^x&PqJHmgRq7Lk3nn3d4IX"s6soVZHi ڨ^z8j3KHb)ϫj(]uePSh[(Y3J6DyQd>@Zܸr@Z%63i6ՇlR7si-ZhѢE-ZhQ_t:ß;'{ l%wWٿ]PK!Fgf,word/media/image8.emf}M+I^MuuMW~p1XfR+ma=k .x bx腖qC^ ;0 0x4xPb %G?ݧSqO:72'ND^u:?d3cm{v::N:h ot:^ދrΧہ:n+' n_Cjc&?E Ώ:?꼋{~_v~ v.WYo{|_Kw~6Q~` ʽ]nw7_|ś7o>OH>& {sSoC{w3'~S#ӧx}gM??}N 4g[쯶~uOO_~ko˧ϩշvk~ĺI{I3O?5B~o:~u֍~1p#spݨ$Ws+Ut]Q:C]s _5]Wv uEc_ Q/TW4麢3g+Pu99?<Zud:f᭴rX,ZifE2q./ӇrxZiRr,et?, E!Υ컑5]O[oNoy};Y?<RhHۄp *%L g\HMqpˡp8x)2T>tb1Ke5LH4`rTvfN Oٖ`G蠐`4GS—vz+Á) I; hB/uJ*—T/P¹"xKaœP_/) ^0O_znhzԽ9-DZoB9gn2f.$PځqFƧ!W5I_oV&7T .z'~s6PuV`l.DWc4#9pP$l, n_aLd|` q;Q*th5lF'`X^c fmz2 _Rz <I{ctX3d!+(5 pMfaa}N_>/`EFm#]N&c2E"E-8bp!9mQ&rxMM4 L EwF&5$} M-W뽫( gY1ژݢ #,M<gz]ŧ}يf̢o22E mv@_8pxD #:Z T0g!9n1"?!|2Wa/nTϽGcL_'q1?KOOt؛)Y 5kwgNi fd{ iV HTߗO #q12iLq1PrKP~ȳxk2¸Ab|Ը;.es= 󎳈=oÍlf)0AP̵E,b$ tO/Fakclyd >1em~saYy_,RBlߣœo7#5>]$F*CP_|jb7_e80̦1c1O!NSd FC(!"љZ節BÌhp9{2CD ^mўVK5%B,|C{7JKȀ/Gw (./. 2l&ۀa4V+Ɨ"$V!CAȺ9t=2dS&ivo]l/ 5KB-)^F"8:SL&'Uq!{Ddn69PS4."|V/ݓodEk$}~H 4=gtjk "*8d$cq́0J_Ek_KB&%v5em^e|87fzr4(d)}E߃p^\8o-a,i?&Pզ…oٳ`NK7xA(.Ìe5Z$q^ x\7VO 4aoΆEinb`Ck6eP泄Ɓ C<ﹴY3Lckn )_\~GYk&%,Ia >V _ Uaؙvl/~މ dar`8}ZQsҥNW>﹖i eaw2fKgKlוr}^=32؎(O?zx >ĥGI"=>FM.jo+/91U=ooNl>7-"CT 4(c+l/V 1eKlx^ݔpUHl2uKvj :K9Ñ 2WQ|?9kK4_\K@ PfM372r IMlxE@dχidM%]|ِ[P.s͓^ $NTo 0G-> Dήñ{,㦽 ;X 8 b*4_Q%18`{;ۍl! Ah[ly-> W_UVp)"Ks8Qrde64_e}4-w!q(3|Y.xgpk‹_Nϱ૒Ew/[ ^-Q`g|/v/B&3joe/cϕث ?]f >yO S '/, Kj|1B1.03|EH;)xD#oR_mx+,xw۾ ҷng [y->k㯜f:+sŧY"%6_.Klլ>0%"[_Gwfp>H_GDno~lbCli+e:R,-> ׊FuB/Ϻ,X.=`l8 YR>N}`JD>(/_mF(s6{٣&|go4H;)ru⧔&m^jd Sx-_hJN1R2ZS"q:/a<%9#C3ͫx/df[|d5LbdaO/{Ynv6`"[|/)/éKdfަ5VCŧAU_/P\1ER/(skgа-> r—˖pk4ffZd24_<_E>y9y?*.^{ 3ڐzidĆ],y'3l>2¿e[|/rc؎6%.#f|hܦQR*bcaKP=(|5l}>l9 nf-jpp1dH_+ʝ/)Y.ŋmWB7NVb͌U 2RdS"qF\>X@} ){eer if JBGlu08{cCw3Ũ}=/2SlK&_ەBFSV09&d!b m}/////#Y|ݐ6 ]i8_h fKa Kp[`|]U8W='JB (sn9/_AF( #X85[<;Vb3g;MKl>lx _'ȍ+NSfK"PXt}<ЂҚL &7/-}nI2/,tKl|W# %̀_+U}/)YpEX|zgE.݁H];_) Nrw]{Hdaj/,; 8^\_Aqer(<[ְ2]i^;XYވa/,k;3FVA:ڲmV$kjK`_R*ԇpa~1t2ޥ 8YmE"y&01tgPnpC>b cownf|I}Q= l]ݐS_M㏜%[UĖkk$aB zEٞZ&/)  sƸg1]˴KoqHתY|7@'0 T|9I3BM( zEC%EKW@GK0.s,JAe}`JD" ̆ )ICT2K/)Dt7T4s6KVQ+q,dApVVc 9wmhջopլ޵Dx+KU 9~_]?ogJ+J+J+J+J+J+;o{|wjˇMA50[Kukb_F~f~yתTd[)Y_^(zضJQ/xMG=#] YBRCxw3'[w>5]7OO?S^*iO_=4g[쯶v՗OSݫo[S`+I{ US#CJUgcw17m][ֵum][ֵuԵR(?w8G34u`7`վʵbwj=lq׺LiK!}Fۗ%,;FgK,w>ož9ɿVd޾fTe0p^_uUɵ B.m׃`9o苋[ 5 kkAUf}gRF n* ?,>;p뚑26b>|`zУ7} >3[ ˁ0u}]slAb4Eע[fb毲V3szmòNCxS2Er< R@imMʺt\`|r!jG"!k0pf5{샥 Hm9 Bp1p] hbME _yE7~ :XndbDD{|f4Osדs;ypTc/o>.q6@03Q{iڻm2@CCf}+E}o(Ł]HTj)ŋ@F KFcj),3C4 QHS"qXjwo[bp8j[ S"qi%FŎ6uue) AD.n%HxA!klX \D7n^&j_,46PkHJN_ v vzݐtK_0z`O_Ko9,_]p/Aa4U_q ##)'/PuxoPcP!tM J_y_H!pȅ4\ b &i-r(0^ #_R/Y}`JD"3s?."B(%ZO_ _&^ڙh_/"Ȇ6%*c k|)_N2+K7T,!pHR0'.vFuoNqV[PNC 3I9?v`xiU_R6+ _ 槞(:ߜ+/`EFm#]N&c2E"E-8bp!9mQ&rxMM4 L EwF&5$} M-W뽫( gY1ژݢ #,M<gz]ŧ}يf̢o22E mv@_8pxD #:Z T0g!9n1"?!|2Wa/nTϽGcL_'q1?KOOt؛)Y 5kwgNi fd{ iV HTߗO #q12iLq1PrKP~ȳxk2¸Ab|Ը;.es= 󎳈=oÍlf)0AP̵E,b$ tO/Fakclyd >1em~saYy_,RBlߣœo7#5>]$F*CP_|jb7_e80̦1c1O!NSd FC(!"љZ節BÌhp9{2CD ^mўVK5%B,|C{7JKȀ/Gw (./. 2l&ۀa4V+Ɨ"$V!CAȺ9t=2dS&ivo]l/ 5KB-)^F"8:SL&'Uq!{Ddn69PS4."|V/ݓodEk$}~H 4=gtjk "*8d$cq́0J_Ek_KB&%v5em^e|87fzr4(d)}E߃p^\8o-a,i?&Pզ…oٳ`NK7xA(.Ìe5Z$q^ x\7VO 4aoΆEinb`Ck6eP泄Ɓ C<ﹴY3Lckn )_\~GYk&%,Ia >V _ Uaؙvl/~މ dar`8}ZQsҥNW>﹖i eaw2fKgKlוr}^=32؎(O?zx >ĥGI"=>FM.jo+/91U=ooNl>7-"CT 4(c+l/V 1eKlx^ݔpUHl2uKvj :K9Ñ 2WQ|?9kK4_\K@ PfM372r IMlxE@dχidM%]|ِ[P.s͓^ $NTo 0G-> Dήñ{,㦽 ;X 8 b*4_Q%18`{;ۍl! Ah[ly-> W_UVp)"Ks8Qrde64_e}4-w!q(3|Y.xgpk‹_Nϱ૒Ew/[ ^-Q`g|/v/B&3joe/cϕث ?]f >yO S '/, Kj|1B1.03|EH;)xD#oR_mx+,xw۾ ҷng [y->k㯜f:+sŧY"%6_.Klլ>0%"[_Gwfp>H_GDno~lbCli+e:R,-> ׊FuB/Ϻ,X.=`l8 YR>N}`JD>(/_mF(s6{٣&|go4H;)ru⧔&m^jd Sx-_hJN1R2ZS"q:/a<%9#C3ͫx/df[|d5LbdaO/{Ynv6`"[|/)/éKdfަ5VCŧAU_/P\1ER/(skgа-> r—˖pk4ffZd24_<_E>y9y?*.^{ 3ڐzidĆ],y'3l>2¿e[|/rc؎6%.#f|hܦQR*bcaKP=(|5l}>l9 nf-jpp1dH_+ʝ/)Y.ŋmWB7NVb͌U 2RdS"qF\>X@} ){eer if JBGlu08{cCw3Ũ}=/2SlK&_ەBFSV09&d!b m}/////#Y|ݐ6 ]i8_h fKa Kp[`|]U8W='JB (sn9/_AF( #X85[<;Vb3g;MKl>lx _'ȍ+NSfK"PXt}<ЂҚL &7/-}nI2/,tKl|W# %̀_+U}/)YpEX|zgE.݁H];_) Nrw]{Hdaj/,; 8^\_Aqer(<[ְ2]i^;XYވa/,k;3FVA:ڲmV$kjK`_R*ԇpa~1t2ޥ 8YmE"y&01tgPnpC>b cownf|I}Q= l]ݐS_M㏜%[UĖkk$aB zEٞZ&/)  sƸg1]˴KoqHתY|7@'0 T|9I3BM( zEC%EKW@GK0.s,JAe}`JD" ̆ )ICT2K/)Dt7T4s6KVQ+q,dApVVc 9wmhջopլ޵Dx+KU 9~_]?ogJ+J+J+J+J+J+畏:7ow:[3k| ~PK-!kw [Content_Types].xmlPK-!N _rels/.relsPK-!s>:|c)3word/_rels/document.xml.relsPK-!?9! word/document.xmlPK-!1&word/header2.xmlPK-!5O$word/footer1.xmlPK-!=Ҥ8'word/footer3.xmlPK-!x *word/header1.xmlPK-!4|\1/word/endnotes.xmlPK-![ D 1word/footnotes.xmlPK-!4word/_rels/header2.xml.relsPK-!H6word/_rels/header1.xml.relsPK-!ZbQ7word/footer2.xmlPK-!0C):word/theme/theme1.xmlPK-!) 0@word/embeddings/oleObject1.binPK- !0G;;Nword/media/image9.pngPK-!) 02word/embeddings/oleObject2.binPK- !3tjjYword/media/image7.pngPK- !/{::Gword/media/image10.pngPK-!8<word/media/image1.emfPK- ![zz}z}word/media/image2.pngPK-!Fgf,Bword/media/image4.emfPK-!edDoword/media/image5.emfPK-!sΖG7Rword/media/image6.emfPK- !    word/media/image8.pngPK-!Z]  word/_rels/settings.xml.relsPK-!b|>^( word/settings.xmlPK-!{ս"l@Z word/styles.xmlPK-!69U*} customXml/itemProps1.xmlPK-!Ѝj~ word/numbering.xmlPK-!t?9z(' customXml/_rels/item1.xml.relsPK-!\- customXml/item1.xmlPK-!_0  word/webSettings.xmlPK-!9 word/fontTable.xmlPK-!7Aޚa docProps/core.xmlPK-!KL docProps/app.xmlPK-!ed֯ word/media/image9.emfPK-!8 word/media/image3.emfPK- ![zz}z}O word/media/image4.pngPK- !3tjj word/media/image12.pngPK-!sΖG7 word/media/image10.emfPK-!Fgf,f word/media/image8.emfPK** libdigidoc-3.10.5/doc/SK-CDD-PRG-GUIDE.pdf0000664000372000037200000400275613560273131016740 0ustar travistravis%PDF-1.5 % 1 0 obj <> endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 4 0 R/Group<>/Tabs/S>> endobj 4 0 obj <> stream xUKO@[أeg[UxԊ "! EUHIߙuL։"y37N^ &0gexn6\Yz̳G9Nyv|s AL;BtylgoVyvWȳo:^%K36zi_ \A0] Rp\:6r/&ΗlCCHn:@r&] Ef׶3ǚscW;n?}C$-\ႎ/ x.U*n5@[nힻU pFdg< F6PJp ajֳXۑ'ZԎ4YsIJh_}b;-=:=]_'ꋏV@_e }PwPcRo/ot{_)| ye.nJ{Ų6wS-،W >CG4EUs2@ S>v I/94GrE"&$v[7 ڨB|(O<>>eD }/}p ^ 5J4)T>U [Ut~IoH`Ч@-$R1}"nƧz endstream endobj 5 0 obj <> endobj 6 0 obj <> endobj 7 0 obj <> endobj 8 0 obj <> endobj 9 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ56" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?5M/mn1SڗZ]~X;wgvG,rǒ}kc`0 *|?sRv>\n(?WOjU?ҳ2z2zuf=兣eV ! !>WYol/o#>ʪgV(y > PsEYd݅#u `2 S$ƺpŖ7Ȫ<6Z{J(o[K5t?[uF\ߙQEhJ7y;) endstream endobj 10 0 obj <> endobj 11 0 obj <> endobj 12 0 obj <> endobj 13 0 obj [ 14 0 R] endobj 14 0 obj <> endobj 15 0 obj <> endobj 16 0 obj <> endobj 17 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 18 0 R/Group<>/Tabs/S>> endobj 18 0 obj <> stream x]YoF~7@t"C-9'3}pbeal#Yd4[͏g:K*2?}"MW9Vʴn7O_O^}E֍~nUjY Wo\uuIS]?>y_'/?>}HNVBJ][VxFUo߿[A"붖2̌;4iyv~~lwt]&?:2g٨Zq0bf'zZk|mV/_=^jem#g#y _]oǞZ-@uFE/fLmmٳQT/cG6~~*5nW{> T'?|>;=A-G-Xl9fp$ZJwv0嬪cyjUZBx0\B" Trj?@xUZg~(T&Bu 1.J5edZ3`ńՌqukSY߭YH >nzu oB> wwKI>/߭_|]tq*0߄;7lҀ`93!ֶ({ I/Qn_Tӡ,RCʪXȑKZX0c[mMzY,5n唖5OkhD[ojDKķٻ $ VmnSvʌHJwFٴVB72\Uj1I: e3"?skc4 sy4oO@bWaғ'c;Az Z[k Zw2 2 1ԓQ.M&koc}H$> (N x_ E 5$!\Aء/bT*H&ȉ6K9gVaӛku{' ` `%@4` P, l6t[JҔ6 þwXbv ui[il6x,q)#]f¬N>itxҝ6&-@Ad&exҐM9u4 y@kM|lb#$bS/@Akj/@խ6ŮŜES1t{C˰Xmebx~zq <Ŝh¶/5~݉ӓbңb Cߤh}' qP kKEXmu/ٔ\ūU]%tknB¼ƍ६W5V.拹r\#&)&ƧNHL(US smI0FGV +~SPS~Go_!f;6aBPTz)A!2o|P ٠2bAEAC%sh01Zl\YZ\9eI;Mt1d!,bqȚ 1inlb9*nr6܍Xb >zH]G"yw#(=16%zUЁzGY|d0/oQi&:>LϮ`R5qO[M} ctS"ݍ -2Fu3aP޶bhE Tkz^FղM` ,?+ƭԹDKlbVŚ."x7Il!(H`Pu0äYI8/enc3[}ĵ5bK[i 75Q|t>{`LEuV}ÉfdMaWH~thk656Ys-ZNQ!P_i<<ۧumO% YvG|&$RJL%0_/%PtfUh2b^ 7 ةEkY{2n%"CѦX}lG Q) yE X~~Zk,JrاooM*Sbf_zr'R_1[H4NjC#RɁgqit<$XH 5}L.HM%qȐbjC H$] b OP Llj|dVy@/Hȥ7[ ŀUug"cY7"fz7JBhZU(\]L}]SĥH\ `j?_ 6 *K,!(p=)ŷH&B|񍯗[G&2&F^,$2YnqڍxN:R(,gOIJ|~c 7΅:(ơ߸T]L}ñKH6_i?v7W/..vA 7roscڑP ;|f}ѷ#lx?\|gʐ;VzqmKY?3l]a\~1 O5nx7 zžh٩h{k 0 o~4 c8R> C6c7`rͿ,$o)@C¹>9!N_rBT!tG :>9Nѳ3N'@ge|XyxLRO3>xr9'bbޅ0RҴSU#0򫡅rȑ7'H%!wrp=Do)y_N>2=aclPzhwGik`#w$͔rsF[o0\Iٶޯ+տ[nj7duMǻv~We1=Zۯޗ07W^xKq^Q)7xHA&Pj:MMw7aJƼ}}C{v$ƭM}?yK{I=?Iw\P{?H2zH[^cĴc B7 řy|Eǃ> OC"hX%x~{Dk7j{pӀB.a:r"s=[c.vCeBNߌ(CSɐx.ێcdkt*RZD2kt^Xg 5:_/C=kto^U07F,ke0rsиNPanU|Na6%JctZdWb̲PH(\X'΅:q9^&.U+'oJrT8xAE-eK*w,O|>?CB~@xn&.v!!,nAV["=1˕F-/ *6yqq{yM/ۤrN_oCpRᳱ~[qC2yt+/ȬT 357#{۝HF`o*G;eA"X;jiCEDz BXLJ/xba/m &qb鷅6t+يRW o;=H&?2+Fe8:3儏piDOIM~cN=&eOO5}> $tzNY> L&ѿ"[ruiN٢P),JE‘H(Eaz(. {UG;9yd0AAhl-Z;6^rj;>x8K.cł5wK7PHbmﲶ{Qy)C6C7N cH:)w KcF0A2; ]EOJ&!N _Ӈ}ľ4D@3 gۦr ,h" Xr*:;z^yS3l<Pǂ!{"(ۀ 2T&RYԗכT!8 , p endstream endobj 19 0 obj <> endobj 20 0 obj [ 21 0 R] endobj 21 0 obj <> endobj 22 0 obj <> endobj 23 0 obj <> endobj 24 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 26 0 R 29 0 R 32 0 R 36 0 R 39 0 R 43 0 R 46 0 R 49 0 R 53 0 R 57 0 R 62 0 R 65 0 R 69 0 R 70 0 R 73 0 R 77 0 R 83 0 R 86 0 R 87 0 R 88 0 R 89 0 R 92 0 R 94 0 R 96 0 R 100 0 R 102 0 R 103 0 R 104 0 R 105 0 R 107 0 R 109 0 R 111 0 R 112 0 R 116 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 25 0 R/Group<>/Tabs/S>> endobj 25 0 obj <> stream xݏ6Gm.wEka{Y4s^ofE"EihbpH8?JQju!TSBJbxW.^| +Ż_VȦLaڶŻ? 뷦xQ龽xqSqk+.VIeDy& SÅx)/?^K&R5R#0+M_D]W// ~olNy%JY^.LK++ɲ[ (@PlYe9-*m[|c}i]eitŎJz]o+|YMXVݺ顗S k?P^1dWEYR-,0gB& u%m9uB3@2UhQQMU)_{b5T nVx<'zԔꘒ~ʔYkS'W3Uk|*rh9%V:-ho-$:m|@~z;xT_WDɪTZdwdnZT~Z06훗plj![j/KDUPFXS pM5kȁ2 @\x4i&Dŵ_8?X>4 1i-ۤ֫K^q_KQ>'k\Xs pA#x̧u:#$ּCH;o-xu^|^5fV-іgШ*lilT#u3%lI0[;³ RX2뻌r,[r2#e} =z|+= ml@Cg,EGU \m%=sD =!n& u[%e2#38UrpTGԔXI_jJ7+70|:+^2NޣhcԂM۴nڅ oMUa.iuCZx%4Qn9zA8;$@eb11 YItiVDFip +֔:,K+xJkjbO 0i\}F7_NU8tKa\?!q`1ps(XzA_%lMfs{mJhH'Ӻi~*h[Y6]>`L:ia si5u4n 4S 6|L+g䫺RN{3XӬ gG՞i~ %XlO,fjQR)!zCbIDzSͮM1̮ ~7kޞXƟoC0Ŧ,`VTqtb`l ,)uB7"KzLQ6n9(jJRyPeL2֮/ 9MOR8g@f|g+b26o'wqW`)VhK+Y>-ȼv!&4]R߲IAc U^Hx6h= d*`+`X: ->;;tJM=yxOFaGŧedqsZkb6dÌvf[h0ن@҈:5C4hlb:( èjg J-M&)SJSZP372J sy (4z~4N4pE1k^q bbxMxu瑪FxyxBT'Zb4ZVA#izˋ㦑 s M$ҭia#2]TI!D76ޖl%)bJ*I ؾvؾ\llQۏHJOAppMJ{ڣ&rRʕ2=xF`K*SMm}+0,qptp~~ _l|YUF*̅cbjN[zDye|R@7]:hthYυ͜hчFBnVISa.v(E$%v' A!.vd[so@6Uyg{|ASvCo'76SKG{rMc}8m Zǧ}5& 7l}tՈEDZ<Ґvpy'̈́ yަ#䎠4NG=:X!M7l\%ʍ:4ճ79tUa(k%0M7eGtbGtA3sۭwatCvN.8?!l6;x*Env"* hFpnLp፥O4>wG 3}Xړ`9lq0X)q\4]O:j.6W޶xT}׼8J+h:Nk:6"G-z(h9:/S꨿,8%)PdfI'$=抲G$E%￀9|sLW 82p: Q~sŘ^!cn0^Ѳ_хM=͢pac>nu<+;;!.Ut#{x6GM<`[csT3:1JNliuq3pNwj'[Ydy'U6V9iZRD\Hө]As蜴|.6~J i0W >_8 nI'1MK?j5eOEwAX 2Y<sLQ >`#$t 3]lm$\A3G`ZgЉݾX޳'~OOOǗrߞN̓ԸopsXܷEְ-R 3vOh&CTY6@i \Q\XU\1YlM0cl6ǣ{oN[,b[׸"g]hF s ]թRA5Yl$":TOPcTv]}78RKۧNڅ^mSa.m\RV>Y 0ty/~fw⟴ wr~{=m '!O|9}v0<=ppXPOq9.{ŏR*<3IiG>?tCL[Ω3l+fv3ca7D 1F}_[ߏ?~טm ԶA3Y~ NeE䪐EE&@$$fZd?+/vV}RӬ>2t +3%uWg&BGjڿ]Lb7wV#_-bϳa"ܣӡO\h{\zݘcPaVIxSa.ֺ6KTgy<mrlҦtyAVQT%`{NǣsoT.w=w+ ^A=-F†[hSanLT #&]A.2P endstream endobj 26 0 obj <>/F 4/Dest[ 17 0 R/XYZ 125 735 0] >> endobj 27 0 obj <> endobj 28 0 obj <> endobj 29 0 obj <>/F 4/Dest[ 31 0 R/XYZ 125 735 0] >> endobj 30 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 119 0 R 120 0 R 123 0 R 125 0 R 128 0 R 131 0 R 135 0 R 145 0 R 154 0 R 156 0 R 159 0 R 160 0 R 161 0 R 162 0 R 165 0 R 168 0 R 169 0 R 171 0 R 176 0 R 179 0 R 183 0 R 185 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 118 0 R/Group<>/Tabs/S>> endobj 31 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 191 0 R 192 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 190 0 R/Group<>/Tabs/S>> endobj 32 0 obj <>/F 4/Dest[ 33 0 R/XYZ 125 735 0] >> endobj 33 0 obj <>/XObject<>/Pattern<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 205 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 200 0 R/Group<>/Tabs/S>> endobj 34 0 obj <> stream xc` endstream endobj 35 0 obj <> stream xc`@0ga1Qx̯" $. ?.#G endstream endobj 36 0 obj <>/F 4/Dest[ 33 0 R/XYZ 125 281 0] >> endobj 37 0 obj <> stream xc`; endstream endobj 38 0 obj <> stream xc`L a8`] %"̭ᆴE m)WS0>Œ]n eZ- endstream endobj 39 0 obj <>/F 4/Dest[ 40 0 R/XYZ 125 213 0] >> endobj 40 0 obj <>/ExtGState<>/XObject<>/Pattern<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 267 0 R/Group<>/Tabs/S>> endobj 41 0 obj <> stream xc`; endstream endobj 42 0 obj <> stream xc`Leb`c`! ̆k9zL=nÕ|_H}Fa`r}&B .2 b/4 endstream endobj 43 0 obj <>/F 4/Dest[ 45 0 R/XYZ 125 735 0] >> endobj 44 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 342 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 339 0 R/Group<>/Tabs/S>> endobj 45 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 366 0 R 367 0 R 368 0 R 369 0 R 370 0 R 371 0 R 372 0 R 373 0 R 374 0 R 375 0 R 376 0 R 377 0 R 378 0 R 379 0 R 380 0 R 381 0 R 382 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 363 0 R/Group<>/Tabs/S>> endobj 46 0 obj <>/F 4/Dest[ 45 0 R/XYZ 125 672 0] >> endobj 47 0 obj <> stream xc` endstream endobj 48 0 obj <> stream xc`@0g/_ µH3 uX#`Eϟ|+"U endstream endobj 49 0 obj <>/F 4/Dest[ 50 0 R/XYZ 125 619 0] >> endobj 50 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 384 0 R 385 0 R 386 0 R 387 0 R 390 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 383 0 R/Group<>/Tabs/S>> endobj 51 0 obj <> stream xc`# endstream endobj 52 0 obj <> stream xc`@a f=LͯĂ6@Y_OB K5`y- .D=W10~t+ endstream endobj 53 0 obj <>/F 4/Dest[ 54 0 R/XYZ 125 467 0] >> endobj 54 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 394 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 391 0 R/Group<>/Tabs/S>> endobj 55 0 obj <> stream xc`; endstream endobj 56 0 obj <> stream xc`<a2i c`=Ĭ0գ@Bḅ3BE^>fX1g̛6/g`//.A endstream endobj 57 0 obj <>/F 4/Dest[ 59 0 R/XYZ 125 735 0] >> endobj 58 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 396 0 R 397 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 395 0 R/Group<>/Tabs/S>> endobj 59 0 obj <>/XObject<>/Pattern<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 398 0 R/Group<>/Tabs/S>> endobj 60 0 obj <> stream xc`; endstream endobj 61 0 obj <> stream xc`<_"@f J D`D&`HDٌ`Y60Aj¿AD- endstream endobj 62 0 obj <>/F 4/Dest[ 59 0 R/XYZ 125 134 0] >> endobj 63 0 obj <> stream xc`; endstream endobj 64 0 obj <> stream xc`e7 Ł, 0 K3O@#"^@خ6g$ "E* A#nc`X ذ0) endstream endobj 65 0 obj <>/F 4/Dest[ 66 0 R/XYZ 125 617 0] >> endobj 66 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 501 0 R 502 0 R 503 0 R 504 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 498 0 R/Group<>/Tabs/S>> endobj 67 0 obj <> stream xc`; endstream endobj 68 0 obj <> stream xc`<eYK30 \{_ 'w /G !V3L("|x ~ 2 endstream endobj 69 0 obj <>/F 4/Dest[ 66 0 R/XYZ 125 431 0] >> endobj 70 0 obj <>/F 4/Dest[ 66 0 R/XYZ 125 389 0] >> endobj 71 0 obj <> stream xc` endstream endobj 72 0 obj <> stream xc`X  g3YbP`|0@a$  endstream endobj 73 0 obj <>/F 4/Dest[ 74 0 R/XYZ 125 688 0] >> endobj 74 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 510 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 507 0 R/Group<>/Tabs/S>> endobj 75 0 obj <> stream xc`; endstream endobj 76 0 obj <> stream xc`"C/ a@c`3AE: g1GP?/ d,@ nNrq*= endstream endobj 77 0 obj <>/F 4/Dest[ 82 0 R/XYZ 125 735 0] >> endobj 78 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 512 0 R 513 0 R 514 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 511 0 R/Group<>/Tabs/S>> endobj 79 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 516 0 R 517 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 515 0 R/Group<>/Tabs/S>> endobj 80 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 519 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 518 0 R/Group<>/Tabs/S>> endobj 81 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 522 0 R/Group<>/Tabs/S>> endobj 82 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 523 0 R/Group<>/Tabs/S>> endobj 83 0 obj <>/F 4/Dest[ 82 0 R/XYZ 125 701 0] >> endobj 84 0 obj <> stream xc` endstream endobj 85 0 obj <> stream xc`@BEHJ3o??|d (B7g`Z?$ endstream endobj 86 0 obj <>/F 4/Dest[ 82 0 R/XYZ 125 633 0] >> endobj 87 0 obj <>/F 4/Dest[ 82 0 R/XYZ 125 429 0] >> endobj 88 0 obj <>/F 4/Dest[ 82 0 R/XYZ 125 261 0] >> endobj 89 0 obj <>/F 4/Dest[ 91 0 R/XYZ 125 349 0] >> endobj 90 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 526 0 R/Group<>/Tabs/S>> endobj 91 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 534 0 R/Group<>/Tabs/S>> endobj 92 0 obj <>/F 4/Dest[ 93 0 R/XYZ 125 147 0] >> endobj 93 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 535 0 R/Group<>/Tabs/S>> endobj 94 0 obj <>/F 4/Dest[ 95 0 R/XYZ 125 476 0] >> endobj 95 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 536 0 R/Group<>/Tabs/S>> endobj 96 0 obj <>/F 4/Dest[ 97 0 R/XYZ 125 175 0] >> endobj 97 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 537 0 R/Group<>/Tabs/S>> endobj 98 0 obj <> stream xc`# endstream endobj 99 0 obj <> stream xc`_>L&H8L,Oc (?N 320?`@,bA{B, endstream endobj 100 0 obj <>/F 4/Dest[ 101 0 R/XYZ 125 688 0] >> endobj 101 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 542 0 R/Group<>/Tabs/S>> endobj 102 0 obj <>/F 4/Dest[ 101 0 R/XYZ 125 451 0] >> endobj 103 0 obj <>/F 4/Dest[ 101 0 R/XYZ 125 332 0] >> endobj 104 0 obj <>/F 4/Dest[ 101 0 R/XYZ 125 174 0] >> endobj 105 0 obj <>/F 4/Dest[ 106 0 R/XYZ 125 705 0] >> endobj 106 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 544 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 543 0 R/Group<>/Tabs/S>> endobj 107 0 obj <>/F 4/Dest[ 108 0 R/XYZ 125 256 0] >> endobj 108 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 546 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 545 0 R/Group<>/Tabs/S>> endobj 109 0 obj <>/F 4/Dest[ 110 0 R/XYZ 125 190 0] >> endobj 110 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 548 0 R 549 0 R 550 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 547 0 R/Group<>/Tabs/S>> endobj 111 0 obj <>/F 4/Dest[ 110 0 R/XYZ 125 167 0] >> endobj 112 0 obj <>/F 4/Dest[ 113 0 R/XYZ 125 584 0] >> endobj 113 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 554 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 551 0 R/Group<>/Tabs/S>> endobj 114 0 obj <> stream xc`; endstream endobj 115 0 obj <> stream xc`! r~ 3<0գ _)]@~t|j\#P;TX Ud @0 endstream endobj 116 0 obj <>/F 4/Dest[ 117 0 R/XYZ 125 735 0] >> endobj 117 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 555 0 R/Group<>/Tabs/S>> endobj 118 0 obj <> stream xmo8GyswPhn޵; {ٻ!%ER"- CmLYZrRKCd!x\_^b{y?J?A"uMX+EUl׻ˋ۲ˋՙ/c}(g663W u~! V|[]Vʪ>wZcZk"4x?ݙkf'Ad'l.Ψ,oLo]?szbDUymvc7;|wn ӢL V&RÕ*H ?w!o?  o*U^/WR\-Qh,83- f ᨀׄBԔh@Nqtqͺ.wES(B[#?ᓽ4++J[_/?tOk'i>ި&-7 ˠd(s F\T;l ݽmr* hK?<ƫ&ϔwd2_2lY1?.4,bVİP+=F(!<&GK1_ #l1%c8'L *;!N0 :vJȡ׎+==c06 t1r5Bѝ"Y>{ a/@{ f]8l+^Y 1 :0$7ps1y0Q2X(y^']'eNjҕWIv+ G)@oWf`OQCYhQsX!Kh B= wˍaH!5aQd >3 㗊&LU7qUi~O>>px5-jVJ #!%G+/Ux>>!^a?y&2e囘2Sp?/Ekq>q*J$[1<tui;oq\.=kxq~!la ėK"?fkI)1:TD>z1BJ&LG^Ed09bQ'ae$  A`GI YS@ZÍFZiPvbnMj-;/F%^EGRCd o =ZYtd m#'B{d01chQG- hAZM/aXtaR[@#o񚽹s!.k6%-d!Wy68U0kiMi28Gᙬ?"'llx+7@;12+"j'q|!{/~d Zu Ҡ,G)Mrn *=1!c0,1HGIWC.mq90V ):YcӉN< B MJ"f:SUCyz0F6ol&qi`G|-f^˽]!K 6#y,+yT#/vZ ;CpGS [US=5a<4a>5rfiT0jxFh5?{)ڻχ20!!38'2\d3q ϓЄWUGl&6oXBYCR1ƾ^pьA_Px;ӎf d.zm\>AG7\KcſwLbof/j_ϴ0QUSFcn$j3ч7?jW4m$-O{ѼɆ>WP=NX:m6گ v\q(L^۩unEqU.0J/bE# v|N}V#d5Y)V*t@qÇ3W)T2,`ͪb[%XǍI6|4A\``i;UaFKn#i5i^O<\JFtτXzakD,a)`"aeP0˽]Fvw #jw?gҦQjEU;+^ZɞZ&A[i6F\ex3L?( lvm<.9p16< JӦy=s&LMJ54^L$4Ym^&*}&f5aaWnڭ 8/nG=j/9gMy&x6N%+K0˳D.\g%:INAo$t!#3lpWsw4ua ~=bO^kwbErwT|1o{D9)îo-&A\rgaq+wzF4gc 3]m6g3KTNL+O?ehZPIhUG}E@.l< EЂ\:ISߣ"QKjVn3W3j2ƝJTa8J%9|i=VOz#7n^rfQ ĝx== E;p̙:Č-Vu$Vv.4.Y=}Ĵ /Ah_ Lٳc}W5X OVPM7;=Njjؾ SF\U!ږq3&B?^w4o,7?W!Òѵzj d/ J3ǥQV>p$7 -naigobi;YP<z-0]Lqߤ,m8 ^A<]m^rĵ`嚍'ԡ}v? ⹀)78} WXsVj,!y>p ON; Wس`y"z / IUiҼÑQf& !u}h75_C 궚ڳ  ;9ndϴc߮z&LȭtCUS&<{=y p@0]m&8[Y*Nh1FS-PE endstream endobj 119 0 obj <>/F 4/Dest[ 117 0 R/XYZ 125 280 0] >> endobj 120 0 obj <>/F 4/Dest[ 122 0 R/XYZ 125 497 0] >> endobj 121 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 557 0 R 558 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 556 0 R/Group<>/Tabs/S>> endobj 122 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 559 0 R/Group<>/Tabs/S>> endobj 123 0 obj <>/F 4/Dest[ 124 0 R/XYZ 125 735 0] >> endobj 124 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 560 0 R/Group<>/Tabs/S>> endobj 125 0 obj <>/F 4/Dest[ 127 0 R/XYZ 125 735 0] >> endobj 126 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 561 0 R/Group<>/Tabs/S>> endobj 127 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 562 0 R/Group<>/Tabs/S>> endobj 128 0 obj <>/F 4/Dest[ 127 0 R/XYZ 125 440 0] >> endobj 129 0 obj <> stream xc` endstream endobj 130 0 obj <> stream xu 06ݩX# #%\"$B… _[&SM^}_>GKabT' endstream endobj 131 0 obj <>/F 4/Dest[ 132 0 R/XYZ 125 682 0] >> endobj 132 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 573 0 R 574 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 570 0 R/Group<>/Tabs/S>> endobj 133 0 obj <> stream xc`# endstream endobj 134 0 obj <> stream xc`e_[?/H?\UD n`0P>PXR {YKn 羃@/ endstream endobj 135 0 obj <>/F 4/Dest[ 142 0 R/XYZ 125 440 0] >> endobj 136 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 575 0 R/Group<>/Tabs/S>> endobj 137 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 576 0 R/Group<>/Tabs/S>> endobj 138 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 577 0 R/Group<>/Tabs/S>> endobj 139 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 578 0 R/Group<>/Tabs/S>> endobj 140 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 579 0 R/Group<>/Tabs/S>> endobj 141 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 581 0 R 582 0 R 583 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 580 0 R/Group<>/Tabs/S>> endobj 142 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 584 0 R/Group<>/Tabs/S>> endobj 143 0 obj <> stream xc`; endstream endobj 144 0 obj <> stream xe 0D0#c1CaѤ3 *p$B_H_]w=&ÛW J~-]t(H3/q m\-vS<-0[`ϋ2%>{3 endstream endobj 145 0 obj <>/F 4/Dest[ 151 0 R/XYZ 125 545 0] >> endobj 146 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 592 0 R/Group<>/Tabs/S>> endobj 147 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 593 0 R/Group<>/Tabs/S>> endobj 148 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 594 0 R/Group<>/Tabs/S>> endobj 149 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 595 0 R/Group<>/Tabs/S>> endobj 150 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 596 0 R/Group<>/Tabs/S>> endobj 151 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 597 0 R/Group<>/Tabs/S>> endobj 152 0 obj <> stream xc`; endstream endobj 153 0 obj <> stream xc`CYhfX ,pf-L"`F02 j'P2& endstream endobj 154 0 obj <>/F 4/Dest[ 155 0 R/XYZ 125 735 0] >> endobj 155 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 603 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 600 0 R/Group<>/Tabs/S>> endobj 156 0 obj <>/F 4/Dest[ 155 0 R/XYZ 125 701 0] >> endobj 157 0 obj <> stream xc` endstream endobj 158 0 obj <> stream xc`@a0Cg \ `$ ܇g@ᗣ5suIN endstream endobj 159 0 obj <>/F 4/Dest[ 155 0 R/XYZ 125 673 0] >> endobj 160 0 obj <>/F 4/Dest[ 155 0 R/XYZ 125 482 0] >> endobj 161 0 obj <>/F 4/Dest[ 155 0 R/XYZ 125 231 0] >> endobj 162 0 obj <>/F 4/Dest[ 164 0 R/XYZ 125 635 0] >> endobj 163 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 604 0 R/Group<>/Tabs/S>> endobj 164 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 608 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 605 0 R/Group<>/Tabs/S>> endobj 165 0 obj <>/F 4/Dest[ 164 0 R/XYZ 125 203 0] >> endobj 166 0 obj <> stream xc`# endstream endobj 167 0 obj <> stream xc`@A#2&c200P9@p>#όP`H 'g CB .% endstream endobj 168 0 obj <>/F 4/Dest[ 164 0 R/XYZ 125 169 0] >> endobj 169 0 obj <>/F 4/Dest[ 170 0 R/XYZ 125 646 0] >> endobj 170 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 609 0 R/Group<>/Tabs/S>> endobj 171 0 obj <>/F 4/Dest[ 175 0 R/XYZ 125 735 0] >> endobj 172 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 610 0 R/Group<>/Tabs/S>> endobj 173 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 611 0 R/Group<>/Tabs/S>> endobj 174 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 612 0 R/Group<>/Tabs/S>> endobj 175 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 614 0 R 617 0 R 618 0 R 619 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 613 0 R/Group<>/Tabs/S>> endobj 176 0 obj <>/F 4/Dest[ 175 0 R/XYZ 125 661 0] >> endobj 177 0 obj <> stream xc` endstream endobj 178 0 obj <> stream xc`@L0O``ek00<g z;\=+~ Al|d!$>`!B' endstream endobj 179 0 obj <>/F 4/Dest[ 180 0 R/XYZ 125 735 0] >> endobj 180 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 623 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 620 0 R/Group<>/Tabs/S>> endobj 181 0 obj <> stream xc`# endstream endobj 182 0 obj <> stream xc`@L a:  B  HOn@\Z^c@4K*A4K :ϗ0 endstream endobj 183 0 obj <>/F 4/Dest[ 184 0 R/XYZ 125 742 0] >> endobj 184 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 625 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 624 0 R/Group<>/Tabs/S>> endobj 185 0 obj <>/F 4/Dest[ 189 0 R/XYZ 125 735 0] >> endobj 186 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 626 0 R/Group<>/Tabs/S>> endobj 187 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 627 0 R/Group<>/Tabs/S>> endobj 188 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 628 0 R/Group<>/Tabs/S>> endobj 189 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 630 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 629 0 R/Group<>/Tabs/S>> endobj 190 0 obj <> stream x[moFno$( $v]ksh>Ȗ,M$W߼쒻b|AٝyyfvualVU*S)Lfdal:?ls~7"kRgo`PV?,ꬶgeۿ>?m,̄8J(Y&q$V6/Zwx#uSH9]>̌(NҔVyu}9wYem =h/g,KU(-S5X\ O3(cO^Zɢ:byku>[|MRyыAfaf_R~eYBgw/+x!^T*Kr^s#g5budO0p@BL[Q`r*:Y.|XW6fnHS vMM틧o&J2S v*:6^(sEBYY@JJ3B3"bu0 f'N*X5,Ii.L0'x\tlLDf<%}|iV2%=17Q%;\RG+As&%!fը  5qN/oQnzW~eMf2PUj"-ȩZ鴀0&65Ʒ{pTilm$,e| hDSJH H8 GiXLBV131~XApX5$E%FpXm!" CgHES9gS)!H#HB?$9`pT$œ KmTDr f|f Kfs)0nDDCB[s7sf |cnz{tr/ӂٖf.1v6gBB|oQQ7@[@#c9 uQH8C6p<֔ӶDCjS1͛|~ˑ~)S>ZJ Zta )ϙh\w.TIr`~<3nbjWUx"0*ƽ&]f6j]؈ ́ɤj,&x#HOׁÂ,<̜з7{xpc6aM-,~MiEyfMi9,~xxqRр%zMR*orc70!ij݊QؠlVB'K(CR9h*;@XL)Rf(l!܁fyݾG)xwMQFVn]|WFsdY~ )@'@UBh9e*C ee} > eo]@P8TK]>f0 Z2^ (J"ZJ ↪^{%`XUyčs81L#vI4 ǐ2_fҮ6}S`qP6O>P$*jihIwWUi@HȍF2(&E %<}؆RDD9.a+'}q|ŵ) eFAfd+FLPvAudAe0 XQ?b^>u9MBⴥ)}nKP )+P()Lyh[l8d0k0 '}:M0!AΛu(K*mIQUؘh0N%nS2OX2 kۅyQy}lRʯS^V= aEf_/j!ei M !ܐ6t|yPҢEa*i Hud )٩4CY[W#("h?i.`Gt e5&z~Gh M?`sDݭlVB/sנW n:e 5%6PꯒQ ĕ n?@E.3X3q):[d e7^N@(kدjq/if%(^fgzO2n0Evec-lj\g+Q\#-;]hb?Y풇"Xވx\P)DӶ\e߱7qU.m3;\priofsIbG'n~jgT0A%GBTIػIn믜PH||ԐbS?#},O~=Ҩd̓Q2|J,ugłpXMnhɕ3J@_uhтSC2ܲX.OZQv&}[ p>Y>EHׅ(dpHb׈qGH +& x5kk=-v8[Ihw+#kM‘X}uFmeNl 5%/Dq>9E#b"SlS3Ct8mFöY':bt9S#@o#Mqp-,ՠRD7ˮzϮVmOduP ?3RtGk2<ݏ2U CQ^| DJŴ8)R۩{}_;?ھiz$$ ؈h]dkN& VxI!bDf Ĩ%=X~fJ Ǟtv}^@89f`xUl$/ { t}ta÷4!m]{Oh?K 4}'5~T@vuNAv»h{< WɻP (_aɲG,'}gO: ",)˭F_> -K 4 ņT-vPɧ'>ΐc.vZb[8OMeL`"ns"هj8{Ѥ55џ]6- endstream endobj 191 0 obj <>/F 4/A<>>> endobj 192 0 obj <>/F 4/A<>>> endobj 193 0 obj <> endobj 194 0 obj [ 195 0 R] endobj 195 0 obj <> endobj 196 0 obj <> endobj 197 0 obj <> endobj 198 0 obj <> endobj 199 0 obj <> endobj 200 0 obj <> stream x\mo9rn|V;,w9ػ<$^O=Ud73= lU,*O(zL|g\]t|w~/n>y'~T]:u:>t!^w\?}2tOOzԭO~#uxKaJwJ͹RF)v!-Zrћ?|{kGߚS}˳tCY|)U2i7OV?V¯+w÷oUooKS#y _\Z"5 |bv'1{`̉??= 2l-S\~<=2à't9ڒlocz:TH}ig.֩{y.0 hM%!.4#c謢FMnb*aD6 ؽ\[3V_5fG_(0&;ףoVj!zeh?>jݯ=*-5U8oy[6G}SOl>&ɹ_ӕ9qvF 59~7@?#wT_W !a4 C9-CZoK15m_c!ҋ ,]M>v,@|?Gbo4b/m@^r7k5XH6Фi^s2vEY >kgDGsZ=Bi ya /lxJ ڜ/@2^cqȧyHӥ ۇYۗWklj$p{I<GoR+@&zuaXMuGtRqKL,}#֥վßa # =[<6["Wd^oB1{+9?M-j^4׶4V] O+HP˲`rQ]&&+#$w4-()Y^#y!lN롏({ݔ2gv9?w,JrQw/؍>`LSt/N̉d/6 4I}AiCjy'Z%"+b|Xr(z(ܢȭs=DZ0ÀaKtfyח`1&ۀzi`kX$Fҝ#0B+w!nݰxt:=GKXCm-L/-ޔefFX뻏+3Ұ(>Hj"gD`EV[l{i̬=$gH $ R\r^4JV2~"wD Y@sM{=8:9OaiX,%Pڶ"gڶg, 1wXN7@X?r͆=׈v toe.i"l<:>8S^ j ix"L X&|޽;#^':^ {xCv>n}&\-~D (vQ졆fC"v’&#ph m+:,\ G7/AC:I~߫~X XX"Uv,&kĬdҞe.e/hک$y m$HW65C6l 6@؂wLzwLZYD' {~*0ي b!L$>߻z_ё0[1У1ģmE.xvc y}gj=;7bܒ Ii o3y`f#_δ,Cd,3r)Kj)G׷l,FiAemRd%)Hڷ.:]5\M ؈>]q{6+ m}S;uՖq 2HǗ򀡏m h^kHi„ 8W Ҥ6϶-Ŀh;d!ƌ0#^2`,-~ioSroՌ[DʷoYA;7$?gd~%~v~ttrǑɱ՞'* VZ*aqh;Y>xQQy.TrN|rSiCs{~yM'[utڗ> $ Ç9%١K٠Q35 T0o "Ǟ[>s8nڎ~_@\. [`Z=0ʠ^ţq\q%'ZG]҈I@)˧ N=z!k}daV웷`EDҶ8dć-"lmM3*/Bnu/&-N7 >kp^FkdȘ(/0RXa;#ƤB .A{n-_6!36&dl= 72XH[SA'&* 0Q Ni onOT6*)ΦRL!]'7dyZi%/iY榿.*E!7;\ 7ZnYh 7'|6{=Xu|RT'KUV$.tq1٬ͩT|a*Tҧ7=_"%, (}$U #1w >q,#ar51scMC Ïy⣏qS:5Wڛ<3P$of4`s$X O.]K1L#cD8s!2џf &S~OZ4cz.Qk\g<{HVX&EbPXE]@/Ϭ ^e9Domeo060)L<E[I (f CNҝrf^OO9MqxV>yL5J/x;jrx\yV+t&w|q{"F\cuP97Cu1ٮ7-R#mRG/oLn DF}"OEcn!Z^\rȺ 1ʙNڲn mfS/Mv(eOt 6u1>mRo]R{ -dCdC.uXYҶM%E拌evTѪ8NPݠbjǽPx.Ο>q?rrJPSTwƧ^]{C2\:R 3VPSA3ϗ:uxK&Xmle*3%)Pg3x Hf,%sLY+s]I΀NP] ɺ \+lUL].˛d^=1gYӛp/o&Q[RK݊N%R+"/DH˜ c%q g ,| g .~ x_uMມ>tқxZu(3_$c2/)T|EsK<}UoXǜTG;8Z*m4O}wztVp+!Q~! HF4foܒR%&K51 Y!&|6U}mN/bTt/{I#A9 W*mΊXa\\rr+RjUjN(WȔPi2oПpV}=M$!\Jke /K%Rc$4|qqy,C ?L]v8rD0Bɍ|&_! Tl$crjJebkq@d!hK[t&~c4ʝvoc.~bSkDbȸ[ iq>|k]{~#AͣD 4SUYpN}xsU&$v4 ڂ _.%({ _e]|K?@{.>ECN%P saI2ʲ#w#* [4HNNX_г&弡Kk1تϢiЍ+|IRY|ÑO[|F|(_/Iإ d7So6:1̾"ӬL # X:[/ָ!s#hf|b0;(oCCW;j;ĐAڦ򄖐R/kTn r&c%&Ž"3*8F0.Ze)I9Q 3ts@I6#hk:*|҄I\2X[&+,>"҅+xD|u$6HSxK‹:`'Y V P򎈆O4VYUqʔZz`҄vEr_f| 7(K snc4[O`riߓywwKKY!3>&iK \êf/jsR;,գ}++ twe`f`'3z=UÌrZ*iޭ@˥T vxJŦG2:HuQͫI3g KlR7v|+mz]>5%I)hb,48>ۺ F83׶L*,=w1#4bT cWBaJތhPa#X&`W,-FБ IP$4ȳ`GhA$IIV)xn[)peʖ/R9R*| I ˈghq#G6 N Cb3U _u k7cE>$.ߙbӝ)jC'b(ǜp$ qb+LZlħׯI8Wm#Az/ey;Pָ-U>0_Js(@dpj; OJI+fᰃ,l=`b۟f@J&msQiKq+JDk`p.6s(fr> &s|q+dx6ȳ!yfmODGgsFi|+ÛȪ}0VyPy]]|S\ḁ>12ᒑd/qc"W)C*8%K(>J8'/) ӎs|T+S#RnB1qdR> stream xc`` endstream endobj 202 0 obj <> stream xu!@E?@!I (. ܃ 9Wax΀0$汳?_f&jBбI u`0UX^!NOyݴǡt-@k/xn%|| ^=镮45K<k endstream endobj 203 0 obj <> stream xc``t endstream endobj 204 0 obj <> stream xc` tN8b68#{, D1k)xC=\/ "p} 8:x}`ƒ"j7$qm8 mfI\ &4T(Dn!qSpul| endstream endobj 205 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 449 0] >> endobj 206 0 obj <> endobj 207 0 obj <> endobj 208 0 obj <> endobj 209 0 obj <> endobj 210 0 obj <> endobj 211 0 obj <>>> endobj 212 0 obj <> stream x  Om endstream endobj 213 0 obj <> stream xO@#.VJ֖[͵eVjDcCͬ>oswoU@ rPgv2|I*ׯK1mT+#4'[l;ђ0=6*A,w:'_ydDUDgON3P)PVk s) sͽe4(]Wћ)?%2ih&(ջ?[`&y`\"bq4'qBŌ&; YQێ>feYCըW%%\Ӆ$+2 nV7^Y endstream endobj 214 0 obj <> stream xc``Q0 endstream endobj 215 0 obj <> stream xK P V H)Oڦ[kg1L"B`Z{)P:ᒫu۴x 6z Pp`Ԣ7cs9)VH;1>+(ٖӆwA4c n endstream endobj 216 0 obj <> endobj 217 0 obj <> endobj 218 0 obj <> endobj 219 0 obj <> endobj 220 0 obj <> endobj 221 0 obj <>>> endobj 222 0 obj <> stream x1 Om ? { endstream endobj 223 0 obj <> stream xc``) endstream endobj 224 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ?" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?{;Yon!1{uc @ 򼇮+'1#5(a=f?tq4{vi>YG!}h}h0}?ޗ4YKѸa=we/Ɨqqð{Iz}fwZ7Z=;q?xo>n>c'o!xtѸa=?ޗ?ޛ}Mð{Iw7Px;EO,޻V7SHX㩣ða&x9 :Cd=o\yub6SSf߅O?uxG?'ֺx7:.hG3]1$Fhfy4\ 3Fj<њ.5h fy4\ 3Fj<њ.5hLњ4f&hG3E4fI3Qp$Fhfy4\ 3Fj<њ.'fh'.5⣖J-+gGFdž/$v]ΏϏz(w;:?<+sOᨣ/{|Oᨣ/{|(>]ΏΏz(w;:?dQGc"+rv.2qxJ+Mݛed endstream endobj 225 0 obj <> stream x=oPoQBډ#"ЊiPUP h6̂`GU[: _{[DġGl>g8t|JR𩨧XE}wij:ڨj-Ed#{!2=_M1좿Cʾ9Sh_/])Ĵa/!yF2oG^Bѝ-%/pQ o{ 119̘"9pppppppppppppp 1^Q !b:~Q3ݩa/!f5zO?k,-<-ODtB,MEO;}{_W.vt1GfJ>tبNO3sh,d݃Oz&K;뭍o'}vUͥBZ)YXL/*b򪋗N-*r1giBZY| B؆{lCIW&QR(*"!0Od endstream endobj 226 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ5x" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?6 ķF Ya]ݷ4/%|וخS_H׫uC J28JVL_D<=MG"7SFkñpC޲ghC?Fh}M qG<=}$n>ayzI}O&h}M /"OD<=M?4n>ai>!k}.! 伨ۏ#1yðY=pz*WTGSc1kV/ ^I+ ÒKh]70&7T{EěQp&7T{EěQu nfifi\,r$s)> stream xJQq̙wgFE^$WbA!Z6BhU#LKA{]ڞDps~.lا] Y6L 46.ڃFkHֶ0\t䃑ֽbrkXW`ݶ&"67n'h$imX6"Wa.s\2e.s;g=%ϐ[R'.@lj gf})|住pr}03B ffJ}5B< B$jVn^lEM gΥWLDeqݍB^T&L\6G [FU=bD)fDª+K0(ɔD̏8D5e5u endstream endobj 228 0 obj <> endobj 229 0 obj <> endobj 230 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ5W" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?6 ķC<»_>B+>9;ȮS_׫uC J28JVLw">I &F]i>ƔxGğ&FGo9_D|=??di7Z7Z=;<">?UuNvZ}i1֏cU'!o\򢼙Iz1wI|0q}'ֺn+kSzgu2]nF鹅7QXu=nbMolҸqf?:򢼊=(|(Ӌrn+k[*:+\73)kX6g=X7+_u+rz7i?,s/e.ƶ7VW? ?,M˱Օe=/{hwg.ƮkYۖ_? [vYmRdj:+M+HX;bET((((( endstream endobj 231 0 obj <> stream xc`QJF%FSS> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQnY" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|'aej/M$A3bsֻWYC*HA\W%7s)!zeFP<]Yƥ!G'o}M>Q9}O{ #KG真Ʀ4d=E3!r?>SGOy!ƏB<4)'5>ObvhQoSp2t6xMvf$1\u^8Yk TGnTgG M\wkҸOFokSu7QRfRfI3@ Ai3HO8_V}_V=/x3B3?]ʞ+o&ֻ W/^}oH<! )⸟Z]4>~h74f9,;4f3@Xvh74f!_?vjx/_/ֻ%yc?QBkGaHw;kkXЮ=@% U sE3(G endstream endobj 233 0 obj <> stream x;@QR+Qb6܉6܉:Lou)Lο/7>aE.޴UTտwRۃ}}!nB`>g 0` 0` 0` 0`] D0LSYnd6 xXZƴQl> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQAY" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|%cewЙb *G>ޯ<.Bj\G%7s)0vyKE?B1<Wq4n>Q9}O{!+_ſ(_{ƥ}MD^ڧ?I_q4n>e? 4ɁKޑyD~ڧ?/7N`1n3-5]WZrU%6tgEÍFokSp8&ֻen+y57V%7QFę57P$HO!SJ嫧sa_OxH_?v*x?_%Q9lI3QubLњu f 3uh N^+2[sWg7<*ӥs^kf- $Tڇ*UEXʶԗ5}?!I?- n7?- ?!GA7ѾkoQ?- =}k_~C(ֿQ}M5> stream xػ`񞾯*MH00:$X@ݍMbBpMro H[J'm;)uٞ޳D!1jr/+;z"Ϧêu!v^6` 0` =bд qJaMT&P\kx<\7kGxAT&XK/ endstream endobj 236 0 obj <> stream x1 Om w endstream endobj 237 0 obj <> stream x[ 0y\ %ZHRdI%I ;;lxX9{8h׼;z endstream endobj 238 0 obj <> stream xc``Q0 F endstream endobj 239 0 obj <> stream xn0ElNIyysGWυP>ٹ{(ŷd e a$Yi;3 jқ)wӈڶZl"Vιu!4ӭ7Fqft}=m֍qq^Oٗ&х~o!"j|MCYUy4mKE>N{( QgR !3JϦl>vz endstream endobj 240 0 obj <> stream x1 Om3T endstream endobj 241 0 obj <> stream xc``Q0 P endstream endobj 242 0 obj <> stream x1 Om w endstream endobj 243 0 obj <> stream xO 0wn.e eTBdQ)ʊBMKw:v؏gl{,CcH0xo==k,T .MrpeڵO[g8[BK ٯr-oW?l 3x\$B<*򙇆rUE"}|o[ivR?Z> stream xc``Q0 F endstream endobj 245 0 obj <> stream xn DxKc;`/@|Mھ5i4юpx/_EP,G2}r)s!QYuQ*c (r|#j݆z~cG:6Ϻ1z #nܶ罩x}~s[yҫ:GBXZ7= %4gDxѴU%UZm[]e#% JdC& D(eMn>w endstream endobj 246 0 obj <> stream x1 Om3T endstream endobj 247 0 obj <> stream xc``Q0 P endstream endobj 248 0 obj <> stream x nH@!9 endstream endobj 249 0 obj <> stream xc`C023RK|*Rdkgw 4'zF/E62H;{ 1S\<"r Ҽd£e/Fn д ݌j>}xjǦhl<,*E"FRڝf." Q/2\Lg& Yzz9(#ajGf,*L~A~u2,@ endstream endobj 250 0 obj <> stream x1 Om ? endstream endobj 251 0 obj <> stream xI @qߌijCd HdYJm.-?x3 EuTlh}T%Y86҇mχɐ[MQSpب(MނN}W+ qW\q pT)QD> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQo" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? м3q4[}+?Gq8d(S^! h,*?rOƂ&'ֻ};}OßOG"~LZ2}h0pOÿG"^m4dѓO÷}xOà/"~oi2}h÷}Oÿwyo'֏cߐ{I?74'Ɠ'֌=;~A'܎hr!ZH۱ OO[ƙco:Cb+qj'´<ʊڋ=BHu_'fz ]+?vq?zx_8uWIRQ@ E%RQ@ E%RQ@ HvFxBK\4Qo+ǭFzT?'ֺ%?A^Mo?~IOxk?$rv`xGGC|86V]xwX欽LњnhtFi4њnh;4f3@H2Gi\g_fUO|r墼l T+wN;k!7tl02Zw/]͏Ώz(/`ǝtG_` y|Q\=}e`ǝlG_` y|QG\=}e`1FEXLv$jŢU%bE-B( endstream endobj 253 0 obj <> stream xOoppRDldF3M<c^M{3&02D@b}<_{z /rU73jr/ΘK؃XMJްRQϏ'Lc5*ԡO3#a; Cv@(r+{aFO[?9wfoil~С?u~#{ El| |!З\L˂㾏k8XsXGI3:dpH%X Pxt@:Ёt@:Ёt@:Ёt@:Ёt> stream x  Om< endstream endobj 255 0 obj <> stream xc`fvFu3r+H0c3EM9ts(*}UyP)88> stream xc``Q0 F endstream endobj 257 0 obj <> stream xc``0 endstream endobj 258 0 obj <> stream xc``Q0 F_ endstream endobj 259 0 obj <> stream xc`PecCb2fE3 2!ؕ}T9"E&Yy;*sT5T%ZظTxِLeSBq3HTed&6Y5n̼Nr"pɘ[z[rUZ8U0rz"\$h"ɂd 9xĂʧ; endstream endobj 260 0 obj <> stream JFIF``C   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ==" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? i:VO1 O1 2@8aEW0Hl5ErHs9&4{/RahgJ>{y #+J9<ʩ-n8"Dgúk_i0Vs9ajV|@I.Ҹ1HPqoSZU\ݙEWnNUk-Pi[U*>tcw>į?7jjQ2s䇷Q*|Lo H> stream xQ P:AʘԒ!0B$֜)va va 5cuw_GFz',_R0;Pr]ٛȌ endstream endobj 262 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQg" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( YV̏Ž%dkwTE5T#Lː}} q͝?_WmIzUN . WgO+>P,2Ӑ~] =ȨQoa2n䚯o[\,Rel`^F #s{zVK.xP\sK4m|NR O&[iIuȱ.gZdApsۜjƑ6fx84(6oEAop$ EPEPEPfk'ifvWe~*nO]4UGv_(_d Ǩ'sO.pT޽;V!em8f#x氓jCH$y EGq LeTnw>+*Ly48 axv%3$zxJX.to}\eǩ"I@}XJš{}rZ2InG^6d6;Rv-Żry`U؏ÎtD3;~uIh}zo ,ViQ'$NM-ujZƩ#q: e9*ՔmV=;~UaC3?sU.2x3[vǒ99\z}8EHtVo$Hg7>sٶ7I'Ho_[t+mx~`Tx`zDJ*.[n_oCVH(4U]Fo*O?i]M\n[ϓjj %ǷA?)Cn]u,,!K En#zf{Y^R?JoTjKm#3M82ݳ9VnChrAwOۈPp=+Ob^V dcy>J mmdivrNk3@izΒLG ;p;TiDBdF8XZI4v__w2);i /`?֠%{ŭ0OPĊ#񖻥IO; Ǩqc|Sj6 EIcW[_.FwM0Xmkܟ^7kio.Ӏ//`O?^xCclHuB0\ uG*s_3\ 6UZWz(E.;q=ۻ?zx6*~bvwc=y8Ҙit,lKI&2#\rOLR6mеXɓqpj 䝭A&N#'h$s^g!|ܷOvQל`c8ec9lmp 6:ZSK]yӢ=+ʌQ`E(5L!91̢^OA\}΢t3m~q)Dz!ʶ֯# '?S4Mi 1\t> }j42}4d_ҡ]I:Htppa<%Z3I.9@``1ӁӭCG-\*r>P?x9V%g>THZqIZ/un[ !o:LGɌQ];HQT9 8= sNt5;2dŷ,3=WV),"@}EI?niE,[@"܈Â{qP6xfKۯoO<G[I_a]LNj7_Ў&?c$8srO.R5JQ6Y(H.Asv ]O#d1(@;rq:Q lHG\d 3[;xɪhn< e) Cq2]mr?Y3˷׽[7콺#СԟSH<3LWԮ c$iono" GuXj&5(Qii (&V$yQ|dGA~aҰd/| u!36ї,qfp;~dqUYv*0w'<uIk*8yW o2,}OW \74Ӌ(%YI|UkU;)!;~Au5ϘĞi,qz RXkIkpsVE=ѱ<jL'n,>%uu G>ty<)f;Yl}ZIN-d+J۷muqq>fzO3شsO%/qs@`AϮ1TGz~fBxSF}bPO #=pKvQ{կI1=:-ii1Ƙڜ9lq?Xѽr2B~gag4_>pmXC{zfKB>0tAt f]3-nƛV(kRRQEQEһi'պ(w|ʥOY.>^b?_[tiF=ݗfnJ6AϠj$]%4[8I>dvH㰫$SGXW]"xȍ 5L&.Ϙy H$~+o1npnO> stream x1 Om  endstream endobj 264 0 obj <> stream xc`` endstream endobj 265 0 obj <> stream x  Om` endstream endobj 266 0 obj <> stream xc``Q0 ' endstream endobj 267 0 obj <> stream x}[o]{QjD6 0rԠq5&@zYe{Z*\}kqsȪNXeqqݹg9_J w!}%Oyw{O>g}w|;_uٗ]imw\?lٽ-|}}>]_};ouWXe_N^#ǺrrsOܾLK*_~=sIUt!wd?='v/O~c䟓K{SkuyM&ڛ#8⃓}Oe y%xc.Wuً/2)OaYgEʕ=g2b,L--{2:C\\v}p}i΀v=YI%/_̵yrZ:Qucײod Pˬ.:2B|DyGγ[}`T5Oo>0LUw}I!_N^:uK,z4v~w.|;B݇ӳVNklG`zse%c.mIi~yo7{so2T7_G@ Ky2BovԶѥƓ"m7J CضL}۱ʑyS_OO1ܴ | d%Gӱn!}NPN(//UYӥ?lY*C<يNC qyۛƓ;ӳmwM; ^Zo|vUwb+cuNn5m`:mߜeq?O] ;/\yE٢HȂC<|䠗r/(zM._ҥnz@{#`ʎ"u}yƘON`x{zVsB'NAӮ?AkYD:w:wuENQM[.~wW}65)~+Wݭ4۷eo]~-iZwǦ̂oIEyȕ߈T$ʏn7Z.ݔ0}3wBeG  .m5`(݉8w7-_ ^pTn$'v_ՖBl.Vu t{7ս{I^*GkX4Ũ=4P>}0gMI=& %"{78EdDХU+ˏW\E9!*EisW"&.qB"ݻ{YmP뜮/ )gCk2gt^]ǡJ7(V4ﭨ/EQ]ryTNxɻhU޽; C='tr~H{sw7"W*Psw*ub72%d@{?";||{7#a#kA@\J?$ΌP–7Ҏqi"lK =[%n{woIe˳ݭbʓ:Ƹ"s.6PR k+}pߎ)4%l:zDНu!N7$ULq뢛V}/ L.a|^Ӑ7p_k0>R' 7#9pLL-LFpc*'O1#n<c92D mtOmQq%hPmyhRkį,Mqͅ?gWRcQ DGXtGIK˲mHkܫ}yڤٴ}y_` } X`Vmv˪_ n>P9b\}LCXMWk1%o3㧠H&a?8 ō=w#*2T2#@go٦O 9>D*7Gu@3Lx8F1&y.85 MI:9eFIcB<1uiۻ'uݴ)-zl!exVdP9')YԆ) u!np=$yez >mxҙ̽騉"'/e9b'UO5=$ָ Z ph+VQAeW-[6rϕf*w Fy~k\+_;t JW&VbBK(#XE*~u`;.~UDW8FZ fc)؛U ZܮIZ jT,^]Vga KXxVN؎qv܁ 5G;P8GUSbMݢULNxm% }pnvK]/(K ?Eh߻=^릒AU8B~V8z{4g^de ˎgvt*},,60{orCGC9i?nnuZ?Q//^Μ%Ou_.boOڲIMDM$|r۾pq_hF읂c{'BwT6^˺ygֺAG Nm5mnϴpϺmNs}@5i D)(@!@JEPz_k%v'@na|4JF]-xʬQ4Pᓓ@SH6%?rϿuzX`IVg H [h,GW]e:C|>2s΂P@̤J'0^xX*bijy`_t r)kۈ#ŠRr |,^ `RbaԯTQK?cb؃KK+.lBMގ$!a0 Ne=QKe< x13u>kQ6;) }'**":~.  Xovu΀g9yNW;TDI|B\x[eU:3Kjn]l10kٿ 75ЮL 3lzILg-z<4ӏ t_s: h%KdMoDqTg"@g]5s69pw/}F+ouc {U#-Z) <_$1cvsD+AF0 +{\ӊ$5J Yg[+@`ceMŒ7"VV:8(aDK,-y<4FToyBR|u Py ub>o3KJb`)g;A'-;kx9ֺVeDa S'βNWnD,uQR F;ⓨ,гn~nŎZ22|eϺvFZcb@iC~-1nR7^\IJ0C撩Q`EyOU{JVԆ NZ< bhV-Z4g]F֝ʤ1ظ$b@ؼ'>l.z>Vp.,;3?-'.jAY[VZ5mM誥(£'4fgINkX`IFvW4$bKh[PA_bQ[WHfȈBxEZD? P",!O"\EVR8m(n5CTxڀEr0~hۺzjĸkGYE 't=UPJD-Mh߂*zҐVAj]I@~f S29f[hg>/c0'{]72WSBi.#%IK*V$%ph{hh3? A|+'* ^B9ՊU&HGzܤlc,jz~&}Oԗ#O& F˔("fO+ ʲ Ru%lZ~5mE~Kl"g)κbEJ+Iɘ+2=jjw,TB6 A 3fdC[QQf] 5 [軏ŮVoU0M*jpaT2 9JI VS%ᡁ3THcúzlA\6^m"1ށE 滔#ӦBis[ 6U늧q1zT/oe*VͶ3`X4ZU%>V!_hh"#⬢ME4gK#5]#6G&EAs+쾞J#Ci䓑FWvQhgL"$ wͪWgG`w_:$D,'D~B663I^a8~U$y (["g>IFN4n,dA\řPgGϕ]dee$l^Pq 3V2$'stgsHnƣy.ZlʬP^Q(LlEx/Fɋam#Sϑd#$kbIP>CS( (DwfEFXS3h.I[M`d9Gm,}=A"iq#n&yLzi%7c[?GSm%Q1טW?//xb_JB6WFJ-("oH%"5Zjl4e^UrZ0].zHSo4Z8uO#ͬgqz8-5ZbcJKVVLloڵX 6]S@Pav\&@,P_) e 32k*k=t9'D=̔o' |#C~]Bb([h !)/DA#=y2vaJUB&]x_r6KEgnp1rfga_NwN\%Js_l'NHp$2,ΐ'WeZg^ǖ;o9X~[%iT$^x/U悻-HED>:2 IKĬXdr=S\ ~#w*͊ZBm3j cɥa0P Qv iF +R  $O]orKDK "K7{10$0+p`!}yօ04"Mx"c&"G9YZ R] #S-qΜ^$~K;@ A$u.aoky7X0ME\HQo䌡MBR ąd}$ |5@y#2 TRLNv0P( 2CW,|Hz#[zY` 'e6Rx63xs "A\;F-I"g`XBU8<$01qkbu:p8oAGBia殒}Vr7X(ID݈lR!DEĆR) kF sDFbk *k|#3+SyX*sh&?YmAWL  sedco/H'hDh mڞz|\9pSc2(aN8wta-zgXcK E*i9{a%E:s+?jDfxrH5[*HRMו1ȍYxឪljms&52~G)6MlQ$<(+V5YE6V4sCʯb̦cˆɠoФy֋)3L0P !CWXh2kbTXY$\֩]h]V9d (&RJMqEOI K 8Ƹ&#iˆJLSxj\m7Өc|Dq`B43'10@9;>gURAT> tԔa`^`$QNTl@-qXHiL4 ncKVΪyY٤\S-"pY|sZ"֨m%}6"Jmjj  ml\nK+#ث)^n;vs&z'}'Y>=%`-S7v$ nG7jYo "|3A7!($Z9;|2)6\3E(")Rg)4)U"7⾴l V S侧CI 0"gme:pbE"yc)Nk)hUe UB5\WwM|WN* !epU͟܉DL 7`Yy?B+x~fA,_4# eqSل\D ee41=)-FL))c(DRC61E>`F<ܷ'S L `A@EyD1=NBt~6+oĒw-q`]j%88%GׁR pO!/!h2 *C9x>/_h=1Fc"xcFW^}GACxqŅPgMN2KH1g-r9)VI[nv%d̍  o&4_L'9 `/08Bڈ!S#5ͭp[ZC_9psRȜ1p^4͌zl( #_*7tv)j#c)) ,/cqPbi\^aɣPJ9]@Jx"  % f!&4ʹφtf6YӶ4@Q<> [܂iTcpGh2CrHNO*j$RP.0dkhR퀃!KyQD= sH0O(Om=W ~XySݢ*3QBfv]Ԛv)B%JdwƂ_pLxcب:`F|2ǰX(,#[~gR$QCG mN1B3zKƉnXձ7P f '{g%ęq$YV 9 Ja3B_- L$fl; Q\W_̨dqtXJ,Ra"7`<&_"q)ښ>](UQQ*P7zf7*Pe$D1M?]Y 8TЃyHAxO 0%BtP _7pk^JW| @*d?!𘲐qc%㖽 meƐGtU=g u58r?*$(@4S逇4 ~1wB2Rސ̕ΕOP7%.||pD4(@'C!)C0icn*`lKY%w4dG~.<^ƖC $˭A4/g1 h9k8"?2_qXݰsC/E\~ ͛ix_6g)T&uE)W!Zt ZĨ0Z8NGRT0[3+4D[D)@ 1BqW5WY EF)Zp̫ 5 tϡ<Ϳ"ٙAҸ̱~p #"1ƾR O8A&0*HV m%#:dU_U 0,-d(mQ 11+x7`J%Ql~ O81/`89DnUT} $i$n#3,R]wII$pF#fi jy*٫gS$0,M drxpҤM^cf-s ET.ӝhM]ε{J]y 7y"*PH;=Q <<50GJ9N- R׿NЭ-j`w t27MQ^RwhYڴmHJ-VbR9N ߴ \4`>\ǹ^4ÚhRP.Q7G hA '*?RZmیFrUE|bŰ;$<] U7W@c/1^ߙExk51C7yQ5)y,.f_QHeDX /Zζ{ ǭDr8I=ȉeN ,kG79}T@ ]In-dDz z`S.3f endstream endobj 268 0 obj <> stream xc``t endstream endobj 269 0 obj <> stream xu1 @E?PkO5< AX,6 >3 3 3#WR{φOMX`洰YIoCuF9UAoP5:Iasݦ/H ԅez, aEѪ&N ~ endstream endobj 270 0 obj <> endobj 271 0 obj <> endobj 272 0 obj <> endobj 273 0 obj <> endobj 274 0 obj <> endobj 275 0 obj <>>> endobj 276 0 obj <> stream x nH@2 endstream endobj 277 0 obj <> stream x[O0ו نlHb*F(D!-S9M\$q{Ӥ}|w}>Z X*dC J^DX0(HJ2OErx*R(JU7GIƨ;3g":۶gǽ$'n\gDmbd |˰v=ڦ!Q@~ܐB}S@GL | ā8ڋP!?a4_O| Fu#u&J"ZgǼn[),j7HՍ5ƕ*@Ϛ!)UxxEz0'f&α'W_GEFW c9Fauids Ũ(i6{%[0@eHo~yu endstream endobj 278 0 obj <> stream x1 Om_5 V endstream endobj 279 0 obj <> stream x90@d/ LcC e5Rr*Խ1} K>Nqvn[Y) fKuj4>n!R|P6ZJy٦ އm !X{g#zrR0 FϞ g endstream endobj 280 0 obj <> endobj 281 0 obj <> endobj 282 0 obj <> endobj 283 0 obj <> endobj 284 0 obj <> endobj 285 0 obj <>>> endobj 286 0 obj <> stream x nH@w) endstream endobj 287 0 obj <> stream x1 Om O8 c endstream endobj 288 0 obj <> stream JFIF``C   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?ഝ Rּ_'nҢc9#=JCI>2W$Ң,v=_|c?PutMtM/h+IxNxqJwv"+BOECZ?%zT9ۜ:PL'?\[mY_2*}&TJp"UǚRqZDu]GBߐY:Q @lpNFk4x#!vOڬdT %/S{OɹV<(#~֡I^jGـ#9PI`c۠faDdTgkR}(?>`P< `/f 0h=8@:*NV50kg[ n^4N+35hkvbE~v$dֹ?-/M>LP+r0*>#mUEb10T)+;υV7 `=igG^myos=!xV?e[YzB:85ܥ+eq*e,6'@);b#pY'E8m<*[_"*!NSuI.G͜c֣˸D{裶/,P.Cc\As\6S(;S?e[R?7nUv=ꎵKC  \rv0O #Шrά-hӛ_o-"x&U 2qLsr(V#Gl*@@5\ԗ<'oOד9'$U6jW2TS + (,M}yp'UcNXv?V>m (6G!U!P@QE5/7qL%|w^riW.y%abǒX$&(I$Gg x~S( (? endstream endobj 289 0 obj <> stream xA Dѹ+ -PDV)/HdldB!e|[3ZOD; FX'^ޢQwCǦs + endstream endobj 290 0 obj <> stream JFIF``C   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQSS" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? ( ( +ּ 4gzz2 x['9 v)xfki(%eIH9sWQbmYjW 8#sLs#sX _ a%n?C] |G`ͻLdP={9 ɺ5 (˻ t]2s:*EPEP[% S5l_Br>1Sڱ./⵵VڈIo΅4Xؒt}'@sM+&-GU-',>߻2:3tré~ltǙU]!I_T,wx @ǯ<<}jUU\B]֛+^?>*ڕVeBdr_$xŃhM]۬qeN-"\mR7m-pf#2{p"v_sRcB()5 !{8WWZ Yrp={ڻ_~*U[ 6*LN?WXM((ᆇe9mgw1 5W -Zan*/x&{oiccR 8N>cmZǰUO*=UyiU;Ir g7 y_@vtMJ8; >~p:ժN'BF@ƼC=Y/9DH'w'fVrwe%`*FQEQEQEQEQEQEQE endstream endobj 291 0 obj <> stream x[ 0D=:0I{Fw$4̒aYthIHpICG$\<*e-¿ g١Ql!R32ظȓDċ+Dy qZdċ_9{E23߻vQqO P ,UiRA%4NrlN|T?PE⥂ɽ?9p endstream endobj 292 0 obj <> stream JFIF``C   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQNN" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? (m廜CR0Q <"k?34Nlv0|qÃԌ{ׅ95̪~o`3ّ׷}3K5cSVH< 4ڑB4Jv2!qP3#?^qd۪¥0<^ndR0>S$_Z 0S\ PIsYΎR nFCҼ -$d*YQ~4EWS6A°# c xNkJ[RDy!pX^kEVBĥPS'ޔts}G- \Z2"Qޜ)* ^*ը%RGR/U=ϸjOYsc߭Une]n;3j }Q?Qɝ{?oɀtW~Fwmuݹ?J[ȗִC E夻ZDF"@bTt4;m/P;kcp1W'^83J6濭x}jxm5rz sc^MKkv3c$ \;%'ZOC*Ďzђ5tyDDeO1dr) z3:EFH\Je坽As6{{CY}^^y[iX c,p;;I Qbil/bHFxHگ1 'Uw+ky.n$XcK9zv+bTP\˩G^ 8sF8+OZvY\D3N3WC*Kr#WSt 5I%nx8Fu]튝 29=v=0E\wA# l" 1"ӀpH<GoyOJ2h+?"aN'lR?Ɩ6TWym rOKWHXtVx9Fnd #iȱFK$w@mYa 5Ű(i'3=:#\Sn4Ȝf`9U##:ޞf+`8O sӊ( 4Hkw(&+i /*n|{E:jHsspߓ^KEvZ׎|i"Y-ۢq#ҹS,e݋:( endstream endobj 293 0 obj <> stream xػ 1 DQOk,?F \XcI9%=Lʊ +έBi nEk+/ڔKa3.M8TKc6 }q% ^Z#[k?-kf gro 1PmgK  :$а@sI\3`Zc endstream endobj 294 0 obj <> stream x nH@2 endstream endobj 295 0 obj <> stream xO@9N0Db5l.UK34N,Q82G>E ߯?(c!0,Ht^봛j*Ah!./0~HL_u][l#zCډ+掯cD KOSά.G ]70|?Ğ{b;P!wqp%i GLQ@x>Ro>MuG.{.?WZ9)383uU֌Hn,{NĶ4p;MC=; {P$*rZa ȁVO1؜f#D沢$\.&%w_dX!߶6|pu endstream endobj 296 0 obj <> stream x1 Om_5 V endstream endobj 297 0 obj <> stream xŒn0 !J2$!6v͖,Y߲b@ |XHAB< `@}s5g]VUXzJe2f%Bb%oWTQ4  :dD<eHy+#L*T[6.ֶz4{ޝ}?/ 5k>76s3NK7lF+7.Mo?W/ 39&GI2=(D endstream endobj 298 0 obj <> endobj 299 0 obj <> endobj 300 0 obj <> endobj 301 0 obj <> endobj 302 0 obj <> endobj 303 0 obj <>>> endobj 304 0 obj <> stream x nH@w) endstream endobj 305 0 obj <> stream x1 Om O8 c endstream endobj 306 0 obj <> stream x1 Om ~  endstream endobj 307 0 obj <> stream xA0kmF ?%8:e'Lvm.} {JTlѩz8U穤LNF8f?Ƴ `o( [Pzڊa@ꠍe~O+E Vhѫ endstream endobj 308 0 obj <> endobj 309 0 obj <> endobj 310 0 obj <> endobj 311 0 obj <> endobj 312 0 obj <> endobj 313 0 obj <>>> endobj 314 0 obj <> endobj 315 0 obj <> endobj 316 0 obj <> endobj 317 0 obj <> endobj 318 0 obj <> endobj 319 0 obj <>>> endobj 320 0 obj <> stream x  Om7 endstream endobj 321 0 obj <> stream xc`` endstream endobj 322 0 obj <> stream x1 Om O>8 endstream endobj 323 0 obj <> stream x  Om7 endstream endobj 324 0 obj <> endobj 325 0 obj [ 326 0 R] endobj 326 0 obj <> endobj 327 0 obj <> endobj 328 0 obj <> endobj 329 0 obj <> endobj 330 0 obj <> endobj 331 0 obj <> endobj 332 0 obj <> endobj 333 0 obj <> stream x1 Om /xV endstream endobj 334 0 obj <> stream x1 Om > endstream endobj 335 0 obj <> stream x1 Om /j endstream endobj 336 0 obj <> stream xc``a endstream endobj 337 0 obj <> stream x nH@pa endstream endobj 338 0 obj <> stream xc``Q0 F( endstream endobj 339 0 obj <> stream xko($p0I.zm+ ERl{΃%WRrgșLȶ6jq}U.ߟx-*W7z vMV>?k|U7äzW0˟~xHNVB JU)}DV5kZŇɻ?<# kWKypٗ^̈2^5.[_"?+FJؔM ;VXt' 3yfKEJ[R+k|!7wҪTxLmžn.4c /F*JUmj4RM[;̞O\-*`Ii0yn*bfcNfo}S6d 90"( lf s[w8on^P?~HSGņ(FB  hXע` G] Ehj'\a]8;F#\2kjEK*@2,°EƝdJJ/^}G" K޾M=} j3ܢdu&{0{t'?O@Kϛmu7Ub:SNgawkTx 2kO7)רAKU=l7c9dUr1\r "dōӠ/ C;D aV[dQ# s셹Ey,uŒ, !=NQX7J?C: dWSt)r$%Y46hn0iIf?js%ƥ Qi%jaFgl. 'y}`2耂)$3PU.-vs7Wc^8էX>C}RS¾=%D{  /Jz>}l֝m>+ucQ/kBF9@O 1KA]{"ڳ63$* +܇'HdTC& K*p[2F: KT|9;pE]X%Y E)tYhY=fSS67dƳMRF2yG%8ύl"i\ιo߁dL_|%"e@DTZㄡæ΀}WͩΈ/I==AXgT&_PEc> aXTirz\:Uxϥ}jYAE`w >Ġx*G1)G. _弱Rޢv*`3йnT۠ʶ.@}~a|H񵿘9J/KW1bX:bPPM2cձJI <6Lƒ,@*s V~ a&.hKIdR:%v}#*/Dݩ"7Pr/،JHObsL L[ǙUpz2N0iw k ] H npn7}7+?a`}]8$ݜ]`[@bXX )x]jHΙH*1t~ cdI ŒCCx8]to81e@O2܈qѺfr3ߖtQ Ki 7\u kov@RR:O]o( knnqw Bw |.fD&0&6D_Q/ؠ F?qΎc^ |d^ɡ|rEQO:[C-Jڨe,Na/*HC@[Χ4(A"x^-nOЖ4n>m b]LF|O^{lT lh.SIbo;r J 7mLҝל))BY \9ѫ}-xj"TǪn6#qD͂5 OQiv ##E;ܻ V,@75ԪR^х_oco-spbsx^ѻ6eߌ9KxK$r2X;]:5$E:GfJrO <9^ .eYԡРsN)e3j"o>[.m;nI?!FJR0 %EQ˫.thٽxC\)wZؑ߸s(,mWn)ca_0}MDOSʋld shaKnEeF>Dp{DЭ̷s:% l"DZm v^TbV7R'CtX1(ˀ`du$E,ښ9ޛŸHI[ɛS!-T ٗaO3D) UcPYI\5%װ65@ZE*װj_pq* \ܻpPWTE]^ϦIM`"u yx\Dz=Ebp5)z=ox ~-Q' 0eYtТK2 >eÖGSۂ?L(O!c fԷ;FC:6iv2z/N9ݏ".Bٺ>X p;?$ራPXsB,6RнLG7NOmX攕cA&kBS9Tj\_Y-#/K_ ͹/_txmCFpX( †I x<30fK?l8cł"SHb0wN;tl~ Қ]&fv^ϱzv:^L0?ה!!ʻr#s&0)T+[x 9MnJ`"M~H+{߼ߊXYiH>wFxGhUQd38?-ϔGx WPM Oa)ÀuVa.%,‡`b`Z@#x)/a$6/g@FMmziVƯEYD3')MmYZ%X?RZ_a@<"% Ƕtbp9~݀)m5 6b۬SHDはWq2#$: 2,,-%5'1mx~Hm@|I=gΧl}+Ϛ<8pjQmP%&;t,ǏT0uwMX\9 Ԣrd<15'w!̥AVRxXWx-2Z2=B~) s.xk(#ˬψR@>/rewr9q~_R(m[t,2ٽ/[|̓Sf ;+ ZYxLs%h.i[ NC -u,?XS4T5+<;<]F^AO*x?&+K-TuҶ,98JGE0 ꀌsuOas R0R;.o=XB,H4Ldz7ЖI%Q4[1y,3>u#3bnץo^\+=_i__oPҋp8 AyvƜh83xdP\nW r6+}06{ayQ8g@%uS!geC%Jr]]gpίZG#o endstream endobj 340 0 obj <> endobj 341 0 obj <> endobj 342 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 629 0] >> endobj 343 0 obj <> stream x1 Oo7v endstream endobj 344 0 obj <> stream x  O7'_ endstream endobj 345 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? )ȏ#mE,}^dmReb`1@cP"^9,|]A#J߲LJ9?m:ֽvuAgr_Oq}¯]{)pٿ1@_*z\t¯]='oP COq}gv/=(_I?W?{(?~b8U'~='?~b{(_[U'?~b#ȕ 45RYNYiW}9,}}&vkXrEx?6J袊<qX4 |ȟ+TJdvF0 N*/濕>ȋy'GOʤ#!I|C<(y1$EL_?O<y1$E>gOQ<(6-I|mz[=cPY?Mx?6J?Mx?6J稢<#$+ݡTJh/ҀEPEPEPEPEPEP7?J=cTOҢ?(~Oƿ{do@Q@'d{?^?#p1^P袊((((:aVQVG΀&wP'VEB:W >`;K#ݶV5ha|akf9o-Ҹ\wy$Oj˾9f[6WxǽW(_2Gb"Ku84YnNx#һHrړF}%EzVAEp.jm*x7ݖݙOl??|6ƀ;":QH9a^wwU_Bg+*S#hg-d\mLj+R@OW]xS"6sY7w7LZy%9x^} ƺݨ!4Ek Zzd~4E]6i4=T}|Uf]G\PQEQEcfgP?ޏ?ޫQ@|z<zEYgP?ޏ?ޫQ@|z'&> stream xklSe9޻uu].eGYmWuc[7+!*7CF&/M JLT$R.䬧&4<{=oW@C -w0:>t'̐F(n>3BS E 1/Xp!ʖP O_—'Zq  !k]rۻӱ 0j&F( "D{bK!ƒ ecDytL!i"ht6s !,ɏT v!*cLSݡڅ`^H """"""""""""""+BX`rrmByǎ}OË!aUZ\zǗm"sA)S#b!1 4ژQ+E ]VI|0QZ,]N(`Bo},XgՐL0vj~U0Ť/j'~8t|/nY>)0qK>9Oz ֙*. BD\qg_Ypop:8U&Bt'6mpmUe%kj@9ߤOj"W.dwi+/.72tZ\&|bu3Y/&NzܵR0.$uL"s 6))072œdB&Ux ݘ^x+<3R y!g\55>=ݙMښ2L&A*q 'Wnk=G7 ב251C]|Θ:Z&⃑A\aKVW9ܞfCg?E|Wx<.{U՜Uĉx|/iↃ 浕6{m]c˦[zxWϝxKEsgϞ?msʭɪx  %OΕ%ME֒uOy6xzw##f9A߾g: iIJ96&g#UV;<Cݻo\ w۵s[m 5%D^_ˊ/+2D ?0uێvl68q+[cYG%I"i肜ƆƍZֶ97zZ3i#S[]l6lj|l6 E稛{] UفM !% W:Qw9m}eQwRVtBƪ' ūrtZL"5LՁW(1dy edPZRVOK̩x1! `kHbZ@(8PĽ1Pa1B0]y"hU! ϨOMT+q)_+Xc3\@"c~J1`~RȤBBCњrIdG d4fg2tj,tՆ5) 3Ȉ:"j V|JI2 jCRmQ 8r4H6 BKr!2҉=NRq,:&&$uX, "y,]!t@ @ @ @ Ȋa endstream endobj 347 0 obj <> stream x nH@ endstream endobj 348 0 obj <> stream xR0I4tRtű)DfQx/\o^B"`M1 4(Ӌpf*_WCK:qpۨzX}l=ot\[=z(kEea]^O;6 !bd^̳$f}7HD^G=wV ׳.3O?7oӷyi&&UOj5n'zu~zmFm;b'N'8n_<( endstream endobj 349 0 obj <> stream x  Oml  endstream endobj 350 0 obj <> stream x[o ]o,tC_6i:|3sB~C Q Br O<\S3)c S^Cra #"ͺU5ӨӦD-ֈC?d&M-\7ƫqK[dUZn>8=ŵ/]P7ʸE#ꋟC;i]6֔E@Vp.s81/8{vJQ,hD>ol;arq@3^sB'شk:c rƽmmU癨MlI[>w`WRЫ'-@9Ɣ L>i endstream endobj 351 0 obj <> stream x1 Om /  endstream endobj 352 0 obj <> stream x  Om  endstream endobj 353 0 obj <> stream xOSgqrA1lPzJD,&*2aS@q-a&NBEA r+r96٦94}zڷOH89'ߜ4Vƒ瞗BB>Sg97GiI0f'1 w٨.3':ğlĈP '[TjGyIyMj^; Z69΅憡0Eռv>5Ⱥfd]IPiռv\jKQO>&'d” CE 9ű?;|DSv ro_:pW3f4s+2/fX|MVBQn|p- 9ѱzzvu>Lєreu)Oq4}s_t~0fUZ#_{E4UjneYUjȻo"_{E4_[zD;֜ l:cN4.=Bv;4$>A9-Kk+4$i!;`N[fs}r ;R=rqaK4iyz?͝OD4R]4?ם ͅEU*_1Zt1 N\#T6^,mAP?DX ׄ\>yuqc/bFSSj;Vty/ͳED7p"ׂ.\g-#>:n·ËP,놟/֛g;^ω^km8ylrH4 , 8j^;Q11Pܠ]|=ˆf c Jiig5?v 3u> stream xOHQ}f쮻8!AA%O1Ży/V$Q=ޡ.ꦘ<R kmkvf3w7{y}ٷ/nA (>tOLz):NwU0. 4R{u׆kTpiB]Ӯlksy;WYx,_ ɸc쫍? :`~-Fi@ih/y<{eч$rݖ\ͮxc--k0U6mns6mns]KdW 3q]AgqypÓ s_dz7µMEx{zBgRa4іj$mNiVOz)h$쪆ԖnJwa*8E a-nޙIJi S\:@#MoP_:^Z |]vYGhXKcۮzUU" -I"¾ endstream endobj 355 0 obj <> stream x  Op4 endstream endobj 356 0 obj <> stream xmk0Ǔ46lmSCu EiYg[e0[. c^~/AOk\x{:+{ڮ@ XeM0AsjW'MP+u_"Z:z&2O8%`1W#$s[oq [:`Y;}`)hf3a.5w&Ef1};O|#L;RNWS[_*ènCjJk þ%HsoOLA$X endstream endobj 357 0 obj <> stream x nH@_  endstream endobj 358 0 obj <> stream xőێ *"hWATj|Mov&dov  '@`@'XKF8g<%, &,tUK5uw6bmzWcpj^ЎĴ`UscG-1NUFO! ipF?#:=`#AR _)B)g"p0ҭ7J1H8sΤ(0Ӗ1e0r|wzނH M=ym󗳛[ok=s ֖chƔ i2?9Q /X唉n1˹RxE _;@[Oroqd endstream endobj 359 0 obj <> stream x nH@!9 endstream endobj 360 0 obj <> stream x nH@  endstream endobj 361 0 obj <> stream xSTeqZڍ@a' s^=PSMX.{4bB$KLS¢eEv1 z9+L+»0{Ξgp6lyIP(3ܲ)$Kű^J#W&[sdY< IeviAQ){Ivdm/Pj>0n&^MؘMk}jԂaC!x0]DҵW\8:v۹Qcem?g7k^؝mqxqvwd!rww] 7Mn\<)s+3<9+=w]e[{jh?yZkz'\Ygͳ퍮aMIN3_;k\a3`G}>8X' 56Cok9Vp$|)_aOuG=l/W9Vlsg041ȽEl3D:ԑ4CaqͳKoe;PXB;4:pG| j^\smݸ-bjRFG߭_|AaԑG~ԡ#?)Jd fTzeQͭף $*+9z;cPazu^<#6v_ԡYu(,yMqU@ Kj~{@]߼rhJEIՖocÔh.e{,~k,ỏ%2MpSWbAQd^=Rs掯u(,K@]q/^SQEzLmjeL^| @EQ͇Ij=yU\| m8JBsC:H~yֲNFT$=L܄ .6D>KpT gPV_CKTH b;*|'1Uz5Ne,_׆I`d'e>z~ytۋW(h3u,TV 뽤> stream xٽKa<=5<&T)V-*C:894 8BtBR]IW7 @ pj&yzɝnx>N* Nq$iLOb/cY2] G?K#]Rl8 OEڕ },Ndh>p+îSliJgyp++:z̊Wi@^7Dߖl6mD:HزT6mns6mnۖsu3مO~ؐm绡%`vḅ̆#=;1ێY'mM{Ek8lKn)@˰73e{?p[cSTZy(Ĩj.NWDBn߰Y nnH,#@Goxt+V w={V:嗀P|ۥniDB$~&h?㕌q endstream endobj 363 0 obj <> stream x]oFn$YHl㢅WrmH0F6Fhrj0>8dzuuτLcԨH,6f?>7ϟ-Q':zs/E #"%q2z$Y4Wϟ}aP)) QJ(,J3`+:LZћog?bXgogS;nIdj`V."&FJ͔I =a~g=fvW's3{55qo)gm@C7뛓5\zhe@ ^ [Llm;%RG$/򿵆 {d\7K?G*Iˣg>>:/_9x8k1Xr_a0Dډ8!gUl|eqyyr:d69t`dp|L"V`8%0?y,HzSUaʁuP*Mb8IEuƙ-}*IJog/qE84p?Ws=|❛P-Q3y: ǔV,ƛHcV97 9S}7&經-SngAOB%܊A9 WGis#͊>_gg7KE{#*w.=ۤPo@eߢDId~T ~+ˌ>[w|P/+Dač!"%}m|@Cd?xѲ4OcS+R*l`jx]FAٱGH0weJF&{?!ԲS|&Ѧ䭚#8GjWWuM9\GD"rUԌjIq%,jt;Q% c94*p[e4h3)Sﺐ-T Պ%(3n/y)0~74~k,q!|Wg  PhGT9]t:DVJalg,c#V=n "%`lFFo1NN)?=9b/U d4w9\㵚TBQWo1 ;aTA(By+;nd 7A/D[̽㲄ys|}Do a\'q_3XU B<ü$A͊ s:}UoPbՑۧaP@ p=z9Y0/Pzv?ڀǠi!Pmba/分o0AP* [9>g7J;}lo#OScLA[ "zAg73hz?u{TQ=dnzX5fZ ]uÜ:dr2o ===fs߬/psc뵪5Վ$ψqjK;z-+dJUДDaIm}+^q6K{W `<XulyP XXŶ 68N[vmD4.oau /w3ԄtL̮Y%hrGYDhQ^ђӉt^3o_tbָG_ (N"%]ڗΰ#sQpa@[2_cC}UjCa/8NΈʒ&#`͚7X8IJ= J}%]=_s,|^H}8R$s. |F[Gx3Q|At]y-"EJpKMZ[kb ,Vy K\l5|2hߤ# 5SbDβ%`~Ty3=zӏSɁO*o-yrGQVIN$%/;hkiJp.>?o~Pϭv#qmy%ϴ䴌` M"\ B֧F5lpQ_HY^^nѠ^qJ"B [ןb|&2L_EkJ'\F?"Zyi:GE*kzDc})8 &_UˍY,qT1/v\/׳`|SJ(K?YN&-*m #XDN.&fEL` DjmЎbL 2`[52oD]fғId6 &m_5aGP -e RbS̼Kco i_uN03-]=EU%~.,_>A%R0"tgX2xm wK*+K@Ò)j];)rBo2X? Wl'FߝޢZmP `"},n拌ľ@k*K{_.A<Ə\\TNo)B12~yf"޸-ӏUtL6f®HeJ}wZeKE*vVL+lB;1BM"Pks(8; W/U&fL_%nuLp;6U:35mnѩ2ݓJ.tb FzǠGbϠD /'vUp\5^t^T] ޼aֹb0Ց j^wmȦ L!á $V}2SYS Dc%<s-z-s"׸W) _E5.=2# 2ÿQ󠉋gw\=?[[1;yl/BGKL(gC4h:sY#ۢ)T-vp%_R涔6"Qb淅sS!q x{{Kf^'l28ɑ7=x%Ϋ"؎5Z_r$mKMn\&FRlr۾}j6WS*s$|Vd*@gp4Nw*:jCƶS8lm,X88hg ׏u6 v:7Kxs )Zղ0x.Iz  WxIy_IJ&Y]POم,lơzPC #q.4pqG"fGBV(R*jՓ vXh!Ӡ;o[*1j=7 KY"jkOۉ|Zp\nШ,rS  @T#bjC~ظGL?1yߦe~, ׯr|ꃭ$~Vfqس2}E\\OTt[ۍFby+ƹp=B,#5njD=͝iia䙴/D &Nhѹ_&"]p7 ;ҙ]1)" Hv@:-8ժ%gMM N^R?^Q}6Qsz'-*u@54UXrbafMFo(1gجߏСC@K\Lhk$MRBĸݜO+q]`8: ^|`[x\on4&abbh<,M@V|&k/!S^{I~b1I cKRy.H9[ lI7 r̎VS'npޟy#e뇿K۴C2o|pR$w1^4WZ&GʳJkROz`AF$La%/GL8di<ց;

3bmq~ҵIvO\z܅۔A(ܝFE:+{*rhQ hwǴŽ}u0څAGcl+S >ZNY l)?2)-#W>vz (]Ӏ+n?@u\yyrF/sG84齬<_|Q-Jqu"1ts1]L1Hx.ēt'ިtiZSNT;w>r$,{'ud,z'MOyWQnXLʓtro+S@Г7(0Gg{Brڤ}_s|R#2RZmA3}fOo*3ݘLT2u=I*UfxL$I endstream endobj 364 0 obj <> stream xc``t endstream endobj 365 0 obj <> stream xc`?M0w6& R df`P_Q@Jؑ$PP$B[qw?j?731ȟ:/4H/-@T H 68 JmX endstream endobj 366 0 obj <>/F 4/A<>>> endobj 367 0 obj <>/F 4/A<>>> endobj 368 0 obj <>/F 4/A<>>> endobj 369 0 obj <>/F 4/A<>>> endobj 370 0 obj <>/F 4/A<>>> endobj 371 0 obj <>/F 4/A<>>> endobj 372 0 obj <>/F 4/A<>>> endobj 373 0 obj <>/F 4/A<>>> endobj 374 0 obj <>/F 4/A<>>> endobj 375 0 obj <>/F 4/A<>>> endobj 376 0 obj <>/F 4/A<>>> endobj 377 0 obj <>/F 4/A<>>> endobj 378 0 obj <>/F 4/A<>>> endobj 379 0 obj <>/F 4/A<>>> endobj 380 0 obj <>/F 4/A<>>> endobj 381 0 obj <>/F 4/A<>>> endobj 382 0 obj <>/F 4/A<>>> endobj 383 0 obj <> stream xQH:( E -K'oexri-o HDGb Ęp.N$&U$ _-$xOҐ Pvj#phT!txl FfHg=lj "# 3IF(*A-s'Bq*= ^)d&ِ`'dXu"ABOP81 q~*/&LӅ$97 B9nP-&YB)c#)Ż ֲZq*8HN55KUndtp|d]J km7(η_ N(7l4Hy_%P1g'6.H]QJcb$ }$+gcz.oZm7O=}}\^h׻oo3q?>;ƙZ=/(n'dG!F\tt JHnDmT;KxHkgszzw՘;ذ6aJe[m `Ceyo7FesM]vDF:N, IǓyp s!gzjrhȂ_S= C$nNސܢ٤ϬsժsumхJ+ԟ5*tyBG2ar;UXDZ -IAH<1a<#@keCn* )G>TŬFpJ)(* &8=n e5HNEUixHEќ_-(/V-8v>(LH-ܕfD W>tMX_#Ǒ%݂},Zhד-8S'w>_oZB"Lţc"MՍ58A=AtjO[nQᨃ?iהQeW9Idm14~6JRds鏹 ccUa?a'Y1B1Ц jّpp ?9vR4y7-6,ev!E.L3MiN/  W[O4٬$y*ɷPj?ӊP a*Q*KR(MnPi ]M1t$V4HTrˆ%q5Y/{0YgSa~Bه5= `|{@)Jt4t6䇟Q ڝfVjB"-4nzc&Oʋ-gMa7S3i4:Ẅnvˡ] , 8SD$n&=h$ޠ˓:`3.lJlI."(L!`[XN)RJp Nz!jF^j OcLF\'I#5UkiFOTWvi#);a'Qsת& Gp8<+SUoh|m7z#C ^qͥZtv٥:"uyqp6h2 4 hz{.E] =ep8 Χ!=ö|E@),t|.蕜SK@WbxG_6,ifO?2tIĝ8,Bg1P6UE+Kuh*3Q:%nI[a aŘ y&eD8U"X6~? A0nnۃӬ[JU ϹJB֧KBP-ʇ9 rnV,Mh riƹx M Ƶt?vF5%M"QnYܬ@QLV3@.Y$5v91 K!!F㥎&Κrnlb7wtrjjĎEo>jEe'8T('2ڶ]l;X+8kiJI?z⶝"FsVjsh}GٖDwW+I :0uSC2PĬt˗Z(Nrzzí@ VK8[őG"5 c)5vr(rrE\q#.wȉcoGZ&ޏH{ǃ,6dv̀S;sޙEDwGXޮtag舨E y&H\wnX^s5qHO[dlʷ\$et= vRa m r& &]eGN*lLxiYۊ:D~uI.(wwCИS3 <u/uЉkӚ,TLFW @m\w`km5OKji |z-I0/,m!K&\qVC (ؠZS"x"lUVЍGLfDesڍ5G؊eԂ͇?@t3*84! g`:}/#ӭ>(Ȱ2ID?fD޻s*j!@V9b ,6"m )aXOS&c'rՄu`'D_8;m(ẼgsM)ƢY=/nK |3xew6KI"ܹ:-"{EO5-PYI4a`VeBBXX.>Ԟr'n7(-݋>Sljr{ WJMLU l+R+N뚥y>B&3Rm #uݓ97Öo)i oVL @I6X\jhݩk3D}i wpӻ@jN #7p@} ҟpq5'R+`#+/g'23kfWRP8 @:dQ4.ɦɁs&'Q ՗>cMQf>.(J/*n-9x_B;luXr=ڨGUa0-GXuS+ pDʖ>?hʤUSQPB,8 P>L,`p 6I64j^>ԣ{@^(;Y%qZ}b1b5 b6jg IQí(A$ex|pեX/>@%Cn?ɦf_FׅY a'x~)5WvM5}#9-2[PWܻv$e0d.)2e)\ɧM7gܳL&癲CML+XE꫘FRtH[,/$s@ҖAVQ3m1*-x)"C0YH:ܐu_sm ibi [I؀cgTD'yz,C&uܠEžU@ c*Y[76qbF$-.-%]_g]o~7mN'6 <4l\f([R΂4cy~`kfx@X0*~bRg3M*cݽqGRfRUq2W,6"X9 (ץ6F7$ROe. c=+jqϴ;l; nqBW!_sG P/l`eoAƑoT9 1u=M˴ZYj/UZ|* 34 }->Vӫe)Cp?"n r5e0pE5>ht@:8ASuJ$gۺ.S8&L^d 䈪|>(7^ ;8OJRIFfT2wU OBd9`"qKK%:pl`Eq8/Cxd+e[Dͽ5.NyMp8 }]1t>/F 4/A<>>> endobj 385 0 obj <>/F 4/A<>>> endobj 386 0 obj <>/F 4/A<>>> endobj 387 0 obj <>/F 4/A<>>> endobj 388 0 obj <> stream xc``D endstream endobj 389 0 obj <> stream xc`>K l [ Ae#`>N pd`61!K?&,qPd18A\` 0/pFS\W@@#ȏ 0)إA`~n< endstream endobj 390 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 344 0] >> endobj 391 0 obj <> stream x\[7~7yNl.o]{8g8 4NҬFrBv/zF°F.ź|,?ϟ is2kTL*7))[?ݻϾȪٻ[hOd*rYrD_lY-W}I6woϟ~z?㘏d1e&DWNdV JXEfnO$0U. s33"w:=JS8չ9[vuVik.g, +_,,X =y*5~ɫs"R|N/-e^X^q+ru76 HuBE/f,(z1_~B([k[%\ L+)* Ņԗ/.Gmɋ3[ӹ5ǟ`a`؁r2v"`rK`>yi\j&U $5:[/!$*\̬JN*lL0F?5B9% Aڌ"̧̾hnl^Q펓 #VUCR[D0 ~.zTm=L/J tN~1%϶ ;ۖ;VL q9-~>۬ڭ=/7(7]å:M n3j J5rXZ-xZ@i+E#N8tm46d$+V_ nQF*D.Fߦ[Uò&JA#A jvm! IAHFAC'St$EI[̿N/*聮C酝o7З|M7@^@'Ga3g /&Qq[Z-@a7;ߟϣR!sT# #DZb?Qs9>(\47t3PuFO>Hp_k#H\USV?JBe P@²e>%&JwLfY q:~ ZSN{Omqu_cx]"& cZ:|KO4З |dKlW ^ɗ& /kKѝ> ;Y`^S&]lo)65=c䘧LiжV}U'ǛZM :rdܯNՒBgACg1XgH N;RZW*Y19.!iwyq!Cы;* Ez9/ 뒾1%'|,~P_!f(Ix5XT8}!o  `]+jrI}En-f)| u2G8jW!8%ȳs֎;rJ"69x)>T-U搜=uW$>Ib"k>7r)\ 5: ʚerl~D>L#uraW/Z&{ T^}~!b#$["cLGI\wY$| _cpoz`R}AK$LN4V };l& W 5ig ,c#H h{$5HB ͩ1G1ndDoc pұv-a#y7u(Z(fOj(+b*pF!" ZY y]@ҋ)Z0>cNݮ1aG, iU W=l0h~lk_g ލ3ҀI=UO+fªO^ Zn`(H~l({pݘx=Kq.\ /OԥXGiTFR)u]]<%N4Ҷ('c'@jPCb !ڬ) J]6’ުgq @ies4D" `pm1a 0Js`)~<)(ZM8,[u5DggB2 72H׾(F`?$r:T5D\Գ苻hl8~% KK:%mnP4޽+4 ktkڢ[fy:Wd7g>~Cͮ{95zp||w'{zXy(3Hn/hj`2XLD`!;@V*[~9#·LJ*>C@ҳҟ1dGH;G-T\Y 9ېŸ 6I7K.qd!cY;2څڗ5QTAja;?U*w|7䱓z 9wbo4U? !aD#`^Z +9O;n^E?lD$.n%}Cakȅ ( & AᥧBAKN_EڙuZK`ۇ2kZi 3ZddUVn@ZESe{gW;ȺNOIPy$8TH`CEO(~zHmm 'QjS`+\7\\cfB&X+UզFs .!_?n;tӞ7yΕ /XG }̱Rn3M6;$DŽВ,*WؓrX+%bBe-YF7wS˲Т/"pKzJs Q6SƱ$S'.E RV_Й CZ.ʐKgSL_tr%h=)ݸk_ÁZAZ-Z 4 ׶\1xO>"h OE<*5O[IPRDI4KL q ]h,|veK:cuÇgg9˚|Ztxg?ژv(O>'qd\NUU^\6Z?Q6Gy=/l>6u`FħyO6UnOh9F-)A,ZEQ HEǴxo>գQIR6vdX ociQCAZQWCbeeoiכ߫0{k%]lԼE3YR ab{6pJT:%W-#Ӹw~D,]"٘&$DRiC,@+n(B9PQ( x.L?`Jj: 8#Hn|j^TQVсyvOQiSzdpdp{{:bL~k\:A5B ?D?* HBdL̮({+({&$ +8Rx)‡>?6~m'u|#.[;Px`H UG76\ (0Cx\_++|\DaM ZnVV[gBX2ۮrZTuRYn" @Q.~/@v- VƧPTf2K9Aa8Yd4S!Pye@kV?@@gp7Hi*~N@Gh} Wvb?ԧ2>+Qn}3Y'8ZCӢeSjt Y~K'r OZ0Ƚk-ck,0f V1ZYR'/J5*UG @0uOi=R9БMt^*?,.cThliAo9OKeIմ 6Wgľ"S(DP+ xxe0x4>CKUCC8EWK%L[삂̒3z!$w 3E,1’4GҝFa6`ӛ >D@z{p֡#[=6f[47'=ŠjNcSQlKQ|'zo:i@uCz;m@}6%lv2z %6c@&w⻓:S>( 1 Ɨ/=-C%& B@"؂׾f' U\zUѠF FЬ3V *i~}Q` =r2Lar1\K#>2U2reG`X0v}=/ 2䲢]cu]Vu\MK{8=>wh`UƉ46z aY,(Vv9Ka ą_}V1D?0X?Ů떴>g(G'}eP`}o r:ups0x s15f&X4o<3\]i:Y͉tvEFK/t\e/z!|4.&j8򫙴֝6m;"<wѰ5_kCZkG̫nuh;iU_qriY30ǷZ8R@UH}}.pR*[IxAuU *O% endstream endobj 392 0 obj <> stream xc``D endstream endobj 393 0 obj <> stream xc`#K`p?00L F?d?(Ӥ74p'9 CeYEaߏ9c_ l;ž10@)Fg20  7zk /_ Nl |S endstream endobj 394 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 629 0] >> endobj 395 0 obj <> stream xYoF݀} 9# mN}-@lɕse)53_"ia]Ԕ,H<-d5?%9zPv6&Q\#QѤW*nʢoYOr)ul%W8Ir欷r%޲tv{=WgY) *Vs]r.9Ea]Yr6w}>$²@#YC`QyVƢ7$81 &0v| ԶwږG>_(z?ªXݪVVE+Pه1`c#kԉާ(xvEuOei+uoY֟躨m}CT0NmLHpp8-B2v#<N^?XQO Oy8 $a7{g+H^Z6L0[GZU˂DK^7g$om_-0> 1l:8F91nKʴߢ}ߠE=&l@$8OtH$ALHto㒓`Am9!hm{} ?56C.l@Rfָ"o` y0KuE3lc"@8>&ͥRbex.*sIA}uYX$\#cE#slx`]N 8Gu4dNIcܪ70Ui9CDFmV U{DQSOVAYT^ [c<֑i:w'e'07 ~/*tYӼ} (HՁ%liαs|t^rٵy"-!r,yG􃜮C"d?쵐2 WWO`Y??iRK44IiwYTɗ [?^`Y^1Sl9[^2%7ln0HP%Eth1n4pS <*Zme> kYO;VtShǢ}sEJn|OCDmh7>|QMjlHAt6#uś'=^qbhʄRw g %WV6m\l3mifS&N(QQk]5@gi-8vdr`|)& sփͺy>8$;C ҆CdS-13}%2@7Z\o,T ib-5 ǩ\a"_I^O'|kjKL'x z)]*y6a7R<:inT0}D&Z((, θ\]veURljW7n1"_M.*=fW 9zlQPaJP6 u)Ǜ %1 P }-$xmoq=u\Vnѫπw۰{5i_q=8=CJ Kэ;|c!t(1xɥlWE`18 rJo] $خ. gtҫ\N5oye9$/2o~ZWh$C:rEV|%ַchXJh0,m8ڶk[%-Mi7{rfF1qc^PYG+А P ^'Œ_w=k,[֐+ Y0/JfF~3$΂F~.3a?- +l2UGG.NT9Jy9]iQ@>`:'gc7\Qp7K9u ߍY ]/KPZy,<b\Ԗ|>­C.hźoB3EouTfsGU^ r}% ޾mI73uL~h:1|ZPVG"etTS}O0COԝ ZK{)-P}%b{ fjJ$pGڕk_1QgH( >ċ}0Z][ m)GTEc3EWo4qWWHK?E endstream endobj 396 0 obj <>/F 4/Dest[ 175 0 R/XYZ 125 735 0] >> endobj 397 0 obj <>/F 4/Dest[ 175 0 R/XYZ 125 735 0] >> endobj 398 0 obj <> stream x][o\7~7p݃QzE 7;;(yHAne$.1﷾*4y. ;&Hu%??S[tάo +8r<7WϟUVm@S kW_|E{kjqPC RQj2zC5B9j tg> =۰zrGO=Shgȳ<9=};Umfŕ&io[27n;Z<.[ӥ[|[ s%) yBs&N KtqϒMxmZKh9(.,ޣ-p-L `6(JwyH|Ca);qF?@sRq\ >bԗ^|Y*E  ryg&juw 8Hf8ѓKnϵqW@yZ< YoYsUECxhYE&:ߣ,dmcC's$ OwDk'w744,9HB YiִQWXDy5oŷ<+ѷ)b0א-՜ H&* yV rHr+Y1=ASm>o{!噞v 0 ;ջ1D(<2i$n{4 bAt4;Zw)ᐦpOV~f_bɈS@Fz< Ρq 9Cbd&S0$3=Yiʏgu]C;,>߁?U'b)?&wb4kaWYUO #m<$#vMIj?oX0NfQCv{vb15a%A J Cf=mmKT.5C9tFbUwКTq'= 6ܔ}ǀ;Q=4c9ֻjw)6wan}ElD$,7y 0t\L;B^ K!FAzdzt9q?ŌYwXRM~Zw˘V]7X2g ۑk=1^!dH C gOBUod!>+lg1; ?@ǃ.>B7&"^Y}(˧Dؐ׮(5>Utv,v:xC,_*݌_|&Y SDΚODWLAlQ4N?.9RY ,mFo2җ0?.J1HL2):&Й8a1YUkU*S~vsg*Ù;FZ{=y1?j$@hΏ | ;0QT'̳Y/(Yiĸf?:D<<$ #w_HK&#݀IuV3;|cZ ʑ5VO3"+VFSdKPQ\̤V:3zQH}1RģFzz8d);Y$ yؼiĝzB 2yV7Mo2dӹs8P]Ɋ#uq-p铮V>61u9e0IAv6a4iM]hn´M\  5Xoy=Vw؜x OcXI6ژ$%\7_%Bm-g!psS*{\~ֶwEN۾9"kyyxDm!e,Ӭf߈ًk@'`ZEMc7Ls XZ~k&(0/İm ;m, ;q?2%I~Dpqa<-h݆f1CzG+ BDyBO9WI*LjKc0#Ο/at ϋ6'.5Lc^\řDyȔ&CY?DZ#a\ߥզD>SF+IMȩ j5,gK^ gz ╿oNFG2q.dIE2ܤ+9'9i'ZIsTQ GwB~CBv/+9p\*쳣}3'JH΃(y@b[N褹BȪ0u?5L[DLm.G,aǹ:fBB7䫶'dQ iGsOU\D9%QTn;b;uu,] <9>ة߻k)ӗg32^;?Fi33 VuGҥ]rLI HR4.Rc@U=[-u;42UI+SC^Rtj㏳ij*зY]_o< .^B"$;z %9T5{bP$LG@1i$1(yl}gDq66 9݊Q*)^$2re/>Y>KWV>+͒% ;x'N5Ŕj;%B"s+5Њ(7R_(bu}xޑ3ە*N .x6GY~SfSF'.3mʧ&'̶ܙļA0؈N?FvCr?Nr\4C'b;J 4uqtSF ۲}uH-AϷjjD;r}Wδgږy* 2m(*9yJxq?+/ 'U>!t;(JZqFkyDҾg/YDd1Im8q@-mEI͉ǡ\r5- 5({YСm+L*׮ðKAM$ĂZ| A. 5UCDBs7^:5Yr,""$-rɒw\K_pJ~2u:B\1Cj5)Lɬ5"mPXvhcbEמ/VrftK-r)9*R tx4Z9+Ǵ 5Nwf/5En^Ol˪ O|utT,._YnV`Btdӝ7Mwf~F6lRg2&nFMqY/5Ѣ^un?/ޞmnmmCsV'viR_Cu`\EY0M]YZHB'9\t+sŶhl25 _ƇPa@?L+hjoB@2AH9.dBJVhTmZ\R*-H@% V^zE.H[T2h9nӁ멄#}cQ54:2fvS)Ε>P]dk)$9y3?w]yy]1.j_A/P! fWjWBTLeN6y.2e`@ɥdse1u$Qf`qĮXeѳJME9-Pvd ה qA~ T]b0; ̔vg#YrJ!V^!'X<Աy*9ډ iIN|Iu#FM״7f9DmDTWW'Qw9 ,Y"R+:c`k*|Y9Tj)B,4HY0xĉdˑmǏxţ/{ײ;PXG6}0'ƞH)CL1خ &Ӓ^a95{S;v-V\;S -Xl[i aoeY#nj+Fq,qۊY8#E:!^(1uպ0^_Os4M):gKFwiF <.QvAHLN沼g"\Zv,BůLو_)g[lU-pU ;p &n xkК -< RN{.pAVڭt7@{'wDπ٢QvTxaq6퐗|aIm,o.L7P^W[?`7*q&sOZu- UM+ ghα]`yn\yjIsktcE @JL57^}5$T6NeIxPkX%*Zt{d똴T@7Ӵ?l푖] kԿK@ىtGFj1Ԛb; <1"x7I`>+פ3Y Bh<[r9יfj{y;m;-ɶV6k"xzܦ|1=/@ֶÎݫ%m("Xwື|c4^xry[Zi}GŮuֆejZ6L+;B F:,@{ .%AE~!)_ N氙X4*CUKq(TnV8зÇ'A4^IUկcyfECiI6KGJ +\(! xkN-k3mn [)|Kbms`2yRѣ WgƝCtsi isR|H[2E"Zi" ݲW:I`O^DB\Xq>߱B)*Vܵ$QЋKr!KC|tRrRJM4ODBZ)I pQb'\pQ`+I[AanB$62D+2.8/^&E^_ < %ӥk 9˨b4]ITt]O+/X9Y;']\i22R;-4\V/J}XЛf~<ε|$C+AdRHm7DwOSBf]zsQ y hQPH(Yo, %SEB 'rW95-Tj-g ȋq:W@/x ߍXPH$dFW-ǔ 2Tn` (b3v eX֩g_2A%?2A:00A>J=TrZ , ]Wdȣaq&UT{J! R!݅6mFmwӈ9RN/d2{V"W cyQj8Ihq!'mBL"/]NB5קPiU-oJ:y6YBh{L$v-(mLJg**<5 #VX#:3+zVa&vT.O<( |JՄYu#;Q-oF endstream endobj 399 0 obj <> stream xc``D endstream endobj 400 0 obj <> stream xc`#L̂g`?Bb:Pbf?(p|B2M'vH2yH. Dd 02!2`b΂\ w4 ^$!J30܄C *$ D endstream endobj 401 0 obj <> stream xc``D endstream endobj 402 0 obj <> stream xc`?L$DL@hC0900X"Mf`e*i??G6Y d3aMmP (9si `T@R7i ī # -KK endstream endobj 403 0 obj <> endobj 404 0 obj <> endobj 405 0 obj <> endobj 406 0 obj <> endobj 407 0 obj <> endobj 408 0 obj <>>> endobj 409 0 obj <> stream xc``Q0 F( endstream endobj 410 0 obj <> stream xc````D `#( FvI#{W7pu4HXE @X,#_D$22gd DŒBh"@aQ",.y^@tb#& B\8iK5i]PRN䤅I XY endstream endobj 411 0 obj <> stream xc``Q0 endstream endobj 412 0 obj <> stream xc`#  endstream endobj 413 0 obj <> endobj 414 0 obj <> endobj 415 0 obj <> endobj 416 0 obj <> endobj 417 0 obj <> endobj 418 0 obj <>>> endobj 419 0 obj <> stream x1 Om Oij endstream endobj 420 0 obj <> stream xc`` endstream endobj 421 0 obj <> stream xenQi S`S51b=&} BZ)a3 1x&&&&^xpXq|ן݇dN` 1@/08C߿ՙ4+L"/1 wiA~# S<R=6\# g1-T@ {'V!}"0 K1J}wS(b]k.jqM\m[y6owC)!o-ۼTۑ>Y5.> stream xc``Q0 F( endstream endobj 423 0 obj <> stream xc````D `#( FvI#{W7pu4JXE @X,#_D$22gd DŒBh"@aQ",.y>@tb#& B\8iK5i]PRN䤅IX endstream endobj 424 0 obj <> endobj 425 0 obj <> endobj 426 0 obj <> endobj 427 0 obj <> endobj 428 0 obj <> endobj 429 0 obj <>>> endobj 430 0 obj <> stream x nH@> endstream endobj 431 0 obj <> stream xֱ 0@ѻD$8؊V "&q9? 7еeͰl(lp Gxu-ZhѢE)&Vem&hv J bUU endstream endobj 432 0 obj <> stream x1 Om_2s endstream endobj 433 0 obj <> stream xM tH ?mVbA,\[b^$u"!#tnr42iȹ6 ?#2,.8崙:gII]-cE3f8G&j6}`sf['ogàzjN&DXV!z^g8G8Vii~ }g endstream endobj 434 0 obj <> endobj 435 0 obj <> endobj 436 0 obj <> endobj 437 0 obj <> endobj 438 0 obj <> endobj 439 0 obj <>>> endobj 440 0 obj <> stream x1 Om ?T endstream endobj 441 0 obj <> stream x  Omb endstream endobj 442 0 obj <> stream x nH@  endstream endobj 443 0 obj <> stream xc``$0000 xYyL1DhIfFQD"A4H}¨QG D8oz+o"((@ XV_v endstream endobj 444 0 obj <> stream x1 Om Ol endstream endobj 445 0 obj <> stream x[k0 sqS۪MkR'|t]a-t0x{Y?⠣PUu˚nۺnWY`dߎޢV 7\pwhxݰ\B6E'M=(V|.}0ė1N@}yts06>MޯdМ5δ=RD741x{%(Y Aȵ֯'O3O- endstream endobj 446 0 obj <> endobj 447 0 obj <> endobj 448 0 obj <> endobj 449 0 obj <> endobj 450 0 obj <> endobj 451 0 obj <>>> endobj 452 0 obj <> stream x nH@|-H endstream endobj 453 0 obj <> stream x nH@ endstream endobj 454 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQL" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|'cewЙb *G>ޯ<.Bj\G%/s)!zeFP<]Iƥ!^[h+Kh53!^[i? Sd2}M!3!^-[i -[j\SFOD=O{#/xg}ԙ>SG{jEWݿxgx?or}M>e? 4ƥ4dڧ?<.Yp5ovvVZ;bĜyCrvO66H<-쭓UsFh4Mz' ty@675_4fia4њb?-p-9ks sA_?v*x3œ_KvExf3FkSFi4\,?4f3@X~h34fњfha4њØxRO?ɏ\g9ԗk ׄ![GOY.ZxKrW2(#ЕMݝW%_i?(xKrS'O%?!4Q\{Y:J-猿?(2Ckk >U EG%_rQdW(xxV=W%_'%?!5QG}^c'?Ʊu{hՔۆRsrVeF endstream endobj 455 0 obj <> stream x a͡h&cs(Q,Hb 62 ۽$@c}"i'i~bi&_+iKoqJJz;(`O?3Ç>|Ç>|Ç>|Ç'>ϺΗ6(Z-¶Xͦpp~銭iGK'v@xFMKx|d)@/Ȑ endstream endobj 456 0 obj <> stream JFIF``C   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ!" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?5jZvd,|u޻Ax?\w5?1]޺ӌvyx!Rf}ρ=o ?گPkήPEu,kF}ze5?toQZ 63CY2?Wi^qey-Xv+4S_*Gk,לѿhGz|VTd,I8QOb]&6(N( endstream endobj 457 0 obj <> stream xc`02b&,,ΏM(%MRW43PO7DReT$`s$޾Gʂ%YxM|P'HSL + &#*ba'yV.n4,Plmc endstream endobj 458 0 obj <> stream xc``\ҥ\D*}*H%]x4NZW?2e(WѨݳh{Q޴Mr)ex4jӟxW\Wg[)GZ4mCC NymdLd> stream xc` 0F#8`a !Y@꘹B eG endstream endobj 460 0 obj <> stream xc``/Ѩ3qMڇD¸ʥx4j,5Zz4?cRA+-s2^z87zBsv]YGjTm#Erx4*طNGFm3 B<e> stream xc` 02B #D?0Bܬ uL\!v2f^9$'HO !$ R~] sDG> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ9p" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?YjZ}ILX9x' ɃM[k_Wy[&KF3)'o ?]_oSohI?生Ưgތ?hI'o>{z_xgx[i?џz=Ox"!2OB<3gޏoS?GH ©&տƼŖ6z~ kӘ7!v`u-&aS$1ƫ7s^{R_EwVx|sFj=n+d57Sf{E4fF,57RsK\5-yuC 59[qK\vEvXFyyỶQ`2'FyVȟu0Q 9Xs"}n> stream xؽ `N!4r1!E Zjfn5 ??H LER*1P4ޮ.liCC*<>x'Kas.vw > stream JFIF``C   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ!" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|/Z꺩2e@=@=> stream xc` 02]FT&Ƈ&*%&GM;LW ]N .ǧ2*7x.]ׯC;y042sC 4 20J!;,20rpq#'3> stream xc`%%h9ST$EəxS|۬MݮT(GL*[տu*Jhْ,sLR ]39+)G˚Xyf6"Wa> stream xc` 02)#D?0Y@j9aB@%t6 endstream endobj 468 0 obj <> stream xc`g/T(T$T$T,\,R"ģLPt.8 cz-4C *hٛ!F}Eno=UP+G˖deLX\-kb6䙭5]@u.xX+)*(V< G(  H endstream endobj 469 0 obj <> stream xc` 025B# Xl0nfN1;P #3L@(«(tM5{fYG/O7[ &Ne=SScA@=’22`1sr';r+02b76 endstream endobj 470 0 obj <> stream JFIF``C   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ%D" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?<7iiy|{I\X9x_D_kZwסe qWc%h[_ܗo}o1qxk4-K7ѾeOsϸE5t-WF) ]T6͌JTqE䞑ᣋ?n;Ff kkb{u ,VR5Ѿ,M?&eFر4lXc|=;cc}Tԛo_?&l嵑bX4V-n5NIsTQEyxQEQEQEQEQE endstream endobj 471 0 obj <> stream xc``@`J~N6(dVl 2|3ZY@f ֑oF+0HE7W &fa5cԌQ3F5cDq9d pM윜NF z[\ISG ( ED"\ +;Y b" A% endstream endobj 472 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ;F" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?9iky~#0{ID<=/ƏD<=M4n>a=Ƣm/VoPۏ9{v<{tȃ @4SΊ%=%჋?֫q\/sVaqW7QXu<њ.$Q-J~Z?g褼oExݞk||Jn$eg endstream endobj 473 0 obj <> stream x1 @qO3-S۬p\ B(hljilmb_8EZhڈ_ q#Qh;ư*6ݛrp8лr ('WRc(gP@P@P@_nڷdm3|~N}Uq&4ӋEyfLҕTi`NtsJY8*dtF!cbM$0]"4ިT endstream endobj 474 0 obj <> stream JFIF``C   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&G" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?<5iiw~{ ±s]džHȊ_\/s[ <#(]生ƏE5<4oe ,vq m\=MtUTWSI;>XZW#7N:Վ+]&,ZnZQm?QT}~i\F}G}QoGr3Cu#7T>m?QT}~c5N_QL]d$d`q>W?QN(((((( endstream endobj 475 0 obj <> stream xc``dd"022BMaJJ (dVP OEq&XC1@cE)2M+&Fa5fԘQcF5f.j[TL(IWwWم> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ:S" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?9giy|xpEvk/i5x[?s^ֽ=8h))!k}C?K7S[v="ghCޒgh}Mð{ID<=M4x{giwSFh0}C?X~&Ѵ>ʤe}McxĮ_uJPPm"NJhDZUG']PaW?oƲS2\Sݼ?/?e${ۗ?G3e{IwH4o?Əg(in^?Es\]Bb&jsH ( endstream endobj 477 0 obj <> stream xc``@Zb"kjw\]T3ҟd$+?Ռ c&4jFF }.2jF AJ5#G5rQ#G5rQ#G5rQ#G$H*vF2 xQ T}HVE#{gW?+-o@9Qwx%DxY윜\NNv6&* P< _[ endstream endobj 478 0 obj <> stream xc`@*be,c(,@< OFH3 Ӗ_ ?"ԥV~o[HH3RXph8t?Ve^Ěiزl])ǦklX1J_-,K Zlk;ԟqj<2)L|`_{ºENwE4S?qyNcjO:ԟvl8v\[/՞>jUϬ`Aݩ?c@WP94ЦEnӼ7S/nPU^vGȶ@}E;Lr7%"Lݘi&9-KvY﷭<G6Z6/bF7n& fDM1ZkQݪtM>r $Z,a8cj.!i"Ԏh,e+kKwC 1/j0}v.!bVDA2 [,YoD@/E7g6H]9S@H35CSd5h^fU@LV3J_@3_H35;ZYg-v@9E4S=U7aQ28<ݸY|ĚЬ76c6d6 h5'f5'vŷ%t@ E` ÐB.+'fx:qo endstream endobj 479 0 obj <> stream xc` M$0"IGۘLl|r;9ar\r{xYYxQ Q ɩ˱Q"3m(=cBRX;yzC <8T L!HC <"R20 -OLL,\> stream xc`֣ DZ@Ax$ΩUԌGNDu{‘ab*> stream xc` 02m&?Ea@f.I(H > stream xc`UC*ޕ fb8rdTz`-:MrֵGvѢ? .yx9$`"U0 F3 endstream endobj 483 0 obj <> stream xc` 02͛7cCX&`撄 r8>z`fNqucK++ eav& 2",`grps0\ L +m endstream endobj 484 0 obj <> stream x1 Om x11 endstream endobj 485 0 obj <> stream x1 Om  endstream endobj 486 0 obj <> stream x  Om5@ endstream endobj 487 0 obj <> stream x1 Om x6 endstream endobj 488 0 obj <> stream x nH@n, endstream endobj 489 0 obj <> stream xc```D 83 eg¥KȲ̀3 kmċ(c03ģUQjG&d|x1A+V1C] N%,P?Zx:i 2 "MEq. >a>82qqC+A*a.@8`VI/N% endstream endobj 490 0 obj <> stream x1 Om /g endstream endobj 491 0 obj <> stream xc` 0sq.6&٥5р ;nƨјzf.~T eaΏ[=#32ëU?T3ɜ9ą8`efA# UV|5UYc/osY.> stream xc`@Hl ٢! U"4L]?m_.XGTX3SXv?MŁ/0X#"O՟i>+>òtqrL^bWwʱ|ƚ(slX1J_Ktx$ͷ,m[s̡Siπ(dS <} 늃E;Ro~6UjO:ԟvh8~.՞>jUϬ`AB "ԋeժm1@LhSyȲdifyħ%y,KT> .gQ$w^qbݩ=$gENvʃpdSy(bUۼ`I$98kyv=6elʁh?.kU۲hY&U1xĕ4S+(c%0,wX. A@6Pļ`I::ѓ7S3 mIz-E,o@Y RkENQ ̐.E@m4 t3d2Yg\?ifxfj'7Xi8u1:J[L s5Cy͛- s ӖLR!L5F YABD[ojafn$c[mZA$n$L1%8T! UW#e Q0Bwm endstream endobj 493 0 obj <> stream xc` M)<<XspI&6>T 09f. T˼,P,rWr|hr"Hr*rr)UAAoWC2RX;yzC <8T L!HC <"R20 -OLL,\> stream xc`UC*ޕ d{brᅭ[!-Ls7G) h vϟ3g$Ѣ搀mc( t3 endstream endobj 495 0 obj <> stream xc` 02͛7cCX&`撄 r8>z`fNqucK++ eav& 2",`grps0\ L +m endstream endobj 496 0 obj <> stream xc`]*A ƣ y~Ȩj5z> stream xc` 02͛1B $ea撄 p0$AF9yxJp2Y* LedUPTf[s3011bs7+\ endstream endobj 498 0 obj <> stream xϲf/__}ژ!; qP2V"ď@+}Z}}'82r)<[<`FN5G3K[zZo>ȲPRiŠ%uг˹kWRZʼ ysyℷ ^=7kU#OR5!UuPzx5S5:ؼ*㎓ 4<{q. balM` G=RW$ ; бW$$8V*gM݂Kt  ?nˆr&Oi2ʑ,1 ^4H\(fiL(d)LP[b? %8b|Ȭb%_as8u|X߫GpbKb;0{}l/f ݁Xf@xbWȍnZy MbKG챑uSrQְ1$ Y5!F߂? "BټBZn2mKCc}+$SI-]H˸Eւg[xع}ck[F |mHHRmfm0MnOa3t^cLU@5>hzs0>A^qBƿ[2hp)}iU>87 ~ u3Q:HH[;L̦=9ʪYZŨx7zoHlv}ƵAǀj4( 50K%7>.eKɗjH$W+'`nTjK6k)o"٣I} q#PW"w"ѢJ^vo^Θ܃6gHƢ I 'ϔkSg77٬y#3Bi-[{|Vu4ފ/,B3yC^eJB 6E-OB 00#Ϳ1VT(.xTRFR4)%ߜ/QZ*9(  73ơŹ^S}#ٸDpX ߫r3nIOWIWH`B +`$Mٺ\ s^i3ګYh)aG ^!mb^m[MM`/im^ 0kdZpEK')sUEGs@~naJLL9 r064)d,Is/A3:wVt5_ҎbbXk' 8|tmHy=e#ȁ0YҰX[FLT "SHXLJMxL  xe1zTAøæf=ZۻSOG]Tp]EkRQQ>I( z q?YovVyUӄ 't!:^<돏 ]zu5º:a"`Q 9F,_H m|?~iCֹFS+X ˭& G=(rX~{Lɚ|os%YWzu=(C&޴~lf(z~Jov%8W0ﻖeq(6A1(yC,NA{3;= =3g^@by,'f^>V7v<|"<}k`M^*Qp= }gM.S ~Nx5hVJaѼԼ#{.WVX2e_4vY{c77}bLWiHR#?Jm'e)(w!DVӪKVGuxҲ"?h^A74}NPm[ +.zdzSNGքYyiv @U2?$l2 yVSKPq, 3]i$׋b鬅ů\4ZIaKf'W˥S]2h֫k,`JyBJI-(q剮}͊+a%쎇u1ӌQ wQ=!04{.~T_E q5PW)+7u]yD?BTgTf- NaOmӯ{W]Tdij;q?Y)s Ng 3n/t`rOW]Z-ywh9q qQL|eP& V7Y'=)`9jFcr]А۹&W vIC 8՗+sUd$:GmQ)GKF6/=gI'.pdW+MfsJ:Xΰda٨R yU&gxWsT\O#ԛNޢ1lR.e#v?`@pE qJ:JaYJt"d)nKfTM5kwJK忌#fx'Z$k.a*W+{TZԣne8;T2?:|D?Y-@wL20 =,qT8,q9UQAo{J%EW>N"|Auڡs wc&n}h]}X*K*Vd]:7?EU 8zG~Ųy8], ZۨiQF _z<v~h_l߳)].t to-Opո0;p \G! *ysk|us*DWVC{_X?C1T+OuCù~3N`96unDqDW: vwǍͻ͟\3IoE=&,  wLJB+ E QFoAZ#شoOǡ#ErɌ}j~laNGXG'A]b ;H )PNw("N\λجiM9~&YPLr{4t?j+OGl@1t~qN$wZY~p)ϢdH( G } H8/Wg=p^l۞?p-|gbj@obJl dehӕڹK&;ujNoxQ#naOnoTaߧ%Cח Nӗ]YY"jX#~'} mky)&p ;9fw 4zJTڸ4BDHD6T֐b-TZۊrz!J^}2CPh ,Z$K;|] 5qc?֌qۗQUyg7M^Yؔf2XvNlGlQ * 1}E*k՞:mxyvհ&#hxm7kj%:W1*'tK&uJ7 '馠c_1#H᷅7o~).xԤJ54#dTK<0 X[6+41`ϚlnC*0j27Ux@(]V_ӾdvH!)gzT&OyM͋0@P4h?(]9tS1(N`dp- 7~+N4»~%7VIӹe!wiG/nG Aqd{6v>+iv ;v>yKp>$._ݍ1M_%,~)%^Э>Z/J1ԑ"]3nB܁Sz3.owgT_y.ꌟry% .t! ;/}@t M3=*C q rp*ֶx!2Tmzş9w!Z֣31WŸDnSYr U]% 4.s6mUxS2`D$-m;U`3\됶BvR$ÜDVE_ [lS-?M 1=ocqM7g'_[AV ]ᛟǶJOlTy$6m>^OX`aBT_Ǝhyw?>^@cN?BU endstream endobj 499 0 obj <> stream xc``D endstream endobj 500 0 obj <> stream xc`/U_ @mM@d0s+BV,F$6d?+Y2+* Aph-g`xөS@?C qK+w˅+ sWY endstream endobj 501 0 obj <>/F 4/A<>>> endobj 502 0 obj <>/F 4/A<>>> endobj 503 0 obj <>/F 4/A<>>> endobj 504 0 obj <>/F 4/A<>>> endobj 505 0 obj <> stream xc``t endstream endobj 506 0 obj <> stream xc`De@`YB[f_gLUq@'$;>%gcC# a=!\A$ 0GPFHA #$ 5j endstream endobj 507 0 obj <> stream x=ko?,/AYqPHmo -qjK$=΃.wڵ,!g8΃L|!d*)J>|%7El/_|$%7˯/_|s<$S'! %ӪLR4# U|4  e*e/Oc#3"t|&hg\(*, Yf*U4L0cd?LO䷩0w|j&o_c\yy;_cV :Baڋ^d&~deR,ӯOw#н~^,OO ]rK}vz=YZ*j1s *U&ѕH \y\A/=nUrJl2O#Ƀm w_ qeUYg2X7@ViY$ZoGMT}DU@3KU(RxVH˼{qaL`HJsO׸.".N |l`=TɵF϶ӓ$z?~>ϐL/oH"=$+s&cDM_e3xVK1vK;'Q_FHSYf0@j$,ȱZa- o{pd鍕X,V"YZf_ &5QlBϢEUU+شC"eT!oe5Y f Kf p`f?uުρ2|zi(XH@e7ӓ B Ð4„c;UCK5n< ls\ӓ2kUSa–@ r,pttzҎO ۀvzY։4J0@h(<y:ԳU ?!93AX+DDM[M#6Žu=z컷5 werIvM6^#-]/ů};)v_l!n~%oG|Nբ {F KG,p-,B7,zA\Qď8y8>;Wb= wV m~*Y\?6,-|6xZ1.䴐+J*'_D j2:q92g(.*Th[:ljUA">sY$h?b #J@xDi xARS(G`_[XdI e?)Da!%}EA ~5^8̽seܭeh˓x`n n T@հ NR7lǸRRE>($e;:lEKpInYWoͷՊmf'Zb/}gaH &hFPFCvÌ\o*b M2܄Dg"Rw\L|P(4d~ ,D* B wf]SMˢwrRk׶19? b1`,vmH$_v쁹0iCM3ϖt Edg;o3k,jc$P`!WMSxNTlSPv=!c68AMyKI{ԭSWMPH˪} L2-㣔ύ;4hV($xuvxx0ּBICzxӪ ,F UnHn*ĆwoOٲ~E4q`40Z_IYQ` @0enDdKhSb?W ]kݝU!%w7ѐd);4[ʣYՏkeAf,)y_}SۢĿ^ztѨҨϙo&l0]1p?Ztv eI!6%—Wp?YDzBN.puɎ[^YyEd$js&LkU5y@rx=G7$ɥ7$7 )zuk%d>\ H 6|XÀXX|V,ZWRp+%2C}GtX6G9 ($\prQhEa XCQx]'Q^Y +Ҳ{>'ۏڿ݂e~~M[;YgP$MwRpq黵UU޷dE¢"΢[<^Kr,<6~š5sp{#=FG:}u ˮM{Lz1Cȝ+>ݔyjSGE_ TUu`Ls&-.!gqx J7)Fs(o ;eB[vbv;}CkS9mCma<`W=Sbw)s6T|۱+pn}-H̟EO tNFsFC\1(n.,{͆te3jA6C,P lVEeZGuW7s׬Ҩ535-ЀPZ窩HuZz?#N 4Ր3>TQ`~?X4B4%(u#8ea]Cu'~ @#[v:Hz$ESAحR`+tscc mBs .p~A.^\%+r'g2 fjH(}brDq.lMw(qϡ.LOop>R9~&.| 7%WWu<)kJyrYdnwV*3(M>xC 9\>3# ;iU|+ Ù&0{TN߇Vn^a;l^_S󼾴>pA_Čo[=ـe lxFTɆI95 r M]`!me<1$jK tAcdMfE]<=ĽʥPj,!I2Jx%g*9%3k'~T〒Phv<;_e"ԉ 44xCQ:iitޒb_"cIZ!1uk(cʹ ьH!]u=H+]q ‰ySHC'.%-jLk{RCz;IJT7@J)z䭾<' rYՈ4&,#tԜEw3CmkQH*:iL5H[X8FJYb(-joB3!lֶ2rO@yWYiH64;kC3*Zc%},p_[Gq#v o^v7ST B* 0D%ؙ P\ \7xk7s*$['dgC_D)7n7 B!djd!h(ḋs>\8TYo:TYlR oKr H8vJqM>F>|{ ps/t{lnG4[Y{@$Ǻs]kºUT 5PBr M] g=1@_Gߺ"[ \ YҮ`XA*$,]ŲI]fXlI|";4搻P:b/\ew t/}7KV0P'dR.Zjդv[.pzTHP>::mL1;̷cbr0l5IVF؟.]&% EbplAd>vGҎss {Ip1QZp` Gރ̛B+qROW ERLByI0}ݷ\@CX XT۽[R?oWY]ތ/EDB3?\9VҜhcfaVΏ n ,i R,k&+WPx;X"^űJM 0hwU %ӎSZ'.]]%vRT")}(^TN.S $˜R{ }>[( Oc+ ST56bH9;eЙ𥉉`詴-L,c5TUDe]g̸cUUY*s]o4/BL9otFK Qp že7r=*tD-VHQm/~OEvi'ExcRKݬ#[[ܛn2m7FI"6 " 劯 endstream endobj 508 0 obj <> stream xc``D endstream endobj 509 0 obj <> stream xc` f@bkEY(?̫g! U(˔ِ%Za`I#9D!Ef 0 _dD ~PG1" x*X| endstream endobj 510 0 obj <>/F 4/A<>>> endobj 511 0 obj <> stream x=s۶g&gS3D_3y{qݤ7Ŗ?r H꛻~.]`uZD25e"*-"O2Y͟?7?{Z$U%Te=LJrtta'}a~>ϐZބN)kẃsE8I?fp-N}v-=l/ݟn|R4B ͨnH*HX#*Qc4lѾ8++ ı>Y4,r-L4ы2BM!z FqK,ZXDE?UV$<5^aRh T̈?| 1pFdZN=GTtwyGq7sA-ӭoi@bLk+ iEϏ !|eaK#>M[/BzA3l (tC~q^(C>,$ )9{H[`C[d>At^v /VD/:hWvLt>;ZHg͡Qj#,fͤu4{/%QZXlsLx\H((ظ"T3( G ,~Dy!];{C-4G2im'4sԑ5D3Ԏ떓s 7cdsƊmz جcgw63|uٝStTiYYF]`C٦% 榃_Yy2H)HzST|SAYD+k arjF4:iX6tA ]0V،zTFzPθ*wASB2ƤXjUm,՚ m%܁ڴQ' ,zn?F1#b*X VK)gi5Y #abhڐ&FO K^σf% EH n QCaoF?K*mE.ep! pN+G?4~Tppo\ Cw7z.H={1EV w;:xz#uu|vwd LJ*}w[*sǮ3OΦy1Xal9Б JhhuY=;Vܱ3#rizc(,_;ݡqWkޓׁJlsP?{/n.apwwBnq~ԺŽCj Ҧ_m歸!5螑qn o+XBlgяaRՅK씁#4w[M>m[ͷwbh`QBm^}sw[ƽޡ$-o8:~z L~xOP j1˅SS+JiC Az&_$ԧ#*!K63Tcg{laN/:bRXcXHhŘCV,f+b[+ƻ ^;s_ۙ[ Ɯt|F3[̓8a>ۼD0yRq630АP.kR`mKD,EV}XL׳WD-ĶT8 ѡ"n!F Z鐅 ]`窮)Ǽml|c@[/Iql`lMލC$=4ʝ.XVl.y+u&1Ґ&f:63АPnQT/+{>HK)^T#_x #UGTDߢؤ [v67__"H(st(\Q楎 뺪Oklc!P,.4 Ymz 7>=ܸv[s.FrrsIՏmeD[_--&1Ē6p n 68sN\]9UNl5;e+ l7~l+D]p~V*G*#C>Ja9.bz{f /3ڍ+lj KDXH׀FeXȖ8h^%n"^åb*heRu!fǴ@)ɀh!.BI](Ղb4&4MT1)Jnwt\ & +'sWrĤOd,DyF)¯?a\auCxc,D!Bicؠa#)[+Ecg0x&n:4EJ=]1NIVXbvx8`dLWVo;q;\GWf&zG0zZDusE4@*mV .*[V |5:Cb.ЖS2Fmb Tq,IK҅uU^o ²QZ\1Aetۺ;!fE(7m x˧M8eqf5^莉5$vKiQem}RE!\kV-ҭǾ[Uu>Ƣh!!`+y6xYPjM<ИJ|t ϫ7 eOJ`1"VYAcun hJ7T̚ɕl v1'??ͩ r M\1PL5{α6~risF5']"ӎ+h(J6 l TP}\͉o1AQe\}Vv/^n[p̙q-J {^}T 奄 |[s[4ʹÏ '^b<f]s|uhSG>x(l誖(M Aq#u J(Wt`%7Sko'F,UW\A/S}r忈cٔ 'u0__ TIL8c !8t`wh=BjCX[@U 4}`Qdp{45=cMccM]Hb~ v9 Ɋ#ɫQڛv19%صY#@?U7_%ȡN-rY ZrVeGtP߃i~U^&cJn[e+m%_XkTvvVN @yjs _#c.v[#D*"FjqƢxE\<#DJ*6yv΋EwW!td(6 g$bT ?B|axU["m]L:raZmNma0bQ \=旫&7|B+ &?Mm &Zݐ?}-WM/~nB4wo`\SlPN9<]݀ [s:YqÝԛ,b|ii/7e6ޮX5s7x~y4 ݢuf؅c7w~m/~<$K XMk\/`/Kh}^믳P Y@W{+9_xJ1=s<|/#YxI憏ꇢg~mrJZ (IM{>Òb%+F칂ަ>/F 4/A<>>> endobj 513 0 obj <>/F 4/Dest[ 155 0 R/XYZ 125 701 0] >> endobj 514 0 obj <>/F 4/Dest[ 155 0 R/XYZ 125 701 0] >> endobj 515 0 obj <> stream x]mo8 AX$qCb{ٝI !pc\t&;믪HJHJju{Lǭdaʕ*%r]fBչUmWOן'/<}{y!7বX&"Jgo>?}Rdw'.doߦ3R1s]gUZ*{soD`,(_'fXe˳cs?e|H|uÑ9BBɋ f,\dj:_űK)%JK3#;|woZ54 y/LF,RBJG)|~ʄ.%[%\K_U( ﵹS EY-G-s&  GBBeR+E^V PyJgR9sBx0]cB2 B"BwT}* &cjHJw!T>ȥSfyzUeO89`ĪΠKB]fm%c%z1HpLM{hN]ז5ܼi_q> CEnx*c؋\nDN)}oY ȠÞ:HG@My9)7y~ fJbRhlVY*Ů^P p_f$LEZRYS,W $bHfMP9w֘{`TeQ#AJmZUVo z\"%3VH7pBPزΞ %ʜIc}qA2Ρ[$V3I4IZyXY \fcK\kQvWq5oY|[ =?Jʼncg:cإ{ נCrJ]B9+#\-6LK1T96 d*zv޲_YD6mB##d9+aqMb`t/?{ÊX% jc%1SVϏOӍ0؃>"Efwv'Za ($a*"|vaQn=úʸՄjp(QP[^:=5<=2Fi(S?(Mke"0鲷KPq_bĦi_i>[l1mcYh0^縖qqÊKB Y}1[2#pf)^beM&P)ȫ(1x 5K* J^k01uL #8$ 2-i2A8"uA-Z\6Xۿ.XX2uXl |}@?n\S&hYbXTo0FZtu-a"O̫^njc m#v*k/{Cm5X cD{ E/c.x6]߻kf_L%*F~`uxj/~_a" WǗπ֝?{S#CH"e6^W. f3{fqpSBWMLu||[9I!舐| _DD ޜӒԘb $lj5 ^F*KꃤH͗ 28N$ueX}l%>*E)t y! NFݪ~+TyclF Յ:!W捣)%5%V=IP)G( }Eɱl*(}F:pGS$K@41~Yr0kyLXR&WZQ$m`p x>@o vq`7m)MluMțFٸb&)E*_?6;+6yn%0c!3xȶed}u+f23HG8]ҙuꝭFuB5pڕ\] r'zˤp6:5.) -SfBȒASGz %~,ya7·fPSPtr9Gc'c&s $Lu0MkʖrIV HW=MY$HrH 'Ɔ-\X{BGjT&F4{ X5я =n|S|pqq0J7c0LO OJ|R]M V\LJɒ,8`2Udg<`ukI7=΢ӏ=BKElbНskbYϓ47 ˯ F ӌ:z,7G J|sdxo,  (PڊQX I,鼽R7=ؚ Xlݷ`+d2Ede5<`qcE7㊎IZ֚#@p`51<g74Ξw\,_ Ndg% RkN@t W[[Rxtz(.PU;yTA$LY;A z)ZY\ 볹lh>ۑ϶=Lݲ#FbCސQr\<.d!ux mSnlqw*l瓂}>2JzoJM8hq`)HwƀIWχv%)$U y&p5֊u.u@L0zy_ckKR 1`d>^,65ÍZ!@ ΁D]Q|(WTA`)iޟJ7M=M53e?dxn AXNYK/*-JeDv#e@jC<90Lw<;D@ #-%WQѭs3 &߀HN|wikwCj65Tbs.cUA^1~b&q8{ń1,qvsEI \7 aGIhV` ^02iCc&,2+1%PcPj˞cJt&t(@iBYP[ε_y; ῲM1 7q|Mܾ6늛Sdsj\Hܛྷ5٩rw {:er8nzn_:/+N/Dc2}ߜy ]sv`]HVE{FONT> lM'NERf\r|tMΚ%MQݛf6)0xø+z˖8Ĭ}e5l֐bϛ$HYru? endstream endobj 516 0 obj <>/F 4/A<>>> endobj 517 0 obj <>/F 4/A<>>> endobj 518 0 obj <> stream x=i8?/UDz[+lf3@T;IzH6dP]Y~Sy(+?ȫ6/_?*xQ6g]@?s7TC2Qe&D*!YUYQв^yq:/AGGLܪ(uaig8QV6W,msY\0ˢK {6>RwcGX.y_JM3#sCV *AaڋAd:7f (ɱZ).-PtХ6HEyr|Tu-*lrbUΜO0p@\LYW rF.Lmv>\tl4w_@$*l Ǎd^W0xmW( : 0CT"W-̾h6Q펓 #TuC[{3tq\Nj;-G<$=Bky9Fsa.|&3țr[))9݆0"f#@-Ә}[ ;n_|'He0$@#,]aлÂ3l]~k G8Y ɢm/QuR_HC^ @ozo5)u)ѳ`55)ݪƕ;LѩVZ@۞p* :5xh z>FߌJD,,Ғ?"DV[*h+DoвZo 0/꠮`f P)q8/U .mAH(-Tâ'! 1G~1 'ܹ-sR&ȭ rkJEe838&;V IC ۪a"$XqqMcr>]".s ֵPܦB hcv6fKnOTْHvJzmkT^H|AG oa anTw`Ğ_.~IJqdlyZKc(هjrz9:ցG47wG@g8_'#M . ,rV*t,hrCVe6"w=g03auaѷȭ-5;y0-4b&]kd P%4"n< \Mꛃ趰F>'j_ї&QXz)̞0b#O7F)fiϡP"tSQއgTE17> "d9N zPQPl1!Q%V֨̉\I O5|7Cw_.UnʾĀWV""f+EgT?p uL0mx qv3;iVfzL/@P T.-l .1jxq RAXE^mCస)5}CJĺ#qMnv^#M= /(x6'ڷ1~SoC*9 @ldxB=GzOh(YDmPbTzܢ~~f ~NJfԻZU*VKu"֣M(ǃjA&LJe<G V@ ! ~Z/+iOMXSG4w^KCbZZh/ʇd4}➠S%l7vobz@յZNކوbk?oϾT9=m%- %K#]bPbGB洯Zv{#;qY5,҅j=I4U*c!b}  $)ˏ|gS_F` ʍBǢB=>Zlyp+*ncXF΀'8rB Z+\}Z&.*u=ϐmpe\&Qp3EK OlZpHAWOgs[(3~8kg7&MΕ9 I B?3=}0+Y˯~X / 08' e.ʡYH͸9a"Ks&8E%: \;& [yHUy> gbN~ ;K,Z ߎ}r5u9:5z Q. Un1ׁn,YE5]4p/ٵx@ cAPHЉfK@g{ӗ'Е6YRm=Z/#iGWp b.n59@tttqKTK²i(iD]1vWL`X+wV7hٴ$kX{˦Xi'PS˲x pRn4Z݁}Q|ghHa0G>rh!aun<Dw{,CLd.M&E1lzEҫ26Lv 's%@k6!m5k(5tMt\sgP[?RyEGHN%&Pm~wՙe_d y7䈆2b6@I; #Co%Me+#yqyVZemcʬ OdEIzsZ.5s{~GCi5Ŋ'Cİ#5-$4b6'Pe/j9I.QV~@j:.*ʩ%vqIP~9Qsz(^ v7yiTLhqRم.Uh![[r\%Z|~_$C>TKKkrp )ֹlEL.:HN/5 =5I5T#ݫW'_|C+}^;,NzLT-BU=(zs8kMH,pϓSty\dh'h(z4q&\:t(a99z"f'_vޔDfWb{= eE[$n |\F O$O=Vÿ/IgޅZ2?M1[t p Ro!f'xڼi7{ -<6 5{M1ȫv&cQ7Zz 50i2Mjc ǰHX}{tBzr6$Cvnduv^'<9K+~~6fٔ0y@7&|sUe]m)~ا||J#9pߟ>~,ymM 8`~I?mJ#v(*_a%n @ٿk, i>0ZGZ~<ﵨ1%^qkG .v6)d;x"pB@=ClHR~6QD(CP.#*Or+7 [ʷkEYݑyy^إ g ›! 0lE&~tn8DFjvk!O\Km")K/܅&跱K}6Wj^ILpdaZ:+u%ݺ&b緙΁$enB:6+72X7Ce e%ɻaӦٙSږgvԴ{q}8dX PdP1L:ЮX$,GKn"]^ֿ7&iI3z`TX\scinYs(_kEMՆKI2L`(&SWesк>za_q gcLJa x 'o:J_Y#gj&9"ؐ eƌ9b\; }$/6$wq\& .VrEߑr񔆣~9~`8UڃA\`\uh?2c]yEr4Ժ;9'AP"ndTkl4#/7Z՝-@݆Kh,j䅃{j̚苇Z@{T{B5l*k3@2k%aX endstream endobj 519 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 449 0] >> endobj 520 0 obj <> endobj 521 0 obj <> endobj 522 0 obj <> stream xXmo6nbx|' p42 baR $k^Zɖ\0Hss>M' 79xL 3WtrN\hD%&;B-ou<-NP8W%(6Qiy]EHs5f.}ca2LS*n@+oo׫w,xˡIpFM+#@/l$>֙?i 1^zVT3 3$C靨:u |~seeT#nb-?;CHq]EҳDLWC zZEsw۬?88|()lFPʪxG`b1Z;::hÉu΅X_.n^ma eEaX0HEņQ`XScfHKlgFK'0L2+zQb)_4)/W,CB<s :M%c5Nc<>ŪTzUYy\C̃Uq#_i*d% 7qej\d,'\6jdy%+(bqrG ?#8x'? ^.^Bmc~:ƛvb艿i6@]D;8jA؃p$$JB#o*v44SW]/Ƒ((}^7,'`NST9.urƮJ*Mt*ž'MKsBu]ÿqDQX+T&6=!7Iaa(f{gYo1al!F;gOubMy*#R5k!fKs e8!RĂjJQOw;qi`g>xe,Mbna;e5 endstream endobj 523 0 obj <> stream x̊0~;m!(Y1J(Y6ujGVZٯ*'&u)?z2#FWiVyqygvw߳Jה0K7xfYR2e`2/safo̾kQֹ5[jݛֈ_@u^<>8)=<VRg1U_ k VߙG`r񹥯+UUGꋳb}ciitɜ a @52nD@*+˷ۮ).ׅRR"<خ}Ab D\UOf9 ת]l0~GЛĕՀsPzt"[v_$SW6ž"2 X<߯sQOqOBnOi '姹ߋ!뎿d&\ٸzX 3)q1_e-wӚøUx}t%<*y4U56'-CU'‚<V s:,D'[n8q,6e R2}OрF*,F̏QsfMnQ'І  h~JMHLUhH2,3:4nJJ ݏ=[C^J~t;|>sn~|Ό \ èdYjpN \/'la뺄=܍.,|?whWqlsDK|}Ԁ>lۇ9*||7UXd x$Rdƨ^VtFD,~\_pR8M/s.v F <|#g2##}_Wȴ졞؜jpi$ |Y-ᄿuG:4mgk10~e`Gϗmq7k]E1K01v '6}-!%7K8`K q ԳWg=v[{Xx[E]T?>auXtw91)Ջ/)%"7,]B1-2nْ7'[M'*$8hN C0B/i:MKq=m*8F߭c;A so7km?zŚ(nʐlE0Y{Ѫx"qHXRG*%.pHLJ(X=zZ+HSY0)tMqqUE(fA+J܏2$E-&XGfR$oWd" -o䚝B.nrIP~k0mʆ}%3b6AwMtM.+Ov|7ʖ$#hqo(<;kdt7 JMGSY@n@l s;K^@h%DSH5 0434׹b,k \‡=}Ǻ)?$|.GZ UD_yp R@[󟰾^#gPa4k6bOmO}LhM-=@W@ $5wDHa c<"Dܡְ?a}W[7!(5E5 FԽO4On0ǡ)u!FopG7?uT>PuwldxAl҂=1l?< Dy_!>%OZ|f$AzR#FEsHA*V L;G6򿯃 z&;2=%8&(är *&☩$FrAϤ$) 4A[L 9=ފ~9T D*X+9v S:GԖU1xŖ}o!g|VEa. J0)^%5+ XHAmn4nY aZVRb`- _v3ÚjoC~,ts>䌖531,Vu%>ؚ@eJ%n 4t@)0AWٵ +_0Q{l;(8 Ktz\:g=Q}ZmZ{SRըj&U'KJ%W{k$1 ^2`&3 FkXoyElAJn;#20waR5)K@p*xX*Qr4E.xsiYstt``2# hNn ] ˍjo`wQL ([{}DBW(KTnXVXpR/K5HFi/3 d'4ߙRPbȖ|+:؈aW&reSwBe`xW _XjJ*D'ޭB)Rw&zOMXq}l|}~h(^ >ùS){4@X6S@0tL9)@y`;BLu~O\'GNgiP 5X|O%UN): >)~Hla?Õ7k%1M-T;g=I6 H" kp+ѸRZ~>uy1a ~fKt"; ,Wh)z~Cn^(C[Q$eN1+Rh vEҽќ-P3`j"GU^} _(ɴI{Iuo 7qīqm T#ĈWWl =eę[uX!>aEB) G].Kp1<<}*嶺iWR,8K HQ!K:{وQKV+j;!yXMx'ki> )gw4GR |R] GAQmWHٗ]tԬmhޡ߯Z=MY))ċ `x:,h)Ar7j9٧+2oB;%vH?kdi2BY|Z64᪡M#\Q/H4BPcxB.La~hh~_gn~SZ͕oJJT)\ ;PD׫Pg6X^rcQBP&G}e(7Q4ȕ#3xqBÎ mԳ | "5uvQӒJs#qs>1$#1Xo2$rGV lh&ka>qRn4%@#enwn͔>y2=j]独A n$Wd`:;bMACS1NQmvh`JKE%x;sj(q26;IĎ`Gj z }[Ql#(:t=J<`x8A` i 1=Wjs aX#[6;ؔhiQ;ݯϢGP< E Hg 8gt'\xrº^3 צ9G; ~c ď9iz82@Wh/PxF h< ÌC*as{O`g: 34lCd0:?*g#gjfdS믟 =PUB@=mcm dk5O1Xs`e[V|7cbf|3 FX=PR9%f023%R8~4{ F3idu8\$'*7҈d4:g M&_W9ƞR|Qs}IM~E7ցl`.A0hR`'=@TJ\lR~b"SӘ|g0$#aoB5OrxVLu9\V5uťičf@ln(۬(({tAs1 -'GA)~Kr2|-Ub7l/_C%C`&HOC7BzS"BH`31qTc=b-L>ݳ.Ps᳻pgȒٗ8D]6t*߾RYi gk1'΢Ѕkf<iftHs"? ;)4Wb4(bHi ܥJPچB{l HkwDi+9%c*͕uw%]upU@mZ2[=_XCWRĘf*5"ᮿ=ǣL_Kpٺ"lf6 lB ;sl§aMN9*޽$Bd20>)Z`$y=5ю&V V2GGVAĸ$#dXؽѯd@i̘ lNg9 %"7'yۑw n.{spXdD Ioy?w `P:2FO endstream endobj 524 0 obj <> stream xc`` endstream endobj 525 0 obj <> stream xc` v$^0"!> stream x=ko? a!]Dᐜޮ8[M{(dK-W//_uZmI:el~ݿ|qק"kBe?CD"m2xE]o_8e>@|˴C2Re&D+!˼mEв>^>Y(&VM^_z0-VgfK\k,6WK \2_4Ͳa"};_٧г3t2׳oJMl!'I.ʼ  _ݜl&@UI/L뢐H*B9|W |UD.=>諮'Y団En-GUc/L-ʕr( (;m.uZ@r̫:^^-mvLʅEу횬4wL@*ZjL9Wfy%Δ /R- Ղq!UpS-뼩Î FC5LI*n}>{a. b|]l '7s!g'z8_Te!;y=_] I_5Dћ1Or:iHWI/%οml߰|@C y5Y6!aAGNUBO c2lS| `KzehVlېID7P}!+R`r=hD bReE4uU;[c$ۨ ,jS% C^EZ\H" [\4W,D-rvU^Veyō^/$p|DiGn$o6E;g%A36řbwzvƿͅ@ƆNrD>BzvmpL:k1i5e]!#0&~-e\8,4s/`-w~Pv k}=5)%ut.mK(9#bن'9LWI_‡WD"1 <¡cK'#hw|#ԊƆg3o;uLQEln^[1MxZnZ>2DO辐&pGGYw0L o4o@@=Py @r1,QNLJKGҒd~ݻÃىW#Fi*7=U#u!j}$[QHzkE0cO~GQm}0-AulMĐ&8LPI*W-M p0cUi=!{CF.)izh &QT7J 1`4=jډ`։J;6>"-[9m ۍl..- ױ{>`I`C7f։RwdZ7NT3@DZ(x 2r(ggتTrB/x` 1>x> ^*J`R(rN%蝪yvȢ$^5I )KA ٵN Ȑ>욙]kcÊ++Ўz0LDx%]wUT;-!vbROy&;O( VD[ǩZO瑄 }9=[4۱A\ôuz3[-w1udY:T(1W{瞒M $2̣Kfƒ3̤KEcAP$ U_jKf|,@f#U)vCWNfQ;˜]-}m8hfŚōq܌4lq$'+!%61yilPʉ lqN$)c0n9!-3;pVQGK%t C3M9Ne4;x3Z<YCSf+QF,ab8/{NEjn(rÔY>/a> MCUv`\5'7܎¬p.-1Tᑀ>M[ Z-B-=Zq)bzFTNpnamhӒbFN6V'"+;ȳϩt,207&/1O~x@Af.hQoq1+׫rTkpvVd0qȋ!^R{r˝If;re0) 1˙"6RZRPKpNɟ&T!fo%Q @+"MQWS%lQj쐢}{T8 LZ3:EG(bvIB4H^=!;Lv,eK$,6.|d gڎ`%lE>boq)jCpqҰ]{B2AS+,i5SCv, @P@%(l`<$Kd$.0|@JY:fE`_b&{ur.]UI#‚sܛE M_:Bs #-f k -ARL,=94^TCձr[cvಬCc^Y-NQxP?AńKzgp߳TW֗䬑6Ж#(YnBp:f@UQ]$"R-sV Mhn׿{@f龊 oYa=Jh/tEԾpTtϾrZssXqhr$MMz;s2OSsƷh-T}hhI CC2ʂlٲY[U?7ȥS½ %%WRND)*`_v&:JB2+=S">oM@Ix"_5ŷM6 :hP$Vz8:9EiXcmH虍qd/j?S2-eܜ s;%ƚl8 ښ"`7 ɴ` LcSk$= ))SDD^8EVH m7f CqáS݄NB h 1!u[oqUqޓhI܁NjZSuMfڔ0 v*dݎjDT\yu3ITWnD}cHt;X[DrZ86敉mnwJ̋iDW]T`DjCbG%7$w4[-^ۃƪ9òp՞Bl!Q"nu)R䔒SNl'm~C6M+%he4ul %.e\51acQsFlk1}$ 1+-.ٝ5OMl:@JD шI`{/vK:o:)nwoW=fi[v7iZ+Yo0R&-Jr93T9G7pgcS6GxZPʊKa%U/։piަ&p`Z <=!a[UOtO*e35.PKWfiS`j%~4ڶ-uk~W?Gw곫sҜ ?a{XȠ;,^`W><&iZ'EoUM@j`C } S)ePb#F:6^w<eəDpTa~̀+<4d_$*oOh[` m6_'% C#'Jn1(F8CJXKG'm;A O %@vw]?FeQT Ut}c4Ш܃<z# YvQ1Zt zc7#uuE{5-Bq9 Ax~tl e_ǛTe",(};QL1fC'ύgxG-O1EvŠ !q5 gt'/ ? 9& aGWkw(W:+U/nJk֕=\uefN0&p(r,͙ξ(7-VC]˼f~ 6'XBRڑåR˖Q/ɖ+7`2ղ~\:JJϪ G=!ָY3 rju0WB4\X^6eeBv$-rk^Im#pcb;*T[n;>,w;oU>a?sBEO.XތPI1_KWfO,v̅hNX%znx3q6a',@秫 >&W#ffK eHN k[9HHPX#ofcgqgoS| rssnCOfpU$~a7>Rf-h:Y*2\kd}TlVMĖNts^^%>G7MO$<`(%&R 3:S|*nᏠ);5P:e@b2@`BxGeHf*ݢ 23~5*a16xS!"  ',IpʢD;g{x,Qסn̮T@UZ]hM@NRM_;߱qr`5cݳߒI_Xw$ܝl'ZeUֶK۫~ҵWe4_Y5|Oqu˹ kkl42$ tg 0 ȉ2Z_*5ۥ+}^<KX>ՍE7 ]PUXڣL4n\7Ò*?沠f1szHdN7o: DRsuv6-NqXEyfjCx])}0AE+Tݠ;,m^c,ջbO*di2>7mV7Oj,'/] q0cʋ;$U]s{^7u'"?ACp)2^iw\ # oNGIUz;FY1.h=KS v'g xa:Fp }t<G+iɋhN1t0j!%ԊedNM -ݓ%e#n[ΞM]\6~.{sH؇2 NԿ.+fTҕ=u7.څ-<5{݉۹^hc71YP7]$ C 2!t]P+]-yWc^-jg ohb[-Ewg]ܻ}Elt8SL9T"IX{摰2ZǽdET眺)v}M7ыK7=Q|wGޛK86V[^b?k[ͻ脏Ə6!wKXzQ>LɰN:yש L" Hٕ8ȞNyqN3$LŻ+n=&[i浛nzOc[7\{A7+7>wۈv/&bs7"VVwWr,'(OQ,BBYҺ<46+?p1Tw~N^Hf\ŘTtY0\Q>$U QzX~-}4߸"0?~I endstream endobj 527 0 obj <> endobj 528 0 obj [ 529 0 R] endobj 529 0 obj <> endobj 530 0 obj <> endobj 531 0 obj <> endobj 532 0 obj <> endobj 533 0 obj <> endobj 534 0 obj <> stream x\B"u4M.ϟ~|E>_ 5}ySgGhe>\|\PX׹\`eY44gg_{dSkfi\/i?WY*W_4MYر`-Wzץ(ٲ\kש9kri%h0G N欅_j &x0=8XW`R'dQW'Bk nȥۧ]Ya`L-εr &We J.oݮMvfI]!vM%w_@*pjH9WvydZ5^jd3X G\8Eh^*=8`4T/E]Jۥ^xf){UEP//\4 I|M11f)yX +Wưe5`8ٵ۹gޠ#t{ri@M ͬi(LXБsa(Â16("؟pqI,-Њ b3(Z}"E/eQ#j¸ -(Fߤ[ȹøUeV3p,QI0C@Sa!)Xv$2-s5rJBN8[\^>gg$+TX P(kfh6tm,[g\$ǁqg7D?z(*?,딷D?K] %>[6h.4Jzc۶ ovKN/(qZ_,zXj`Hc!;fT^Gkw~-Bijuq S=`3(fW!ڴ-W''r6*f 6o%UeMsc}BOnI2D2 9!"`gϑeqD~#DܧP݇{BgsВΰ4E/AԷsCAR$H']$@s 2z+]5zCЩS'Ss޲kτOR6%~\$ad,A4` AϬ*Qxa^n Wu\1:)Ro%ь)&. @;}o-PDLSZ#tS:$9+i'#+OT(S"K16Y:dܞ#j2Rؼ$;"Ԁ ?dfvX*wZJp,{mK @:KmjYW5aNj̯&m &.G9[IKGjoadĮYNx̓d'kn'SvFtNU\l~v-g%ԾvT֋g~iǤQUGED`׵$=%hfy)}TĂNd0A[ՋF)uPAՋ%A.1iMpo }v #[)l;qtuGTxO[A!10H*P-7C~Dr.7;PG{$xҐ?[YA,_Gdi,Cc9պ#uK6%U&<}4 D,к3DUى͉\UOO)Z!E}v |$A/^t(gk߂}](Ud7_6U|𗡇MhF}M/ɕI81ITl#;.CxD[Ƃ I{J7e7׀xnRΪ0tp4:_.ӱaoL)h| s6|kdd]`%e%p6Dxga=T &A$1HȠsR!r zj#}7V/~7~28?.oT2tc F<8-VcnjvѺ$gPn-ycAkmyyuQX,0̚\cbgBjXQ0[ ( 1bS2x ix{s\Yf%fHW }o-<2 F+bӌ Sҭ˜\fI7ތ 0Oph^ "쪥N #$q 9kl7< ;,N*dA+)p촋׫k?y`(p4c'u6Yy/7ItPQp= 9XeHKrHʀu,I#4M5G*۶ٿv3Jym '$2FevI]8p)ԳOx6]I]uq[|=:2z! ܨԉ9* ذVY !a搁{KwF>ŕM4o k_J4Tt"|`E%L%h\DfMUJ-5 EhXtJV35/IG=ʿa&*Hu4Ȫ")+tF*E[wSK<7kZMQMi2B8iLDD'RĽNa`LgC)xQHҢ-\%L8:$-0YP**`tdF1s#{Ћ׭KC۸h3i+hג8́ct} P J(jRa[C᤮TRuf= z"3u6y&=(9w'hq Rp]'C]T !(C&y`ӪD`PC߅ "ߺxΦ6ͱ|қ[HD4\[wkJZJ `w.KvoIvBh {X~p/lj]I5Qo[G) V$tՇVvVT2*R: UՄ|@Rg OP%OCtc`yBMB{UFi B.h7)#% sI$et*D##ѕ,gd-wuQ9kIx~jVs++ pwfdZa"JDXçN! Z*V_֢W:: V9i|IRL01gLqtS"\5ФUqgDj} sE;"TKGiBF7j#j_xXZEZn3ז}Bq>Zyk 9 o,H']abfډ?Wֺx)&J诃~μ,f Y GĆ۰G4%Cɗp~Ɯ (pڞX endstream endobj 535 0 obj <> stream x=]s۶L_N_yǩ;m{އdK5u$WmHbIJH>ϟ isSg֨.3edFm}^^ FYD"\fo?>Vdgf{h~6tHFJfBtJuJ@+~7I( \_{0#Zgify,m%_#BJ) ;Bk. ~{=7ZUj>'M.-e^9<78|ڤUN 4ŃL^Ã}WJie ȢgBkw?g%K_tiJxB-,^WR_-GmWZZL^9  T+ZHTyik囏ueIU#vMM鋻& cu8X9 [~Vye3-`Aomd3X G*\8E^hNUw\0`JJsws俫(opw6sf778_!GǹE͐ty͆ބkc֝R+aL ~H\Qԯ%za{R$ %(PEE3QW‹@B 0KhBzf;Z~n 7f`uE+)JSm1Y߸^$T_" z}*ԝQi"F j]~٢KnmW‡E-eo(&;qMjI<}vhz?GyMiPЦ6`GcJ LS`ts@YN)2 PҠ t&D+qMc=8R_:(|8QOd4[moW&o<_D&f 2YirR/B~GvV1lh[oHy6';Gu[ׄVhio '`=4L dRXd" 8)Z 6߯piݚ1C; *(왞,+ #Aٚ 2lTeB0Rvt|o9B aR;:DCWc(&4 ݞ4jUGii0b_0'3W*Q` q^N0}#B8,-x]Vo;qr?tgrA m)|x}D1Տʈox~% ZXԴ9E-#?V@" R  G$b%r@(fZ)`6.`] ޵Ҙ8C?HlwxKzQ7$hNvI-?`+,=; A&+1 K-|P}, TK-sa"zjE9GOI K[3D]HGblMl}Nf!?%؂:ټ[2 K/pR|=jƱK}Ӭ;Fk9L\D['/t23H P!hHL@MGbfd%VJMg ?clᰙW8㺞=,)QjDauU[l]hїUGB 5R;c.$;8S%7|K&=˳r Pmcja,M6Il! NuN͕kaD6FYX!6D]zii01:-Lkgl^*&#~֎@kƲMjzNI$Y$$lj~5s![~C&mȶ:SQe"ɼPr9ISg{a/Pbڑ>d M4(f{tLmx' x}_gKDI5؉h-68XHle6|An!}agdї! =iyjeaG9QYMr@PQq:iȻC]כß)-%hؽ@0E ܏,qTzT}\"M cRD+B H/Ih+)gwG\- c3isPӦİKN䊊x)HCvE2? ,$.n@s$Kk {qL>NQn@2R~(U.ɱJR?e)vM\H֔<)i٣r9-\5i?7`#?"+_iqBb5#CA ~_R|Rmv VX߰c5^?m% ~Of3r,wlfoO6T+;%h$5r 444YMd]5wDȮFB[uw=:&ƌP'laQi6o^877.ӸAScvE!7[GE8FnC{veũ lkڃ!|EkNjƲgLnUAHDzDk$"CzyJFbvIƔT8Nhy87vE/; P5eK;ph`[, E~X+!K2C.#:< Ja]:e!cs]ưiåaOczi*qzӵ6 18k}}pL(b}в:Cs&ұ$)/Pe5лM-2.9졙-hzkc wI;y8J]+LF7Md 8 {ǟz{p3eވW]Ѻ,lIHČ?ή, y;@\yy8BA,@ɝ'l&v ao wfC?-=[2Bcт\"Mϊi)A06)B${:F"]YapJHѮWPI~,1=7),]cO񈽘6CU:-כaKWAG!'"jBrǶ*D h14Paid.Z[ JU1*ٚ㟞4NhE3U]xRD1*g,Lq1`S]ᇓ0Wn0G|ld)<<]Ҥ~=0o"@!DE$+7$]6f9q K*L f͙O0 _^L\TP>e/v UV(;LP瀝T0]-AwG}a߻ʅ(mXzE`XT1 5YAD4L34/f*(#u)ѿ[Ukz/ ^8e˙`L +z􋹹^(p;~Bb秸E|J[:= c!\LD[tG r%gul;~<o\70!Qy*_qk[ i{Z 9}Z70Il ;~|yCn"ߦMYs*oG ٮ| 9Ya |Eh//EXҐDr*̭aS֯waEGX~.)MSIK(VZDBMeI] AaQol n UINQ̵kTȧ;Ԙ>ytkj0, &: G2/}ڕ2n &s@nce: DeTsDɪW0\KpxGxZ|Y=C!)y7u>I;0d'Kl{!2ِZ0dؐ' Ӱ!7i0bb2S eoZI̍DQ*y,|0HF/ ǡNX5 MRJq鰶DC%4x*wl\(Nʌi[2b z-,||YTTIU2XϢv͓vss98qpFIĥ ia4m1.S>%Tؒ Wh\ |)Kz#3u̶j4e})Osb\iyqO!]Ua}"[I/ȸav\cr`4P=QHW혯 0fMg68߮pW>idcx]2O/XPOg+3E֠ B،oI50q8M M, R>{]?1B%%47Ư14豌k'FGBqƚh,xUl ’*(ZYCe%/꜔Ysץ\z ɕ783nb͖0s/[8rK ":[9A-KsR_. e-VC94jӜ@z+Z%$n“P ;?]6+weWdI{I!Fv"jK͗9!pO*uei=\^K˛(enu/'+245:-M +:4w4@G'A8χnuvɄ`L:~0N< OnKgNq!̦r^Rr)xhLH({FY@H10M/NH%9NPXG|_$}׫.QPiF+GT(϶pD*Tq-!um%v(bjQUDJ[oMjCSSoʣGZxC'O pg2ZB۳CeL"8)֜JE1!Cojwq3C~sظ_S,װ 8=YXaoa6,yq Ub #\d yڌa:!t۰[0/=HAPr=~ȚG% Xe;H=T.T% 4!*WVU܄ :\zSx53Z59H)#*pu R4eY-b@e(afA@W"'EV endstream endobj 536 0 obj <> stream x̲e勿A㿿|˴C2ReT+ܶYӪEк_}OBqd`e98sVܚ,,?Mecs3Lh-xg,tie%z0U5{o{|65$N)˼> ܝof@MO^<zxBUeQ'Jocʥǧ5jx|}hw-{4 69bMnda؁2cU: zyay6&m+$5yov8VaͩFm )}EHYY΀ڌbTqh^Uu{q`4TfQU],*?s3ہ<\ٵF>5A9Hz@q~2$|1T&Ƭ?%[ q6GQ̖m7Nsv6v77=^4O b3ij=ȩFUa˜ 6"p7 D!^"o˰/B״ї&M5Ha\-(FҭZa*JC ˦DeȔ}R璸!UJvnGfl{|aP-u4~K#~pSFϖ}\bW8m@ZBr7_ /J5[lt&epD['n9Ha`榛LkIq{s$im.G9@>!9 ?I/2v®ηW8'$y1[*ُ`wmO6oxר W;֭D?0)I~+]FTK5(A>YM[ ެՇCqe3' '\ES譾3Ξ,گS2gܝ|EȆhcd.(' B}sJ a `*NZ:M{T3 fxjN&JYTկ, Ku%vae'З|E6 }&_wWxIe:H=6&5ʦ&C:*O‚1tT&{}@߬wgQ_ߓ2\/3SS*;_̖%2-uhҬFt%&GT6j-RqɎJư:C(<;.-rO&2tZn$#ufK15*_k2Y١gPX½'V6Ue =J5EeCg_?[rM^} 94'|o_i-F#A^GH。=u/WnƎBMA [0 O.0+>,xu[ q,zQ롱}6Eobr]x"8c[yYiT'ބ|T6b5SyYOce@_˶^V[ΰQ_3:uHc 6JFM*GV8ص*D2U ;-43R̎{d 2VF*>#^Hsxiqi?S<ϏR' *\ƽ_J|0.6MF t8~L`Zn=` 3eKi|wK0!Ucn-D* ?Fv&d QxbEld{ac??wf#6 ("&Άrrr Mov Ɓ8рkzav |V7C99-ߋ`V`Ւx#Uۺ7:$70k#g؈3|v:E-:&r)uή]50:O݄3Aj ;'> [t8>rQ< NADn窱% Py^W]ל%>h3¨ q5<\f&H5jo%wU9긑йew\.rFp[zR&dI"YC<`a%`y91x(S$y.d_MʔU's5U`0IAP = ]܋ G\Eq3 `$G!ha[J[z/:] (~[[~ok$b=n|,m*ˢ`8& mHY%:zc/Z&0 ]&L66 ֈJDĨFJGW6 v%j D؈ǁRA.cFmcpuhb4>?b~,[J/[ebX(aNS0\k|!q!;JKHS -%=,q>#G)* vr^r\L"}mHn{}qf99#]Ff)9VƆI.SǤzf0E"IySU ">Q ΅lIl\!~vBGI?gVC'P`J E[:7ys#-%IsPu>GgiF^X!dĴ }BZzD1UI+VP T Pש-?eL+(cߥxu~plLkb<+vT&HScePp@Uqr`$Zi{F=+ q\ὗw dwMMt4Zt>SWaCaԸ2.D_63Wx5ܦd|VrE*@ܬ"P`u4X5Myy^r ڀI,#oXEnOn7,zwH_e+q+[dRRcR:$L^cLl7"Z7P"7w;$ooMJ`C4"8ưSUYvpFxP*YE3nM܊q!wp?^~b,-Qqt9[Nz4lgt-WbZoxR0R5A5<4"eB)*3|͈ =֟e u. -U:L7+U@O.;!4t]2 Γۂ0H&U-7`'hmn #Jl 8lE \X-a)QNkMs HM yTE`*G}a8ԀQC8FnZmxGlۃ݆s8^D]K@ZJw,1cN[X*m@AD՝ poܪcۼr{?F{5&w; +ޔcQSj A۫v1(pIP9Vp ڸ+|ZJQ._J \ҹfSM`s3.\aQ];f`톉 /_Gm;pL&Bˀ"ua ($e.%+R5IwoRXY|eS{ߣP̌ %mוK~CYۡ5X< '+h/ahe1 `a IXw*)e Wip! T"B wN< ߏn5FƷ,~J:gp҃ZQR։?~&+֡j"T%A*H%!OoIi[>!=[Pm֛Iz0QrTrT1(OR:w5)ǡꈦ0IM9m远TqlXt9[9YH>3y{y%M7>"i[C7rs7.h Ԉm`Y+%"]>6OI.ݰ`.[݃,R\$RRnU|}C)6+YBGGS' ^/aj ]˨ǧGG$[zdG"k Xwz-}@TKC{vBhO)9X m1^2TEN%Q(Fgu/> Gxp*kHårށa5ѣ`ӧ|0h;^5z=b`" .,vPA3l]s!|$AN 6IΪ:X#X>$u g=(6 B2!Q/tUk_%M7fp[^K޹ %12vETiHoKK2fSRh'䬢4Vbg-k$j܅KK8ueIo> stream x=k6]R.Cmj<8n;&WWH󨵥Fr/E+UW$4Fgsfy[e6l*o?Wϟx&/LeOe):6/?+[Ϯٷ~7|HF̔ctMV7h]gooP4yY|8҃Y&=K[4W_z9 4Z˿,t4Ͳa}<3_.oKKoTޤ?/)UW'C9 +}W?<-QK×B \K-AJ_[i;m55]>Aޏ*7ULȤUޣ(8ꇰ˧U( 3X7ޢp KX6?N*fF"E> Rn "h GKb9rġAzDZSO:O\'qOj`&>/[02l GA6_MioapAjZ¸=?]ivhS¢*ԉ: f|D3p]޸0RtiIUdu.<^#W8DN;8#r6k Ih~GoleQ}6ФYAg.=bfb./^Wf,-Z] kSC0dJ/-re#k㜐\MdzgBm;ÑPvnKwψywHx$'>9Bn)`K]h#C tI>$N \(0*6)pD{k!N!;<߭l0y'NPO"bBXTKcIѡ2ɋAمx1Dsyq/qr{CFs8<̧MS Tymb3=OK +:L͞V'YX®2' !d(RrN- ~:O.GC8bfy(YS@jT*Qڢ,:`4 C#xQ'$ܻN:XPU'PVIk\Sde`YM ])ǒpS~^ u!7YTvJE(n[Y5 (kvb ?Y[ :d$}As mdgvOe+J)m0\w A @!5E}2_Fm-,1,w?=H(!bsq8IM #w/h$CZ5IgR)0S2ga+gꏏĥhRު0 mU"aucbf\OS㦕)+4f26B p .ŦqcS@zo\փ`~=~J^/.rp郣$>1X 6M'%n2Lr爒x2hP?8J% D)).}C $rπV=w=y +@?͘T2KU@5 Uv ش֠Nwkq6Okb8g@* a_A:7.aebH"sI5Is9AWW^2'E8yٸ/c (fNG}K9Io:aYˌ?b;?`64)e/vkUAN3?"93ZshnJb:ܛ*pHxً%P#Vc0ILQx.\[. _Ţj"ps".4ϔc "c#ɓB%gVXw1)_q#.T`mKSDx'n̾o&ME:ʍPrE-wfHww4Cu,3mF3P/'!e` fNG}xؾF'΀*Coب"6֙LϬحڵ`uEsE!;&6c1U]hBk)U?$u!V3,,wFgbJl +,2m;k?M4ZFA> pQ_&o[J,ڲR=5PY-3'dma]buM4^ Dbm SKNt9nlȐRY$6:%M+aZB<=ڿZ]tM2zɲ1aY1A?{3&:%⨇tf~8_2N2FeHo[iJs- [S% yQ,U^=VdKG.^(otR"r$Mq8k?ǀ#BQP&h;06Y.47aakiZ!+k꟬KYlJT\4[8d~d@|/`ϼ!6 _ihӛ5 F{3Kx^mG1^XVǖV0KGٽb"4)Vކ? =B6"a-ÿ́EQ@h^Oge*F׮aV_8d vveսDq0b wAē43 y#j')OAE pIuvɭA;zCy!-Oݶa~ N˺(4QK%yt ۙ?6t_HR&YO%WFưcBHAp[I@8{(>)zv}}vl=NIk lh&UTYmd I [ψw]e'+d$d~PVa2(?`\x&#;p‡ t` txm#A& n\0z޽B@ ?zεƅ)5\VK WT3LdPVGـ~%v8X72TFԍ"fUj4O1җ^vtD 3E$H%תpK7X9~e7^&RKaǜ539aoV=f,XN0hUKyU-Z+<4\Eh*)T$4(<%>Oeȥn>lKE[}!d5]0W+GCʸ]=ZέkĜm&@|wjPJ?ۼ6ݗ|x{(i(O*i3^)fih> ֩,0+7F㒂1^(|E 1>nsCOэD.vm.|J8቗ Y|KHV5,VzhUg2K0i.rYDQuXTUԞfn0(./t[ |NA<WFHrϪ6.&9OxXN5SjwJl;q$ymg$uS`T|7B.)Ǐ4GnX)#9_=>wt'd0e[ =nM ⃐+_=n5 8%D޸|28sj\89ZjDM~¾?71isSq'{1z9Lm[՜vbӿʹuN0lͰCIR="# Z ײjlfmkvt;}cogʂ:# S+"Tg$n ͔wO*)%խN\Y٢u˲l$4?%T&8#^&BV.$91B3 v "KX18%(ZvQ 3gqV8t5K~j'rZd R 33z`9OYwGK> endobj 539 0 obj <> endobj 540 0 obj <> stream xc``t endstream endobj 541 0 obj <> stream xc`  bACř ` F$@z') pGaXTk%PuM?A$B| σBv= NE100.L ,Tlz endstream endobj 542 0 obj <> stream x=o6 pLQ/Q $qd[$Y,&ylq۽}) %|$c}HH:Fu)S&327eo?l=}%*/te'2]l]2{ ^"ҷ}{"[5{Ǐ^Bw?>~C22P2V!JZ٪hegw>őuKytKfD^,MQ,_~鑭A:ֹ>^/<,TԿic^/WzRt4_z|-*5$SZʼ  oNo& @uq/Ley|oB YىPKjJxB>;YY^qKd=jMN0:bo0p@չ2EnJ6;GyzMTe.<lliej8VQDŽSc*ll0~GЋ:j+B CQ",ha+- n8.1ZC"a_@*I2M8Q#jHEoQQV㸕&JABGNAn+<[*p^{9`{@lvBf?B^zs x{= >{n{Z"W S`;J!#Tܽm.|opjQb^_gKYfv_,Ijk^gÙ#X@ZE AdUЉ48IRJ>Ϣ<gHIZ { +Q*|c,WY0w`(>?YUN炀kpWNuu7GN THKפ%pKL2@ +DxD_PWMc\; V#s 9}AȇAJMgJ{C*eb=a tGLڢ:B'+Ok;W Z?]c ~[ u*|? F. `TGD?똇ƭ:HH]vd%%d-JH f{*$ F9'#LA,W:հ39n ޑ%:葴"~x%P@:s ^\ApS>?kw?1׋?V"vXU QbPjb xr`'xarY%|s[7e.vZ_OdH!.\ لdmI\5d<Rs~%4{Ddϴ*ChU]FVI }0KEҰZ A^po~[x=wa?Op>o.dk7 r !9H$ɌxMr.Nȱ 4av8MKp%#Mqt$]/-+:v$Jҟ2$ݦ5|ć:߃'#uW8Юߐ;~҂#ΠwtyfˎݽeB6M 7FT[VdzVO׬bPR 8auF M{M"v e vh޸$m|;?ޓUPh3d?g+3 E)yJفrsK$r@GoUE5ۤ'eUx bjxU&٨\oXx9\f_mZ]a}Ōuɭ4{Pڔ v>4!i{$'޺D?99b:$&aTAц pd\ӆ'J;iۯxg̕hqg"`/[oޠ;g͐_ F\2k?VH8(Rs돫UR0*A@iVya!G}`컠.ttփgYVnꃓ[ y^z<"sG&5wRS[+5-ԣ0k r?⸩L6n%Ypޯqo?d=};x?Y g?ӇI!L4i*qOqR"qBG5 ^t"ElgmЎfأM!gàyjѥY:TZt.&̀m;V:) X l#Jf4'=!%2w`a'mX0A$MDC>x2bt$G$|kS@#llX cD3uQHt\gPx/;<.dB\8[[ǹR Xoox ޴4C5C^ꑫ[jj-͡RC^G}%%Nj+ ܦVx n8#Q |⬕fhYRIpгR Q:~EYᚤ_ŢlT],N8ږR'QmHLW/J[_)gM.Bgg h668p} dm?(^k$ZGSx at"0}P8eKWKɂpE.N$\b*]SL02 )=1iOX> `ɂ)ʼLF p&m28 &]璒pi9goBf$Ne.BCtjr&4S>k'-O#2Zco nq|~TFNucƕtz ˸CCYJ8.|!E`'Lg:jXQR;q2 9 ayw|$鲡v騒Py#h;Vjgno>?^XN_II]5IG$L0'Y"**MDo(]^8z6)oͽawSJeq60IOã0ٓeal Gsj#?sUbJS$$rT(eiiEO˔Lq:T(•0p'JY9T4`M!ѹ s"1yw%P|;|3J*CD暴Թh*v U_B̕4<̩HRۏtHGLCJk\IϝqK7LCPǁjTP\nc( j\h cgIX-$U$iLRFb%_m|.˭(tCygO_Oٕ[/|<7A@OT^q\ %z=D_ZAJŒ#TdHDRoWKݵ -@ݙl%0_#h_3~D/o GjF7{ΑrRhYz'+)J6#%FXDyi6A>YI{E|qf%K42r\d%_UcyQx, T \o p>DdEi~WD6 8fTgF`@2cC v5阹-kThZ&@y`K ǧ|GǡG@kl5?83G#jYkrnٹ;d"RD WafjaycK,׈q֏iІÆ?u!j,ŏ {YP`y`Okx"]B&jWGXŻaQvXS-+5 *pV"ݐӖ.X,[ `S.N} %͗ZyP]pILU%Z֌kD#o7(RPYxU Y+M mM͸UtBS7]ʫȘ4eEw|CP14p"2~DygG+:"ګ^NOqvVir:9: l4 q ]sZ +LzeƈSۉ 4HܮףAD/c&鮥) тoGx%1b]M"c T7ݩagG]jhWfz$eIE1 JhZQYX v.VK-|YKM n=T(+~kŽ*umznI_j:SL17Y=u4w侱0m)  >, K"83›r(uPA;!yt~:υ(GcO^<#yRN}XM:ÚL".Izw9}M:Mk)}c/ڱbm[9Pgtg"t)iU s.pDGfWpUΛ0"kC5im}v{Bx\_ ǝ׀}יW{[:Zʸ@U&n,&+ܪvJ! &JQ( 4KI_W| ?,H-j|j/:yFsc$)q#D}97LQq3(f qv 3tPJ7$6)a7˄4;;x^?`BN l(BR[$ ܢ &u[]9nAޜ8hGYK-:s)fz.vC]3W#'bRt(Tr]>^+cQgl`Q#> ׂ /uPc#W.0 |@C֘v| )r 1бl!>GT;nEv湌^Z o"AbxcN,T%fGEI~n Dᇛp. ϒ>.+2 \;z'^|Jpw \g҃&Hp7d$G;AswAϮ1sʡ3 ђ)ދ<Ĵ*1PJQbJL a #Y]?e#8+YV^{U8 $fWw)mNߗ9bGXE푮@CxE#1k !BthOn{d'xg+e lutеD;2$!?%` endstream endobj 543 0 obj <> stream x=ks8S&mE AU'S$Ֆcˎ+#_@|H$O]M,`h4&珇Tr3guL:-s[eKvw<~:/L:e2S˜yA]d/o!2SKeժGV6+ZۿEĦrȬʽ-<1; 4Y_|desiAtf&O_S;yqlFN>.ʼ|sy.pW%>?hjFO{123U5짢Wyz\T*Uti+|z2sx]sOd#]N,-F9  ϵ͌Wt^FygLUH,ζɢ|D"Ȫ!TFˌkKKDZ<,Pg m6R"0"*AݺӁGF ~?yT0/Odq-ғNgAHM+ϐtyǗ)){R֝R[l aD[89 plCra:B.$2 ҍPz{҉:QlKE^5a*;KC-n'H/_@b4B}wGe;6#]tw iXNq{@l$ J .Ph$ؿeEކQRp=y$c2rkټ# ֥74 +Nhd*gSg›t624)-d/ a h cjK2Xx[ ޹6`@LAZfy"o 5&/h2XN*aHa~i(Dn6`tۦ+WW7ALt;~_/Nf 7}ɭr[k_/ eUM6ॠ [#6bߨ ؝4yW >DuɁf̄C>,t!Lka\7dF#FpG ,zrH*b;I^ͧDp^YT'],ϺtFDsX} , >Skd_3uQKDX5RMw슎08A>0Ȩ$#I^WTW l5ǰB\KZ@ Oe4o~߲7jŶt.3{ Q*F֓;vYL>0Ye7SkErKc51YM|Oc kgiL=ROU " ';gS74.h¼<җe{2+k(0R|2e-ݯQG!R PXUpJقH[sp8q9E%IA;ڐNB{'tQDUg" "cIptY 4l`8a!| ͒ȬeUY0) ]) !53UЊjM@CGT9h+n #[c[c؇sk[k6!!j36%AܢY, .'LrZOJ$C Cg2HQ.3$[D|e^uv3ZgR(G{%H^#H#*^-Y , {Z)vT t`hZXJ}/ E=b&K2#ݶhX_z g ⎔Wk5}e5 qa|pC'o )ю\ ʀ3_i)Q,u9ZgV+N͎G"aޗja`k]gZ;,`!xam  .̽`!-m fF3P8Y]YcRU c=V@ܢ~;}՞F ?7Zz frR9ri~.n1n)j ݘ3л993mʎE&ߊHKsZفvZ-ށ$aKa ֓Ϙ55>5t 5u$ΰ ;#qNʈJ V$"K\w64LvŲ]*3TU&WIIH IL NX>r!q3JmVy@ 4ȳ _p/IrN SJ!-i8- w0O%%$F7f RtC T/5U !_5PG?SAO=hFa 0 uŖV9OqxMՂR33lo"u ,Yf`ec(11aˏ 5p ^5ܱ_(Kz'NbcC Ĕt`J:g)Bkכҋ*Wpd_2sĠXrvVARU<Ŵt jwiaV MtRzZ|i2]bb7m0¶ E_JSmЪ`` Tע.3A1kgP7٘5Gxf䥤WVa'(F|p6 bzqX]X*}RnM)nq<]JH" ➷դwHj/Y&3VwAhFhm 0ȚCGZ,\nEPit"J^/A8 4=2tE=-dZ0Bk45X/(ZV9PTPAs8EkYyxa.Y3¦=wJ槔)fQ a*ȏCk*pG}Ռ+$FO_7kFԆvcfEhFrg X3auƇ&b@.!;]qpT$FS{8q fi5uc$_%-3QA``RBhsF@UK/J)h훠[-Ő$!%KUAX_wY 'D! @ 1&bi:mia:> \w Nu˸ɴNqf 7@j[28flDj.Ҕ 𙙙䦚$6VOKZ<,#'G[CFkS[4mҼn Cv9ڃ8;G|Ro{2a"\4Cu[?>fE ?Z9 ʎ%ox{5y>!_ݤcN.0Q ?7^;%/Q`er{1-AEiIy 7tƠ`],&z(il^!BCh>[8|Nf8|ܻȱƢS ܪ9d)ko^T BTcz@Qm8Qq&-/]O >FB>L,Q)7@9+ wǢ_ʶPBU9|us* ն:yub9VQ(#($R6;(IEay23oK(*pfNA{cM - JEV4Tf e[b1@l \0JާMl}VJI)p5UsJֆz9jʝxF Q4֢aHi^,eS*CTX¾Usr0zRmD.H&qVMcMdD"anh5 [*4wD%xX uőU!V9] M!YCViIwㅟD%*(,նT `pn F/)FD(bM6QI̚T8mKMWM#pQΑ[:yg'BFyĽX̳b9;rGoI}_~G}jRGsH>iu{8 .:I!t= KE e>; )?YqH}z`.pnTquYTXӛQXuJDt:hDCܸ8 aЮ?yn Uh; /|l9gCQ -<3IΑNYqd?7vщl::G'Ɖc5vI4̆|t"IuB!'@r:@ endstream endobj 544 0 obj <>/F 4/A<>>> endobj 545 0 obj <> stream x=ms63&=S3D'N<82Ob^߾ @*ϴDrX,%'5Ѳ]%u_J_V>}'^U}FUJMm*cmV<}TW'ΪWKh_O[WC2Qm%Ę*!EFVu4Շ_gc/7tm';uvtδ*R7F=fi2?{}FR6f4zWK+k.y9]CV@~ڋ;S;iXU+3/HH8"RVDugs͗NkwD"y0];&ľwMǕdݛJ `F˿ DYĕeAg:fHf_$]kS]=E\duW0$\Gbf+Xks3rvѽQGP}|?7sa.2%3ț05)e!8S؏3 żH9Pvi̾ݭ=p/dcq4 Pl䮰Ja7q‘WNcShE"oc\ з}ЛޓFԠDn%z^DO[ritV[h1k<Fx$}%%os V"ʦJ͔̀"Ǫru+5?^i &*nZaڵjb= 2&@w%L6 ,ԐޯGJH;N8"{;qVN`mO =s &$jB7qZhm΀bRF$nTD4=&t11.( ~8_LX)rܩ&V51$џJAbEUVnBP:]7+R |DdI>70iuQ:^!|b(b. 82#ݯ'+yyOEua]sہѵ^6lw´}TpiwȢA´%]W@yaF?pPt'mv:wԆB^Bp$ZNw߿l3nʝ`ߞ| |{ȶ";*=ۂL vi v/&q75ǚpsH.aHq+Aop܈9 ң 5tO>-_ӟn^DOnI F!Ub3oSXYS{W劽 w Ii&'xKL'38>|ujbp'</)iw1S}r -WvADg!;<|ИHX>N:z؈Bym[y辢>?BɐFk) tATV'#(aD DTچz[(V{`A=M7:cM6\PB+(:`<\TW:HYu&^pOA+ ~}P-CW!^oZx`F<2ܑLMKMY}qVvAm%mW N  du{o ){'tWC@5NN!m?DVNu2<;^/:@jr(8 ,$^8}aCH7E_$UXPu>vquHT+jk' qIqPhot =}k')1+ht_-k!Њi\@A[fgSӐ^+UgK^Ʒ?дͬ*r<ҽͬCJ=8?oT@`ZPrwhGl fD[kttLWKD3(+wɺ?|R(ף?<{7l+}RI*Oi 6-q^XiZ@x@FֻXT LbJKӦQ CE#@.)19GtHw !UC@q9D-/!@*rrqz(H5Ö'Ӟ=pc9DXPO\a9D(FAʽ/ۺܡBhd?E7 .zzd\E%[z :Y  g^𓾱TڡSa'Zk#nCzƊ LIޥ&e;Zñ1& 1A/0< y-GN~ j1\_m#ކsuPCFY#Q"pEwuHaB96s4bkq)h%NFƨ-2*sۺ$${L=j¾foٟΉv"W_?:W ze5>Η>'aW'&}C.(YwgqF[` ,dp:D;7^C 3kS%u_.XwFdkQݍbƝyL7\Up]?YW J޸.v7u(G#v"*TNa{];U|BΣvEyXCabDdZnH9MIL lyiّ]gG|y;i` ̔: #iIF8^sc]s|BNWkuBTcvt"Kq|%."x5L15dB_S n 5{pE} 3>%`R +W{z<ĪԲc·<QX٭IG/K#q|e9e!Zpղգ֧Ɖ(wB^$|1 %鯨IuȍV)0iY H4\*s_lJ;r{c-l(x?3BJ@HT25 1L(h|-H e#LQ9s#ݐt4opDT%!RՍpUm[!!b)-Nb鮊 $@gxX c.0fWz3U\H!8ʢE8&XXZO6{cB[ ")<\0UT!N;#4r%v:5$g-Hl 7IMV5i  Z DC|$^aso̶v,~begwܸN,&U^emnΣEւMLfyT˨*@qכ p MxBdDh68j%R]I.xbğ1>C3$/pd5[Bzp\Vtfg8KzU@g|j PtZ闟G(WZ֧9X$)l\Ԍ.D#@dTTh»D@%U.i;Y<Fwg1mQ]"g*bI̦㫋|do-,5`}g_ 04KPg+oTS̜0.}& ~ 'u[> U*oEx؁[Dt'C<&$BbB4ZxX<8 uKK> ,(iN^aFKyޑaK+o}9;{gx2z i5g*}bn;v~S k乶-᛬h(? \,?`ΞT\Ii IjBN1>l޼wo60O?&H;]/b۔ZCZw eRu=aMreH`럙167@Xzc z7?=˜J;{-C"$a?ʦ泧"vrRr`cYyV߇g"̹հً&on"Y\S 8$= ޠ*{۔L}}B="ߒ(%%!,Y@or/;ܤ}Q*:%6Vt~)rW]r`E É43{ ؛+'`s_p8ϐ pŵ/׳g xH 05w[LA8S%zthXBɆ[G:nr>TQr0dSN|B 0(7Jdn .P #gBA҅vB8.ƣ,-~;_b]s|R5QiGڈ؈ZݐJ#?]y9~w?X8B?V >/F 4/A<>>> endobj 547 0 obj <> stream x=ks8S֘!^$1V'fvn\M9ֱ2n<DKLdl~$~}Th(u]ՖPTu?}ۧON?}5+ڲ+hTT+d[Mh]O?<}ӤW?>yɯP4D>ULREӲh/N$n@,ےA?MLR(Ui/OOQ8(]aFs7+Q  W Xٛ鑜e-~;ɫC㗬lsSM>ּ/a8zq@eݬA&=*!%Q /;\|ROU-QUQ[R<>eM,-Z  .*fe"WnKOs]. ۤKD`F&eoG*"SqmKQM!L0FЫuDi+"Jsr#U1*SfEzl,U[4@; 8R ~Χr}\ŔɕFG5A9HtnLn3m 5nbC8b؟'@iK{[1vvwH7]<͐&*j3jj1|XXxX0Fö ڷO8k+ ı!YԱlyH}%jr\g( 59Y=˷jQsiUV#hCs03SfX)[b FqsU%P4dGf'7Sb zF_8ПQJi_)k0]Bnʙ ;'1v6][/i;0/>NQyg Ci*\jhC!~RdG?m81(sj)y`O ty2TYAl*pT]-_ĩjta l_wG/K5>@k\[$L%שP*2 a%f# S 8,fCzu pu=pKِMt8 p0˰&tj\4hJ&(vk5vnmt558/06c lvˍm>A#_bD3oA('o˸]9~DZ;d7z\a[0PG,Xsw'K- /eJ'K&U}(B)J>9bwoTFu$E',b dƁ-,z$oGA􏝠K^Z"Vkۜ~LP!Y#uv2ʅ;`2Sf<.7cF,DltC2NB+3f(]v3V -P-k7 h=0 )̐'4Ah45+&bjY8$> XC7Qk]GqcM-[3xۭ"ؾ̘Da簔x]U]Ծ;T k[kTЎup)˪:>ۊٿ1cϩg r䘵a[%=PGKTYtm֑C}ŧ>_?ZL:S>+~*X&u7@H.gC&a-+Fvq>[]ĥ1??(#[JQ`zm o3z~?W:v~TA`PyP]Y މKՔ *0bb[=w/g+c'^,FlD]RzSx7QlF1@3x>`LnRoU$EvHY))Kq#+7mS%NioR3e:g D¿~6u[^\id/N|6ɻ]W tZ(>U)͐}RT[;F7EJ4}+p5zvrLd38nGvDHHx7I2%tՈPuI<#҃=J;<q:xrZAѻ.Zvqj]јxa+A%Rtd|ڸlx'ў`+* IM؂t5((~lM7r$(n((zp|()-քT'@a>*u6 TҮBP, A}m0( @V@h}7C!n DBn!>|Ă`e,|(jMJ4*cB1G)g^"NL}2ŕdbcZ`61 ZT&'Hfo)B+3f|x=,)FŽ᣽3 ̘[N:z,$nV[w]d=ZŶ^QGlkEo3C'%]Ε1fe4:}^V.q16A z8mMU5޵:U &)vd~SXQw~UaF/ҽXH[Nan6"%j= D!eR ΒI y%_\S13 %yQ8K7OG)dgm;~qJ 7[˳;3ou9蠼^uxͩ8ҵd6$hrz尠KKau0hb7smK<2$wGŵ(jR|l#҅k3[t6)*`uWX$йKgl%y[gvOfۿᛟg1HC|{~bL\Ps÷pҾ|iŻ/IUElXm'_dS'Plm*ֽ*Tk}XvD[UX259!ik4-~tԯ7 KjVa}o.+7]]㰎[GP~F>ޛT$,(S A_m'lK>F; 68$vspcW!|G,Ԭcc6 `70o#?4^Yu=>sّ@?<6 >mw,E=^i.L\k"l żB[Lxhs*f|+c8DelA1/®slrS/?gU( `qOeXʳG:qht ƏْNAUň2c_i1i;dpSG 1klϫ&SU ʰmڶrN9( lhIB9!N481Y*"P.Tp0!a# =M̈/pW$&?O2cM崶E]AO (8׷m"zJm93yD($-"jV䆡# E;#j(2)+:1j̊vMl-4$,c*{}`aUGvO孃;4 0I&W.ͦel^t>Bp >0<::;YMA,SFU'> kn`$cДNpu7 m0;PxĎaȪ*a^5="'3s4$|FYH Tnɰc>iHO""mʛ/rדFQm&?-;M$]ey } < `٧pP)6MZY딺q5𚬕>t狚󅋷hB{50)p»Z{=A4cyҬt^0M Ea_cSjoՒ^4, endstream endobj 548 0 obj <>/F 4/A<>>> endobj 549 0 obj <>/F 4/A<>>> endobj 550 0 obj <>/F 4/A<>>> endobj 551 0 obj <> stream x\Ys:v~w4U|̝gSICKMKjd}`SέKR78wo/_iK֨ eF./w^xVMYgTTOJ[ض-eUq~zXW_^M5%% !T %˶)l#*VVpqĉuSJ9:GOfD*M*6mǷ49,+U*-SVN,3O˕^R;t4=ePֲ<5:oq׷;|Y:Ci/LNfʺMU)UOBZ 5<KOkjjxJW7SW8eեw-)t+J ,WuuiRx"<8ٶ  "q'njSqתll0~ǦX Q-,PgJORNTWyTэ-:=8a4US'(,EC |R/@v)sDZ+.ߋ['Mز)e%vΤm?-e=IPnwi;ߝz3MTբZVlܶZmanXoIxล׎hxMDTe#㱀+UWUЛ I'ꐣHb0h|%wz)5Q!A!uF#,S*̜4YSrs9Am&sze)?XeшaN)rB*{zUn06j™BmI|&A l{p<[m=an8RG5mf\hՁQ'o۵UD\"kYg9q܌ԥw F'rk?mnmf&퇘1587qK4*2*^h,ry ]UrWa2bEUK3xv'~rr3vɿǺ-dI5x5F%u(o޿YRC#e=_gLQu(2wg j d5mvǐ6jghNiQ&^ܴ!3sԼy"e|.qms:1?X\^0<R4bs\Ŷr w}=v!MG|E⦠nƧn <&BgR+(`7dm ~k:$ :rKIvOY)Mj"fi{rZwnmwjyu+O=n@4Iޫ/?S+JmҹA߾.tV,fп- qsɸ7"N)dK&~ٸ삃;hG}t$2AO9s~ &:쎘')w<I!##̿ʉ3a9 R ӂfՈ ) C$fA5k<[6 WiI̹E9< `/Iܹ3u [NӷS v5~$h'Y1ӕs7нX2gi*,8bi93TM3V@`b=Tr0*MoHm%NH ڣPom!z Js.2i٤.e&\/7u;p<+7&Oą\. k@Z{'‹s=L /G9Y 3kҕwS46w xHl(e-9th;&:[;D"FP QEzU@KϚYYTX9{M 9tVi0)ړxY5mj<b9;!<-Y@<%Uŧrѕ62AdՄl<jWqZuiA~ɉƥЎcdqcOj/Sa_~/ pcsSR[MK`z ݻbt#WLnqehsSG)g!gP+(z$28׌9od)LcۡleꞴQKI YSp3 0{˜a{OsBZ>waFPVbzc!w&'(6 _*"s4%%lʦ{zc&䋘A2[\=q|wK@9GKS E0:ױbvu*[X0>osXE)~GܴO@}y%{5E Ve||v訜33b06h,M혆4E7,0m٨tgч$=Xa5]Sm! 7l3 u SG&U' <d0}YpQuH t}Ҫ:U83:rt1:ɿX, 6_y6:hxl)ʮwrw,~>?AqCRlf OxceohYf .+4kf .@6w;w-nHIIlAU^>R1```.3E G2iHfF?vPu%m,$aKk 5"zZn2.*"te!%CnafC"UVM% c~޷sm#Ȝ?Nb&Ė `b, ,9M∲iAr/agz sO^yi[TF}9 rgK8wK׾.8w[ʦmIP"0 bEmw cV &߰_61.M*jS!~=ks8Kw3ɡ)FUG ݪ+ yѕEDGFYKg8r<.rF/gxC8g FCA0ݭJ!QrY-TQ֙ #GھܾbM{ĭL.6&oĬݒM(B.%-+˿ u!ϊ?>Q6X1 fXspOYƜw+Ms| >,F, 2]-Eɼ;HYJUa]R#kW;ZwR at ɬ (lgJk#Mp(/M ۴9 mdY}pOqfU7Tx7-%CwH) VӮx]k."Q:Pg&AEKCJ8aF1ѐ|=pS.+.r vfse XTvwI|$^?⣸_l0&tz-r6W E. w|ÈAul̬r͕Oܳ]վ-UF>mt-"Q)>!Ħ:(+RPr>ﱰQF'tYJzx *'@z̅U\TeX9Łz k#15pvu;J ٴXrPI x#ᴹȴ/$ Q6ôXԳ͡M5rI)]35NXg- zXx6_ot2̓5 'Dc/܆M\l}jWCЙEILT|hY%s?¦dv0a ԌFSr{~]՘Nt)]AD2e>yD NWKgmB.w[7Cp׌U?2mIu衚O~v[_Gt> stream xc``t endstream endobj 553 0 obj <> stream xc` 8c I@x,$@Jv $S@y7?HX+#$d4+00&8}Ib$ 3B\ ,B~a``? (qh۩S= @Oq@ a`pp `<d`=} endstream endobj 554 0 obj <>/F 4/A<>>> endobj 555 0 obj <> stream x,e׀嗧O~|HNfBJMZY٪he :rcwVQEC|^?vϦDkFi\O4{ʕ S$J/-~Z/_lɏi̫._q78૛u /[j潸3=YWtg) 4)KE_ ek  9^zeTQg+kn_6쑵ѹ9ǿA@jrUfT^<ysku&u G$=I_A$U4~gT}\YZɴwn A\Q ,pg TUE"o@"j4y]yCQQWuCR[X@{X zq{Re-WA9Hzlni{0$}! 7&l<Vx_ex=Ә]{M(TѠJ̈́9r.|X0f[3 Yzeu86Mh$k/TE oAR*,F=riX+fІr*ԀZ.Wj+df1RS4굌Ju\Ջ[٣v'h7۱ H|f]3seU`cQA"7znJp&7 /f>ʺikǢ^=W ] bqKXrNnyIrLR.5)_nES/ZdI-Ϻ? zG^bç#e8RZtnᢒ`F~ S=|c R%otmYFMP>,n?` ra(mw^vk]=h-AMEa Zf,Л":\6a FbncC?n~6<>Ybg,= 6'[L1:nZG 6Ab滜g{e4B Fv 3UM z}⸬:f_: U&YnB̐7;A.8rdVWp1+PM Z0S_:7X;R(FOkIiY~Mԡ!zf0:񴶀| g=ڮI`pw.žҴ28Vx9v$?Ae 7=ON@I'wY?5q52"_k65|=dܑ20@0F m^t@4\88edWI9B_W$}/bEosX;7{ ژaAͣMB艑K10nXC#0s%nhDUKX".rP۬h0xc>n j'xSIs?7:V;t!6EgHPvQDȍLWZØ5=xʥQsw*Vk,ogÎ*V=4pdyTcs\!ɒ]\E5kĵů6\@/+dLgWQ!Y\)YMb9gM+IwLkFbc֍ƕct1i aMب ~zE ,xyT\z5Zz@WgW10e.|QV}.~9ץw\G/=Ŀ^Sr5sjDIWM0\c "k8ڴ' | ,cz\rd+1P 9c<(KRiIm|29rz<@9HىP{,Z0xig-o[XQ[)KXY]o«zW#9>Rv4wZ_)apO`@VԖ .~P'AҎGӯ FqkŅ0|ޅT;xF_"hhªV9P"X́ӕMQ1ɲk FXȑ[_pH%p4$dHl@qkYI>sQ mȟ7 DcXnQHK6aQ w Sdr#$߻w_g0T>YA<}\V 9A6آ>'D+}J,7qV'иcEmPiJbo9}{eWaR ''BR$۾Z56nw6 kE҄llR # E>mQp&S/{ "w+(a/; %&<dOĢ Uƚ88'9H$kl 0 )Qy9d87: .\xCc~rc댆9 `ɬؓD:+q|MLm/ 乐4n8`ڕ<\,\SD V?:{~??M |#>a<>} =Kt8G1ikfDR }*WkOK7<g%z|ːHǰ]<. [Qkmk /iB[;hýkbYTӆv0\4=i|D[2/=LY)j&81r6Th^v.2*^Ԕs *J`τz L6L L @X!'Bd_>.đxg}Nx}?9TFmSʱYS넝6v=Ve϶]+>ް=vf^1qdo۹\xѴ?18\() 4%j$Fԓ$ڙ U|ȓj.z6̼gS0ll;ts Q|̍V%ƹ!HV(Y=A¬<8r2or$dpz Yao!ۉ 8zTASA..nno +2~\F0iJr؍묿C^A+hOգ~ "LCj0LR*J] ;!Ƣom*P0jNtvdr:nnF' u͛6nrv.'tn36Pooك됯ο҉nrݸS=:$AWn'U9=&*QwROS_yrF"B97hqݱjxoz.sDn nYj_0e0 (ՖH|;yotOJY>*;:ӹp4Ac c\3IWnPp7aLxrU:i)Eo IwÝ ;TTa/#M]FUi[N "qQô{E~3LӡΩx %1FqɋOad᷋4.3:i0`\pP6.KN<^(GЎU] Ppl0~b)ɮ7˯"J#6Wa57`Ѻp)L`va=5YZ "ko-AVWgQV,Sv +ʦߔ}$4bҚEFvjDD v{wYٍԩB.Ny(ÓPQMԸD `}@Q嶲 ^Nl/+ $Z T갽stYm|_iwUah 1 `ӯ;_(3j{D&IS Y2_?7#$OQQ387!ޞ+ V|)~xu ǜj^^ɳUc ^ l/KkyJXn|( -f$HH#$_Lo 7t703>٫3_*/л6vbFZ -X{c2g7ga:zc^,U*oTVNXeŐ 4|)e%!2=kKZܴs^" .q޹T/nWDnWfh)[o{ S9٧2vl֟t짪F*kLXZcyVy9횮ki)$kQ8oޢd '3Fr,> stream x=s۸g&HKA;Id/ݶQ,5\YtﯿGAѾ$Ex7<}jWڮpV]Shۖuiby~[l>y铯^-+Sy ´U ue]@뻧O}EͿ>}Z'|HƮ.t]vmZ hg@kWzG8ѱi˺KwfUٙ(m(/./tߌud-opuKYWV,73Rkt_6N #|}sW_Z5ǽ33ڙ-fJss1ŸRmtU>\\aa/L-)=s( (]ma:U: F+PtUڦT$5[HY/n$Uuqg͘p`\.[W Jg;f* SJn]6Qi  ~xǥ3 q4=,^?Q!(Wh/-^u IӛreR̆Cak9$.$W iRo+,@x E%~iAMWnY虰 #eÂ1u?^{Z.$*:n z]g0 =DrZf1ET|w8nPkns|&JPzY0֋`Ӝy9EHBZyHX۷i|Hu6Npm `ϭoq_A4t̑ae8.5#kPد xP1wpv/' _X~Z.CU M[JpVl rcJ h! U6C@xrUb#y%TY~.v~b70I>\y`5qzŒ ߘ}y) 䏊 | Ӌj}%O??gfe僖/a{ 5uAKg6h@"\c KhP(Ph߈F?Sqǯ+o{0W(7=n(A0ĺ oQ1BrxTݲΟayV`o_hxЌj%MpO (4HLxD w4r A!6s&Ӱّ6tdHwXwl"6Uϗ+BS$ %O#^"w7`~P,8L(_Z}G0$˰Y\FԿ4]n}WA%<}#mi8FɊO..?l , ҔNGϽ[ɪfjLF#~Esj<:K|1|*D EfAֱj- ݵ*N@W`V JRܳ՞ej2QkVQ{U׏Źj#AQfz͔Pj5USAEƚ%tJݢjIz}Nbzgz>Q56Qmj/FM`5>t2Lk PG&pj]ru@jFg~+Jq% U5(=@9}nz\WNk[{^F]WQk|+9Y`gQ+˨X_|4|59ɨK1`خ擯qnZS  ^mVs&zs?y9TgkڔQ.fCv#hs r Y١3̀{M|Jg5@D@l'3= ~~~ [3Fsz@~Ć sU SS #Rr{ڥ&?%_eZuq~>XϴԨD'!12.[!yASe"-zDw*'@}s#;6ޝ}&g@sSեFY>f=gQ@Dō_n{q]y)Dż^D7|o[7*m@M5' SpJ-B S뉎3j%ء+ 8 9j9$K5ST#LvD'zT@)cb@${e+b␌,e@q":^\/ݒe4 `AFs0x}dzaOCFM']S>Ci^,c؍86z:BY;3_bst]+SU|nEجo줗${x:ZG^b(<GȰ(DFsWUbw0sA9)ɹwIVAJ(טJhBʠ{ Wٜ`*6˒Vy|'p?8#ܱ+ 4a y}fxzG,Y nࡲYNoJ#oXq" }@~!fuHi=gjI 7lR72R%w=(r+Wqɫ>q4ozb'p/ ɥ'r^0,/\\0 ܝEh.L +*k>?pmb|noeDfd Xfa[ў<8+Sv7 3 1P9(=ia2!Ь1}+3Y]1vNXC$x5%a|m{U Xn882]/ӁɔaZp\ d;s`6&Tqi'U4kU saNR(0B!( X*wW#d Se%]gyXJ8ktmѬM`}low'0:J'm2v,9@Oޭ"D]@-+95TS42JڙJ:%(j 9Ekݷ"BN̼d* RZlQ{ ڮ"AJzx#2p_F>߬V9t ;C I@fG4:2:RB.fRӑ aRwնG\nr`;֣[21?te}Å֤488ٷp!jri~6J'7rduY[ɳL^v݈(9pJ:ω$HfPZi\,wţn&b3hqK;i)ȌQo$@_p"7АsЦ%&yLK rB"LJi(ԄDaf+Rr8A,Z)5>}2pHճʧKjkzBw3"=܊"$ץgJ4倖'ltvVrH>I/Nlk4s<'pW: cꮎ(ӆjAݶ?!j~ؘq EPgRa*/!I@N?٫ůː Ղ"tGxSɶ MJ 5spsl5m3O)S*̙%*H"Rd$ϧ;ltUf4G&!N1j_F`jQPcD! #H0AAuV0hCX܊ WC2ћ$SQ ^* l`r隸udB)|?:s[-e~̕'XFi^l|ْ;Q1 w-9(>x{/(=|F'TA-6R6~9:tWm'=F4H u.v;+fX>V"fP0$NA!ڙ2$N@`HC#qʹ-f~w fa#1Y922xbr2 !|Q7xM6T#}&ѫ&L#}J''s#uߖ,S}gOm e0O0t{`?AǥCb.ݯ%;FCt#ϛ1m3B91lʙQMvquGr/Ÿ] 'gMwEb?>;#IΧ|f*>)P[9Ty@N{"?c(nci㇢?:%K1T |N ܚ?Cڋ+oWRs}{ I!)}֒~%8$~ՙ;ql\>5H >T#U֢Iys蜎6\PiQM/#p pd:(ڙ (97 <9t$PQzxSjJ+ {rU$mo{NJO1ЂYQ?c0UrM\y7oa}GMK"g`h,I/ ɟ|mӞ'*&$ ؚ*Lzgrf 3bM|dCIz4᥯R(+UZI[er' ̊nޝxP%@J(XqɫNar6W{NF+|th}|^*E:anN'g fMiYIu԰#}!>/p/e8tTaA.c lD48{Y#5I5.>LKΔD>Qbb ֝: ð_:y]6M i|pR oѩK=i*}*%G1 տ)O>5+ o峮xKI90i~O]}x8h~{֌TEq0-EV(+JI9i sV tbә5]A( ?lelf qNmf;yb(>0,ߟ/EH]z44؁?-|:?B@;2')zs/*ve{&-z$ Pjmp>x/ӸCH$ O: A+qk{x&=֑^1ɂdSU:Du'ZpM6୷ɇ/C |q:0% Y?ʴQ13Ky pD5aN,q~%OX"7zz<UE?pea?@HtCq4:z79s`@Tq5twmβOtӰT QATwlʇLbҥj9C1aroI>z3}1Vw,(2!HO:]{C@vQk1Z+_.u['% go)Ӟ&27TzUEt4aC$!# b=ղzVbtկx^Zwxo&Q.LZ'H/\nZ(2&uGȘY'x5e&L.t8V6 G s;KmMas< `6wNXwñe@3Qn.~a|O3~}k 윎N=;_4qCs/ n$+ v PC|;lGg 7Z9ofW('7<\&&#_-\/wC|a+BN߲a@G# _ۆ2Jf/W{䪘pJr wge=)MaN%aU _1G}`2SBb+;#={!7]GGzRjkPH 7⼑UB5/6-rx8J9Hz>zh2ʥW*cڢd mqP/*>@UL{0Uf{uq-^_y\\jȸ\7@ح%$̻++t@Hlg+i"Zk.g7y6Ddkuǫw *%3|uE2 }'خ | endstream endobj 557 0 obj <>/F 4/A<>>> endobj 558 0 obj <>/F 4/A<>>> endobj 559 0 obj <> stream x=ks8SOWRj/ܛsU'Sdoo/s5%Α<<_ PE{S[$4~wgJҵwl¸tӥ(ϟwh.QQMU·m?+>Ίϟ6m鐌.b.ۦCXTm|x#ۦg/=SektUK|szGw3Kߖ&{O|ueJcIԕ |ag+7{NnKoU/ɥ.!q78᫛ |?Ҥ 4ŃكuUsb9Ue_(# Njx"駫ᕩ*dw-훓h=69Ҫ+c-+lJ$W9ժ-N74iR$=خɺ!}q$q) Jl|al0F=R- Ղqa(V@uUZ*[} 5ӎ FC5LXnq 繪os5-̕]v|QTW~^ I?gfGoʗO1Nհr.eHףfKx6k9v;[ě_2Ϡff4 @f",ȩV`aLm<ʷGp\+ZCئLq_@I&{҈0vڠe1E5eU{Zh5̾!,yϚbڜ,P&@O:Yh%xS!@m- ߑ(%~*4#5c ep;6 1U@_;|p_×o_Ή^K뎢,#dPƖ>ȁ `bH+&40/7(||%v#~F 4Ͱ6 E>_|Ϳ@)y5]"=XvLbЂl铻<˷$cz-7Ղ K/ނtB+-17Vqn`TD$N-Y͝,Ҽp};%57&, &Cu@*?;fi}T}RR`,Vg)Dl8(5Iң-|;2 n!bBwc xX.buN eqz"ֈ9|,>n3/1`0&@xءͯRَj:Aj u~Ŵ4l-ü揖_϶J{+-I7R:ah 5EmxyS|ƥDguK$;wKSUq+V i0>`*DǤWv9EeϬYu6U8%MVƔzYPQS2b"Q#2a ecե4 ҥqw8TW) E7h;]`#ԥNASE$.c-sLȕuׯbr~6br6[1Hth{\5V AS,*`7->]厖b١9dɡګRP&U3G$R6YkМZF*09Oh3t* 5u;&hY8<6Vd^ݑ;W,eGJ"w3`]ՠK1LaeP< 1N\5LW踙N;|3df\Sb)0' h[f[q. WiQAޠ23,{#wLz칂Tv> 1h c>Y QZ6v\Mܜp`9iz{[:.ZKb_ #ڲ \^V[\N_Zz I6wjž8U"wj ]h]|m֥M[S ཱA6?}گhXҔ18٣-KvN`8jch&kNwb5|wZkG}L1 L*]ٟ,ڦi25S/ l17SS,ʵ{@a"h/Z?ǖ>'!=NI 'Ԋa;"\Ee] :@mB7YנQV&˿iD\Xd~57#VXd7.:*k ?a'!-K Luԃo PIBϒp#ƢWt%6GMtP_"b- A71EKJs_s t9dK ǿ 5l X(_nE7:0E7?,*df}'3{bN7&݆h]$مٮeExx .p^RIx!)=r:cmi׳n lba^:}4PN`N; XB\WwDI]PAv]77of 9Szvr=XCԔUgTT'>Wwj4Ƀ19;ރµu3k,L`~I%"zAR5'*b d 1*dӬQ&3ʊZyΞfOPHtI٭;bX̒'O,A3Mx_&4+3 >)Y.5T+e[+ ^Eh~Z93ry3OaHH텘HY  c-`6@j4Hw IAt}?cq#Pb><-oa+7L(~^kKUxzK8v%vײ~Eu'SBf?8K XiOFY"~ J1 Ge{lTv|:($a.eEleC~'u">3Gmmخ:EJ ؽ $VT2c;}'Yh~Bvg!P UգܘiZ͐~ޡɑV%&CFBR4jMDL l`z9i̪Qq&o!٪$!|BS*KfJ@;,̏}_ i{"cԮC'])*@5 %h‚!Uo !Z6*ЕD Bd\ #PSd'"z t$&hFSSfĪh zjFS{1/ "~k|\P71G:.9nYa# ]^ +iAlWt-/QYko/CVm;V D;}}.lOjl* ƭU:B&4Ϲm~$GUvCPDlV܌"eŰ̅tDK.!%T\S{Wp,Ȼ7B"KQM'q'*F&~7c>tԿccRXV<ւokɘ\[4gisbDW &=dFcz9o{-n8~Xـ(*ڡ뼻yݎK)ܭ{||?>Yb>(cmҚZ)Îm}ꪧw#$#oQ'9ZM%}Q}wGȢ [y16 "GBxY>&o&Gz3jGrvסYX'iQēA i1xg2"!,PQUQ(XpDžCI\9YZ1-05&g/ ᑛOCME;zsMn82y,4W3IbOC˔yF#eU3Rrd-~{ViϹtqb l:G;պf.(sv-x05Q {Zv)䮗[kDGgvTw~ǾuÕRAĬ*p8(ưu4Ǽ36)l># Z1^;=z|pmPӰQe,LRw yel߾1 T9o"5eF/äAdH )>Ogt{]! x !}<Wzgƻ_L${YNj7½U: 9cC!zy( I/>.[y('Bq[)^t՚]U1o|$j@t#'r׽ɛD( Kf|oZ_Kp#E=dOK=ė,n3!`28 l}1[nE=n}-s@A}/zn}P_rfYmx󱞴i/0~_djɟ0j *._OAhዺ8.H Y¥cH!ăvEn}-T^% C"/7႘6X8«:jӈikDwOCn h T Ը !A/#V@$,9`_YQi,Xj\Tʜ"$'ʑi˻MH!W3XpB::mw<75Ba'c,ƤTHӢ}.'7ޗql B!xcQglÇvnA endstream endobj 560 0 obj <> stream x=ko6?X)bE|@En}p.g@c;oy%9 xfC3!miUuLSn|]=vghJ.QQDmRn?+gbŻz 4u5}edG@+[8_g8ұnJ);>_}Ό([Z/ݳ5QڶS?}{* SVV,7#e)-~;]ś/ݿep']Z˲>5y9/Z '3=ؙ)zWR>co5<KOjijxJ:>baniua@2nEijUֶ,/ޮ6mq-\.'Ƀ嚭 of}UmY=*WnxZo#E\ Q-,g0JRvTW~IW=ƖMaOg'j | KQ#f;؏{|rjqѳQMP^^~Xo^ I?gJf7a֦`%̜Ia/z li̾ݝM/T⶙5 P :r.f>,Xa-/&Up}jRJg( =iD rв"j2ߪ;L[mrA΅CJ x^H-JY.EnBdF-s %{IXUul{ G˞hAǏ0=5nC}^ݢ7W,ߵsTipoAdb`}A ƞ(Rр')6А^D"˜lSd 2ܕ-v-H.~ VH 5B)CGP,n6 і^ jM,i4_ZJfPH&NpfXaIQaC4p`5~pv!Y)a4( U##b?&2zp&K] Z.^v$3;PPuϼ_bxW+܉cYSk'ɝ3䒤~YӸ^p Q%~:s#p%2?sfWZ8TemR<׸e(A8ft 1f0av1I%w[Č5?> H|Ljl=]t4<:gheF3qsm݈Z:oe,VM-tt*Y{rM2CδML-9  8[fio 2N 6uPMي\@kRdFX<•S-u$U[jC0 Q(`2c'#BȀk\G sr⯝#7#xE?[E>:>v+JE]~ 9@ߒ#%C^B/:GН &<oe"@~,x,ς@v`} Twx[P$f?Sh{)Џ.)60D]sl]@+?V~< ЧC$m SUC[;v3m`Kz.Ԋ:?w3b?9|*EUA/Ʃ(^~ezu7s'A 8,!QÆnIn}bҩw$:[9\זiڈ9(8)HLt颍Gޟ,i!M`Ȃ3ZŚ4m1 a! I M0ŏǂ+DHb2!v֊ٰa9<iyM~Lly`գ3ӢnѢo }_SF렓i릴 o̶C0ooEU(1ْ`7-`ͰR{@jJZŶiMF^Mfc9FIk}iV c'0#"o> ꈙ̶aX} /lm[1I襇uOa^Z4gz3*-ttVo3S uu6tl*dXt=jk.zxۏ˸?1'iQܚ&>2IHO,@0dl!0y[/I󒄪5T$"ښ '_a.4⃯n?_VGcgB&&Xt[v9 CKZo~rJol7N륚tE%5"vbSw0yܠˬ(4TS<.V1uC"16=V eR0~][' "莨s@h 3!μcA~xk:m[br'ɴ$T96/0˰g._HE=#3~oli֋;B7U\0U;J,xW/r׈0nV[av^xn\_×bQ إ/V\a4 */ aR f6nVlOK*0R ,Uu;mz"3Z?uDNY#WF:^wN:R=^.`(X}BG׮ry9[O0~̟і-"gêk0sEIa|8Ϩ>iB׎=B,O dfwBDMYNsw4*Iap .(`~SϮ :fn:<կdxX"ǵ$F]t;F>e:ҡFE .@sNa F2czw0N\] la*4H"8<jԫc!J{yOACϜsq5gٖ 1 ʴ;~U8 \Y܅xd,=`ar> O7(ɮ+:|[N@{G+卷*6 EE1-*NBxr硅9ٲmBZ G56 RS;DkF=1 Q/n7FzYr';w">~\~֯8܍sL^RVLNj=Ms ;5 4Rwm.^Ň|u͆hJW)^m\eƶkj/3IE,t CտOx\Xn(?rg7L Ttaufrh5t :yi(RE}?cט_rhSX X 0mMťմDHE`Va{mRsS COCg9@9Y˰NnSrNB?9OG>j$]¤3OQ2:իy_5zPN^u'cXf*QXL63 6B9P$Uy_xjͤ&ld*E'wєvhc݌I@DfatC׎x^vWg=J9CI'}xɱ~ϓb<"/f({nJ+z;/Tfmb|/r9 d&vXMZsO1R| S~m/V9_^A[.D=[/@/9QD2F,#O,ayՂNz:Qx-LdpZ,kZ<\s9(F,=C^GW4)I`B'9Dػ* |TvGx:/5Sf㍧0 }xtۀk6fԕ9hFA/]1 A-Ϙ2H͗P:oW endstream endobj 561 0 obj <> stream xX[oF~70@_"d!rl m\Fe!t_2IY Qșss9G)sW L^¸2wbۜ؜:?{e.&!O [ _UWwgRߛDW>?~?MlJ[ΫRR=1KdWO#mk}Pu=2ƽt"//?㥯r{8˛g֬ɍÉEI3*ŧyoU^?B#FWy ϋNHmĀ^T8)Yr>ZJjLx%~f,^][FJjy|/^2h=̞9[*[ur?dd8 0Un=\a‹Hy^5"Ez#<8&D]++]Nc[^XHz`T&FUYg cZ5UTܲWpjjOyYOGFJ.+ "sMj-c+TfDkiVUOI[wTO𾪘^uj.ߔ+?lߥȹ)H/y9m= %,)fdes s"-ܑZNd#Mh?cHW!(bryDz )7.b&b;mӢJbz*rVDm3um1C Y^#rd [i3<2iLˤl]c E?%RC9?GT$kf&iؖH͎|KLUܣDA2ȯGHb{t̺*ozP,%RJL"-DkAIJVp^Ǔ?S#Chbxs?|e)uU,^c>b䜻oS}%\Ъྯ"1FTZμmCzOH Ν^ : }LR{&7YW$LBʀUL"SQH3RUTP1CG(fXG9]=kU=0"R##d$cco,/- zoZ*/xsu tR .Yhl9#dĒ<ı?nbZ /Nq0 WxIqASHAہҾbWJ⏘FÉ*MbNd?p GcR'j5n- 0 bo!sjlA\R! J45Dݵ_ fߠbj\H9~oc,N>c=_AI޽\m6GvŊ;~8<l #<}": #t,ѐoOon c'0Qax,\C{?BPEeeJukloa.(#풚@M M 9I=UuI]r'_"urкƮQғ7)Uh8HIQΕsw^'NHn0{]=*HɈk8{|=X4t?jv݂j<s]PL5> -ޒ-^9-p =|MChP8o)AɘvhCWmJ_0gc0ȧ2H>Q I`h"E?#M?*=Zo)W!ogNHY0rzC/{ll3sq̘ Qܶ%]cZDKKosc&4rNM95}-C-ƁQj 3+ve!ܡa ]ð $nE2?kKT&=0JM_]{oCCLn&|Jhh嫐7as$_azp@RP-6[D "8#/ؿEjl #C}r@ endstream endobj 562 0 obj <> stream xj,R5fyKc6 w3Kck9^/74MرG~V߿4~궄x_j^3#'|u_Z'29LZ#{4BHM#ߝ0K w\z|$;ݺd#J]N^[%[r8 8XNZFyv{C廴fH$knR_nv)2=8W~x)ToS$XQd3X !'首OS[}ꍮLd|) z^˚50F7[=#>Y3ѳFT[:kյ3 359e)uVN_V@ZO~mݵNs W_|YHchX :r)dj9,Xa[- 7/ny:p}#4)z ܄u%hY:)jӦU^ hõ 0 LPFsLd XVikaEEI&WmJІ".~ƫD~SMMPsj@i#J@St'K6Vp8`*{x8B[Pw<+q^LpAo@]7?㙆sIvz08Y2nP ǢĆU=Q\<8qCme2րIV[v$uG!97NÐP ܨv A8e#?Wͺ(qKKqqJ ?.u[4)5ϛESJ `J̸tk أiH±@/& 9p(AmcTGG ,q3T+uNS;|xQ ?#6jO=xvѬ}WlnV?9$L;$?qY8߯bxVKBJS ݔaM(d_mԝ՝Z\pK)<^l_x^oI,TGNZ}uyϋ`':j'.î#k~p.XhȎ܅E"@G@ m4bSVR@+Tji 6CɧaF&B]; ,0,3(Trض+K۠/!+V+Pd$?6 s@z*TٌrmR#ҙN)*(ug{"x -^1ßK>ش`$ "ttB'=dǩ]DUѩ[.jnRb]Q)nB:`x_PE, } Z6N5in;gVnIR׃v |̂VB׆%j4rV`12z3, Tۆ~`d caՁ; Daie`iJeQRd Qd0^aT 8Ig@,Ȋ0lgFqvPQq EJVN(H>Pb`'4ylǻ1 R2!7f tx)8aQqe)3. Mz*'r"v; m\^̥|υ|K 1hP(?q_F`'!S c4jFP #M­qIy(HfAJj1oeZN.&9'`i3D<12-S i ibȠwXt~L>e[c8BR4{HRS*C^bWFhak#l ty a1a-}E~C.lxBTLC)6bsw) Rjp`%UbLa[JcJao>s-"FZu{L?60ڔΊS2Y6B%Pk&5s *@Lk0S@}LEe3Dhfƙ1B;3/#Փ4 խ)`ۃyG虀I-1Ws g;! W$C>x-TACvJ[% 1 ,D%Gcm=viOb*qlLaMܢqvYXh*1a֓-8HGX(2NqZM%<,o}ϼ͌_]ne9:|Jvp@8p_%982RZ,TL `ľlDi d?sʌP2 nos6Ũ|V"=Qx^/3b4#VHw)Ei1 Ǵ|)gpFeuõ3iMh$'G&fT㑸ddg+sMYohpƝْ1Y,S!f kj㙉ȱbTۯwů6tAz#&(u RjT*O6bN[i-8wRsp|75`_^UoqG:P|%GS|;,NL:|(8X95 ˈ gEј`vB _#qmuڠ_ [r݅5KPTO XJsJ!]ʃ)=nBRL5Mۺrźi,٧K53ii48wLS,UY |EL$S%ꪛs_O,NѤRThQe(6糛D ʉ&5ѿܐ(zą3.nU gĖlnm0yHq07#֫Gh9V8WoeI,{(+xhJ$O!H5Ԕ) u٠Č8|MO+v&A@C+;M#\6zQwSا4Њ}M:rT$aDV(ĝ-O*Q#ݕwa`ܮD&h|w@ E *D顯& $ 0CŪP5b|-_Ө%gbr9x2r ݷDVś Afˁ~tq`/=p71=r!?z;j2n ,suKۻ0g`On @HxmB]w/DyLtrMc!iF!5V.iE K?jB5CpE>.=н(dHi*#1ct"60Z52yOU"5= Rw7"zǙE7D#sQLs(>Z#\ ėd?o&9d@ z.=3d4,;@e?&I^S F; t:˧(_PI5W: ?3- vǻaoI3IEg$,肊3؟IU-NJP|VSG]"ͮoЕ.܅cW<>vx,J/+*tE[1CZVx1tt -icBhh,}O, qM2t>Y1oBj7u Ht}.́1}&3usd*䘕HYv=|ǃkDȚ7Hc፯j̓QGDR2ח4܋܅l/_2]΀n/h\z<}[ٍBH^97>V *v}Y/%궷iUKIϤrv֕I t^[P>oy|&;ynBh >}.u5Z1%O:`lC}$w k&ݐivCɧa<]70N 72:jS3IǸ3i0a P^?%IwEi1*c8n/i$&"-ak/ݛUY&۵O0̐ya2F|$ta:7R~$`:x1LY̧c 8{nI? iaxnt~"ENeN,] 6Bx~ K2&MhWukF E,ӥ' ;MowT)ѭ,>1:E9*RG6|@ܱsӨ1(j`e L˛o]k˰d*"2/d1RHzLT Ovʗޖ(b{YtM Dfb*]FJR?0'2ٔ>A6ɦȦlqPWS4ưTEeS݋Kn4[X mٸ-ÔP'"^bU$μ֝q ݦV.K=tzzr ()$CIz5iF|א8e]ŀc' `65y)9R\7X3Pa<+7c{99 $@ endstream endobj 563 0 obj <> stream xc`` endstream endobj 564 0 obj <> stream xu1PDo bG0^ĆPs{ w>lLbvd?"J՞Ĥ( _h6НnHɵ̝!<Чs,0Y^*'`sXz gez^ ZKE=m,YDuU endstream endobj 565 0 obj <> endobj 566 0 obj [ 567 0 R] endobj 567 0 obj <> endobj 568 0 obj <> endobj 569 0 obj <> endobj 570 0 obj <> stream x<]6ࣴ/sMǓ|J6;H3V45I~@!Bک< 4~BH[Fm](Ӕ04u[|?/޿|Q4eTT(tSm[Uq}ŇY1x_/_| ?|sTL,R%,ۦ8 Zُ͇}G&M)f=eӫ4UK|{}3[ҶgigYVTwZ,Xboz?saf̾~(ZZ˲>-׹߭EP <œLY㓽*.5c U\ k V粆G`rUM_M ?o./,~oSEgVZds  T[*SVDVemջݪ-CiRx"<خldPx&Hj1T~9Z- zNJjf9f(}x*5S-쾈nlITMKR?ޠ8 qa|]l'P=2 CO_vO] I_kLf'o–).9~oQoοm7Nkx׿ x Jq MU-M2@*|d.&"lƢ}` G9Y b+FcW&Gl!(6Rad1E4*ՠV [0XÇMRHR\gZ1M]ں4*oTţX.k- j/b<@,Q9DY?nv0i+/x蘔.U"_^r~7g'9ē B?c4!a~:PɺuN!w0G=P{IM ATlIչs Q#,S?&1R {~ 1OKՐjYPųe-Ӗ%>@I㥷9[ FָbK{{g 2aޯ|r"kAoLV4[t;lz%Y a bB[AX i!=Tkڶ5E=)J t[;YohG=G`~;,. E5H;([TUɛFUǥhDTUv? X?8M h[^T-"ߓ+WBР[o4*t -э=L̖Wi-0{./\9`uWpTj1<5W_KU(GeZsY,tdA΋*cUdC9|,RaטKdbϛ(s#0w%l)\^s-08R2639}#1q Aш`jA  ihf'\-}K ]ŷl;lp ^Klv:Ņ'qE_ !?X8X.m31^#p0 n>xjfFYbxpG~oaDDy'B|*x1AɨҊ3%#=M2B)aK CAn))̎`\>dpҖ`GGJ $҉HGdBm3 vjQc)ZeQ^% j=k bRQE]n hUiZ"NiUZXqiʪa}Nc,K5Y!4ăTMCJ[U%˺͛#tvD[JU?& =cD+#`͜Pl>VC:maa jK@ؙkf0mLZJ&-'$FaSnJ"#ŷPBوtɀJqC-)ƥ6QpJ-).W<"2a3')1Wr B0}E4XjqXFlȀcH/z|&zYb^.Eؓ ]Nt#ݡ L&}]DnX2O!,7; Vg4"NnCDHEd3w aoKnhFRץlL͋2݈)UQ6b .teĒUVmi)§U3$'/y<{ .EKDU6! +Lp{T*)h4Hk>U*NE/U:S y8N \ͲXS8"VLipOqJ{xbf%?wD3i2im;Q@ ZiXICHR MG5xGe=.u"c5;v<%С&Ef6}^CQ&IA qfj 4ɍeEcUa-J:(Ln0 ч1ttK|V"!pO֎|hM2.NEݱ L՝˨=|yJr>9"7g*Sq1Wx:D|ot^443 )+H>K#zp abߝN|")O*}B\ j8g<%W3kN!I1x8Gk 3vt`GwzrYRH>1%-ԐmJ($?:ik%dt(Ƭ&QJH"yթZ ?$\ZnŁٯXxblV"mj,0Dk yZx)EqƔzkDelU)NsO>J 6q`UPxc"CA~?7^ Y?;u7OJA\VjTÕUB,=9/q; ; JAګ¼y"-,ңf  ,w$Q?U3{' Zs4Nh|#%o4،QlL ?e-`Sis>)냿3WqZ/ uSF)Aedy_䕐JBNOL)5~X0-RY64"b{~b~I^KO$3?cgrǫ&.q}峷U`qJ#!g%'E:D~0_]`iQ]kn͗,u͙,B%$`#+ӝa8Ż"6=ËE#cWy©:zV .XQ4!w#NJ 5~>1V{Y]Q+6iS.ևJ;RVbgY]Nh&u8@jLBӌC8eB㠓/ږ?g*YIOSRdMl`XI3f ٙuL;eƬ:ox[cf쬶 D)L L#C"F_4f ?l dq =҃IO`Β83=[bO#6Ƅge2{i޻hvB`*\g@rϛK>g6^O$"v@ )qO NBĩ$WX3Aovlg镋#^m Sa74 U#'_mN w)Nw*]//c:c^Z@J@JtR2@pR;BNv;ֽhdMdla+Ig3:WpFzY>8#T8a[/\qxexZdx U3<i'D2 p>Ûx s1A6):@p)u/:<_d 3o|g]FrY;Zz<1w7@^{vQ=;Q<)Q{ \{vVM-A+zM؛&> wYyGR?X70oKgzиu OQ$"E_Lwe֋?FO,AxSk: ~C ]Hikow`;ʘAb7XA^jR Kbݷ~Ck؟"Krc\[[U,r R=\XԻ䆰tLbac endstream endobj 571 0 obj <> stream xc``t endstream endobj 572 0 obj <> stream xc` 8Wb@{``"7Hh/lԁ?#; o?bi w $%%8$nlVf/Bs N10(# b` 3t@1ފ1 endstream endobj 573 0 obj <>/F 4/Dest[ 108 0 R/XYZ 125 256 0] >> endobj 574 0 obj <>/F 4/Dest[ 108 0 R/XYZ 125 256 0] >> endobj 575 0 obj <> stream x=koȑ ?ȇ V4f d&o^HDюFG7MghYe5$]Eτq5tuLSvX?vg/ވ)+]t OJ[XJYt @o_}ì\^t?>4!yNd6/G**VZĺ)EavȌ(TvyzvԘA>ҺR49wĘeJM۔ {;?ҳ̅㯳~jZMPRJkYG 7|:f@uf^L"3e]#{YUJkc OV~u,Vn'5],^7Yp?Mx w((YE1쟂TuP<.#hQ}p^9P0O"↖t@cf fk8J;u\Wr/X~ozSPY"X?7pMoYݤD)L Wv EW}EjV|7η7[ >ݖ*lhL~?7a|n~/hI;:EH{|w@y5c}Ti.W`3,t|h!3c)jZEnmS:žH3؋̓JI`щR`4n̶緹hӀmi8d*U o{zo : 5iNGF7 #58wl]1|AiH0 =z# %"Td/? ny@ La BE=mz pJqKEJn"ۇ:j7@z]ЩoԈE(>Z#'x5tr&+(Yv,:0' Ʌ&&`MXyDaPnZXv)yeBm(o5([BSռAqBבY[-qbabϣbL3d^hiTMj,f$JqqܮI-XXd.`T}tYuGǥJWd`SXv6'̝,Ii. \SX,.CέI1|&MoL~ bEH#LXE$|ciQ&R+' bm#EWmAW.J`ʺX'8I;ޘ#*6yZ'X:f`~zi!NaO0CʻJO?|rN :0>juqr|VC@(szL OD'@'n.0ߩg75?A(h[iow3cU`^)䂈.lC ’swZ 1Eu 81X!I‚zKfhxI^hǏJYׂ;_r RCSxYjR}Cf|ѩ-W{1s:"RLT0 ﹖?Yzzb+]hw*T& 'Ssœ]_`]̛tIOAE/zH291`a=_xIrњC^|znFJwpk'ʔu7[u dK&cqӔ]z 6E>UD%GhL.ⰳ) ITgc L-d!z۵`oa tQ\!|7S En۶ԋ|!9LaB%)"R.;^ 9#e6[,$ X~ J'%W4i/' P?xRm}Ь4ކ'9OXLol0$"8wxCWĎBd…BڼHt#ɨiӱݏHoNnLaɸ[]ԉYa_K:<4g'zb5>Lpޒ_\72%CbMp4E O4 Nmh"xjOO-NadB|Wecáf"?lwUW҇\ե/XFvu*@ g18p]ަ|ZQ\E-{%؅@5퟊TQk8~ۣs {\8@g mʦ%ߡMa*zǁ>]] T/NtTm/ˮ5@k_ʶj*1m6z*\x7V z.I̠%v0(7} RN/W.uo$Rckϸ Vcq]<1q?[qf@6[y3$=o$HK:o1lSP9Gmrzć>SLLM†DNy-abC<9&X%@klԝ61c !՟UzL2SV&!*myWTx -B55V!TL`GjGڷ]SkZPkze*zר*zUBljL-Y*&o"o zu^iaۮQ(795Vxڄ$YrSWc hlҷ6Mb&Wik겷l&оtwJ9>F4e9nxN=_RoQx Sb~l^?/CPfuXJPs^ۉa[W<'ob',%f].^+(TdxLVa13%+|maF/ "ju0.BH>c* ߇- o.I jϙ!pG4˶:A )rDcW*B6x {QԋrC Q 4 %Sn;57ծXYhySzo%~i$YDVH¦}J%}`smfĞ*P_{fu2{#ލŋi>w7i=د܁L')OxZumr}9s>~A5V%5WY'+zu:NCkR4)dg5bɐOszS[YbN&ʿ դe+\zZ$CL=YH?x6V3ӞzmZ-t#'q_ q Wm)G&p5ي J]Ooc=;;^Sq=+3:`]nhrFwTOG 0T`Fy ~y*{u+OIH3iɍ!h9')BfyF`-Va w>#XT%1b!!ؾʼZkW#.UJuRz{M$֋VP7AzE`ѾhOW~ ,~K21>$$2cO^ffߴP_,Hj*@j}^4 Ue(kjpiXČҨ`L]jY:}/Nx Lsoa)hFS=z ?Up7zS̎P8im+8D9V= >DJLzΨuo[ݵ^Ӻ JJ Q>-;۞]L~ֿ:\r5mMAZ=}!0)3LGHdQNɿpR0"mk%i߼^#FM\x4\ 6G_gQN&Y/t!܈,ѭ2֕xHJ/àFu~+݂n$?wO?<=&<ƥ!LŐ]Xw(up߅r牻IOۈ3(s{~]힄3~ jZP 0M9!O6 ]Ͼk`Ln8Qԥ_v&lpt/x&l6`[:(K;N}8WHF~o3&KlH'З})R5w4Kz2p\ĩ,d;=[0JVbA!Y#sAk (_tu~?S> ⷛdr}R̮(W!hf`_FlQkmGvN%-K(3t~Jx(1n7ș"6<уu9C)FKOjoD7mwMutup/%" fGoD 떠!gǹJa7ΐ C R҄X!S`h !})C#T~kG9F#7؏i`K1BqOu(n  m{"JUx5#=c#؆a#̔KSx: -L?C8EtNWI+f]i#3G~͌4bTcZ+CTM >%9}ؗ8^^07-MUxo"#ϩ BSu92UEUJ[fǘMѸQdBRSSdSU?ZihmY"K>V[J]h%p,D2zIda{NALMfH %I2d: ɼHuzLu3&$P W!;owQ%~ͿJ#PY'5_1OJH Re2H :6d1c|JI b]Psl6"tMP=w!_OgงٯC@E)ߘ&"=(" թѩhc;"Eoz^K[CD4 x ;7Ar'v؏ߌ9l"j3Ԁ%Zi" j_GɮN7 bͿttO!C \+]H]z&~ښs uN9ǰ q,;.wޥ8ܟjuґtu@}[\)lhQIX}ўk/}|Q~[~Rѷ8 tCe.Yxjk= endstream endobj 576 0 obj <> stream x=k ?/Rj7_1=.sby`όwf9?Vh=FTXjY"X/{P 5uj11vb&h'Go?z]go/K^wr&G#w⟳y~[茐+hƙIlLޞA(nǎ*wek`tOR GyEkR{F)U$M~n c4LK=c~^, "Ӌl n_rrK.h7 OakuS>äƫD7 u`OBG?;!~\'~E.>~>W1Xg'K G&?=YB\+'W';S+Lp耩Wz LㅚWơ#I@OO{ew@`*66^GK?I@e ٍC{$8Cbܼn ͂П׋j~'aK -r-+廅6eZok_oDvJCmH۾k$NF4f+Z71o<_ Q/&PciL؎mk[NmsQ|Kھ ~k)V[*ew#ҫgnLM`%|a cAh2KOs b-ڂAv"Q^OurmƦqE(ɨ Dk@NwbhAXhf/7Hlݬ t:hqiD%Z3aC@&%XHyLʿR͌ec0.NOa'?Y TN䣟sGP|Uǰ$7v Qʘ*!Zu HH%!SI6KQt| O6Vd-s~[(P(TNIsBF셤wЊu#" \Fp/ (r~֬F?F?w"&*-IS /UTq3NqDQۋ3nQ^K1b0Zp@a9bBrs]_;:>4[z(dqgHqq׊jdu Ե('fSZ!X]fs6$cX,86[Pa ڑ/c)_ cl4oAz. _'cD+3X1(Bn*Y$ȫOY]t ME x;ɁKPe >>Vג5QpZJDn}IyZV %aŅv^zoHCWݺֺn?.bNl> GoP9S̵0xٹaʔ> %A|;P x!&4w kZ#߂r߄/h(7\vKmz 0_]m` pw2:(!Ց Jwns7sj~ONܙč}t~|QoYHanN򼤴$f3o=D]L+iZ6pT}2&ιx fU 0 @$Y:0<ٞ8Ƈt**f^_ewhHh6uciM\RtT:/|wsHaӵ0C砙_ܷ.'N桸v;kt2MA;]()"(@w-ɠHtV:2陨{d41{1=?z#qayK.< Ό^1Wih[0뫌;qvc4*AK!=ԴE(FsUM(T#ana9.Y$̼jmW )U, Ȧx^K\r.o2d ^;c/ jrP SuA^#l +,o#ܹ./;VW՝b[eJ/ڐ&HwaGuYMG C'zm$a `&vl|>_Mq\a}`&$u +kA@F$m 0m؛+9%OBhI n{] -bR5 )Sy([ԟ`qFv8솰!2q'puؼŰ#Hea) #t2Bg j%k]ώ1թ$ UdI{yΜc'B,,8ٙh\bҴQ.l]uIToK'zxPs,76O6XLLo?ApbA+\Z:`$nҲV^0a+W_qQiW-luփw$k a5C0{=(#qvN&'ڝVfʬu =:G9L3W&Z˚K&|q1ojwIv-4 T.%&-e3-J0v)6ԁpAjDveb}@앰pY:d}Yԁ@!*k( z=@XGpTpЈ^i+M јzp3aJ Yۆs(Vљ:Ucp4+aۍWLk;sr5gS%'ʡkxbDd\ۓ\v^u6`UE N D S8LgzBQJcU}dd^z;QnJhұC c]%Pn=Dk43é'GZSΛ`zH8V s'])6WM`t*lM܂e3biC[J [Wa]VD@#Lkw_ٻ*Nm;"%Qh20p&hDC)#qwsJV:JwyNoVcrDwtj#'J+^2^ǴM&{BPDǙ *KQs(oİnȽfDv"w坧BxY0mGQAfWnpٝiz2W4E]"LʺAnpI~W_fc-lm=(ល<<,'>tpe(Ah9ϴIɚ:CTQꂆfA5 5Z 85KЈeo!}fL1[ٹxx 9ր8^TWv>y>s^`57iEpʑZrD0}w8 ᴙ(Qvc07.Jʵx\_k(;Z9$Pc37\^3UwarʬC`+)&,QD!&w9V=2j٣Nrxέҫcٝ~=؂FcߏȹCscԋ8T%&଄PChv` 3ޕ Ƹs9^YٺBD|О??k\ 3`/ňv27*0)}ц -YY^/B[KDѽBĔt1h,3S0@rȜ>3^VH6_LecssIͽF>W(^Lc~9 imdLG߄ssN=µ#an¹ey3ɠ=" pdRX)fqU:s&<-v:1{v{ ΟgFH Y\'Q&XvBk$Xi|2>VċnB5Lׂ݅14t:@~zD!{0 5=eR~Fi>݁јm{rQy znԂp8<4d,*CrE|uZ>DŽjڢDd' GGVGyZ*2h9fzG'1švO&LE=cg{ǀ0DŽ neC3^S gV1&bc~vB:H"uv[{)TIu i/OD4I\2C> RBfn)iw.2@U$Z䄍YRNݲ΀fkW5pjaYE5Lۭ%Zg$7 $h @^!T^x!7˧2*zKg>!tTbOcdm9Anm9An[m>An/\NN<:jB*% -B'pvqr89UOv dć\T0\@*`N7@,'B`to8JPjK 7@R$;SݙqBIpFyO۴;Pˮ;]Rޱa$fG`s{G6k&aepx;aaJ=BG_.;\kl?P[Dk&yWG`?)qu7!7mHD)=Y],fq/*-5;Z]ՂN1QꢒdTu<+Gכof6,Z|U]p]%W;^E46kqb\1! 㨙pej<$m`L^ϧZC;٤0jQ((I kn)sb^1$.nXd7Kڞݜ[eQi;y7QVR?avF~bۀb\]݂)oZz28w;;!^PSe|G2W' F> stream x=ks6]3C HRJlVq6}we߇4zZ3hN_@$AR#e*4C6FЯ/_L:) 6EIMv/dŷo_/*$oQ*1UIYi{"K/_[$IA_u<&5j6'HH8vTUZY2^<[]lHʦ 57(_}5c+}dv9e?iU&FwS; UsftT!"di Tދ2{qaJ$m7o*.N _K؁>RU=,O,A9HzuG,fHz0ySeZȺ$59pa/`vt0w ͮƽM/Q/#CYj3 PVτ9֨b>,Da[N8Zd86$u$*K >Ӗ"# 4ȢEUx 5wxljl* 4dؒ9vyBʦ2.(Y+cXOF T{~\!jj6I P\m H\Qh61Zqa.(a_P4l{ ,8o8+liN$W5Yev"hSsQ9.GA+ >|'&`S:EB~Xt"&:ǀ.7>mY1[UO.Xn/v$CQ MT]V{Q,#N - )7kGvV:mMnF@yxAQ5HDxB~,f-$  - M~w_PXChsPYt&m)+t`o2|hD ŦgS␔ή!u-[3E<}AMqͺiyCO7qD̤e 9[1,/ ,m-Ѽ$;b@^$@C6o_& QNuJ_FĎEd.a8FL @Q:n?-kd/Ɓ2Q `A0޸̳[J #d2[@/Ǧ`ӟbV3E yqU3J!^$. 2w7 HXonyrogF '!Gz%G';SgWhu@_%,GɬM`OtV8E.`)&@PB-AY?URl0~CEZ8 s?ߘe%h5q5YrP(gCF *RnxN0! 4p Yk ntrOR}'S02?fEN*SGx`TkhXV)y*`WUb!(Th^Mw63,*–iV\&+*l7Htƅ5'aXs> _+`T<7)TQ_D`yZP[ȥkaC rS rLPeح!`$4L jdž"}?,I+-&v'*5>(8&*"43:{n~و`y/;4p"~rLc}hUD&RgMo@o`;>@L L.Ϊ^ }#|!=O[W"sMqT]u LӼ8ceotAZ>Un2HmI'Iߥ )bP30pnM6F";M 2X?Lt`_3ѵ}!BIl+_ 95U5:PPQt ս>Ub, C$Z\!?Ѯƭ},:\p_T&JJL& }]S CGĴ:qOG> K12VLhΟ\Tf 7ҋ^II2$ioKQ{Po˃X7 yϏRu) K&\I+ljžf_O7?a " ~0)WwciQh=fj:ܲ$ p; "Hpa:\S21A UvVLTcMMVfaQd'Ɣmvr|z2mΔ;r}%zI=>(!ț3ZW1>S&#9oa`:7 gOAotZ7uL vjٿ\ Ǿ4bPrG;ʈ?t44p0|6ò 3r:&-Q?{2,8085a, Y$挱kX5ic y\Ѳýϕh0p%)7f 2} YS0w-. - T S@`o>-UXlp Lk=;0K'RI{*8jFB^+Ww:]h]&9 Y_RoƋ:x^ܣ c=sYIz.VC9=,N,ܷ~Ӳ$J|"P 9mTG7HV4!_Gm{imubڮmĹyFu1#.3]]>ןU] 4-6w+NK+&V^e8C"ZL4VrkGsUk i~W<6\i}V7(FӎBcc}4qNZMi4 DdQ?aixKOB{PUh"i+РpKJ EW<Վ{ѭc52 c5ѮƝ w Pkο90yǜmY2@[&xqȩ*#n\Cuiބ2Ш2Ȅ2Yn "jDChJC#h([vXvOʣ Gar¸J2)@*)@*9ոJ*JK䡄Ο1i;V=7%*nʩhz]k>#hԖ}53Hf2Шf2Ȅf2Y; tUcڊCihM0! uƱẉ0V0ƨj VK1@5xwQD@l)fMqU0܄U*kU{QơنpP2ھqTƭ1Tl/b(JuJB}TS=+n*p lvw}M왎c-pOkmCW|Ĉ.m$e?tGus[Uh1>ʪm~OIw@]_ch;ҭuHQ*R{mi* y`c{"Un@:)/#H ; /@tئ}huP[ӓ+qr5]ȗ0Tr!cOqq4CWԏ~zN!t2'(N թ¾5 B}z8AqD_zjZ~B#ָ<̢MٌN Hv ͻ19=YG̻ˉLw޵LIf4Ļ; U α//QV۳3;b댪j{t#}CPu-@3ڪ_ǁ4e,hS#\Gx}?c*yв p C~D`t\Y۹FkumBh$hےlEt6 ]o5akzl~c84kaܓ%E!Z9^ѧ'freu#%77Rў5Xւm^…vUVΑÕoy-_Vy_Ʌ Ʌ+la4imĥ5%:`X)fy?b`fum#@?i<)!D8aHSDrM*;7Fv&h ڝ2Ut՜NL}tAM.*R+t*ES䛤-.tOtow`R})oaV3}?G8ᤏf3Qu"wDF5o~fϙvڳa/Ks:Rl}]Hɵ]`h\XcQh4X־FaJVj% c{yָp~Nè׼@L>'V(Md5'AD:&`튀h[yp Acjޏx1DdѪRdIkޏ6# fvL辎zMz>-\L}ҧKDW kAԵ}>ҝ?9T1L}أ~EooUIdAރ,,z?j¸ÞItwpo)rq>̙"R@, 1QҾQ 𯏛E x.k:5d9@>Z<ӲՈ|@zc{0-DS @NAG5$6 Ì~CuQ=Ulmd/R;KP-p܎%wFC0, gH endstream endobj 578 0 obj <> stream x][s6~wuf#$TUIe/IE=IeOfo7 h*L%GkOϟXs5SW}WCMuٗ?j[}2U Vvjo?kޜUϾx']UzoTWUyƩMU76c図QMTlv+~svԕm=[Yʾ^~GבrkߥX~ǯ11]3ˆ }}:gqjoק쫧߶$՟2)Y:tT dD9oP7˧V Vh㬗Vð_Mc =|/_mbG`r/g?@i|N9hG≵em=cfM_ٹGPX]B)s{z^We64åz/_h$̼aorjXF߬Q3,0gf[W444 FUmJzXqb D2~sݩm~?O#>9{p:* ]ҭisM @BZGK<Ʌ0Ч3jtB̴M}֮`0q5}s㧏΄KoB#ш[ ķ#4Qއd2`wY^0Ð ߙ.)J,cf鮈b<>| (f6caYsh!^ɵAbGGezs)A!y.4oߊ94, f(6(ҵƭwxQ˅ߑG7q[Up 4gEĚ`~ft#V78ԽQ }я hx+\x>_ k! eEٮ=W³\bqG ;85͸jeݱV Ĕ$3;1ft(0nF`ŗlGL 8WI[wQ6O!l٭ifgzd ꉣ&⍪TOEuC)zPN`4 ?,WĚ`t:iI+^)bLXe" )n~W~ k"8vՇ'tű<]*05;ֈxQ4*bMroȤM4M+n04J2iFNܝ5;bs2 rvÌ`nPhbBy.*4jӑUh 4Ch1jB!vt\%ӥ r5C*ϱ4/>,!Z!Ҵ_n^r]] D{5!L%=C&%jnۺʎDbD~Ģp*/\T '1pBnv]dѠ߲ť:fkaod'cy`IG҃ǹ zzv}Fl+v*["zn(˺%ȷgEbtz@߇'WY=DNK;67KGtm=hZaPA_LH vyLQo2ћ63&ףYiBdc>lAS)kohq| 7CKtfbi8/[T -MMYSS4K'C#\a);@?Y@&],MĪٽg 1[Rͨ_.UFmGuPH{23Nc.56 'ҧWl Wrvn\=5YgV7\ +݌RʾV;v狰{&"Xgvg' y g9L:EuVoպ)^vj (k,wHΈR1Cunt'wƒ&펦gbh>6k↝CK{dr)7M6^3>asfLDv*#ckL`&Lw(sIp?I66mrf;}Z~ԎG;`vm"lONoD(I\OM7fo ةnӤq@(`J)Rpqۿ,&dL4NY"8D{`:tiԦ#i4KSNSy iԪөj|`ШHrVp=y>踙'fܫJ סޞNkPEcJi/WDawdS.OYLj7S` xG_,ϒ'I{3)]o" >xA]r! ]o 8 M愮uDq<'#ƢcXf֠gxv|CMg¥S =VxeN:2oآ·'9FpRH/;@Lb/GĤSY 1t;tӚ#ٌNɰSeb4ᴩZh% MHOp?R>07QhΠdFwlM5a]ݶ9AbY'9Ab ƕװsY\O6&vx}*y+'{$vF#. \-{Ӗ7-IԵG=`z:Î㟣?0'6g,r K]0=QmU ]!Wwqmk,&%16& mXԑB.q6.U&[)d*,cK$SK]Bm~玓m&&DH TӰTfFguL%=30)MbV|e+6mâ6نEK۰M- .Qy?ǖ*ϱ1VsAfߒa_٨}\x1Eey<9L* {o0!U#/O6Aʃ>lYٖS>F?m} 1 6Đ,aQMv |E!qkF^vsY˖0u?^P}D|qZc~I7+I7˩+eܕ;|W2\+ɛvd*RdԬ+}ő[Fw*Ѧg"$̈kY^9||674-ǂ 2<<y_ ~)=v~!.Lr<wŃr2 _3&yg9L[{lj[e}_G,rjm:4ũmWԖSVj'\ ,U9!;SS6Kz010-:[cPNHmIψäu FHj={mב|gjWr_oN~WreQ] >߄>=|1TN}BH|!fmWr7`JwFheZ3JäJպi<6o(l|0lԇD4a#}F̥޴#a#HYO6򈁤}Ka#HꝛeA{ƚb f~M{7}=> %ƇOYT5 h9ÿȚzK8OQ=Sٳ>&nQF5Qum_SxLzVk L+XBXD5q1`{+p² gf&0!ZdbL9˿NKǿݗa9ſDK/;,/ gw^V'964lM`YL6Ӝ]j_xf E2 Tqr3Rhp0e1;'wǒ&Zӧ> _t0ϥsDm:2>Ҕ><OԪN'y"M̂kTmw׊p;vijZ#KzƎ0c^&W̮I%r+ 5+,F%rlrN:} +T͜rRZŻaAbskѕ=*/`Ri=w8%sxIp8I9lx-mV~ͪȚLiu^v{/0Qsi֣p[pP\Ae5xTe'ɥ4G8޹|&ycRi:$FP53XڂRVj9_F YVyŗwUKzfWäT3áq.t-*X\%Fk*,Mz[TҤDZ/" b\Uѻ9X?䰤g&&n1J`ws\OJA?U~jA?UXO-駪\O?ãow7MOg=Mۋ;||jy1":;?n*s~D ~j$@ ˜C vǵo?5V;9zwB+b /s]ÓQ˱i9^9߾*wg2bދJ$gJ/-L\t_np׊?Va+Ҙc0-G/`0Խ v.3 HQ%#Pwsou _ Z/,%#)L j \'Pw(;NC9)vy U\ endstream endobj 579 0 obj <> stream x][o7~7py9guM/@/I"Ly4l t<'뷊bE=f,W$XU$JƦUhbƶv45G5Ggv/ї@ǏQT=v ]3aQv'-{qqOba56]llЍiLRq5\S" ~-wlٵׇσoWcK~H+|<"GUkb:i6Ӎ}ѶR*5tm >+[9\io>dvONOLQZr_0p@N;5fe on__Mǝ#FNb`&e+:mmOMN-k'?輒8씀}ǥStj !UWaC}(NL0"hjU'3M;`I*K}APʼnAA/7(4E7ƖO\Li>~n&fžYHNؗ{ijCmgOw˰|`Jm_£xy`& ͦ ^Vba*뱰¨Ǝ8#.N;Zh}+{3ѫMp=֝ĕŪ1y-7ݷ^sT }u x  5{!ZJfBkvBd 7nHFrFjʵ/v Ȱa ݰ0E0*b򘿘=gXIV}O~z z)#N&elj=Fa 4\,̪uD; g@7Q E;B Yxwz_o,2&{wHf\Ŋ@OͰjƋ#ԊC*:H;FmR%Gu%M@v"nZiR};>yyYT X|m)!N2pΌ0ψ-ƥ`+iNy?>]gy 6>}[Yp[=7E]#7HIÎY95OKLvN0P8#Yh.73L Q]BѵI$kiN]Cd4- ,F.u`yz&HaM].ܸ|& P8 & Ī+?噹 pVk ݴq.XB%Y[rIHiIH K$7KˆҒ+^ExvoU: 759I3K;7/]_ͳ,dmM51ިQ0Qꭵi15033d 1+m?Ͽ}CǏnoR +:]ֱx3ܮA$i$xAMFE Bz]+\&RG=;'=Id =Y'l7]\Wvni jW$5,d@J5Z-K|.9H,Q :}譁"4-SѠpG=eEJujd*LJg#4%eL&|2gynZwxi9ᴘKw[/'wƻV㑵x,;1.ĘnSe40DPtIH8{I(dD+uGa,3n= cGן $`f]qK̞'|e67 СJ6!{Y_ ڎ}h)bs!.~ӿX9`Z9,a?W"n.7ns~AG޿߈4GAuud_TO̢E _߾Nַ8/U|*=vQ `R?֮g_v?0ͺCZODr'v &{cpFW);  KÀ Ű66pMOFi [#9'Ow_c23k ~hGV&/k>;|w0~o+>6{w1T >VWmΌY㻢Xp57Թz\!g+w J PZwGӛ{< =GF\9)@54۵_bCrzF١htQtwlgێ[ :T'2ϸd,/{4]5sP%ֱw[軹T[M~ ꉹ@+OO>*Q GQqqQ({|z{~gSf:m8SjUJ¼JM0#"}z"m)MhaD*t(6e{R\KraŀWOoun`fTæaWI~D|yQCڰQy .fAGz4 mӑ 5ss&N'B!gG}uiuf+PѮ53*mi P j˝U^SbTJ ,;~IF呝ATۃd}}loeyD+=bZ$[vC=j{{G!KFwB[D(*}RSd]03B_OŝTػ:R0;G1.~pұ.2m]u~VɼW=6(GGi; /E\yzJ'GCCrvDXm]ois7H>-a8=;qUvᓳ>λu ΅+pQ&C".FfhiA3Y搡ߖ6%e[`w?݋/^<բPg7gNi^KhZ3 |Š~=z^j~`sdDžLʅ.wpڇ&CVi*{?YL< $lGbK oPBxe8gN HM!]6\nb2~t+qotYg*,#luB$8P)L,$).AƧdbS{x__®|ZTmb+ZKTfr*~@j EkfF)l_$ۊ\Bؑ47xoٍ͟_#& ;[ ? 3@&s)68_Y#9"NG(J%m a)/J]_@XH [A<30(s WڨEL'~r0Wˏq^>B$a;Njc.ψ#px$G ;s-+|2 vC2K&% ,%)' ^mM&L` /k_ \!b̧K-`{@ $Yr94xz/y;v؛,˃So8Z,&|>:Ǜj_e˧:? zrYjޣPu{uXg[2zi,XD~;> ̠6.\LvpL4eU4vfY6M-QB ]UqۂS zJs]q֩1ŖԸ^L.a \\%;{4H빦Ah|c\KLmP]Y~bs~Ԅ9afVy33fDfM戰rqjJYȽ\?"H > th~UK/\+wR ȏ';K9?YL<`qfF<4;J)Hqh(x-x*uX)UZum[o`뮑ֻHn"Lw*nW<9L0a/eؒWtu tbKYUOO0*}w~b|} 'wh*hi*Y2&sZ_úwK2꒰o)7|YLl7}ij`jH|V^, JU %=in񞘟B'xOx@%PUĵ2?ӄ[ƹ<350c5zg[Ɗhgh.0 l 7_+AMb˹0:'$S 4g餻JSYܐJ6g,n]4@Dӓl:<+?OIgW:GNHڠiЬ${*?`]ҔKuG̬ xᴣ39;%ck\ю&a_9yNyN>) sۜh׶9,n=T' sJ3^s*$>ω<'mn^GRtJO(sy#0Glp^^D.# +"ѭټWߙ֭k>=Z鶯 ]/ c߯gl?_w{cɑfyZՊwq+ 1w}c@m%Zb6jÊ;ǕL\)܁)tCW;ޖr޽e11?co+ԿmL#仚CA;>wtdrGX$xsͭ6An=1G 5$ QCJU5 %jinQØB0֨aa-D Qo%J!ayg8ga[>,/qߛ/5_|ݚ%Vא=pº:3 -FY ![vi~fmO}직K+xn $4i?kⷮU _oЫ@7󝏰_wy|VתVݗe؄MZ mr.dۤl?|'IM.-pIT%e*V-YkUD)w |+ #a;VRoVv^ 鬐F~n\~9L<&47"_?R]yBzǫzWubK^(IXcX?abdS|ZB[VN-fMN5+^3kN1 5:$ЇKS[N3+w~z͵ 3 6*/Ψtkwժ0_Q:ze}#麰 #.tiz ^)U:eECeJAW9 *ML+^9xOx%~^ɲ7N [\1& f¦5}-e[[ⱄ2K:c)a1O야.K2/7~cfK![38ޛPlɛDFҀ4RTZGl8ʅQ)qR]%Ri[//[+n%Q&wLW K7'o\o^~{3 $rqԌݼ@ǜ]+6BTmQ:iYS@XmingM1?W[Ϛǹ[pouZ`w,}I + `xl_1ņg0}3~_Av^H, Ww$QrajX??`m| endstream endobj 580 0 obj <> stream xZ+zێq%D5@f(}t"[N_$SW6ž"nMU$y߻řOu5ՓBMnOazf *@ҫ/$S7# CGpeRKja%Ia/(7@ia&C޾Ai4U5(6ʪ`#jaÂ1vqKFNp۬hQO:]:Z 1gs/ mtmx@ǁ_5L:b Xgy+NjSMVUxR氁{$`pkB:X Cf67! 3BBmjڒ1+0=Acs#gҬb1 p|a4x 6k5+KjY*[%(edQPT ;E5(+u,i].lĎHJDCc^eT+bnqFD>ұutpyxWV  {/)R3s !ql荃BٙI_'( OܾE*?v=IEjBCgBhJpLqUW~Ft|U1Fg[iIA-dUG@u:la0Dme'եgB!,/Te⒟ Ցb{.z_h FY4䑁6C.*^8'{A|rUVQ!&ic,'6abSaZv`9߭7Zsohr.vj7tT:<0.ʶ.bBإӗn=Hq.ڊR`L)1pKUa2Wwm T4^oH`#LWX==us \Ҁ SkޓK;xc5\usU!MLM+Hm`37IPB?j֊0!!t)6 T3!< q1"`3̼BH?ċ TQRZ=%FE~<9'xD*Ȑ 1Y/K.<¬:2tM87d7n\`f3(NؠǿެH (KLAb\:wq:NQM^Q5 ܙ(HOۣ(XB,#57zC5J9nȹ^RQr>y+N cyu#n7AX'9"%I}HD].q 0unV{$5T{ {nM󡏪 YsxbrG/x}1bYѐk+ɋ_Q kݛz(e/sC2bA?el)U _HLU̡]\R55G S67+d J.TþR"p %33qNA5 E:Kl؂gUl~xtŁD&m K1㹈t FUiO`QHv>=dWf_z}y=fbeFɨ5AQh PF-B)Wނ%Bhmc"NRGL7ua"%;-8it%"p=|F.Q\ޤRSΤ!ΎD-,RwNy+]Ri@[iU[HdN6cWzKok&% e`Ja؃ʖFs-`ri9'1?sduSCk*=[qGY\ Ed1QLh{YlV`|ugKHwT!bgr_#s~[P#%.z3^ n+`sE}GϢU>K2%wgy@qES)òZ#i u`Y&Fr $, X$Xvի}7$.8gqa+ Ȥ<੢m\ϒj6#4|& U q HhY?vLmK2풂S!FØA6DVI3J挾$fe%X61,C>N`+e1nU4 $uYfܲX& fҳT/YWU|" %XY/ATF|Kb(DIY(Jq[NDc˗>,_1 xIPFW0ц+ E kdwA8T V>ĪL P{(Ē{,A;ȯd {{~9mL/6 :->~.RzK1X"g/ (30Ů1w3FM3=7}{ M3tSeUwn ,~z(ʽo"ԘΝq4x>m/dETpM ׌ڢcXyh{ғ" L*RGbd;r`[Tzz274uDPK(ʜ "Y,mOA*߶dW3X9J9 нbY QtvzƷo PWs {4Yw5Hw'pH!i/(P- ܚr  ͪ5e!NY]!q褢o~gQ;p9P҅Yg'T̯ݷ3\.'Uzdt;Ƞ MP,Wf̽cmt];! pMz$Df۵ږYk 1?\l endstream endobj 581 0 obj <>/F 4/Dest[ 108 0 R/XYZ 125 256 0] >> endobj 582 0 obj <>/F 4/Dest[ 108 0 R/XYZ 125 256 0] >> endobj 583 0 obj <>/F 4/Dest[ 108 0 R/XYZ 125 256 0] >> endobj 584 0 obj <> stream x]m6nAiY|Ŭ1qevǍ'3=y㯪HJ$RYcqHf["d*HVJԦjU)^?ϟ~ًXՍ޽X%֕6ջOϟ5-Vw[`g?5UNicc*ݱXզjwVD4,نXm>wcF{C|s}[ g_Kmj9?\?s˼nFÌ%zZ3?]n_K?]ɟsn'M>b? >>ju@*< lcr1U|c/F+ 4-}U-ᯮ6wS`R#g#kɊG  akEjvoSXf^H6)/[}W $՘v85>nRԝ$ HOP늄2Yg0BfjZv쳨QJ]W0jKBZVp}f TQ ruOk&VOaiSR'Zk-gRG57kc]i9i\omVHr[v:9}V[?N&˦ZQH 6V2UN F1m"ڿ:]E/oDK^ʄ#&bHI@b EÕ;/[R\ d G,D)]κY|l?ݭ7bqtjwէެ7d2a7D)w_/*u[8XDlG&^or’)y)( x3#k[{?}y?9iYqw$0ao!8;ytK  !3!hz̍hq4~ %^I&r!uk6x4l$~Hx qb483;:VD8sPvb7d16k&T4 >Bw#Ilh^ίuJ8Œ=wMEu5qm l5+}ys4S]nܐ t 'o0œWLq9t|L)@[2Ga~K)6J+1+m#|V 5wH>pN岒Q⼛ϓE*5v-.X);`*S{^7)g az CA="̊L^ ]$h-¼%y(z\ys@۵ߠv{6ao?tIzCrzĒwQ+6iŲصt5R8f0Jfkljoѻl L5'A̞ x: Tva44 :}! wq4b^J q^LNĚMkTlhdL(iLXHhdyz[7g;am;$/ș\[}FsckOG}y&LtY+6|ttPXӓܗg&9G3iAƌ&9f/ iZb80L@Ę6~vp3Crߏ+7 f#j+ C4)M[3Llnk%tw .>mx0" L M*7PE]{M"I/%p6 Cy(4ShD1PtV/a( v54S=EX&&#Z/u+/MohڵVT[k!Z'v`~vKkM,j+M_Y79麁-u]Ѻ7]{joyY ߀"]dCER/>%E>0Z$\6qzQ398GDCnهn3 qw7hlIћd?dՒY@ڟa%(P,8@01&< `3v0h<*c .S#@`bh%{eҚ 4?:4B~[*,FRbz `홫f'ASӼt5+57>z~3Oč2pc 1 r/wɴ3oE,_aUX2\Y iZ$ T_l,jW4O8GQ$ЦbN :5aq!um.uGlp}Ts. LN㹲ZՉxr|oƔOCp1@{sӻ3li/񩩸(66a1ypsZ!w5{F \E8#RkGta 3C/,CxgԊ;3:$k'rzLW?N ! P[)&[kdyW*D?<ڵ%7|N8fZq*{/#y6J Gni+7\?=Fu?Ka no3v%'0pOoi"9D&5 jaD: sI[VOr0BދqhA=&߇7 ^LQV3'\P$5L6|]{6mEqϯaCD3R("B8Dm7b[Q.bn}{ t1rAZJJ bY"aP &{[s{~(.[;wHGYVŸxFءZ2$rj|*ywZRWf2Ξ~e2._HKi_+ w+zm=%wPiU&S;{br TYCbZ94V'B͐"wwz!M$a~954AzM-l݀(ty{<.Dz ։>_C[kb2'gpCT.\_(Rr"/Pz'FO` Ìq<YJ_ -Od^eYu"q z<&Gjoɷ M7TmhIoÊJ`b.j |i,19{Vx1L })?dL0vHMyG'+!4כJ ځ5z ˳qƉY9}_uʴjJY.㚥}cZ6CKb#@\fLҬ:AHy7X]9@"EE)F^w@H=@Ġ#8K ,NؿbC:MY-o$ /Cs r(O'e /N**B :ѾGFan_I/Pz{7!9 8 hu`DERE3E"x0zf4zL@=LY* !cw\高8ܼ4M[rQQXg^ZðVS.kxjY_} F  |P  X#p }ؤlM(҈;("6w^ twDovO̴ 6p5%Y1J$ stJx|D\c;\4E(`wݨgC;H6=/ e^zO8s[ #Z1:?b@ ؉˼+M$L +dM+ ?3!MlZPɣ{ \Na ']q=^]> S-1Admw}^97mg_/{,v(zy, %n±xh.b |} endstream endobj 585 0 obj <> endobj 586 0 obj [ 587 0 R] endobj 587 0 obj <> endobj 588 0 obj <> endobj 589 0 obj <> endobj 590 0 obj <> stream xc``t endstream endobj 591 0 obj <> stream xc` 8 bv``T { H(/b2j-+PC"%AdHH10JじaLB??120:e b]f` Rq `E P[ wCk20 endstream endobj 592 0 obj <> stream x]m6nA~^(-$;`, 3ݓ'^_)lח 6dXjy@H[Fm](Ӕ04u<|.<}hJAB7Ui ۶,^_?|P@Mqq~lQ,*^_A+y}Χdd!Đ=d6mDUT@ll7bcݔRNv|8ҝQ:=JS4gϟ鞭}FiRO4^}{*)+ 3^c)%~{4tZM%I+eY|cq^/.VHuC/LOvfʺqU)uU ~k ?駩HU|rzbw5lQ[rե%c-)t+J *W9bwԥL"{0])73ľ6쬞Z* '?`^0IgŶ"Z,3YOU0"jкeS 'F]5 Ii}xRTĉosԋ=\.ZѳIMTɖov3)Mز1g!u$gb7 `ٲβ~v[ 1z[_ *kxT7kjlf CUf9V 3<ٴE|h G^8] MbFmW^`Q%HŠPGZ Z4ou7fc*aZYwɲMIq\ю*NtYM߾q͓U3]tGvs(c0]n~=Z0yjӾ~^S4Ǩ7EӔAIڼzZ]f Gc<JA5`%A)vb9LJ sp?.E!h-zy"buK'+jimy@9ja㊈/|jyZJШnv ^(XRRQK<3(Àr=HJc2޺h>x2ިh7Հ`P !m}~ƲG875a04NY4!EJb&O`kWWbÔEnAA圥:,!n;aC0ui;S5c_, n(E|Ψ'QŴuuJdVCK:XV1aYmmǼ̊IaH] b;ZѾ'&NRu)~ŷFV6'9p<xv^j}EQ]?}m8#?^h\%(*^\^#nn_ yeUBHEY5K"+M-^;O&FX&ָt- ώ0R=7 b""}Gfw6hK61OyjESPWy )9NsRKGf&qYEf_;\MJA8cJa 5+2.uȈ/T;Gqn .0iޝsX-%n=ԃ$';JuM_h*". g ;xZ^:uuxD3-RYW]l>b AEjMMXMԴ5*Ğ2rKr }NP6n;^a<%!te+=kX{D[ux~8Niɶ7 6n| Ю X8@Ku@Jlx@׸kq&bn3V>U6>6[>YY p1q?c`<69i׸fږ7CVbv.LYxk%l')$`-lY+)aW2, 82\fHZ.4OډW2qNju ׽uהcѣrdkwwcn݀HZv%1C/1^@_n;96n=o s6u^f̚_FaB])-XM-P݀ 4zT".E}cjVRbrSLt>DS ]{ ]sk?4uWu֏>DDܺ*K0N߷VFl=mHDD*g !6TfX'-%Vk,*ѝW _RH޶@Ƕm4x CufK:66(c-4B{ipCՄ=i{ vhSV%Vt떷(>֔ L{oۈg>O 97YZɫX_8ۥZ$Nՠb\U1R/Șcbӧ*2k&jB޼Ihzs}t2є{-=ehj@EbG?g uۦ@Vy#E\`+%\mBWN6?&2O34k=u`PWSؐ៷A}_u-ЄÙ0s6w3ь\x>ea}cgNc3cь^Vh*+{ҶL4 9ra.r3rьRXsn0F2*@ n_U4'}ܱ.-ޑ z;[|6>AO xDWG_B[e?rsBkza!$?,v)ьT:VߦZ[J{3*tꑗOQtpasڹfTw};vK|trT;-Vx#u)#B>#<$7Dy mH|2,RWӚ+ޗ],XOIh~sW׏?904zC,h5l2HU;XxGq?A4:eiƳn F\q ~ӷ/z* +2ˏh1{F@/ee9Ms2G-JY,>#yGMf3,xk> 3<}Knqc&H9|~5"l)glA=ݷIpf!*f1|+}f0,Y^2cX)%^Pz20wH>M3>!aZ.;=:8JkZ+#d!rU9VuьUNt^+]e&X5:ܶ*xP_RN(\|4 H6bjr~R7Y\&%Dp$~%s]NjO`fh:;eVƛ5JĎFuGOd=Kl>~řˆa'$EZ&Χ.j;+қ>T1zLazYڔ=啠޻ ڷDavRtAvkNǪկU hj.d$ݠ\o%RfdGwWb\JSFHyŷ"&wu^:eLKlby%Rfv LvD (+0~NA6 endstream endobj 593 0 obj <> stream x\[s~w<,N$'ɞxkJ,mlRo_ 03(9Kh4Meܤ1rvL[d^趮I\%'>=VO>wϟNf;y^C|adDTBʵ&U3yw~OqcVR2~?VQ+Ϗ͹1V6*~wdβVRfʺ+0n6 3}W33}}lZTmp$sZY3h#|ח6HuAy/fGqf/Z '˥ǧnW嫓y-g'sQ7Xt_0p@Jvj䬪l3Z^rim%(tɠ}qB"ڥXpa||ᵪft0#:֕ g;e(W+|AUvTMj+.*Xh\_f*v5-> 5Wn6D('wf)os1rM.YIVLN8ٽ_d x6k 6r+/Q 9 :b䡴ZiaL62ڟQ-lDU+Ӻke)k[&(IlBd"Z*\ő;.5R J ۋ7v3e4bOIz:+;TLoE(F`a˄eObi$'w2uWE(q̢xU(_Xק)NbJ~T)Uѕ_Sɀ}L%:վ! W`p{@{zOlCǦ?B3lނCD77W%6|*:F*}Lm0p=iهZRP-祖6MVv\K{rz]O 'pWT)M^O'_xr?^fEd!pU'a?6,BKhLc`º~(hd0I-ZbR0C!oc;^FF\GܺġGBpXY+9)v9H|Ө#jԔ1ԻS䧳WX@ajK]b59^T]!Cd.,*&]>,4I- uqP^xb6wӏCh8]' D 7 u)(Hr~w @*Df<h{M~ k , ,>@Eg *cYrYJL@SfBZK$|qSS&kܦo'$rߑ 7(פ3mPukoξbVQĶ[A, k@x~7 brRRigŔ$5\REi*kgƋͧPw++ۓ+Q֓(Bzz«F >^LwL vM4['KmSv\?$֜~?>>Sw[-e4S2 Kf΢RV\ߐԺ7<deZC+B6 ChFKn$\i%ZѲKu VERI_JtA'hMnGծ:n`3''u1=L4lMAتIFP?a'S)2)O kqhȅq-Tf+%uaO^FM:ս]yeyv) v@0s$5_jȳ@XQTעdkq[=Ս$sc i0l]c-0"x-L-!VxjApF,Bu$_'Wv*0/ePC6 \0xO+ wlv=|(gȚ- Zs&NK1|W}٤yǑQ q@ٞ_;ƀ5.%6hl.@Dj&ei3 YШuujF\P8c/!ȈTwѭGPo?*>=xm.dD )l:+ ܟ8uC6%9S3"o2.dD; \nBWt!n ^lGr6֑PG㽥asޒ㽥P780-q8ϦUBޡ?:*LyW4 cq4kD8O.r̰a]~O4)*aoF7AI/L8bouV9cD/L]J!Du_[vmqMq/g돷[gF wGsF Ƹ~: :[HEzLJy 3šNb֠N-jlc)1CD'(z :T-67>M& ϰpÓR-6UCw=- }$H/bJK|5 gpE?бS%C_Ǭ"/!ZO'pb>!t{* 8]t1_2vw\:2Si;¦वw '=𙁃&ұ3ݐ9=F8 ˛oĎ&2Y5kU3G+yS352. |%_!93Tw_ƦgV_8b^j*]ǡ*Md֔Hsdʍo\hX1.?2Ȃ*n(MCq6M~m8Ë4*cۢoسzDAgnitZ6a&YY\΢'T$T$a&K CP'4)i1qAv8[lemqc͐mqs;T,K`N<W< Khƥd,Gg+aI\p}*BU[=LJMOi%No.=gY—![Ί$RL4UoѮC뀡7GʉU컪8kga"$xK_\ K\tʯ!$8duca6)`BzYHt4>]9%aksWFs<WOu]̇Tw65AF?]t,{;$jobjV8@:H($܏+G[>MvW6,~7oVL (i0?@ 79vkV"Jc$PoՃd r)iǾ\ 6\nT#hoFԅd4-ۛ)N@LaOD*~I H:N ”82F +CiŞĐذ]e0$6ƆlFcg |Oujc&@)Gg>(GRR$? HIAYF1El[(5eT`N YI70fs$af2[P\y<xɗ=bC< 4fyVc_8~p֑>R_i ,_h,_2#_&&Mt%oZܯX'bmX\L|cῙPl1_dS^RcU06v/Rm'ڇ<؋;ߖ}g(-;' nXco2 0T%E>Mn h@!Z3r;å.]-|]=ϬTNKj|'`of*6y\~_bD=d4#j&Ǿ=yGz;K -} 翧ϫ/#tS;B:#Ǜ#c+P xC{Dx-]:ۃPk?6: [/>hæ}g.jm mA]4m7V!*uE]fh7]{qڗ@z?m/_Tۓ}m,?Ÿ(:a#450`aBho֛W5V},@'BA#dx]Y Y].7/򠁊~Pw51AZ:R2n@6/~vWn.vG*ӧb>>Nn=9Yo-CR8!$ChS)wO[EBOisb(2܁g?|.)Ï]eF\&rQ*=kiAClr]eOx6CM9-+ϳR,]ϗ{<6ҰX;Hn|,9}n<ꩺ5iAfzd_6>ţ\qs҆5%#̵f㔀.{flEGWK\!yp؀o>>Phm% +D]O.j*C `dO) endstream endobj 594 0 obj <> stream x=k6 ?c""` x %]ۇ `ngljUIŇzs!wK,>Կ<}ld5ml.>}*O|铯̊D=t**ʮ,ǧOyɛU=} :_ʇT Ʀb.e_t=UUͻ՛ի#ى߬N=YJ)X6$,/./O=s ,;Yy:'xf]udgbk֬^uzv+$RJۺl)/Gs.[PX㴗LN֔m;?ٷUwk!¿nʥ߷tٴī^g8w`ٔSpYlmW\(_P.}[2H\+65}"qJړsƩ ^]!0EIY EtUDmU 5OUJ>steZ FSąf߫5`v-Vw G[3z?|{볖 $5}$Y_wv&$]>Kw~c]);weS(׸oWu]lpۛ6oPn} JvX$MZ 62V&"ۮqMի_׌>`ێ>կϤrhHG+cLl1n tZG@]״kY~ qƻ=򙐽Y; UՁhzҭ7eϭչέ *K&e~owq|f)vP#s%W.w7t(F@:Q7J#ӆrC}K= Т?h߯7"ZSp7w u jCTA=SqIMUk4q e]>~qת$'Hi7mf]"P] 'ź' (8UItpc@;R"VQ& nuz(w.Ұ&wb~?nnos-8AJP';.i_g@mnaI1_4/# ^\Wr}2sP@3#FC~Ph?n8y,J\2?DLp4*-K,-mA!pQ6/(qD5‡وFZJJ1Li(pm#Zs\Tݕ:"ԡxbV.)qBA;AfAֲN:'Q6`Bi#X+$wam6Qjix 05Jɺ GS*=K$,%}{Ecze1W裤] !qGgrAĬdyɑ@ ̀>_/>*U憍٠:Xf 6hE 7j|@ n7h(,Jz܋aQ ƹnL;qFG"SAkC^)#)vt` ;54-Fuq:ϻOO:t8jf56nPCS&E%*,~X-TJ7X튮3gj}PF<Cq\|xLu$*3R,f;s<v:5:N!\F6ef ak+vxl>*{y[Ƣ} %嬑DQK eh%Vպ2]2R M\/"=Λf="1hK!?l Ih>Km_/ z9=o}/]؟ap~Bǰ "S6f fлiDc"z84#Y g3>zQX5ÂVWw1L='Xo쐂=CSRpW^+p:#L<,]XVeM3gю;v#|eRRd C{xp,@(cy5R(ja `<Ԓcy4(5tbDnL[ vd%zc*Y$Y%e8Yow[_:JAxeWk|5c*_V$Z.,o9K-o9egpQ:5oE-3JLfǔ&L'?Qߑ,&=>3ARϹ/ ޒTu *NG!e)7Q I֫vh1_3f׵cSJPNT )Ai/[aLW,=bc0>+}j49*='/434 jQH)%2nQvɃ#Vdʂ]{ee%-X9S+$()õ(۲ZTtiBII dw2 gԄڰ#j" NDOyMIJTxi52.Q#V<5b/i;&Ո;Lj6ƍxT*JpDU],QQb%RgFȳ q _%Z*+-#az EjwL ,2*NJji*=yaUq㔏BU)ڌT+ c{86"ݴӜYU_AM& {C{ RJW5ZꑀI)Du2)"&q:1tMw2LW> 1,NR[X[(/X{|u$Q\AzE%oz+mm=Z8w~gCK@g7\}xLYB0U][m꽟6@Сo sӔW9鄹p4\eSP[7딺+fb3꩐/߼Xl7_ŞRnA'RcY*8/׺gWFc/T/&5cc($pȣm$H[<0lx,IJugX4YsF{hw p-`[X `VO͢kGapcKcHIbqi6t"[˶dBIȬkD#s$GtLI|t92gU&kmQkmvegFR畂(-Fx⍏vo藈!){e%tL<2iI),hv`)qOGOQYVP4Ga> stream x=]o6ܗEFD 4q[dw6blˎo|)N7اu<#C/ʟ?Җ-Qe[4),M]_~ijT'}ڋӳ{YUJie Ȫߜ k +9\z&UU򛳍 cgQ[D9RÀñՖUYzͧM¡4u) l/9L D~IdJ):aJQf@ HƇIeZ__ZՐ0*g1H[FeP7A>TqB0:ш*8qmde򳻚C VBNWC{g~FO+U/Q72fn0u{DAmԫˣ|;9z?ݟk"T.UPNNEu؁mdOkLj%De`%k?38F:zf><M.Mo'§ Z.L&WI =V`־5Zy5 V;|poiIR+ kK};r?{Ҵ1~r:ƒSۈv!_[O'h/|;7;zp)?IҀS:ԋ}MgPu]*Fsc4$i6[rꠤ3Efwg.;c.ځ[~Kh|`1" WpW^}a` ^hv-]Yy^ՙ[K'uXuzq6]:/ LV1a,`g؅-D/6%9e35AIL`hb촩h55r>iUi4 ]^9ZG~zܺ⎌fOsFa$ W(TӔfI{(LI]5S)ά)ɗ` Hx7@SXAkYmbwi5sNNY2Ew+KM$Tt>} gLه8ZINeS;(0I>{sg@قTO2Ye)W̆4a:)1 :t}T!/[ܨ34lG!oRDX,96y6wnJ/Ju]! (Y֥aK$쌄%o_%&^PiPḂ{ v=#-a4F85<9kvGpj$7o_%H[pD oHpp4X.be#NGQ|ru`*gz>+6|0dO ]M[v:1m˧A…K\?nO=t3``/LiFXB׷/TD ʜhKu%=EEz;"V$$!QryvRA~4 e[Zt.4D;-zN07]ɹCґe쓎A^*J:FrHbr}1%*#;9iGQʒ ; Xz\dUÈ1q;ƫ,qa6y޶!yUĎBc-WpVEpH‚"q ^ҬV ;%_U EG8""Rgc݄S HP"ˎ&7kPSt˨*Tx!`& @nX nʈִm;փ=֓z(G/w(mC{cuOٺBVic…q*vϥ*[Wnﰎ1YZI<ަyb7[e̟6ZI,9niu}.uӀO 4:2u=$9#1}ŞZ\װOK#JPˁ(ڝ]UDS=]RWӍ_hEow{<`GsdTEgHc|Y> XT]lr*,M-^#ZyQJ`t:JX:pL6aXAAhVG\b-jvu'v7sё@YRX/źD?Agbu=&|(ˡch-@5 {GQyr3w)#XsIx`[Fds;D50(MGz r>i$xjPWit'-xTIy3>0B#Sk6ZnѶ.s'CG/-,#dh)z.Ho& xx7ݞJt{MYS2I񕴴xg$i3w䚪,~A O_ܤsʴtSvZLskGV-YǞUn4hǵnPuH^l?S7ehe;m"hd] {cdr"w/(3WV-u۵ n9E [KLP ^wE7{LzaN9n r$zi0mI5&*RQQ̒nRmnlMaϩ=fSb bvN3JuCO,9Blkn&͐D?=< =<%䲱 qx.A^9ÍyŲ0ޭ.軓-VWl}[ǀsCظŪq8jU<7e:Repz*K(!D.Np7Φ+#e^പ$xT\9 ~jI^Wyl}D`FֻPƹڽ>wwRQc6m{ߑp\&h`K#)tA}}&vS^降 o,\!c*vdkg5,sl01 :m†Y 5ކ\AvnB6rJ6p0Rf/ d.3AvK2=E,_9-=!E*V4(mt>u;t>gj&WT\p:՚l0dϝ`SS{Ws'gK5x"D-(2Z~;cڸ|t/AP<>SC/~zH_qE일p1jzB+vbUn>2iV5#XgӹZY pOHȰ4^o2il%%Dq]0 _T1LVH|YgP.w쇂ܾ}A6z:\0rǧud7%bK|N-09-Ҟj4Iz(=`N` `{7J@a%80Qyj&B#ur?> `-~ xVؙiG @EsbhgUځUJ栲Ox>H kOK@IP`EJY#ؓ3PBg&esP4"<*LZq裻AFu f(/sI+1PZRVϑJ..ÜSUկ]r9!u3 QZkֻ[LXa2˥KRp;%%+-YQ^Ov$劶TdDKޑGj+#oTX6(Cun\0ɸXWr:*t! F+I+_1d jxEq3=)*Ǎ̄զIX#JYa'w MU8m|y<'eHXSW TQ +/l;(Hv]x2\@CoBǀPqk;/Q߃دP3)"# /.]L2e,2dGڟaO#Ч`߅L; =G9Dž9[vT_tdlzDOdE#i:3tloO.BI`l9͎kzsk4gF%Qz]b DAX> L'MFTŝeDnKk)X(VpnǦv)FՕ̽ňbۙR[vѥJPy6*X9 rotNNx9Yeϣ8/_.EZ6 χ*N5J}<ٗ0x):lR*o8 c_ǹm nxxf%TiſU7 U}rQэoE)W=V#bu'&A:ns](ǵ3|ሾ3)]o*^\]|NLEا$B?y$x-]3 endstream endobj 596 0 obj <> stream x=ko7 ? /3NIv7[owٵ9<˒&WGwdk 9$4*wODUl:-+n+Mo>U6oNiSb61Uy{mn>7gS?}f7{[O\x9#1SȦ2'gkDbbaWMӢ2Rryci߇TjyK=M-+)'6cnW }Uϭ?Ҷْ#y O[zU ^n1vyoZ#ճ#!gw?G-|F~u CgG?SqF!#KQ;  (#DUmNП`6/6o+DชFrDZKΩ8+YF 8`28WD 6C$UBm])N]8}-5]wUߒ K`I*v N0^_S;|'t~w۷*@ڡVowAڏcL oLS6eim`t 8޵IO0Ʈ..N_ѿ#UcHA)bCT+ aG*a!(;oxลg^-ɢDUй@kZG CM"pFbd1YEkG]l蕍*[wۆ՜Z5g5GTJǰr{~oܦ6D\];Sr tۛ% nAe7eT1-5RqNȱ'pt `n>7`+w @I~<pgS헝װIDŭ{ ^n9G;ހ2'ABO6el9l܁]}.c%Ftt 5mk n3*4m 5pb ~cp똾ju Ѯ+gE3`=d;p2xEe\4u>-R<4~:}9Bκ^!c;|}eJb$3;3\eUBOqx}j^"kW7wV bTwg hoonmfSeZHw19r[W(pvݍk;;"k{X.dU˟bCZ~_aopt._JgKRZG G{%&k>o;KQ#]#ƷG{ٌhopHHtoRO@_ xҧ]I挍)/HwFi@ROQKimL:N<fIS#=A>d5Ь; RgMxر[O ]$jĆnsƗ֗֐XwMB=:")&k;9 ݟC 3ˆE3ԩ1膐sh\4ws Z7,G_']wjfiAbag Sxx,-_6VUo"|8NN{L),9`nWmЬ [ZmK-kieq5U8mJQ-L#e;깝 f`b3~Mh4J{7:z{j6kn %7EHCĚaQj֛.L7L>.ȁ]wzNv zWҎ0G5xFO+jBP0م-WOOƜߏ=mm<@()*{F IW A! l^AٙA?يXc[u/* %r%W*ɢLڞP˹ f׻+_{~9 P]ms,-BVěKu+ x\ZC'6^~%Nn# sBVj=rl̦ʘgݗm+H'z?rZ>ȭ~ kln#29bib5lT.{:mi}XG.!񒡎&]!f'P$dd2$d  ~~yFtws+yS?xZm6W9Yx^ѳ_\7+O]@ opqK'OFaLJ ^ 'kiԑ- S]C{@ :@x`Zi:c3AZbqi AT,BX2W"5XT#֌E rնw'xOyXwJW>ĸǶMkAqSƙH B2' I7ky@m[JF]1{^bb[>dB|BW^!HZnm ^95p.ݐT! [<ثR'2ȺF E+ $]eHa3vs[=!VlgW,(o^B` ¥ lfBY9aB0*tÔ5n"f"7nxO SygQg3f-hS0%Th^LTQGuXez 37AO@{ P ,Y` {HmklI׬>{s16~0&D7;/nr(M\Uxq7k'a$!׵-6.b2'$30ّLs]tE n@&\H)mD?V -#Tjȯn'Pp_L $!vZ_XoiAhe>ֵ&x@]?Mqd(.<.&ڦC#ۓY'9 "Ș)$|AU*~MgphBg0J`foEPד!9=%y?LwYi>LMfn#ߔa<))tJ7ZY.!G(SS8iM:B9?8ɓgm]HT|*6ej.{ѪKhY*l 6(3AmA)A}(!"x%5B4gFUUoWT."W`]; [RoK zKawfQNq0K? @s-朅My|Z&Y9aW)Vc4)|GYǾMcs씪)؀Z_4\oԑMq>K ZXOB|0'̜5uuy&:۶.|_n—oolO5\'0\Fe %0ǵ!Erwy'ŚVf8ʂ s +/^f Q"hR2t㰬=x4 {#X6&kѧR^w$Jfze% )lk+Am'Nb?\^L`K}RIblI]^Ƹ`}TIەWR݌󲒶Gl1]leB`MDSC'{fc.>pP &=0)`_"$E6sE4"dyw S0skiP!}RCilUG9F[m?#I& >okMъ 4`sU`G4G{|='`GTrSy E[W+G YV0|V[Yap1kxK`sP$PrO䨏$Mc ~ZۏKhk?G` rGI4;+%fs}]DήXʫ\MY^BNwsjFX{[j^IM\,L´xg\twg?w|N10er1zxn$FK<#аf'GG""|-yA3{ 68& 3H}}ErOYnj8vU5ߊͷ2X|K&\?A[K NͷhLeAx 5'*3WV.U(|"A*)&1 XiM-B&$3~rꡝs U>>?x-Қ|9k$FbOH]uwe,Sn aXe壈5}1W>Z&_>)ET=Yɓm]qHT|)Y̆Sb qGhn9.C TQ֙1x8ĆG˪D^K h)垀epup eHSj+Q18/κ>N\tZ| .8d+18_IH](WxE7Ԓ32Nהv$X^4ػS~פYEkE )!B3_|\|o!Vt8`Aas&h^o3(nFe1DZ8p/ɒwGq\nBD*'tz [:μSe\+c+ihgi3Rڶ֋O9DʑKwqoY&t |cN9"ZMBКN5h I opE s;r+_)nI$Q bɬNݤZyZʇ'@ 4T㕭<7x̜p&}g.Qx0YyK;7sX|E;?ǿvۊ#3:311LUH>|ky? `ߨXKp(፲O+$|Z!,Zac=Ed^XDy/aWhy3/,^XWE+VhEco\`3A3K_~Z+U"qũ{.⢔%2-~ȍ`'nL[g0`BהYF>(bwl.r!^!^3G{K4CޅMwZ?83=P>j=q¹rD(y`f\8q(~hO̔O")8)I٦M%MAYƂ@\!**+3D4iiFB27期LK3Zɓ[m]KHT|Y"4YV0k5qj$afVCJj[ پYc5BjDA`WݘFnL+"ʷI`]/ +E[hEyE[ݻR-.6$XCV|uor#E䰬^o#BP^B0{Syuee1l5PMޜ=P2Pɨkk`?p endstream endobj 597 0 obj <> stream xk/XidKUk_å6i?W(䕆K,vy&dj],⇯deZh_Jk^փ%ρGs .}UP y.&GSe]/XI|xU+&o)oU 75T5 Wg7SpFeRlA@qaJ iXAjQֺ`ٟ11]Sg 9~\z Pq;p1/ߑn| Jq MT& PȄ +ʇ #"؟pQ7NHbchb#aUp.JU&{D)YVa !}jriU K m]U5\h"z2cx51?KP>B$R0Xmz5e@jrI(G&im_lPrA$g=ДXySl&$Oj—>s᳇ϣo@hg [7O×)U xABZ?{-AWT0  %g\agj 'ʷ9ēaMb9L0NS A$H|9s"]p}v:N];ڎ3CZeU)v7ZRI81N881>|f UPzڈ֫(7+vMnއM W')3Q"Q 7ur~#9:~ 4XҪxiĝv|b`\tc1/aͺtGw]:8>/ĩ˦?&1?Mb*Cb* όssj-8v:7%u~R1'trGy]؉E,1y|!|{?hu;!.jzki/ЎOx)Yl/P3\"Ξg fȏlb/la Л(d.õeQxpsق΍lh7 T0/t!¹ҹ.A^8||Rdվ 2[[MF%S%TڏuR, vIKZn{geأ ÎH>cT/~q fY !fJ1 ]a9[ {;aΝmnn.KDjeK۵mLDL<ɌnOhPyjԮzvf9o'X𮌊 WĬ+CKxt0{rSP4 c0Ü-S$NS C6Qvsݡt;fy@ CM't"Ĺ87ݡ!?3ݡzUSd9B&wn$Aq-3p,UqvHH:Tr7[6Ql4#.pvi; 3Z:\fF:5:2<Udڛhh9yC a:;-{czvIH QP=dt0ˈAYNT;>aPS0CRt48L&35A@ΙS z)3r&ě cd>/s7 frǛ}Ʀ{;ϙՙyˤ1yJͺMaLE\Ǟ00Kp4*;Ow(cx(Ps j%@^=n =K I"/Bq-`;Vh e`r&y]r=T|)A/n}g0/{4w"4T@X,^h5Ӧ=N9n.޷Z\7xf^<[:_NG9+fxx߀i N'!&֋D~@|9Kk4Zţĕ _l aұ-`G<",S=p tI~c@5:k0nv $5)IEW`nP6Yd'XJOlַ55^9}5tFdv71=~//`_%a RտĤS>5m$-LvjJi ]^@gzR`ůdWWdG١?WK /} $O[~X$]mzD[I/R7̴Ćο, ˱0<Q,z6 oG?vȓR`>haޗ]2DZ9*(v0~ݟKl)w>M.-#G2; )sA3UX fQjG oqn;hy> qMżTean)Qim b|*W|'z>E56yF9#kO¦'DڶeCӨG&Iq 2όSiq*DS!:4s!NE,,gjpnRS 71l2ɚ"d.XgJ1&*~]i8۰*Qk1)Qm$%dSL>J`wM:I=l̥6LR4>H>g#. k1ǓSAc%PT=?2u kD*qS$Z??2*u_S0`|A1Zut-۠9sC. -|l\zB6 c6#hT1=MC9U aJU?6X9F gd:⠌z '{)8*3> |ֽanoQMiz*J5}XE"XhOc&1 K endstream endobj 598 0 obj <> stream xc``t endstream endobj 599 0 obj <> stream xc` O`Ў$?HL!ZĠ B D~%8jP@.4_w F\ @ U00@' mWN+˃df?U w] endstream endobj 600 0 obj <> stream x]s6w>24A$r#9)'7v{K#y*FmF6F_ϟ+.:%KR*T]ح?wϟ}ߋ/x 'ʮ.Ϫ(x7~_gSP˿?kܺbog˖,%=Dc[υfJ_f:{]ecm S! hY;Kh ̶ܝ}gl7|?ᏳLdqCU+gBK52ٴ}-}*1@K٢ʾdK^L ox Q\U-1q=z/MURJh:h4@@;U[7TIWf5p).E0CQ "27sDtc}oGKEѾ̌gHIz1n1qi7QlFP|V"eZؽI™P@t{0" 0-ھoCksd^tD3:XVB_`$bkO wטyG"(@eVwg#|oߖ<#CyĤ,:5$Z@:n:dS 1%3'jEڃab` ^!n'W7^SCmѣ;Y;kvlTmUhE*oŞ z |%ukla;T'ؑ_ɪ:vUٍe;¶h{=# @ @^R/rv+R q #ƽwX4Ꟶ1\A|<[b}h t5ޢ1-~%һWb 1@xWGH%!dYV@X XPJIHaȾ)궄Ӧ*T 8[C@I7xGZuTQ]Xhr@-5''&U.:)f.}*VG#4܎15j˥8kJ[{ELыuAz /:CT pAJ0U)*$l00ĺXӰ$ײܛ lK-fTɋHDU;-Rok\ESPMJe}=r|Ayx6< d:f]g"DitII.67d[UG5\z c S'Նx"05npʼ|y:;v@hֱʦyg pr*_I?P֭ H)Jٜb s Z8#F9`/sJל&EW$hK/j@bWO0mK͓ы5qNx{`y!ƈtt#Y܈lfgPG4afl2ȚxMjzG&nX\TK.;9n@`܀Vw"^8ZN}}J4qĵPD'c.nRyѽ[۟ }:3i'ןDu0)id>wd&=fK02|MSxu'ބ܌?[5yHKRWF ]<] sF"N ˧0](7;P،pX蹛 琋 <0i*@09"q!1"&WBhsDcذֺ$+= ciGM iLKjIH^xD3Y*5Nd|R}a6s ڦqXK#Gc;+v1.t)6}Iy 7be0u#(cj[w D P58&BTtR`Vcg[sXu/O<11"?aظƘ,p8`4̱ռIc8Yx`>5֘fNca"}xZ6Ҹ̞NŸ5 Gv\/΀zjC)mWI0hd]#ZC1c'4/j, *DVڪ ڪmaAl s}""GdO ݪI+U~W-f8+vsPQM0*ش ' G DaoMٛ@yް(ua* iX` ?dCQ}wc?J7|cOᅤ^x0[trXc Aqf_-5TR`oSwϐ2F;x䷣S1>\ӷ?UH ѺVw+ N:X5=VlmcĄp7UE R?$eYvzxQxZ'fqc^'?9__ޓw%~  -5.vԠb[{"3tnع2? |W!x)9gna1 `dJr{zvVf7m>Eamڜ?Wsqenu[Fum ݐ\)1rqq?kimR[KlO=$gH~\Zh-xM఑%6#{քGԸ\sAk̊dz3̛7XR6*; ; e^(LD={;/!nT؞8j9TCGdc2b/&"qYHDqRO4w/M#2 Abk@umh0}#zVW c-fKl{ἦ~V-^MVAu,m9q@KVDC2U)ڱ.͸qt縷ޭ(Qƶ$rd18 N MLb ncc{kSe4M 6&*[tAijai_>e2Tf'r~6?ڨ%geWf l)dCqm`ܻ&I=>^?%<tQvB^EOu=хLN}=VFn{K+dtoޚw'abV x ? E(|#&]XMTO$ޭevw}8q--=.̿w+[[P6HZ~LF , 9v3am!j\Iؽ=hPɯ0ڭ…2.7ԅc Hp|ܙ2-g6,e`cvp'ψ/)/3<8/1|-w8c?>AM4uI'^ ڨ#^PPFRQBFр v(Z!%+K4eIڕah` 5{ (_qv‡, P %o{FMe0?jE}1;ABX >ÖLH1IJY# 8{@&B~@̄㊖F}}4KϿܘ-[y!MwhrvH0Cf qoCv;\}69/aHggiڛLh[S\2=r~1pGK=seCܤG)QEu0{q݌y]3gz]F#Nwm^ w7ɾj*7ʧq’Wó5۝@ jaS^֝7ɼB[ճkENt.LiEk T %E[ntrĖf5ڱ_xʥ d]&蓮&nT2YO~Ϙ[lj1ݵp$yDʬ+\7hV/['3HM;:ER!4ƍ=Md*cJUc5OiYGuh,;ya c?$VhDegECszeB3 v6W oAK:*`+&qpSL ߓS*{ф r\h+EC%![-_&6z9Xh̺w~Th2=ĕ~ʗ~Yh:-CnNɒ9eƭ0ٍAd1ʬhEe&4t~Qu1=VEeUtUyc+{W LI=vm1'^ʴAu85[)Q4\Z$;1&24),m,]H;ܫm=3T똉.KQ[pn7UA&rA$V|q)\d/ЊݟvM]#~ {Ȓ̌h%YSK6 46{C`2 ѹ3*zVDz;Sv _> X~Ď7pRf}1Tu/#b.a51ܭq/c,&}sYj|ٜniZXyqk0.hLhȹDEYnELB 9SuGk֝1L^Ѷd;菱gڻ')tZL_ZlC bEDUyS'-X걶Kʰek^5&TW4Bu4!n@:HV]x""Ņ/ٺdiUwn!4p W̑1({'wM7(#jF$.'yWvT؉L&&֑51;GcS {xCQONh\W,_^ٌGoH/DH$DH$o5N:qzݤLH+D<73sKr'0Q)&RjN$" _T,Y@U:#?n?fbY#?~,Ә&:LfSqV?h:% F{FjkO"]Ke>l z>ͤFq*'&*-n՛$01IBd&e7)&A-ٽ@/7}?A6{d$zFGJZ7xМ6~흉{3lƚ2m'Nz7axs88d`iPb¡(#,w%[H1MqVVCI%xT&,L$xU{0dɤsM6dLZ2}zu$^r 4Ww&OC endstream endobj 601 0 obj <> stream xc`` m endstream endobj 602 0 obj <> stream xc`CCpa[hd@70AV`4jA0„2bk/`k\, T< 酦(&ߡ@U| , L̻o[a endstream endobj 603 0 obj <>/F 4/A<>>> endobj 604 0 obj <> stream x]]ݶ}W}IE7ϪIrĎ}pAkˊjmˑ_htt7HI*hfnO4??2x<\l?]K^GOG7sMwyKg.\8Gg٫Ǐ;D?}7wG/>~:zKlf{1fNc<]PC}|.Ogmo{š& tm"7wOn ֛Q|ŭ?'qv.MW_vc䶱WkIaM9|⾿{yk\'?ɷC{2.F=oo=&g1 8vB_ i{_4ݳ]m࿧ _a?6M~/On?yz2wT~u#̍pp`/lr[XO>ͻŇ 4\Mh$4]ժFV3`CiqjxG4^:.0 fm Fng3l'*k8uvW$Px{05]\Hÿ̿Wq.;7~' \~hL73^1m6Ŷu=קsx~?Mֵ?31)|?As7gfMUY ֭mèF%_.}GcXi,$1ujc_n7v }2-pM7ߓ?o-0  fnmCuܛeʻL.|1e M+_%=j,㉅Ky@90S|y߻}y_>_Dsoߢ_I&_O6u1eߺ5V)2;=mp-Fnʳ!?|5Ò γxJ|wWC֏ar٪n:Y0w7B?z+5shn%OM+"I1YL:b;`@9,?IrCqvCe0a|mCcZLPR6.pu4_[73ָ]:|l[1`-72S0a5])"02!"rW? im'ڮ'D+bjД,jV6kJ ݘ;Ƥ%4 95 }K¼=7xs0S/W_m.ut0pW_}y?[_~}#ue$vy&߸xe#g[t}oYޓ[Fܱqzel(odso4:4Pk4 lAvЖQB~6Hр'"mK`:ެswgIDzC7Y"dpX $|۲oK!ަ'.8&۷ Nw?{^_~[DS>᪑KT60L1RdNY;շ $-L&|?>^ћֵ1hө=ܘ=rXDxF 7rq }JAץɗ. 62ԆbYm|, 5V c=#%|; ?/>x`*0YI1V¼ 94&$Jлx&eeTiT] zҔ@W>WE]Xق1Cxs<0*CG4j7I`fsVP P1Wr:ű]x_n%NBesܾ }gs!?y3d"gV'l~LԎ Dir] $ ,6>&4VK~)&H.odI\ Z2f6s0E!) c:WC+".K( wd0VAU% ߺ+?s 393akaA\c\NqD}7cA \V ULӝiO?rETwHn#߲ni$67ȺAJmF[$ᚉHUL3($2=UtRE24Ӝu9$DQ|4ŇK"=8@(ەفAI-+4Eץeŗ'Șu˜ބfvv@S>'V㬽$ǼK:b{VFx IE$]^ADXmx!IDo4[fs ѻ7`*DDN(#H=~ՌTD| Kb+p+Y&q7NFi9*"KUHc%r@^Kę8{D?xRi* ĊDqϹ&awU-û꛱)F˱yR`Abl Fn`jDvV剎ʨ^`Pf0J<&+0yP&c2QVzAgDf& ʢ eOۧI(5r^lqnΏ wOu"QL_b7SezXpl-Y Y{NϝXLF&R5d䂲ՕTQFVRI&&d%Ek _ aPbjSQO7f$D) cVS(#YtF@A HVO1zyը,8LtPQpu^@H\&W:8^j@R(nGDneBQiWqhMeJeAc( =!*];\{ ?7 VM [뀈s Zerx@;.fЮO3J@) 4Z:1hMgV*$BF@z Y|!&ĵ }NlB%?1yL%*IA!THCxSop*T9RVG qX{ yEp2ޝ.,zg{|e~w&4c&[ PG9+4E("g#RDJ9h%MA䠕(r[#vjo=$">OmImRe&q?I@RY<$pV#h& 7oh& @@¥ae $/{;TxgFD`Bȍ!ЈpM@ r.`i6H6)!8B*)dQTTc {hl枕jX(-ژsemVԌ@PvBmKsty$!m|g+!{/G?ߛi&;kQTv [GA7GX~I:mݯK wWj|^h0Cv~ڂryz|[cDi)M˛h?I >Cc ) 9)ʙ+7q^P<9+YV<&aD".*#E\JRDĺ(dMYBljIj1Q%&D֗E2Fށ4a+:mjS:YRL^*hDQN卬Sy;xTU=vaէtaJ'S:`0xAwK$4W3JyC#&\ֳ tȐxCT|aꮚݹe<J"q;%IN /OKGo9a6MNcO!]ֳ+K鐮t+(GViimvCc:$ΫC[9nv#FǑ7B+vBL ȏ!+9C24d%eh6VrY b#dh$?fgE0FfsH,=hȊ,j4KEPE,YA)eh^mYfɀXr 4KoEn&(gCx;o+!P\e ˎ;ZǦѹj͞t5U+oY+1FV4Zi3~S犯9}v҈ziJjՁG0)Qk VjtaG*sԂHoV"E+VV¥OIpA7e!uv!*u+ž)π !*&f\ ǖmc7ܳ{;v{-Obs0{8;Pa7mԌ%<匮 C8vF}R2; yz w2(moٵBkޛe~:"khɎp9q U4 ,b\h֣{s|Fd"Qw2{Gd%SՕDJJL5/ĿZQl1ZvGFբC-ĬFVen]컧}`j{EP![7\PZƒzTYA @9\.H8gWe턦fQ-tS#}˛iBi+2ZͦGHbT 3($62g?7bKrePKweQ#"d*" tUtZg4}cm1Vyĵ߷s_/vIJ}GkDž9ݗțpBY#xL.2 "?BaYɅ]+.MA렕XELHS|bXFSvyN)TFޫQwRE!)]s8S1FBQ (*63jSps28VA: \t)c.hc6l A?zKV<+~ȷ\kED©/Jl.sD={OfZXto:*w.'f'KR7„@'r- 0yi.aI IdYawXM"OLMI&:4/LF(„^A+ 4 (d# RJ&h% MA(L$2`j O"L:Z%Z9ӎNh1h¤uV FJB0"L aRT`s$`(*1N- BXͼOCa&9 /LeU 9uAG{GA̻ڒ0ya 1+CS_&eM ۫nqG@QdCK(qI 6O6ti-qb>><ڷo)$k,lGXVji͇WDjhɩZ4ET|.ET(QoTDo^!PD"j_BЬ"!+"vHLdEYɊhu%)"&RDd%+"fM^WR2Mk ( M$j@hG1UFŶ9"*("UE I~bwSPD[W$Gh+Im%9w Nc SSPN\@7܇O PЈ=Hښb,pǺ3-=BI(Bnf¨L[|V5)̵rJt=Y6u9*{Pt͸  AwGIk&@f<^|:_@;XG nȟH9TXrxE) ~ËDT h(ՏJQ +Q)6VRkXFWzUzǵ؄w7y%?R0sCi1٪Qf HOj 3`5B׾j9aEB# :a@ I>_1 #¶AVmZؙ!&xa9;T?G MI&NeHDiPJVmFHP8 3OoujtͶ5HvɺIe ހ²hR8HTL3({2E" P]5P]hh̙إ*. \w;Hq kӔqT7xBo|Aܞ< dlfod<]nofQ8mX=umIF7Y#U3DTehՏJQe+Q6UV*kƫȀUe D?n`ws ?;[uml>g`o0Lhf8>s_?,l^ / @y$-cp=(6W{gþ^&VEVVp!yfbzdhԻFZ~8G Fמqe׊4@ee W\B Y>)A+gk!zGf&2}4^;:'88uGxFu&7,;2֌#ɭw.] xx?l}dUg/ƃeS9ƊL$D&2Gd8YIIiq$b8Rh^fmvR⍬\bBAa5C3b(*\b+T8'yP/_~9.GZ7( 9җAJ)#g:6&Uȱxd'eD*֎Ф2xl\(S3V-׎P(b"׎0hzPZ3E.7߰'HyмBtNr$ϮC16?[uP'WfJN<'4NM-V/ɵY|g=%6BVɵY)*:6WɵE9#)'JNz Yj6M6˹٦iO, =t#?$˵1X59H9'C_|D>jAR>aڦrNu ڳQ.'yv<4(,yP+I<^ IeŃȂ";0N=靬XPNBԃyцפwK+;S(z"wZ4l/ %~XJo?QW|>фJ"kρ S"T}AIqȿ?[k @ ^DhՏJ+6V"ߧkƗDlIj×~b?kv!I`mDoɄ n=E"$ $H>" ^uJ`yLˆ`n4ڬqT-"˩;BZc YPo Pp]ѤSǪ׃pQ2a$D,?0V~l㨒 (?b{k QAڏCI#TY5Õ8VN*CB{9<;tnwp+P=7 ˄yw+ޠF !-cbf3HܙLd3Yyu%qg&d%rgR{j0* endstream endobj 605 0 obj <> stream x]mo8 AkE$%JZ,d >ێ1n`_U(ngtJ|",mEׅۨj)Y6m??ϟg/.TT?Q]UE,}޶gUqM:gWŻ?{ ?/4lB)Bɲ(Gl'Pxw~X])eQuZʦIӳFnԃm_.ǟzbdYRja`_O/kѬ৳uz(~8rjYdD9oP뛳-|xjꀴN0pe(XSjkU)UUz)k^j ao6.^3w֧/Oź[^>uY=gc/USԽ([P9JhO|>ٶ[:] $õZ5_nU. 50_kZw$TmyLfr,W>Te/oMT.}|nW7|MeMEh%\&N:pv͵-[{ 7| ?u5U8mJ`#֢YN bڮͣuz,?IDUvm R } ݻnHqHEttӋ]8oIݥ@F S @)R%i缳Q25%QB%ZJx5 ]nN7wU78ݮX}&hI=NWC hO&OG2.0>1 6h]؃DXL # ^p;M_ h'6_ԣh$. mЏÂբn,; ߁DT~$*R\njJ<\N&| SDjBRan7RM] 9D#Ժ Ww|cAɮjK]}($xzjq tAuԫ+䔶^Z#_qc?ݛMKp1<*w-]ۗ炽~} )XW)x9LK'(!LvΚ\F;`RNW)HI= v:% [gM#$zh'_wHbg>O}۶2j |{nO&_Rxp&tC $'9&L4IZ6& `{6ϻNyɝo{wp o&t63!+v߯ rVF%.n2&ȹvM ByoaynF6fk^}'s\p4zu٭{+|Џ7;MvolZxPH`jlkI'.|Uh-zQx-ӕ˼>~"۠Я-zt 4-8hr/b] eGZaK0:}ô΢-~] G9_1Qm6xJM{d|Ag % MzbB5&/_juU}Ӟѭ86jKZ$ug̎1L[ؑ99$s,C'T 54J qLjTmwo#qj <ր_nqa^ݒx.hWyj$,K 7=ڤjUʧ=Mjeѣ5I#3Zsӭ.٭,qF oq-MCE2]n}/f,gz#'2Hty+S9bGѮr!X UY3p*z[mvZ<5L-]F4Cwiݑ"FX]!jNԛ;|]Sh[*I# ig}fIVNRA$1fE-IWk41v\M7ߘ 8Gy]$@dxn`r۪M^:L`֌af4ҝK] r:hL6)Cq|ާ 4蕙!<Ձh ;PZgk~]O?QijP86/LVa ŵjIu \'X_ndG˓qvE Mb]%uF. S m_&W#[b2oJUK)%J,I*Tm:Tz\o\ju9CW1^n1|ёL H>۞8оB^wӇ& h_D'.I5顟q_DSiu(Plp_ХC:FIvqzwYuvoSIj<WԸs8N4/Tvթ{Ngp/h{5~X9"G ib1DD 6TetW+܄Ś(9Pa+:Ŕp2; g첷p" gky]=RoS壱49ST"!#zpd8][*E%"uPxaC﹤-c^f[lN PBk˪ȉuKmY >士JgwNxD<&`)huL~y18a5֤RС, =,H3A2@GG`O8DO;h 4-| "r~T]kt_  K"*?w[ҸY$Ą^.pm$5-n6}8PEөf `E2 Uӄ2UIc^K276wLP^}Ȉ=G Sqib sxh2 UL%B6`rY#FVT wI( 7{F|n%NpѴX,F.KpE`o4@Fa7:Fm_MPިV٣7{M@1yzN^5=k~4|xH&E^0aʮI{st?c!US?_:մ}%Z'&@J#Q%CPxP 1xCLX(e!FQ5ٔJ7;TJKcGR ;*cE U_5%rLS3{4˜iɉPjУdF_lXr4W=yՋW;Qvx>31ȣTlpS-=YDcݎ3xD3ocJZ .҇1hP)lNLKCFT&&6{b" :p(%bDvhGdLA (WWR .A'4g|msGI+ p3JW^Wq]Uc?8ފ'=xޞ1r%6nڨK,Lrc"mbԖ/)EO1Jϡ%[By^Ae}oͬӑ\f5fݤҬ0HVG3 {3I˿0LPD B/3QFf9;1cv %t/a%p174o)ޘLc76{cLfZrj.ÜG-avY+4aND:atv5yR >Rd`dH s*[5xM0>ۦvp"}Ďn0!lv8_'#ջ[BA M$}k@Lt!yn!:Ns{e&ӟf6ӟWނL-L;L'ϲ̄B%D GsP(tX=C_P" .d-KD a&ӟ:s. J.q&l _ߜћFZ !#gL\[=QG3E*{JG>BƇy☡+TcJ ?~?nOX#ΓqA8pa|%?o{ _2QO1,M2鐍PyD)[<[2J*B5ҤT%0S)2jcɰ&@ fGKJbaa:Ph3{0ǧlf7*$:hӬbkcҮ^| ?{gί3>B YĊMm'2|輟 1'gB pWbYzi>Ik)Ӵ0glf1Mws5de'gO"['k= BHB&DW_fB#DW/;Z8֚bN|R-kjy΅ q%,{ 5>RVYYܫ~` B%UOg鲀X0+B~, \X$0~/;t` Ռ;S"?\0h.\-qB|nRw6CmurBĂ(2C:hw!؉j;NKxd%jf4}rUk^\bQWXPk!:pU.?Tx[diwiMKXՔJ\Dٲ\ v+ Pʖ;zU1 oTF 9BoakB4;S̖C)BjeWcYWz7[,A @|mbLg%ǺT>s_| !mG̸>/N)ns/ Rt;ߡP2%7j# M\BH,Ƚ-UY5=Hҥ L.E _^.vR{.y.)_~nJ;H>"|e>*~fȃ^!ŸS-7`Kq+[ӛ+\vQYo59{½9 %aPjAu=A5[+JA-YTSUp-kG6uE&#Wv {unZ\[8Ӧ|^mTJ|cNj.R ,6ݽ3Y7g[Sk@qX{d$ -T,'ٰ1ɺPMsl endstream endobj 606 0 obj <> stream xc``t endstream endobj 607 0 obj <> stream xc`L y)ae `%0BFHrHU|9@J 0XW(' %4"{ f0/$nwI&̤`"?N*r endstream endobj 608 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 96 0] >> endobj 609 0 obj <> stream x][o8~Pk$RH$Howigg,]kکN=JERI؝~H?ϟ%"T9˕l&Ufy4[>g{̊(NgY "Y^}ޝ糛 gw[0[2ub$m)Eې5;g/98A$vE$T*.ggc# ?(uic.?nddH=uS9̘qz?:xWgi>|[ǔLDy }~.7\_Z4M= ^ :Tenq,I (q:I;Mw-нtuF ~q,^wO'4GNF2$xaYFR2r`LFY>D3ͼf"H$+H)/~}@$bť S qOeT4 ƿц  CT58J'Jzʣ"3|wAdOr 0 az;D\Wt8VUKa~ܒ|?dQ7)kwn+`T 0$(SoAt+ŗCi2.Ql!U&ۂ m&*-xm['p 4b.^,BQ!w2#CR7A>YP%M[|OIx*l 2,^u8JRQp$((8+Rͤ(pkZJF'zW`*'hI,+1ZQFOʀy}|:&q1W"FN!+FSP8б+%^~<̢G94 /3]"6C094F/3=@$?0:n=bw?sH6gykZfyau@]qojD;-eO+u$z8>vT))~EE*StN9i9(*r>OʓcOb 9ܳ "-MҟӺP一y9iw>[SA*EO$M"3萃Hj6u#BH\[2'^txNmt44~I)qE)cŭ$U^"Vj!<$9$+gOM)X:A'|+hm/kQ"5$leQvvgj{V'7nxqd(# w02~LR oee2"ݾG,43B%5T"uf 2[拿RN J{#!of{&_wAXwoɩ޼B"YOmX.n)tn>ٮ[7_slróx}S-@fNfS%+oJt Msdo'e<3z,@qg_rNf:$Q/b0s`ʃżͶs>h=[cP醼;M:ƫ$ 9 PU)3#g64/DZ6Ujحkի”U~f.i<8^MmRP9 xjcߏOl'@ۓ~%g(k2m^nM}PI%rwy| tGUuD<ڥfn~ׯºw*`_42Q63lGhY,諱JHa"8A:;ٺ"TӊP1Wqk;r=| 6v5KكB V c#0 .Ǭ2lrPKY2lۊyITJgYNnahэasY(fcۨ,F *.o)2aUKA`AJ Mt/??sD >P/޴4J˔ֹZGJVJPFƙE+=hrݻz4uOx'hMO|-JقV(\g\F{5>Dw7f?J)|=5XmqIH-嘃^һQ حttB4ݾWqW|13HqiAJ(uV͘"4cRt?HR 8Ñ8˚M_.^ϮT9=<}Xm+W9;w]í^r ]/kw=OFG @IPFQC +;cm12X4R}yk{#ӫjs+= u,Ѱ3>VmXAQpX1J:F>Qӄ>٨G3eV:Sbe~ә=W]Իn0!Upg|2T_)R+4ǝ>3): WNc,:n% Y*^>iȨz;V#_|tnQks7F3펏Ll/W3$x۠ڠ,(5 fL8az6%[i0Xl 09}[Dax+t "L o';9 Xi8~3tf#ͧ|.EՒ@!pJ5L;DW֛#@?i:H,~Xr> Vt +!TFJ"}G@*3jUB&z[Rh(L0}VEM υ9oUFӪQH(t7bJxÑ(`# ( 3 /gl$"ˇڳ^l#X:.WH׆O1 EMsjS T馆XVŭO/bR 6Ӧlr;R ñ(`crƀQÐPTbQI1 CraөS 6PBtϕI3>z; Upii栠J1:3ȂfeAG;!4@to#}9 8܄f:\ ֋AhKy5cKoPT}Ȕ5Hl~tC~{AS}4RԛՀApQ{s去BtIB\7f(U*{úQOuXաHpEkErVH.)z"WGrxSXAq8Gr-$#k1:x {^g_#u:<#=:| gߢy0*$%"ElpXm8g(6v:P Pu= u7V+3u;> ~is+/[$~%V]PBHU.+ N *jM~ p hP\>UW6nA >jУ;Nj9IKWX&T&s@ o& P lѧ@ Mk:LA>Nᡎ,=A1cP7BYUݨʣ[uWyt׌@WU;hw 5K ܤA(!F`E uAꊌ-k[N am<ρ@rBYfٕ!S݊:-XXn34עlhG0SO/{\\Quꐶ 2:&G8#U䀕iϾ/sUsw} SsmJfyKIސ^YFwu\- ۊ0`M3Kk5 +(uAB{سw8bbi#[mKe8Gfq"@ KovDIѠYhT㉝mZVG1~+b\ԓgΝ:Ѡ ܅e.}25fJc;W,\(b2;TC1g$ SZC#3ljxTm1۬r'^l6ڞosҿ4iڞՐbuѰi1J6K3Z+'{s8QfSL p5R9Ds: q{SCvAAـwcs'ڇ 6Ki- (Ǐ$웝SسTP;6A1 yA zyd@? S2bNQG^:`'aY STX7/\ZRvTF Y)ͬzL GU%d1)<(.US nP: \5ȨDDp+EljH:Y?1_IcRxJMgM1j.ˉ|ۀS1V&:q^'3?;s:[ȶj~ެ0',$ ?v|G?Ĵt1}ĴF! ~絫ر_eg?o++r:Q ?Z4_Ҍ]n YMf~(m Ԓ}MnbhޔױdFdt(Nac,\s0ibب6i@w1ڰjI@vІ8͵;tp^IG;w=GT^P}*˦h*]_PF /F 3n6;*٧wlUj3){VF=DuU,h.k,K_4exΒ[ٍkDʢ,A \5`?Fz4?/۞vϊHd~>:&a)o #Zm[.Z@1ؽ[v=_Y7'I{v]֠F#VC6竸{ի ^@@Ҭ"L@`fL:HJS#BIbZ$i _Ƨuuz1:b/.cܞhCH*✒T{H%,҇B-h(-\rYC.%}9z/bh;MtU#̿&^K:Td@+@o* \Ьph)>N @G|r3;Mq!/jme3dizzN%%߶x4ڰ㳃^a@>a8*t64c]W\Sِݫ}3+;@7zgς)eϊݨgŏnսG>^ d.VV;sg=lQLy=șvqfB>:ͮ{1I<|SǦB_}d7:hwnVe4YFVM~llk l힙xYfZ Qcx܌֒w^m??gL4+Tc0Hy 9?q4鶡,f͆cR߃nK`P^Mo;NٽYg0W[xss׾QUŮnydI!ɝ0F=Fݪ;è{gxd+E/XAYmX*ɋц eQd^Ny:?#Xm4'Li fWte҂QyG4Jj c{{sw(qfD< A '|tTDžoY!" n 6L@ڽH?(>JLʞod#b,SL'f 7KDDZGD:&nyS{I@O?-"ln-2@/1^F=N`/n9O8`aOuuDa xM5Ȭ(e誇7bIIδnc3?z*WZ;]m&pֻ &%c6ks%ZqfBzJ嚸ʟY92b!DkMĔ306}o=pFJ ~F,n^trn]RVi? endstream endobj 610 0 obj <> stream x]mo8 ?A \``b'%$;@ ]_etF5zX\m?Wԟ^?~`qe??zGߒLIҥ3Ҩ*EhB>$k,VbDb(4u>x67LJq\̍\HpYTpwik,?zf4΢,i\>|&0oP_$Q3yYQ  ZlܢUC4E` &4QU)dڦd"0%\Qv~6ky[׿ -Ѝ__"8=LQldUllض"*ct۲jJK$ILg)  TuXxěΎ-ҖhS#sK=|e+%d&xjʆ;M?X#NZЎLFJX+&ͫHVOr U#pqQ\LvC./fƩnw &s '9pNww0'j7I V g!co*nj^د>+J4b)@!l[{X%YFB ufmfdRNAH&P̡XZ':$y+:C $ZsJ#(⪙zg i)ҨNYB~foL/m6`Vb< UXV+qa@D. [*}\) bbeTjw!oxe@,9k=n|Č_혊L Am<2dcjY^#ԮeA}CgP#]~fVM~ od ?2ƍ@qo %zр GM2BZۣmIlY \GGJyxzɜU[̱&ΟmiA"NJD(%]UvJ>;$4iҩle%F\"G}VjV a2%ԈU;5"LH#GX Eo(5#Q$=iaH&P kՉ JhzjāҎ!Ó&&&OVJ*1'V i\RiPI%BWeU;De N}pRITz4*{2ivtAI'}PJo~pJr?p0gN'iݟʹvD}uz+#n$qW[\XSܣ*Dwc'JK-7V*pcѐKXb,tFeev5aD: YcC~pJ ڌ;@'ہV[1wFUs )њ`nr()aٞQqVe-.aٞju}Hcy w(`#HjZaAX )ҚjJ:䧹aR9X=hÿz58Xz%ͧGZb(T5&SZ/عb8m?0t #k&5z|7O&j.ڝOm:.#Tۺ*2X؊x:ո}m"8k\ ؠ(EK9)ˮXTX X)-M'kVfb>"9=uM%PF7j顨t-U:>_}fY+~r yo^đ>5r/o](K7ެ3*o{a7L<5fL&3%^Q"Bfsa{v vBd&Ak9Oi%=v}tiH3ܧv S+L__HZҾ w6fYk*8gT| DLMS@|9i9'k-o0)uoRcͺ\f,ܭ˱Fmҙ{֛,U5ddT}G?@,{>pt@:~éϲP\ usfUOc2!߳pE19И*NoA{2 6 SkT t:,a4(|;8&jeP)={ߛxM@,vq=!2ӻ7S!D;2 mkhFqjTnM(Fsys(,vpr^ .A˼(z؅c5肱@¹5&(%v?̘鰴.Ӆu4,'.^*V+@cn.=EoYgF^NG^B鈃)3p`*-$W"{Ʋ$NJZ9XY%e':_uYqj=C'SI6 :8 b9*7]p$PqoˠއfRݽK*@Pj`_zZ\v2t7NǥW9pF<K:Je((+r;:4j)X Vщiap ;i,.2!LyshLL CiXruSČٿC@&g{ PO'KY6sJ֔on6Mc=C?9:#&ݰe \2arڥ(|gtu)NЅ貤`ڦXOxeىzIqaOe>u2K_.]c'B_"̨ʸ[!x֤%;+F[ZZ河tW _]ֶ)Y+׆?4W5`U:ay) NL8&N#8U9=gׅ0s8ijKaU @lԖjYe7kڙVoK4|g7ce -n/Nק68 ^bȆI&] j~>Crݛij-\k~gFjF?{N^6\\5whO^βV*JB}1tXw`&f'/dV?Cxx&z>{{7a(5TQK꒲U*ft ߎzt@}NG !3';ם; W[8 {SN^[CQ5N^~#$1A5Z>kl9$l PwׅWSp/R&mϊWbѭu%ua){3=I]4$,Nr Mz^f7ue+ck01nŽTdseB1;'K?J9#SG*i)gH_[- ]뀯8%({S3UqhB*2y^zi.fwq?T&ANU˝܍£*p=i1Ur߈w ΍dݪʑS95ϐfkē endstream endobj 611 0 obj <> stream x]mo8 ?FER/I2/ b=3kQ-Y"݉jJOY,Vտ|!,*2*ҕyW:tzX|{ߝ|bGZ\C'V*lENnѻluEO;You?|8- J.B&Q\XB>"kCkN??-* yg7QqA\F42\fE]~9e$Bl&q#nw_׮;hWDsI2CFܷhT0M{0QR(5ız} nߥQ~s:<7 9,-s_0p|,"WQ"(V縞=Z}$O#Qp^4ʗy}>HĊ&XZbWx%<[)^MTjUu!V@i)GhAuޮ(Ooo*_KR?w+bxž+U;0;{OUْ|5ߋ´6,*6e] n="wӭegn͉Moзn}"8!MNQlHhʑmaV =-XVqK,PdhOGy|H},SZuCMקּ>u"Ѳ蠈[S9\7m{JSZTSFW`UFX+%ּ)-yS/\{):D#8srQ8pIfEX4}m+ZQi< _F nۃ@_XlG|?YU|%YK~O` M; ?IbM8IP;2!h4qb 5IZD:+߄ kM!J.N)i Ϛ <̅|n81sD|F|W $1X:6+{*?K;]/-.FJck %q #T} ˢp&JBsD?EOs^]Kxpd@5]7OħGtͩR$xY /Uu/Ө`UA&uǪnC]=ˏx48D+⠷W JPg_"C)g$[7>G{3jqxX,BŌj Kٸ| Ijr /2x8{gxռwkxrqZL=r7IR x\~OBK"Q/u$oMd3}~li|8jA3kt;(8d``wQhḷZ>}4+MTDUEs޷@ 9&BʻT) RD |oGs?*uf)]GmAh/6, TX"NB -kZծ>)&Q.)(+ /S s@c4a|"2n5Uq]xwdN={&(:3cÚPаFU P)S Si#b}ѱw?_ې6cr3;Q-EI#W12`ZqN0M,X|IV^٦+IUU&"J͸:ZNZTjSt>8%R0MOJ,(19'0I5K$H$ɿ꼩ta`8)6Pi\8H]КxvgCPVpUlj鰪hD c[1)wkU夘-n*Gk)luǑs|00N/\czԸ|3M nCGQE1jOw:% $?UzqT YX{C fcSR@1+ CBAx`pg'pvaZo>UwR2eR`B ,(h2ƮS攍b;*I޷u-28\l]1&08y׏]o5,8]9l.uY HkC#," ;e vt@r22XpaS-՗Te1t24Yp@l)r7aLBgx619E|K,@ۤ|a9Y.jO/ڕPNxQ߼T-yQ|I6/,\Xp=^ yDj!PW+j -?WuN}T+R[ȋEm~A_Sғުk|$vwoo7Qj3q~z:7׍0/@>&f&)rN?Shr@=UWj_4d I!-S硌Xܮ%%vdzx7sG6~+GErR~(AQCJJi+T|ؿ=CM=Rq2Y,iz·"0u &C a e[b_ >pqkJ*Qk6iHq?4,wspit$B[}*Â=;yFUOVѧ0g9'o[E e妀mL41U8Ҧo+uX?"{AwmAPmmmmK%VʗSu5faH% Rj+c3j5Bp[D5>nM"30mϬ;VH@+퀺$xLxfo[ eF3jRo1vz.coR68[R7(Tft(:ΡFLF5UEIu7"w*-AQ\w2˱jNƳCiOpua r\*XEP6vU<'~P3,Lj醙Iy7f⨡4𚉃6o?~iV0[`Pmi!drևQp S,gn&=es(䘤_(b!¼soߞ1^6EUB\H~n&(#GAxH#4m.ܩchtQ}Up;#e}L2$%Z֏}`3du7u4Ҝv`SQֿZaufPٿh8hZ| j_L'gQ,0StbK?NNm\Gdx5'8ֵoZ0I%jev X37y9'噛3/Ɛb&9 [C!?8~F> stream x]o6n~ bU|JR?\ziZW0Q{._3CIK$KqHlkw)fHΓC[g*IBZ((?b"ORx7-R2OlEoћlq..U^ziXg[_>!/kO|$#;)ѻQ$v< i37bI!\ .F΃2+X~<&O3؛Վ\bjWjy07dIw%yN)<|^!×Wp}:ʡ 0N{0S~Wi*Į?JOSz7ş] oRiH))vw2[vg-L$s70Q$B-d hOޜ\EyKVp V y|>HJ LS qY/Eg `56x!g5*@g:&NipҤg Uzz#|, i|wb)giI/M2ƲȚYr9l{"VS>7ݮ9\ݷ>OH7}o%xq &fZi1-ȡm%Sۂ1m~k]zY1\,B$`֧BWYЛ Ŋ ,Z(,~ߕi*tzhE #VR#[ rZ}UX$^[xRi \Q! kh=#}8yI,ό]ks7E%;8HwKt_]ؚ52w|Y|v1~<9P<2lkc g3 F0VDeՓаOU!I&F BΝ 6 9 C>n8 M#Rg w40+)x*5⭱ r~E&H^>403]*>@.D eQm4~ @cp[5w+أ^a8X\2mjIp)q9v3qq.kdUS!a*sO)@6Ы+ ywC9P3q0']]ecK;7FӔc[z ^G=R ] >Gvq mLo9AD* Vm/Ķkp^b{ZQoOgZ/)ܿ:t (i;^"S$0xLs3?Ə'xf]}] IoI9R+94<~>1bnP.).q@ab~ǡy3CfrvI- KKS\4*(R۳8ZyP6pq" Ik_6(h!%<R٥+Ƕګ!+8N!hȍVEطo+b^=qsS;kI=C#|hiYװymE \SK_mz,FKpPse&5(91VIc[FA)p3I &0vN)08 ܛʍBn>t0́m ;pGnAU\7 [YR1|2B_ Oח?j!0ltɻެ \F`zH,n&m(azF'&GMo |鰚Xu.IC< ܸw?SD'$UqCIC]" ;F|2v@1#.ifh:n ek,jҙFNцޞ)Fᆘt*P#Z qRcJա%J悲$3 G &q6Ftmb;odć\L]^0^*;ĚuYA5VE"c ڳ9!@[x@NRYey;l_kO1Xz KҒU%,Xd.q#.ͅap4c%aM: 8 4Cq#X2C9oܮ<<5h.t˨pFØOI5mֻߟԙX'BJOMť3}Y8Ga}8D+0!zTi/Gokw2C'g7ֹ\BxL`qPm}gWp1Z,5PvAVʥui[ZtM: Ji5 Y<4TViM&{*y >fYED TUmM<*P*^f'I, jpxh^QC.tpx(F"p4p/_BU)T )c]-3x܂qqzN#mB*m8NTXyhڞu.k,"kVVE1SI֎t$O0l|pax(ဝQ5 lGX=фz{~,ýDX6|Zyڀw\lPP ;/%-0>d|w$p(8eUoh.*(my^+۷F;a*6C5*Ԙc^wL+ni,?P\Acrhk?͎Hv~+Ur8 6XښC]`sJ4 /yԩ{al<w_ MzFVa5jWB '>c}]UoaM[3Ah>/'8O#)ldx\@Og㜂IqIzY)]hq.k o:n]2&j*}kƥe _baì} /՗߼CSVX% 9\mtZ#kZE7EOr1MrMiy`DabnZ崀.ɣ{GQ^2sH*&CAZvz(4L\qwފ?64$\ \smt6/$C?:%|f{g -EMtЩ1f[wʃ1Tax2B։5.s7DUUqFU>6:mҏy~*Mj򈖋o$ nbUM톎oSB%hdUZե+օ Gյ F1:B{L'!rjAL(-Ûs߷ ւL$lązM 0W:ErxPsE9PNr[CXa9 " )k!O8y$с.xI*ց~Y]t5~1'>Z&9 epf SYlo}qq`uӎlwʑWF'ҘqioXer6 ӡrvELbхhJZo׵ b7= &tɐ^wMJ5}MOa)㱖<֬^ m. zg5SKPķBEy1[_hTp޸;栰X[fg|Suzg=@ C= J9s9QOΤlՓ31YZ۞iɞxn;}>=%8W=pK endstream endobj 613 0 obj <> stream x\Yoɵ~7Џd0tu-]1h "s#'J(- I EMRkEK-N;;vN˺7Զ֕nkmZwU}J٦}쪻լ_}M>%VB{[uV8B>"Z4Zvכ&Vn۽_o=uʫMOJԶ4&6;Sq໇5\߼hYh :œژ}h)O~ڦQ'B{w?'gnWiӓE{:rҫZɜA@qRWu"gdmɗ˻.֕bM-Ԁ~9Jֶ {lwʈf9fHu|"Ԋiv_dSF]mM2z>pa4`IRq)\40Bs5ۀ>n\ٷpEϞ C|KztyE-os2B8ssl zi;ʿMoQHMj3iZ9-ȩmB1оem G9Y >WԶMo!GmY'PX#,Rߗ{Y]%ڐA#jlLh[f 9u+*ͪZdjIa2CuǞEOt='?g=׾҉Li׏|O{ٸ~&4.{ڵyl-y Žæں_ ވ^C~C6h0Ma Kl|_ʽš֑f0е{DOӰ&Zj0Уٍ Seb~qr%u2Wd,*~w`.H7Nq9o2CBp~0CB9kjgu۞X4n USlf6P v\!s\b7u,a!OA{@vH?-94 6B<*C|S !o~A}u\:~ʣT0ckQcpꐔA"Le`bdprěсŨ:cm?.KdQEwߟd|ϾS;Mzv4(]JFԴ(k¦rGV}K>?ܭho ]=bΗT)5AwAhx%h(Ao$f@r8>g;…(i$sE,stՃa %b0/hJHv6! 3Ns>{"ir1x;v[!1@c!邌h9.9)m\'qL8~W81HM'ndC,r.!S x`fl69? KZz烔Beپ>_pIZul1Pkj9<&c_棘sUnE91[`޺a3-e+ yߌc""$;"Ho*v7@r2Q!HTG Ѭmet`4OK̶7uhnyi*tGI|'-(,lK`H"iIrtP% tm%_Fn_b\3,lDjGc-tR笘8$7Heb}Ou/aqYv֖o 9GXPmt{wmpfTNZB.tˎ^Ezcs)^Juɾ]?QrEmh?9B .Z9TKϘ`ybUJl1V=㚨 R xa ꒙XWrǢ6c Mm$kYt9 ut{6:N:;A^t 18ٸsrP^R8 DX=| ~kf+SQԺ^vumdR3OA#Ł bfi, AeM>8NGfl1r$B,*F=͵\)6QDwz#٢]~g(N$^8eB)ΤSg"^A65Ù VܕZL48șNB07̊/ctAu}sΡ6I&)Dfd@%4Ctji#R"#2ce.]>/I#! L\1גZ!k 9x(0b؏ևWX^cUoZx;:0vR,.(^%\݅km[P K?p93EI8=L1Q-qc<TAwitg|ȾC};$Yb>Cy +c }屿o8@PXGk9f_mzm3 9Ċqp4 zJ$\B(:u[y^:ΕJS 떴M GB|3 ,iWXj B" g\Q2Sj} Ԑ.hwt/CS2-k4,I.D|va!m{ /[ڛœTl"vWtϼE+uO[2dh"! el0]߆yy=w Qb_ uWkos 62͊11O͚mfl}O'਀Ut>;cdu+>0Sx1wW=w 1) n{]\%ưPXHP"F& +-™v]sΗZlmm|Kgu·o7 FIQUYȰTj!sJQ QtMGhHhyZtmROŒJwe?Xz`x+ɇra οٺsðYNRQ=!npCQ|!cZT~[HK;q=K;c}W'iz)c.M$!S;^1قkEm3BAbT; tz( I?9syG8Z;z1B2>_`>vG.=xi#QQK o,yyvb$*)mc6xtc̄")GRe!^v=˶:h~L(n*N$"je5.!WE )t --!\\LÍ ϶x_NZA}Զ ncQ1"o)RrIyamJ0X_?8~w@W* "7ĹߤhνbISshNzῌ2A9}s^\N@8j{{>h{>:t!6{wt;cED:&>:e%$6޼+Rx&T:n/ق0^G3IH\˖A'K,n'eW>qݏ\ s ֺVsBXD4~ŖA (~eH; i۽c XC9!x}}yȀPLH]1!u2K’1Z0B$ib2Ԃ-k=. ۤPnx4ϕ1T,!UBwf-FFA\lH!I&[Mk2{;Njܸ;b[st']Da)jYMړKo1uao|wrߙ=+>v;W :%5ҞSUifR9JJs"|$ |s)nSy<{h̏VNt< }ryG ;" EӰ;9ƻ&>^!. xtwGZZw|Bt+L$#pQqJQNP.ODCESwݘldjz5+zHzt( }؁PԉĝyD}\6Ew~RqQ4@l"Z'ū ȶÇ2(~5g⟸J%VVy$)_ jqoO-RPqb_y?9C UOvgkkKfF"o9,`ucg`|ȦuqP6/ ݚP8 ~'uN_ʏs1 endstream endobj 614 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 629 0] >> endobj 615 0 obj <> stream xc`` endstream endobj 616 0 obj <> stream xuϱ0_Q;ąчy7q#atr]zڻ×6ԸN|xx ɭ @>[@+2qn%2F8xϖFc"Kr$= ydˢ8Կw_jf@<"Sϖv endstream endobj 617 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 266 0] >> endobj 618 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 201 0] >> endobj 619 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 162 0] >> endobj 620 0 obj <> stream x\oH ?R1`[qwdv ,&G3soEf6X(Uuѿ<]X]tum[V)[=v/U}NY Tfڲh*{|dϟ-jϮl?g7-*SOUѵY*!#Z&{ws?D➉M[Tɷ̪3㫴eG;̍E9Ϭ 3d/7*uhULrrb(_lbz~vl]MZZWE3y [V Mzdfp2[de*Ks6UZ~%p 0>駭.lz{ h2ҙ¨9ǟ a 8 m3өuQ7 /e֙tiB9"<خE#Ĺ.rN%ǭ7h(`M?)X Q,0g mRNTyʢWTmSu4z:(h6%iý3ԿU'rb O?+89kI.?N\uܒ~>ϔL/o)&$߶ٴ{I𜟭WМ3oWH7^/>LFHejs24mG({|[@GmoI۟pÑ" ı!YR%QeVX nI'0F4",NߏjQsiX/ ІVpX X^LӨ &If`s6diSFI ObT?kqQTdg_X@t&*5\dp5G'7~|yx_+TEqi`嘡1MK`2mgݵtaDaqR(IR]&' H+fjGON X{g2vlUG\,=>[flmmN,$:{0яOaM&]NN|]cZi{`], vW_ z6{1t?αuT~ KB;\%.jDg;o3Lf2bDx?i{W78="aEF"bF!n4!(=YR{Ag^yreWK 8'Г}DNi m>&4A5Q @#UJDSUz@iL9!f$gthᥞxcdn'~_N-!qP9u@7[y >BXOBrna@U R}j-IDC*y$ڎ:WS6H5m0hy%^ MZƤZן74[0GRjԀLu`+T]#>Kڎ4EUmlYEɋ&^9[j;>9K&L7OK|>Š"*aj!/&ү@?WdQ+ aQ.XVDPV di`ԇ uʁ.c` =}D?1hbp<t6e28χO#7[P/ hǠ .`^Uy=ڦ{APr=󘍢iH HC竭OAHXsmAGNtM$L3]dk/uS`d{[EHF7o.P.o#m%<YSƑPDQhvYAE8’D6R$q-xnO#u6lOE&=D/|y):J~!rZrJХC}a'un u ɴ"/3qpJs(Jt;wHyȮyoB58unEvQ8r^oLg ]ƅKJ7KCS ObLsf^91{c0BCN_0uqC;vh"!*. IZ#jyÞD ,iu@#or')+;r<]Ĭ'l5w,rww}[^g*|!vE@Wd2U(tu zxanR4DPܱ,2z`!ٓnqW <_ӁR9Cԣ5nJ:0l~b5VHVse[=n_F`a>ˌٶA4= AeWLy!ha4dGyjnx&[*^U9D! >F.WM8lT#6FRSVbWeF#;B : ѩ 6B#DDHR l>]V.Qo,N7ЂStq&A;RZ3`NjQ&?vrYPXO{2Q _n?% O[ѹ>_fWh(Joi#T@7/숀hSHI(iH_Ű1ΓŐ%hwd4>HI%ۃ5cdI]`E\8Ϡ)1hUBĨu~uKN+r>7d'ncxK`ҹ +2i*W4B/4pm Y_9C]1XwN0=$ HSPp햛 >\o 3ġ$U@GM 99ukxb_N@{lVٖPQ6-e*NZ3!+QY!F NFIXeO<yfwKw [9x*BKtvA9+AʺԳ+[a!Qt_7ݵ3C)cZEMQ9>l^ /uE^@$Iĝɐ$ڴnEMMȑrGSٵ8e}JS1ңhO_\| $NW)]6 `t/qaGu"& ԿB")} J 'uxX"]RUa]؄kV+]f72nDq2NQۨ҈CU!$~}<8}TN@wv|z1VB bІ uQD⧑X8zQ WO 4XpS(4'" %$Dz %X梊BCȤ#$0!T56J#aeTW+EDz:*['aٌ\Żz);rba\tzOiBRs:O!UN{&)X\kUq=T܌E b$5f;ɍ=[v*ˁ:^KH UTh}_ܩ\q!hY,υ@ހUzӐ&fCZDMVVQ#C]PNPzsMwHt0R\) {;,/Qos]Z#atNdHow`EH=fԷNĉjm>r"ܤ+WOsÉuT9D{<]j;ocdv| 8'LjNB/1Bz"r*G$!uLgRɑR`F*U &ѭ`rH={3A& 6G~'BA$6] NRP1hӖ0kiӣNkLk D_Sڢ A-] &Y{ļEtozKhO,႓(OrmAȲݹN)gocr*""Lj)s/ZgB/%EMnB!/@WM1mcp`Ia~\/ɈvLX4Mn~/b,=`X?tST퟼"RQgi+]@?Y2FkTDc+88cYv第XרND9nSpi^J06KxP ¦X{ *7R'V\˃BA5 at|쐯7 )~;קx5xPFpX]))7ʒ 1 -M+褁p1Dꄎ#R4ORd8:Rv ?ϣech%A6lČ c4豔 u endstream endobj 621 0 obj <> stream xc``t endstream endobj 622 0 obj <> stream xuN1AlL* (PJr/pe$PBS3&:Y?HJZإA둣G̀_޸J9|z# h >@&P_}*$5Өǎ!Rߒ?cAግfvc o*v endstream endobj 623 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 305 0] >> endobj 624 0 obj <> stream x]msԸN[%9U1%hkU!\p^*{+5$K ,tdIeM=(ZoO[Q6y3Yy*u?|Ͽd?|ڼPT #2y5Zev 5EvI?dყ>y:%;L!\Y\4P;,yQQ R"o*BMv}iv92U: 2*> Gio}:ĻDsi`RM0Fҋt*7 JyQf>o讒*uUb&Ya6SP :z%p8حC?͠ܔ-@Ns-2l_PK7>W9>;\- +Уg2XRhhEQ{%<7ğ<1U.FM%jH.C^0`9"?|U-[4ù9~P~XPsm~.m蕭[tD!a 6C=2KKU.to `\!hK[q`aP\p6Fr9s'=8ڕ;[ݯ<ݓ`pKTP6$W?{zn5[Ka5]-fPbGFBWE 0o`eA~ҷX6`q-d4e kV58̳80X1 X"J;f"yj'_RcaN mo^sno]kJJ\na섗[( x @zà^8䟸F"*hd~fm׭`vWZٹW\p3d$BZ 謓$z}Mܡ`Dg-5_w(@{M|p]}s\NJnkۮ}]bxHxqW{Vւ\PHkjlu[rný[n>`' nƽԝgHArVТw)ntV"/u_{ȡ[|%rzвw5J0q;NŘXU fO1h(E!\6 O^WN"5v i7.2d&HƗߓa3Kh!kW{ՆҬa=P b1\K.3TFn7T[nj7/Ana%+pɚ7LeCO tQmLA:*16vF[yIJ[ r*}͏i?8\m:2# Z$Z3яMER )yҚD: NR; $?1eUc $5n't >S6 d$&"ffLp|ZЙoDZu^D_4AŽ*^"+i9d :9.97rUV7c:ע%3Umݐn Pjx]j\Ujl#z fUwUl hd)QT`a -4Z[avQIYDjbLhn1Eo̠'#B% :J-ARkpČX6mU^qd"ʍЇ$I ,jE)n6】!{k"׺<^ eT_,{*̽]\%ߑqQS.Z4)h 3%*èNT!:a9NC"W(E`v Qaem걯7Wpbqn y[;pVKlPr~KG Y!S c :8DB8{ixg ڤ[1_SKfxz!F8br|$}5I/eQQ(^JBZm\cI>wǢv뱬c4 V9CQZ_֧(+DSŠTP´! i7Zәo6/ZI]6vhָoh[ {RN${k 퉑mY".X鑩X$z芶EWȆ?΅YΛ[{/Se:JenB$:hj fxԺr6Mޤ"ziN6Bm8j6le36+怳8LLp Ԡ ̟wV;&u@BkfqWW+B$E&w7Ӌ@%L7b]J"lkv1>9 G< DaUXLZ9^a<8CN9@4xi;wO{ԴY{O s/vXS>5%-H AI3uÕ!I <"Y  C?rkWܲb+Z_SY<t?Snzݸ0d+7}'cLɥ2lcH6;8Iy)WLdghǕ!IFQQ#kV 7:!7k:`۵Qb"w`i;b7Iy#Պ-X8r18{BM kB9#ninj6 ߗ w`rqW\WybEyDHRDcEN[N <8B!Ư(~web8%Z k ܶ` ׯK F~ĹדܞT2g5x1ͬ~@)'xvYμ|LEGe.)p'ie:7?wz9P!0MDfLf, bY#/IWK2B ”d4&3em Z{Nh"(~I8!tD&ƽ\U Y3C?ۯ&_|F/MySɞoFf;jň_s)RS8"D&q!,=HTyprVc$)*,6ɛeKwl}ӌgܺI{I| ҋ$o p\ ecǢ4)j誱F>ٷ|L~$ytʼnYi`U㯭05MG{JClk;cyUx{1fюoQfۯ.^w5ě^WΛI:הO˺B㑚s"$)ӫF2!xŶ{'gӫ.\x )=.T\Gko ˖W&LpVrO4E$EFx=BKpJg绿p-۾iNdcF4e>~&dfG -oG +e]{z!vR1VL|s3}}h47k~Z]I-]/ν+/)۱8{UpnQm%#mdW}9~e Qa\2 _tȜkNW/9DIpDGt~3ol" y ߟCbV4 u[,mNG;v-Rwf^Lm‹7uŔ*x>*$ PWyd~gY$5iY44 ڵpњ+sҽ ΚSUdd@ѣ=c$wgٌgL:9P0hD,tmK]).r^G+QMR, WNyWNEi\ endstream endobj 625 0 obj <>/F 4/A<>>> endobj 626 0 obj <> stream x͝moݸwoVH nb]nNr_)ã365u3|q4ԓ~Hwc7}Cs}=nV7jnZ׸ij8wͧǏTs~^<~tyGݟ?YV\5ZSƍznhh_hVsڸ_JvlnoŗG_^{٫)kzM?\t+))g=ˡ^§kou;RW\C*}7O端襖h^2^)cYO:g̿[U߳pC|Q{cώu`+2jş0O880SkNukxÛ9kfqhHh.ѪQHKMaIq3o5 }ܨ ||V N~uQՎ޵〼 U9C^ڃ{?79x>> A(Cч?zkěvʖv)i;?r}oPmo_nHtD-.~0BZʆG3ЅSa#R:qQl #w0Z*u )0>?9e#|P֏<]۸Y27# J$PKyp@%ɟj~ X{~ > q@n. )uyYʭ$Vtj@vjHb5 CRi,:S02\ME+gm;jr.0-j'k9$~v q؎#k9v˱0Cg iY~ -ï/n0u="~ `E \NXH`aD0Nb-GB ֞ kq@?|=yIj^OzrzS9=dҝo(z uq>y@wk#M~㝍ow>:8gAvi_ϩØ9[(N!~e~U5VA,܅+IXK`=trI.a{& Cn9QԠn͓]!mn&@oR#z" ju/>|mW2@yXwk7q 9vl c2@S9}TH$8tq/ő%fo * |M#?݇S*7y?8n^545VHSjc>mh03um}ЧrD0vN<h>ߘQMY'F!(T$l9 (LvS X[Pq8mݥ ->MtQsTwL4֪gX"Ѓ1@i+ ƷCs)?uZ$7B(](ul:į 0)|}aBJCSrFO>Ȍ;lB,%Gpp%A%wi$;k8va7jv X[b1*2hNjDž\1]VF̚ӈjS9j+ @!Rɪ9fo& \n(1,E"I7ްCmQCM?FCu[eJ2J'ᦋtMq2cK;Y ).˚8tOtH$>\s)_@ /IPEw -iBC ҩ/79GӉ Ow {>~G( w$6X|Ƿqoޥ`qKr{,n"Ñ!-U@59TNC_H76f7A'<v> ,~$}+>rg(/Y}K=[\ V8Ir{{SKr{*l k _W]̙2vb>ye|0&uX#*4"}Di`hEai-8 Ջ!pĄBJgJhLaVtNgNg )1܆G7<Vs{xVg*YŎ8VvCQXNZYS0Ozu+($~MP3F;a 3Vd *@] [("ej J="EyE̞ROT(jiXUUsg_y<qŅ\,IJ54q-#'. endstream endobj 627 0 obj <> stream x]Qo6~7 ^"%JKM5S;?%;QB[^~Co(Jn\kM=tiڦnjU?{w]GoT)ljWaWz~=U]{_?N}u?&k\n6֛~jC_^[աhˋ˯riulbuЍ,V ''ݲkK7v)-rLm#uQΏC@ptrЮN}j;2J<}~@oNnCSPK8u+6fw6])e3(ei3m߳p.v(=;tw-C:0yllmşaPjVvеLݹj4ZpgNB[ju&'z<ykUVuN >gtOWeCmlGՃ}]4Q{C',4WKFفV?@t>?8j EX?pr=Dd7mv)a;q|б_zXvCveP|J_~> \3juxTgX?GJVrWbl 70pJG.3C$Z}W }0 mc@Yl`!r Zx ߼q,Uw!/OFC 7s!5EQ682¬>y 8|oO ߼NP.YP #O mf(tCLAd!л e5QWrHB=% ֗p:PQmlmv1]~ 8Ghǚ őa|Xh?o_!ȡ1jl]*؆@# qBIP;uti;ɝAwǡ4#1Iv/6l钿-T Z/υ?!]-J ah#.DhYJxn)ՂܙFn2VX)х$M8fktۤI5'mpq:ݦn0 yñr2*r9Dҽ#^od.&.?+F7v.z"4 ,wkh>EF_-lcI)lb 6u}nbJ$'/fJUγz$𼎬yi^3 in:3kX++ti+p,v56&eu:^;n$hBp筨'tMTNHFͭo>#>)AXޥ۠:gblƓ(!g3F#&F(-'1f#baẺ0Nq8chhl%qĕ@k7Ąk-cdr9="^E=ఠxB\> l\W/)]S4!v`@1J0 &HSFϤp>ڍ`A@]5`t0kZm4幷{;9lb\d1COC~wv p1oK>j|1q&N[ k-oT2Dݣ#@$aL;jM ZZXqP%OVD:Nr@ ={B [D (LVwPq[A.a,>['r( C6ܓ ߎ`:R9C DCڅ<gDٟ9AP}}ceA-f6yY\G$sa$TGpYo/sr:R9i D=;tSݳy.Za,Bt| -tMY`'4eEdaa2! ,j8MvhhHFC.'HoÃkh8G}iib8- ';2 !:]Wc%)n,Q0XYq\ifrY D,gAIu=x963'bFs CTs )cHQf<]#Yha1vq.>+2@$k ,H׆kc#:U>3wӭ1WVD6i~j +%@$Z=?Q5fHMrk;`.`.\E͘ 'gl³# ͎TNa١rRiRriL'ܺxr&,$ IBq >,ZeػB!fzɫ+Z/,$0^f< # hr DBCP#^饳X;[2-,Fyʷs`{9f'b [ vTMP4Aas++e+#-[%J]ݧ* ~)s96<->C-myjQC'ӡ@$&ʫ#޵7O)|<ޝWp!r dH:lƓ.9MTNHH^'$j ٟ9|V;BXpkAïx, y%0&[*@dk|OV,j?x7j; l u4%]a4:#ly^Q5XVe,ZkeX1}\z ?3SaObA Op~9+!1>kBA^]0ކ[xSMOnSsIwzy‘=dd :j1]X^ Kt{{]r9I7'&j0GfrZ|M-|c I .oٟ9|VQȫ9j0&[*@$d3v;иVã1>14; |a'#_FB #WF6#+lH@WS8NN D_+0DXr{ D=F=ù\Nxfpx/ቭ|-̒l|fs99s ջfƋuuyX9ݽTNwHPִެI:'&:0GGfr](` pΪ> stream x\[s۶~g"wj ;gRMsrsmA=EV<%W]HZM"v @0T)DYeV򼬲pwfݝvw̲:/dvvB2YT<;D/NU6;^_;GZܯ;5Nicz2TZEQ?T+/4PwT4, zXFҽ,{?<|U 8x^&42/D.uJ؋}mP:+{GݾdyMlɏiϫ&p˗ ZJB/^12ՍPBHOY?(&R sPG *YVJ~wm8e`$J,F%[#L#&e&+ J.!= p,uNIPOOWr*_F|$U4~cժTh㧕"U&` :(hݙ !Z UE.M;EgAS Kו'=L6UgKBA9+RM=k[g :JE[ޟ5ޛoL 5[쒥zʐVWEUԚzS7krs7@<נ7>ҏr(G&&BSU"VTZtZa$ [@{ C:j# Mh$kҨ/Doj{Ҹ2VXLh,ЭZ^7KjVhPsF;^54hzP%;(޻1CP5'Pf00gCx0CAS(Aq2YBgzAg/0.A:-d.`eW7k @L}2/*O^j "D!HdG$H6,%ꕑvQ8 h&F_CP#R=='(~ @ Q Y&0r_ sOpY69W 0FU'z Flb ac냦mWm@H)RP[0l8nЖT7#\;K)_-/FJ瞜f[c>i"nr`9sڝe 69G-hu`(6h"d3459VV$ آkg'WOT$ofc(otoޜ>򒛷6Yf4 ?Xw;XCG@|BbԬ=0-634l= I ت:8 qFU^31mIkm}fUK]O_Y'wd,U ccJf5ф,qXIaeiXEHR`Kh(V o>ZP1-<8zk=57 X2IoG@(M *8*.$y'g%^o;71n0zsxwL) ڱhk+܆!ཟ71<̣uO,vh,D)xW ،G\ےzJ2:z:EHR@L|gEHRk c=6m:ل| (A%+34l= I sۄ+&>t'>KQf>#%1PjpU?u6(b`x/Ca enxdhM⋹ɵM&c'bf3Gqђ]X+w1|oP\)xӇ< ]mډzډEH& ^W&MxP?)>gpmK)4픑q$hb$)KY拭p{^${JIR0cN(0z6I1`*ޣ4)Ъ0)I _Im> zk=5e X2I*[OI J#PzL6 |\Ip|tQ\Zy{Fԓt NPT$P_M,_PE1\H\s;_ѧ!I`ɏ(ɝ – c4)]KYE_tZbnZ0'x9aGc%3bǽ1 Z}C&QǣUeM\P՗W\ KhX$.ϹnӶt$e5'|qxm6}R8uvBdES@:Fv[XqkNۛ-B`oV#|C۠wr{O y ?.1Wh3|g _O\1vK8hgā'q#IA]CXIāфm=9]%8<"I嵴64?R(Wzx1ac5d.?5E55 $  [O#(B j*js-\M N ۾vy8=op1Ly|u֣Χ]$-|Zm$J2N,Y#(M T*eēTB0"ձ_vXi#6-(X09("D)p(GyoD@,ښh_ii_!I,KQ_N[x[uߐYଭ'ݪ;Tw]Q/HRLs(q]?@jRcj] P*ouvizq {E 5@ ;Үxfm@xbq%36[ȸ!|N+|p3+ؿG:.|wB'n񃽹E92kC F)jq>62H9,l\*[@Mp=AY$"Fu.FĜk$帆KC7AܹWLX~ 7qYf)Mpqqz]ͧ%3T@=VI6Oz>3񴗵@EdX|{;sQvJ{510l|>5w%gsKOp&:1ܻ&|t|xܝNOܾ~f洸 ړw! M<4|m= I |t -JNLϫX],wщ?;ZWE]G- nzJΑ*_+N{(&P5394xS Gd2 ŗP|M-a!=׆рvMMˋ:*smr0N l:b hTԊk-uT`STE4˓Y_NA2N{WL<_ў8mP#kᴒ:iTE}jʦ쨬˴-rcPvRm /.д-4U}S,;٤NҚ endstream endobj 629 0 obj <> stream x[o8AVDEaIEw{p66[i %JH#Q3ᐜ͐|z"Jk-sWeR\guӓmNOߞ "SMfG zd˻ӓ"[қoNOM??~zyf S2w63VxEI?R+@-M/ߤrP쩅i;.%Ҹ\ 3%̥N, 3j:SMƧ˩mJN~]Zyu ƈ\〗-<_=Ҳ@ |bajPΫjXrSz1ҿ+ WN+z|EQ [T ̟x8+1r?0X؁tԙr"7*W&xbYry["(tVwoG(  Sc+[)HzCþ:J9YR=UWPUQ޵m8i0e3Tnߛ('xjǖTMDmwYET>}|75?pLIUYot5-rK~J\LUm7@Nc| ;ԛ)LJӄjpmF CU%GBKO c45:ᄣI~-ņ֢nQ䶌U_Ȋ}߄a"ƺ,zR%4ŝM$p\w~cfW!ĸ cM59 *PIo%eй|"eH^/ݐp| o}K. lqk[8a{wjC# R=Pj3 M3F&5 9br]O䢯Co:2m05WdgFR~=}X}CXTcRޱG#}ItMe3ވHe ,и׍zVIOr3o{l2*`Ŀ/pl9jGֆu/FG/h<ٶY-T*w-{|ku+ʦ-A1+qm~B+mJ!!vw MzDM{[亣ix.P^<"l Zȅ;u= 8 Ra!-!_QX5ѾSϽUsW l+7h-+R:oͲYD-}_plv)4|bhV6Tl(*!;yyb޴'G6. 1&!h}6~N[\شO`wh&?aWlf@;6ɱC>HD4꜠C,B.s_0 H5Y|&RwɵgUc$ 2ylwKЪNEW"5|fç"KRpTaTYHĄQgc* ]WϨ!3@[*Tecs䭦MEdv=Em6j2hʟeHIr8W~:p~h~À_a{2LQJ mr_޶Bz_G9w>|AD܌ G_MdAS I)r-F*\C^.)S;5aɁO+)͇:<5pV1ae5eoC?-S ͽQ1di3(jl7 H07Mp?|ӨFl/xa͔͎ {74{ʦo@4 f'0?f/}' 1-aw,dKSXє#iM:}}ɉ_>>|yWqMJ,"`.4>W頙oh4m@GXɝilnz'_X6&UtFc!&ŨČT ||R>53TԱ~_OqN1 axJ!E9'3(LRbuMr)LR 'v=HM*@5**RT]l>_M %lܣ ϛE(b\$WZ%3;1M0i&Rc1 ȝxlit:Q!MJ~)#T 4J̩BfeN7YBg!+sS:Kri s*.*} *5)@z2aSݏ|,u ۸i4&E{'pswԔWOS msyժز `$&<=y~o ٢HgTm,ٛ}&>`4x3 ?VQ4L/7&1QY|O@\.UqhGa ǧ$măܴ?C hϸW@9e\t`QPFipeACz<oB-_a_* dgZeޭk::[j@U5-_fdT]V4.e׻ƞMrvV6a%4;0vڝm3}ա[Jt㤗JbyC6KQ)dH:H^[ۃqT{kR+9p xL3 X4us{؂,3% _Roi\׭>ۨu +N} OA,I?|5C,_!gDx/a\ 2OF;ڽ~Ŝܡ.,:q ?3H`Pݍx|aTf쉵M ahYݥE :aFl q=΍ʊ܀ߖD;]:Vbq}*6:{#yK N‚TUWl,Ulh2}n4c{;t 3U)*(YAb;&V yOC6:+()V2]Z_vLZkFn犼 ;H!YqX#aμɥڼG yHuRxDPڶ4aA8XZꎥk oG}ᚑ87R;7qᚍOvp'ɾs۔N<|^p|[}Xn1Ux$5(#M?} wh_Te-)z 6vtMe:>/F 4/A<>>> endobj 631 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?4=tژAan䞸AUf?Ny XֲtKYgh|ɘ۝:;cI zhX䕴TwmtQx{@M~ba``Acق)1ށ\Ff}t'cv@#-0*nWMs@ɴ۩w@BH8컿.3G3W5a-dcA]YH9`c` x3qJ%ԥ*G#H= dQGBï>= i4~FzluϪH$l J@ L#"f0isߜ~b;[BHd q9enyIJc⹶['k{E-'[\JM14c!Q]eOp1LeHd;3g'sR]9I!w0(K8QO?캇S.njoM##B|Xs ZZ[ UqgdQIc욇SCgwt|Da{ o7I t\i5g>})'utPa5tX[KC_ao-n_Ͻ7=OՈHc\OROZSC+Ȓ G0V3[هji%(d7b[r:H >V%rV#@ s߇ >ԟLoZPE4yq N:iC}ݎpr?@ԟGړy~*kN嘲dsM> BTc и $|$rZs߇ dTlRʠăڒ l$ S^S0.m66E&$?1U8OQYW:֍q%MJRc0FC| !U;05Eo獿o"ZV٭uvFQL89 b^/"[I[ #Vꇠ<EG, lvۘzm^[Rk9-"V @)X}nKO_jO?I<R}F9ž,_@ml\, ʲL# YO|m$`O'?Qs߇ ͺRBF?!9<=ECɭX|$R&B6~z R9jO?vg^yy~6zg8ٜ{__Tb6.CLs{`ړy~(R9S!;>cTr=ik*ZOEhp 2;v@ԟGړy~*:ãE}mF+klr1VԼK ;m$' 0q9#k?¥HD9VjV>ܯ!pyS?m\ EPEPEPEPEPEPEPEPEPEPEPEP\^twQAEPrV#Y7bZ1$Sa~F  rG/427y2$c#b ]4?0Ppww>gϝ_>|six|PG6#j(|j*'ؕQpg qkϱ;G}ߥ `r'#v$*mʮ[8<֕_eݿhSv12/R0eX#Ii٭ cbA2G t5Ty0 3?p㎽8ZP|5,%dRX}[, fGb0՘J(ikt1,cn;ڤ>S5c?djLPD(9è#4MkxSMezdYa0c+ #-˒c0h _9aIӊ/Qc>v€9SOØ^c#L$Vt?o~(ϱ;@ޕw~ ˫9hJq0p}Fu"ݯŽ.[lx>gϝ_>|rnμ-Tm!ay'b>nk-NvnP/=+ϱ;G}ߥ 4y,+[xO0` cר_ ;hn,sD߸J۾PmҺKgϝ_ hvjos>bƛqins*!V?/Qc>v€ (ϱ;G}ߥ (>|?o~(Kgϝ_?/Qc>v€ (ϱ;G}ߥ (>|?o~(Kgϝ_?/Qc>v€ (ϱ;G}ߥ (>|?o~(Kgϝ_?/Qc>v€ (nU-vQ,0Ջq׿~( +_1䭉?s_9+bO@jEsQ]Ks$0yDlɜ]ÐFJ?kTWKy16$jBsjUdW[JB`8S=۴aC DZTYܤpUPGMӿ/}XmHѝ݊TORp=7Mĭ>x1n8#iLf%ӿ/_)%hٙl+|w'pG?Zy4M;ښwu8;$gHXPd - aܮgη/z??ƏM;4F+n\QR>_SN_N23IdjXSȠӿ/_>;x^iƃ,xSN_G?ƫY궷_SN_O}Mϩjikhӿ/SFhhhđ: 4ꥧ_<xП((((((((mKg?TumK?TtEP _1䭉?"irVg]OzCCG% $387hvXZh ;"E[f1yE" H$J 2㢙:+3l-2Gjc& q#ct+J(ssw@+o-F eCpR}@]Kcy-Dp,8= 4E;Lh6I`$8Կ_m~P+qhkh$"ݩQ vw{wGw}+xtkItH홋bF:w (κor9{;Bdcq<`eyϨ4=40Y#G5țafF:3:~-?7 CKH4Km,>n-I'qni:*dXtv@Τκor (?4xty?7:~-??iO (κor#OG::~-?7e+4O?"O*,U?"O* 4Uo0~$[0~$ ?߸?EV ?߸?>?"O*,U?"O* 4Uo0~$[0~$ ?߸?EV ?߸?>?"O*,U?"O* 4USc~$~?"O*,U?"O* 4Uo0~$[0~$ ?߸?EV ?߸?>?"O*,U?"O* 4Uo0~$[0~$ ?߸?EV ?߸?>?"O*,U?"O* 4Uo0~$Ul988?_ 4U$AĨh OJ=vF5d~Qֵ{/j?}_EG@tR@?Jӓ>0?U8EZpOy]JʛXŲʩ RtҒ +ʭ~8LOid-5ú^5Hl>vQTmTepŵC6jʒ "~ by%-l!PFʒ$3۷Kڰ^Zwt!k{Bs(:Vi<њoG3@oG3@oG3@oG3@oG3@oG3@oG3@gqZ w 7cjbxGoVeITd8eEfMlm羌*\3dpkf8ARX;.D־dTSp{(ЭKG[Ȑà%IEG/meD&VY?x 3`N0\Ǿi-4\鱶e.r6:J^FvwVeKۑ3?َ[]I8qW@7Qڣ2MoFhMoFhMoFhMoFhMoFhMoFhMoFh{4 f#cN'JU3J'J@icV`;o?_՝|lQKEdjCrU??v?rO@jU-^vxt$4uZ>/i@iYCʪ'OJd]ʲ[#Rpjчc:iTk3xSܼme)W~炌O۾=+:uQǠZ7<k4y ku۹/¶Ifd;si57 fV))O-J/U;=V#'_ѬI'/]m9 [>`p8$*CqpZVim=-$x `>[ hy+KmA6*H{*7Bŋn.è/D >UDrhvpsQ@oF!?b^n L7 +9m3ךަ?!?B}@G'_ѣORQ@ hԔP~B}<k5%F!?IEG'_ѣORVG-tCEUaΚ ?!?B}ㆩ2\]}ejXpFG`8vы["kAm=7d8{慨=OGF}n˽Zq;y8dFnikEi)j'B'tlIPUy>j |k4y kZnK6Qw|!$ջ}feOK%ebȐ%Urr}Mtqz䌫2Oi=O1Kh9˻#^>S w}l3Sq'_ѣO\\uK~Z"H;[k]G]\^=Ҥqʭ"*,X1} . yd% $xނLLy0 %Is\phY2yׂY&boL},bJ@_ۤ6Ǚq4-;hVxRhd#q]$$0iB}8ԭ܁1jӠk4y jJ(?!?B}OGF"#k4B}P&S'SV괟%Y V봿17z|_s]эTn*:֢/5vV.s2Vğg]O7rWS'}YS5^ֿ{]JUWi # s?( W^ }sZTVPNropȋ$mgk8>+RFCpBā#BEUDm~wU]IUV(((((((((ⶌ R<$ԔQ@Q@Q@k M,HU`gu J(mKxdiI$$֥((((' 2IVj%Y V봿1!-kǹƮkSwQWJ**(o K_Q䮦O@jB9+>/Uk_EYֿ{]JEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPi?)qBJUO *Rs]э\֧! =vF5sZ.Ҏ:j(9FJd?Y-/}G?V?ZUk贠 4QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEVB?$5ZO A\dВ+o?_jJ:micW5B(( endstream endobj 632 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 634 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 633 0 R/Group<>/Tabs/S>> endobj 633 0 obj <> stream xYo7aW&@$kڸs(F)^&5.%w83z\I免ZDWiU_?TfrO 1{XT5_V&4W>FO@歯O(ћm]Mn4z >z'|<%*)OZ*dR#YW7w?_lPz¬ 6v~i"~](eg?޼dhMx8ao3Ss*m3>]Om)sO~I/uJ3+#7}KC+P 3YeaF빁/kO5Y̥Ncc)4t4^Q8JϐdhF9r #RxϟMUZYITkt/fF(.%c-1S*"B1 C/jU r0,N_N[/q/D o3 O0LM}/?M}o~/#S𙇥-ޤїnU`9[ҾA}Q;l ~n!Ai>n3jI 9r,v<-TiV&&,.a1N"Tю@/т!XYH8*~nV YH~MtFަ/ 5iJ&C{A)i^pxw .(`㳍? ? Q#x=B "|ki7ELA{x{VoX b-D+V$p@]&@A@wR4Ev24M%gH6O-sW V9xW,[4ûV1s/gƸA2\0ؿbIC\F&#Kӎ]ڴĩN29Ii kC1s%TM,ߺDl>xIK&).T&Go̦_Td4iɷn08Su3mY.=Vzi1/]x+hJmf%6BuMF&TsЎlS XYY b\Eht{OpL/AπԇUxf]^OSK|s&jx6[l$)Mﻺ dY.xKmur5sZvG+68}ttIx> wwb ^X_|%sTkzy?؁F5Z=k8],d ->8AYN|,Rdm (L8!wTlzhia&c~\ݻ/dgG1x oXGl*5Ni9 ݄*D|zUhVZUBK%aZ ld2VǕr endstream endobj 634 0 obj <>/F 4/Dest[ 45 0 R/XYZ 130 416 0] >> endobj 635 0 obj <> stream JFIF``ZExifMM*JQQQC   !(!0*21/*.-4;K@48G9-.BYBGNPTUT3?]c\RbKSTQC''Q6.6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?-iV^5F7?@p=hsUiSJnױܺxs1C _&&b5iloŊ,X/˜DqOMMod73^FB#&;_שRyLu THR8|v_NtƥrwWXg8%8m'x8G=W4?;ZKtRZ@ `Zg'Z͍]o\D?Jν_9@ 8M,I("G.PN9I46F,rrz\k-̲b!n}3ߊmyϔU>D R ҲMe KuI PFG$p@ZV6QE ( ( ( ( ( ( ( ( ( ( ( ?)?qBQ ZEPXXkD :8HXkV/ hGӣdb@p 9 Ҫ+fc+=T A)f_vtP"`xk" w<3ޕZZ!Joxʂ'?vTP}ig{,u͈E*2H$u=A˂rğk,q*,*!*fmm%A.wđ*`Z)GmdӭVg]1z"tY:6cA' 秨PX>swB V% gS5v $v{QkY/ ̹`G_l}MFE1-Zd M񰔀NTH8" (x,/Leǖ뻅+A ճӖ4Od*£2/HW+8WVx#*s͚GӬ!Бp#0 u֊ӴL& sHڂA8u, T1lT"g:_;v6{WeEren.T!rz/-V& s>l עn?E 3g?pG۬+Fun?(;}~h YQ? Ѣ3g?pG۬+Fun?(;}~h YQ? Ѣ3g?pG۬+Fun?(;}~h qKɾ)E2#5R-lGR-W(_,E`5]O"_ _]5k@QY/Nڴ6?6ɂܩFG$A֢tXϧG=Ħ9<ǒ8fG$dkige (BeH?2񌜌PPVbdD)9bw@[QY0evCweAу? /T~;s*$qnNE:=Vh2ڱ\n0pz?s4h˟mD'dfXC1sQ}gKO8>hI.fQ ?s4h˟jQ\\[^$%YQ 6BOilgx''=hh˟F\,MRִ;%y$Fۻ'1Zu]9o퉄 W99 ?0rehу? /Ut:Fڒk@sil 쑤.A<ۯ>kF\,M0rejvp{n(,щT#=SKn0KU{P?s4h˟赸D[[8Rp#2z18lݑ4rH"3j._&?s4ոTgh`NO@ ._&?s4@ ._&?s4@ ._&?s4@ ._&?s4>-FT-ZrUn'<ԷĔ8ee* MTmuKL"ФQEQEQEQEQEQEQEQEN?赬}GB)kb?赬}CB)h*"_ _]-k\_+E`5]OYZq]!k*!̨ˏ&2G?.pHj@hKk8d啑NGQJ 3$AkLՐ`n8"w=mQ@Zd0A 7TLo?֕P1{ E2 uyG#<{任6HV7/yQ{zu+r#O\nSi?|EP.4񆀠$m16N9}dWOV1bW~,v|خpyRXkrEc4A$g凙 퀕vGlFU&tVQ @8LA&x0ICK$g82]tEON Ǹd6χLŊ#$;3'yW3@774fo4o5hIѼy4&FQG3@o4o5hIѼy4&FQG3@o4o5h9vQ!\MڍڣϵϵG3@Ycޭ9n,oW)N?赬ˑZCKZqEgL3)hh6@? _[wEcB?≏Dk@UU_S2<^Uh)?qBzpOڮh6 $&g!Rg4+#[Rh0`ӤyRx 8ކhT>Zܣ<ޱ^ҹz{OG=,!B:A(eD 湇k[%-`g OA~Gr^=%wܦ-(1}TsS!Cd`: dƀ}*0lbe07sY{ 0f_*<>:|ͻK\K}͌-_dBɕ$q Niy14biWVSP VFb@7, $T`sz |ڈpm&KonJ|~Ty14_k뻦|eT>G!ݙ=xL=3ɋyGOʟE3ɋyU'"Mmm;CʀLY̾D|Α^RA('#zh Pc8H$]P}F:G>91Ku?AϽrǨ,Zy4\J B H}OCPysAhiN0mb!~s9݀}OjKP;3!K]t[%+VPYpӓubvmB]B8xRH͌s1f:RgOúG2^7&8䎝uطC[Io2 l`ʦbiW$du{bagu$e;yQZEyw^E>D0Z~PK %A9cl`v&@ɍRFƲF0YpA/!$XvlT[{73^KkhDbrNv@v^L_?*<~U]K V{ioNHFX>ݨv1.0YYK,3H8xUoW%g$4rIl"Vi$EWfPaOTL_?*>soj$iڑ15@O8͚M,7+>w[%!0xLLQ:VYDQƀ;=敨WVE1ɑ_nzg+,loby#(5 ofo3~n_-ܱN[\0VoESRE o.UЎƀ<ɋyO<ɋyO<ɋyO*\"%Ş ALޭkEY qEQabCKW[y]Z? Zm&(b+h?WQw?_"r]k@Z? O\cОh)?qBz]&g/$%6sddF&~jz1j:*68(q/EQ? uPUbڌ k}gY ( ( (#naxn"IbqI2~q U (!ɻ,ds5$QG IQq @N ( n<͋wczfEX`2T*PԴQ@5#DgdERs1>S((HQG@S(((( _e]zUf)];*G?KZEsP9h35cD__+V/ kA19@Zh5 '1OVj=Y((((((((((((((((((((((|YcެkEY qEsP9kmv-k?%/r@RQ@ endstream endobj 636 0 obj <> endobj 637 0 obj <> stream xeRn0>l !HP~1KTeȁGX2]Yet7jk;XUpt%k:5~U_ tŻyt;YO';ź[|;wGc~=(s@Xyj9QCZ "rm]>}{NBAD9%+"8I!ɉ|ASkY 'Dn0$흍/S[dۓ y^ 5MMiB7x&)QJB+DʭHf o!IM vqeh<>6u`|[ư endstream endobj 638 0 obj <> stream x |ǟwfvg#lv#B\ȑ $@P x#jQgR jmkM@P YjJւm*I6-;y~=ﳳwfg@*5 'NY}{jM}5pON1;s64sԆUV^8qʲ-߄Onl;(`?!:{p_̨>TT,ϩ4֥ݶpY늿/ZxJ>3W셋rv,{Vk Hpg=뜋ϼ?M-LYTJZW@_"[X~ ˙u%8b7n;\ }_n9'Ld<^=Z/ZaX?L_4ܿnJ֢hV_ _}.4EE_mק-J>zߗ˫ZC_X!sV_CnVIswKoL.i8V(B/DpQ8ZrDH 1 ##A7pNZ/9DCp)5> b|+1Jhyꦡ52B>Vi;̥i(_|k5™h0NeX~m'1kX7/ĺu6a>q}yx#xh1oWhW$R8 cS걏*kɳ<܏8/c'L,_y/ԂD;A=)3>nT?c='z|)Ԁ6so; >ό `0CTɢ}{|e0UB[7 `0 `0 `0#`|i"!dV EӏHBXcD Fo횻սk Z׆J&J27h%<A:6)Eh4FIj2( ?\eF`0J1%\g^ P/sQꥰ2Xz9WWJԫ` PjP EŨk;KQ˰=p#\z\z3\z j/|BF>|W z;F] ע`N.Tޅw nB]7 އC܊|p6nW?PCpCԇU܍܃u]oA7Gnã#Mج/1 VUQ)oTPQ > @(SG}3> ݨFe6GQͨ//Q_ԗ` ˪[Q O(k.`]-$a[T}F}A}U^ݪoaD ϣS=x}x|G[?ʋgx /~ P +/~xߣBOx3x_;s؍~WO PxM[95􏾶8?&׿Ԛo5}ښW]Uꚾ5}^uMUoZw5ߺ5~]Ngk:[ӿyM₩9A zA <D$V9*ZQҋV zAϋzɠ7cYW$JL4qDߒW7U%hX|Ʃ)HΒ>.0 1 ʑq F_iu`6W~y0R dЙ F :b\/F[8__%>6eHʟA+:Ab%aՈYv`0’ +4xVkJ+ʆJ?bK S+J|NpAڡ!1z)HΖ1.0 1 ,bC3<6W~y0fbM 7,LH+ zAk Nb֠k:iр))SR _9T5\hf y1v`0aZE#8̂(JFId`He5k fl5[-fĠނF Z `nm,z9)%SU#WC}3904? 0wFG`0Z`pEҙiH,JhGDjY-h59lf5,nB?be -)f,EfL{m;<@X|j9~^:Ԃv`0a+Nw[ ծ VI'I~$jZnOIۜdN3Ŏ1fX Xhhfә%ɁAtL.>U-iX|aI x]`0 c@ؕ#VJס 6IT}Hft:nhqXNGa0þV(EHVd273)e[V뇊-(d hr`$V6.0 1 ,bCX*tN`t :΁A8n3Yv`vNg 06(ZEC2Ug ;)e qi1 C9Grurl]`0 c@qy` EC+\_9rRS])Tez]T3Օq8㦷vWW.uԤ4 +0re$i _1!LNzDzg?zryi> dc2|>/`4p03` /7L^ޭqbE㫀:S0)%v^XW9ŨC7o]`0 c@qy` EVrz͑f~洴4?Ree=A̬`2tf~Q1@6U?~KVϥ fXƀ _Gc͉чis#`02ą%1L>Q/` sU @Ɯ! |.{AxX\GN#aĞLmGu қ_ew]=?]UR-w'P$`4-VݑtS=^?-= 3 3:aL4;'7/`laѸ%&O*2ēOv3g54ΞsjSу@hqR4X^M`G7=kٍ'M(-?plA~^nNvt Ypf(#(>'r86l2:Ij#S"#-q!˥P+VQj}rM>g {z=c=U.6$_ =d&Xjij5o|05rȵ),muա6}nt 5`." f8wmY {C5qOzõ3f6ܜ8^ZPUܒvju:.K裁宜7XaAKqQhQ뼦8Le5q%.M;kSȴywfӑA͸˅tNoX l8YSGx|mZZӲTBUŝK[van7Eo 'Bͭ5uFOLݒe%lҗ1̴9;?z:OPFOBJBR4_ȒZF&l ɝrtMk_6lh'dz(=Ej|N <>7.Za13ض6|}O `!1)Qabql?M[:o ᙼIUwƥHr.. mP̹MrmgK߱o^mœr^gZh2ƅ0hՓzQ(YyJRf}0&/>hѴj?Z mhԖ}ww_&S[yō6'i3i͉nenc%iVN" ;h7nt.|.t|* !{y'8^W3# ,'&[aS`WD Fp}I^xmmz1GmhѴ\/nq{{,;6m>zmhDT+6]Th6>?Z0ZwɄ-j&;/eܾUý<"LPgtz%nF9;poe huμ dh-h+д{sC-h,CN^ 4{^T*]Kܳ#"=sOo0Mt'Lwz* 8Ɗ|lpޘi(6nj>dhnFr۸E;1)솏'pXO@JlP#\,N,Rt+D{D.sT"\9*EK1G%2w>D7b[̬@\i.ģt! (]w!sh]1@V8E:'mrq%('gl'#F:#x(:HlQ Tұtk6ԗNrF'弲uM'hF;p';phѶGSд;YU j>dhWGӪG`y9=e䂱4ߚmoK:s%SfIb_@Wnn4|"nKo<-C<t@gƴxK4~n98 l%f:jss{=f??xCHwwXas`o{$y}!/l=^hBU$nƪxiv}̊d5urS3ƹ5*CZG-@m>fHu]09u6aJ7HKf&|Z|m}CSx!(ia 9P[|B-|[,ZW479j?'ϘO~0~ K~w%q<ˤ tj?~]홵5]j jv|da}\SA+.~?vI]j?].ש3pPS/Nlqby4j նį`qjc,w-l"- .ik[9V_&yyb 66u͋tOM 4o:c\Qs]?׸߰tg\SK6OsйJ\ScSչ@=g4uIPՌj3|m\;1zo+^< y>hSnen%m)du_S&+VBUrU*H]RiGj*z>VArMJx>>fDk[C3j>Qe;ҺrZu/cI,f>^Rlk)ތdCs;;e\՗;+H~CVv[;Vy5?|!M.Q>4 ]OY6xQ` %P mp-Ś`nxM }"=."Gp_QP 3`9HNVV<-\ %p2 +HҤܤܪ<?-sW`/,E寚7!GwnrQ,8Orz d;{oH*ƽH+Oa/?.JƓ\P3O." q'-bPPrD|<%?Օ'Qe9 WH[1j 51%.H0)#+g)J|mx/'n [ǟ8Ew4 k*f|F"C~MLHeN"}\57!M؊ X7I)IN#ɥZ=r'yB>*Fln??B­Ah\^OϔBÕx~nK4@̸$Hfv9O$?#pW^$}J+-|xC/Bxyw72np>|͏f~9zu- n{q.Ԭլ<٠yRs@kWѯ=\{&e89W VܖϸG5bc%QRAN#3,%瑋H~E~ 87~U\736<Ľ}N>OOZ>ο"腀!Dla0_X%>>"}~ NUh^Gހmv*O QIF{ Rw;pt hX2މ߅>ݳ55! ^PB3u]@w)j׀ %BnVC7K1A6 b@ ;:PUש n$4b>Gchl^޺"ճXکv#:ӨZ:o3 VcjI%vJJ_V|^ԄMCvFxL3h59Eo-[ّR  wy|$I$J1fZh"&tVj S.FnbRX]XW UQ]1h8yh6c3-%Wß@Aڊ3+33e}}ǜ2g .d;2ILfQ ʊ,6QZkuR!nO>KruLYBgAYsɅz.&.J*څVWZ-Y6"r+ Pr=a>aɵpf+ OMOsy{QV:l%[}xAgӟeJ)&[ XiB_0_=u}z3. ;K(;J94g:ۏ M| Ǯ}rlaؓcoK֏_^(vK[_N!U !3DAA%r1@K`UKl>n?P\8H6#B6f)&f׳zyw9 ل ɦWvs<7tlγ9hPUgWg`ܣr+ f_KCYD+"0*# e!/vFN F}2{gahBE9X=<4ّ\"4(`;KKx.!';S24Bq ǽ]jϾv5W]~> 7V5\37# 7=c`g?a7ᣳZ=rʂ7=3; ?E_yCKɒa=3}94d4d9YA2=!Kd5YZU r\{#{I[ CN)!S [ɐ,R*H, /ԯ,Ǔ<Mkd_$_ť\3~ss:u'q)sZI"4KęXeKxM⌊ ) wxvCc@ΪV [ae3J-/RVZ^a!JWx#2ǐc!%_^?/~f`@) +s뮟{⛚&O0oOFzi]'}x[ ˮ^5lk*Ǯ0Z<# 4܈ !0fcI4NB;ixʼMd"苊r #!JڊKfn7[#RRƃ1cت1.VW"|U?_յݟ78%qA|[Ou᝚U:~2]Mz$9Ly3зtL08bM2mfH,gt:s4/%ǭE`ك.:X[v&|j߽w dG҇C,qPd^"3&>f8*yQxE18JXx3B®Cx- H;K?suұVeC+FDh+.Bqg Ke2t~VQ@n/{6Jn^Lw*㻫 į0$fIXgLPYRgr c'8Q׼$;cX-q7r3XݸGP`=bAX1$ 'HWo1=ۡv޲Ӏ~5E%.Ɓ#?O.Ǿ&II5)s 3~n#leq*׃W|ܺgR4+zruaƒ$@ۚ!DH Q4j?ݟvEIkg>I1JK>'ӯ ;L5υ'CЩ&uI+(p3_11GFCDe]eѻRu9xWbBhaClHaWGQU5TM;(w$=X18f=ReW(ezy-W3w_'m4iMGu:xV:i$ @3 Z u?WZ&| Cϧ9Qcym8i_RRN,Yα XVXB.\y'R8{yY]k c)]2UF[*nRU\|} bwCVRVr@WjY,@Yێ ;U=:)/Pq81nIz$C.v={7IŠ)cOqД\}3U-Pb r;3|KE!TaRd2i/d' |C}U `_o\kYn᮵#=w3\{Xw-r=|"5PʉL,eP-EQܜ̬R9r1ӆ[qnRqaLlNfhw`бcmū N ³ ^b)AAũDKncG>yO7Div(23c5 RtsTY8"葨}5ap2{;ck)y7hI /н F0"`오Gga V9vg8TmʰX1}/V0Y #P`0ڌvXU/9|LNO"sPteNfѝݺvMwQl>PMy =uʩ`$>H|Tר92d@*w[;c\28(Fp RD!ـ8Y]"Gڽ-MǮQQ׾KG /TW=|MWy_M{k}Em 97`^&ꃇP/ˆLqwH*g\9Qʜ!$50kDpT^۴$!/>gW׈5Zf..pܮ͖d,g/籋cq^&9Qظ!yZf7t FknJ l@{rTC`3XD6B8{xx9ztVҫ %v1xS35``5r$#4 `*' uuHf_\96ri-]ωgӮ827:<1û:!M$Lli OϮ࢞.io 8s+d0.L>UypzSEGVriy7lZuVȺ~ZO(_SPȇ cK|LՂ06bkk5Iiܺ{Rd}̀R?]= _=+Ner33<&?kE,ՏfryQܻoXL7K~M&K|h~-}jѧWg91*! h Lb 2RTCɊ)+±ִ_|mTg[2W3fx+!yG,ec[9+2x1 cB 8 XI:~[Se "e a+ƈ:f++^( ( iƪ;ْ͊1.c?ܠe_ɢĤf\c͉lյ( @lT/ yyAr[`J)VJʭXI/Rvdwb9p,KΊegkp8Ƈ{gRkvl'3vɘ.Tz.fXgHR{祜c:d%"&!y{|MQqڎQ=pP csFO߼87xgIf']5ȊVj$Tߵ &,1y-TitDu%mTgT1d:ݼS^)Rl9pIEƒ!m3*`]skT)RHB+|LH6c2ECSD:r69GD[1# mTUH E">n{ (KZbΪC<-HYFP=O a;ͣ T;QIl>6Yd].})dܧt=#C3JkH-^GfQzͯARv#pG:V!9cr4;s&;~Y/Oȓi29>}QFf ّ ȿs8/H!k@97dPd9酛}J ih9T]CɁtFu3^0V_O咽pqRy6ULU#aB;Or l×C$$K^I3zvaek.|}uqru׭N4m5$i&ӑvɿET*놌!/{32щ=ɌLA lɀq3h }XYAgڭL{f&#вquO2pi@Sy_x>۞d`Ԛ:-!IED9H2#Idڑ:JśPM,DX8*nI*PiՆƫvN9gi?ҥ|[SՄY2X =kX#eֈf&$`&|yЭE?}dgF@]`sS]A7KN젽zKrQƩ10!+|фq$/0F9X}Su͏ 7~Z2#e#eɷr?ZJ,=x8O֗ } d3D\w$+"r\%3<6g>rj"eaav١ aԋBRڰpn؟|\No wIf<?m=ˎ\\A^]'g5?|7Lk}hꛖ_hIx%۰Y5pK92[wd"%`MVi6<`d χ _hbR{wuRǓ͂5DL 7WٴK"PR1l 0ɁJ‘GȏGt |[׋!h<@0!lӰry\R%>'7g/lcQK5BmA;Wt4} ޡFDdq99]MFzwޯ |ukgźi=3#,45VtI'v]B ae]0bf֊ L,K3+09 (ekN999qTIH&-?0ecoz%j>N#),Jœfy,(lFgN~F#5/~omwuÃַf|p>~$hC4"*eB|<.P^#8!kͯV/sH2}'zR79¥Tc  J6ù9gf]L9ssK&0I6I2O9NeQ ˈ'&YBLV2Px ?̟9~ĮDASb+Y+f}wmca|J: dH1f>;Y vI{?Ƥ>ۃʚdiV_gt/ j/TZjb#YHpXcM'o}Q(g{=0DV#*e26Ʌ;z԰Y8G?B>bFu;O>zr] $Vh%/6pIpT<&vy~Sl@H%*HsIBJVn0+HqۼM&d2[d"Y0lWM{ UaV ((HJ _ <-gJLr؈A8L捭2bht,1e[/mv썲xzf0t!S%_N} gbC{)15R/HF^>lzo>* ־acSxoE:WS5كZ*?x+p4 /0 1fGbvỵ2fOg0 ɧx0I(JDT2qD] |Tս2۽ddfLؒaUwDD% JD5VT>\(-`jq)nEJ嵔*2wι3!h0=;2xt4cI0 XQ D RPj4Nja~^ӝVl g2-g.d\h!#YEc - пQx 3EI%A;o=,5ΰ&AJ~8qjؓ27z~fKa z0(Z+`<Ey| N(o[Qz3*$^'4= ҴN{$S OWU4 -L꓍Y,kJ`j~1R)o1Q&Pށf+pH,1z%DK"=\?Tb?[c/b߭8g5&aO\Voa϶w???[OO+_|x$a H?sj}:[!,b]=ǘ!G=3Zz$%^/B,[~ cĩ%`NEsRaM,fqwNV>4Ƈ=/xg1Q]sv/x1=G5w4ULZjsu들%A՘')c^f*97c1d\6-y3YCa?6RcV Ĥ*f0Cg&鄯*e#eSidЌ)ѩɵ~^v3" fhcU1u MR HZ>`c; a"xI$.j1 #YvI= DZȪXz' ^^_]{<ՀBMkfVߧ,b-Gt^PPnid9U2?{r^˿u)MO-x' ƙșVeV{~š]#>2;y}6B<|(KRk@hFz~A0GxASh Rqd+;Kz^R gp?ΒszpF?GAB$5 [{#ZvBLa54ah&  Dօؙ%>3(|`2iRl''"-'.KqbP9/ƩxkAeSpz֩.l)nYkCjS[m-u ЂF?cet2{ӦtQIBʰ;+}{߼VLu7M7=)ߗ3>^I">ni{ -j:|.f%7v}FM%vuubj M'SHnLȐItdjŽn MhA8HAbg(A9Qq<1@K I 3#:lrFi2_3ǺUMM]__XI'ݫܧ=+7\{Œ`2 $+aNT\tM$1A2) `| r,*U(RGd xQ)oB% ϱ4E /X&=c) z8ALM`!h,lw/7%$JP¶+WSUj= lG\W![+|ٱG1p \\6uΠ;2LdVE#̡C_&kk sG0{=6"l|Ao~f҄'6צoV2{޶13zo|-ML|7פnsf7yz;g_1xײ/94/u{m!p UA.uV^`(3-a|?'E'qNфޑXϪu깣:Tq0~8Zc|Q?ѷ3>+zԦ}ɷ| x%-Pdw(5Ev"](#w(vC1E)w"O9 pRDS2Wf}Os _f~8~ZƟk_00X.r_IWh;Ӳ'$MJPV.. (\|TC [6NDDs4 /V]ЀH+;e9J( (OZPqWv$$/ :M/(LO~ՆG}>_vWͮŎ&wٕ0O"+]A` 5$ RnF V=1dF"G0-Lҕ\T&]:NB8 * `=/5s\KxŽO\Gw/^>O'jwO >txtN4($^nF:K J$! $cBm6`qk]W -9#ݢXt u'HEʔG)($  P;-rBTl;EJfO->A߯S:|-F J 9Ը3Hg1,`^TMCZYyrrt:m7|Z A( @ɬ̸ q;'Q4AO!@ӎ2nR>Bh8,j$.DI^шD#mkn^C#./;7t,@˟qRY+@۹:0ͷW/m0ܓ{RB8&|%yyÛlD TWYXj\P*JsٹG,9eDqEXB]$  ۂ(BS -[+mU$IuxAAlzSOr%ɅBDZUg\эs8ʄnWNxL}BUm&tV!DueAt!3X3O+&TQ1ta_qA98Ɨ 6aW'`qz~g'HJ0k܆$owH4H%P oL 2Lay!`gi8ЂH,+D L1+PNx*&̱$q/]?Hp}y& H ;+(qghdP?LK~T?͔72Xqp 2_U/Eq^SXX1dwgR< D+bJ #7zzv?݀Vc7κ)JRgqh&Yr2J,l>(EZۈyˌZu\wq/;, xhDVn(҃d<yN~7kfpu~SN5 ͠SmLcuLe`+Jph!}='<>/FYh/>xFդ~)?Ó(bFTuU:CgG#Sͩe*yMV͚ǚUys%Y6.YnUR)U.yqw3ݯ! mBh\ -kBTy~ bQ]Tt8$G<cGh8Zdŋ^i6Ō&&& BP=zo7pYo3CnȀë́U'2%#lK*d-Qɬ*̼a h 5CNV}.um׷8PDCZ%Z&4O;KI\h3$X3y[_xDnCWqk6~f./kXyϓ%wM=Q@Lf3c ̡tY47JVtɖVvQ*,-"g  5ah@$Oi 0j Y€A- N t4R@J PkR R/U*(mG_C ,LDZxQabm+G܅]ڲhAk ^(+-eb==8ʿ$xƁW߂~tB W0P;4I}BGBgh ^Gwp 簆Ϋ67[. }9=lr7S?U62yd35Y*/TZ-.aK}JSRKgi7kwhoGMkh1q3&c~cTR}"#X:#LX&#C~DT&qؽr Kݢ`wM?LԢ"ѳG?AMИRtnxK%_PߋN;f~fւ{ >;n οo 1à̎8p0,PJ^%^4:#0y2ÖDRdvd\#+ɡ0TqrrwQuTIנEJA@$uYi ]?`ݰ&Հt1PÅ,A " 2C3nhƍ"#@PEl+2;uq4xX尟Ž*b =-cOzޢ(ゝUX䋡3vH8={ǻKsW}v-]V,߸gkݴPMT #]oWl4ahg^(I!B^g0YCgnH7 OQJ4* _Al ],42tkArv,y ӜC" imu:9b آ7]ֱ ǴaQ!bKRdzO(JoS X"Fg2f# J%!c`!,#̋DXtÕXhcϵ /U41g0 bS_< TpAS`DAE7zt랹`+n^ E Z(v#oPVRlwi?@$]+D%S7M<]n64ALoPS1RH~V \ԕ"! ? Kb’8`RD&6Y"F"Qf+zܯu*딁hP=  I\A` %y՝wE(qEJL[C^͋vBر~;pײ1A5Wٿ隖aS]OÚ]szh'RC@7Mxg4 %j).HomVLXm6&] \ݚݚLP<ЫP[|();h AF/k#ZFGm< tbV[j}OU/!ý9厞E'-4u@LԎr9ڳRKn_m`ٶN^m˜6ǶmS5g v??(km=?˟6\EWk~M{4ޡ ?5ڣRO!b8$ @|8l R$n@06w (Ps ~~v7;fz@zﴏ\>ғp(S:Q1AcI9gJ"q꜓$6K'ཛ0{*#CėqYA`TYK @Xٝ4j.lcXXeݾtaJ"7Z1iMrx˾Z`&l BDX( >1"IJ`eXZdC 6f;4IQ|FNLNFSigz42"!=-;ޢmvQK YYN^:!ֻ~=w4`ӵJ1yh7<2m0PbAn*(I "5H% T U\(H¸2MIiO=>  ۃAv~ Csp>--Kr@Ga+aK |1G>c{p(vD:&Ot;|&wdOrxUeqaSe;鑍 p)b..h0L1^.8\y㬺us;/sP_|vP|J?>sκYz0QeQޣz|.s֧*q Yι$mI8ے- T_fg[ζoJb;kcw(N4BF@u"ZmVE[YaogTnP=jsCsWȊ6,[/,ޞof~sĉkݔ1uoo}7^Y|31N{D*k09Uf 0v !!II­ww]ٓ^I)o/$3fx<ZB gW5k֤jta,= Z7a B@)|h5:/oc}|5-c 8:x]Ib?`3 >7\VW=27n~hy.[.[)LǁހېksWPϿ_{PU(g: 4}=^B A!(H$Qh_u7Yj}wm4,vDeNqHǹ^qTϞY@S)nJJVe-ᨯq0PKf^}|xCӢ;hNP,L{])F CSJ@X+~J̀e]$jFQjy]R)et iGD8KH Zjs֦h%8–{ _ -ӷOե؍"=E\л=4}g2Gm_OL L?aLǗ-Y4 ZIϢư,!\E;7^ҼkoZ׮HI)̏+ࣲVFk*GK+pK) gƬ]84771~K;Ur%t 9.sz חr;1MqY[ݢFNk۵}!MeSEH~5cb(C_v9,kT:桫wLӐE;a|jt&ѾUeLX0hÆw ~>E5eнic&ʠ=w|,C愙SaPIa8љ!&6,%/-UN'2hJR,e N gj'R:3tsi5rQaWvrr%tzs7)ѻo ˇCNGN^ K"0;.59b>QkE^︒uFa|O\ܨݠ q{x==fd6b311XƑSYp#;T$~B\T)/-`ԇJY0JP]NA !K/Ģ2C<r8 g~-o7 fP+GD"ypi=hߵayӬiK7}e}ȑ)>G`5x6.GZ%нW8sa4U/v.?67,&/xma_?2C|o+-eӷėmڭ#O-.GPt6fSGXP iYz33q; `2!Rkx=_5=B59 ӝBC!\Wb&^&hr:ss z1S d\##~/s͎8}v wӵ4$J|jѢ4k/٢s)ZaI<Mρ'n3sNww1}ybv!p:z%3iCir_9q0PI6C֮r 6zC;!6B5sJOKtػa[֫XKb_(g`wߦ=[6?1Cv(ԟSia2@Ѷa?y_ݏvGcDcם}IԞyK+ix=mzyS *T74K#roQ!)%p79V<{ݡۻϾOݧFR3;WG:7;y<\ϏƝ'= in_|ļ0͵'OT?z}r%֞ +;nK^h15\9Jux3<Qi3Ջ#NL,'Κ?N}& Yں:|A.5%MWXJӓ]N@宜r w-Z^dX:mSJTagt%0i/eGtzmd>^YUY9G %⎠BCJ|\@;-095=5]ǧ UZv_w776o i<ҿ7t E(;Q)AgV[U M#B ,uWb F7^:vK2  ilxwfעc䮺P"WOԱtyBi cir(='MR֚=mb2gCׄb.+7r=hezExYn 0r)etF~/Ѕ*Ƨ۝ݫcaNwv7vNI}+ٶگ]Z}3Oijijscos#O3q(SY1F,k+ i~ȱB.S?ǕPomղc].2t)K=di;ig}yi?[X 9By@ð$g.4Ty3>.^pi3{0WWΧV Zߨ λ4&X&k 5( <>BYh&8@X!N~G'P:YEa$s1rhPQTm5+MM?E~.f5:Q_V Y.2bӪ`Y\I& |d+%zUtNJ]BXx:GSXëch>679ٳkhyf6~j3m# /rPaney`'}c{y?)&ħ@r1;/WlnOx/ƞg~y' gߖ=|\O_HՓ4>^_< }ZiO2`UQY6/S[Qy,"%#JXWZab* !c7kIK2i#cBe>S#5:xgJL~ ET+JkS{>^SwjݎZb`=)vn'ޡmmk6> NCR{]ÔҚ+ɨ\uk_zJ =\g(\^n_V0ࣁ w2s>{\;tiq0JkK?7F:/̮0J-Ƥכ"Wҕ3Go䊌:_uu?x}?3u:_u^cuu1Ul[3f ˍm[;nbu,)E y擻/`X6\?r+"Бn nGz?'7qJRHr%er,c>P(|X6ɕX1Ŭq'wr/c3M>h.[\*8E2rЗx3 9gSp}3$Mxors)N%)djn$I|6s]U*HnY Ox6(Wp%ah8)>j l(O`YM<&ng#d:~|zR. vl%.J#fDy\S; `vhᶤ8vZ<|kli"Ά;M|6.א Ι پpNX-)2͞g4-.p7moenSK=@O}pBF#\&wX24qS&nM-))C7eh Mܔ24qS7wo]Ik9$oZ1A-Bx()~/*$SgR^&8}\7~k%''J w0 bHd(+6ձYk5B.]t^O1ր+f l9ҷV_ثV#H+S*@ѫFUl%šXyVg$CܵZC ÁR=[Mx.i\z VIv v#8 \K9ɧMz?!Dr!l7JOI~3#~]e(g#7A{W'>J#^q>W  H,KoYjtPɛ3M:kv,,㮙0q:&1 ~8\Z*K)%ܓLu!(լGM MUg ,zM45!+mmR̈SW|l6({FhEp74lS>:g:ǔgO*{GhUQ?Jkʫ,jD66vmrĮB|+ d/ Q% sbiS)uMr["o>l*w/?6:=fƤC 9&d$0]LwX=?OW9/p2DuQaBY.xL6fkXݶU_mmv;~{1aKeG/^V2^"_u:u&YHouz9\mvWeB^ߤma\3h[]wcUQ:??~ g`J'FNf^LY9|s-/1|y wড়:ϝ Ϡw 7wbǸNg;=_bչ`}IMi[rFgDtMD|}1*}Zj} ܫ )k^_ zo~}@VRJd" BG;8PyGΏ,{7(,E Tw*ʒN.e`wNfV-eek њlJ]([Pֈo0>{Feвb9- s $;{9'q@iҬabr| W+kFrȽJzro r w/ުVvKzM!UsHi8x5Pz - %Jei,eLŲYoos;Wm~F 6[6vva;Y'ۏykmv}Nxy%gY2iv*-N+ɶ'-{Ү'zzҦP2WidV;dSHd%b8``zS̊u=xc}FH[PϕJsȈ=$̎#=PYOf B"+;(6g{ rb @{UuZ'Rd 4 !&@y(MxuIc`lH?~6 -qLUR?-cZnb^>b> )|)| }a@@07&rOgՃjԗЧ/^ŽRs}s}py\CCH:&#pG Ŧ@S $l/_lY!lW)x9AR_:M~z]C*owRbw H|]ԁwZjb(v>!s/(Y@uBx@m]17\5m"Q:T"Q>د^AHq R%DHu"Au)"A< ۽loMOL\b⍩H=`;bs-!ݐER a1D*'rg*i.`1!xJy) Hy\LųG_ <@ `x酔"ĈNq QNPN*0lNj %/Mkb1[#0HsڨpI=a'ʺ mtW$zpDNPqURI}FE[#(TJS$eI| lP>W X"0g,` ?z YavWh`9%ܬ /"tL E+r_gCE(`ŢPabJDbDFb<+.b&ŗ9b.$CjQ.ubhf Dhs-׋YAb#c\V_;{2}C_N^> ^w|$4+0?`|0)zΣ_¿P 0 0VT{BRڷ`}yUёQ[}'_EW?ҲEVWGѵF,:Ykft."Ҳ%e[tq z"w6 _|>E qOޏ[ѭėߌ><:Wѷ ND|?v {i*Ae8/{ZjHp}pmFݲ -ow+klˠ%얌%_ka\nDzͿC%m_t.;_$GȤYwqKo%r{7n~wSx2 TgYoioxk}X\Wr/n"H)HSJ))Rpm)%Hca0d#1c,lو1"M#lLi1M#MSĈ1҈Y=gfv>?|ysysg.);a{#8| t^ %?<i`u=5."ԧD-\eJ*jZC>g[[>uV;|ٌm|e'q!BV^t¼ov(ڟ[lݎa;O̓kAՠ7#N^L$:bS`0"e>'<e61\e46وba#>M:m3g[ Q{s?l|%*񅸰8~Ojly ; `YlS[)\8~gЫK"Lȷ;$mf23|yA7Ew4'fdD AC(yy20@2x11|0JdJ ӅeE%t̗Q+WQ5kA?l?o2By?1fg|6zT|.z=T /1QbG̏P cHü> y }yyU2?g~>μʼטQ 22o2oO2b~j_3Eb~Ǽ$6GOe* }fEY=,kdh;[֢ϱMcsJ5f<+2RfdcdgF`9& fVv`mHeYuv։vn֋>XaUVE_`lbCl}@ٝN%FlۃB{neE}v ,$Uvc~5v?:;vB0;dA{#;Ža0&{=Qv}= ?bFwٟFٟ;3t}} }}?g&_@/kkE/Iuu 4ɾɾ+t5kS7o[߱C߳Gξžΰ`~#:%mm43z8X.En{4݃^˽]ǽ݋pCorshr5.E}JQ<=O%%'SɉMaKct9>>2>T&'Q|2ŧ)ԃ|*Jei|~=t!>ϠrL> P\>z~zB/ 2/+'J7Ou|x4oT/2Uo7S7P&o̼Rodo[Vo۩FDiߝ3}Ɗ~lzJDЋPs{{?sppppp ppp0 ,=#P.nkQr gn1@2 aߜF ЎV'>@݇6*T '#' ԇ:)4.9t-S1Tʦ*{b'OB䖻Kr|(U{9M>-;iQE>Y)\'%dQӊ\*=@ʻ2\y/!{lyP)r^ކTl@ɛ /Ye(Z.\D[n9 kE+reZ.\=%g5&YLc$ТZH#rjkV\7Cn%n r2krlMdQ7=4_üQ` yW>BV#+ ~d?Yg#_.DN(K+?O< t|iw.?] TM@ B[LΓ[<Α[|KP (ݚd-i KedZ6Y̖6`B섴˲Dz25CCXƀ*n*a 7? #"؂#%og1H yT@ !.ҁR+@O1KdE@v~ " iPO[ IgrOd\@Ҏ#u= Ѳw` i9@A[UD?c`Ί>Lx#GqI&u;&J\cCі?ԹcuP34B~RivMmԌ)uQit]6ew?Fz(J52sͫHvW9%dKRyRtݮzu~[ 6)Me~MݠZ@LeѬjc)fҹV*ݜZLy|4NUrɝj+NޠP- F: t Wu4.Sە%w AoS6ln#XU{АjI ꏁ\$*6'AfiuiQ3mV%]re}E&9n 2H7ǖnV}ܶ#P?8 [mvN>hv/m:mS1)6C&h |Wۨ"5nVnFn}jM }Ew?hOt;o# uF9 l=8zF^e$:^!v5VS*Fu:\?iI_OBcg0m[XEO ̩v- I%nK%M@hȕnymX QE;ɸO{G ʄ<[n{t6>~{A<@Kd/WV+BF ^= 9`~_xKaq̞K&0-y3`X8~z//t_W{A׼j~[?d_V@.M>9QZU#J^3iC˦'_ző*;)G׫oP<;{wBFq#Ӎ`]`)w#ǻV>̩jow(pP U֠ѱb(́'(! +ݮ {$pf mA?cY ̧ (rPs(T<+;*`O Σ>1$:jCҤLܡ9 \];g+9KiķCWMWCQazz:mzP MGUX;}IjwvOOǰ|{q42tù;RmYV}T];OwV}rGtLZ^gph0DTm:a Ƕ #,E`~5ֹ\츤b|GgnL ,8 J5r 4M;^q6FTඣ;!<{vK2/xfzFdԓpLSF=Yfs嘭7 9p;#yɋ|i!= FD0b]{ׁbْ\U$ƹqtxK q+W;8 nrVe>0:R,;fcey5ױ uQ 3m>^΃ J` `c7 ز L]!Oc$i`t߲aҒ!i8 ٬J8F:ʂA[RGepc:uz:>Eh(2^qLzF,K]7:3 v%¼NCtNV:w'w)|zLwf:f4^1;7HKЦR pd,Tf\˝POh |qfݾMz;50wPɞ cݰ]9Y*ޙR_Mꍄtվ5%U,h?,6Y7,NHheԹ<t\Fq}g;MS9Ŏu)tbDgY1 y.7z:[5"=N݄nv5}bմ<0)aO}\g? =!Zm-Rwtg\9:>FO8:fEt$LiY:9!%L+ॅ4Ba(yO`.=w^O a.ҨṣK`?p`iOj?8Th'mSCq)we3rWFX.|r%|/$^A ҕk JsZ#> ]?- ??1ptLtU)usgt#"ȩߵǟݵɵϟe=5 z+51B9Ĝy uOPcs؇pq!n{2s/r/R2w{zy,G={/c3x||/.+{/;S/_?ZRoĤСĔ{L{6~?aMd}_^wmX~u#/" Jf}~ `kavT{L;ԤvZ;@ qB* YB.~i㴈Dd O#Do7".KM?A?֢{.6K(62Bh+4J"J?KCh\sz%%͠KDF YMVm֮jڝ]=}vL;=Ҟ՞^^CyM{C, x!EX/d 9PeBP u)QdQh SͼvN"mp.,nER[8-0( õFc„pUNçiaF$\~v㿧PkK |02_ADW!}*M }8a$>[L 94=[[6~"M쓱S 0_(3 k9gv0 8@eYvA-ho B&dE!O(RBoIh v =!;uG1=#k@:9hkjkOw㞋MҖ R1$ 7G<裱4) =(:sP] Qu(Y@/n1Euq$*Su%ݪ5Ѥ>WWdJ":7RW^ W}GrS:K!?\z2]ʛFg?cI\nm栩i{Mۦ流w*Z8ֈ~zN_ct,a߭\]K)a=r;Xϙz.,orִEF~tn,=1 OBYl:O3Yhuy 9 1<.i'2R,6拤]D/t(0o"~/cX]5߳k}jmZ":@ľܰX^"!sCsoܺZ_f{[?oYѼyOy_5@ P_wZk8nZZ_cUNqGcbt'9ʗp;싙N)-W|X{/.&io>TE,z mD֡*HI{)!݃& >gFi/n#;RR!ݏNC_FPITz:wG֚3LQ͙5j.̖滋Y(zbfffsbL͢ &+bQ*fC]^^SvX  8pT+ĪֲI 5sGM5gjΈYk26臤'nLvK4iP8̋ p\[zѦVg f&yQHS%c O]`͜X5%Ϣ8$ɩ jfˮVp[='TlRL1`ΊqQHQE(WG5!^矘KbhwM.P71Au)bh.א;뿂Y]]]TɀnP7эȻ Ttp~PVX\U1OY<KzPsNd^WӔjtjdf)ЪQ\G .uNIO)u;̺>faaaaaP!zk CĚ00$ c6YfXs➲il;6ce7$}OΖ]/i#Olw`ݔ]T@2Gi*Gw <8=8=1Ĉ~VTOL>1-%ۮ d}!͐AFhava C ];O0P ?촡PeЋˆM5 fl%CX%)ԝMfD3H3Pw pE7}WOw]/Uv+=.b}>IOdz(ZndnB0f坸bmd^,a%Cx z]ߢo+z^z7DT= L}/DW/f8vi^~ɚ9Œ=Opppdh5\p<}bD[ +J0/3dcˋ0zaY,0"#g)bţ nzc1G47 cX]Ra4댲qCbV2!:X'o3)U'یd-|gΣ;퐜|! u. H! BF B:ɂI-㞊k$ 2C%?w߿!!`Rj?RL2ijF1EDD ED:H UDJ)HRF)j1" bDLM!9=^RPۙ߬Zuw}s$W&xY'Ϻo)7IymoszGo~o{p-N~I+=vcv򍴺$tlwe,>w1}KKۚ]gk?Ժ-i>srm&c'M-i}<*rO~ ?-uIM[ލgL}-+.}(**iguZl=锞>$w삍^ڇqH.NE_2B}L\_)MO(SuqպsJ*Wrň4>y1Bb:[ L{2W /Ocreiy˹fSyjX+?*PqeW:jum^d }h-}Ko#YC9r|q֧/^&ShwZ.5%zS+yS.J68OUl!Z+[.P^?d&EI;]yJG&Kɼ2ŹPtN,vq$I>'T2^ )T-4Vh$)BӅzSG9Oo2yl]s2}nL?[1T%bk}\Ie\tt8g^{Oד~{:"RIۚ-/6v |kot{/vva9*9 \ H 7 Uxv!qK?TW?ך^~n.KhB tO :gŬN6ByiTS$T"KۿLhW T%4"F q~hۂ& M3Kg*S:򙥋.[imڶ$]>tyBk.Qt}nZ:n%}*^]4vm _˗E)riϷC.!^Hg-߫Fg:H? y r _) | dx{[LOcK.u?ۊ9֖=$ozHnhFW=$z9[( u;>zvն/$/Ȧ_Mn×c7c¼ɝ|3&t 16L߀)/%|_yﻔ_5fg@01z!`23_r{dlcm |:ϻ\+>c/VXE}iyu]b;Q[SէۓXx>] uZd/&~LU|_z@87 _7d"&o7;w&;>=~isVM,3]-̆]68,Ցj]^+tR Re:u9u/ٴճ̆!lYw.jBya~LЯ7u{;Vh>wlׂRԶ*wM_/`b]4$A ֤,Y;s$Q--1>-wS&6kB Ĺ\?7&7OP˂ܢ^}ܲ܁"+ʭ̭~DhqY;Q2>ɹܙblgg\ԩ$JԌ/̮8,VכYBsyM iW`f-^g9x3J~I}suv^Jvo|' Rf?j_+o4Q&o2c}>?$6GeٔIdU~_еc#,/LxWIwJ# O[k!ym׎2'#&3&DݓsQ섩l.;d˯-dLG&hq.-f{XwM0'{:pk4qiش?.Ni~?ͦh1j׾V^G-kPu&,|dLv`6ّ,Dv~vwiv}ȇʖQ[+_V(z 7=Ul̐Ru\Y7RgVOM7eOH[7|6(z8UmB9i$ [XH2$UoY+ZՎ_'OBh\1ݡv#;Ld;ծ)d-ѮI˜%rO$'rDnDqٽ=Ԣ ՖZ`'OeV )WFMƒD'95m+O{6;lŻ&5B\tPWwu7эY%ҏ}32fVV9"cn,݄do٤!Z?nn 'S[RNYfh2'J9+o>292?HfHHHHHHszÄd5S-$7s& MquӅ$ks;}g;ۖY$ثmle+k{mUtnmGضhvLmrۉm'R?nnD {j Kɯ*Mi;NpgtxxVzirXr3{;˒srhNVѹ`ʣ \ѳXchuJ T:ah`HD6o+^gMSW QIhRFEiC0ybig4<4R/ @1|7p SXS*"O9>?聇z|ڣ zCXtvMGofcsg>zzzTꨞuw84):q}?_[%^g)ʬԨ|hXJ@k(﯂  O\~F~L&E3xM_^H 6tiNL^QB3 ww×?-6UXX&ff|R4 >ϴyEo >'| |mGt/eoE{]~5>u\k\+DӘ՝9e%X(a4_+~A#(#}ةoڠ}Gsô"9Ggq#bp=L4'"Գ7/W)QzΟ >#WپB4\L}%xWQgߣf_29}X d79:p4b4Yk-ە엄;uuz6("٪V[7 i@ҀdkxuEԢ;hѩrJL#}6nj|AePGEKP-ZkG9^kGMcg ߋ9h[fD9L>O^NKXc۸yGgeߟ0l*8;H^f7h^/v^e^^AiKTWӀͱk0wyjGps鍺 qp+->6`s,^u/o֛֦Oh%V;kʥv @zU*c9^{`C@K=H6Y[T"+nPGeϞr_gjj=Vg%r,7QQR@QiɊ2_RGD=qɀ쯞:3<8\ʼnu =cz\F1CfBcgZ%*A=jdvbFFffձ1+fz]#EcU.*|68 *W576v5Q2P\=ǺZ 0/xW W&qf N|desEUh>x+̙KI`o9PWa'kރRkua9SMG2S  y[oCDx }? w_ԙpg4R&V>7M } MG2"E+s=w{ TPWwF+F~2e9 |U18)Ww#J1$Ns-K jax,u`;$g? l,3h~>ZDP&?S4|6mO/,k5σ u+$(p H;֟=R;n'*CGV~ (xƃCK(vz"|~!$?X7c:jcy2j89MCAC~>2fG[f~Ub\ w#J1D2|1^k-(l-+k)߀jaV!vvHD؄Y`g:|>L$7#yilۂ3@d𗂓,k5σ u+$(p H;֟=R;n'*CrAh2ju>(zv4Rxl<Ⱦ%Xxz"7V~:hk%Bx;|j]~W>ɫop ͒8>tQ.P'E XpACzտRp48ix,c;G>C +<ւ {<Ak~z|kvxρH}<7X~O`M^at~Gmc~o%Ű( B5, ^+r~ d$|7Zu#y5R\ (Y4|Sb?ӣweݸ\#o{~O!yUq$\Ov%XfdM`7+ $S=`?DFA{]PfZoQ\Ӆ?^q]\D?9z{?iի%mMv' 1ZM_FBq`#NkzFoD< P K*؟KOb.G?ֳ9Zлr•z7`'K"Y?Հyb7wgiWiw9nwOjZثW(EmE%^fشY=cjg_0|arrc lGp }'ze#=,lWW{2XȧSD~*{ b#qҽ"g~,S;)Gjb܋Qr_"YɈFjU>l"n;MZjsR1cЗwӫygtӗ|1i#=C":d$1N an@s c91 ?fƑWwu.ExZ gp:#(U]΂]x>I | H*ͻa_ .؇'OXh@6=w5>2)ЭTg[U]ַ+5ڬ1xv?9[T C{!_ ,KAi~j^sg/%aW#<-^E+Sfh}2/;=*77é ۨb;[>=x Lu_z=` @߶˺?z*W>4˽մ9o v&]fc9|0|EF46ʇB'Dl7R$y]8j=&{F9=Hhe W+~%x.P1vŷÿoy ;xr]@G?R%?;O> WL)6&(шL$\#xٙKdy?gy=f'GF)>9^TU^Ɲ ! w֑FoȽj̈́`*_7|@[GCւ׽A|6H~rbbPnDrI&X#x¿Θ`AKӺ`Cx@g(_@l炛U_8Z1czsM3Y1ALȓaE1<ҁ߀a(ևPdV | է[ n,&2M^Zfk|πWi뜝-}Im;<ǨNOm1ةid~l~^ ]{,<:oY;|4Xx]$5wcs<| `sK'$Wo_f 2Ǡx [{dY5Ğ by>Zc4!9l,ZQJ<ܝ|kWw;ޝnާEΒQ_ϧ%v[;ں 2`W>iUD7GԅYEW`aZ=w{}.#ac9: /J_#ޑqD}>q+8 >3XMVޫ1Wﳁc+[$[o0l~{mmݓM7;` 8{Gӧ|y/z6W;]sH)z.$Ԏ,ς!,+ӳ Q`io}ا|9܈<=he | Xbm:wSg5d?xw7j}}W?sXxuv97ErZ+Su A|~m~1ؙþI:rѿG_SljCp$YގySB@^ 6J=ѩwm"䟥Ds7Ej+\*半?kt~@R`=9o#%m-X{ C _Ɯk*Hf.ס+"0ǁo~ k`6f  OXg<""&[?ث >?3uX?Q`2GE&)Ʊ~īd֊X9ZwasGRݘͺcgAT0?0GHOuvS M&Mجl*4ќ?1 O׼[rSpL Wl둛;2Oz0KL73E3궩aNuT3i {"S(gfƟLl%ѿZ2mM6[4if1xyK9qT{^ RӛS]Yw_fa, 0 Z;i尝fz~f4(3ƌ75f,1O`>{ [Fk^Ln\h/?ᆿX^keN-s~RvbNiKv^DA5MhUxfW M'Sa5Ufь3T3< 52ʬ5̋fy71s4srȊn03)D7R>9&))n\}苔k/_-khLLt++FQBD˯gEUg;(DIlt'D.VkkS>M6k^*"gٟ*"{o\ds"[igu ߹pqyťE-."or9LDu9"{."IDN"rE]S."}BDfYsɈԻ"rE3."?9"G\dD4看y&fhH̳6"F$؈6"H,j#وED]f4gL{ XH,F$m#kc#k؈و6"\XH2HHH,fLrXLfLOO..WjOcE..]\\]\tq#r*."=\Dr)uIDz\"E3."}\D>KD|E]Dq)s)wp2fߑ1]d v_625o@Le&cr6dJLWn~#3cYFldV/dN8n_md<&էY7S-եZz+TKoZ:jp#ɖ˱/d%;<:Xʣߧ<:?SHyNʣ)Oyt:)ΤdYٲ\2˺fh9Y^{+ydn[?{%mKrz۝~ ,QE&7 Iژ<?{'mN{_}Z„DsFR܁fKqo)w.*|S$\c6~IO{'ҥ.lq/_m25_?כ$++</.qQ_ii^C V4嬣H̳㦳_b K {=||7;(LQM*s,DTDɠ$`1QE*& .*"Id㯦T?o{{8TũK2kznŰ {~Xjxa=/&l ᱺa}H";d3rAny!?B"QRP桅(QG Fk:mDV  UJtբc$Cg9t]A&jB=E/P7Eo;} %Lq%C(eU)5JҤ)]J2)2,(kjeO9RT5894h1ZiZ֠i]Z6=hWړ`:gѴV"PpʡUpt`l` 0p1G KR  `q5qX+($vHRX a9,2R{,~ +Vqr`0WPU< JE\ @ 6 k@W&Pmj¿u\+݊m >Zvm|Ѕ+_@@$Cdlc rBNp\7`<0I8-~'&XԄ+)' 6(łqh&آd x2=Fk!p N8e|\p+N2S8}'NZSx$>8/NfSdn8`Nh )pR+@0Nk%{ւI(: Bq~ς8@E0 g ynqo6 "]tD|?Q8@4SQ;E] ġWG$-B_9 1R1R`6fC0#A5 )%J d`VA&&EdcZ؊i5E4C3`mN5m 1`&. (=hPF>`'&:TrLv(؍{03@<10 A=@sWŸ&Xwp`;z>Sl(q؎|(9N)K[T$Z9i!ZiIZE+Ҫ&mLV8ڞvioڟC)t8Iq،Ml̈́EL%LL%BL%JL%FL!Fĉ$F#I#I#I#####$FE4Ii q"qq2q *:&6.>!111 1C %0%0#0' "&K `C 0`<1=11#1131 1+11;11'11711/11?1@f_L ,܉B$Bn(u2u u*5:NhNhAh F6фf,a3OL l$l"l&6Ʉf*as6a7Mh/ټmx3MHFj@m܌~fAD((!60jXiJ[6xډvhc_&%A8(Ekpn^r̛>GY÷1e~\M-ldGŏT6~tG;=#a9!0Bh3jZZyC%EftM1 x@ A `c^$m`NF\4W- l[ N.u_a'! f XsBrBxlRp ]u9#8pBO{S]o աyֳ-j`97&wl9i‡  %|s ʒ@,WD=ߊ%|Jbq9( $ [&3XB,%TL` -Q,SQD4A H ~a f-[(v[119I/gB>_,6[ &ס>9#>,kM8QaO 0Rؤd$#!X(,#UfKd|x)i))^Dz~"XeF>8!)((=")U5ّQ)5cLLb 3C]&濲g G##avRcx.AA~6N֮Ffܜh|D?DA1̄R~Y@>k| 0sQɬnD=!땓F T|m/Vi{U:oשq^f ɮv96֊_vl\V-;?VΨw:0"Rz5 7ku:v6)ǥ=cUu@Y ?xpbE# ^MZ}/[q?ȤGya@iNyO,<ÿ`#I45[}[yN6؂?2G1J*I NvzH.i,>36׀dHICh##a@Tj  6Pe|T(^q:G$J,5IDgD QPERDJc J`0f|/{a~{9s bxbtFFZB4#}H(' %#JFګ6ZjT{>x}iZ/d(uaGSBm\˶莽~rI%K&XUM]g{2;z< sp|O5:(˜=mSxKHۏ7dդ>6|x/(sttM|=˕T|m|۸\"_F֫!LfsYdƴ}ة޳t㎰~zq~fݣ5֍54Lc1nG ?k," F+ GǨ%%Qkjnjjff6̇L"9'[18V*Nw)4oQˮJ { jV=d_>AC] +DbԬz Os$%Q_7Ęv~^W2 dS'\8n?^#eѭ経l"|烚*y:ryzg"xlOUa.^B'_9}Ộf##P0[M{9_,:1/v1.Nd͸c- c#bH+QDyDQ%ZYFF1f'+R/.ߪe5X˟*„|?X? 2N2tȌkdp)` SLd{7Y_zYn_m\|E_?9XV#{۩ⵥ8z{r[L1`UkO5t])͈qbۮW>Y{5l,yLJ&a^${/?YR/;J I}+דm~>cˌpkB{ݒdg9Vµi2.>qykM+QJNq^gm$^`ǺMke ¾wbf lgM']05Z͌Cu1_SRpb"cT3Sx YDf̌kjkfefk*w;̛6>uӖ̠c\sM٤/V8fRbN~^uqܔݶ16e b d3p;ITg8lz%QU,h]LWy2ksc<młỸRf1ɉ篣,0yEnRM0I|5=g]*+FܝWlQVigs"dԺﲎxގt\tp|{NkFOnJm/!ԷiW/櫘D_za'~V^~!Sߥ16N*Rxt'0keNΊ q)pmcghHKdwmiJh[fx撁D-KkXUw5ōG5XOo)T\mtE񥤜b1U拢/HO񳛯籍w?r}wI&-X_P2Ny۸3N,ܲd<+7)նqf1+Z$FIt{dGy ( P6غw[ ~zj2&)pUH<+]*zygZ : lh(Wv@~A/ EHVHZ9g)aW-oNWbll 3Fp2j%]<ݿn콣4ugn=-4枛>U錪Tps9ch^;ݽ\x[ ͽ˯\1\My˔:vk].x(z#CNBe t(3]7c|t40sZ&yidfw6ռP۴-~cAIkwx/X)؊Mm\=Ry=~fmU Y$c58<ב;jѣq K#Gī?-:̺eYÉ[rn*ܵLn[+OdV|WIyOZa5XKnZq. XtVyp=k/8}$Zf37n.[y|Ll'nUlUbW[y{3kХ'Ar-׵lΩ2Y;~TOǶ[ ?I=5oYb Kn30A32^~JU' W^\;Rgݗ%b2~X{..X^O+L~4*ەJGN^sMّCj&G)٘뺥2&"%SWi-ywYN߲֗bRs\J5xةel?jDql9Hr_v;295E)+vR29R6ha_e΄ɝ,42ynކ;xZӜ^#1[ 8۰;ɾpGoƐd eq9"x39o|ykޫ\&-wHvKP{SojC endstream endobj 639 0 obj [ 0[ 750] 3[ 278 278 355 556] 8[ 889 667 191 333 333 389 584 278 333 278 278 556 556 556 556 556 556 556 556 556 556 278 278 584 584 584 556] 36[ 667 667 722 722 667 611 778 722 278 500 667 556 833 722 778 667 778 722 667 611 722 667 944 667 667 611 278 278 278] 66[ 556] 68[ 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556 556 556 333 500 278 556 500 722 500 500 500] 95[ 260] 98[ 667] 104[ 722] 177[ 556] 179[ 333 333 222 222] ] endobj 640 0 obj [ 278 278 355 556 0 889 667 191 333 333 389 584 278 333 278 278 556 556 556 556 556 556 556 556 556 556 278 278 584 584 584 556 0 667 667 722 722 667 611 778 722 278 500 667 556 833 722 778 667 778 722 667 611 722 667 944 667 667 611 278 278 278 0 556 0 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556 556 556 333 500 278 556 500 722 500 500 500 0 260] endobj 641 0 obj <> stream x}Rn0>lDBH&.*"crk͢ 3yָy\f x )4Ys G85ҡ">~y[)5rh YwNlj'#<9y"4<+-ȁxN1zkql] h,wzUqЕ pC"b0E rԢ}pt1al> stream x |ǟ}l6l&$! 6 Q i"Z g jeAh=fkZ Vj7EEvOofޙgyɆwI",6?l-WyH~g65ϸ#."g3[̿ɱǞI_̜T/H~2Nf\?bԼy"r7g~E˂gbo>qA kۈW/>[jQ'asWjO6zG-/oCKO}kE7yɊNxtSznAeKN>sÇ-DM/ToYkɋ ]K$]_e'Q 20H%F ǯi'̕Ӥd$]1oq+;R2R.ɓR6Wn '@ۉHJ.S6P_*y!l ݈TtR!BďxW|77@'<]ԅtq]Lhۏ.Qכn+P;X_34cQʸ@͗ LS~Wd-o/@WcM͹@i!e(e |y +xN-嬌ksH@ Hҵ֑b@0Ho yH6Ҿ@ @ 8%IzlbDflJAkLf3]Ww9ʂqueb# cS GEH$0eL 7?O, 'e/bԁUf]@ R$QQ$@YWE' Y=d%+F6 IN\!7G^| Sk&AʄfQP) C(L!h.@( U)Q4B*44]BIQZH"c(-Bh P)ߦ\˨ZN  28UTET OTjh-N 7i @:&AAߠ4:h=M_mDӡΠzLQMQ4-4z8#h&H: :fC[:*ͣh>m#Gq]@Я\h;C=BjC ӱWGNF]t4t-.溄.BWk\Q2-. z"-dZ =J_Jݴ uZ=NB+DJ: t2 :EΤnYu\ϡӠߠMZ ]u @k t&<: z>o t!}zyVC/5Z ]GB/zҷzz+"9.^M=kki:{CAKCz=]?K?亁n7е:swf.t}z t+@G6!v6BB7@7M5I7PmEO\C۠t;t  ENv >JOOOJB>.'t! ôE=BmG>wkO;h>N?ӟ҃'ow\1)%t 4=}8~ }wҟ>G;<=3VA/p}DzvAFOkGѳ' M\ߡ_{2}z !+UX?kMo5Ok?>7&_k|Mo5O5}7_w5}7_w5}7_w5}7_w555{M5}|Mks|MN_bM_?&5w_kܚXŚ.t"gZHQ#`0bP>Vf-fbVLfjb3?`6+dV͈Ɔ?V&3x׃z#@ pȲ% #)L7-lXDV6b,ò7?__E|%jDY#@ p VW> ,dj0[-v b,Ӻ71`1-t<},BmIi@ wTf(i4`4,)Yv]9nd#0diYV+1c& j#>_ _YŨCv獴 @ ÁGs%Wd5Fv!a:lNyu(im6c P:y"|y!ϋQF@ daP|e2h2?_ȶ7r++u`SjJc|aGW A援 @ ÁЅhʞfX9].v.:>_LF/b15nOE|,BH_8.@   lQlW)af߿$7p9=.#b,r\{ÉtajnݞabB_ !Wy1P%#@ pUcoWGIJ컭)i&kvzC ze/YiYn3,,DO /&oCbԡdU @ A VN(i٫-䶑<^gdd ;2| _V5뵐b57"-W\vuWg7k !Wy1Pr& @ AL_l6BKyO:>"?_ ׾y10Ni@ -EV%vYV/ ( 23-`FNfVFVf #3(NX~ a?py=ipGbB78*#}^: Z|]@ " =ʞY̌P f`3LLWVYs3 ϟ߰{J|3Ca]@ b}Vq8\dslpb `n5TsrsQɎfS_bbs6 "AB-HoX?T+8*>/FvA `8(iXX%].9\G0]M! "y`^( G9y0\^a asB\DHABwo.Cyy10 @ A1Qr:]QW;C)( DpE1@-ZR_b cs 9Ƅ/Ύ @䫉7 !h8}^:Lnj @ AՒBrYQrSPKR!UQ3\E "ZA"B:by. 橪{r9ip9Lt WGy10U-i@ ' 届 KAy^HP!UI;(RVTRPRTTP_bDܔ箈jy9ip9rrկaŻFŨHZsֲ&-!uj͉/ilpv[cql,(QJݽRp ryrL'JM͉h Ě$Z77D"ecRERޅ4 SçіuZ؁K=Ա$bަD>bp_cEoQzksӎ[96g'e :RcGŽjFٞ5]sB'.M'AΊ$C}BZO[{4j fPϼZ-ec{=ޡr  KJ-Yy= 7DB[(ZY\þ"!*Wdy31j=ok+M}vqM4^P6~ybۣ!Vۮ8ڹCu$)^Qڑ;YޖQeޖ}Qw恄p'߼lrBC--snך{:S綥mP{T)olWrTIQx+ncufvG$ܔ|Hx:g i-9M1~ufųR^&&__}?= 5-mGkgFTկ]<ў---=͝{/hu]Nbƥ8edܬ25FƥݾŃ,ɍ hkߢa{}{YMc5jp'e o'Z[ |/'~yhe۶ީAd@5H ŕ;Ϊx?r_ϓU[&WeWWݮNQ5vߞ $ܩo#m@nt$EU19C7c w}r3*݁#)fʹ;n:7q&XHv T$IAFHrrCңzmi |ܒD*FNUzr "ɔP$^+HFd8~ [l*:L*z_dßt{9C>OVU+™$)KS*!_H"e 9>j-曎ӕ^ɤ*MJrxUIwqO@1SzEOYUJ E)|Sޫ4+aDۉJ.Px~r@~}_aXئ\ŭdbiCִ>jުLCkBr>*/TP%s5AWWWN#\>ԭA6n@'t /ڢd+Y81m8.YVݲ)+pqee_0mJ ?}Y9̠;>%8ti`.}J'\%/P*FV$ r;PgT\w;N~6$ iy JUyKoA^|k2/!O:3&K+R5*sR_fU}LU~ yG~?,JzTsy;{{y_\H$,ۜ4'IVȷS]L־ս Id꫷7H[贑v|6vM"dzjxY|R,ܤh1L6ir, dAkHq ő˗$ 5qLdZ Kn^"g_4] c5H"bX/t7DZtVnXtâܢݰE7泯BbE',:E',:a NnE'hE+,Za-Za VXrVX¢[aEqnEqXĹEqXĹE%,*aQ JnQ JXT¢[T¢B `B-4XhиXx`Xx`၅[xY,a1AX rAX bbUv?0 d'Lvd'Lvr0 C_Of5Hv*$fE X$E X$` X$`aa[lFXlFn߸šߔ|isv J<_C|57ߠM/.@IYi.D1K"Xʪ`hhR,?Nb-T.d2JڽEj7Hqz*i߀lG_Z~j߇T`%1GZ^^o%|zb~uZ,{Q]Vy1OǨۙ!˷ߣbp:3]"u_l;;T54XߒX?Ǐ闼sԜo33,>8,6b,,`-a)1FY4~En $S"-hdC(e6H _ 5$jK[DMiKܺW.ބ|1~Ig.a?r$e_pYGee>=kowҌϐΔ~DNjk['nHTђ8Dc얝M[d:ڷew<ԁn/n]FE,C7Ki֓ h_!/29+9y?Қz5}vc}pjR;%G5X1HUѥL]$c:6X;kzg4׳lz6W=kz|:y9[{-xP'm;s" i2%:g[^ڑpDN$TV_VϚ5OSMYDrJ<6SKSKbܖDdVIĻ>`,j^ބ? {ҊdgjժLV jIoIL OfLԁ}{) k6h,J6+J8q.Ѵ,Pae_(/$q >gXbPpP 3屡<-Ca}l}ekL{&T7JZYb@qeN6bݐ 7BiiG OliIwbWF]_ _WbhU{Vx*n44Pm|jDƭ  /M{/6J;R$zJ#i'GAzWʖa;G!]𾍮|2(:L2O)]*}_?]ҕt~t~ڿMw/e GRzEy:.";byR&uѓކWS5xuTOTBwY+hdO=rRDwRi0"t"]@ߑ_t HXx?f:)tmZ]1i9"Mo68i38^ n1.3]^{%]zXes9,Aok54c懤\I qƟj * oWJlmth^2iHBzSvK$Ïq9ZI7=kzvHF_)J'HJIKrB~Ub8Cc=Go#t6. ޤ;GI7H iPzU[ʑ É /43w|iU{~8/8⮸'0,?tU̲BXZSzHz\/O0i8OWWc'3LT?c_Uy,wsg[&3fIH& H.,b *T[*RIm+HXBkmZP5l.QޚsN@}rys~E6zt.+p D,SG[3B0U#IJn"slJŠ3`@;PX!C\4nƿO3EX {1@F44j'(4Ai:N7;a w%thKS4ln[mvrw5~? !$d l9SQQ*4g"Gb lDP G tChl!=+ }g N܄^EG1~Xѭgy2\ , n3S!j/`v ^Ȁ;dmw[r0{}ơ Uh~ ,@dL:so}SC(jbz#Ytn8+ ֑F^܀*AØr_,)֓ity;z=61`.a/@$6Rgϙ)"gb$d(֦kG]ZTŝqg Pe 1(g߈h|#N*Jʍb7Ѥ((AV􇨜/H"i>c@3l՘⠢a5~r+TI#RǏ띙HiO@z=}2Uܧ qi>ζ;('"IaR6?;55Pm~%x¼!!Ja!BÒ'4om]UEpg4q|`L&7@x8q\ّ%DPXl6YB[5f͚%5#7?YFh#?,o}!m. )a{^K}z--.ሡ:kUSj]^鞽OSw7Klr%NTVwW yi \ 4t4|\zO~cv4|RO~%#\1^a.f汏2{ty  n3#3:b )dd}8ÈWm=xȣ:&0NJ]U]Aȴ[nlWU&N}it33}󹧦f İ$n H2P֑9(K:_dB ,vJO٘4;,?LZsy="W|eU;M CYhnG' ov++vc5SӝύedC,q°[vb0 J2Qe"@}a 9c!mcQcBeoț{?X߄ LЌTCj*JN WCv|(hN= Z˗ lA96!>rjP~yōlc~SDrUAWQr WYs0VE Ns9eZHӻ~6`&0I <&h!F!Z6|EdC̟G!dcǃ0I(sTf`3`)+iE<ʪ oz;1);%\ݝ{pCFpqHu]ݡ᷸?AAY"cOqp$!CBuh7(0(8($r!r+6DdmH.#HȲȚ)x`hXlȯZ 9X;=ڈζG}> a̾h.˂@F@S8Ś3(ҽɰaM]$0;k2 / dИ*avcV75!cupwʂ-ѷo vƫ\q* K^UnE|]8Al /_-rڄ3%tKonh}yvǰKun4m=Y[[o5*Y|% V3ʛ䞬&<ٳ= ||3$h~/t\֠aC[ @þ6L G]&n^01~.pinSݶl`GFWG7FE_hC. (Xtəz )M 찱2 -2RA}(γ|ҞX}[T9X^7nFD.?|tLݢwqx:_`3\6gtָkOkݾO¯,?`9^O[LmA[m6ۧ6SBmvYۣɘH&h"l6Mk/!y(fb4NA˸IP܍8ހjH.](&R1#K !A{;x#zmuҩZB`ȚX2"t{ۮޱ}lQb*q;1Y~s.8K}aҷ1mq& qd٪]WkO׹f]N+L aM-6bn\sQx kfEQaS=dS1<ӆzNJ:A:Tgv8C8cÏ ramDX>  -D%A^-nЫXUQ+roݼh5T^nysVow#(2koߗg,(ffi]p3Yz޾Ž׾۹Ͻ[Ub.G| op-lPQxCK$T'cC>$wTn 0LY9QbX6 6ذ-8 Gٮ('c2@_a>r]ЊrYHb!\қ93ʘAgm~ݿ⢯6ՒFΜ391Z]Ga*(V=˗Jǁ*ZqF3!J2nQ_UQJ^*ZRNmPV3_CD&k)4PLC-ԲLҬiA_\{10/@?rU#v g^c_ed`'9O9G8U&&.9wrw;mz??38chodLA_&L[2,3G\ v.q ,A|K} yB>e\(R#TĢݧIP݇**F=yrPso?O^K[~b!_'W:LzBS3f҆'@oNvW>b78P9 u|mF֭BeY8["bˀ#ZKF_br# )\|l'f/pK@ϐ!qu8:|K#s%^X{nja~-g>ëD|'~|C.dt,HFlU)c2HNP/ӉP(AF`Ym@' 7Hdϔۦ^-Iƅ[=lrm۳_7Oy׃-(r_~˖]v!柁hqQ\Q 2&"IFP2LA@B1L3f>@Vd|EQv"5!"Y*og{Hhf :~H/FH/ybL*^>RiD$ e uBD)l$STX~ɟ4^Ҭ9ȷ{?25wGfo7o|im̶ܿ,, ~!…@a0[ȍ'{ŁC?hot;bیh+%a_VoAv1shpc767"_oE7tk,bSCr- v(Q=p/#c׻:|>p>Vצkg9 ;srꪊ^8b%#KR]'-/רe-_I˹X_0~Go`1Y Z.`uTJНw덍g/~& Hp <*&\+t1[nݷ4=%Ɇ z#FH˥(<%T*+$+P1E#eK(2P*TRj`T6(qmd~0F.bTC2i(  TX;ۑZ %T- ykT+4h 5B ω˄Y`wGkI!v򄫔 Tvz*!zAW)) L 7&XhO:vu\b$9ff?3 Ysu;:t7ۀ08_ѹp><} 17dGJdͫ(,"UFh0@LJDB/׽gdXO@./:EYP0# J|r r֕I%ve͞MV A SRΩ(nrTI^\L.Uf4y,~#oQvYȭ7*oQ}rNȟ+y y{P~XYC42!TE8#q8y"R{\%~J]dEA/ q~YiEAQD\ʭDD%iI *,ɰ$U6 vT$12f Pud'm)1NLRN  qdQڱ koV1 [c|hK%,[ VاT ".BQF6zWcgq^%nL7ֆ:*pB?ވ2j3vYSG+IR֏xA2V_1;͏;D=}n%lL='Xa _\uAll6`E\ IT"D2 tE9b+޵>;.Y?.|.==$ ]OH ,z~/r˺xfAUۚf9)% 5SS,!d] VDO'=|B> e}ҳ*, 9/D<`mH LآТEB+b'յݾ7}Y,e1Zt_nB#.חSPH~P6r2as#m8YϏ ȈmEգMW-EFє9EME-EBL)ذ(k~^hOoGu]zdxKS8<{ Ld߯.VӈyYI];~A}Ϛm CBc׮fbj/GIx^m6_]s1{4o iGw5qlu}c%~TVIPOq.;=vãW٫CÊP^Y) #ye쿶fhaj~_[)xP,΀ "ZqHӁ ۅ!$p,Q r<\-/%YiъS={X2^n!]8-!k]_Sj>1~ٵ rwzj~N7Б^sg<ܿ!㪽ζ7{q[~ox?navw1  93m]3 gZYYKeGl6CrK9sܟG?%QyUuw},Y4@:h. 4!.,Qʀ(DpO5Y_Atf21e)),+MW{̞/_zI!zw?[9`;K=|07NΌy ~ ~17+k2sݷꖏ14M_hW*UJlU(]=,aRȡBQiBxJrW!v+zg+Y@=ܨLNH`ʥ>EƛLX+S.uH'6ڹkҧ-ԇkov 9'av$`yY05ZxG>"3Ak]'nb[Mt03ݱQRFK( 1f5_&!]{, FKi~J)ƚ.OO`/akU|Κ̰mmp}Y]vvv*9m\ uJxP}{͌^eUn}7-VQḦ́k;9H hMD Kr]6qd0$=J9*U/Ik._Wwr|O?>SŧvuU"RAݑ[q`6mw&lC ~ 7nmfYW& ˔?9 (e}CϡU!4Ud9PB5]ϙAGS]UMVCp*J qƥ}>PlOȄ޶h7m /cYߞl 3'K/Nl+9ˀET|@*>N2x3\y Qpz:#=(Kq7yn>1u2ҧ姕G;t? ' ',.&!ޡ(<\&5N+&:^T]FT拏{ը}]}*Q$MF`dE'`AAҴ8`\Q4ݒ dҸ5`26UZҢ1GˉD Ds}{ {Ρ3^oNNp ez[dԡ\nuvv=Syͪ3q%0(m^^*ǿX\ -9lNWL7'0u"K`k*Șg dɄ )mB)n&GOc/T:#&a#zL`*B$BH &Ih[8(Q9_U`6 𜋱bQO?/$iLb /gchD,JO1[ԘxԊxԅ$(&\V<5L+I,%$/J>qI\n$U9UtSʭ2}jf"'ANO.š秋J}֕dJ4E""Nb7 D"2`&7 [X펹huO98T9Ş}Ç+Kʃ 0fY(N⏬&eI"ccn@+?Ho[ITƠET{kHrԓMb4w#OF-Gi\=y_=b$ @6NvJJK$d`LʔEeE3KNfdr2cݚu> 61MKyƄsCf䆝T u#|x6O aIGRfd M:)9ct3ztRgڡfB<1+? IY!!ѿ,&a^:u  ӛ|ܙ%}w3SK*!m,6sm+vmQ@eJe 626P1p}|EZG4,y}7[ =RR;ijF8hٕ;oWq47o[1󮖼xQíC©Ӈ$kKfC/jxE{9Xti:=8=;)K5t1WE[ߨC;AС(ۨ.~6>Ms!5pDw9.v 70i܊m#gi:'8'ܑ'eQ_aH= 08m/[VK77ݺlŽ[_[Ǭ/n$MZ]z4d¥ȄP=@{AQV<$cV`#1 hLN##"&gۡ.ԖNXGV+J#lI7/uNK?pȟLzS6^: bna^ws7+eլצu@eAAW2z} '4MEcTc:5邡PCN#\(Nɟpl5Q l!5RᵩEj&5z< |.˭oFɴkxyī nt q\L*\M$#K]Ytztk\<|FupxY)R4RV)g0h NN'ne(.{"(Dp ])8ՁõHZ2fLGDՃ``AݦKHs<=Cªxn]_#÷p=f/qo:s;*%&B"Gp_,,G$qP|o#eӯ-+0~]Xp xw7԰@A"8{ٹ]=xz{nsÏ3l, f]ױt_/Y %dgGx}`|AVTPԤC1%Dv d ocar4ȟ 8ۂk7DBvw.LK;+v?Xm=Ч!^9r~ r;e+]qRu8>-І{?4fս[f4hmYdxR~ţ6JB~-"*Re3T$# .V:$J2U 2b$C#\ζOϳ m7݅uq4͇0B+afq 2톇7Gfd-2GzN}I}MNrXi.q@w)zM'st(j!Ji+ QiQ=SQAH%vxCj\kFJG]!D %qbiS9}3 3j8CcLX^ۦ$r]@ lO?Vc%x [ŽOX?>z?))d[E%noGm@Rq3TVQY154jqm?nAHZ\1A6xH!= qd™&21*TDž)J{yWG-NiO˝xrmOnrST3M\zPbyyɔ r'sfMB&ͦ+KA<ܞnGi2b6R\ QYjKSx5$Id*So>I Ta+%TxukHѝX:p/='ؼ'X{WYߧknO֛7#uLIk5ž)[N_0εgv9YOJPѢϔ8O6-ML3;sRT9UX~=XX= 8x+~rsWж^eNX4ORس釷oU._m|Ym #oG&<ǂB2Y1^bLeCN)'~݃1 T FrKa0 `&=n+-դ?4?ݙCuDC`ĕeZιڹ,zCc]5g/> bvc13/}Žo6<4 |0֊Xq)q(Tzg89x0YQ,6ef@$ )nJYP%ԻKfyz^7J2W?P!]x3{<83OE&؊8t!61t)CbȰ,oӂK4g/}+ir5M54)*nhcy/ybG* M=Xf?`qH|V|8Q$ӌƃZ=<,iJ-*ܻ{ѭ%JmrԬ3&E%d^`5%%6RzQQQ\Rd^_1E+*Q«Cwxb)L+'`T;KIϔFpȝj$qdKCm%3zEKYy}w9w0Iԃr>AA,hNLU#t8Dh4QD|Nʢ(eZkG}2XMoW[g-n;-Vt{a]DyٌA-j.Zgmb[+`y܂CnگRWhMu(M~jMI:/aEQo~G?wB!m4Cxzֈ"Ei!-D涟jA~U|d td;: =IqQ; h Џl_2 habk#7YX#]֐V'-:Q@ p eʌ"EvH9gS, áج+DZj413ϨH( -Hɭ}4%)XB*jdZՐJ5UQ:;6ye({ Ej:1L:*%Uv.8;GW6C =m "|I|v`r-TmMũCNX{9*8p )ThgU$U _)P=! ZP'Hu.(T( ~%tє8P)SS`T+^4d8F,FKbqD]/G+rqB]>*GzH<Q_ |BZ=G|'O`~$Q;m„ a9+hdC Jg0|c١Ci2;8bGmeA rX4bzfuS 9Z3uVs `'Cii? ଵ{ƮWwe!͇i@:̷v>֙(Y'wc萣4,Ihc Eiy(8yvJ:%+4)WZ_Pxu*ͪWk%fFޫK?VO@eYQ4N+jڨ6S%@#j:QFBwT۽a62[7'*S6r88BU>0Ƿg|j%!y{Y Z$C2kI hٓMƧ`Tk{vۇ`>;;FȄ3[z fHw\'2TwhY8\ 1WFUK{%/YJkb"XK kf3iMèpfL>8+#Hb:boψD ) IG `7~ؠ˨tx*kH z 2īp$pRBx`J^\̼$JN¦ms譅Vi"Epset=mԍh{^pc<9 ix}n_"oQddnrn+=d6Q/9q:#KG^uE5W|/I:M]qAc,"zރw ;S a9ɨ";TrRI6Z3H KO[QNJ9  Wprn3;).a튻\kKrEDu0Sm{zpzBA,aόBqP oI/;넥ߏ2J8]HTl,90&3ǀmx mU: 粨dAFՉ@J:Ջ *L<` \}St>Pb}0^7T(Ϡ;UN`` v'~s0OX):IuNIAK;O5a~_e͗ u!;YW:#seJqre4=젦=m@':?.uϸܣg w@2|Ahap/ѩbJ.G?8$!\RhӴL8g;wrps{cߓK #"b(vK^^ ~,4qEG)>Xڕt'5?&ፊ7҃ l p>_p>3χ|8·|8·|8·|8·+ '.$Wv ?F%H| qy}x~ԗ#W_>@M%#****5ezkkE!vb7>1f|_ x/x,څJ4~i>Ӡf.# qnI؄Mff6ݬKDDn1"rsc"mBR))EΙ%{{oy{ِ0|ƱjJm42%AMlĦMlĦMlĦMlĦMlĦf1-%°=%c%)smZ٨q!),l1)rfrLwY>Lx8砅> SN[F3^#faQ>^S #maqŒ? ,Z #2'3[- ؛8嬳0a{?.{?~j?~_\D\"'MGL@* A[+ hyqRcA:B]&^p> \T . 5Zt3gSrҭqN32a6Pd"6at'~[ҧ&/׸8rWo9+zr5`u] ۬Ptšhttcd̷!'f ok@~>_LjuE:1E֘*뺂Kٗ}lT%aXOjaHx">f7ȝm0",lDGe`el%ݛH"<?ňYbb+7m[W?ʄQiJ*p祓k۔fS?ʡ̧ӳt ߠU5 ·E5},ҫ*oZMEFwV8 [B[ld)s伆:oJllgƂEZPmL>=Oe YU4/v~fQs޹fB,0E5*^tN{htwC" UN  :tT{~SBw5QuV0Y9t0ok " =}P k3DC}]șQ3Yq9YUJ[IYe`j) VY u ށN0MҜS V517WU衁wȬ|hcP@{{@k5_g[XR_z/8[f+7!Yo`@~h2PQ/6-n )\]Wغ }4ͱ}[mm=4`d}ihʢ=)حzw껟Dw'?'cW%@|:[|6hWb,pZ E$kW%p rFCG⏀7,nx =]Pa!^~_B!$ :xIG 6+"7}nz3l,Ev^bEv{WQ6C(2 7WmUn.[>8-Y,n_p\VOY]nS :~ϿB4]+tC 0Z\@(JMX#tB['3AXYn\w xfڬ?Wnֳz ff_o_.2dSGsHaǂO a ÜQ&ӆ/ˮԙf7ߪ{ͺz+z}G|g}ͫ_MfyU[]]]ټZ2dɄ%ҬY/}sw?Z0!!O}ݿſ8Զ+Q_45^5k%6r:6.ZUeBXR|:"' Ղ8]'^V 6qI\ҤY|/AH7måQ[glZ`}r|ZJ]]EݫRs!%3ŗ>Ҟc/;hu=#uo So8ՎMfEjYݣ^7M,+@l1xuxw_8t?əG ]Ӈ91skXA8 r DT*NcKd62㺝Bf ^f/C -^G^GƁI^>~|Qހޠ M3o2P?d36-x6"2FECg)A4 n111'--$8Č/b^"f|3{!IHyR'qyHI{ i쁔=~ 1܃Q{{0rF=4a9:Q08M {f9o8 /(12葾[:BGP{8@xJs5勨A]zh!W.R]\ q8'1:K肄_AmJ F1,zy@.C Rq\ 5dŇaQ4C^ _  gQ{>[:6Dft,> }zrҗqWQMe[_]gg0ēta#'GhCCOHƊxq,4^LSxxMz@'qe-}"M'h%S̤L9x8wbGs|1狅4O| w/.=BWKatOQu U+T%WR&bɿ N: FHۄzuhUuvbZZ ::z[-ۮ7YV'@AXt 흨nƀ9 ԙB?lN=iֆ92"2%mjk y| 4j/no.=l8_Kk6Fs'SQ3@^j G5YVrZ攭ugAGp}{Qֺ8:Fvh5NSS4[tXR]RbcXW>h\av7l c0og 1&`2ĭ:hڈd 5|=s@Q36' ;<<kOn+>n#ֶٌtZuZdz!Nv+V =[XQ3e+e*-Iiҷ'Hw^{i4NCrJ?~DK?tߤH?~FSSi )R%=(%JM~-K%͐~#fJ~Klws334Kz^z(J?I/JǤc/!I_ޒޢ }E:'Bm> y =.ϖs\ΓFΗS\ RyB"r\LKv&%C\*R@.˨I.˩Y+)({e/jGaV& I 9,GrTR*jy#WPR^IߕWɫh&jZ+}yky: QHM&YL-UJm67y6˝r'CA[N%wV[=oh[i!N=R~F~?Я[~Y~~+Q#ʯʯ?^w1ߐߠB77--zV>#s9: -M-7* +K>  @/F/GGtDGTozi 2Hqqe2ܥE'PzS[N)R>Eo)(ier/QS2A@DzWP22YL)S)tYT2}%Kɢ+t%>Pf)躒|>R(_+J )eJ`SʕrAV*JASb!EQjDTESt!11Hc0TUQT0ZUTEWva 'U4a:D"8a0a:\.#§ՑHa:Z-|F&cUpN&ՉT5C2dA ",5SYla:G+:O-EjZ EKu %jPzTUT-\jZ&|M-W˅RܪW Z jP֩ujZ/  IXeᅨKADQkFV2@aPcQ[$,v]nը7[u{@{jNqjΣB,ʣByJm6᭶zt.u& #ta'y<ݳ ϾDZs{VyNx6xN='=knw~w}ҽ}=Q?C'}̟(H@TZoe jľrw/5렓V[.&"(բ! - g w;Ýq E12P.uQսҽڽ-|6ҽYzGuwPڋWHXx, x|2"CGi2>ţxhIND3}3 4 k00s%RPeĨe?!/MWIs"$䞛l@sIqtܤj0'U%Ak) 0HXdP(_[@n-1Xy?bm#bEh.@3ZxVYZ俥-@ZƘ式 V۪-"ffж$vm5n')Z|U =]4Wu0-:\3D}fpttύNsxY<0BE]|nRȟ, ΉVz(5\azފYµ-Xmk,芮\F^nѽhYGzk2S_AnVG{})O_ GxCWM \Mۢ[k'z+7΢e vwbTgb kq[c6zhH,A!fc#PfP&gh&beΝJC eB~opOm[Csc0gsÞZ6v_@?J4*BE?3 3:xZ8`dKk(/ǃgS ћegXg/Ɂ4DDnDZ󡲨u"0 ?ndKy<Ҙ]MCCʋ7FBۙPmt y>`Z@_ HXBŷ0XC >j(5Vy O-V^zF|`E'ԁЦu4k2B[><M# 4Ȏ$:15C<|^׆#oZ8=z٨ n4Ax&Vbk(;_m23ƪq\n?vaSםlnt#"X'p༰2v:\g* +aGVhxdt1/<Qx g<2Nv< b;P]bKBXq57%__Ύub7uDhkƂk 5?Wq%0e;Wy>D~f69?rFc^/yfᅱぉhn` [_Ɔ)x%gKv˜=u𡨯i4?5SkwkE(?~õ#8hl4xh4&|- ^6T6eؔr;7nl8cn li95C`۲'~ʲ)ږ˦7g2 Z.$띑<ƫG "d8<)CviEmCŮ`7Sbq'#;ao7#ި?{-P>{G OpFW*']a%b#O|wف% #W7|E>ñ@{ו@\gco\[ 2y uU1X^{w]pVȞ 9'۲ɖ8r n? WƏb9?Z=U<,в"~"p-~:peM@.$nGUl_B%~UkZvb;h{IJY1X ,5xV;\7uaQeWz""ViBժs8բ6C18!1vqupMK~ƶmcQpZsNqĶӓu{ߏz ]-WՈS~-oMe53xnc{wM1Ou(?jn1AZIϷ/~uE}}6}͍v_٭/km-=v~H:O\[˂1C` 7]94i-k~7ř|BjK Z+Wipsiwq;ؿ` njel]p~ ֦J͛jذIimkXbÆ+ MI׵3rCzO ۚ鴢pqOvVN MYgU4ٔ:ذ)uaSah8䢕pSyXS9Aik84-mKG9߶,4c8rؒndk¯oIB4//_ ?OyBbh-b'NT.r-*##^g;EqSxIoq_4!1&$Y)m#RGW5YX','-?,-oK=oɖ(#9OKOYYOJO[OY*oZߔַZ*}氥I߲MeIl3l.&9Wr9Gw5ՃC_(jN]Z6Rdڡv{nL Ţzm ?}D,#;ӢglOٞ>*ٞ=#| DV(6%le2Y[\T>e/>gZ`x^I\NM\UDONer@9QTN+rr_y@t_y5FMTSLrN5W-P2u.ZcrWY_eg[{'y&ll?cVS3Xw<ΪuܪaHU[B{"c8Wm;ct:/iyz}F~3j7_?G6aw~%:Jܣh=e}SڅݸAُKAwbRdE^p/K܋½o^$*Er^$jߋDH'D{@=(KJJF\Jp2\ٮ%]%=.UJ lJqeU ڵUXrYrkUסKpW(9EO@w(> gۍ"Mbj{2D'䞗~.--o|_E)%5N/ $7U4MeQӥ)ACꎉ*rǸݩLӝ.p/u+ܹ.wK9q5:J,6R[[ wSww{;X^rwR>1 kM$ J5͕qq_'GZ  Jys=vw{Iqs_ .ʒ[Gv%3JXcġLAҳƓI丝s=yb2Um~/_=WI.9Rqnqa\XAdg>JD:s ,,huTy{Vyj=<5#iy3yy:Bi3%HVGi"y۩a"]]IPRBh"9˔ %lA,WffMv D妻I5WB gz1.AwX~JY9Er]9p'uxxJr]Y*k^7!9qRnzB}ݨQϩ=%9zJnRpzOG1jT9۔x[z-W(׸wxdW]7Λ)P?w$V+͒Qr7dYN{Fwjȹϟ9:ݩ.J~veA\u.GHW;$S |?$lݪuAHPmT[խPwј{F`Qk+EJ)Wx*]9#_UE(KT`jw})ո ]zV/{X3=2Le{A6fOENmL}qf]|˾x~}\\.z_v-qdr\}da$QJ\ShlO}s#Eh_vV_b?'w/,g]!!yx.ˣ<}44@4D4=+2]#9 DyLCGOcYK3?{<,gfx:eLTAr8E~ykd mp"lGLd*aSu1d֨q d6="OUl f|IoMi-{j#6Dey s ՇyMXrGڔ`H?gj#DߧP ~Oc?}_oz}l 1nhYgxYiP4gΟ/CJhIӦh &Mc^#=]DDGNAt蜂ynj*랧͜N{RJx_|b_&D*;~a}\gNχzfItW _OD2!Ѩ^ q'ejNu 5wOg ԏ:Wk[oĺq&ʨ.$K!ZI(HHJh.=q:c1kc9ؼ.O~m?ю'ͽg>[3'?1~x_6eLD:a}6ߛ:ZM1Ƙ%ɐ6xyL`n{sLʟF}.)1i{ yz]DzO+'@9kJ"NJ:Jt 3D.]!NtQ? 0h\''HDSx֓CDyD.rgC|6TbY+gU7+87zV#)gm ,1kה)kg ()SVLY1k#7k\=kJ>jBn;|xݑwwL[;2io61x;G1QrFRYc=?IJog]@$|DD+t5Zz6f-:mi֩Z*v 0g}8!!#grir&&[wD1&w<ْd -nlʼnWrYxJ78,4Q,zt>vO~z ^*Qe2 ;JCXKU]L=.tə0ɹ@,RLpf93:S)AgbL~gٌ ιyS:c8 T o}g#?xlM'B:[юN.7XI*x\X++ݱEp|%sǟ8:"t4IKR7 'o3tJ!l ~M~?T4c"F,͠Y8kX՘:#3FVcZBZi45kWSo=.L??|ZCCwI^N+JK7,;Oq/M:@iS/H(O34ڙ(@e;MiHd{)%mRٳȲ{Ɋ)=dۓ}-/qȝ~>+H1RJJS/~:4**<=zϰPV.-""oGP㨡yq /du,%v0vPtWl5,oL]r}F|@L*~oN(DRi>B- =݂nEO;ccE<4q2< {:uSjI2.vjI2Hs?Vh$A MQd~+v6 XOxl]x׆xoؠE]H&jVu1_}VzR?Nqd&L}O[,۩!CiH+OTN;EJYSJSf Il P((GnAJ5/jrE)ku*ט<;%$/ۓGx_~bE3κ[G#T7'FuSaP 9_i$-ww$|U$kb|SI:ߕߥ9'Ӯ#+ uaw]&[:Oe%*d'KY4&K8a2@Oa2aZ$(= PKeD?V#즸KO+dL.ozMvJ5GqFv%<b UǚGjuIM+L|nozo~ˤSjeq[|J;ΠM4l{@P,Dx+tzΊ!GX"y99+=rOG:Kx<ҳtԒqZH.~1´Lr.Żl}=$HKQuTn14Q.]&7jDsF<-$ hDTkjω(6yS;yW'|ܫ11)Is2JTK1;NjNKx/Cks4.ɧcc<11]ncwElD.ʩ>&ĦP2bcg+-iYǎ"+\BX/jNO5gǺtMP b.CO>Tϝt()zI"Փ7O} Qo@OQV! E3 mGn$ 7ic%خ$'ܘ$EI)&%p$YsZ}t}5M&=}4D4@Iv[m-HxG~a;Ѻ +Ǘz<srTVnۻm@?m'diN3sU?겐[l`tD-Ӳ$[D N;+]FA@:ŊpW߻q-,O"t&|~F[~oH7e.iF$I.*Eͧqf"K-fd>㐟d0<I _ U3lbX v:[,#oi=j!@A4(B8{ϵ.FڨU3o Z. 7Q߃<5zu1d1/MC8CS KvUq 7a-$ކzV+p>4vxT*#վ@l-$A $'[G@?G_d8Hzq" |Mh,]%%^t߲u7: #SSXzMqoGh$Bۏ&Y$X=!X?hig-)O~yr3jFxiI%c-w,;fQ$$ FK3!9ˌѹ GoӐ,D:-ӁrF91;Q Cmr<什͐0N =M\i_,cT1"x50O?vxq=Is1FuBOU7-͈SA_:{*؈m;qF$)b  y40[V'jNg~ò\Z>~'?̋3T'G0~Hy_'nax }rhѽ3t0NR!9 iHNC2iA!bFD=ZH!/?C ,:Cy\nXS~;afll!xC\9;Ϗf B¶ע;v Frq[V~FpEܦc]@펅ob=ODG?n佖5o|r<DjHz?$ P>_^`^G3?b. +@'0*ҙ4֌1xR~Orcc Pj8/Fb0{y6 zB;8Z!z;>XG9;/Gs@F,D,j#p6vu y;|^e"*ذzBit{x ];pQhޠk+HJuƋXvpL-VdF)A;`5F6lS!rR#p #X_ >T+S{XՍPπ_C-r̨8A/'7-G&rYN9igI]PoqYP2\dDOd˨+Ő\CnW{_ŵunJDQTADTA@Aq  QQQD4NchQ1N Q8qg1wW^[[Yuԩso{=~**.3Mc8Fwj?co/#qKpvy8#W2QJGs<- ƱQ2g6blG}w dX|q`wKDN31+˵34 UPF36_?V :+Fό +gǑ-cV77js9rR?Dw|Rxw.++F?pBOhߨWcVXv8ػ8J1j GpT ν2Ꟁ O.yD,'ԛ _((Y)0~vHz|JO'N<8"27C*~xN.óc+c&Y <#9cck{yLb#8j9wxN#f.Ʊão|ıo ;(i@c# s"ž| B6uQ@DJXX@+n08!X^nQ#sփC\>۰~H῀DV4}@x ^'3DiR^åP?;Ai@$P+=6P"@`D=׀<V)3%ꇘ\e 슽K< Brj`0Y9;Pf+U~<ʢrggıᨨtTp1|'^ؼ3y$ı =\!^1*XNOY$ pV^" ԇbq{G僫U۵y5sCͬ' ; a6Ĉi8 79Gcp-u!Ck#j#梚8`^ZEr>+`݅O]{'ql8^99Sx ][/ >~FG"7h asV"xi{6q\jkᝨ֫**zm #Qj :>@|ѯ,PLת=+"x8ֺfhJ1K/zb`/FPG+55ӪCc{ (3n 3 l%cMYOTo=v$`^c_O葺G_b-?Xh~^|nyj?Ѫc=>FxT }3o-= xzG|g@sH`{w<@nxR7u0̄ Q*qqYubu}Uh<dXC@W6Dd.F<-`j`<`d" n`0hxD~yV$_Ga]ː #UŷJyb`ᙈ @h.z3W.Uuo!Snk[IXbVbsHV:MJCJEz'f#Eގ#]I5EH{pĊؐrĞH_8),)O*[Z<7{҉okDdBEVѮw;_cĎTٳo&  .OJOK%R%iҲ(4L$3z;G}s,[GxK7l a[h؏l y!GƶpBC13>-2EÈdqj 34fNk̜6]y #5F.i\1r\1rCc-`]{#5Fh<&yd)<)y1Dc30\cV1h̼Ԙy1F;/4FJUFЀNe(`ĨW122b4*#F=9I.pFNYUF6*#FEeXFeh2b,+1ک˩˫UFTF#Fc%cebUTf*3ƪbN*?Fgj?./5ř]5^kixqWyy`aCcHm:##^`[cGcWcOcĤ1F4F5F#A##!`$TcHH=bk4@4Ԙi112#~Q@3;Bex+ĐxW&vI͚՞NkL wVf*q4k&~ÝPHU=|E&(-#]t2H-#]t2ҵ#)؄hL!({YlF-3aMˌnYft2;ݵeF%=eFO-3⽯ Gɑ_֐jམ_1* _jmF$%hbX-a1^Ze~#g89_ Q-S~\R"suM!Ly;G9\u:.Z'cs}%XG,V:jWt\u%:rlI43"YB̙Ob$1^Byl%:o.Xźl2ĕ/ &%~m Ǩ}UK=өQ8 ǝǟd+q^ܵ\mLV2󲥒##DKu9!NiQN>kCz$do(3U$˄ 9:nۄ^s*rr|*$>O?א)T2[ӤԱxa8WZ~v&[4''_$<[$#+3#+1;Q"S7٧CvbL׶M"L*4LA]K)4jʘl~{}6m2T_V$-Wrkd(ר1aC">!fMS :$g Jlѹ}ʰ+KZMGClIͮOs&mdk ޷_^bQ:4O"tR/~(Lmq[k7 ūLiբ+l?xI _>L󐾯:aGN øvZ"s]Mowyuaiב`[z )ѱe5mʚԉ:=kUmwvm?u*藳mڌ+1*e;ikW㣳 [cf[$~vqΊ3LΜRg[B/)[BOO{ݹy(/Ԑs }e 5̯~o4aAo{)V[Z7ˏפWvvf_Ϭt߾ɷgF_>i뗙4g?2U"!x1Noeja$ _Y$s^̷^1YLIӐTTImOU+zWx6JvwJ{|޶YOi@MV=ٿrwxhЃ3nӸ\B :QkX6U^;H_ӔX`ovxw׵毸^\™並ihX^Ĺ򎞸0{zV5*^su<4ta}|fiҏئ5~S'xRha$Տn?w!h3{{Z9ot܈~ u䦆3L{nO^F+֬XeHp@91`;op tpj)N6&.\EGkW2/nP@  1qD{rgYSS:ddkcޣ{bi޶A/gˈE:2W~sUL6|ӷҽ\Lf捔Ͻw^aƩ(i>y+ǜ{8;%%WdFDn.36>{gJeUmI95},;pk o5opSqVnBb4~xa<6!&.' 6=o$FGӅy>Е-6-ዄ,7-V艏 ֕3TV(NWg&7ן*+z=qvkRQgH/->Idy?YWt?cYmg}LU,A$R͚t LWZf:{x\ooִyպì7ڪZ$?b\_,xi ~b&.ʟXr!'Kґuh~Fڀ[nsI͇w}84휑?_E]iWC66z^ĈWJisycvOa-o˼"4-;=xޓg%s17qc=8ͼkp~z-/&淪ǧe{WN;N=V|x w]^\ɜ~̲q?E;~MޔJ}2ԥOǮ9:xvA.tn>gG9]EGŠϪXm4^'z^ֱgv=\iF/sW]^/N^ǯoB?X[?5uuSNhw)yƑ'OT;d~Éޗ]&歶~k_++F4нYrb4䬵٪Hko.|{]AҜҶwC͊iO9}2 /*kA}삧peBq^޿UfǎLؿ۬)7X#.M~5vBO#~|o^fCM!&+vPI\%/{J,L_{| }|\~h[pbo..賶@A5ՐS&cv!E7Xf|<#X}/2:wȾzxAS\s^[aˢr&_׸S 7=5mAjZ*Q/7s)%ln:mcm²-y _A(oQΦO(L;W](Vw}d'On8"^)V޼`ZI¥JF+8D_r'g|15DgyO?ght _7~ϳ >)a 0 ,gbd4fk/c6A "/h<jA/'!5!(1b,v\¶kAM!u= R,j`edHf(br10(00T2y@D +rZ ZRY^XQV412ڪْnmD\{?r{p^euWZ{9ylwyr^ڵg  ;UDe"O^˜7I1Z-;Eo͎'g6dV^̣!jVvY[+ܖ=;iҲ@YegUW쟙ix/GkwaicOM2y+v%AʃۋU,]̼Fif%'.oLHYĤaĤ#6&&Q 8U X+R5@N܈FpVC~(aF<_akSTs}D&ቐ]kPZqfliy6YCG{_߬ݹ;)v_)Գx#bKLf}qi?U։9o͵l=0pk&=9NL 9|_pB\&3|0_PZ endstream endobj 643 0 obj [ 0[ 750] 3[ 278 333] 6[ 556] 11[ 333 333 389] 15[ 278 333 278 278 556 556 556 556 556 556 556 556] 28[ 556 333] 31[ 584] 33[ 584 611] 36[ 722 722 722 722 667 611 778 722 278 556 722 611 833 722 778 667 778 722 667 611 722 667 944 667] 61[ 611 333] 64[ 333] 68[ 556 611 556 611 556 333 611 611 278] 78[ 556 278 889 611 611 611 611 389 556 333 611 556 778 556 556 500] 177[ 556] 179[ 500 500] 182[ 278] ] endobj 644 0 obj [ 278 333 0 556 0 0 0 0 333 333 389 0 278 333 278 278 556 556 556 556 556 556 556 556 0 556 333 0 584 0 584 611 0 722 722 722 722 667 611 778 722 278 556 722 611 833 722 778 667 778 722 667 611 722 667 944 667 0 611 333 0 333 0 0 0 556 611 556 611 556 333 611 611 278 0 556 278 889 611 611 611 611 389 556 333 611 556 778 556 556 500] endobj 645 0 obj [ 226 0 0 0 0 0 0 0 0 0 0 0 0 306 252 0 507 507 0 507 0 0 0 0 507 507 0 0 0 0 0 0 0 579 544 533 615 0 459 0 0 252 0 0 0 0 0 662 0 0 0 0 487 0 567 0 0 0 0 0 0 0 0 0 0 479 525 423 525 498 305 471 525 230 0 0 230 799 525 527 0 0 349 391 335 525 452 715 0 453] endobj 646 0 obj <> stream x|xU9N˔d&I&$3ɐZ4j $@ !)"JłAXbdbA]ˮ]۪Xv ut//gr}SSyQcNB͙Ҩsg56b̅z`7f~dL[Sg-]| cwe}]>o6c1 O_6ǧhߎޅ f%X]9Xa-[fa7}mI;ЖƟ-#ng}RҿԍeMNNG,?mmeXʦ6|Eɦʺ '54KXofR_SO5vnfe,n~.i>_%Uv;Yߚ0Ϳr=K׵*7vԝSw4rNǮY7[R6c~_$3L?zݩ;uԝSwNݩ;uԝSwNݩ;uԝA2w UCBY,aX+bebluQ?1K!qM63w)ǻL\,Uj1~;e.1Ɠx*^~_/k^~?s'_j/'~|?bTL\9Ǭ(ߞT12rL5cj0eƪ52kUw9OF4Ϙ^?mꔺ`MĪ U3ze%Æ 1 NOT Installed libdigidoc-3.10.5/cmake/modules/ID.ico0000664000372000037200000001627613560273132017031 0ustar travistravis00(0`𾛂{WnFnF|WŞĿ|jiiiiiiiiiiiiilzѱpRg?kBkBkBkBkA|XϺhCjAkBkBkBkBkBkBkBkBkBkBkBkBkBkBkBkAmDqJv{[7jBlCkClClClCi?ÜU3g?kBlClClClClClClClClClClClClClClClClClCi@i@̽~V;`kClClClClClCkB}Z~V:^;jAkClClBkClClCqJgOW5iAkClClClClClBe;̾S5d>kClClClClClClCuQxR8W5b=g@jAkClClCkBqJgOW5iAkClClClClClBe;̾V8d>kClClClClClClCvQnK3qI.}Q2Y7`;f@iAlBlCqJgOW5iAkClClClClClBe;̾V8d>kClClClClClClCvQxfnK3kF-oG,yN1V6]:d>h@pIgOW5iAkClClClClClBe;̾W8d>kClClClClClClCvQ߯iVjF-hA%tK.S4Z8gDgOW5iAkClClClClClBe;̾ò[:g@lCkClClClClClCvQ~nK3b; oG,V9gOW5iAkClClClClClBe;̾a>iBlClClClClClClCuQ껪qO8iE,gOW5iAkClClClClClBe;̾we?lClClClClClCkClCsPaŽgOW5iAkClClClClCkBe;̾ƣoJjAlClClClClCkClCiAn$fsEgOW5iAkClClClClCkBe;̾yTh?lCkBlClClClClBlCd<ɯ)j%z&!8bgPW5iAkClClClClCkBj@jÛÛÛ™|jmEi@lClBlClClClCkBlCkB[3)j%z))((,5vfOW5iAkClClClClClClCkBkAkAkAkAkBkBlClClClClClClClCkBb:j(h$w()()))&*eNV3h@kBkBlClClClClClClClClClClClClClClClCkBlCkCkBf?X4'd!p'))))()0cL}P0d>kBlClBlCkClClClClClClClClClClCkClBlClCkCjBe>Y6$^d$x'))))(-~ygoF)Z7f?kBkClClClClClClClClClClClClClClCkBjBg@ab=^:X7uI*m(^V` i!n!mg*iugA'oH,zN0R3T4T4T4T4T4T4T4T4T4T4T4T4S4R3{O0wM2xT:W&^QR'cU~`KqO6rO6sP7tP8tP8tP8tP8tP8tP8tP8tP8tP8tP8tP7vT;`Kvcܱlibdigidoc-3.10.5/cmake/modules/win81.exe.manifest0000664000372000037200000000173013560273132021304 0ustar travistravis libdigidoc-3.10.5/cmake/modules/MacOSXBundleInfo.plist.in0000664000372000037200000000235213560273132022551 0ustar travistravis CFBundleDevelopmentRegion English CFBundleExecutable ${MACOSX_BUNDLE_EXECUTABLE_NAME} CFBundleIconFile ${MACOSX_BUNDLE_ICON_FILE} CFBundleIdentifier ${MACOSX_BUNDLE_GUI_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${MACOSX_BUNDLE_BUNDLE_NAME} CFBundlePackageType APPL CFBundleShortVersionString ${MACOSX_BUNDLE_SHORT_VERSION_STRING} CFBundleVersion ${MACOSX_BUNDLE_BUNDLE_VERSION} NSHumanReadableCopyright ${MACOSX_BUNDLE_COPYRIGHT} NSPrincipalClass NSApplication NSHighResolutionCapable LSHasLocalizedDisplayName LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion ${CMAKE_OSX_DEPLOYMENT_TARGET} libdigidoc-3.10.5/cmake/modules/dlgbmp.bmp0000664000372000037200000160577013560273132020012 0ustar travistravisBM 6(8   ޿ݿݾݽܼܼܼۻۻۺںڹڹڸڸٷٷٶضضصص״״׳׳ֲֲֲֲֳղֱֱֱֲհհհհկկԯԮԮԮԭԭԭԭӭӬӬӬӬӬӬӫӫӫҫѫѫѫѫѪѪѪѪѪѪѪѪѪѪѪѩѩѩѩѩѩѩѩѩѩѩѩѩѩѪѪѪѪѪѪҪ޿ݿݾݽܼܼܽۻۻۺںڹڹڸٸٷٷٶضضصص״״׳׳ֱֱֱֲֲֲֳֳֳִհհհկկկԯԮԮԮԭԭԭԭӭӬӬӬӬӬӬӫӫӫҫҫҫҫҫҫѪѪѪѪѪѪѪѪѪѪѪѪѪѩѩѩѩѩѩѩѩѩѩѪѪѪѪѪѪҪҪ޿ݾݾݽܼܼܽۻۻۺںڹڹڸٸٷٷٶضصصض׵׵״״ֱֱֱֲֲֲֳֳֳִհհհկկկԯԮԮԮԭԭԭԭӭӬӬӬӪӬӬӫӫӫҫҫҫҫҫҫҪҪҪҪѪѪѪѪѪѪѪѪѪѪѪѩѩѩѩѩѩѩѪѪѪѪѪѪҪҪҪ޿ݾݾݽܼܼܽۻۻۺںڹڹڸٸٷٸٷطضضض׵׵״״ֱֱֱֲֲֲֳֳֳִհհհկկկԯԮԮԮԭԭԭԭӭӬӬӬӬӬӬӫӫӫҫҫҫҫҫҫҫҪҪҪҪҪѪѪѪѪѪѪѪѪѪѪѪѩѩѩѩѪѪѪѪѪѪҪҪҪҫ޿޿ݾݾݽܼܼܽۻۻۺںںںڹٹٸٸٷطضضض׵׵״״״׳׳׳ײֱֱֱֲֲհհհկկկԯԮԮԮԭԭԭԭӭӬӬӬӬӬӬӫӫӫҫҫҫҫҫҫҫҪҪҪҪҪҪҪҪѪѪѪѪѪѪѪѪѪѩѩѪѪѪѪѪѪҪҪҪҫҫ޿ݿݿݾܾܼܽۻۻۻۻںںڹڹٹٸٸٷطضٷصضصشش״׳׳ײֱֱֱֲֲֲհհհկկկԯԮԮԮԭԭԭԭӭӬӬӬӬӬӬӬӫӫҫҫҫҫҫҫҫҫҪҪҪҪҪҪҪҪҪѪѪѪѪѪѪѪѪѫѪѪѪѪѪѪҪҪҫҫҫ޿ݿݾݾܼܼܽۻۻۻۻںںڹڹٹڸڸٷٷڶٶصصصشص״״׳ײֱֱֱֲֲֲձձձհհհ԰֯ԯԯԮԮԮԯծӮӬӬӬӬӬӬӫӫӫҫҫҫҫҫҬҫҫҪҫҪԪҪҪҪҪԪҪѪѪѪѪѫѬѫѫӪѪѪѪҪҪҫҫҫҫ޿ݿݾݾܼܼܽۻۼۻڻںںڹڹڸڸڸٷٸٶٶصصصٴشٳ׳׳׳ֱֱֱֱֲֲձױձհհձ԰ԯ԰ԯԮԮԮԮӮӮӭӭӭӭӭӭӬӫӫҫҫҫҫҫҫҫԫҫҪҪҪҪҫҪԪҪҪҪԪѪѬѫѫѬѬѫѫѪҫҪҪҫҫҫҫ޿ݾݾݽܼܼܽۼ۽ۻڻںڻڹںڸڸڷٷٷٶٶصصصش״׳׳׳ײֲֲرֱֱֱձձձհհհԱԯԯԯԮԮԮԮӮӮӮӭӭӭӭӭӬӬӬҬҬҬҫҫҫҫҫԫҫҪҪҪԪҫҫҪҪҪҫҫѫѫѫѫѫѬѫӫҪҪҫҫҫҫԫ޿ݾݿݽܾܽݽۼۼۻڼڻںڹܹڸڸ۷ٸٷٶٶصصضش״׳׳׳ײֲֲֳִײײձձղհհհ԰֯԰ԯԮԮԯԮӮӮӭӭխӭӭӭӬӬӬҬҬҬҬԬҭҫҫҫҬҫҪҪҪҪҫҪҫҫҬҫҫҫѫѬӬѫҫҫҫҬҫҬҫҫҫݿݿݾ޾ܽܽۼۼۻۻۺۺ۹ڹڸڸ۸ٷٷٶٶصضصضٵ׵״״׳ֲֲֲֳֳױձձձհհձԱԯԯԯԮԮԮԯӮӮӮӭխծӭծӭӭӭԬԬҬҬҭҬԬҬҫҫԬҫҫҫҫҫҫҫҫҫҫҫҫҫѬѫҫҫӫҭҬҫҬҬҫҫ߿ݿݿܾݾݽܼܼܼۻۺۺ۹ڹڸڸڸٸٷٷڷضضٵض׵״״״׳ֲֳֳײֲձձձձհձհ԰ԯԯ԰ԯԯԯԮӯӮӮӮӭӮӮӭӭӬӬӬҬҬҬҬҬҭҬԬԬҬҫҬԫҬҫҫҫҫҫԬҬҬҫԫӫҫҫҬҬҭҬҫҫҬҬݿ޿ݾݾ޽޽޼ݼܻݻۻۺۺںڸڹ۸ٸٸٷٷضضضٵ׵ٴ׵׵׳ֲֳֳײֳձձղձձհհ԰ԯԯ԰֮ԮԯԮծկխխӭӭխӭծӬӬӭҬԬҭԭҬԭԭҬԬҬҬԬҫԬҫҫԫҫҫҫҫҬҫԬӫӬҬҬԬҬҬҭҫҭҭ޿޿޿޽ݽܼܼܼܽۺܻ۹ۺںڸڸ۸ٸٷڸٷڶضصض׶״׵״׳ֲֲֳֳִױձձղհձձ԰԰ԯԯ֮ԮԯկӯӮխӭӭխӭӭӮӭӭӬԬҬԬҬҬҬҬҬҬҭԬԭԬԭҫҫԫҫҫҫҬҫӬӫӫӬլҬҭҬҬԬҮҭӬ޿޾ݾ޽ݾ޽ܼܼܽۺۻۺۺڹڹںٹٹڸٸضضضضض׶״׵׵شֲֲֳֳִղղղղձձձԲ԰԰ְ֮ԮԯԮӯӯӭխӭխӭӮӭӬԬӬԬҬԬҬҬҭҭҬԬҬҬҬҬҬҬҫԬҬԫԫҫӫӬӬӬӬլլҬҭԬҬԭӭӬ޾ݾ޾ݾ޽ܼݼ۽ۻۼܺۻܹڹڹٹٹٷٸطضطٵٵ׶׵׵׵سشֲֲֳִղײײղձղֱֲԱԱԱԯԯ԰կԯ԰կխխծӮӮӮӭԬӭӬԬԬҭҬҬԬҬҭҭҬҭҬҭҬҬԬҫԬҬӬӬӫӬӭլӬӭӭԬҬԮԭԭխ޾ݿݾݾܾݾܼۼۻۼۺܺں۹ڸٹٹڸڸطڶٷضضٶ״״ششֳִسײֲղײղײղղձֱֱֱԱԯְ԰ԯկ԰ծծծԯծԯӭӭӭԬӬӭԬҬҭԬԭҭҬԭҭԭҬҭҬҭҭҬӫӬԫԬӭӭױܻܽ԰ҭҮӭӮӭ߾߾޾ݾ޽ܽݼۼۻۼܻںڹڹڹ۸۸ڷڷطضطٶٵ׶׵׵׶׵״׵״״״ײֲֳײֱֱֲԲְ԰԰ֱԯ԰ԯԯկկԯԮկծԮԯԯկӬӬӭӬԬҬҭҬҭԬҬҭҭҭҬҬҬԭӭӭӬӬԮկխծ߿߿޾ݾ޾ܽݽ۽ۼܻܺڻڹ۹ڹٹ۹ٸڷططٷٷط׷׶׶ص׵׵׵׳׳״ֲֳֳײֱֲױղձձձձװկ԰ԯկԯԯԮԯկԮծԯԮԮԮԮӭӭԭԬҭԬԬҬҭԬҭԬԭӭԬԭӭӬ۾ӯ޿޾ܾܾܽݽۼۼܻڻܺںڹ۹ٹٷٸطططضٷ׶ٶ׵ص׵صص׳״״ֲֳֳײײֱֲղձױױձհװկְְ֯ԯԮկԮծկԯկԮԮԮԮԭӭӬҭԭԬҭҬԭԬԬԬԭӬӭӭ޿ܾܽݼݼݻۼۼۻܺںںڹ۸ڸٸڸڷٸڸٶڷڵضضشٴ׵׵׳״״ֲزسֲֲײֲղհձհձׯհկְְ԰Ԯԯ֮֯֯ԮԯկԮԭԮԭԭԭԮӭԭԭӭӭӭԭӭӭӭӬӭݿ޿ܾܾݼܽۼۼۻܻܼڻۻ۹ۺڹڹڸٸٸٷٷطصضضصٴ״ٵ׳״شֳֳֳسֱֲֲղձձձױװհկհ԰ְ֮Ԯԯ֮֯ԯԯԮԯԮԮԮԭԭԭԮԮԬӭӬԭӭӬԭӭԬ޿ݾ޾ܽݽݽۼܼܼۼڼںڻڹںڹڸڹ۷ڸڷٷطڶڶصصٵٵ״׳״״ֳֳֳسֲײֲղװձױձհհְְԯ԰ԯ֯ԯԯ֯֯֯ԮԯԯկԮԮԭԮԭԭԮӭӭԭӬӭӭӭ׵طۻ޿޿ݿܾܽݽ۽ݼܼۼܼܻۻܻܹܺ۸ڹ۹۷ٸٷڶطصضٵٵ״׵״׳״׳سֳزֲֲײײղձձױױױհհհְ֯԰ԯԮԯԯԯԯ֮֯֯֯ԯԮԮԭԮԮԭԭԭӬӭӮծծӯծӮԭԮԭݿݿ޿޽ܾݼݾݽܼܼܽۻۻܻܹںڹ۹۹ٸڸٷٷطڷطٷٶٶ׶׵׵׵صشֳششֲֲֲײײղײױձձְֱֱֱ԰ԯ֯Ԯԯ֯ԯ֮֯ԯ֮֯֯ԮԮԮԮԮԮԮӮӮӮӮݽӮկկծծ֮Ԯ֮ױݿݿܿܿݾܾݽܼܽۼݻۺۻܺںڹ۸ٷ۸ٸڷڷططڷطض׶׶׵ٵ׵صشֳִشֲֳ׳ճ׳ղײղհݼְֱ԰Ԯ֯ԯԯ֮֮ԯԮԯ֯ԯԯ֯կԯկԮկկӮծծծկӮկկ֮Ԯ֮֯ԯ԰޿ݾܾ޾ݽܽݼݼݻܻܺںܺڹڸ۸ٺٹڸٸڸڷططٶٶٶٵ׵ص׵ִششֳִײֳ׳ճײظص԰ְ԰ԯ֮֯֯֯Ԯԯԯ֯֯ԯ֯կկկԯկկծܼԱկկԯկְְ֮֮֯֯֯հݿ޿ݾܾݽܼܽݼݻܻܻܻܺںۻڸڷطٷض׶׶ٵ׵ص׵شִشִ׳׳׵ۻ԰԰԰԰֯ԯ֮֯֯ԯԯԯԯ֯֯ԯկԯկԯկӯկկկ֯ԯְԯԯְְ֯կײ޿޿޾޾޾ݽݽݼۼݻۻܻڻܾܻܽ۸ٹۼ޿ܼ԰԰԰԰԰֯ԯ֯ԯԯԯ֯ԯ֯֯ԯկկկֲհկԯԯԯ֯԰ְ֯ԯְ԰ְְֱ߿߿ݾ޾޽ݾݽܼݽݼܽۻ۽԰ְְ԰ְֲ֯֯ԯ֯Աԯ֯֯ԯկԱկӯկԯկ֯ԯְ԰ְְְհְְֱݿݿ޾޾ܿݾݾܽ۽ݼڸְְְְְֲ֯֯ԯ֯֯֯֯֯֯կկٶկԯկְ֯֯԰ְֱ԰ְְֱձձ߿޿޾޾޿ܾݽݽܿشְ԰ְְְֲ֯֯ԯֱ֯֯֯֯ԯԯկկ֯֯԰ְְְְְֱղױױֱݿ޾ݾݿײױձְ԰ְְֲ԰Բԯֱ֯֯֯֯֯׶կկְ֯֯԰ְְԱԱհְֲױױֱ޿޿޾ںܽ׳׳ײײְֳ԰ְְְֲ֯֯ԯԯ֯֯ײԲԯֱԱְԲְֱֱֱֱֲֲײղױֱ޿ܼۺۺںڹڹڹڸڹݽۼٶصش״׳׳׳ײֲײ޿ְֲԲְ԰ְ֯֯֯֯صկ֯֯Բ԰ְֱֲֲձֱֱձױױױֳܼܻܺܺۻڹڹ۹ۺ۹ڸڹڷڸڶڸٶٶٵٵ׶ٶٵسֳ״׳׳׳ײֲصضֲֲֲ԰ֲֲԯֱݽհְְְֱֱֱֱֱֲֲ֯ױײױճײֳܻܻܻܽܺܺۻۻ۹۹ٸ۹ڹڷڸڸڶڶٶٶٵٷٶٶصصسسسֳ׳ײֲֲ۽ְְ԰ְְְٶְְְֱֲ԰ֱֲֲֲձֱױױײױճ׳ֲܼܻܼܼܽܽڻۺۻ۹ٹۺ۹ڸڷڸڸڸڶطٶٵٵٵششسصصسسײײ׳ְְֲֲֳݽٷְְֲֲֲֲֲԲֱֱֱֱױױ׳ճײײ״ݽݽݼݽܼܼܽܺܺۻ۹ۺ۹۸۸ڹڷڸڸڶڶٷٶٷٷ޾ششصصصصصسش׳ײֲֳֳعְְְֱֱֱֲֲֲֲֲֲձײײ׳׳ײ׳״ݿݽݼݽݽܻܻܼܼܺۻۻۺۺ۸۸ڸڷڸڷڷڸٶٷٷܺطشصششصصصسسش׳׳ֳֳضٴְְְֱֱֱֱֱֱֲֲֲױײײ׳׳ײ׳ز״ݿݿݽݽݼݽݼܻܻܼܼܺۻۻ۹۹ۺ۹ڹڹڸڷڸڷٷٷڷٸشصشصشصصسسصششײ׳ֲֳײװְֱֱֱֱֲֲֲֲֲֳײײײױױ׳׳شس׳޿޿޿ݽݼݼݼܼܼܼܽܺۻۻۺۺۺ۹ڹڹڷڸڸڸٷٷܻڶضصصصصصسصصصصشش׳׳ֲֳٴײײװֱֱֱֱֲֲֲֲֲֳ׳׳ײ׳ױײ׳شزس״޿޿޿޿ݽݼݽݽܼܻܼܻܽۻۻۺۺ۹ۺںںڹڹڸڷٷٶٵضشصصشصصصسصسششش׳׳ֳطڷذװװ׳׳ֱֱֲֲֲֲֲֲֳֳײ׳رױ׳׳ײششس׳޾޿޾޿ݽݾݽݽܼܼܻܽܽۻۻۺۺۺۺںڸڸڹڹڹݾٶٶٵضضصصشصڵصسصصصششײײ׳ֲ׳ײײײײ׳׳׳ֱֲֲֲֲֲֲֳرײ׳׳ױ׳׳׳ششسڴ׵߿޿޿ݾݾݽݽ޽ܼܽܽܽۼۼۻܺۻۺܺںڹܹڹڸٷٷٷٶضضصصصصصسصصصصصشش׳س׳شײײײײװ׳ױ׳سֱֱֲֲֲֲֳֳ׳ײ׳ٴ׳׳׳زشششص׵޾޿ݾݾݽݽܽܽܽܽݼۼۼۻۻܹۺܺںڹڹ۹ںٷٷٷٷٷڶضصصصصڵصصصصسصزس׳׳ײسײײ׳س׳׳׳׳ֲֲزֲֲֳֳس׳׳ײ״׳ײٴشششصصصݿݿݿ޾ݾܾܼܽܽܽݼݼݻۻۻۺںܺںڹ۸ٸٷٷٷٷطضصصڵصصصڵڵصصصص׳س׳׳س׳س׳سٳ׳׳׳ֲֲֲֲֳس׳׳׳״״״׳׳شٴسصصصٴݿ޿ݾݾܾ޽ܼܽܽۼۼݻۻۻۺںܺܺڹ۸ٸ۸ڷٷڷٷططصڷصطڵڵصڵڵصصصص״׳׳س׳׳׳ٳٳس׳׳ֲزֲֳֳ׳׳׳״ٴ״״׳شششڴڵصصضݿݾܾ޽޽ݽݼۼۼۻۻۻۺܺںںں۸ٺٸٸڷٷٷطططڵصصڵصڵصڵصصصصش׵״׵״ٳ׳ٳ׵׳׵׳ֲزֳֳس׳׵״״״ٴ״ششششڶڵڵٶٶݾܾܼܿܽܽݾۼۻۻۻۼںںۻٸٺ۸ٸٸڹٷٷٷڷطضصطڵڷڵطصڵصصصص״ش״״ٳ׳ٳ׵׳׵׳ֲֳֳس׳׳׳״״ٴ׶ٴضشڶصطٷٵٶٶܾܽ޽ܽݼۼۼۻۻܻۺܺܺۺۺٸٸٸ۸ٹٹٷٷطططصڷصصططصصصصٵض״ش״״شٷٳ׳׳׳׳׳ֳֳ׳׵س׳״ٴ׶״ٵٵشڴصصڷٵٷضض޾޽ܽݾݼ۾۽ݻۻۻܺۺܺڹٺٸٸ۸ٸڷٷٷٹٷطڷطڵصڵصصطڵطصصٷٶ׶״״״ٳ׵׳׳ص״سص׳سس״ٶ׶׶صٵٴڴصڵصٵڶڶڸڸܾ޽޿ܾܾۼݼۻ۽ۻۻܺڹںںۺٸٸٹ۸ڹڹٷڸطططڵڵصڵصڵڵطصٵٵ״׶״ٴ״ٹ׳ٳٳ״״׵׳س׳׳ٴٶٶ״ضصصضشڵڷڷٷڶڶضط߿ܿܿݽݼۼݼۻܻܻܽܺۻڹڹٸٸۺٸٸٹڷٷڹڷططضصڵصڷڵصصٵٵٷٶ״ٶٴ״ٴٸٳٴ״ضش׵ص׵״״ٶ״ٵضصڷشڶصڵڶڷٶضڷطݿܾܽݾݽܽݻܽۻۻۺ޿۹ڹڹ۸ٸ۸۸۸ٹٹٷٹڸڷطڷڵڷصطڵڷصصطصص״׶ٴ׶ٴٴ׵׶ش״س׵ٵٴ״ٶٶضططڵڶڵڷڷڶڸٸڷڷٹ޿ݾݾܽܽݽܼܻܼݻۻۻۻ۹ٸۺٺۺٸ۸ڹٷٹٷٷڷڷضڵطڵڷڷصصٵصٷ׶״׶״״ۺ׵ٶضشضٵ׵״ٶٴ׶ضٵصطڷڵصٷڶٸڶٸڹٹڹ߿ݿݿݿܾݾݽݽݽܼܽ߿ۺۻۻۺڹۺٺۺ۹۸ڹڹڹڹڸطڷڷطڷڵڷڷڷڷٵصط׶ٴ׶ٶ״ٴٶضضض׶׵ٴ׶ٶٴٶٷٷڷڶڵڷٷڷڸڸڸڷطڹٸݿ޿ܾܽܽݼܽܽܽܺۻۻۺ۹ٸۺۺٸ۸۹ڹڹٹڹڷڷڷڶڷططڷڵطٵصصٶ״׶ٶٶ׶ضض״ٵ׶״׶׶ٴضططڷڶڷڷٷڷڸڶٸٷڹڷڸۺ߿޿ݿݽݽݼܻܻܽܽۺ۹ڹۺٺ۸۸۹۹ڷٹڷڷڸٸڷطڷڷڷصڵڷصٷٷٶ״׵ٶٹٶٶ׶ٵٷ׶ٶ׶ٶٵطڵڷضظڵڷڸٸٶٸڹڹٹٺٺ޿ݿܾݽܼܼܽܺۻۻۻۺ۹ۺۺۺۺٸ۹ڷڹڷڷڸڸڷطڷڶڶڷڷٶٷٷٶ۹ڶڶ׵ٷٵٶ״صٵٷڷڷڷظٸڷڷٸٸڸڹڹڹ۸ۺۺ޿޿ݿݾݼܻܻܽܽܽۻۺںۺۺٺۺ۹۹ٸڹڹڸڸڸڸڸڸڷڷڶڶٷܽڵطٷٷٶٶٶٷٷطڷطظڸڸٷڸ۸ٷٹڹڹٹۺۺۺܾݾݾܽܽۻۻۻۺۺۺٺۺۺ۸ٹ۹ڹڹڸڸٸٸڸٸۺڶڵٷ׷׷ضٶٷططڷڶظڶڶڷڸ۸ٷڹڹڹڹ۸ٺۺۻݿݾݾܾܽܽܽۻۺۺۺۺۺۺٺ۹۹۹ڹڸڸݾڶطڵ׷ٷٷضٷٷڷطڷڸڸڸڷٸ۸۸۸ڹڹڹۺۺٺۻۺݾݾݾݽܽݿڷڷڷڷ׷ٷطٸٷڷڷڷظڸڸٸڸ۸۸۸ڹڹڹۺٺۺۻۻۺܾݾݽܾܽܽۺطٷڷڷڷڷڷٷٷٷٷڷڷڷڸڸڸڸڸ۸۸ٸ۹ڹڹڻۺۺۺۻۻۺ޿ݾݾݾݽܼܽܽܽڸڸڸٷٷ۹ڷڷڸڷڸٷٷڷڷڷڸڹڹڸڸڸ۸۹۸۹۹ڹۺۺۻۺۻۻۻܻ޿ݾݾݽܼܻܼܽܽܽܺ۸۸۸۸۸ڸڹڸڷܼܺڸڸڷڷڸٸٷڷڷڷڷڸڸڹڸڸ۸۹۸۹۹ںںۻۺۻۻۻۻܻܻ޿ݾݿݽܻܻܻܻܽܽܽܽۻۻۺۺܺۺۺۺۺۺ۹ۺ۸۸۹۹ڹڸڷڷڸڷڸڸڸڸٷڷڷڷڷڸڹڸڸ۹۸۸۸۹۹۹ڹۺۺۺۻۻۻܻܻܻ޿ݿݾݽܽܽܽݼݻܻܻۼۻۻۺۺۺۻܺܺۺ۹ۺۺ۹ܺڹڹڸڷڷڸڷڷڹڸڹڷڷڸڹڸڹڸ۹ڹڹ۹۸۹۹ۺ۹ۺܺۻۻۻۻܻܻܻܻ޿޿ݿݿݾܼܼܼܻܽܽܽܽۼܼۻۺۻۺۺۺܹۺܹۺۺܺۺںںܼڸڷ۷ڷڹڸڸڹ۸ڷڸڸڸڹ۹۹ڹ۹۹۹ۺ۹۹ۺۺۺۻܻۻۻܻܻܼܻݿݽܼܼܼܽܽܽܽݼۻۻۻۻۺۺۺۺ۹۹ܹ۹ۺۺںۺںܼ۷ڸڹڹڸڸ۸ڷڸڸڸڹڹ۸ںڹ۹۸ܹ۹ۺۺݺۺۻۻۻۻܻܻݻܼܼܼ޿޿ݾݾܼܼܼܻܼܽܽܽܽܽۻۻۺۺۺۺۺܺ۹ܹۺܹڹںڷڸڸڹ۹ڹ۸ڹ۸ڹڸڹڸڹڹ۹ܺ۸ۺ۹ۺ۹ܻۻۺۺۼۻۻݼܼܻݻܽ޽޿ݿܼܻܼܼܼܽܽܽܽܽۼۼܼۺۺۺܺ۹۹ܹܺۺڹۺںڸ۸۹۹۹ڹڹڹڸڹڹڸڹںۺܺ۹۹ܺ۹۹ܻܻܻۻۼܻۻܼܻܻܻܽݼ޼޿ݾܼܽܽܽܽܽݼܼݼܼܼۼܼܻۻܺܺܺܺۺۺںڹݾ۹ڹܸܸܹܹڹۺڸ۸۹ڸڸڹۺ۹ܹۺۺܺܺݻܺۻۻܼۼܻܻܼܼܼݽ޽ݽݾܾܿݽݽܽܽݼܼܻܻܼܼܽۼۻۻܻۻۻۺۺۺۺںںܹ۸۸ܹ۹۹ڹۺڹ۹ڹںڹۺܺ۹ۻܹܻܺܺݻܻۻۻۼۻݼܼݼݼݼݽ޼ݽݾݿܾݽݽܼܽݼܼݽݼܼݼݻܻܻۻܻܻܻۻܻܻںܻܿ۹۹۹۹۹۹ںۺۺڹڹںڹܺۺܺۻۺܺۺܻܺݻܻۼۼܼܼܼܼܼܼܽݼ޽ݾ޾޿޿ݾݾܽܽܽݽܽݽܼܽݼݼݺܻݻܻݻۻۻܻۺںۺܺ۹ܹۺۺۺۺۺڹ۹ںۺۺۺܺۻܻܻܻܻܺܺܺۼܼܼݽܼݼܼܻܽ޽ݽݾݽݾݿݿܾݽܽܽݽܽܽܽܽݼܼܻܻݻݻݻܻܻܻܺۺ޽ۺ۹ܺܺܺܺۺںۺ۹ںۺܺۺܺۻۻۻܺݻݻܻܻܼܼܼܼܼݼݼݼݽݽ޽޾ݾݿݿ޿޿ܾܾݽݽܽܽܽܽܽܽݽܻݻݻܻܻܻܻܽܺۺۻܺܺܺܺܺںۺۻںۺۺۺܼۻܻܼܻܺݻݻݻݼܼܼܼݽܼݼܼܾݽ޽޾޾ݿ߿ݿݿ޿ݾݾݾܽݽܽܿܽݽݽܽݼݻݽݻݻܻܻܺۺۻۻܼܺܺܺܺںۻۺܺۺۺܻۻۻۻܻܻݻܻݻݼܼۼۼܽݼܼܼܽݽݽ޾޿޾޿߿޿޿޿޿޿ܾܾܾܽܽݿܾݽܽݼݽܼݼܻܻܻܽۺۼۻܻۺܺܺܺܺۻۼܻܺۺۺܻۻۼܽۻݻܻܻݽܼݼܼܾݽܾܽݾܽ޽ݿݽ޿޾޾޿߿޿ݿ޿޾ݾݿݾݽܾݽܽݾݾܼܼܼݼܼܻܽۻۻܼܼۺۺۺܻڻܻܺܺܺۻܼۻۻܻܽݻܻݻݼܼܼۼܽݽݾݾܽ޽޽޿ݿ޾޾޿޿ݿ޿޿޾ݾݾܾݾݾݽݽݼݼݼݼݼܼܼܼܽۼܻۺܺۺܻܻۼܻܼܺܺۻܻۻۻܻݼݻܻݻݼݼܼܾݾݽܼܾܽܽ޿޽ݾ޿ݿ߿߿޿޿޾޾ܾݾݽݾݼܾܾܼݾݾܼܼܼܻ޿ۼܻܼܼܻܻܺۼܼܻܻܻܻܻܺݼݽݼݽݻܼݽݼݾݽݽݽܾܾݽݽ޽ݿݾ޾ݿ޾޾ݾݾݽܾܽݾܼݾݾܼܽܽݿܻܼܻܻܻܽۼܻۻۻܻܻܻ۽ݼܽݼܻݽݽݽܼݼݾݾݿݼݼݽݿ޿޾ݾ߿߿޾ݿ޿ݾݾܾܾܾܽݾܾܻܻܽݻܻܼܼܼܽܽۻܻۻܽݽݼݽݾܻܼݼݾݾ޽ݾݿݽݾܾ޿޿޿޿߿޿޿޾޿ݿ޽޿ݽݾݾܾܽݽݽܻܻܻܼܼܻܼܻܽܽݽݽݼݼݽݽݼݾݼ޾ݽݿݽݼݾݿݽ޿޿޿޿߿޿޿޿ݿ޿޿ݿݾݻݽܼܼܼܼܽܽܽܽܽܽܽݽݽݾݽݽݽݾݾݾ޾ݿݿݿݾ޽޽޿޾߿޿޿޿޿޿ݽݾݽݽݽݽܼܼܼܻܽܽܽݼݽݽܽݾݾݽݽݼݾ޾޾ݿݿݿݾ޿޿޿޾޿޿޾޿޿޾ݽݽݽݽݽܼܼܽܽܽܽܽݽݼݽݼݾݾݾݽݾ޾޾޾ݿݿݿݾ޿޿޿޿޿޿ݾݽݽݽݽݽܼܽܽܽܽܽݽݽ޽ݽ޾ݾ߾ݽݽݾ޾޾޾޿ݿݽݿ޿޿޿޿޿޾ݾݾݽݽݽ޽ݽܽܽܽܽ޽޽ݾݽݽݾݾ߾ݾݽݾ޾޾޿޿ݿ߿޿޿߿޿޿ݾݾݾݾ߽ݽ޾ݾݽܾܾܾܽݽ޽ݽݽݾݾݾݾݾݿݾ޾޾޾޿߿ݿݿ޿޿޿߿ݾ߿ݾݾݾݽݽݾ޾ݾ޾޿ܾ޾ݾݽݽݽݾݾݾݾݾ߾ݾ߾޿޾޿޿ݿݿ߿޿޿߾ݾݿݾݾݾ߾߽ݿݾݾ޿ܾݿݽݽݾݽݾ޾߾ݾݾݾݾ߾߿߾޾޿ݿ߿޿޿ݿݿ߿߿ݾݿ߾߾ݿݿ޾ݿݾݽݽ޾޾ݿ޿ݾݾݾ߾ݿ޾߿޿޿޿ݿ߿޿ݿݿ߿ݿݾݾݾݾ߿޾޿޿޾޿ݽݾݿݿݾݿݿݾݿݾ߾߿޾޿޿޿ݿݿ޿߿޿޿߿޾߿߿߿޿߾޾޿޾ݿ޿޾޿ݿݾݿݿ߿߾ݾ߿ݾ޾޿߾߿߿޿޿߿޿޿޿߾޿޾޿޾޾ݿ޿ݿ߾߿߿ݿݿ߿ݿ޿߿޿޾޿߿߿߿߾޿߿޿߾߿޿޾޾޿޿߾߿ݿݿݾ߿ݿ޿߿޾߾߿߿޿޿߿޿޾߿޿ݿݿݿ߾ݿݿ߿ݿݿ߾߿޿޿޿ݿ߿߿ݿ߿߿߿߿޿߾޿߿߿ݿݾ߿߿߾߿߿߿߿߿߿߿߿ݿ߿߿ݿ߿޿߿߿߿߿޿ѼsuQN#N#N#O#O#O#N#vQtѻݻa9N#O#O$P$P$P$P$P$P$P$P$P$O$c:ŧѺ}\vQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvQvRvRvQvQtһƮй_9M#O#O$P$P$P$P$P$P$P$P$P$P$P$P$P$O$lEи®gW.N#O#O$O$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$O$O$O$O$O$Y/vQӼȰL"N#P$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Z/йڹ}M"O#P$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$P$P$wQŨŭK!N#P#Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Y/и۬gM"O#P$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$P$P$]ҽцS,M"O#P$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$P$mF۪fL"N#P$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$Q$P$d:̳ްtK"O$Q%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%Q$˲͹K"N#Q$R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%Q%oGǮ}H!M#P$Q%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%Q%c;݌]8L"O$Q%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%Q%j߾I!M#P$R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%P$ѺƯI!M#P$R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%Q%e;ѻߟ{[J!N#P$R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%P$uݟz[J"N#Q$R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%R%Q%ͳހQ+K"O#R$S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%Q$wR݁R+L"O#R$S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%S%R%vyF K"O$R%S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&R%Y0zG L#P%R&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&R&kyF K"O$R%S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&R%O$ĭ{G!L#P%R&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&R&ƪyG L"P$S%T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&S%P$ĭ|H!M#Q%S&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&S&ԽyG L"P$S%T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&S%P$ŭ|H!M#Q%S&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&]1һyG L"P$S%T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&S%P$ĭ|H!M#Q%S&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&T&S&pHzH!M#Q%T&U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'T&Q%Ů}I!N$R%T'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'T'zH!M#Q%T&U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'T&Q%Ů}I!N$R%T'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U'U']2zI!N#R%U&V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'U&R%Į}J!O$S%U'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'U'U'T&T&T&T&T&T&T&T&T&U&U'U'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'U'l{I!N#R%U&V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'U&R%Ů}J!O$S%U'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'U'T&S&R%Q%Q%Q%Q%Q%Q%Q%R%R%S&T&U&U'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'V'T&{I"N$R&U'V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(U'R&ů}J"O%S&U(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(U'S'Q%O%N$M$M$M$M$M$M$N$O%P%Q&R&S'T'U(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(V(U(m|I"O$S&V'W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(V'S&ů~K"P%T&V(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(V(U'R&O$L#}J"{I!zH!zH!zH!{I!{I"}J"~J"L#M$O$Q%S&T'V'V(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(V(U'|I"O$S&V'W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(V'S&Ů~K"P%T&V(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(V(T'oHvRsQpPpPpPpPpPpP|P,vF wF xG!{I!~J"L#O$R%T&U'V(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(W(V'Ǭ}J"P$T&W'X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(W'T&ƮL"Q%U&W(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(W(U&ȯį{[uF xG {I!L"N$Q%T&V'W(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(W(rJ}J#P%T'W(X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)W(T'ůL#Q&U'W)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)W)U'DZҳ}P,xG!}J#N$Q&T'V(W)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)W)V(}J#P%T'W(X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)W(T'ƯL#Q&U'W)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)W)U'ȯȔpPwG!|J"M$Q&T'V(W)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)X)V(Ǭ~K#Q%U'X(Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)X(U'ƯL#R&V'X)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)X)V'ȱ߭txH!}K"O$S&V(X(Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)Y)X(|V~K#Q&U(X)Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*X)U(ưL$R'V(X*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*X*V(ȱ༥xH"L$P&T(W)X*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*X*V)~L#R&V(Y)Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Y)V(ƮM$S'V(Y*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Y*V(ɱইi{J"N$S'V(Y)Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Y*W)Ӿ~L#R&V(Y)Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Y)V(ưM$S'V(Y*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Y*V(ɱԈ]:~L#P&U(X)Y*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*X)ζM#R&W(Z)[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*Z)W(ưN$T'W(Z*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*Z*W(ȱư|K"O%T'X)Z*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*[*Y)£M$R'W)Z*[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+Z*W)ưN%T'W)Z*[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+Z*W)ɱsRM%S'W)Z*[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+Y*}WN$S'X)[*\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+[*X)ưO%T'X)[*\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+[*X)ɱƱM$R&W(Z*\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+[*tL߀N$S'X)[*\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+[*X)ưO%T'X)[*\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+[*X)ɱ}L#Q&V(Y*[+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+[*X)N$T'Y)\*]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+\*Y)ǰP%U'Y)\*]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+\*Y)ʱuSQ%V(Z)\*]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+\*Y)N%T(Y*\+],],],],],],],],],],],],],],],],],],],],],],],\+Y*DZP&U(Y*\+],],],],],],],],],],],],],],],],],],],],],],\+Y*ɱฝP&U(Y*\+],],],],],],],],],],],],],],],],],],],],],],],\+Y*߀O%U(Y*\+^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,]+Z*DZQ&V(Z*]+^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,]+Z*ɲϼP%V(Z*]+^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,]+Z*߀N%S'W)[*]+],^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,]+Z*ǰQ&V(Z*]+^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,]+Z*ɱDZP%V(Z*]+^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,^,]+Z*~M%Q'U)X*Z+[,\,],]-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-],Z+ɲDZQ'V)Z+],^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-],Z+ɲP&U)Z+],^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-],Z+{K$O%R'U(W)Y*Z+\+],^,^-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-^,[+ʱǰR'W)[+^,_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-^,[+ʲP&V)[+^,_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-^,[+xI#{K$~M%P&R'T(V)X)Y*[+\,],^,^-_-_-_-_-_-_-_-_-_-_-_-_-_-^,[+ʲǰR'W)[+^,_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-^,[+ʲQ&W)[+^,_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-^,[+Ӿ`<|L%N%O&R'T(U)X*Z+[,\,]-^-_.`.`.`.`.`.`.`.`.`.`.`._-\,˲DZR(X*\,_-`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`._-\,ʲR(X*\,_-`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.^-[,DZk{L$}M%O&Q'R(T(W)X*Z+\,]-^-_-_.`.`.`.`.`.`.`.`._-\,ʲǰR(X*\,_-`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`._-\,ʲՇS(Y+],_-`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.^-[,տkH|M%~N&P'R(T)V*X+Z,\-]-^._.`.a/a/a/a/a/a/`.]-˳ȱS(Y+]-`.a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/`.]-ʳɲU)[,^.`/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/_.\-ѽkV1~N&P'Q'S(U)W*Y+[,\-^._.`.`/a/a/a/`.]-ʳȱS(Y+]-`.a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/_.]-ʳҿW*[,_.a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/_.\-DzkH|N&O'Q(S)U*W+Y,[-]-^._/`/a/b0`/^.ʳȲT)Z,^.a/b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0`/].˳ᾣY,].`/b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0`/\-ҽkW2~N&P'R(T)V*X+Z,\-]._.`/_/].ʳȲT)Z,^.a/b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0`/].}X[,_.a/b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0_/\-dzvU}N'P(R(S)V*X+Z-\-^.^/\.˳ȲU*[-_/b0c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1a0^/֎Y,^.a0b1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1b1`/[ɰxX2~O'Q(S)U*W+Y,Z,Y,ʳɲU*[-_/b0c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1a0^/͸[-_/a0c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1b0`/[dzwU}O(P(R)T*U+U+ʲɲV+\.`0c1d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b1_0nD_/b1c2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b1`0ç,jǐɸb>P(Q(Q)ɲɲV+\.`0c1d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b1_0ϸ^/a0c1d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2b1_/йY`dgϾa{N(ȲɲW,]/a1d2e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3c2`1ךg:a1c2e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3d3b2_0Y`ehi/y璵ɲW,]/a1d2e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3c2`1zQa1c2d3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3d2a1]/Y`ehjjiiZɲX-^0b2e3f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4e3b2׺sb2d3e4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4d3a2\Zafikkkkkj/z焬ɲX-^0b2e3f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4e3c2̪|Sc2d3e4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4e4d3`1ɰZafikkkkkkkkjZɳX.^1b3e4f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e5d4ǩk>d4e4f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5e4b3^1[bgjllllllllllk0{wɳX._1c3f4g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5f4Īum?e4f4f5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5e4b2pF[bgjlllllllllllllkM桾ɳX._1c3f4g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5`______```wJe4e4f4f5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5g5f4d3`1Ȱ\chkmmmmmmmmmmmmmmml"twʳY._2d4g5h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6f5c3^1\chkmmmmmmmmmmmmmmmmmml?硾ʳY._2d4g5h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6h6g5d4a2s\chkmmmmmmmmmmmmmmmmmmmml#tjʳZ/`2e5h6i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7h7g6c4_2]dilnnnnnnnnnnnnnnnnnnnnnnnl?ʳZ/`2e5h6i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7g6d5`2s]dilnnnnnnnnnnnnnnnnnnnnnnnmj˳Z/`2e5h6i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7i7h6e5b3f<]dilnnnnnnnnnnnnnnnnnnnnnnnmjʳ[0a3f6i7j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8i7g6d5_2^dimooooooooooooooooooooooonkʳ[0a3f6i7j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8j8i7g6d5`3wR]dimooooooooooooooooooooooomjʳ[1a4e7i8j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9j9i8g7d6`4e<^dimpppppppppppppppppppppppnkʳ[1a4f7i8k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9j8h7e6a4]1ª]cimoppppppppppppppppppppppnj˵[0a4f6i8k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9k9j9i8g7e6a4]1͸.nbglopppppppppppppppppppppomiZ1`4e7i9k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:k:j9h9f7d6`4\2ͷY`floqqqqqqqqqqqqqqqqqqqqqpmhY0_3e6i8k:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:k:j9i8f7d5`4\2̸݃^dinpqqqqqqqqqqqqqqqqqqqpnkMX/^2c5h8k9l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:l:k:j9i8g7e6b5^3d<«\aglopqqqqqqqqqqqqqqqqqqomhړ}\[2a5f8i9k;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;l;k;k:j:i9g8e7b6`4\2vS=v^dimoqqqqqqqqqqqqqqqqqpmjeìY0^3d6h8j:l;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;l;l:k:j9i9g8e7c6a4^3[1ݟ\aejnpqrrrrrrrrrrrrrqpnkgiʃW/[1`4d6g8j9k:l:l;l;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;m;l;l;l;l:k:k:j:j9i9g8f7d6b5`4^3[1]K]aejmopqrrrrrrrrrqpomjg"k໣X/[1_4c5f7g8i9j9j9j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j:j9j9i9i9h8g8g8e7d6b5a4^3\2Z1]˵ b]aehkmnoppppppponmkieaˮߖrPW0Z2^4`5c6d7e8f8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8g8f8f8f8e8d7c7b6a5_4^4\3[2Y1s˵ b\_behjkllmmmllkjhfc`ȠԥfW0Y1[2^3_4a5a5a5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5a5a5a5`4_4^3]3[2[1Y1h˸=u[^`befghhhhhgfeca0pƼпrPW/X0Y1Z1[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[2[1Z1Y1X0]~ܟ/m[]^_`aaaaa`_^!f„Ӿ¬q}[}[~[~[}[~\~\~\~\}\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\ܮvK[[\\\\\Lvˮlibdigidoc-3.10.5/cmake/modules/FindXmlSecurityC.cmake0000664000372000037200000000272013560273132022224 0ustar travistravis# - Find XML-Security-C # Find the XML-Security-C includes and library # # XMLSECURITYC_INCLUDE_DIR - Where to find xsec include sub-directory. # XMLSECURITYC_LIBRARIES - List of libraries when using XML-Security-C. # XMLSECURITYC_FOUND - True if XML-Security-C found. IF (XMLSECURITYC_INCLUDE_DIR) # Already in cache, be silent. SET(XMLSECURITYC_FIND_QUIETLY TRUE) ENDIF (XMLSECURITYC_INCLUDE_DIR) FIND_PATH(XALANC_INCLUDE_DIR xalanc/XalanTransformer/XalanTransformer.hpp) FIND_PATH(XMLSECURITYC_INCLUDE_DIR xsec/utils/XSECPlatformUtils.hpp) FIND_LIBRARY(XALANC_LIBRARY NAMES xalan-c xalan-C_1) FIND_LIBRARY(XALANMSG_LIBRARY NAMES xalanMsg XalanMessages_1) FIND_LIBRARY(XMLSECURITYC_LIBRARY NAMES xml-security-c xsec_1) # Handle the QUIETLY and REQUIRED arguments and set XMLSECURITYC_FOUND to # TRUE if all listed variables are TRUE. INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(XmlSecurityC DEFAULT_MSG XMLSECURITYC_LIBRARY XMLSECURITYC_INCLUDE_DIR) IF(XMLSECURITYC_FOUND) SET(XMLSECURITYC_INCLUDE_DIRS ${XMLSECURITYC_INCLUDE_DIR}) SET(XMLSECURITYC_LIBRARIES ${XMLSECURITYC_LIBRARY}) IF(XALANC_LIBRARY) LIST(APPEND XMLSECURITYC_INCLUDE_DIRS ${XALANC_INCLUDE_DIR}) LIST(APPEND XMLSECURITYC_LIBRARIES ${XALANC_LIBRARY}) ENDIF() ELSE() SET(XMLSECURITYC_INCLUDE_DIRS) SET(XMLSECURITYC_LIBRARIES) ENDIF() MARK_AS_ADVANCED(XMLSECURITYC_LIBRARY XMLSECURITYC_INCLUDE_DIR XALANC_LIBRARY XALANC_INCLUDE_DIR XALANMSG_LIBRARY) libdigidoc-3.10.5/cmake/modules/FindPKCS11.cmake0000664000372000037200000000132713560273132020535 0ustar travistravis# - Find pkcs11 # Find the PKCS11 module # # PKCS11_MODULE - pkcs11 module path and name # PKCS11_MODULE_FOUND - True if pkcs11 module found. if( WIN32 ) set( PKCS11_NAME esteid-pkcs11.dll opensc-pkcs11.dll ) else() set( PKCS11_NAME esteid-pkcs11.so opensc-pkcs11.so ) endif() if( APPLE ) find_library( PKCS11_MODULE NAMES ${PKCS11_NAME} HINTS /Library/EstonianIDCard/lib /Library/OpenSC/lib ) else() list( GET PKCS11_NAME 1 PKCS11_MODULE ) endif() # handle the QUIETLY and REQUIRED arguments and set PKCS11_MODULE_FOUND to TRUE if # all listed variables are TRUE include( FindPackageHandleStandardArgs ) FIND_PACKAGE_HANDLE_STANDARD_ARGS( PKCS11_Module DEFAULT_MSG PKCS11_MODULE ) MARK_AS_ADVANCED( PKCS11_MODULE ) libdigidoc-3.10.5/cmake/modules/FindLibDigiDocpp.cmake0000664000372000037200000000176613560273132022133 0ustar travistravis# - Find LibDigiDocpp # Find the native LibDigiDocpp includes and library # # LIBDIGIDOCPP_INCLUDE_DIR - where to find winscard.h, wintypes.h, etc. # LIBDIGIDOCPP_LIBRARIES - List of libraries when using LibDigiDocpp. # LIBDIGIDOCPP_FOUND - True if LibDigiDocpp found. IF (LIBDIGIDOCPP_INCLUDE_DIR) # Already in cache, be silent SET(LIBDIGIDOCPP_FIND_QUIETLY TRUE) ENDIF (LIBDIGIDOCPP_INCLUDE_DIR) FIND_PATH(LIBDIGIDOCPP_INCLUDE_DIR digidocpp/Container.h) FIND_LIBRARY(LIBDIGIDOCPP_LIBRARY NAMES digidocpp) # handle the QUIETLY and REQUIRED arguments and set LIBDIGIDOCPP_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibDigiDocpp DEFAULT_MSG LIBDIGIDOCPP_LIBRARY LIBDIGIDOCPP_INCLUDE_DIR) IF(LIBDIGIDOCPP_FOUND) SET( LIBDIGIDOCPP_LIBRARIES ${LIBDIGIDOCPP_LIBRARY} ) ELSE(LIBDIGIDOCPP_FOUND) SET( LIBDIGIDOCPP_LIBRARIES ) ENDIF(LIBDIGIDOCPP_FOUND) MARK_AS_ADVANCED(LIBDIGIDOCPP_LIBRARY LIBDIGIDOCPP_INCLUDE_DIR) libdigidoc-3.10.5/cmake/modules/FindPCSCLite.cmake0000664000372000037200000000236713560273132021206 0ustar travistravis# - Find PCSC-Lite # Find the native PCSC-Lite includes and library # # PCSCLITE_INCLUDE_DIR - where to find winscard.h, wintypes.h, etc. # PCSCLITE_LIBRARIES - List of libraries when using PCSC-Lite. # PCSCLITE_FOUND - True if PCSC-Lite found. IF (PCSCLITE_INCLUDE_DIR AND PCSCLITE_LIBRARIES) # Already in cache, be silent SET(PCSCLITE_FIND_QUIETLY TRUE) ENDIF (PCSCLITE_INCLUDE_DIR AND PCSCLITE_LIBRARIES) IF (NOT WIN32) FIND_PACKAGE(PkgConfig) PKG_CHECK_MODULES(PC_PCSCLITE libpcsclite) ENDIF (NOT WIN32) FIND_PATH(PCSCLITE_INCLUDE_DIR winscard.h HINTS /usr/include/PCSC ${PC_PCSCLITE_INCLUDEDIR} ${PC_PCSCLITE_INCLUDE_DIRS} ${PC_PCSCLITE_INCLUDE_DIRS}/PCSC ) FIND_LIBRARY(PCSCLITE_LIBRARY NAMES pcsclite libpcsclite PCSC HINTS ${PC_PCSCLITE_LIBDIR} ${PC_PCSCLITE_LIBRARY_DIRS} ) # handle the QUIETLY and REQUIRED arguments and set PCSCLITE_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCSC-Lite DEFAULT_MSG PCSCLITE_LIBRARY PCSCLITE_INCLUDE_DIR) IF(PCSCLITE_FOUND) SET( PCSCLITE_LIBRARIES ${PCSCLITE_LIBRARY} ) ELSE(PCSCLITE_FOUND) SET( PCSCLITE_LIBRARIES ) ENDIF(PCSCLITE_FOUND) MARK_AS_ADVANCED( PCSCLITE_LIBRARY PCSCLITE_INCLUDE_DIR ) libdigidoc-3.10.5/cmake/modules/FindIconv.cmake0000664000372000037200000000300113560273132020700 0ustar travistravis# /kde/kdesupport/strigi/cmake # - Try to find Iconv # Once done this will define # # ICONV_FOUND - system has Iconv # ICONV_INCLUDE_DIR - the Iconv include directory # ICONV_LIBRARIES - Link these to use Iconv # ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const # include(CheckCSourceCompiles) IF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) # Already in cache, be silent SET(ICONV_FIND_QUIETLY TRUE) ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) FIND_PATH(ICONV_INCLUDE_DIR iconv.h) FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c) IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) SET(ICONV_FOUND TRUE) ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES}) IF(ICONV_FOUND) check_c_source_compiles(" #include int main(){ iconv_t conv = 0; const char* in = 0; size_t ilen = 0; char* out = 0; size_t olen = 0; iconv(conv, &in, &ilen, &out, &olen); return 0; } " ICONV_SECOND_ARGUMENT_IS_CONST ) ENDIF(ICONV_FOUND) set(CMAKE_REQUIRED_INCLUDES) set(CMAKE_REQUIRED_LIBRARIES) IF(ICONV_FOUND) IF(NOT ICONV_FIND_QUIETLY) MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}") ENDIF(NOT ICONV_FIND_QUIETLY) ELSE(ICONV_FOUND) IF(Iconv_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find Iconv") ENDIF(Iconv_FIND_REQUIRED) ENDIF(ICONV_FOUND) MARK_AS_ADVANCED( ICONV_INCLUDE_DIR ICONV_LIBRARIES ICONV_SECOND_ARGUMENT_IS_CONST ) libdigidoc-3.10.5/cmake/modules/VersionInfo.cmake0000664000372000037200000000467713560273132021306 0ustar travistravisif( $ENV{BUILD_NUMBER} ) set( BUILD_VER $ENV{BUILD_NUMBER} ) elseif(PROJECT_VERSION_TWEAK) set( BUILD_VER ${PROJECT_VERSION_TWEAK} ) else() set( BUILD_VER 0 ) endif() if(NOT BUILD_DATE) string(TIMESTAMP BUILD_DATE "%d.%m.%Y") endif() set( VERSION ${PROJECT_VERSION}.${BUILD_VER} ) add_definitions( -DMAJOR_VER=${PROJECT_VERSION_MAJOR} -DMINOR_VER=${PROJECT_VERSION_MINOR} -DRELEASE_VER=${PROJECT_VERSION_PATCH} -DBUILD_VER=${BUILD_VER} -DVER_SUFFIX=\"$ENV{VER_SUFFIX}\" -DBUILD_DATE=\"${BUILD_DATE}\" ) set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN YES) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED YES) set( MACOSX_BUNDLE_COPYRIGHT "(C) 2010-2018 Estonian Information System Authority" ) set( MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION} ) set( MACOSX_BUNDLE_BUNDLE_VERSION ${BUILD_VER} ) set( MACOSX_BUNDLE_ICON_FILE Icon.icns ) set( MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PROJECT_VERSION} ) set( MACOSX_FRAMEWORK_BUNDLE_VERSION ${BUILD_VER} ) if( APPLE AND NOT IOS AND NOT CMAKE_OSX_DEPLOYMENT_TARGET ) execute_process(COMMAND xcodebuild -version -sdk macosx SDKVersion OUTPUT_VARIABLE CMAKE_OSX_DEPLOYMENT_TARGET OUTPUT_STRIP_TRAILING_WHITESPACE) endif() if( APPLE AND NOT CMAKE_OSX_SYSROOT ) execute_process(COMMAND xcodebuild -version -sdk macosx Path OUTPUT_VARIABLE CMAKE_OSX_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE) endif() macro( SET_APP_NAME OUTPUT NAME ) set( ${OUTPUT} "${NAME}" ) add_definitions( -DAPP=\"${NAME}\" ) set( MACOSX_BUNDLE_BUNDLE_NAME ${NAME} ) set( MACOSX_BUNDLE_GUI_IDENTIFIER "ee.ria.${NAME}" ) if( APPLE ) file( GLOB_RECURSE RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/mac/Resources/*.icns ${CMAKE_CURRENT_SOURCE_DIR}/mac/Resources/*.strings ) foreach( _file ${RESOURCE_FILES} ) get_filename_component( _file_dir ${_file} PATH ) file( RELATIVE_PATH _file_dir ${CMAKE_CURRENT_SOURCE_DIR}/mac ${_file_dir} ) set_source_files_properties( ${_file} PROPERTIES MACOSX_PACKAGE_LOCATION ${_file_dir} ) endforeach( _file ) endif( APPLE ) endmacro() macro( add_manifest TARGET ) if( WIN32 ) add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND mt -nologo -manifest "${CMAKE_MODULE_PATH}/win81.exe.manifest" -outputresource:"$") endif() endmacro() macro( SET_ENV NAME DEF ) if( DEFINED ENV{${NAME}} ) set( ${NAME} $ENV{${NAME}} ${ARGN} ) else() set( ${NAME} ${DEF} ${ARGN} ) endif() endmacro() libdigidoc-3.10.5/cmake/modules/banner.bmp0000664000372000037200000024761013560273132020004 0ustar travistravisBMO6(:RO  ޿߿߿޿߿޿޿޿޿޿޿޿޿߾޾޿޾޾޿޿޾޿޾޾޾޾޾ݾ޾ݾݾ޾޾޽޾߿ݿ߾ݾ߾ݿ߾޾޾޾޿޿޿޿޾޿޾޿ݾ߿߿޿޿߿߿޿޿߿޿߿߿޿߿޿޿޿޿޽޿޿޿޾޾޽޾޿޾ݾ޿޾ݾ޾޾޾޾ݾ޾ݾ޾ݾ޾ݽݾ߿߿ݿݿݿ޿޾߾߾޿޿޿޿޿޾޾߿߿߿߾߿޿޾޾޾޿޾޿޾޽߿޽޿޽޿޿޽޿޽޾ܿ޾޾޾޾޾޾ݾ޾޽޽޾ݾ޾޾ݾ޽ݿ߾߾ݾݿ߾޿޾޾޿޿޿޿޿޿޿޾߿߿߿߿߾޾߾߿߾߾޾޾޾߾޾ݾ޾޾޾޾޾߾޾޾޽޽޿޾޿޽޽޾ݾܽ޾ݾ޾ݾ޾ݽ޾޾ݾݾݽ޾ݾݿ߿ݾݾݾ߾޾޾߿޿޿޾޿޿޿߿߿߿߿߾߿߿߿߿߿߿ݾݾݾ߾ݿ߾߾ݾݾ߾ݾݾݾݾݾݾݾݾ޾ݽ޾޽޾޽޽޾޽޽޽޾ݾ޾޾޾޽ݽ޽ݾݾ޾޽ݽݾ߾ݿݾݾ޾޿޾߿޿޿޿޿޿޾߿߿߿߿߿߿߿߿߿߿߿߿߾߿߿ݾ߾ݿ߾߾ݾݾ߿ݾݾ߾ݾݾݾݾݽݾݼݾݽݽ޽޽ܽ޽޽ܽ޿ܽ޽ܽ޾ݽ޽ݽݾݽݾݾݽݽݽݿݾ߿ݿݾ޿޾޾߿޿޿޿޾޿޾߿߿߿߿߿߿߿ݿ߿߾߽߿ݿ߿߽߽ݽݽݽݽ߾ݽ߾ݽݾ߽ݾݼݾݾݾݼݾݾݾݽܽ޾ݽݽ޾ܽܽ޽ܽ޽ܽݾݾ޾޾ݾ޽ݾݾ޾޾ݽݾݾݾݾ޿޾޾޿޿޿޿޿޿߿߿߿߿߿߿߿߿߿߿߿ݿ߿߿ݿ޿߿߿ݽ߿ݽ޽޿߿ݽݽݽݽݿݽ޽ݽݽݽݽݽݽݼݼݼݽݼݼܽݾݾ޽޽ܽ޽޽޽ݾ޾ݾݾݾݽݾݽ޽޽ݾ߿ݾ߾ݾ޾߾߾޿޿޿޾޾޾߿߿߿߿߿޿޿ݿ޿ݾݽ޽޿޾޿޾޽ݾݿ޽ݽ޽ݽݾݽݽݽݽݽ߽޽ݼݽݼݽݼݼݽܼݼݼݽݾݽݽ޽ܽ޽޽ܽܽ޾޾ݾݽݾݾݽݾݾݾݾ߾ݾݾ޾޾޿޿޿޾޿޿߿߿߿߿߿޾޾޿޿޾޾޾޽޾޽޾ݼ޾޾޽޾ݽ޾޽ݼݾݽ޽޿޽޽ݽݽ޼ݽ޼ݽݼݼݽݽݽݼݼݼݼܾܽݽ޽޽޽ܽ޽޾ݾ޽޾޾ݽ޽޽޾ݾݾ߿ݾ߾޾߾޿޽޿޿޿޾߿޿޿߿޾޾޾޾޾޾޾޾޾޾޾޾޾ݾܾ޼޼޾޼ݼܼ޼ݼݾݽݼݽݼݽݻݽ޻ݽݽݽݽݽݽݽݼݼݼݼݼܼݽܽ޽޽޽޽ܼܽݽݾ޾޾ݾݾݽݽݽݾ߾ݿݾ߾߾޿޿޿޿޿޿߿߿޿޿޿޿޾޾޾޾޾޾޾޾޾޾޾޾޾޾޼ܾܼ޾ܾ޼޾ܼ޾ݼ޼ݼ޼޾ݼݼݻݼ޼ݻݻݽ޽ݽݽݼݽݽܽݼݼݼܼݽݽܽܽ޼޽ܽ޾޽޾ݽݾ޽ݽݽ޽߾ݾݾݿݾ޾޿޿߿޿޿߿߿߿޿޾޿޾޿޿޿޾޾߾޾޾޾޾޾޽޽ܽ޽ܽ޽޽޼ܼ޽ܼ޼޼޼޼ܼܼܼܼ޼ݼܼܼݼݼݻݽ޽ݽݻݽݼݼݽܽݽݼݼݼݼݽݽ޽޽޽ܼܼ޾ݽ޽޾ݾ޽ݽݽݾݾݾݾݾ޾޿޿޿޿޿޾޿߿߿~ZnHlDxSvϸƯ©ª©ªªªªªĭ˴޿޿޿޿߿߿޾޿޿޽޽޾޽޽޽޽޽޽޽޽޽ܽ޼ܽܽ޽ܼ޽޽޼ܼܼܼ޽޼ܼܼܼܼܼ޼ݼݻݼݼݽݽݻݻݼݼݼݼݼݼݼݼݼݽݽܽܽ޽޽ݾݾ޾޾ݾ޽ݾ޽ݾݾݿݾ޾޾޿޿޿޿޿߿߿θR*N"O#P$Q$Q$P$P#}̧`N#O#P#P$P$P$P$P$P$P$P$P$P$P$P$P$P$P$Q$f>lҼ޿߿޿޿߾޾޾߽߾߾޾޽߽޽޽޽޽޽ݽ޽ݽݽݽݽݽ޼ݽݽܼݻܽݽܽ޼ܼܽ޼ܼܼܼܽ޼ܼܼܼݻܼܼݼݼݻݻݻݼݼݼݽݼݼݼݼܽݽܽ޼ܽܽܽݾ޽޽ݾ޾ݾݽݽݾݾݾ޾߾޿޿޿޿޾߿߿кM%M"P#Q$R$R$R$R$R$P#ζӎa # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES libdigidoc-3.10.5/RELEASE-NOTES.md0000664000372000037200000004713613560273131015577 0ustar travistravisDigiDoc C library [3.10.5](https://github.com/open-eid/libdigidocpp/releases/tag/v3.10.5) release notes ----------------------------------- - Fix OpenSSL 1.1 build on windows [Full Changelog](https://github.com/open-eid/libdigidocpp/compare/v3.10.4...v3.10.5) DigiDoc C library [3.10.4](https://github.com/open-eid/libdigidocpp/releases/tag/v3.10.4) release notes ----------------------------------- - OpenSSL 1.1 support [Full Changelog](https://github.com/open-eid/libdigidocpp/compare/v3.10.3...v3.10.4) DigiDoc C library [3.10.3](https://github.com/open-eid/libdigidocpp/releases/tag/v3.10.3) release notes ----------------------------------- - Minor changes to allow build openssl 1.0 under OSX [Full Changelog](https://github.com/open-eid/libdigidocpp/compare/v3.10.2...v3.10.3) DigiDoc C library [3.10.2](https://github.com/open-eid/libdigidocpp/releases/tag/v3.10.2) release notes ----------------------------------- - Added ESTEID-SK 2015 certificate - Fixed OSX crash [Full Changelog](https://github.com/open-eid/libdigidocpp/compare/v3.10.1...v3.10.2) DigiDoc C library 3.10.1 release notes ----------------------------------- Changes compared to ver 3.10 - Fixed ddoc format and version checking. The unfixed library can crash when reading a ddoc file with unknown format and/or version value. Sertifitseerimiskeskus and RIA thank Aivar Liimets for his contribution. - Fixed validation of DDOC 1.0-1.2 documents that were created with older version of DigiDoc3 Client (with only DDOC 1.0 format support) on Ubuntu and OSX due to incompatibility with OpenSSL base library openssl_1.0.1f. (IB-3997) DigiDoc C library 3.10 release notes ----------------------------------- Changes compared to ver 3.9.1 - Changed validation process of OCSP response so that the responder’s certificate reference is taken from the response instead of the signature’s XML. - Improved DDOC document validation. It is now checked that the issuance time of the OCSP response would be in the validity period of the signer's certificate. - Changed the validation of DDOC documents so that multiple data files with the same name would be allowed in the container. - Improved utility program's output during DDOC document validation. If the signer's certificate is from live CA chain but OCSP confirmation has been issued from test OCSP responder then warning 172 "Signer from LIVE CA-chain but OCSP from TEST CA-chain!" is returned. - Removed duplicate configuration file entry CA_CERT_6 to fix KLASS3-SK 2010 (KLASS3-SK 2010 EECCRCA.crt) certificate's configuration settings. - Removed Finnish CA certificates from digidoc.ini default configuration file. It is recommended to use BDOC format and relevant software instead. - Development of the software can now be monitored in GitHub environment: https://github.com/open-eid/libdigidoc Known issues: - Validation of documents in DDOC 1.0 format fails on Ubuntu LTS upgrade 14.4.1 and newer due to incompatibility in OpenSSL base library openssl_1.0.1f-1ubuntu2.8. The problem does not occur on Ubuntu 14.4 with openssl_1.0.1f-1ubuntu2.7, OSX and Windows platforms. DigiDoc C library 3.9.1 release notes ----------------------------------- Changes compared to ver 3.9 - DDOC security fixes: - Improved XML structure validation for DDOC files. This is a highly relevant security fix having an effect on the validation of DDOC files. The unfixed library can mistakenly give positive results on validation of invalid DDOC files with incorrect XML elements' ordering. DigiDoc C library 3.9 release notes ----------------------------------- Changes compared to ver 3.8 - Improved checking of signer certificate's CA chain length during signature creation and validation. Previously it was not possible to create signature if there was only one CA certificate in the certificate chain. - Improved DDOC files' validation, added check that the signer certificate's data would match the X509SerialNumber and X509IssuerName elements' contents. - Improved DDOC files validation, added check for Transforms elements which are not supported in DDOC files. - Changed signature adding and removal restrictions in case of erroneous files (incl. files that are valid with warnings). No restrictions are made to adding or removing signatures, except of in case of files that are in old format (DIGIDOC-XML 1.0, 1.1, 1.2). - Fixed error of handling quotation marks in ClaimedRole and SignatureProductionPlace elements during signature creation and validation. Quotation marks are not replaced during canonicalization according to Canonical XML Version 1.0. Note that as a result, the files that contain quotation marks in the respective elements and have been created with v3.9 might not be compatible with v3.8 of the library. - Fixed handling of special characters <, >, & and carriage return in X509IssuerName and ResponderID elements. The characters are now replaced during canonicalization according to Canonical XML Version 1.0. Note that as a result, the files that contain these special characters in the respective elements and have been created with v3.9 might not be compatible with v3.8 of the library. - Fixed error which occurred when parsing DDOC document's data file name that contains '&' special character. Previously, the character was erroneously displayed in escaped form. - Fixed error that occurred during signature creation when Windows redirected directories were used. Occasionally, writing the ddoc file to redirected directory did not succeed due to synchronization problems. - Fixed error that caused the library to exit unexpectedly when trying to parse a DDOC file that contained a large number of validation errors. - Changed compression functionality during CDOC encryption process to deprecated, by default the data is never compressed. Removed DENC_COMPRESS_MODE configuration file parameter. - Updated cdigidoc.exe utility program's commands "-encrypt-sk", "-encrypt-file" and "-encrypt" so that "MimeType", "OriginalMimeType" and "orig_file" encryption properties are set according to CDOC 1.0 specification. - Changed ddsGetStatus() function in DigiDocService.h source file to deprecated status, use ddsGetStatusWithFile() instead. The ddsGetStatusWithFile() function enables to determine the DDOC file name to which the signature value is added. - Added command "-mid-test" to cdigidoc-exe utility program, to be used for testing purposes only. The command enables to test the whole Mobile-ID signing process, including creating new DDOC container, adding data file, creating signature, validating the created signature and extracting data files. - Fixed cdigidoc utility program's "-libraryerrors" parameter functionality. When the parameter is set then only the errors that are returned by the library are now displayed as "LIBRARY-ERROR". - Used coverity.com static analysis tool to find source code defects and vulnerabilities. DigiDoc C library 3.8 release notes ----------------------------------- Changes compared to ver 3.7.2 - Started using coverity.com static analysis tool to find source code defects and vulnerabilities. Fixed resource leak and NULL pointer problems that were discovered. - Fixed createDataFileInMemory() method, added fixed SHA-1 digest type value when creating new data file. - Added support for new KLASS3-SK 2010 CA certificate. - Improved the validation of signer's certificate path, added check if all of the chain's certificates validity period includes the signature creation time (producedAt field's value in OCSP response). - Improved error handling in case of missing CA certificates and certificates in wrong format, error code 36 is returned in this case. Only PEM format is supported for CA certificates. - Added support for extracting data files from container so that the data is kept only in internal memory buffers. Added command –extract-mem to cdigidoc.c utility program. - Added validation support for DDOC signatures that are created with Finnish live and test certificates. The certificate files have to be installed with separate packages. The live certificates package contains Finnish root CA certificate (http://fineid.fi/default.aspx?id=596) and certificates which are included in the Finnish national Trust Service List (TSL) (https://www.viestintavirasto.fi/attachments/TSL-Ficora.xml). Finnish test certificates (http://fineid.fi/default.aspx?id=597) are included in the overall test certificates package. - Fixed error handling in case of NULL values in DDOC file’s format and version variables. Acknowledgements. Sertifitseerimiskeskus and RIA thank Aivar Liimets for his contribution. - Added possibility get all validation error codes that were found during DDOC file’s parsing and validation process instead of only one error code returned by the validation function verifySignatureAndNotary(). Added error code 173, which is returned in case of multiple errors. Library user must check the list of multiple errors by using new API functions getLastErrorsIdx(), getErrorsInfo() (in source file DigiDocError.c). - Added warnings system to the library. In case of minor technical errors in the signed DigiDoc file, validation result VALID WITH WARNINGS is used, meaning that the file is legally valid but further alterations (adding/removing signatures) are restricted. It is recommended for the programmers to implement the usage validation status VALID WITH WARNINGS as described in documentation. The warnings system is implemented in cdigidoc.c utility program (identically to DigiDoc3 Client desktop applicaton), warning situations include: - DDOC file's element's xmlns attribute is missing (error code 169) - The DigiDoc file format is older than officially accepted, i.e. the file is DDOC 1.0, 1.1, 1.2 (error code 171). - DDOC file's or element's xmlns attribute is missing (error code 170). - The signature has been created with a test certificate (error code 172). - Changed the priorities of DigiDoc file's validation result statuses. - Added error codes 168 (ERR_DF_NAME), 169 (ERR_DF_WRONG_DIG), 170 (ERR_ISSUER_XMLNS), 171 (ERR_OLD_VERSION), 172 (ERR_TEST_SIGNATURE), 173 (ERR_UNKNOWN_ERROR). - Fixed nonce asn.1 prefix verification if nonce has no prefix but first 2 bytes match required prefix value. - Added validation check of signer’s roles. Maximum 2 elements are supported by the library in a DDOC file. - Added check for duplicate element’s fileName attribute. Multiple data files with the same file name in a single container are not supported. - Improved element's Id attribute validation. Added support for element’s Id attribute value DO (capital O, not zero). - Improved error handling of invalid DDOC files with a missing element. Error 44 ERR_BAD_DATAFILE_COUNT is produced in case of such files. - Fixed CDOC file’s element’s value, ENCDOC-XML 1.0 is used instead of ENCDOC-XML 1.1. - Fixed –validate command’s output in cdigidoc.c utility program to show validation result correctly in case if one signature among multiple signatures is erroneous. - Removed -list command line parameter from cdigidoc.c utility program, changed -verify command so that it replaces the –list command (validates the file and also prints out the data file list). - Fixed error handling in cdigidoc.c utility program if input DDOC file name contained also “.cdoc” in the file’s name. - It is not allowed to add or remove signatures from DigiDoc files with missing element’s xmlns attribute. - Removed configuration file parameter CHECK_SIGNATURE_VALUE_ASN1. Signature values with erroneous ASN.1 prefix values are regarded as not valid. - Changed function verifiedByWrongDataFileHash() to deprecated. - DDOC/CDOC security fixes: - Added check that and elements that are verified are within signed content. This is a highly relevant security fix. Without this fix malicious ddoc files with data not signed by original signer but added by third parties later could have been verified to be valid. - Fixed validation of OCSP response, added check that the OCSP response corresponds to the signer’s certificate. This is a highly relevant security fix. Without this fix specially generated ddoc file with changed OCSP response could have been verified to be valid. - Changed process of searching for CA certificates. The certificates are searched from the secure Program Files directory that is specified with CA_CERT_PATH configuration file parameter, not from the working directory. This is a highly relevant security fix. Without this fix, CA certificate files that may have been added to the working directory with malicious intent would be used by the library. - Fixed the opening of DDOC container with a faulty tag. This is a highly relevant security fix that has an effect on the validation of DDOC files. Acknowledgements. Sertifitseerimiskeskus and RIA thank Aivar Liimets for his contribution. DigiDoc C library 3.7.2 release notes -------------------------------------- Changes compared to ver 3.7.1.992 - DDOC/CDOC security fixes: - Fixed the opening of DDOC container with a faulty DataFile name tag. This is a highly relevant security fix having an effect on the verification of DDOC files. The unfixed library can result in overwrite arbitrary files on the system with the privileges of the victim. DigiDoc C library 3.7.1 release notes ----------------------------------- Changes compared to ver 3.7.0.910 - Changed the handling of DigiDoc container which has no xmlns attribute in the element. DigiDoc C library 3.7 release notes ----------------------------------- Changes compared to ver 3.6.0.26 - Added the support of slot choice option for CDOC decryption with utility - Fixed the search of the signer’s certificate issuer for DDOC verification - Fixed the OCSP hash check error handling for DDOC verification: error messages are correct when there are several errors associated with a container - Fixed the error handling of the DDOC verification function verifySignatureInfoCERT - Added the decrypted transport key option for testing CDOC decryption with utility - Fixed padding control for CDOC - Fixed padding handling of CDOC PKCS#7: now PKCS#7 padding is managed by the openssl - Fixed the DDOC signing function ddocLocateSlotWithSignatureCert: the use of the digital stamp has improved - Fixed the OCSP response handling for DDOC signing - Fixed CDOC packaging according xml-enc standard - Fixed the handling of the initial CDOC file name: the directory path is not added to the CDOC container - Fixed the handling of special characters in the CDOC decryption - Added Mac OSX keychain support for OCSP server access certificates in DDOC signing - Fixed the error handling of DDOC verification in case of the lack of issuer certificates - Fixed the DDOC verification function readAuthorityKeyIdentifier - Added the function signDocumentWithSlotAndSigner to the signing of DDOC to allow signature over CAPI/CNG - Added the support of signing DDOC files in the memory: no temporary files are saved - Added the support of encryption and decryption of CDOC in the memory: no temporary files are saved - Fixed the logic of the xmlns mirroring in the XML root element in the DDOC signing and verification - Added the PKCS12 support for DDOC signing - Fixed the EVP_DecodeUpdate CDOC decryption function: buffer size improvement - Fixed the notarizeSignatureWithIp and finalizeAndVerifyNotary2 functions for DDOC signing and verification: the setting is supported if the ocsp responder certificate has been issued from another chain than the signer’s certificate - Fixed the hash description handling of the ASN.1 signature value for DDOC signing and verification: 13-byte and 15-byte values are supported - Added BOM (Byte order mark) support on DDOC verification - Fixed error handling of the missing OCSP responder certificate for DDOC verification - Removed support for DDOC format version 1.0, 1.1, 1.2 for DDOC signing. Only DDOC verification and exctracting files from container are supported. Creating container, signing and removing signature are not supported - DDOC/CDOC security fixes: - Added the check of the ASN.1 structure of the nonce field for DDOC signing and verification. This is a highly relevant security fix having an effect on the verification of DDOC files. The unfixed library can mistakenly give positive results on verificaton invalid DDOC container with wrong ASN.1 structure on the nonce field. - Added the check of the ASN.1 structure of the signature value for DDOC signing and verification. This is a highly relevant security fix having an effect on the verification of DDOC files. The unfixed library can mistakenly give positive results on verificaton invalid DDOC container with wrong ASN.1 structure on the signature value. - Added the check of the nonce field of the signature for DDOC signing and verification. This is a highly relevant security fix having an effect on the verification of DDOC files. The unfixed library can mistakenly give positive results on verificaton invalid DDOC container with the wrong nonce field value on the signature. - Removed the EMBEDDED type DDOC file support for verification. This is a highly relevant security fix having an effect on the verification of DDOC files. The unfixed library can mistakenly give positive results on verificaton invalid EMBEDDED type DDOC container. - Fixed the signature verification of a DDOC with a faulty DataFile tag. This is a highly relevant security fix having an effect on the verification of DDOC files. The unfixed library can result in the crashing of the application or unauthorized code execution in opening of a DDOC file created with malicious intent. DigiDoc C library 3.6 release notes ----------------------------------- Changes compared to ver 2.6.0.18 - Changes according ETSI Plug test results - Changes according Cross library (jdigidoc & libdigidoc & libdigidocpp) test results (DDOC, CDOC) - Removed DETACHED, HASHCODE, DDOC 1.4, BDOC support - CDOC padding improvements - Updated documentation in doc folder SK-CDD-PRG-GUIDE - Support for software based private keys - Versioning switched to same schema (3.5, 3.6 ...) as other middleware components - Added Mobiil-ID signing support for cdigidoc utility - API change in functions dencOrigContent_findByIndex, dencMetaInfo_GetLibVersion, dencMetaInfo_GetFormatVersion - DDOC/CDOC security updates: - Fix for decrypting or content viewing of CDOC files with broken orig_file tag. This is a significant security fix which affects CDOC decrypting. A library without this security fix can cause application crashes or allow running malicious code upon opening a deliberately created CDOC file. - Fix for decrypting or content viewing of CDOC files with broken EncryptionProperty tag. This is a significant security fix which affects CDOC decrypting. A library without this security fix can cause application crashes or allow running malicious code upon opening a deliberately created CDOC file - DigiDocService intermediate resultate file (DDOC file hashcode) verification fix. This is a significant security fix which affects verification of DDOC files. A library without this security fix can mistakenly give positive results on verificaton of invalid DDOC hashcode container. - Detached DDOC file verification fix. This is a significant security fix which affects verification of DDOC files. A library without this security fix can mistakenly give positive results on verificaton of invalid DDOC container. - Added key usage check in certificate on verification of a signature. This is a significant security fix which affects verification of DDOC files. A library without this security fix can mistakenly give positive results on verificaton of a signature created with incorrect certificate. libdigidoc-3.10.5/libdigidoc.spec0000664000372000037200000000256013560273131016244 0ustar travistravisName: libdigidoc Version: 3.3 Release: 1%{?dist} Summary: DigiDoc library Group: System Environment/Libraries License: LGPLv2+ URL: http://www.ria.ee Source0: libdigidoc.tar.gz BuildRoot: %{_tmppath}/-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: cmake, gcc, libxml2-devel, openssl-devel Requires: opensc, esteidcerts %if %{defined suse_version} Requires: libpcsclite1 %endif %description Library for creating DigiDoc signature files %if %{defined suse_version} %debug_package %endif %package devel Summary: DigiDoc library devel files Group: System Environment/Libraries Requires: %{name}%{?_isa} = %{version}-%{release}, libxml2-devel, esteidcerts-devel %description devel Devel files for DigiDoc library %prep %setup -q -n %{name} cmake . \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_SYSCONFDIR=/etc \ -DCMAKE_VERBOSE_MAKEFILE=ON %build make %install rm -rf %{buildroot} cd %{_builddir}/%{name} make install DESTDIR=%{buildroot} %clean rm -rf %{buildroot} cd %{_builddir}/%{name} make clean %files %defattr(-,root,root,-) %{_bindir}/* %{_libdir}/*.so.* %{_mandir} %config(noreplace) %{_sysconfdir}/* %files devel %defattr(-,root,root,-) %{_includedir}/* %{_libdir}/*.so %{_libdir}/pkgconfig/* %changelog * Fri Aug 13 2010 RIA 1.0-1 - first build no changes %post -p /sbin/ldconfig %postun -p /sbin/ldconfig libdigidoc-3.10.5/libdigidoc/0000775000372000037200000000000013560273131015365 5ustar travistravislibdigidoc-3.10.5/libdigidoc/DigiDocConfig.c0000664000372000037200000022404213560273131020165 0ustar travistravis//================================================== // FILE: DigiDocCfonfig.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for configuration management // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 17.06.2004 Fixed buffer overflow vulnerability in setPrivateConfigFile() // 27.03.2004 Fixed ConfigItem_lookup_bool() // 20.03.2004 Added functions createOrReplacePrivateConfigItem() // writeConfigFile(), writePrivateConfigFile() // 20.03.2004 changed function notarizeSignature to check for PKCS12 arguments // 10.02.2004 Integrated // 29.01.2004 changed function notarizeSignature // 26.01.2004 Added include // 08.01.2004 Veiko Sinivee // Creation //================================================== // config data comes from there #include //AA 04/01/26 #ifdef WIN32 #include #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif #elif defined(__APPLE__) #include #endif #include "libdigidoc/DigiDocConfig.h" #include "libdigidoc/DigiDocPKCS11.h" #include "libdigidoc/DigiDocDebug.h" #include "libdigidoc/DigiDocCert.h" #include "libdigidoc/DigiDocObj.h" #include "libdigidoc/DigiDocOCSP.h" #include "libdigidoc/DigiDocConvert.h" #ifdef WIN32 #include "libdigidoc/DigiDocCsp.h" #endif #include #include #include #include #include #ifndef _MAX_PATH #define _MAX_PATH 200 #endif #ifdef WIN32 #define DIGIDOC_CONF_NAME "digidoc.ini" #define HOME_ENV "USERPROFILE" #define DIGIDOC_CONF_FMT "%s\\%s" char g_szGlobalConfigFile[_MAX_PATH]; #else #define DIGIDOC_CONF_NAME "digidoc.conf" #define HOME_ENV "HOME" #define DIGIDOC_CONF_FMT "%s/.%s" char g_szGlobalConfigFile[_MAX_PATH] = SYSCONFDIR "/" DIGIDOC_CONF_NAME; # ifdef FRAMEWORK char g_frameworkResources[_MAX_PATH]; # endif #endif char g_szPrivateConfigFile[_MAX_PATH]; #define NUM_SEARCH_CAS 10 //==========< private types and functions >==================== // forward deklarations of private helper functions int ConfigItem_new(ConfigItem** pItem, const char* key, const char* value, int type, int status); void ConfigItem_free(ConfigItem* pItem); ConfigItem* ConfigItem_find(const char* key); int CertificateItem_new(CertificateItem** pItem, const char* key, X509* pCert); void CertificateItem_free(CertificateItem* pItem); CertificateItem* CertificateItem_find(const char* key); X509* Cert_find(const char* key); //==========< global variables >==================== // currently I see the need only for one common configuration store // Distinction can be made by item type ConfigurationStore g_configStore = {0, 0, 0, 0}; //==========< win32 specific functions >=================== #ifdef WIN32 //-------------------------------------------------- // Retrieves a Windows registry key value // key - key name // buf - value buffer // len - value buffer length //-------------------------------------------------- void getRegKey(const char* key, LPBYTE buf, DWORD* len) { LONG rc; HKEY hKey; memset(buf, 0, *len); rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(key), 0, KEY_QUERY_VALUE, &hKey ); if(rc == ERROR_SUCCESS) { rc = RegQueryValueEx(hKey, NULL, NULL, NULL, buf, len); RegCloseKey( hKey ); if(rc == ERROR_SUCCESS) { buf[*len] = 0; } else { buf[0] = 0; } } } //-------------------------------------------------- // Retrieves a Windows registry key value. If the key // is not set then uses the default value and sets it // key - key name // buf - value buffer // len - value buffer length // defValue - default value //-------------------------------------------------- void getOrSetRegKey(const char* key, LPBYTE buf, DWORD* len, const char* defValue) { LONG rc; HKEY hKey; memset(buf, 0, *len); rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(key), 0, KEY_QUERY_VALUE, &hKey ); if(rc == ERROR_SUCCESS) { rc = RegQueryValueEx(hKey, TEXT(""), NULL, NULL, buf, len); RegCloseKey( hKey ); if(rc == ERROR_SUCCESS) { buf[*len] = 0; } } else { rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT(key), 0, "", 0, KEY_READ | KEY_WRITE, 0, &hKey, 0); if(rc == ERROR_SUCCESS) { rc = RegSetValueEx(hKey, TEXT(""), 0, REG_SZ, (const BYTE*)defValue, lstrlen(defValue)); RegCloseKey(hKey); } } } //-------------------------------------------------- // Sets a Windows registry key value // key - key name // buf - value buffer // len - value buffer length //-------------------------------------------------- void setRegKey(const char* key, LPBYTE buf, DWORD len) { LONG rc; HKEY hKey; rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT(key), 0, "", 0, KEY_READ | KEY_WRITE, 0, &hKey, 0); if(rc == ERROR_SUCCESS) { rc = RegSetValueEx(hKey, TEXT(""), 0, REG_SZ, buf, len); RegCloseKey(hKey); } } //-------------------------------------------------- // Retrieves the number of subkeys Windows registry // key value. // returns number of subkeys //-------------------------------------------------- int getNumSubKeys(const char* key) { int n = 0; HKEY hKey; DWORD num; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(key), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS) { if(RegQueryInfoKey(hKey, NULL, NULL, NULL, &num, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) n = (int)num; RegCloseKey( hKey ); } return n; } //-------------------------------------------------- // Deletes a subkey from Windows registry // key - parent key // subkey - subkey to be deleted //-------------------------------------------------- void deleteSubKey(const char* key, const char* subkey) { HKEY hKey; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(key), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS) { RegDeleteKey(hKey, subkey); RegCloseKey(hKey); } } char* g_regDigiDocRoot = "SOFTWARE\\DigiDocLib"; //-------------------------------------------------- // Retrieves the digidoc librarys config items from registry // returns error coder or ERR_OK //-------------------------------------------------- EXP_OPTION int readConfigFromRegistry() { HKEY hKey; DWORD rc, l, i; int err = 0; char keyName[255], fullName[500]; char keyValue[3000]; FILETIME ft; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(g_regDigiDocRoot), 0, KEY_READ, &hKey ) != ERROR_SUCCESS ) return ERR_CONF_FILE; i = 0; do { l = sizeof(keyName); *keyName = 0; rc = RegEnumKeyEx(hKey, i, keyName, &l, NULL, NULL, NULL, &ft); if ( (rc == ERROR_SUCCESS) && *keyName ) { l = sizeof(keyValue); *keyValue = 0; snprintf(fullName, sizeof(fullName), "%s\\%s", g_regDigiDocRoot, keyName); getRegKey(fullName, (BYTE*)keyValue, &l); if (*keyValue) { ddocDebug(3, "readConfigFromRegistry", "Reg key: %s val: %s", (const char*)keyName, (const char*)keyValue); err = addConfigItem(NULL, (const char*)keyName, (const char*)keyValue, ITEM_TYPE_PRIVATE, ITEM_STATUS_OK); } SET_LAST_ERROR_IF_NOT(err == ERR_OK, err); } i++; } while ( (rc == ERROR_SUCCESS) && *keyName ); RegCloseKey(hKey); return err; } #endif // WIN32 //==========< item handling functions >==================== //-------------------------------------------------- // Returns true (not 0) if config store structure has been inited //-------------------------------------------------- EXP_OPTION int isConfigInited() { return g_configStore.pItems && g_configStore.nItems; } //-------------------------------------------------- // Initializes configuration store // szConfigFile - name of config file. Use NULL for default //-------------------------------------------------- EXP_OPTION int initConfigStore(const char* szConfigFile) { int err = ERR_OK, at_least_one_conf = 0; //g_configStore.nItems = 0; //g_configStore.pItems = 0; if (szConfigFile && checkFileExists(szConfigFile)) { err = readConfigFile(szConfigFile, ITEM_TYPE_GLOBAL); //printf("config file: %s rc: %d", szConfigFile, err); return err; } #ifdef WIN32 snprintf(g_szGlobalConfigFile, sizeof(g_szGlobalConfigFile), "%s\\%s", getenv("SystemRoot"), DIGIDOC_CONF_NAME); /*if(!*g_szGlobalConfigFile && getenv("SystemRoot")) { strncpy(g_szGlobalConfigFile, getenv("SystemRoot"), sizeof(g_szGlobalConfigFile)); printf("Init win32 2: %s\n", g_szGlobalConfigFile); if(!g_szGlobalConfigFile[strlen(g_szGlobalConfigFile)-1] == '\\') strncat(g_szGlobalConfigFile, "\\", sizeof(g_szGlobalConfigFile) - strlen(g_szGlobalConfigFile)); printf("Init win32 3: %s\n", g_szGlobalConfigFile); strncat(g_szGlobalConfigFile, DIGIDOC_CONF_NAME, sizeof(g_szGlobalConfigFile) - strlen(g_szGlobalConfigFile)); }*/ #endif #ifdef FRAMEWORK CFStringRef identifier = CFStringCreateWithCString(0, "ee.ria.libdigidoc", kCFStringEncodingUTF8); CFBundleRef bundle = CFBundleGetBundleWithIdentifier(identifier); if(bundle) { CFURLRef url = CFBundleCopyResourcesDirectoryURL(bundle); if(url) { if(CFURLGetFileSystemRepresentation(url, TRUE, (UInt8 *)g_frameworkResources, _MAX_PATH)) snprintf(g_szGlobalConfigFile, _MAX_PATH, "%s/%s", g_frameworkResources, DIGIDOC_CONF_NAME); CFRelease(url); } } CFRelease(identifier); #endif //printf( "Reading global config file: %s\n", g_szGlobalConfigFile); ddocDebug(3, "initConfigStore", "Reading global config file: %s", g_szGlobalConfigFile); if(checkFileExists(g_szGlobalConfigFile)) err = readConfigFile(g_szGlobalConfigFile, ITEM_TYPE_GLOBAL); // MEMLEAK: ??? if(err == ERR_CONF_FILE) err = ERR_OK; else at_least_one_conf = 1; if(err) return err; setPrivateConfigFile(NULL); // set default private conf file if(g_szPrivateConfigFile[0]) { //printf( "Reading private config file: %s\n", g_szPrivateConfigFile); ddocDebug(3, "initConfigStore", "Reading private config file: %s", (g_szPrivateConfigFile ? g_szPrivateConfigFile : "NULL")); if(checkFileExists(g_szPrivateConfigFile)) err = readConfigFile(g_szPrivateConfigFile, ITEM_TYPE_PRIVATE); if(err == ERR_CONF_FILE) err = ERR_OK; else at_least_one_conf = 1; if(err) return err; } if(DIGIDOC_CONF_NAME) { //printf( "Reading config file: %s\n", DIGIDOC_CONF_NAME); ddocDebug(2, "initConfigStore", "Reading config file: %s", (DIGIDOC_CONF_NAME ? DIGIDOC_CONF_NAME: "NULL")); if(checkFileExists(DIGIDOC_CONF_NAME)) err = readConfigFile(DIGIDOC_CONF_NAME, ITEM_TYPE_PRIVATE); if(err == ERR_CONF_FILE) err = ERR_OK; else at_least_one_conf = 1; if(err) return err; } #ifdef WIN32 err = readConfigFromRegistry(); if(err == ERR_CONF_FILE) err = ERR_OK; else at_least_one_conf = 1; if(err) return err; #endif // init certs err = initCertificateItems(); if(!at_least_one_conf) err = ERR_CONF_FILE; return err; } //-------------------------------------------------- // Cleans memory of configuration store // pConfStore - configuration collection (use NULL for default) //-------------------------------------------------- EXP_OPTION void cleanupConfigStore(ConfigurationStore *pConfStore) { int i; if(!pConfStore) pConfStore = &g_configStore; for(i = 0; (i < pConfStore->nItems) && pConfStore->pItems && pConfStore->pItems[i]; i++) ConfigItem_free(pConfStore->pItems[i]); free(pConfStore->pItems); pConfStore->pItems = 0; pConfStore->nItems = 0; for(i = 0; (i < pConfStore->nCerts) && pConfStore->pCerts && pConfStore->pCerts[i]; i++) CertificateItem_free(pConfStore->pCerts[i]); free(pConfStore->pCerts); pConfStore->pCerts = 0; pConfStore->nCerts = 0; } //-------------------------------------------------- // Creates a new configration item // pItem - address of new pointer location // key - items key // value - items value // type - item type // status - item status // returns ERR_OK on success //-------------------------------------------------- int ConfigItem_new(ConfigItem** pItem, const char* key, const char* value, int type, int status) { RETURN_IF_NULL_PARAM(key); RETURN_IF_NULL_PARAM(value); RETURN_IF_NULL_PARAM(pItem); if((*pItem = (ConfigItem*)malloc(sizeof(ConfigItem))) != NULL) { (*pItem)->szKey = strdup(key); (*pItem)->szValue = strdup(value); (*pItem)->nType = type; (*pItem)->nStatus = status; if(!(*pItem)->szKey || !(*pItem)->szValue) { ConfigItem_free(*pItem); *pItem = NULL; SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); } } else SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); return ERR_OK; } //-------------------------------------------------- // Cleanup of config items memory // pItem - address of config item //-------------------------------------------------- void ConfigItem_free(ConfigItem* pItem) { if(pItem) { if(pItem->szKey) free(pItem->szKey); if(pItem->szValue) free(pItem->szValue); free(pItem); } } //-------------------------------------------------- // Adds a new configration item // pConfStore - configuration collection (use NULL for default) // key - items key // value - items value // type - item type // status - item status // returns ERR_OK on success //-------------------------------------------------- EXP_OPTION int addConfigItem(ConfigurationStore *pConfStore, const char* key, const char* value, int type, int status) { int err = ERR_OK; ConfigItem* pItem; ConfigItem** pItems; if(!pConfStore) pConfStore = &g_configStore; if((err = ConfigItem_new(&pItem, key, value, type, status)) == ERR_OK) { if((pItems = (ConfigItem**)realloc(pConfStore->pItems, sizeof(void*) * (pConfStore->nItems + 1))) != NULL) { pItems[pConfStore->nItems] = pItem; pConfStore->nItems++; pConfStore->pItems = pItems; } else SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); } else SET_LAST_ERROR_RETURN_CODE(err); return ERR_OK; } //-------------------------------------------------- // Creates a new cert item // pItem - address of new pointer location // key - items key // pCert - certificate // returns ERR_OK on success //-------------------------------------------------- int CertificateItem_new(CertificateItem** pItem, const char* key, X509* pCert) { RETURN_IF_NULL_PARAM(key); RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pItem); if((*pItem = (CertificateItem*)malloc(sizeof(CertificateItem))) != NULL) { (*pItem)->szKey = strdup(key); (*pItem)->pCert = pCert; // take ownership ! } else SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); return ERR_OK; } //-------------------------------------------------- // Cleanup of cert items memory // pItem - address of cert item //-------------------------------------------------- void CertificateItem_free(CertificateItem* pItem) { if(pItem) { if(pItem->szKey) free(pItem->szKey); if(pItem->pCert) X509_free(pItem->pCert); free(pItem); } } //-------------------------------------------------- // Adds a new cert item // pConfStore - configuration collection (use NULL for default) // key - items key // pCert - certificate // returns ERR_OK on success //-------------------------------------------------- EXP_OPTION int addCertificateItem(ConfigurationStore *pConfStore, const char* key, X509* pCert) { int err = ERR_OK; CertificateItem* pItem; CertificateItem** pItems; if(!pConfStore) pConfStore = &g_configStore; if((err = CertificateItem_new(&pItem, key, pCert)) == ERR_OK) { if((pItems = (CertificateItem**)realloc(pConfStore->pCerts, sizeof(void*) * (pConfStore->nCerts + 1))) != NULL) { pItems[pConfStore->nCerts] = pItem; pConfStore->nCerts++; pConfStore->pCerts = pItems; } else SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); } else SET_LAST_ERROR_RETURN_CODE(err); return ERR_OK; } //-------------------------------------------------- // Finds a new cert item by key // key - items key // returns item pointer or NULL if not found //-------------------------------------------------- CertificateItem* CertificateItem_find(const char* key) { int i; for(i = 0; (i < g_configStore.nCerts) && g_configStore.pCerts && g_configStore.pCerts[i]; i++) { if(g_configStore.pCerts[i]->szKey && !strcmp(g_configStore.pCerts[i]->szKey, key)) return g_configStore.pCerts[i]; } return NULL; } //-------------------------------------------------- // Finds a cert by key // key - items key // returns X509 pointer or NULL if not found. Must be X509_free()-d because it will be duplicated here //-------------------------------------------------- X509* Cert_find(const char* key) { int i; X509* pCert = 0; for(i = 0; (i < g_configStore.nCerts) && g_configStore.pCerts && g_configStore.pCerts[i] && !pCert; i++) { if(g_configStore.pCerts[i]->szKey && !strcmp(g_configStore.pCerts[i]->szKey, key)) pCert = g_configStore.pCerts[i]->pCert; } ddocDebug(3, "Cert_find", "%s cache %s", key, (pCert ? "OK" : "NULL")); return X509_dup(pCert); } //-------------------------------------------------- // Adds a new private configration item or modifies // an existing one // pConfStore - configuration collection (use NULL for default) // key - items key // value - items value // returns ERR_OK on success //-------------------------------------------------- EXP_OPTION int createOrReplacePrivateConfigItem(ConfigurationStore *pConfStore, const char* key, const char* value) { int err = ERR_OK, i; ConfigItem* pItem = NULL; #ifdef WIN32 char keyName[500]; #endif ddocDebug(3, "createOrReplacePrivateConfigItem", "%s = %s", (key ? key : "NULL"), (value ? value : "NULL")); if(!pConfStore) pConfStore = &g_configStore; // first try to find a private config item for(i = 0; (i < pConfStore->nItems) && pConfStore->pItems && pConfStore->pItems[i]; i++) { if(pConfStore->pItems[i]->szKey && !strcmp(pConfStore->pItems[i]->szKey, key) && pConfStore->pItems[i]->nType == ITEM_TYPE_PRIVATE) { pItem = pConfStore->pItems[i]; break; } } if(pItem) { // if found then modify it if(pItem->szValue) free(pItem->szValue); pItem->szValue = (char*)malloc(strlen(value)+1); if(pItem->szValue) strncpy(pItem->szValue, value, strlen(value)+1); else SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); pItem->nStatus = ITEM_STATUS_MODIFIED; } else { // else create a new private config item err = addConfigItem(pConfStore, key, value, ITEM_TYPE_PRIVATE, ITEM_STATUS_MODIFIED); } #ifdef WIN32 snprintf(keyName, sizeof(keyName), "%s\\%s", g_regDigiDocRoot, key); setRegKey(keyName, (BYTE*)value, (value ? (DWORD)strlen(value) : (DWORD)0)); if(pItem) pItem->nStatus = ITEM_STATUS_OK; #endif return err; } //-------------------------------------------------- // Deletes configration item // key - items key // returns ERR_OK on success //-------------------------------------------------- EXP_OPTION int ConfigItem_delete(const char* key) { int err = ERR_OK, i, j; // first try to find a private config item for(i = j = 0; (i < g_configStore.nItems) && g_configStore.pItems && g_configStore.pItems[i]; i++) { if(g_configStore.pItems[i]->szKey && !strcmp(g_configStore.pItems[i]->szKey, key) && g_configStore.pItems[i]->nType == ITEM_TYPE_PRIVATE) { ConfigItem_free(g_configStore.pItems[i]); g_configStore.pItems[i] = 0; continue; } g_configStore.pItems[j] = g_configStore.pItems[i]; // no-op until moving the last items forward j++; } g_configStore.nItems = j; #ifdef WIN32 deleteSubKey(g_regDigiDocRoot, key); #endif return err; } //-------------------------------------------------- // Finds a new configration item by key // key - items key // returns item pointer or NULL if not found //-------------------------------------------------- ConfigItem* ConfigItem_find(const char* key) { int i; for(i = 0; (i < g_configStore.nItems) && g_configStore.pItems && g_configStore.pItems[i]; i++) { if(g_configStore.pItems[i]->szKey && !strcmp(g_configStore.pItems[i]->szKey, key)) return g_configStore.pItems[i]; } return NULL; } //-------------------------------------------------- // Finds a all configration items that start with this prefix // prefix - item keys prefix // returns error code or ERR_OK //-------------------------------------------------- int ConfigItem_findByPrefix(ConfigurationStore *pConfStore, const char* prefix) { int i, err = ERR_OK; for(i = 0; (i < g_configStore.nItems) && g_configStore.pItems && g_configStore.pItems[i]; i++) { if(g_configStore.pItems[i]->szKey && !strncmp(g_configStore.pItems[i]->szKey, prefix, strlen(prefix))) err = addConfigItem(pConfStore, g_configStore.pItems[i]->szKey, g_configStore.pItems[i]->szValue, g_configStore.pItems[i]->nType, g_configStore.pItems[i]->nStatus); } return err; } //-------------------------------------------------- // Finds a new configration items value by key // key - items key // returns value of config item or NULL if not found //-------------------------------------------------- EXP_OPTION const char* ConfigItem_lookup(const char* key) { #ifdef FRAMEWORK if(strcmp(key, "CA_CERT_PATH") == 0) return g_frameworkResources; #endif int i; // first try to find a private item for(i = 0; (i < g_configStore.nItems) && g_configStore.pItems && g_configStore.pItems[i]; i++) { if(g_configStore.pItems[i]->szKey && !strcmp(g_configStore.pItems[i]->szKey, key) && g_configStore.pItems[i]->nType == ITEM_TYPE_PRIVATE) return g_configStore.pItems[i]->szValue; } // if not found use any type of item with the given key for(i = 0; (i < g_configStore.nItems) && g_configStore.pItems && g_configStore.pItems[i]; i++) { if(g_configStore.pItems[i]->szKey && !strcmp(g_configStore.pItems[i]->szKey, key)) return g_configStore.pItems[i]->szValue; } return NULL; } //-------------------------------------------------- // Finds a new configration items value by key from the store // key - items key // pConfStore - store to search in // returns value of config item or NULL if not found //-------------------------------------------------- EXP_OPTION const char* ConfigItem_lookup_fromStore(ConfigurationStore *pConfStore, const char* key) { int i; for(i = 0; pConfStore && (i < pConfStore->nItems) && pConfStore->pItems && pConfStore->pItems[i]; i++) { if(pConfStore->pItems[i]->szKey && !strcmp(pConfStore->pItems[i]->szKey, key)) return pConfStore->pItems[i]->szValue; } return NULL; } //-------------------------------------------------- // Finds a numeric configration items value by key // key - items key // defValue - default value to be returned // returns value of config item or defValue if not found //-------------------------------------------------- EXP_OPTION int ConfigItem_lookup_int(const char* key, int defValue) { int rc = defValue; const char* p = ConfigItem_lookup(key); if (p) rc = atoi(p); return rc; } //-------------------------------------------------- // Finds a new configration items value by key // key - items key // returns value of config item or NULL if not found //-------------------------------------------------- EXP_OPTION const char* ConfigItem_lookup_str(const char* key, const char* defValue) { const char* p = ConfigItem_lookup(key); if (p) return p; else return defValue; } //-------------------------------------------------- // Finds a bolean configration items value by key // key - items key // defValue - default value to be returned // returns value of config item or defValue if not found //-------------------------------------------------- EXP_OPTION int ConfigItem_lookup_bool(const char* key, int defValue) { int rc = defValue; const char* p = ConfigItem_lookup(key); if(p) #ifdef WIN32 rc = (!stricmp(p, "true")) ? 1 : 0; #else rc = (!strcasecmp(p, "TRUE")) ? 1 : 0; #endif return rc; } //-------------------------------------------------- // Reads and parses configuration file // fileName - configuration file name // type - type of config file global/private // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int readConfigFile(const char* fileName, int type) { FILE* hFile; char buf[5000]; char *p; int err = ERR_OK; if((hFile = fopen(fileName, "rt")) != NULL) { ddocDebug(2, "readConfigFile", "Reading config file: %s", fileName); while(fgets(buf, sizeof(buf), hFile) != NULL && !err) { // trim line separators and spaces while(strlen(buf) && (buf[strlen(buf)-1] == '\n' || buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\t' || buf[strlen(buf)-1] == ' ')) buf[strlen(buf)-1] = 0; if(strlen(buf) && buf[0] != '#') { if((p = strchr(buf, '=')) != NULL) { *p = 0; p++; err = addConfigItem(NULL, (const char*)buf, (const char*)p, type, ITEM_STATUS_OK); SET_LAST_ERROR_IF_NOT(err == ERR_OK, err); //printf("CONF: %s = %s\n", buf, p); } } } fclose(hFile); return err; } else { ddocDebug(1, "readConfigFile", "Error opening config file: %s", fileName); SET_LAST_ERROR_RETURN_CODE(ERR_CONF_FILE); // MEMLEAK: ??? } } //-------------------------------------------------- // Writes a configuration file // fileName - configuration file name // type - type of config file global/private // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int writeConfigFile(const char* fileName, int type) { FILE* hFile; //char buf[300]; //char *p; int err = ERR_OK, i; if((hFile = fopen(fileName, "wt")) != NULL) { // first try to find a private item for(i = 0; (i < g_configStore.nItems) && g_configStore.pItems && g_configStore.pItems[i]; i++) { if(g_configStore.pItems[i]->nType == type) { fprintf(hFile, "%s=%s\n", g_configStore.pItems[i]->szKey, g_configStore.pItems[i]->szValue); g_configStore.pItems[i]->nStatus = ITEM_STATUS_OK; } } fclose(hFile); return err; } else SET_LAST_ERROR_RETURN_CODE(ERR_CONF_FILE); } //-------------------------------------------------- // Saves all private config items in correct file // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int writePrivateConfigFile() { #ifndef WIN32 return writeConfigFile(g_szPrivateConfigFile, ITEM_TYPE_PRIVATE); #else return ERR_OK; #endif } //-------------------------------------------------- // Sets a new name for private config file. Can be // used to override default of env(HOME)/.digidoc.conf // Use NULL to restore default value //-------------------------------------------------- EXP_OPTION void setPrivateConfigFile(const char* fileName) { if (fileName) { strncpy( g_szPrivateConfigFile, fileName, sizeof(g_szPrivateConfigFile) ); } else { // use default snprintf(g_szPrivateConfigFile, sizeof(g_szPrivateConfigFile)-1, DIGIDOC_CONF_FMT, getenv(HOME_ENV), DIGIDOC_CONF_NAME); } } //-------------------------------------------------- // Finds CA certificates index by it's CN // idx - address if index // cn - CN of the CA // return -1 if not found or 0 for success //-------------------------------------------------- int findCAindexByCN(int* idx, const char* cn) { int i, n; char buf1[100]; const char* p; *idx = 0; p = ConfigItem_lookup("CA_CERTS"); RETURN_IF_NOT(p != NULL, ERR_CONF_LINE); n = atoi(p); for(i = 1; (i <= n) && !(*idx); i++) { snprintf(buf1, sizeof(buf1), "CA_CERT_%d_CN", i); p = ConfigItem_lookup(buf1); ddocDebug(1, "findCAindexByCN", "ERR112 Unknown CA: %s", buf1); RETURN_IF_NOT(p != NULL, ERR_UNKNOWN_CA); if(!strcmp(p, cn)) { // found it *idx = i; break; } } return ERR_OK; } //-------------------------------------------------- // Finds Responder certificates index by it's CN // idx - address if index // cn - CN of the responder cert // hash - responder certs hash in base64 form // ca - responder CA CN // return error code or 0 for success //-------------------------------------------------- int findResponderIndex(int* idx, const char* cn, const char* hash, const char* ca) { int err = ERR_OK, i, n; char buf1[100]; const char* p; *idx = 0; ddocDebug(3, "findResponderIndex", "Find CA: %s hash: %s ca-cn: %s", (cn ? cn : "NULL"), (hash ? hash : "NULL"), (ca ? ca : "NULL")); p = ConfigItem_lookup("DIGIDOC_OCSP_RESPONDER_CERTS"); RETURN_IF_NOT(p != NULL, ERR_CONF_LINE); n = atoi(p); for(i = 1; (i <= n) && !(*idx); i++) { if(cn) { snprintf(buf1, sizeof(buf1), "DIGIDOC_OCSP_RESPONDER_CERT_%d_CN", i); p = ConfigItem_lookup(buf1); if(p && !strcmp(p, cn)) { // found it *idx = i; break; } } else if(hash) { snprintf(buf1, sizeof(buf1), "DIGIDOC_OCSP_RESPONDER_CERT_%d_HASH", i); p = ConfigItem_lookup(buf1); if(p && !strcmp(p, hash)) { // found it *idx = i; break; } } else if(ca) { snprintf(buf1, sizeof(buf1), "DIGIDOC_OCSP_RESPONDER_CERT_%d_CA", i); p = ConfigItem_lookup(buf1); if(p && !strcmp(p, ca)) { // found it *idx = i; break; } } } return err; } //-------------------------------------------------- // Finds CA certificate by CN // ppCA - address of found CA // szCN - CA certs common name // pHash - authority-key-identifier to search for CA // return error code or 0 for success //-------------------------------------------------- DIGIDOC_DEPRECATED EXP_OPTION int findCAForCN(X509** ppCA, const char* szCN, DigiDocMemBuf *pHash) { return findCAForCNAndSigTime(ppCA, szCN, pHash, 0); } //-------------------------------------------------- // Read ca and ocsp responder certs from files and cache in memory //-------------------------------------------------- int initCertificateItems() { int err = ERR_OK, i, n, e2, j; const char *p1, *p2, *p3; char buf2[300], buf1[50]; X509 *x509 = NULL; // read CA certs p1 = ConfigItem_lookup("CA_CERTS"); RETURN_IF_NOT(p1 != NULL, ERR_CONF_LINE); p2 = ConfigItem_lookup("CA_CERT_PATH"); RETURN_IF_NOT(p2 != NULL, ERR_CONF_LINE); ddocDebug(3, "initCertificateItems", "Init ca certs: %s ca-path: %s", p1, p2); n = atoi(p1); for(i = 1; i <= n; i++) { snprintf(buf1, sizeof(buf1), "CA_CERT_%d_CN", i); p1 = ConfigItem_lookup(buf1); snprintf(buf1, sizeof(buf1), "CA_CERT_%d", i); p3 = ConfigItem_lookup(buf1); if(p1 && p3) { #ifdef WIN32 snprintf(buf2, sizeof(buf2), "%s\\%s", p2, p3); #else snprintf(buf2, sizeof(buf2), "%s/%s", p2, p3); #endif x509 = 0; e2 = ReadCertificateNoErr(&x509, buf2); if(x509) { ddocDebug(3, "initCertificateItems", "CA Cert item: %d CN: %s file: %s", i, p1, p3); addCertificateItem(&g_configStore, p1, x509); // release ownership on x509! } else { ddocDebug(1, "initCertificateItems", "Error: %d reading item: %d CN: %s file: %s", e2, i, p1, p3); } } } // read ocsp responder certs p1 = ConfigItem_lookup("DIGIDOC_OCSP_RESPONDER_CERTS"); RETURN_IF_NOT(p1 != NULL, ERR_CONF_LINE); ddocDebug(3, "initCertificateItems", "Init ocsp certs: %s ca-path: %s", p1, p2); n = atoi(p1); for(i = 1; i <= n; i++) { snprintf(buf1, sizeof(buf1), "DIGIDOC_OCSP_RESPONDER_CERT_%d_CN", i); p1 = ConfigItem_lookup(buf1); snprintf(buf1, sizeof(buf1), "DIGIDOC_OCSP_RESPONDER_CERT_%d", i); p3 = ConfigItem_lookup(buf1); if(p1 && p3) { #ifdef WIN32 snprintf(buf2, sizeof(buf2), "%s\\%s", p2, p3); #else snprintf(buf2, sizeof(buf2), "%s/%s", p2, p3); #endif x509 = 0; e2 = ReadCertificateNoErr(&x509, buf2); if(x509) { ddocDebug(3, "initCertificateItems", "OCSP Cert item: %d CN: %s file: %s", i, p1, p3); addCertificateItem(&g_configStore, buf1, x509); // release ownership on x509! } else { ddocDebug(1, "initCertificateItems", "Error: %d reading item: %d CN: %s file: %s", e2, i, p1, p3); } } for(j = 1; j < 10; j++) { snprintf(buf1, sizeof(buf1), "DIGIDOC_OCSP_RESPONDER_CERT_%d_%d", i, j); p3 = ConfigItem_lookup(buf1); if(p1 && p3) { #ifdef WIN32 snprintf(buf2, sizeof(buf2), "%s\\%s", p2, p3); #else snprintf(buf2, sizeof(buf2), "%s/%s", p2, p3); #endif x509 = 0; e2 = ReadCertificateNoErr(&x509, buf2); if(x509) { ddocDebug(3, "initCertificateItems", "OCSP Cert item: %d CN: %s file: %s", i, p1, p3); addCertificateItem(&g_configStore, buf1, x509); // release ownership on x509! } else { ddocDebug(1, "initCertificateItems", "Error: %d reading item: %d CN: %s file: %s", e2, i, p1, p3); } } } } return err; } //-------------------------------------------------- // Finds CA certificate by CN // ppCA - address of found CA // szCN - CA certs common name // pHash - authority-key-identifier to search for CA // tSigTime - signing time or 0 // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findCAForCNAndSigTime(X509** ppCA, const char* szCN, DigiDocMemBuf *pHash, time_t tSigTime) { int err = ERR_OK, i, n; char buf2[300], buf1[30], buf3[50]; const char *p1, *p2; X509 *x509 = NULL; DigiDocMemBuf mbuf2, mbuf3, mbuf1; time_t tFrom = 0, tTo = 0; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; mbuf3.pMem = 0; mbuf3.nLen = 0; ddocEncodeBase64(pHash, &mbuf3); ddocBin2Hex(pHash, &mbuf2); ddocDebug(3, "findCAForCN", "Find CN: %s subj-hash: %s subj-hash-hex: %s sig-time: %ld", szCN, (char*)mbuf3.pMem, (char*)mbuf2.pMem, (unsigned long)tSigTime); ddocMemBuf_free(&mbuf3); ddocMemBuf_free(&mbuf2); // initialize *ppCA = NULL; p1 = ConfigItem_lookup("CA_CERTS"); RETURN_IF_NOT(p1 != NULL, ERR_CONF_LINE); n = atoi(p1); for(i = 1; (i <= n) && !(*ppCA); i++) { snprintf(buf1, sizeof(buf1), "CA_CERT_%d_CN", i); p1 = ConfigItem_lookup(buf1); x509 = NULL; ddocDebug(3, "findCAForCN", "CA: %s -> %s", buf1, p1); if(p1 && !strcmp(p1, szCN)) { // found CN, try read cert snprintf(buf1, sizeof(buf1), "CA_CERT_%d", i); p1 = ConfigItem_lookup(buf1); if(p1) { p2 = ConfigItem_lookup("CA_CERT_PATH"); RETURN_IF_NOT(p2 != NULL, ERR_CONF_LINE); #ifdef WIN32 snprintf(buf2, sizeof(buf2), "%s\\%s", p2, p1); #else snprintf(buf2, sizeof(buf2), "%s/%s", p2, p1); #endif // check cache first x509 = Cert_find(szCN); if(!x509) err = ReadCertificate(&x509, buf2); ddocDebug(4, "findCAForCN", "Read cert: %s rc: %d\n", buf2, err); if(err == ERR_FILE_READ) err = ERR_UNKNOWN_CA; if(pHash && pHash->pMem && x509) { memset(buf3, 0, sizeof(buf3)); ReadCertSerialNumber(buf3, sizeof(buf3), x509); readSubjectKeyIdentifier(x509, &mbuf2); ddocEncodeBase64(&mbuf2, &mbuf3); ddocBin2Hex(&mbuf2, &mbuf1); tFrom = getCertNotBeforeTimeT(x509); tTo = getCertNotAfterTimeT(x509); if(!ddocMemCompareMemBufs(pHash, &mbuf2) && (!tSigTime || (tSigTime >= tFrom && tSigTime <= tTo))) { *ppCA = x509; err = ERR_OK; ddocDebug(4, "findCAForCN", "Found cert: %s with nr: %s from: %ld to: %ld", szCN, buf3, tFrom, tTo); } else { ddocDebug(4, "findCAForCN", "Release cert: %s with nr: %s", szCN, buf3); X509_free(x509); // release wrong cert *ppCA = NULL; err = ERR_UNKNOWN_CA; } ddocDebug(3, "findCAForCN", "Compare CA: %s subj-hash: %s hex: %s err: %d", buf1, (char*)mbuf3.pMem, (char*)mbuf1.pMem, err); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); ddocMemBuf_free(&mbuf1); } else { // plain CN match is enough if(x509) { *ppCA = x509; err = ERR_OK; ddocDebug(4, "findCAForCN", "Found cert: %s with cn", szCN); } } } else { ddocDebug(3, "findCAForCN", "No cert file for: %s", buf1); } } } RETURN_IF_NOT(err == ERR_OK, err); //*ppCA = x509; if(*ppCA) { ddocCertGetSubjectDN(*ppCA, &mbuf2); ddocDebug(4, "findCAForCN", "Found cert: %s with cn %s", (char*)mbuf2.pMem, szCN); ddocMemBuf_free(&mbuf2); } return err; } //-------------------------------------------------- // Finds Responders certificate by CN // ppResp - address of found cert // szCN - Responder certs common name // hash - responder certs hash in base64 // nIdx - index of the certificate for this respnder. Starts at 0 // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findResponderByCNAndHashAndIndex(X509** ppResp, const char* szCN, const char* hash, int nIdx) { int err = ERR_OK, i; char buf[300]; const char *p1, *p2; RETURN_IF_NULL_PARAM(ppResp); // initialize *ppResp = NULL; err = findResponderIndex(&i, szCN, hash, NULL); ddocDebug(3, "findResponderByCNAndHashAndIndex", "CN: %s hash: %s resp-index: %d, cert-index: %d", (szCN ? szCN : "NULL"), (hash ? hash : "NULL"), i, nIdx); RETURN_IF_NOT(err == ERR_OK, err); // check cache first *ppResp = Cert_find(szCN); if(*ppResp) return ERR_OK; // compose search key if(!nIdx) snprintf(buf, sizeof(buf), "DIGIDOC_OCSP_RESPONDER_CERT_%d", i); else snprintf(buf, sizeof(buf), "DIGIDOC_OCSP_RESPONDER_CERT_%d_%d", i, nIdx); p1 = ConfigItem_lookup(buf); ddocDebug(3, "findResponderByCNAndHashAndIndex", "Read cert key: %s file: %s", buf, (p1 ? p1 : "NULL")); if(p1) { if(checkFileExists(p1)) { err = ReadCertificate(ppResp, p1); } else { p2 = ConfigItem_lookup("CA_CERT_PATH"); if(p2) { #ifdef WIN32 snprintf(buf, sizeof(buf), "%s\\%s", p2, p1); #else snprintf(buf, sizeof(buf), "%s/%s", p2, p1); #endif if(checkFileExists(buf)) err = ReadCertificate(ppResp, buf); ddocDebug(3, "findResponderByCNAndHashAndIndex", "Read cert: %s rc: %d got: %s", buf, err, (*ppResp ? "OK" : "NULL")); } } } // if p1 return err; } //-------------------------------------------------- // Finds Responders certificate by CN // ppResp - address of found cert // szCN - Responder certs common name // hash - responder certs hash in base64 form // szCertSerial - specific serial number to search // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findResponder(X509** ppResp, const char* szCN, const char* szHash, char* szCertSerial) { int err = ERR_OK, i, j; char buf[300], szSerial[100]; const char *p1, *p2; time_t t1, t2; X509 *x509; RETURN_IF_NULL_PARAM(ppResp); // initialize *ppResp = NULL; err = findResponderIndex(&i, szCN, szHash, NULL); ddocDebug(3, "findResponder", "CN: %s hash: %s index: %d, search notary: %s", (szCN ? szCN : "NULL"), (szHash ? szHash : "NULL"), i, (szCertSerial ? szCertSerial : "LATEST")); RETURN_IF_NOT(err == ERR_OK, err); j = 0; t1 = t2 = 0; do { x509 = 0; p1 = p2 = 0; // compose search key if(!j) snprintf(buf, sizeof(buf), "DIGIDOC_OCSP_RESPONDER_CERT_%d", i); else snprintf(buf, sizeof(buf), "DIGIDOC_OCSP_RESPONDER_CERT_%d_%d", i, j); p1 = ConfigItem_lookup(buf); ddocDebug(3, "findResponder", "Read cert key: %s file: %s", buf, (p1 ? p1 : "NULL")); if(p1) { // check cache first x509 = Cert_find(buf); if(!x509) { // if not found in cache if(checkFileExists(p1)) { err = ReadCertificate(&x509, p1); if(x509) t2 = getCertNotAfterTimeT(x509); ddocDebug(3, "findResponder", "Read cert: %s rc: %d not-after: %ld", p1, err, (unsigned long)t2); } else { p2 = ConfigItem_lookup("CA_CERT_PATH"); RETURN_IF_NOT(p2 != NULL, ERR_CONF_LINE); #ifdef WIN32 snprintf(buf, sizeof(buf), "%s\\%s", p2, p1); #else snprintf(buf, sizeof(buf), "%s/%s", p2, p1); #endif err = ReadCertificate(&x509, buf); if(x509) t2 = getCertNotAfterTimeT(x509); ddocDebug(3, "findResponder", "Read cert: %s rc: %d not-after: %ld", buf, err, (unsigned long)t2); } // else } // !x509 if(!err && x509) { // if cert read successfully if(szCertSerial) { // check for specific notary cert serial szSerial[0] = 0; ReadCertSerialNumber(szSerial, sizeof(szSerial), x509); if(!strcmp(szSerial, szCertSerial)) { *ppResp = x509; ddocDebug(4, "findResponder", "assigning CA 1"); return ERR_OK; } } if(!t1 || t2 > t1) { // first cert to check t1 = t2; ddocDebug(4, "findResponder", "assigning CA 2"); *ppResp = x509; } } } // if p1 j++; } while(x509 || j < 10); // until any potential cert found and I have tried to find one of the multiple certs RETURN_IF_NOT(err == ERR_OK, ERR_CERT_READ); ddocDebug(3, "findResponder", "CN: %s hash: %s index: %d, search notary: %s", (szCN ? szCN : "NULL"), (szHash ? szHash : "NULL"), err, (*ppResp ? "OK" : "NULL")); return err; } //-------------------------------------------------- // Finds Responder certificates CA certs CN // caCN - buffer for responders CA CN // len - length of buffer for CA CN // szCN - responder certs common name // hash - responder certs hash in base64 form // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findResponderCA(char* caCN, int len, const char* szCN, const char* hash) { int err = ERR_OK, i=0; char buf[50]; const char* p; // initialize RETURN_IF_NULL_PARAM(caCN); caCN[0] = 0; ddocDebug(3, "findResponderCA", "CA cn: %s, cn-l: %d", caCN, len); err = findResponderIndex(&i, szCN, hash, NULL); ddocDebug(3, "findResponderCA", "Resp idx: %d", i); RETURN_IF_NOT(err == ERR_OK, err); snprintf(buf, sizeof(buf), "DIGIDOC_OCSP_RESPONDER_CERT_%d_CA", i); p = ConfigItem_lookup(buf); ddocDebug(3, "findResponderCA", "Lookup: %s found: %s len: %d", buf, p, len); RETURN_IF_NOT(p != NULL, ERR_OCSP_RESP_NOT_TRUSTED); strncpy(caCN, p, len); return ERR_OK; } //-------------------------------------------------- // Finds CA certificate of the given certificate // ppCA - address of found CA // pCert - certificate whose CA we are looking for // return error code or 0 for success // deprecated use findCAForCertificateAndSigTime() //-------------------------------------------------- DIGIDOC_DEPRECATED EXP_OPTION int findCAForCertificate(X509** ppCA, const X509* pCert) { return findCAForCertificateAndSigTime(ppCA, pCert, 0); } //-------------------------------------------------- // Finds CA certificate of the given certificate // ppCA - address of found CA // pCert - certificate whose CA we are looking for // tSigTime - signature timestamp // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findCAForCertificateAndSigTime(X509** ppCA, const X509* pCert, time_t tSigTime) { int err = ERR_OK; DigiDocMemBuf mbuf1, mbuf2; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; // read cert issuers CN err = ddocCertGetIssuerCN((X509*)pCert, &mbuf1); RETURN_IF_NOT(err == ERR_OK, ERR_PKCS_CERT_DECODE); RETURN_IF_NOT(mbuf1.pMem, ERR_PKCS_CERT_DECODE); // PR. fix crash err = readAuthorityKeyIdentifier((X509*)pCert, &mbuf2); RETURN_IF_NOT(err == ERR_OK, err); err = findCAForCNAndSigTime(ppCA, (const char*)mbuf1.pMem, &mbuf2, tSigTime); ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); RETURN_IF_NOT(err == ERR_OK, err); return err; } //-------------------------------------------------- // Finds CA chain // ppChain - address of cert pointer array // nMaxChain - index of last cert in returned array - 0 based // szCN - CN of the first CA cert (not the child cert!) // pCert - certificate to search ca-s for // return error code or 0 for success // deprecated use findCAChainForCNAndSigTime() //-------------------------------------------------- DIGIDOC_DEPRECATED EXP_OPTION int findCAChainForCN(X509** ppChain, int* nMaxChain, const char* szCN, X509* pCert) { return findCAChainForCNAndSigTime(ppChain, nMaxChain, szCN, pCert, 0); } //-------------------------------------------------- // Finds CA chain // ppChain - address of cert pointer array // nMaxChain - index of last cert in returned array - 0 based // szCN - CN of the first CA cert (not the child cert!) // pCert - certificate to search ca-s for // tSigTime - signature timestamp // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findCAChainForCNAndSigTime(X509** ppChain, int* nMaxChain, const char* szCN, X509* pCert, time_t tSigTime) { int err = ERR_OK, i; char oldcn[300], buf3[100]; X509 * caCerts[NUM_SEARCH_CAS]; DigiDocMemBuf mbuf1, mbuf2, mbuf3; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; mbuf3.pMem = 0; mbuf3.nLen = 0; RETURN_IF_NULL_PARAM(ppChain); RETURN_IF_NULL_PARAM(nMaxChain); RETURN_IF_NULL_PARAM(szCN); // initialize for(i = 0; i < NUM_SEARCH_CAS; i++) caCerts[i] = 0; for(i = 0; i < NUM_SEARCH_CAS; i++) ppChain[i] = NULL; i = 0; memset(oldcn, 0, sizeof(oldcn)); strncpy(oldcn, szCN, sizeof(oldcn)); *nMaxChain = -1; if(pCert != NULL) { err = readAuthorityKeyIdentifier(pCert, &mbuf2); ddocEncodeBase64(&mbuf2, &mbuf3); memset(buf3, 0, sizeof(buf3)); ReadCertSerialNumber(buf3, sizeof(buf3), pCert); ddocDebug(3, "findCAChainForCN", "Subj cert nr: %s, auth-key: %s", buf3, (char*)mbuf3.pMem); ddocMemBuf_free(&mbuf3); } do { if(caCerts[i]) { // for first ca it is null err = readAuthorityKeyIdentifier(caCerts[i], &mbuf2); ddocEncodeBase64(&mbuf2, &mbuf3); ddocDebug(3, "findCAChainForCN", "CA cert: %d, auth-key: %s", i, (char*)mbuf3.pMem); ddocMemBuf_free(&mbuf3); if(err) return err; } err = findCAForCNAndSigTime(&caCerts[i], oldcn, &mbuf2, tSigTime); ddocMemBuf_free(&mbuf2); ddocDebug(3, "findCAChainForCN", "Read CA for CN: %s idx: %d rc: %d", oldcn, i, err); SET_LAST_ERROR_IF_NOT(err == ERR_OK, err); if (caCerts[i] && !err) { err = ddocCertGetIssuerCN(caCerts[i], &mbuf1); ddocDebug(3, "findCAChainForCN", "Issuer: %s old was: %s, rc: %d", (const char*)mbuf1.pMem, oldcn, err); SET_LAST_ERROR_IF_NOT(err == ERR_OK, err); } if(caCerts[i] && !err && mbuf1.pMem && !strcmp((const char*)mbuf1.pMem, oldcn) && i == 0) { ppChain[0] = caCerts[0]; *nMaxChain = 0; return err; } else if(!err && mbuf1.pMem && strcmp((const char*)mbuf1.pMem, oldcn)) { i++; if(!err) strncpy(oldcn, (const char*)mbuf1.pMem, sizeof(oldcn) ); ddocMemBuf_free(&mbuf1); } else { ddocMemBuf_free(&mbuf1); break; } } while (err == ERR_OK); *nMaxChain = i; ddocDebug(3, "findCAChainForCN", "Found: %d certs", (*nMaxChain) + 1); // now reverse the chain such that the root CA is at the top - is it necessary??? // PR fix index for(i = 0; i <= *nMaxChain; i++) ppChain[i] = caCerts[(*nMaxChain) - i]; return err; } //------------------------------------------ // Get a notary confirmation for signature // pSigDoc - signed document pointer // pSigInfo - signature to notarize // returns error code //------------------------------------------ EXP_OPTION int notarizeSignature(SignedDoc* pSigDoc, SignatureInfo* pSigInfo) { return notarizeSignatureWithIp(pSigDoc, pSigInfo, 0); } //------------------------------------------ // Selects correct OCSP URL for this certificate // issuerDN - certificate issuer DN // ppOcspUrl - returned OCSP url or NULL if not found // returns error code or ERR_OK //------------------------------------------ int ddocSelectOcspUrl(char* issuerDN, char** ppOcspUrl) { int err = ERR_OK, i; char buf1[100], *p; RETURN_IF_NULL_PARAM(ppOcspUrl); // get default OCSP URL *ppOcspUrl = (char*)ConfigItem_lookup("DIGIDOC_OCSP_URL"); // if possible find OCSP URL by signers CA ddocDebug(3, "ddocSelectOcspUrl", "signers CA: %s", (issuerDN ? issuerDN : "NULL")); if(issuerDN) { buf1[0] = 0; findCN(issuerDN, buf1, sizeof(buf1)); ddocDebug(3, "ddocSelectOcspUrl", "signers CA CN: %s", buf1); findResponderIndex(&i, NULL, NULL, buf1); if(i > 0) { snprintf(buf1, sizeof(buf1), "DIGIDOC_OCSP_RESPONDER_CERT_%d_URL", i); p = (char*)ConfigItem_lookup(buf1); if(p) { *ppOcspUrl = p; ddocDebug(3, "ddocSelectOcspUrl", "Selected OCSP URL: %s", p); } } buf1[0] = 0; } if(!(*ppOcspUrl)) { ddocDebug(1, "ddocSelectOcspUrl", "ERR112 ocsp url: %s", (*ppOcspUrl ? *ppOcspUrl : "NULL")); SET_LAST_ERROR(ERR_UNKNOWN_CA); err = ERR_UNKNOWN_CA; } else { ddocDebug(3, "ddocSelectOcspUrl", "Selected OCSP URL: %s", *ppOcspUrl); } return err; } int ddocFindCaChainForCert(X509* pCert, X509** caCerts, int *nCerts, char* szCA, int caLen) { int err = ERR_OK, i; DigiDocMemBuf mbuf1, mbuf2; RETURN_IF_NULL_PARAM(caCerts); RETURN_IF_NULL_PARAM(nCerts); RETURN_IF_NULL_PARAM(szCA); mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; for(i = 0; i < NUM_SEARCH_CAS; i++) caCerts[i] = 0; szCA[0] = 0; err = ddocCertGetIssuerDN(pCert, &mbuf1); err = ddocCertGetSubjectDN(pCert, &mbuf2); ddocDebug(3, "ddocFindCaChainForCert", "Find chain for: %s issuer: %s", (char*)mbuf2.pMem, (char*)mbuf1.pMem); if(!err) { err = findCN((char*)mbuf1.pMem, szCA, caLen); ddocDebug(3, "ddocFindCaChainForCert", "Find chain for CN: %s", szCA); if(!err) { err = findCAChainForCNAndSigTime(caCerts, nCerts, szCA, pCert, 0); ddocDebug(3, "ddocFindCaChainForCert", "Chain length: %d, err: %d", *nCerts, err); } } ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); return err; } int ddocFindOcspCnCaAndCerts(OCSP_RESPONSE* pResp, int *nType, X509** caCerts, int *nCerts, char* szCN, int cnLen, char* szCA, int caLen) { int err = ERR_OK, i; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pResp); RETURN_IF_NULL_PARAM(nType); RETURN_IF_NULL_PARAM(caCerts); RETURN_IF_NULL_PARAM(nCerts); RETURN_IF_NULL_PARAM(szCN); RETURN_IF_NULL_PARAM(szCA); mbuf1.pMem = 0; mbuf1.nLen = 0; for(i = 0; i <= NUM_SEARCH_CAS; i++) caCerts[i] = 0; szCN[0] = szCA[0] = 0; // find responder id type and value ddocDebug(3, "ddocFindOcspCnCaAndCerts", "OCSP: %s", (pResp ? "OK" : "NO")); err = ddocGetOcspRespIdTypeAndValue(pResp, nType, &mbuf1); if((*nType) == RESPID_NAME_TYPE) { err = findCN((char*)mbuf1.pMem, szCN, cnLen); if (!err) err = findResponderCA(szCA, caLen, szCN, NULL); } else if((*nType) == RESPID_KEY_TYPE) { i = sizeof(szCN); encode((const byte*)mbuf1.pMem, mbuf1.nLen, (byte*)szCN, &i); if (!err) err = findResponderCA(szCA, caLen, NULL, szCN); } else { SET_LAST_ERROR(ERR_OCSP_WRONG_RESPID); err = ERR_OCSP_WRONG_RESPID; } ddocDebug(3, "ddocFindOcspCnCaAndCerts", "Responder CN: %s CA: %s, RC: %d", szCN, szCA, err); // find CA chain if(err == ERR_OK) err = findCAChainForCNAndSigTime(caCerts, nCerts, szCA, NULL, 0); ddocDebug(3, "ddocFindOcspCnCaAndCerts", "Chain length: %d, err: %d", *nCerts, err); // cleanup ddocMemBuf_free(&mbuf1); return err; } //------------------------------------------ // Get a notary confirmation for signature // pSigDoc - signed document pointer // pSigInfo - signature to notarize // ip - callers ip address if known // returns error code //------------------------------------------ EXP_OPTION int notarizeSignatureWithIp(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, unsigned long ip) { NotaryInfo* pNotInfo; int err = ERR_OK, nCAs = NUM_SEARCH_CAS, i, j, err2 = 0, nType; X509* caCerts[NUM_SEARCH_CAS+1]; X509* pNotCert, *pSigCert = 0, *pSigCa = 0; //AM 24.09.08 szCA size from 30 to 100 for Portuguese ID card char szCN[200], szCA[100]; char *pkcs12file, *pkcs12passwd, *ocspUrl; char *proxyHost, *proxyPort, *proxyUser, *proxyPass; OCSP_RESPONSE *pResp = 0; CertValue *pCertValue = 0; // PR. index fix for(i = 0; i < NUM_SEARCH_CAS; i++) caCerts[i] = 0; if(ConfigItem_lookup_bool("SIGN_OCSP", 1)) { pkcs12file = (char*)ConfigItem_lookup("DIGIDOC_PKCS_FILE"); RETURN_IF_NOT(pkcs12file, ERR_OCSP_PKCS12_NO_FILE); pkcs12passwd = (char*)ConfigItem_lookup("DIGIDOC_PKCS_PASSWD"); //RETURN_IF_NOT(pkcs12passwd, ERR_OCSP_PKCS12_NO_PASSWD); } else { pkcs12file = pkcs12passwd = NULL; } if(ConfigItem_lookup_bool("USE_PROXY", 1)) { proxyHost = (char*)ConfigItem_lookup("DIGIDOC_PROXY_HOST"); RETURN_IF_NOT(proxyHost, ERR_WRONG_URL_OR_PROXY); proxyPort = (char*)ConfigItem_lookup("DIGIDOC_PROXY_PORT"); RETURN_IF_NOT(proxyPort, ERR_WRONG_URL_OR_PROXY); proxyUser = (char*)ConfigItem_lookup("DIGIDOC_PROXY_USER"); proxyPass = (char*)ConfigItem_lookup("DIGIDOC_PROXY_PASS"); ddocDebug(4, "notarizeSignature", "proxy: %s port : %s", proxyHost, proxyPort); } else { proxyHost = proxyPort = proxyUser = proxyPass = NULL; } err = ddocSelectOcspUrl((char*)ddocSigInfo_GetSignersCert_IssuerName(pSigInfo), &ocspUrl); RETURN_IF_NOT(err == ERR_OK, err); // get signers ca certs pSigCert = ddocSigInfo_GetSignersCert(pSigInfo); err = ddocFindCaChainForCert(pSigCert, caCerts, &nCAs, szCA, sizeof(szCA)); RETURN_IF_NOT(nCAs >= 0, ERR_SIGNERS_CERT_NOT_TRUSTED); pSigCa = caCerts[nCAs]; // get OCSP confirmation ddocDebug(3, "notarizeSignatureWithIp", "Getting OCSP confirmation"); err = getConfirmationWithIpEx(pSigDoc, pSigInfo, (const X509 **)caCerts, NULL, pkcs12file, pkcs12passwd, ocspUrl, proxyHost, proxyPort, proxyUser, proxyPass, ip); // release ca certs nCAs=10; for(i = 0; i < NUM_SEARCH_CAS; i++) { if(caCerts[i] && caCerts[i] != pSigCa) { X509_free(caCerts[i]); caCerts[i] = 0; } } // continue with the rest RETURN_IF_NOT(err == ERR_OK, err); pNotInfo = getNotaryWithSigId(pSigDoc, pSigInfo->szId); RETURN_IF_NOT(pNotInfo != NULL, ERR_NOTARY_SIG_MATCH); // get OCSP response pResp = ddocNotInfo_GetOCSPResponse_Value(pNotInfo); RETURN_IF_NOT(pResp != NULL, ERR_NOTARY_SIG_MATCH); // find CN from responder-id, right CA and CA certs chain err = ddocFindOcspCnCaAndCerts(pResp, &nType, (X509**)caCerts, &nCAs, szCN, sizeof(szCN), szCA, sizeof(szCA)); // find usable responder cert by trying all of them // until verification with one succedes if(err == ERR_OK) { j = 0; do { pNotCert = 0; err2 = ERR_OK; if(nType == RESPID_NAME_TYPE) findResponderByCNAndHashAndIndex(&pNotCert, szCN, NULL, j); else if(nType == RESPID_KEY_TYPE) findResponderByCNAndHashAndIndex(&pNotCert, NULL, szCN, j); ddocDebug(1, "notarizeSignatureWithIp", "Find notary: %s idx: %d cert: %s", szCN, j, (pNotCert ? "OK" : "NULL")); if(pNotCert) { err2 = finalizeAndVerifyNotary2(pSigDoc, pSigInfo, pNotInfo, (const X509**)&caCerts, (const X509*)pNotCert, (const X509*)pSigCa); ddocDebug(1, "notarizeSignatureWithIp", "Verifying notary: %d", err); j++; if(err2) { // VS: release ownership before deletion pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_RESPONDERS_CERT); if(pCertValue && pCertValue->pCert == pNotCert) { ddocDebug(1, "notarizeSignatureWithIp", "Release notary cert err2: %d", err2); pCertValue->pCert = NULL; } X509_free(pNotCert); } } } while(pNotCert && err2 != ERR_OK); } if(pSigCa) X509_free(pSigCa); if(err2) err = err2; else clearErrors(); for(i = 0; i < NUM_SEARCH_CAS; i++) if(caCerts[i]) X509_free(caCerts[i]); if(pResp) OCSP_RESPONSE_free(pResp); // test if not cert is ok pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_RESPONDERS_CERT); ddocDebug(3, "notarizeSignatureWithIp", "End Notary: cert-val: %s cert: %s", ((pCertValue && pCertValue->pCert) ? "OK" : "NULL"), (pNotCert ? "OK" : "NULL")); // please note that we cannot free pNotCert here because we gave ownership to pNotInf! return err; } //-------------------------------------------------- // Signs the document and gets configrmation // pSigDoc - signed document pointer // ppSigInfo - address of new signature pointer // pin - smart card PIN // manifest - manifest / resolution (NULL) // city - signers city (NULL) // state - signers state (NULL) // zip - signers postal code (NULL) // country - signers country (NULL) //-------------------------------------------------- EXP_OPTION int signDocument(SignedDoc* pSigDoc, SignatureInfo** ppSigInfo, const char* pin, const char* manifest, const char* city, const char* state, const char* zip, const char* country) { return signDocumentWithSlot(pSigDoc, ppSigInfo, pin, manifest, city, state, zip, country, ConfigItem_lookup_int("DIGIDOC_SIGNATURE_SLOT", 0), 1, 1); } //-------------------------------------------------- // Signs the document and gets configrmation // pSigDoc - signed document pointer // ppSigInfo - address of new signature pointer // pin - smart card PIN // manifest - manifest / resolution (NULL) // city - signers city (NULL) // state - signers state (NULL) // zip - signers postal code (NULL) // country - signers country (NULL) //-------------------------------------------------- EXP_OPTION int signDocumentWithSlot(SignedDoc* pSigDoc, SignatureInfo** ppSigInfo, const char* pin, const char* manifest, const char* city, const char* state, const char* zip, const char* country, int nSlot, int nOcsp, int nSigner) { return signDocumentWithSlotAndSigner(pSigDoc, ppSigInfo, pin, manifest, city, state, zip, country, nSlot, nOcsp, nSigner, NULL); } //-------------------------------------------------- // Signs the document and gets configrmation // pSigDoc - signed document pointer // ppSigInfo - address of new signature pointer // pin - smart card PIN // manifest - manifest / resolution (NULL) // city - signers city (NULL) // state - signers state (NULL) // zip - signers postal code (NULL) // country - signers country (NULL) // nSigner - 1=PKCS11, 2=CNG (Microsoft CAPI) // szPkcs12FileName - PKCS#12 file name to be used for signing (required if nSigner=3) //-------------------------------------------------- EXP_OPTION int signDocumentWithSlotAndSigner(SignedDoc* pSigDoc, SignatureInfo** ppSigInfo, const char* pin, const char* manifest, const char* city, const char* state, const char* zip, const char* country, int nSlot, int nOcsp, int nSigner, const char* szPkcs12FileName) { int err = ERR_OK; SignatureInfo* pSigInfo = NULL; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(ppSigInfo); if(nSigner == 3) RETURN_IF_NULL_PARAM(szPkcs12FileName) if(!pSigDoc->szFormatVer || strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) || !pSigDoc->szFormat || strcmp(pSigDoc->szFormat, DIGIDOC_XML_1_1_NAME)) { SET_LAST_ERROR(ERR_UNSUPPORTED_FORMAT); return ERR_UNSUPPORTED_FORMAT; } clearErrors(); ddocDebug(1, "signDocument", "Creating new digital signature"); RETURN_IF_NOT(err == ERR_OK, err); // add new signature with default id err = SignatureInfo_new(&pSigInfo, pSigDoc, NULL); RETURN_IF_NOT(err == ERR_OK, err); *ppSigInfo = pSigInfo; // automatically calculate doc-info elements for this signature addAllDocInfos(pSigDoc, *ppSigInfo); // add signature production place if (city || state || zip || country) err = setSignatureProductionPlace(*ppSigInfo, city, state, zip, country); // add user roles if (manifest) err = addSignerRole(*ppSigInfo, 0, manifest, -1, 0); ddocDebug(1, "signDocument", "Calc signature"); // now sign the doc if(nSigner == 1 || !nSigner) err = calculateSignatureWithEstID(pSigDoc, *ppSigInfo, nSlot, pin); #ifdef WIN32 if(nSigner == 2) err = calculateSigInfoSignatureWithCSPEstID(pSigDoc, *ppSigInfo, 0, pin); #endif if(nSigner == 3) err = calculateSignatureWithPkcs12(pSigDoc, *ppSigInfo, szPkcs12FileName, pin); if(err == ERR_PKCS_LOGIN) return err; RETURN_IF_NOT(err == ERR_OK, ERR_PKCS_SIGN_DATA); if(nOcsp) err = notarizeSignature(pSigDoc, *ppSigInfo); RETURN_IF_NOT(err == ERR_OK, err); return ERR_OK; } //-------------------------------------------------- // Verify this notary // pSigDoc - signed document pointer // pNotInfo - notary to verify // returns error code //-------------------------------------------------- int verifyNotary(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, NotaryInfo* pNotInfo) { int err = ERR_OK, nCAs = NUM_SEARCH_CAS, i, err2 = 0; X509 * caCerts[NUM_SEARCH_CAS]; X509* pNotCert = 0, *pCaCert = 0; const DigiDocMemBuf *pMBuf = 0; char buf1[300], buf2[300], szNotSerial[100]; int mustFreeNotaryCert = 0; for (i = 0; i < NUM_SEARCH_CAS; i++) caCerts[i] = 0; // get responder certs serial nr szNotSerial[0] = 0; if(ddocSigInfo_GetOCSPRespondersCert(pSigInfo)) err = ReadCertSerialNumber(szNotSerial, sizeof(szNotSerial), ddocSigInfo_GetOCSPRespondersCert(pSigInfo)); // find responder cert and it's CA cert pMBuf = ddocNotInfo_GetResponderId(pNotInfo); RETURN_IF_NULL(pMBuf); memset(buf2, 0, sizeof(buf2)); // use responders cert from ddoc //pNotCert = ddocSigInfo_GetOCSPRespondersCert(pSigInfo); if(pNotInfo->nRespIdType == RESPID_NAME_TYPE) { err = findCN((char*)pMBuf->pMem, buf1, sizeof(buf1)); ddocDebug(3, "verifyNotary", "Responder text: %s", buf1); if (!err) { err = findResponderCA(buf2, sizeof(buf2), buf1, NULL); ddocDebug(3, "verifyNotary", "Responder CA: %s", buf2); } if(!err) { err = findResponder(&pNotCert, buf1, NULL, (strlen(szNotSerial) ? szNotSerial : NULL)); ddocDebug(3, "verifyNotary", "Responder %s cert: %s, err: %d", buf1, (pNotCert ? "OK" : "NULL"), err); } } else if(pNotInfo->nRespIdType == RESPID_KEY_TYPE) { i = sizeof(buf1); encode((const byte*)pMBuf->pMem, pMBuf->nLen, (byte*)buf1, &i); ddocDebug(3, "verifyNotary", "Responder bin: %s", buf1); if (!err) { err = findResponderCA(buf2, sizeof(buf2), NULL, buf1); ddocDebug(3, "verifyNotary", "Responder CA: %s", buf2); } if(!err) { err = findResponder(&pNotCert, NULL, buf1, (strlen(szNotSerial) ? szNotSerial : NULL)); ddocDebug(3, "verifyNotary", "Responder %s cert: %s, err: %d", buf1, (pNotCert ? "OK" : "NULL"), err); } } else { SET_LAST_ERROR(ERR_OCSP_WRONG_RESPID); err = ERR_OCSP_WRONG_RESPID; } if (!err) { ddocDebug(3, "verifyNotary", "Find ca chain for: %s", buf2); err = findCAChainForCNAndSigTime((X509**)caCerts, &nCAs, buf2, pNotCert, 0); ddocDebug(3, "verifyNotary", "CA chain for: %s, ca-s: %d, rc: %d", buf2, nCAs+1, err); } // use specific error code for responders cert not found! if(err) { SET_LAST_ERROR(ERR_OCSP_RESP_NOT_TRUSTED); err = ERR_OCSP_RESP_NOT_TRUSTED; } ddocDebug(3, "verifyNotary", "Chain length: %d, err: %d", nCAs+1, err); if(pNotCert) { // #23784 - dont use responders cert in signature, use local copy err = ddocSigInfo_SetOCSPRespondersCert(pSigInfo, pNotCert); ddocDebug(3, "verifyNotary", "assigned notary cert from local store"); } else { mustFreeNotaryCert = 1; } if (!err) { ddocDebug(3, "verifyNotary", "Verifying Notary %s - cert: %s CA-s: %d", pNotInfo->szId, ((pNotCert) ? "OK" : "NULL"),nCAs+1); err = findCAForCertificateAndSigTime(&pCaCert, ddocSigInfo_GetSignersCert(pSigInfo), 0); err = verifyNotaryInfoCERT2(pSigDoc, pSigInfo, pNotInfo, (const X509**)caCerts, ConfigItem_lookup("CA_CERT_PATH"), pNotCert, pCaCert); ddocDebug(3, "verifyNotary", "Verifying Notary %s - %s", pNotInfo->szId, ((!err) ? "OK" : "ERROR")); } if (mustFreeNotaryCert) { ddocDebug(3, "verifyNotary", "freed notary cert, hopefully all is OK"); X509_free(pNotCert); } if (!err) { err = isCertSignedByCERT(ddocSigInfo_GetOCSPRespondersCert(pSigInfo), caCerts[nCAs]); if(err) { err2 = isCertSignedByCERT(ddocSigInfo_GetOCSPRespondersCert(pSigInfo), caCerts[nCAs - 1]); if(!err2) clearErrors(); else err = err2; } ddocDebug(3, "verifyNotary", "\tCertificate trusted - %s", ((!err) ? "OK" : "ERROR")); } // verify notary digest if (!err) { err = verifyNotaryDigest(pSigDoc, pNotInfo); ddocDebug(3, "verifyNotary", "\tNotary digest - %s", ((!err) ? "OK" : "ERROR")); } for (i = 0; i < NUM_SEARCH_CAS; i++) { if(caCerts[i]) { X509_free(caCerts[i]); caCerts[i] = 0; } } if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Verify this signature and it's notary // pSigDoc - signed document pointer // pSigInfo - signature to verify // szFileName - input digidoc filename // returns error code //-------------------------------------------------- EXP_OPTION int verifySignatureAndNotary(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const char* szFileName) { int err1 = ERR_OK, err2 = ERR_OK, k; X509* pCA = 0; NotaryInfo* pNotInfo; time_t tProdAt = 0; pNotInfo = getNotaryWithSigId(pSigDoc, pSigInfo->szId); if(pNotInfo) ddocNotInfo_GetProducedAt_timet(pNotInfo, &tProdAt); err1 = findCAForCertificateAndSigTime(&pCA, ddocSigInfo_GetSignersCert(pSigInfo), tProdAt); ddocDebug(3, "verifySignatureAndNotary", "Sig: %s find ca: %d, CA: %s sig-time: %ld", pSigInfo->szId, err1, (pCA ? "OK" : "NULL"), (unsigned long)tProdAt); //RETURN_IF_NOT(err == ERR_OK, err); //RETURN_IF_NOT(pCA, ERR_SIGNERS_CERT_NOT_TRUSTED); if(!pCA) { err1 = ERR_SIGNERS_CERT_NOT_TRUSTED; SET_LAST_ERROR(err1); } if(pCA) err2 = verifySignatureInfoCERT(pSigDoc, pSigInfo, pCA, szFileName, 1); if(err2) { SET_LAST_ERROR(err2); err1 = err2; } if (pNotInfo) { err2 = verifyNotary(pSigDoc, pSigInfo, pNotInfo); if(err2) { SET_LAST_ERROR(err2); if(!err1) err1 = err2; } ddocDebug(3, "verifySignatureAndNotary", "verify notary: %d", err2); } else { ddocDebug(3, "verifySignatureAndNotary", "\tSignature has no OCSP confirmation!\n"); SET_LAST_ERROR(ERR_NO_OCSP); err2 = ERR_NO_OCSP; if(!err1) err1 = err2; } if((k = getCountOfSignerRoles(pSigInfo, 0)) > 1) { ddocDebug(1, "verifySignatureInfo", "Number of roles: %d, Currently supports max 1 roles", k); SET_LAST_ERROR(ERR_MAX_1_ROLES); err2 = ERR_MAX_1_ROLES; if(!err1) err1 = err2; } //} else // SET_LAST_ERROR(err2); if (pCA) X509_free(pCA); if(pSigInfo->nErr1) // restore possibly cleared parsing err SET_LAST_ERROR(pSigInfo->nErr1); ddocDebug(3, "verifySignatureAndNotary", "Sig: %s err: %d haserr: %d", pSigInfo->szId, err1, hasUnreadErrors()); return checkUnknownErr(); } //-------------------------------------------------- // Extract common name from cert DN or responder id // src - DN // dest - buffer for CN // destLen - size of output buffer in bytes //-------------------------------------------------- int findCN(char* src, char* dest, int destLen) { char* p1, *p2; int n; p1 = strstr(src, "CN="); if(p1) { p1 += 3; // start of CN field // find start of next field p2 = strchr(p1, '='); if(!p2) // if not found then this was the last field p2 = strchr(p1, 0); // if we have found = of next field then move back until before field name if(p2 && *p2 == '=') while(p2 > p1 && isalpha(*(p2-1))) p2--; // remove possible field separators while(p2 > p1 && (*(p2-1) == ' ' || *(p2-1) == ',' || *(p2-1) == '/')) p2--; if(p2) { n = (int)(p2-p1); if(n >= destLen) n = destLen - 1; strncpy(dest, p1, n); dest[n] = 0; return ERR_OK; } } SET_LAST_ERROR_RETURN_CODE(ERR_CERT_INVALID); } //------------------------------------------ // Verify certificate by OCSP // pCert - certificate to check // ppResp - address to return OCSP response. Use NULL if // you don't want OCSP response to be returned // returns error code //------------------------------------------ EXP_OPTION int ddocVerifyCertByOCSP(X509* pCert, OCSP_RESPONSE **ppResp) { return ddocVerifyCertByOCSPWithIp(pCert, ppResp, 0); } //------------------------------------------ // Verify certificate by OCSP // pCert - certificate to check // ppResp - address to return OCSP response. Use NULL if // you don't want OCSP response to be returned // returns error code //------------------------------------------ EXP_OPTION int ddocVerifyCertByOCSPWithIp(X509* pCert, OCSP_RESPONSE **ppResp, unsigned long ip) { int err = ERR_OK, nCAs = NUM_SEARCH_CAS, i, j, err2 = ERR_OK, nType; X509 * caCerts[NUM_SEARCH_CAS]; X509 *pNotCert = 0; char *pkcs12file, *pkcs12passwd; char *proxyHost, *proxyPort; char szCN[100], szCA[100], *ocspUrl; OCSP_RESPONSE *pResp = NULL; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; // check if OCSP must be signed if(ConfigItem_lookup_bool("SIGN_OCSP", 1)) { pkcs12file = (char*)ConfigItem_lookup("DIGIDOC_PKCS_FILE"); RETURN_IF_NOT(pkcs12file, ERR_OCSP_PKCS12_NO_FILE); pkcs12passwd = (char*)ConfigItem_lookup("DIGIDOC_PKCS_PASSWD"); RETURN_IF_NOT(pkcs12passwd, ERR_OCSP_PKCS12_NO_PASSWD); } else { pkcs12file = pkcs12passwd = NULL; } // check proxy usage if(ConfigItem_lookup_bool("USE_PROXY", 1)) { proxyHost = (char*)ConfigItem_lookup("DIGIDOC_PROXY_HOST"); RETURN_IF_NOT(proxyHost, ERR_WRONG_URL_OR_PROXY); proxyPort = (char*)ConfigItem_lookup("DIGIDOC_PROXY_PORT"); RETURN_IF_NOT(proxyPort, ERR_WRONG_URL_OR_PROXY); ddocDebug(4, "ddocVerifyCertByOCSPWithIp", "proxy: %s port : %s", proxyHost, proxyPort); } else { proxyHost = proxyPort = NULL; } // send OCSP request and don't verify result immediately err = ddocCertGetIssuerDN(pCert, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); err = ddocSelectOcspUrl((char*)mbuf1.pMem, &ocspUrl); ddocMemBuf_free(&mbuf1); RETURN_IF_NOT(err == ERR_OK, err); // find cert oweners CA cert chain err = ddocFindCaChainForCert(pCert, (X509**)caCerts, &nCAs, szCA, sizeof(szCA)); // if possible find OCSP URL by signers CA ddocDebug(3, "ddocVerifyCertByOCSPWithIp", "OCSP URL: %s CA: %s chain: %d", (ocspUrl ? ocspUrl : "NULL"), szCA, nCAs); err = verifyCertificateByOCSPWithIp(pCert, (const X509 **)caCerts, NULL, ocspUrl, proxyHost, proxyPort, pkcs12file, pkcs12passwd, &pResp, ip); ddocDebug(3, "ddocVerifyCertByOCSPWithIp", "OCSP verification - RC: %d, resp: %s", err, (pResp ? "OK" : "NULL")); // release cert CA chain, PR. index fix for(i = 0; i < NUM_SEARCH_CAS; i++) { if(caCerts[i]) { X509_free(caCerts[i]); caCerts[i] = 0; } } // verify OCSP response // find CN from responder-id, right CA and CA certs chain if(!err) err = ddocFindOcspCnCaAndCerts(pResp, &nType, (X509**)caCerts, &nCAs, szCN, sizeof(szCN), szCA, sizeof(szCA)); // find usable responder cert by trying all of them // until verification with one succedes if(err == ERR_OK) { j = 0; do { pNotCert = 0; err2 = ERR_OK; if(nType == RESPID_NAME_TYPE) findResponderByCNAndHashAndIndex(&pNotCert, szCN, NULL, j); else if(nType == RESPID_KEY_TYPE) findResponderByCNAndHashAndIndex(&pNotCert, NULL, szCN, j); ddocDebug(1, "ddocVerifyCertByOCSPWithIp", "Find notary: %s idx: %d cert: %s", szCN, j, (pNotCert ? "OK" : "NULL")); if(pNotCert) err2 = verifyOCSPResponse(pResp, (const X509**)&caCerts, NULL, (const X509*)pNotCert); ddocDebug(1, "ddocVerifyCertByOCSPWithIp", "Verifying notary: %d", err); j++; if(pNotCert) X509_free(pNotCert); } while(pNotCert && err2 != ERR_OK); } if(err2) err = err2; else clearErrors(); for(i = 0; i < NUM_SEARCH_CAS; i++) if(caCerts[i]) X509_free(caCerts[i]); // return OCSP response if requested if(pResp) { if(ppResp) *ppResp = pResp; else OCSP_RESPONSE_free(pResp); } return err; } //------------------------------------------ // Reads an arbitrary file into memory buffer // szFileName - file name and path // pData - memory buffer object // returns error code //------------------------------------------ EXP_OPTION int ddocReadFile(const char* szFileName, DigiDocMemBuf* pData) { int err = ERR_OK; long l1; FILE *hFile; char buf1[2050]; #ifdef WIN32 wchar_t *convFileName = 0; int i= 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "ddocReadFile", "file: %s, conv-file: %s len: %d", szFileName, convFileName, i); #endif RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(pData); pData->pMem = 0; pData->nLen = 0; #ifdef WIN32 hFile = _wfopen(convFileName, L"rb"); #else hFile = fopen(szFileName, "rb"); #endif RETURN_IF_NOT(hFile, ERR_FILE_READ); do { l1 = fread(buf1, 1, 2048, hFile); err = ddocMemAppendData(pData, buf1, (long)l1); } while(l1 == 2048 && !err); fclose(hFile); return err; } //------------------------------------------ // Writes an arbitrary file into memory buffer // szFileName - file name and path // pData - memory buffer object // returns error code //------------------------------------------ EXP_OPTION int ddocWriteFile(const char* szFileName, DigiDocMemBuf* pData) { int err = ERR_OK; FILE *hFile; #ifdef WIN32 wchar_t *convFileName = 0; int i= 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "ddocReadFile", "file: %s, conv-file: %s len: %d", szFileName, convFileName, i); #endif RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(pData); #ifdef WIN32 hFile = _wfopen(convFileName, L"wb"); #else hFile = fopen(szFileName, "wb"); #endif RETURN_IF_NOT(hFile, ERR_FILE_WRITE); if(hFile) fwrite(pData->pMem, 1, pData->nLen, hFile); fclose(hFile); return err; } libdigidoc-3.10.5/libdigidoc/DlgUnit.rc0000664000372000037200000000662013560273131017265 0ustar travistravis//Microsoft Developer Studio generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #define APSTUDIO_HIDDEN_SYMBOLS #include "windows.h" #undef APSTUDIO_HIDDEN_SYMBOLS #include "dlgunit.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Unknown language: 0x25, 0x1 resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ETI) #ifdef _WIN32 LANGUAGE 0x25, 0x1 #pragma code_page(1257) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_DLG_UNIT DIALOGEX 0, 0, 300, 155 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "DigiDoc" FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN DEFPUSHBUTTON "&OK",IDOK,240,136,50,14 GROUPBOX "Downloads:",IDC_GROUPBOX,2,2,296,126 PUSHBUTTON "&Cancel",IDCANCEL,180,136,50,14 CONTROL "List1",IDC_LISTVIEW,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,6,12,288,110,WS_EX_CLIENTEDGE END #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" "#include ""windows.h""\r\n" "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" "#include ""dlgunit.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #ifndef _MAC ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 2,7,1,56 PRODUCTVERSION 2,7,1,56 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "042504b0" BEGIN VALUE "Comments", "\0" VALUE "CompanyName", "AS Sertifitseerimiskeskus\0" VALUE "FileDescription", "DigiDocLib\0" VALUE "FileVersion", "2.7.1.56\0" VALUE "InternalName", "DigiDocLib\0" VALUE "LegalCopyright", "Copyright 2010\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "DigiDocLib.dll\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "AS Sertifitseerimiskeskus DigiDocLib\0" VALUE "ProductVersion", "2.7.1.56\0" VALUE "SpecialBuild", "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x425, 1200 END END #endif // !_MAC #endif // Unknown language: 0x25, 0x1 resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED libdigidoc-3.10.5/libdigidoc/libdigidoc.rc0000664000372000037200000000164613560273131020013 0ustar travistravis#ifndef Q_CC_BOR # if defined(UNDER_CE) && UNDER_CE >= 400 # include # else # include # endif #endif #include VS_VERSION_INFO VERSIONINFO FILEVERSION VERSION_COMMA PRODUCTVERSION VERSION_COMMA FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0x0L #endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "RIA" VALUE "FileDescription", "libdigidoc" VALUE "FileVersion", VERSION VALUE "InternalName", "libdigidoc" VALUE "LegalCopyright", "Copyright (C) 2009-2018 Estonian Information System Authority" VALUE "OriginalFilename", "libdigidoc.dll" VALUE "ProductName", "libdigidoc" VALUE "ProductVersion", VERSION END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x425, 1200 END END /* End of Version info */ libdigidoc-3.10.5/libdigidoc/DigiDocObj.h0000664000372000037200000015763713560273131017516 0ustar travistravis#ifndef __DIGIDOC_OBJ_H__ #define __DIGIDOC_OBJ_H__ //================================================== // FILE: DigiDocGen.h // PROJECT: Digi Doc // DESCRIPTION: DigiDoc helper routines for accessing dogidoc data // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 26.04.2006 Veiko Sinivee // Creation //================================================== #include "DigiDocDefs.h" #include "DigiDocMem.h" #include #include //==========< DigiDoc object structure >======================== #ifdef __cplusplus extern "C" { #endif // contains the signed attributes of each document file entry typedef struct DocInfo_st { char* szDocId; // document id char* szDigestType; // digest method used byte* szDigest; // digest value int nDigestLen; // digest value length byte* szMimeDigest; // digest value int nMimeDigestLen; // digest value length } DocInfo; typedef struct SignatureProductionPlace_st { char* szCity; char* szStateOrProvince; char* szPostalCode; char* szCountryName; } SignatureProductionPlace; typedef struct SignerRole_st { int nClaimedRoles; char** pClaimedRoles; int nCertifiedRoles; char** pCertifiedRoles; } SignerRole; typedef struct DigestValue_st { char* szDigestMethod; DigiDocMemBuf mbufDigestValue; } DigestValue; /* typedef struct ReferenceInfo_st { char* szId; char* szUri; char* szType; DigestValue digestValue; } ReferenceInfo; */ typedef struct SignatureValue_st { char* szId; char* szType; DigiDocMemBuf mbufSignatureValue; } SignatureValue; #define CERTID_TYPE_UNKNOWN 0 #define CERTID_TYPE_SIGNERS_CERTID 1 #define CERTID_TYPE_RESPONDERS_CERTID 2 #define CERTID_TYPE_TSA_CERTID 3 //AM 12.03.08 #define CERTID_VALUE_CA_CERT 4 typedef struct CertID_st { int nType; // internal CertID type: char* szId; char* szIssuerSerial; char* szIssuerName; DigestValue* pDigestValue; //AM 24.04.08 char* szDigestType; // digest method used } CertID; typedef struct CertIDList_st { int nCertIDs; CertID** pCertIDs; } CertIDList; #define CERTID_VALUE_UNKNOWN 0 #define CERTID_VALUE_SIGNERS_CERT 1 #define CERTID_VALUE_RESPONDERS_CERT 2 #define CERTID_VALUE_TSA_CERT 3 //AM 12.03.08 #define CERTID_TYPE_CA_CERTID 4 #define ERR_VER_1_0 300 typedef struct CertValue_st { int nType; char* szId; X509* pCert; } CertValue; typedef struct CertValueList_st { int nCertValues; CertValue** pCertValues; } CertValueList; // data file entry for each data file typedef struct DataFile_st { char* szId; // data file id char* szFileName; // signed doc file name char* szMimeType; // date file mime type char* szContentType; // EMBEDDED or EMBEDDED_BASE64 long nSize; // file size (unencoded) char* szDigestType; // digest type DigiDocMemBuf mbufDigest; // real DataFile digest value DigiDocMemBuf mbufWrongDigest; // bad digest calculated in some versions DigiDocMemBuf mbufDetachedDigest; // detached file digest int nAttributes; // number of other attributes char* szCharset; // datafile initial codepage char** pAttNames; // other attribute names char** pAttValues; // other attribute values DigiDocMemBuf mbufContent; } DataFile; typedef struct NotaryInfo_sk { char* szId; // Notary id char* szNotType; // notary info type (OCSP-1.0) char* timeProduced; // producedAt char* szProducedAt; // producedAt in xml int nRespIdType; // RESP_ID_NAME, RESP_ID_KEY DigiDocMemBuf mbufRespId; // responder id value char* szDigestType; // digest method used // notaries personal signature char* szSigType; // signature type used DigiDocMemBuf mbufOcspDigest; // OCSP response digest (as in XML DigiDocMemBuf mbufOcspResponse; // OCSP response (in memory held in DER) } NotaryInfo; // signature info for each user signature typedef struct SignatureInfo_st { char* szId; // signature id int nDocs; // number of separate documents signed DocInfo** pDocs; // info for each signed document char* szTimeStamp; // signature timestamp in format "YYYY-MM-DDTHH:MM:SSZ" DigestValue *pSigPropDigest; DigestValue *pSigPropRealDigest; DigestValue *pSigInfoRealDigest; SignatureValue *pSigValue; // RSA+SHA1 signature value X509* pX509Cert; // X509Cert certificate (used internally for data during loading) SignatureProductionPlace sigProdPlace; SignerRole signerRole; DigiDocMemBuf mbufOrigContent; NotaryInfo* pNotary; CertIDList *pCertIDs; CertValueList *pCertValues; //AM 24.04.08 char* szDigestType; // digest method used int nErr1; // possible parse error codes, need many? } SignatureInfo; typedef struct SignedDoc_st { char* szFormat; // data format name char* szFormatVer; // data format version int nDataFiles; DataFile** pDataFiles; int nSignatures; SignatureInfo** pSignatures; //AM 14.03.08 char* szFileName; //AM 13.05.08 char* szProfile; } SignedDoc; //============================================================ // Sets a string element of a struct to a new value // dest - element pointer // value - new value // valLen - value length (use -1 for null terminated strings) //============================================================ EXP_OPTION int setString(char** dest, const char* value, int valLen); // creates a new structure EXP_OPTION int SignedDoc_new(SignedDoc **newSignedDoc, const char* format, const char* version); // cleanup signed doc data EXP_OPTION void SignedDoc_free(SignedDoc* pSigDoc); //======================< DataFile functions >============================= // returns the number of data files EXP_OPTION int getCountOfDataFiles(const SignedDoc* pSigDoc); // returns the n-th DataFile object EXP_OPTION DataFile* getDataFile(const SignedDoc* pSigDoc, int nIdx); // returns the last DataFile object EXP_OPTION DataFile* ddocGetLastDataFile(const SignedDoc* pSigDoc); // Retrieve and convert DataFile Filename atribute and convert EXP_OPTION int ddocGetDataFileFilename(SignedDoc* pSigDoc, const char* szDocId, void** ppBuf, int* pLen); // returns the DataFile object with the given id EXP_OPTION DataFile* getDataFileWithId(const SignedDoc* pSigDoc, const char* id); // add a block to // use NULL for any parameter you don't have the value // use NULL for id if you want to auto-calculate it (recommended!!!) EXP_OPTION int DataFile_new(DataFile **newDataFile, SignedDoc* pSigDoc, const char* id, const char* filename, const char* contentType, const char* mime, long size, const byte* digest, int digLen, const char* digType, const char* szCharset); // cleanup DataFile memory EXP_OPTION void DataFile_free(DataFile* pDataFile); // Removes this DataFile from signed doc and frees it's memory EXP_OPTION int DataFile_delete(SignedDoc* pSigDoc, const char* id); //-------------------------------------------------- // Accessor for Digest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocDataFile_GetDigestValue(DataFile* pDataFile); //-------------------------------------------------- // Mutatoror for Digest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDataFile_SetDigestValue(DataFile* pDataFile, const char* value, long len); //-------------------------------------------------- // Accessor for DetachedDigest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocDataFile_GetDetachedDigestValue(DataFile* pDataFile); //-------------------------------------------------- // Mutatoror for DetachedDigest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDataFile_SetDetachedDigestValue(DataFile* pDataFile, const char* value, long len); //-------------------------------------------------- // Accessor for WrongDigest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocDataFile_GetWrongDigestValue(DataFile* pDataFile); //-------------------------------------------------- // Mutatoror for WrongDigest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDataFile_SetWrongDigestValue(DataFile* pDataFile, const char* value, long len); // Returns number of DataFile attributes EXP_OPTION int getCountOfDataFileAttributes(const DataFile* pDataFile); // Adds an attribute to data file EXP_OPTION int addDataFileAttribute(DataFile* pDataFile, const char* name, const char* value); // Gets an attribute of a data file EXP_OPTION int getDataFileAttribute(DataFile* pDataFile, int idx, char** name, char** value); // get datafile cahed data EXP_OPTION int ddocGetDataFileCachedData(SignedDoc* pSigDoc, const char* szDocId, void** ppBuf, long* pLen); // apppends DataFile content to cache EXP_OPTION void ddocAppendDataFileData(DataFile* pDf, int maxLen, void* data, int len, int isBase64); // calculates file size and digest and store in the // given DataFile object EXP_OPTION int calculateDataFileSizeAndDigest(SignedDoc* pSigDoc, const char* id, const char* filename, int digType); //-------------------------------------------------- // Creates new DataFile and assigns contet from memory // ppDataFile address of pointer to return new DataFile object // pSigDoc - SignedDoc object // id - new DataFile id. Use NULL for default // filename - filename // contentType - content type // mime - mime type // pData - address of DataFile content to be assigned // size - length of data in bytes //-------------------------------------------------- EXP_OPTION int createDataFileInMemory(DataFile **ppDataFile, SignedDoc* pSigDoc, const char* id, const char* filename, const char* contentType, const char* mime, const char* pData, long size); //======================< DigestValue functions >============================= //-------------------------------------------------- // "Constructor" of DigestValue object // ppDigestValue - address of buffer for newly allocated object [REQUIRED] // szDigestMethod - digest method [OPTIONAL] // szDigVal/lDigLen - digest value and length [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDigestValue_new(DigestValue** ppDigestValue, const char* szDigestMethod, void* szDigVal, long lDigLen); //-------------------------------------------------- // "Destructor" of DigestValue object // pDigestValue - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDigestValue_free(DigestValue* pDigestValue); //-------------------------------------------------- // Accessor for DigestMethod atribute of DigestValue object. // pDigestValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocDigestValue_GetDigestMethod(DigestValue* pDigestValue); //-------------------------------------------------- // Mutatoror for DigestMethod atribute of DigestValue object. // pDigestValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDigestValue_SetDigestMethod(DigestValue* pDigestValue, const char* value); //-------------------------------------------------- // Accessor for DigestValue atribute of DigestValue object. // pDigestValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocDigestValue_GetDigestValue(DigestValue* pDigestValue); //-------------------------------------------------- // Mutatoror for DigestValue atribute of DigestValue object. // pDigestValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDigestValue_SetDigestValue(DigestValue* pDigestValue, const char* value, long len); //-------------------------------------------------- // Compares two DigestValue structure on equality // pDigest1 - address of first digest [REQUIRED] // pDigest2 - address of second digest [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCompareDigestValues(DigestValue* pDigest1, DigestValue* pDigest2); //-------------------------------------------------- // Generates XML for element // pDigestValue - DigestValue object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocDigestValue_toXML(const DigestValue* pDigestValue, DigiDocMemBuf* pBuf); //======================< SignatureValue functions >============================= //============================================================ // Returns the next free signature id // pSigDoc - signed doc pointer //============================================================ EXP_OPTION int getNextSignatureId(const SignedDoc* pSigDoc); //-------------------------------------------------- // "Constructor" of SignatureValue object // ppSignatureValue - address of buffer for newly allocated object [REQUIRED] // szId - Id atribute value [OPTIONAL] // szType - signature type [OPTIONAL] // szDigVal/lDigLen - digest value and length [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_new(SignatureValue** ppSignatureValue, const char* szId, const char* szType, void* szSigVal, long lSigLen); //-------------------------------------------------- // "Destructor" of SignatureValue object // pSignatureValue - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_free(SignatureValue* pSignatureValue); //-------------------------------------------------- // Accessor for Id atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocSignatureValue_GetId(const SignatureValue* pSignatureValue); //-------------------------------------------------- // Mutatoror for Id atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_SetId(SignatureValue* pSignatureValue, const char* value); //-------------------------------------------------- // Accessor for Type atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocSignatureValue_GetType(const SignatureValue* pSignatureValue); //-------------------------------------------------- // Mutatoror for Type atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_SetType(SignatureValue* pSignatureValue, const char* value); //-------------------------------------------------- // Accessor for SignatureValue atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocSignatureValue_GetSignatureValue(const SignatureValue* pSignatureValue); //-------------------------------------------------- // Mutatoror for SignatureValue atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_SetSignatureValue(SignatureValue* pSignatureValue, const char* value, long len); //-------------------------------------------------- // Generates XML for element // pSignatureValue - SignatureValue object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocSignatureValue_toXML(const SignatureValue* pSignatureValue, DigiDocMemBuf* pBuf); //======================< CertID >==================================== //-------------------------------------------------- // "Constructor" of CertID object // ppCertID - address of buffer for newly allocated object [REQUIRED] // szId - Id atribute value [OPTIONAL] // nType - certid internal type (signers or responders cert) [REQUIRED] // szIssuerSerial - issuer serial number [OPTIONAL] // szIssuerName - issuer DN [OPTIONAL] // szDigVal/lDigLen - digest value and length [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_new(CertID** ppCertID, int nType, const char* szId, const char* szIssuerSerial, const char* szIssuerName, void* szDigVal, long lDigLen); //-------------------------------------------------- // "Destructor" of CertID object // pCertID - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_free(CertID* pCertID); //-------------------------------------------------- // Accessor for Id atribute of CertID object. // pCertID - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocCertID_GetId(const CertID* pCertID); //-------------------------------------------------- // Mutatoror for Id atribute of CertID object. // pCertID - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_SetId(CertID* pCertID, const char* value); //-------------------------------------------------- // Accessor for IssuerSerial atribute of CertID object. // pCertID - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocCertID_GetIssuerSerial(const CertID* pCertID); //-------------------------------------------------- // Mutatoror for IssuerSerial atribute of CertID object. // pCertID - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_SetIssuerSerial(CertID* pCertID, const char* value); //-------------------------------------------------- // Accessor for IssuerName atribute of CertID object. // pCertID - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocCertID_GetIssuerName(const CertID* pCertID); //-------------------------------------------------- // Mutatoror for IssuerName atribute of CertID object. // pCertID - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_SetIssuerName(CertID* pCertID, const char* value); //-------------------------------------------------- // Accessor for DigestValue atribute of CertID object. // pCertID - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocCertID_GetDigestValue(const CertID* pCertID); //-------------------------------------------------- // Mutatoror for DigestValue atribute of CertID object. // pCertID - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_SetDigestValue(CertID* pCertID, const char* value, long len); //-------------------------------------------------- // Generates XML for element // pCertID - CertID object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCertID_toXML(const SignedDoc* pSigDoc, const CertID* pCertID, DigiDocMemBuf* pBuf); //-------------------------------------------------- // Generates XML for element // pSigDoc - SignedDoc object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCompleteCertificateRefs_toXML(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, DigiDocMemBuf* pBuf); int bdocCompleteCertificateRefs_toXML(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, DigiDocMemBuf* pBuf); //-------------------------------------------------- // Generates XML for element // pSigDoc - SignedDoc object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCompleteRevocationRefs_toXML(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, DigiDocMemBuf* pBuf); //==========< CertIDList >==================== //-------------------------------------------------- // "Constructor" of CertIDList object // ppCertIDList - address of buffer for newly allocated object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertIDList_new(CertIDList** ppCertIDList); //-------------------------------------------------- // "Destructor" of CertIDList object // pCertIDList - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertIDList_free(CertIDList* pCertIDList); //-------------------------------------------------- // Accessor for count of CertIDs subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCertIDList_addCertID(CertIDList* pCertIDList, CertID* pCertID); //-------------------------------------------------- // Accessor for count of CertIDs subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // returns count or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int ddocCertIDList_GetCertIDsCount(CertIDList* pCertIDList); //-------------------------------------------------- // Accessor for CertIDs subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // nIdx - index of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetCertID(CertIDList* pCertIDList, int nIdx); //-------------------------------------------------- // Accessor for last CertIDs subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetLastCertID(CertIDList* pCertIDList); //-------------------------------------------------- // Deletes CertID subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // nIdx - index of CertID object to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertIDList_DeleteCertID(CertIDList* pCertIDList, int nIdx); //-------------------------------------------------- // Finds a CertID object with required type // pCertIDList - pointer to CertIDList object [REQUIRED] // nType - type of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetCertIDOfType(CertIDList* pCertIDList, int nType); //-------------------------------------------------- // Finds a CertID object with required serial nr // pCertIDList - pointer to CertIDList object [REQUIRED] // szSerial - issuer serial // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetCertIDOfSerial(CertIDList* pCertIDList, const char* szSerial); //-------------------------------------------------- // Finds a CertID object with required type or creates a new one // pCertIDList - pointer to CertIDList object [REQUIRED] // nType - type of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetOrCreateCertIDOfType(CertIDList* pCertIDList, int nType); //======================< CertValue >==================================== //-------------------------------------------------- // "Constructor" of CertValue object // ppCertValue - address of buffer for newly allocated object [REQUIRED] // szId - Id atribute value [OPTIONAL] // nType - certid internal type (signers or responders cert) [REQUIRED] // pCert - certificate itself [OPTIONAL]. Must fill in later. Do not X509_free() param! // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValue_new(CertValue** ppCertValue, int nType, const char* szId, X509* pCert); //-------------------------------------------------- // "Destructor" of CertValue object // pCertValue - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValue_free(CertValue* pCertValue); //-------------------------------------------------- // Accessor for Id atribute of CertValue object. // pCertValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocCertValue_GetId(CertValue* pCertValue); //-------------------------------------------------- // Mutatoror for Id atribute of CertValue object. // pCertValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValue_SetId(CertValue* pCertValue, const char* value); //-------------------------------------------------- // Accessor for Cert atribute of CertValue object. // pCertValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION X509* ddocCertValue_GetCert(CertValue* pCertValue); //-------------------------------------------------- // Mutatoror for Cert atribute of CertValue object. // pCertValue - address of object [REQUIRED] // pCert - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValue_SetCert(CertValue* pCertValue, X509* pCert); //-------------------------------------------------- // Generates XML for element // pCertID - CertID object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCertValue_toXML(const CertValue* pCertValue, DigiDocMemBuf* pBuf); //==========< CertValueList >==================== //-------------------------------------------------- // "Constructor" of CertValueList object // ppCertValueList - address of buffer for newly allocated object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValueList_new(CertValueList** ppCertValueList); //-------------------------------------------------- // "Destructor" of CertValueList object // pCertValueList - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValueList_free(CertValueList* pCertValueList); //-------------------------------------------------- // Adds a CertValue element to CertValueList object. // pCertValueList - pointer to CertValueList object [REQUIRED] // pCertValue - new object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValueList_addCertValue(CertValueList* pCertValueList, CertValue* pCertValue); //-------------------------------------------------- // Accessor for count of CertValues subelement of CertValueList object. // pCertValueList - pointer to CertValueList object [REQUIRED] // returns count or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int ddocCertValueList_GetCertValuesCount(CertValueList* pCertValueList); //-------------------------------------------------- // Accessor for CertValues subelement of CertValueList object. // pCertValueList - pointer to CertValueList object [REQUIRED] // nIdx - index of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocCertValueList_GetCertValue(CertValueList* pCertValueList, int nIdx); //-------------------------------------------------- // Deletes CertValue subelement of CertValueList object. // pCertValueList - pointer to CertValueList object [REQUIRED] // nIdx - index of CertValue object to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValueList_DeleteCertValue(CertValueList* pCertValueList, int nIdx); //-------------------------------------------------- // Finds a CertValue object with required type // pCertValueList - pointer to CertValueList object [REQUIRED] // nType - type of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocCertValueList_GetCertValueOfType(CertValueList* pCertValueList, int nType); //-------------------------------------------------- // Finds a CertValue object with required type or creates a new one // pCertValueList - pointer to CertValueList object [REQUIRED] // nType - type of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocCertValueList_GetOrCreateCertValueOfType(CertValueList* pCertValueList, int nType); //======================< SignatureInfo functions >============================= // returns the number of signatures EXP_OPTION int getCountOfSignatures(const SignedDoc* pSigDoc); // Returns the desired SignatureInfo object EXP_OPTION SignatureInfo* getSignature(const SignedDoc* pSigDoc, int nIdx); //============================================================ // Returns signatures signed properties digest // pSigInfo - signature info object // return digest value as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSigPropDigest(SignatureInfo* pSigInfo); //============================================================ // Sets signatures signed properties digest // pSigInfo - signature info object // value - new binary digest value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSigPropDigest(SignatureInfo* pSigInfo, const char* value, long len); //============================================================ // Returns signatures signed properties digest as read from file // pSigInfo - signature info object // return digest value as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSigPropRealDigest(SignatureInfo* pSigInfo); //============================================================ // Sets signatures signed properties real digest as read from file // pSigInfo - signature info object // value - new binary digest value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSigPropRealDigest(SignatureInfo* pSigInfo, const char* value, long len); //============================================================ // Returns signatures signed info digest as read from file // pSigInfo - signature info object // return digest value as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSigInfoRealDigest(SignatureInfo* pSigInfo); //============================================================ // Sets signatures signed info real digest as read from file // pSigInfo - signature info object // value - new binary digest value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSigInfoRealDigest(SignatureInfo* pSigInfo, const char* value, long len); //============================================================ // Returns signatures signature-value // pSigInfo - signature info object // return signature-value as SignatureValue pointer or NULL //============================================================ EXP_OPTION SignatureValue* ddocSigInfo_GetSignatureValue(SignatureInfo* pSigInfo); //============================================================ // Returns signatures signature-value // pSigInfo - signature info object // return signature-value as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSignatureValue_Value(SignatureInfo* pSigInfo); //============================================================ // Sets signatures signature-value // pSigInfo - signature info object // value - new binary signature value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSignatureValue(SignatureInfo* pSigInfo, const char* value, long len); //============================================================ // Returns signaers certs - issuer-serial // pSigInfo - signature info object // return required atribute value //============================================================ EXP_OPTION const char* ddocSigInfo_GetSignersCert_IssuerSerial(const SignatureInfo* pSigInfo); //============================================================ // Sets signers certs issuer serial // pSigInfo - signature info object // value - new value //============================================================ EXP_OPTION int ddocSigInfo_SetSignersCert_IssuerSerial(SignatureInfo* pSigInfo, const char* value); //============================================================ // Returns signaers certs - issuer-name // pSigInfo - signature info object // return required atribute value //============================================================ EXP_OPTION const char* ddocSigInfo_GetSignersCert_IssuerName(const SignatureInfo* pSigInfo); //============================================================ // Returns signaers certs - issuer-name // pSigInfo - signature info object // pMbuf - memory buffer to return hash // return required atribute value //============================================================ EXP_OPTION const char* ddocSigInfo_GetSignersCert_IssuerNameAndHash(const SignatureInfo* pSigInfo, DigiDocMemBuf *pMbuf); //============================================================ // Sets signers certs issuer name // pSigInfo - signature info object // value - new value //============================================================ EXP_OPTION int ddocSigInfo_SetSignersCert_IssuerName(SignatureInfo* pSigInfo, const char* value); //============================================================ // Returns signers certs digest as DigiDocMemBuf object // pSigInfo - signature info object // return signers certs digest as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSignersCert_DigestValue(const SignatureInfo* pSigInfo); //============================================================ // Sets signers certs digest // pSigInfo - signature info object // value - new binary signature value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSignersCert_DigestValue(SignatureInfo* pSigInfo, const char* value, long len); //-------------------------------------------------- // Finds a CertID object with required type // pSigInfo - signature info object [REQUIRED] // nType - type of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocSigInfo_GetCertIDOfType(const SignatureInfo* pSigInfo, int nType); //-------------------------------------------------- // Finds a CertID object with required type or creates a new one // pSigInfo - signature info object [REQUIRED] // nType - type of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocSigInfo_GetOrCreateCertIDOfType(SignatureInfo* pSigInfo, int nType); //-------------------------------------------------- // Finds last CertID object of this signature // pSigInfo - signature info object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocSigInfo_GetLastCertID(const SignatureInfo* pSigInfo); //-------------------------------------------------- // Finds a CertValue object with required type // pSigInfo - signature info object [REQUIRED] // nType - type of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocSigInfo_GetCertValueOfType(const SignatureInfo* pSigInfo, int nType); //-------------------------------------------------- // Finds last CertValue // pSigInfo - signature info object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocSigInfo_GetLastCertValue(const SignatureInfo* pSigInfo); //-------------------------------------------------- // Finds a CertValue object with required type or creates a new one // pSigInfo - signature info object [REQUIRED] // nType - type of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocSigInfo_GetOrCreateCertValueOfType(SignatureInfo* pSigInfo, int nType); //-------------------------------------------------- // Finds the signers certificate // pSigInfo - signature info object [REQUIRED] // returns certificate or NULL //-------------------------------------------------- EXP_OPTION X509* ddocSigInfo_GetSignersCert(const SignatureInfo* pSigInfo); //-------------------------------------------------- // Sets the signers certificate // pSigInfo - signature info object [REQUIRED] // pCert - certificate [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSigInfo_SetSignersCert(SignatureInfo* pSigInfo, X509* pCert); //-------------------------------------------------- // Finds the OCSP responders certificate // pSigInfo - signature info object [REQUIRED] // returns certificate or NULL //-------------------------------------------------- EXP_OPTION X509* ddocSigInfo_GetOCSPRespondersCert(const SignatureInfo* pSigInfo); //-------------------------------------------------- // Sets the OCSP Responders certificate // pSigInfo - signature info object [REQUIRED] // pCert - certificate [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSigInfo_SetOCSPRespondersCert(SignatureInfo* pSigInfo, X509* pCert); //============================================================ // Adds a certificate and it's certid to this signature // pSigInfo - signature info object [REQUIRED] // pCert - vertificate [REQUIRED] // nCertIdType - type of cert [REQUIRED] // return error code or ERR_OK //============================================================ EXP_OPTION int ddocSigInfo_addCert(SignatureInfo* pSigInfo, X509* pCert, int nCertIdType); //AM EXP_OPTION int bdocSigInfo_addCert(SignatureInfo* pSigInfo, X509* pCert, int nCertIdType); // Returns the last SignatureInfo object EXP_OPTION SignatureInfo* ddocGetLastSignature(const SignedDoc* pSigDoc); // Returns the SignatureInfo object with the given id EXP_OPTION SignatureInfo* getSignatureWithId(const SignedDoc* pSigDoc, const char* id); // Returns the SignatureInfo for the given NotaryInfo EXP_OPTION SignatureInfo* ddocGetSignatureForNotary(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo); // Adds a new SignedInfo element to a SignedDoc element and initializes it EXP_OPTION int SignatureInfo_new(SignatureInfo **newSignatureInfo, SignedDoc* pSigDoc, const char* id); // Sets the signature production place info (use NULL for unknown attributes) EXP_OPTION int setSignatureProductionPlace(SignatureInfo* pSigInfo, const char* city, const char* state, const char* zip, const char* country); // Adds a signer role EXP_OPTION int addSignerRole(SignatureInfo* pSigInfo, int nCertified, const char* role, int rLen, int encode); // Returns the number of signer roles EXP_OPTION int getCountOfSignerRoles(SignatureInfo* pSigInfo, int nCertified); // Returns the desired signer role EXP_OPTION const char* getSignerRole(SignatureInfo* pSigInfo, int nCertified, int nIdx); // Removes this SignatureInfo from signed doc and frees it's memory EXP_OPTION int SignatureInfo_delete(SignedDoc* pSigDoc, const char* id); // cleanup SignatureInfo memory EXP_OPTION void SignatureInfo_free(SignatureInfo* pSigInfo); //======================< DocInfo functions >============================= // Adds a new DocInfo element to a SignatureInfo element and initializes it EXP_OPTION int addDocInfo(DocInfo **newDocInfo, SignatureInfo* pSigInfo, const char* docId, const char* digType, const byte* digest, int digLen, const byte* mimeDig, int mimeDigLen); // cleanup DocInfo memory EXP_OPTION void DocInfo_free(DocInfo* pDocInfo); // Returns number of DocInfos EXP_OPTION int getCountOfDocInfos(const SignatureInfo* pSigInfo); // Returns the desired DocInfo EXP_OPTION DocInfo* getDocInfo(const SignatureInfo* pSigInfo, int idx); // Returns the last DocInfo EXP_OPTION DocInfo* ddocGetLastDocInfo(const SignatureInfo* pSigInfo); // Returns the DocInfo object with the given id EXP_OPTION DocInfo* getDocInfoWithId(const SignatureInfo* pSigInfo, const char* id); // Sets the DocInfo objects document digest and digest type EXP_OPTION void setDocInfoDigest(DocInfo* pDocInfo, const byte* digest, int digLen, const char* digType); // Sets the DocInfo objects mime digest and mime type EXP_OPTION void setDocInfoMimeDigest(DocInfo* pDocInfo, const byte* mimeDig, int mimeDigLen); // Adds all DocInfo elements in this file to a SignatureInfo element EXP_OPTION int addAllDocInfos(SignedDoc* pSigDoc, SignatureInfo* pSigInfo); //======================< NotaryInfo functions >============================= // returns the number of notarys EXP_OPTION int getCountOfNotaryInfos(const SignedDoc* pSigDoc); // Returns the desired NotaryInfo object EXP_OPTION NotaryInfo* getNotaryInfo(const SignedDoc* pSigDoc, int nIdx); // Returns the last NotaryInfo object EXP_OPTION NotaryInfo* ddocGetLastNotaryInfo(const SignedDoc* pSigDoc); // Returns the NotaryInfo object with the given id EXP_OPTION NotaryInfo* getNotaryWithId(const SignedDoc* pSigDoc, const char* id); // Returns the NotaryInfo object that corresponds to the given signature EXP_OPTION NotaryInfo* getNotaryWithSigId(const SignedDoc* pSigDoc, const char* sigId); // Returns the NotaryInfo object that corresponds to the given signature // ore creates a new one EXP_OPTION NotaryInfo* getOrCreateNotaryWithSigId(SignedDoc* pSigDoc, const char* sigId); // Adds a new NotaryInfo element to a SignedDoc element and initializes it partly EXP_OPTION int NotaryInfo_new(NotaryInfo** newNotaryInfo, SignedDoc* pSigDoc, SignatureInfo* pSigInfo); // the same as above, but reads response and cert from file EXP_OPTION int NotaryInfo_new_file(NotaryInfo** newNotaryInfo, SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const char* ocspRespFile, const char* notaryCertFile); // cleanup NotaryInfo memory EXP_OPTION void NotaryInfo_free(NotaryInfo* pNotary); //============================================================ // Returns OCSP responders id as in XML document // pNotary - Notary info // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ EXP_OPTION const DigiDocMemBuf* ddocNotInfo_GetResponderId(const NotaryInfo* pNotary); //============================================================ // Returns OCSP responders id value as string // pNotary - Notary info // return responder id value or NULL //============================================================ EXP_OPTION const char* ddocNotInfo_GetResponderId_Value(const NotaryInfo* pNotary); //============================================================ // Sets OCSP responders id as in XML document // pNotary - Notary info // data - new responder id value // len - length of value // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ int ddocNotInfo_SetResponderId(NotaryInfo* pNotary, const char* data, long len); //============================================================ // Returns OCSP response as memory buffer // pNotary - Notary info // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ const DigiDocMemBuf* ddocNotInfo_GetOCSPResponse(const NotaryInfo* pNotary); //============================================================ // Retrieves OCSP responses responder id type and value // pResp - OCSP response // pType - buffer for type // pMbufRespId - responder id // returns error code or ERR_OK //============================================================ int ddocGetOcspRespIdTypeAndValue(OCSP_RESPONSE* pResp, int *pType, DigiDocMemBuf* pMbufRespId); //============================================================ // Sets OCSP respondese value as in XML document. Must pass in // binary DER data! // pNotary - Notary info // data - new responder id value // len - length of value // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ int ddocNotInfo_SetOCSPResponse(NotaryInfo* pNotary, const char* data, long len); //============================================================ // Returns OCSP response value // pNotary - Notary info // return OCSP_RESPONSE pointer or NULL for error. Caller must // use OCSP_RESPONSE_free() to release it. //============================================================ OCSP_RESPONSE* ddocNotInfo_GetOCSPResponse_Value(const NotaryInfo* pNotary); //============================================================ // Sets OCSP respondese value. Must pass in real OCSP_RESPONSE // pNotary - Notary info // data - new responder id value // len - length of value // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ int ddocNotInfo_SetOCSPResponse_Value(NotaryInfo* pNotary, OCSP_RESPONSE* pResp); //============================================================ // Returns OCSP responders id type as string // pNotary - Notary info // return responder id type or NULL. DO NOT free() it! //============================================================ EXP_OPTION const char* ddocNotInfo_GetResponderId_Type(const NotaryInfo* pNotary); //============================================================ // Returns OCSP responses thisUpdate atribute as string // pNotary - Notary info // pMBuf - buffer for thisUpdate value // return error code OR ERR_OK. //============================================================ EXP_OPTION int ddocNotInfo_GetThisUpdate(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf); //============================================================ // Returns OCSP responses producedAt atribute as time_t // pNotary - Notary info // pTime - address of time_t variable // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetProducedAt_timet(const NotaryInfo* pNotary, time_t* pTime); //============================================================ // Returns OCSP responses producedAt from xml as time_t // pNotary - Notary info // pTime - address of time_t variable // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetProducedAtXml_timet(const NotaryInfo* pNotary, time_t* pTime); //============================================================ // Returns OCSP responses thisUpdate atribute as time_t // pNotary - Notary info // pTime - address of time_t variable // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetThisUpdate_timet(const NotaryInfo* pNotary, time_t* pTime); //============================================================ // Returns OCSP responses nextUpdate atribute as string // pNotary - Notary info // pMBuf - buffer for thisUpdate value // return error code OR ERR_OK. //============================================================ EXP_OPTION int ddocNotInfo_GetNextUpdate(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf); //============================================================ // Returns OCSP responses IssuerNameHash atribute // pNotary - Notary info // pMBuf - buffer for IssuerNameHash value // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetIssuerNameHash(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf); //============================================================ // Returns OCSP responses IssuerKeyHash atribute // pNotary - Notary info // pMBuf - buffer for IssuerKeyHash value // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetIssuerKeyHash(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf); //============================================================ // Returns OCSP responses real digest from response data // pNotary - Notary info // pMBuf - buffer for digest value // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetOcspRealDigest(const SignedDoc* pSigDoc, const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf); //============================================================ // Returns OCSP response digest as in XML document // pNotary - Notary info // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ EXP_OPTION const DigiDocMemBuf* ddocNotInfo_GetOcspDigest(const NotaryInfo* pNotary); //============================================================ // Sets OCSP response digest id as in XML document // pNotary - Notary info // data - new digest value // len - length of value // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ int ddocNotInfo_SetOcspDigest(NotaryInfo* pNotary, const char* data, long len); //============================================================ // Returns OCSP responses signature value // pNotary - Notary info // pMBuf - buffer for signature value // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetOcspSignatureValue(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf); // Removes this NotaryInfo from signed doc and frees it's memory EXP_OPTION int NotaryInfo_delete(SignatureInfo* pSigInfo); // Calculates and stores a signature for this SignatureInfo object EXP_OPTION int calculateSigInfoSignature(const SignedDoc* pSigDoc, SignatureInfo* pSigInfo, int nSigType, const char* keyfile, const char* passwd, const char* certfile); //============================================================ // Adds a certificate to Notary and initializes Notary // pNotary - Notary info // cert - responders certificate // return error code //============================================================ int addNotaryInfoCert(SignedDoc *pSigDoc, NotaryInfo *pNotary, X509 *cert); //============================================================ // Removes Notary cert value and id after unsucessful verification attempt // pSigInfo - signature info [REQUIRED] // return error code //============================================================ int removeNotaryInfoCert(SignatureInfo* pSigInfo); // Calculates digest EXP_OPTION int calculateSignedPropertiesDigest(SignedDoc* pSigDoc, SignatureInfo* pSigInfo); // Calculates digest EXP_OPTION int calculateSignedInfoDigest(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, byte* digBuf, int* digLen); //============================================================ // Returns 1 if this signature has 1 reference that was verified // by wrong DataFile hash calculated not using xmlns atribute // pSigInfo - signature info pointer //============================================================ DIGIDOC_DEPRECATED EXP_OPTION int verifiedByWrongDataFileHash(const SignatureInfo* pSigInfo); //============================================================ // Returns 1 if one signature has 1 reference that was verified // by wrong DataFile hash calculated not using xmlns atribute // pSigDoc - signed doc container pointer //============================================================ EXP_OPTION int hasSignatureWithWrongDataFileHash(const SignedDoc* pSigDoc); //============================================================ // Calculates and stores a signature for this SignatureInfo object // Uses PKCS#12 file to sign the info // pSigInfo - signature info object // nSigType - signature type code // szPkcs12File - PKCS#12 file // passwd - key password //============================================================ EXP_OPTION int calculateSignatureWithPkcs12(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const char* szPkcs12File, const char* passwd); #ifdef __cplusplus } #endif #endif // __DIGIDOC_OBJ_H__ libdigidoc-3.10.5/libdigidoc/DigiDocGlobals.c0000664000372000037200000000421413560273131020340 0ustar travistravis//================================================== // FILE: DigiDocGlobals.c // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDoc TSA profiles // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //================================================= #include #include #include #include #include #include // default TSAProfile (to be extended) LPTSAProfile g_current_TSAProfile = 0; //-------------------------------------------------- // Initializes TSA profile block // returns pointer to global TSA profile //-------------------------------------------------- EXP_OPTION TSAProfile* TSAProfile_init() { TSAProfile* p = g_current_TSAProfile; if(!p) { p = (TSAProfile*)malloc(sizeof(TSAProfile)); if(p) { memset(p, 0, sizeof(TSAProfile)); g_current_TSAProfile = p; p->g_bAddSignatureTimeStamp = 1; p->g_bAddSigAndRefsTimeStamp = 1; p->g_nTsaMaxTsInterval = 1; p->m_nDebugLevel = 0; strncpy(p->g_szTsaUrl, "http://ns.szikszi.hu:8080/tsa", sizeof(p->g_szTsaUrl)); memset(p->m_szDebugFilePath, 0, sizeof(p->m_szDebugFilePath)); // VS: changed initialization g_current_TSAProfile = p; } // init config store if(!isConfigInited()) initConfigStore(NULL); } return p; } EXP_OPTION void TSAProfile_free() { if(g_current_TSAProfile) free(g_current_TSAProfile); g_current_TSAProfile = 0; }libdigidoc-3.10.5/libdigidoc/DigiCrypt.h0000664000372000037200000000116313560273131017435 0ustar travistravis#ifndef DigiCryptH #define DigiCryptH #ifdef __cplusplus extern "C" { #endif #include #include #define dDigiCrypt_Okey 0 #define dDigiCrypt_Error_NotFoundCSP 1 #define dDigiCrypt_Error_UserCancel 2 #define dDigiCrypt_Error_NoDefaultKey 3 #define dDIgiCrypt_Error_NotFoundCert 4 PCCERT_CONTEXT DigiCrypt_FindContext(BOOL fByKeyContainer, DWORD *dwResult); char *DigiCrypt_FindContext_GetCSPName(void); char *DigiCrypt_FindContext_GetKeyName(void); DWORD DigiCrypt_FindContext_GetCSPType(char *psCSPName); void LOG(char *psMsgFmt, ...); #ifdef __cplusplus } #endif #endiflibdigidoc-3.10.5/libdigidoc/DigiDocGen.h0000664000372000037200000001755313560273131017505 0ustar travistravis#ifndef __DIGIDOC_GEN_H__ #define __DIGIDOC_GEN_H__ //================================================== // FILE: DigiDocGen.h // PROJECT: Digi Doc // DESCRIPTION: DigiDoc helper routines for XML generation // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 11.04.2006 Veiko Sinivee // Creation //================================================== #include #include #include //==========< XML generation routines >======================== #ifdef __cplusplus extern "C" { #endif #ifdef WITH_TIMETSTAMP_STRUCT // contains timestamp data typedef struct Timestamp_st { int year; int mon; int day; int hour; int min; int sec; int tz; } Timestamp; // converts timestamp string to it's components EXP_OPTION int convertStringToTimestamp(const SignedDoc* pSigDoc, const char* szTimestamp, Timestamp* pTimestamp); // converts timestamp to string EXP_OPTION int convertTimestampToString(const SignedDoc* pSigDoc, const Timestamp* pTimestamp, char* szTimestamp, int len); // creates new timestamp object EXP_OPTION int Timestamp_new(Timestamp **, int year,int month,int day,int hour,int minute,int second,int timezone); // frees this timestamp object EXP_OPTION void Timestamp_free(Timestamp* pTimestamp); #endif //============================================================ // Creates a timestamp string // buf - output buffer // len - length of output buffer // returns number of output bytes written //============================================================ int createTimestamp(const SignedDoc* pSigDoc, char* buf, int len); // converts timestamp string to time_t value EXP_OPTION time_t convertStringToTimeT(const SignedDoc* pSigDoc, const char* szTimestamp); //-------------------------------------------------- // Appends an xml element start to buffer, but no ">" // pBuf - memory buffer to store xml [REQUIRED] // elemName - xml element name [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_startElemBegin(DigiDocMemBuf* pBuf, const char* elemName); //-------------------------------------------------- // Appends an xml element start tag end to buffer - ">" // pBuf - memory buffer to store xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_startElemEnd(DigiDocMemBuf* pBuf); //-------------------------------------------------- // Appends an xml element start to buffer - // pBuf - memory buffer to store xml [REQUIRED] // elemName - xml element name [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_startElem(DigiDocMemBuf* pBuf, const char* elemName); //-------------------------------------------------- // Appends an xml element end to buffer // pBuf - memory buffer to store xml [REQUIRED] // elemName - xml element name [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_endElem(DigiDocMemBuf* pBuf, const char* elemName); //-------------------------------------------------- // Appends an xml element's atribute to buffer // pBuf - memory buffer to store xml [REQUIRED] // name - xml atribute name [REQUIRED] // value - xml atribute value [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_addAtribute(DigiDocMemBuf* pBuf, const char* name, const char* value); //-------------------------------------------------- // Helper function that escapes XML special chars // src - input data // srclen - length of input data. Use -1 for 0 terminated strings // dest - address of output buffer. Caller is responsible for deallocating it! // returns error code or ERR_OK //-------------------------------------------------- int escapeXMLSymbols(const char* src, int srclen, char** dest); //-------------------------------------------------- // Helper function that escapes XML special chars in xml element body // src - input data // srclen - length of input data. Use -1 for 0 terminated strings // dest - address of output buffer. Caller is responsible for deallocating it! // returns error code or ERR_OK //-------------------------------------------------- int escapeTextNode(const char* src, int srclen, char** dest); //================< functions generating DigiDoc formats 1.0 - 1.3 > ================================= // writes the signed doc to a file EXP_OPTION int createSignedDoc(SignedDoc* pSigDoc, const char* szOldFile, const char* szSigDocFile); //============================================================ // Canonicalizes XML // source - input data // len - input length // returns a newly allocated buffer with canonicalized XML // Caller must free() the result. //============================================================ char* canonicalizeXML(char* source, int len); char* canonicalizeXMLBlock(char* source, int len, char* block, char* prefix); //============================================================ // Creates a XML block // pSigDoc - signed document pointer // pSigInfo - signature info data // bWithEscapes - 1=escape xml sümbols, 0=don't escape // returns new node //============================================================ char* createXMLSignedProperties(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, int bWithEscapes); //============================================================ // Generates DataFile elements XML form and stores it in a file // pSigDoc - signed document // pDataFile - data file object to be converted // szDataFile - input file name // hFile - output file handle // pMBufXML - output buffer if we want data to be returned in mem buf //============================================================ EXP_OPTION int generateDataFileXML(SignedDoc* pSigDoc, DataFile* pDataFile, const char* szDataFile, FILE* hFile, DigiDocMemBuf* pMBufXML); //-------------------------------------------------- // Creates a new signed document in memory buffer // pSigDoc - signed doc info // szOldFile - name of old file on disk to copy DataFile contents // pMBuf - buffer for new digidoc document // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int createSignedDocInMemory(SignedDoc* pSigDoc, const char* szOldFile, DigiDocMemBuf* pMBuf); //-------------------------------------------------- // Removes incomplete or orphoned signatures. // Signature is incomplete if it hasn't got the signature // value // pSigDoc - signed doc info // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int removeIncompleteSignatures(SignedDoc* pSigDoc); //-------------------------------------------------- // Checks for incomplete or orphoned signatures. // Signature is incomplete if it hasn't got the signature // value // pSigDoc - signed doc info // returns error code if DigiDoc has orphoned signature or ERR_OK for success //-------------------------------------------------- EXP_OPTION int hasIncompleteSignatures(SignedDoc* pSigDoc); #ifdef __cplusplus } #endif #endif // __DIGIDOC_GEN_H__ libdigidoc-3.10.5/libdigidoc/DigiDocStack.h0000664000372000037200000001261613560273131020034 0ustar travistravis#ifndef __DIGIDOC_STACK_H__ #define __DIGIDOC_STACK_H__ //================================================== // FILE: DigiDocStack.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for simple stack // to keep track of xml parsing // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 09.09.2004 Veiko Sinivee // Creation //================================================== #include #include #ifdef __cplusplus extern "C" { #endif typedef struct ElementEntry_st { xmlChar* tag; // xml elements tag xmlChar* prefix; // namespace local prefix xmlChar* nsUri; // namespace URI // some important atributes xmlChar* id; // attribute "Id" xmlChar* uri; // attribute "URI" xmlChar* content; // attribute "ContentType" void* pNext; // next element in list/stack } ElementEntry; //-------------------------------------------------- // Finds the last element on stack // reader - XML reader cursor to current node // pStack - address of stack begin. This one elemnt // must exist, but might be initially empty // return error code or ERR_OK //-------------------------------------------------- ElementEntry* ddocStackFindEnd(ElementEntry* pStack); //-------------------------------------------------- // Push a new element info onto stack // reader - XML reader cursor to current node // pStack - address of stack begin. This one elemnt // must exist, but might be initially empty // pLastElem - address for new elements pointer. // If not NULL then will be used to return the // newly allocated elemnt, so you don't have to // do a new search. // return error code or ERR_OK //-------------------------------------------------- int ddocStackPushElement(ElementEntry* pStack, xmlTextReaderPtr reader, ElementEntry** pLastElem); //-------------------------------------------------- // Push a new element info onto stack // tagName - elements tag name, Possibly with ns-prefix // atts - array of atributa names and values // pStack - address of stack begin. This one elemnt // must exist, but might be initially empty // pLastElem - address for new elements pointer. // If not NULL then will be used to return the // newly allocated elemnt, so you don't have to // do a new search. // return error code or ERR_OK //-------------------------------------------------- int ddocStackPushElementSAX(ElementEntry* pStack, const xmlChar* tagName, const xmlChar** atts, ElementEntry** pLastElem); //-------------------------------------------------- // Pop the last element from the stack // pStack - address of stack begin. This one elemnt // must exist, and will never be deleted. // bCleanup - flag: 1=cleanup the whole stack, 0=just the last element // return error code or ERR_OK // pLastElem - address for new elements pointer. // If not NULL then will be used to return the // last element on stack. //-------------------------------------------------- int ddocStackPopElement(ElementEntry* pStack, int bCleanup, ElementEntry** pLastElem); //-------------------------------------------------- // Retrieve the current/last/stack top elements tag (localname) // pStack - address of stack begin. //-------------------------------------------------- const xmlChar* ddocStackCurrentTag(ElementEntry* pStack); //-------------------------------------------------- // Retrieve the current/last/stack top elements ns prefix // pStack - address of stack begin. //-------------------------------------------------- const xmlChar* ddocStackCurrentNsPrefix(ElementEntry* pStack); //-------------------------------------------------- // Retrieve the current/last/stack top elements ns prefix // pStack - address of stack begin. //-------------------------------------------------- const xmlChar* ddocStackCurrentNsUri(ElementEntry* pStack); //-------------------------------------------------- // Checks if there is a parent element with the given // localname on the stack. // pStack - address of stack begin. // return 1 if there is such a parent elem or 0 if not. //-------------------------------------------------- int ddocStackHasParentWithName(ElementEntry* pStack, const xmlChar* parentsName, ElementEntry* pCurrElem); //-------------------------------------------------- // Checks if there is a parent element with the given // localname on the stack. // pStack - address of stack begin. // return 1 if there is such a parent elem or 0 if not. //-------------------------------------------------- ElementEntry* ddocStackGetParentWithName(ElementEntry* pStack, const xmlChar* parentsName, ElementEntry* pCurrElem); #ifdef __cplusplus } #endif #endif // __DIGIDOC_STACK_H__ libdigidoc-3.10.5/libdigidoc/DigiDocPKCS11.c0000664000372000037200000010705113560273131017662 0ustar travistravis//================================================== // FILE: DigiDocPKCS11.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for signing using PKCS#11 API // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 10.02.2004 Integrated // 26.01.2004 Aare // Removed function signOCSPRequestWithPKCS11onWin // 13.01.2004 Veiko Sinivee // Creation //================================================== #include "DigiDocPKCS11.h" #include "DigiDocConfig.h" #include "DigiDocDebug.h" #include "DigiDocCert.h" #include "DigiDocGen.h" #include "DigiDocConvert.h" #include #include static CK_FUNCTION_LIST_PTR ckFunc = 0; //AA 04/01/26 extern X509_ALGOR* setSignAlgorithm(const EVP_MD * type); // I suppose there won't be so many slots #define INVALID_SLOTIID 1000 //============================================================ // Attempts to load and initialize on PKCS#11 driver DLL. //============================================================ EXP_OPTION LIBHANDLE initPKCS11Library(const char* libName) { LIBHANDLE pLibrary = 0; CK_C_GetFunctionList pC_GetFunctionList; CK_RV rv; // load PKCS#11 driver ddocDebug(3, "initPKCS11Library", "Loading driver: %s", libName); #ifdef WIN32 pLibrary = LoadLibrary((LPCSTR)libName); #else pLibrary = dlopen(libName, RTLD_NOW); #endif if(pLibrary != NULL) { // printf("Resolve PKCS#11 function index!\n"); // Get function pointer to C_GetFunctionList #ifdef WIN32 pC_GetFunctionList = (CK_C_GetFunctionList)GetProcAddress(/*(HINSTANCE__*)*/pLibrary, "C_GetFunctionList"); #else pC_GetFunctionList = (CK_C_GetFunctionList)dlsym(pLibrary, "C_GetFunctionList"); #endif if(pC_GetFunctionList != NULL) { ddocDebug(3, "initPKCS11Library", "Getting PKCS#11 func!"); // Get function pointers to all PKCS #11 functions rv = (*pC_GetFunctionList)(&ckFunc); if(rv == CKR_OK) { ddocDebug(3, "initPKCS11Library", "Initializing PKCS#11 library:"); // Initalize Cryptoki rv = (*ckFunc->C_Initialize)(0); ddocDebug(3, "initPKCS11Library", "Initlialized: %d", (int)rv); if(rv != CKR_OK) { ddocDebug(2, "initPKCS11Library", "Error initializing library!"); pLibrary = NULL; // error initializing the library } } else { ddocDebug(2, "initPKCS11Library", "Error getting PKCS#11 func!"); pLibrary = NULL; // error getting function pointers } } else { ddocDebug(2, "initPKCS11Library", "Error resolving PKCS#11 function index!"); pLibrary = NULL; // error getting function list function } } else { #ifdef WIN32 ddocDebug(2, "initPKCS11Library", "Error loading driver : %s", libName); #else ddocDebug(2, "initPKCS11Library", "Error loading driver : %s", dlerror()); #endif } return pLibrary; } //============================================================ // Cleanup PKCS#11 library session //============================================================ EXP_OPTION void closePKCS11Library(LIBHANDLE pLibrary, CK_SESSION_HANDLE hSession) { CK_RV rv; // close session if(hSession > 0) { ddocDebug(3, "closePKCS11Library", "Closing PKCS#11 session!"); rv = (*ckFunc->C_CloseSession)(hSession); } // finalize library rv = (*ckFunc->C_Finalize)(0); // remove .so from memory ddocDebug(3, "closePKCS11Library", "Closing PKCS#11 library!\n"); if(pLibrary) #ifdef WIN32 FreeLibrary(/*(HINSTANCE__*)*/pLibrary); #else dlclose(pLibrary); #endif } //============================================================ // Retrieves the slotid list //============================================================ EXP_OPTION CK_RV GetSlotIds(CK_SLOT_ID_PTR pSlotids, CK_ULONG_PTR pLen) { CK_RV rv; rv = (*ckFunc->C_GetSlotList)(TRUE, pSlotids, pLen); return rv; } //============================================================ // Retrieves one tokens info //============================================================ EXP_OPTION CK_RV GetTokenInfo(CK_TOKEN_INFO_PTR pTokInfo, CK_SLOT_ID id) { CK_RV rv; rv = (*ckFunc->C_GetTokenInfo)(id, pTokInfo); return rv; } //============================================================ // Retrieves one slots info //============================================================ EXP_OPTION CK_RV GetSlotInfo(CK_SLOT_INFO_PTR pSlotInfo, CK_SLOT_ID id) { CK_RV rv; rv = (*ckFunc->C_GetSlotInfo)(id, pSlotInfo); return rv; } //============================================================ // Loads the PKCS#11 driver and // tests if the driver loaded correctly // Returns 0 for ok otherwise error code //============================================================ int loadAndTestDriver(const char* driver, LIBHANDLE* pLibrary, CK_SLOT_ID* slotids, int slots, CK_ULONG slot) { CK_TOKEN_INFO tokinfo; CK_SLOT_INFO slotinfo; CK_ULONG idlen, i, ok; CK_RV rv; int err = ERR_OK; // initialize *pLibrary = NULL; memset(slotids, 0, sizeof(CK_SLOT_ID) * slots); // try to load the driver *pLibrary = initPKCS11Library(driver); if(!(*pLibrary)) SET_LAST_ERROR_RETURN_CODE(ERR_PKCS_LIB_LOAD); idlen = slots; rv = GetSlotIds(slotids, &idlen); ddocDebug(3, "loadAndTestDriver", "RV: %d slots: %ld", (int)rv, (long)idlen); if (rv != CKR_OK) { err = ERR_PKCS_SLOT_LIST; SET_LAST_ERROR(err); } if ((slot < 0) || (slot >= (int)idlen)) { err = ERR_PKCS_WRONG_SLOT; SET_LAST_ERROR(err); } // it's useful to test DLL load status this way: ok = 0; for(i = 0; i < (int)idlen; i++) { rv = GetSlotInfo(&slotinfo, slotids[i]); if(slotinfo.flags & CKF_TOKEN_PRESENT) { ddocDebug(3, "loadAndTestDriver", "Read Token: %ld", (long)i); rv = GetTokenInfo(&tokinfo, slotids[i]); // if !CKR_OK test tokinfo.label[31] = 0; ddocDebug(3, "loadAndTestDriver", "RV: %d Token: %s", (int)rv, tokinfo.label); if(rv != CKR_OK) slotids[i] = INVALID_SLOTIID; // set bad slotids to 0 else ok++; // count the good slots } else { slotids[i] = INVALID_SLOTIID; // no tokne in this slot } } // fill other slotid's with invalid slotid for(i = idlen; i < (CK_ULONG)slots; i++) slotids[i] = INVALID_SLOTIID; if(ok < slot) { err = ERR_PKCS_CARD_READ; // if not enough good slots SET_LAST_ERROR(err); } // in case of error try to unload the module and notify caller if (err) { if (*pLibrary) closePKCS11Library(*pLibrary, 0); *pLibrary = NULL; } return err; } //============================================================ // Opens smart card session. // slotId - id of the sert slot // pin - card pin // return session id or -1 for failure //============================================================ CK_SESSION_HANDLE OpenSession(CK_SLOT_ID slotId, const char *pin) { CK_SESSION_HANDLE hSession = 0; /* Ainult SERIAL_SESSION toetatud, Digiallkirja andvat privaatvo~tit kasutav sessioon on initsialiseeritud CKS_RO_USER_FUNCTIONS staatusesse, seda on tehtud Netscape lolli- tamiseks, et see igal vo~imalikul ja vo~imatul juhul ei ku"siks pin'i vo~tme jaoks mida ta niiehknii kasutada ei oska. Selle jaoks tuleb vajaduse korral ikka C_Login va"lja kutsuda. */ CK_RV rv = (*ckFunc->C_OpenSession)(slotId, CKF_SERIAL_SESSION,0,0,&hSession); ddocDebug(3, "OpenSession", "Open sess for slot id: %u - sess: %uld RV = %u", slotId, hSession, rv); if(rv == CKR_OK && pin) { // don't login if pin is null. Session can be used also to read certs. /* Kommentaar: Ainult CKU_USER toetatud. */ rv = (*ckFunc->C_Login)(hSession, CKU_USER, (unsigned char*)pin, strlen(pin)); ddocDebug(3, "OpenSession", "Login for slot id: %u - sess: %uld RV = %u", slotId, hSession, rv); if(rv != CKR_OK) hSession = CK_INVALID_HANDLE; // mark session bad! } // Return the session handle and exit return hSession; } //============================================================ // Sign a string using a private key referred by the supplied handle. // hSession - card session handle // hPrivateKey - private key handle // Signature - buffer for signature // ulSignatureLen - signature buffer length // sigData - data to be signed //============================================================ CK_RV SignData(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPrivateKey, CK_BYTE* Signature, CK_ULONG* ulSignatureLen, CK_BYTE* sigData, CK_ULONG dataLen) { // Set up mechanism for PKCS #1 signing CK_MECHANISM Mechanism = { CKM_RSA_PKCS, 0, 0 }; // Initiate the signature operation CK_RV rv = (*ckFunc->C_SignInit)(hSession,&Mechanism,hPrivateKey); if(rv == CKR_OK) { // Kommentaar: Realiseeritud meetodi CKM_RSA_PKCS jaoks. rv = (*ckFunc->C_Sign)(hSession, sigData, dataLen, Signature, ulSignatureLen); if(rv != CKR_OK) ddocDebug(1, "SignData", "Error signing - sess: %u pkey: %uld slen: %uld dlen: %uld. RV = %u", hSession, hPrivateKey, ulSignatureLen, dataLen, rv); } // if C_SignInit else ddocDebug(1, "SignData", "Error initing sign session. RV = %ld", rv); ddocDebug(3, "SignData", "RV = %ld", rv); return rv; } //============================================================ // Locates a certificate on the token on basis of its CKA_LABEL attribute. // hSession - card session handle // label - key label // return objects handle or -1 for failure //============================================================ CK_OBJECT_HANDLE LocateCertificate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR certData, CK_ULONG_PTR certLen, char idData[20][20], CK_ULONG idLen[20], int* pSelKey) { CK_OBJECT_HANDLE Objects[10]; CK_ULONG ulObjectCount = sizeof(Objects)/sizeof(CK_OBJECT_HANDLE), i, j; CK_BYTE buf1[20]; CK_OBJECT_HANDLE hCert = CK_INVALID_HANDLE; CK_RV rv; // Set up a template to search for Certificate token objects // in the given session and thus slot CK_OBJECT_CLASS ObjClass = CKO_CERTIFICATE; CK_ATTRIBUTE Template1[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) }, { CKA_ID, (void*)0, 0 } }; CK_ATTRIBUTE Template3[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) }, }; CK_ATTRIBUTE Template2[] = { { CKA_VALUE, (void*)0, *certLen }, { CKA_ID, (void*)0, 0 } }; CK_ULONG ulCount = 0; if(idLen) ulCount = sizeof(Template1)/sizeof(CK_ATTRIBUTE); else ulCount = sizeof(Template3)/sizeof(CK_ATTRIBUTE); *certLen = 0; /* ** Initiate the object search C_FindObjectsInit initializes a search for token and session objects that match a template. hSession is the sessions handle; pTemplate points to a search template that specifies the attribute values to match; ulCount is the number of attributes in the search template. The matching criterion is an exact byte-for-byte match with all attributes in the template. To find all objects, set ulCount to 0. */ for(j = 0; j < 20 && !(*certLen); j++) { if(idLen && idLen[j]) { memset(buf1, 0, sizeof(buf1)); memcpy(buf1, idData[j], idLen[j]); Template1[1].pValue = buf1; Template1[1].ulValueLen = idLen[j]; } rv = (*ckFunc->C_FindObjectsInit)(hSession, (idLen ? Template1 : Template3), 1); //ulCount); if(rv==CKR_OK) { rv = (*ckFunc->C_FindObjects)(hSession,Objects,ulObjectCount, &ulObjectCount); ddocDebug(3, "LocateCertificate", "search key-id: %s, found: %ld rv: %ld", buf1, ulObjectCount, rv); if(rv==CKR_OK) { // pick the first cert that is valid // list and ignore any other for(i = 0; i < ulObjectCount; i++) { hCert = Objects[i]; memset(certData, 0, *certLen); ulCount = sizeof(Template2) / sizeof(CK_ATTRIBUTE); // get cert length *certLen = 0; Template2[1].pValue = buf1; Template2[1].ulValueLen = sizeof(buf1); rv = (*ckFunc->C_GetAttributeValue)(hSession, hCert, Template2, ulCount); ddocDebug(3, "LocateCertificate", "cert-id: %s", buf1); if(rv == CKR_OK && (!idLen || (idLen && !memcmp(idData[j], buf1, idLen[1])))) { *certLen = Template2[0].ulValueLen; // now get cert data Template2[0].pValue = certData; rv = (*ckFunc->C_GetAttributeValue)(hSession, hCert, Template2, ulCount); ddocDebug(3, "LocateCertificate", "cert-len: %ld", *certLen); if(*certLen > 0 && pSelKey) { *pSelKey = j; break; // found it } } // if rv == CKR_OK } // for i < ulObjectCount } // if rv } // if rv rv = (*ckFunc->C_FindObjectsFinal)(hSession); } // for j //if(hCert == CK_INVALID_HANDLE) // *certLen = 0; return hCert; } //============================================================ // Locates a private key on the token on basis of its CKA_LABEL attribute. // hSession - card session handle // idData - address of an array of label buffers // idlen - array of label lengths // return objects handle or -1 for failure //============================================================ CK_RV LocatePrivateKey(CK_SESSION_HANDLE hSession, char idData[20][20], CK_ULONG idLen[20], CK_OBJECT_HANDLE_PTR hKeys) { CK_OBJECT_HANDLE Objects[10]; CK_RV rv; CK_ULONG ulObjectCount = sizeof(Objects)/sizeof(CK_OBJECT_HANDLE), i; // Set up a template to search for all Private Key tokens // Given the session context, that is associated with // one slot we will find only one object CK_OBJECT_CLASS ObjClass = CKO_PRIVATE_KEY; char buf1[20]; CK_ATTRIBUTE Template1[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) } }; CK_ATTRIBUTE Template2[] = { { CKA_ID, (void*)0, idLen[0] } }; CK_ULONG ulCount = sizeof(Template1) / sizeof(CK_ATTRIBUTE); /* ** Initiate the object search C_FindObjectsInit initializes a search for token and session objects that match a template. hSession is the sessions handle; pTemplate points to a search template that specifies the attribute values to match; ulCount is the number of attributes in the search template. The matching criterion is an exact byte-for-byte match with all attributes in the template. To find all objects, set ulCount to 0. */ ddocDebug(3, "LocatePrivateKey", "LocatePrivateKey"); rv = (*ckFunc->C_FindObjectsInit)(hSession,Template1,ulCount); if(rv==CKR_OK) { // Get list of object handles rv = (*ckFunc->C_FindObjects)(hSession,Objects,ulObjectCount, &ulObjectCount); ddocDebug(3, "LocatePrivateKey", "Find: %d count: %ld", rv, ulObjectCount); if(rv==CKR_OK) { // get labels of all possible private keys for(i = 0; i < ulObjectCount; i++) { hKeys[i] = Objects[i]; ulCount = sizeof(Template2) / sizeof(CK_ATTRIBUTE); // get key id length rv = (*ckFunc->C_GetAttributeValue)(hSession, hKeys[i], Template2, ulCount); if(rv == CKR_OK) { idLen[i] = Template2[0].ulValueLen; // now get key id data Template2[0].pValue = buf1; memset(buf1, 0, sizeof(buf1)); rv = (*ckFunc->C_GetAttributeValue)(hSession, hKeys[i], Template2, ulCount); ddocDebug(3, "LocatePrivateKey", "key: %d id %s len: %ld", i, buf1, idLen[i]); memcpy(idData[i], buf1, idLen[i]); } } // for i < ulObjectsCount } } // Remember to call C_FindObjectsFinal to terminate the search rv = (*ckFunc->C_FindObjectsFinal)(hSession); return rv; } //============================================================ // Locates a private key on the token on basis of its CKA_ID attribute. // hSession - card session handle // idData - id value // idLen - length of id value // hKey - address of key handle to be returned // return objects handle or -1 for failure //============================================================ CK_RV LocatePrivateKeyWithId(CK_SESSION_HANDLE hSession, CK_BYTE_PTR idData, CK_ULONG idLen, CK_OBJECT_HANDLE_PTR hKey) { CK_OBJECT_HANDLE Objects[10]; CK_RV rv; CK_ULONG ulObjectCount = sizeof(Objects)/sizeof(CK_OBJECT_HANDLE), i; CK_OBJECT_CLASS ObjClass = CKO_PRIVATE_KEY; CK_ATTRIBUTE Template1[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) }, { CKA_ID, (void*)idData, idLen } }; CK_ULONG ulCount = sizeof(Template1) / sizeof(CK_ATTRIBUTE); char buf2[40]; int l2; l2 = sizeof(buf2); bin2hex((const byte*)idData, idLen, (char*)buf2, &l2); ddocDebug(3, "LocatePrivateKeyWithId", "LocatePrivateKey with id: %s", buf2); //Template1[1].pValue = idData; rv = (*ckFunc->C_FindObjectsInit)(hSession, Template1, ulCount); if(rv==CKR_OK) { // Get list of object handles rv = (*ckFunc->C_FindObjects)(hSession,Objects,ulObjectCount, &ulObjectCount); ddocDebug(3, "LocatePrivateKeyWithId", "Find: %d count: %ld", rv, ulObjectCount); if(rv==CKR_OK) { // get labels of all possible private keys for(i = 0; i < ulObjectCount; i++) { ddocDebug(3, "LocatePrivateKeyWithId", "Key handle: %d", Objects[i]); *hKey = Objects[i]; } // for i < ulObjectsCount } } // Remember to call C_FindObjectsFinal to terminate the search rv = (*ckFunc->C_FindObjectsFinal)(hSession); return rv; } int ddocLocateSlotWithSignatureCert(LIBHANDLE pLibrary, CK_SLOT_ID* slotids, CK_SLOT_ID* pSlotId, X509** ppCert, char idData[20], int* pIdLen, int nSlot, int* pIdx) { int err = ERR_PRIVKEY_READ, i, j, nMatch, l3; CK_RV rv; CK_SESSION_HANDLE hSession = 0; CK_OBJECT_HANDLE objects[10]; CK_BYTE buf2[20], buf3[40]; CK_ULONG ulObjectCount = sizeof(objects)/sizeof(CK_OBJECT_HANDLE), ulCount = 0, l1 = 0, l2 = 0; CK_OBJECT_CLASS ObjClass = CKO_CERTIFICATE; CK_ATTRIBUTE Template1[] = { { CKA_CLASS, &ObjClass, sizeof(ObjClass) } }; CK_ATTRIBUTE Template2[] = { { CKA_VALUE, (void*)0, l1 }, { CKA_ID, (void*)0, sizeof(buf2)} }; char buf1[3000], buf4[64]; X509* pCert = 0; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; RETURN_IF_NULL_PARAM(pLibrary); RETURN_IF_NULL_PARAM(pSlotId); RETURN_IF_NULL_PARAM(slotids); RETURN_IF_NULL_PARAM(idData); RETURN_IF_NULL_PARAM(ppCert); // mark as not found memset(idData, 0, *pIdLen); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Driver handle: %d err = %d", pLibrary, err); // now check every slot for(i = 0, nMatch = 0; (i < 20) && !(*ppCert); i++) { if(slotids[i] != INVALID_SLOTIID) { ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Checking slot nr: %d id: %d", i, slotids[i]); // open session to slot but no login since we just need the cert rv = (*ckFunc->C_OpenSession)(slotids[i], CKF_SERIAL_SESSION,0,0,&hSession); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Login rv: %ld session: %ld", rv, hSession); if(rv == CKR_OK) { ulCount = sizeof(Template1)/sizeof(CK_ATTRIBUTE); rv = (*ckFunc->C_FindObjectsInit)(hSession, Template1, ulCount); if(rv == CKR_OK) { rv = (*ckFunc->C_FindObjects)(hSession, objects, ulObjectCount, &ulObjectCount); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "slot id: %ld, objects: %ld", slotids[i], ulObjectCount); if(rv == CKR_OK && ulObjectCount > 0) { ulCount = sizeof(Template2) / sizeof(CK_ATTRIBUTE); for(j = 0; j < (int)ulObjectCount; j++) { l1 = sizeof(buf1); memset(buf1, 0, l1); l2 = sizeof(buf2); memset(buf2, 0, l2); Template2[0].pValue = 0; // check length first rv = (*ckFunc->C_GetAttributeValue)(hSession, objects[j], Template2, ulCount); if(rv == CKR_OK && Template2[0].ulValueLen < sizeof(buf1)) { l1 = Template2[0].ulValueLen; // now get cert data Template2[0].pValue = buf1; Template2[1].pValue = buf2; rv = (*ckFunc->C_GetAttributeValue)(hSession, objects[j], Template2, ulCount); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "slot id: %ld, object: %ld cert-len: %ld rv: %ld", slotids[i], j, l1, rv); pCert = 0; err = ddocDecodeX509Data(&pCert, (const byte*)buf1, l1); if(pCert) { // debug memset(buf4, 0, sizeof(buf4)); ReadCertSerialNumber(buf4, sizeof(buf4), pCert); ddocCertGetSubjectCN(pCert, &mbuf1); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "slot id: %ld, object: %ld cert-serial: %s CN: %s", slotids[i], j, buf4, (char*)mbuf1.pMem); if(ddocCertCheckKeyUsage(pCert, KUIDX_NON_REPUDIATION)) { if((!nSlot || nSlot == nMatch) && !(*ppCert)) { l3 = sizeof(buf3); memset(buf3, 0, l3); bin2hex((const byte*)buf2, (int)Template2[1].ulValueLen, (char*)buf3, &l3); ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Selecting slot: %d id: %d key-id %s", i, slotids[i], buf3); *pSlotId = slotids[i]; *pIdx = i; // keep this cert for signing if(*ppCert) X509_free(*ppCert); (*ppCert) = pCert; pCert = NULL; // mark as used memcpy(idData, buf2, Template2[1].ulValueLen); *pIdLen = Template2[1].ulValueLen; err = ERR_OK; // found it ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Selected key/cert: %s - %s", buf4, (char*)mbuf1.pMem); } else { // useable slot but not a match by slot id ddocDebug(3, "ddocLocateSlotWithSignatureCert", "Useable slot: %d but search: %d", nMatch, nSlot); nMatch++; } } // if non-repu cert ddocMemBuf_free(&mbuf1); } // if pCert if(pCert) X509_free(pCert); pCert = 0; } // if get-attribute ok } // for j < ulObjectCount } // if found any certs } // if find-init ok rv = (*ckFunc->C_FindObjectsFinal)(hSession); } // if login ok rv = (*ckFunc->C_CloseSession)(hSession); } // if slotid } // for i return err; } extern void dumpInFile(const char* fileName, const char* data); //============================================================ // Calculates and stores a signature for this SignatureInfo object // Uses EstEID card to sign the info // pSigInfo - signature info object // nSigType - signature type code // keyfile - RSA key file // passwd - key password // certfile - certificate file //============================================================ EXP_OPTION int calculateSignatureWithEstID(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, int slot, const char* passwd) { int err = ERR_OK, nKey; LIBHANDLE pLibrary = 0; CK_ULONG certLen, sigLen, padDigLen; CK_RV rv; CK_SLOT_ID slotids[20], slId = 0; CK_SESSION_HANDLE hSession = 0; CK_OBJECT_HANDLE hPrivateKey = 0, hKeys[20], hCert; char keyId[20][20], kId[20]; CK_ULONG keyIdLen[20]; CK_BYTE certData[2048]; CK_BYTE sigDig[100], padDig[130]; CK_BYTE signature[256]; CK_BYTE padding[] = { 48, 33, 48, 9, 6, 5, 43, 14, 3, 2, 26, 5, 0, 4, 20 }; //CK_BYTE padding256[] = { 48, 49, 48, 13, 6, 9, 96, 134, 72, 1 ,101, 3, 4, 2, 1, 5, 0, 4, 32}; //CK_BYTE padding256[] = { 48, 33, 48, 13, 6, 9, 96, 134, 72, 1 ,101, 3, 4, 2, 1, 5, 0, 4, 32}; char* buf1; int l1, l2, kILen; X509* x509 = 0; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pSigDoc); // try active driver driver first snprintf((char*)signature, sizeof(signature), "DIGIDOC_DRIVER_%d_FILE", ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1)); for(l1 = 0; l1 < 20; l1++) slotids[l1] = INVALID_SLOTIID; // initialize err = loadAndTestDriver(ConfigItem_lookup((const char*)signature), &pLibrary, (CK_SLOT_ID*)slotids, 20, (CK_ULONG)slot); ddocDebug(3, "calculateSignatureWithEstID", "Driver handle: %d err = %d slot: %d", pLibrary, err, slot); RETURN_IF_NOT(err == ERR_OK, err); // inittialize slId = INVALID_SLOTIID; // not found yet // try key-usage check if(ConfigItem_lookup_int("KEY_USAGE_CHECK", 1)) { kILen = sizeof(kId); ddocDebug(3, "calculateSignatureWithEstID", "Find slot by key-usage, slot: %d", slot); err = ddocLocateSlotWithSignatureCert(pLibrary, slotids, &slId, &x509, kId, &kILen, slot, &l1); ddocDebug(3, "calculateSignatureWithEstID", "Select by key-usage slot idx: %d = %d err: %d key-id: %s, kid-len: %d", l1, slId, err, kId, kILen); if(err != ERR_OK || l1 < 0 || l1 >= 20) { SET_LAST_ERROR(ERR_SIGNERS_CERT_NON_REPU); return ERR_SIGNERS_CERT_NON_REPU; } } else { ddocDebug(3, "calculateSignatureWithEstID", "Find slot by slot idx: %d", slot); for(l1 = 0; (l1 < 20) && (slId == INVALID_SLOTIID); l1++) { if(slotids[l1] != INVALID_SLOTIID) ddocDebug(3, "calculateSignatureWithEstID", "Slot idx: %d = %d", l1, slotids[l1]); if(slotids[l1] != INVALID_SLOTIID && l1 == slot) { slId = slotids[l1]; ddocDebug(3, "calculateSignatureWithEstID", "Select idx: %d slot: %d", l1, slId); } // if slotid } // for } // use default if not found by key-id or direct if(slId == INVALID_SLOTIID) { l1 = ConfigItem_lookup_int("DIGIDOC_SIGNATURE_SLOT", 0); if(slotids[l1] != INVALID_SLOTIID) { ddocDebug(3, "calculateSignatureWithEstID", "Select default slot idx: %d = %d", l1, slotids[l1]); slId = slotids[l1]; } } // open session if(slId != INVALID_SLOTIID) { hSession = OpenSession(slId, passwd); ddocDebug(3, "calculateSignatureWithEstID", "Open sess for slot: %d sess = %d", slId, hSession); if (hSession == CK_INVALID_HANDLE) { err = ERR_PKCS_LOGIN; SET_LAST_ERROR(err); return err; } ddocDebug(3, "calculateSignatureWithEstID", "OpenSession ok, hSession1 = %d", (int)hSession); if(!x509) { ddocDebug(3, "calculateSignatureWithEstID", "Cert ok"); // get private key for(l1 = 0; l1 < 20; l1++) { memset(keyId[l1], 0, 20); keyIdLen[l1] = 0; } err = LocatePrivateKey(hSession, keyId, keyIdLen, hKeys); //ddocDebug(3, "calculateSignatureWithEstID", "Priv key: %s", keyId); // // get cert memset(certData, 0, sizeof(certData)); certLen = sizeof(certData); hCert = LocateCertificate(hSession, certData, &certLen, keyId, keyIdLen, &nKey); hPrivateKey = hKeys[nKey]; ddocDebug(3, "calculateSignatureWithEstID", "selected priv-key: %ld pos %d id: %s", hPrivateKey, nKey, keyId[nKey]); ddocDebug(3, "calculateSignatureWithEstID", "Cert-len: %ld", certLen); //printf("Cert: %s", certData); if (hCert == (CK_OBJECT_HANDLE)-1) { err = ERR_PKCS_CERT_LOC; SET_LAST_ERROR(err); return err; } // set cert data err = ddocDecodeX509Data(&x509, certData, certLen); } else { // cert already found //kILen = sizeof(kId); ddocDebug(3, "calculateSignatureWithEstID", "Locate priv key2 id: %s, len: %d, hkey: %d", kId, kILen, hPrivateKey); err = LocatePrivateKeyWithId(hSession, (CK_BYTE_PTR)kId, kILen, &hPrivateKey); ddocDebug(3, "calculateSignatureWithEstID", "Priv key-id: %s len: %d hkey: %d err: %d", kId, kILen, hPrivateKey, err); } ddocDebug(3, "calculateSignatureWithEstID", "Priv key: %d err: %d", hPrivateKey, err); if (hPrivateKey == CK_INVALID_HANDLE) { err = ERR_PKCS_PK; SET_LAST_ERROR(err); return err; } if (!x509) { err = ERR_PKCS_CERT_DECODE; } // save cert in file if(ConfigItem_lookup_int("DEBUG_LEVEL", 1) > 3) saveCert(x509, "signer.pem", FILE_FORMAT_PEM); setSignatureCert(pSigInfo, x509); // FIXME createTimestamp(pSigDoc, (char*)sigDig, sizeof(sigDig)); setString((char**)&(pSigInfo->szTimeStamp), (const char*)sigDig, -1); // Signed properties digest buf1 = createXMLSignedProperties(pSigDoc, pSigInfo, 0); //dumpInFile("sigprop-sign1.txt", buf1); if (!buf1) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err; } mbuf1.pMem = canonicalizeXML((char*)buf1, strlen(buf1)); mbuf1.nLen = strlen((const char*)mbuf1.pMem); ddocDebugWriteFile(4, "sigprop-signed.txt", &mbuf1); l2 = sizeof(sigDig); err = calculateDigest((const byte*)mbuf1.pMem, mbuf1.nLen, DIGEST_SHA1, sigDig, &l2); free(buf1); ddocMemBuf_free(&mbuf1); if (err != ERR_OK) { SET_LAST_ERROR(err); return err; } ddocSigInfo_SetSigPropDigest(pSigInfo, (const char*)sigDig, l2); ddocSigInfo_SetSigPropRealDigest(pSigInfo, (const char*)sigDig, l2); // create signed info buf1 = createXMLSignedInfo(pSigDoc, pSigInfo); if (!buf1) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err ; } // get digest l2 = sizeof(sigDig); err = calculateDigest((const byte*)buf1, strlen(buf1), DIGEST_SHA1, sigDig, &l2); free(buf1); if (err != ERR_OK) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err; } ddocSigInfo_SetSigInfoRealDigest(pSigInfo, (const char*)sigDig, l2); // sign data sigLen = sizeof(signature); memset(signature, 0, sizeof(signature)); // pad PKCS#1 ver 1 padDigLen = 35; memset(padDig, 0, sizeof(padDig)); memcpy(padDig, padding, 15); memcpy(padDig + 15, sigDig, l2); //rv = RSA_padding_add_PKCS1_type_1(padDig, padDigLen, sigDig, l2); //rv = RSA_padding_check_PKCS1_type_1(sigDig, l2, padDig, padDigLen, padDigLen+1); // checkErrors(); // sign data rv = SignData(hSession, hPrivateKey, signature, &sigLen, padDig, padDigLen); if (rv != CKR_OK) { err = ERR_PKCS_SIGN_DATA; SET_LAST_ERROR(err); return err; } // set signature value ddocSigInfo_SetSignatureValue(pSigInfo, (const char*)signature, (int)sigLen); ddocDebug(3, "calculateSignatureWithEstID", "Sig-len: %ld", sigLen); } // if slotid found if(hSession) closePKCS11Library(pLibrary, hSession); return err; } //============================================================ // Loads the PKCS#11 driver and // tests if the driver loaded correctly // Returns 0 for ok otherwise error code //============================================================ EXP_OPTION CK_RV getDriverInfo(CK_INFO_PTR pInfo) { return (*ckFunc->C_GetInfo)(pInfo); } //============================================================ // Decrypts RSA encrypted data with the private key // slot - number of the slot for decryption key. On ID card allways 0 // pin - corresponding pin for the key. On ID card - PIN1 // encData - encrypted data // encLen - length of encrypted data // decData - buffer for decrypted data // encLen - length of buffer. Will be modified by amount of decrypted data // return error code or ERR_OK //============================================================ EXP_OPTION int decryptWithEstID(int slot, const char* pin, const char* encData, int encLen, char* decData, int *decLen) { int err = ERR_OK, l1, l2; LIBHANDLE pLibrary = 0; CK_ULONG keyIdLen[20]; CK_RV rv; CK_SLOT_ID slotids[20], slId; CK_SESSION_HANDLE hSession = 0; CK_OBJECT_HANDLE hPrivateKey, hKeys[20]; char keyId[20][20]; char driver[100]; CK_MECHANISM Mechanism = { CKM_RSA_PKCS, 0, 0 }; CK_ULONG outlen; ddocDebug(3, "decryptWithEstID", "slot: %d enc-data: %d bytes buffer size: %d", slot, encLen, *decLen); snprintf(driver, sizeof(driver), "DIGIDOC_DRIVER_%d_FILE", ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1)); ddocDebug(3, "decryptWithEstID", "Driver nr: %d - %s", ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1), ConfigItem_lookup(driver)); err = loadAndTestDriver(ConfigItem_lookup(driver), &pLibrary, (CK_SLOT_ID*)slotids, 20, (CK_ULONG)slot); if(err) return err; // find the right slotid for(l1 = l2 = 0; l1 < 20; l1++) { if(slotids[l1] != INVALID_SLOTIID) { if(l2 == slot) slId = slotids[l1]; l2++; } } // open session //ddocDebug(3, "decryptWithEstID", "OpenSession id = %d, pin: %s", (int)slId, pin); hSession = OpenSession(slId, pin); if (hSession == CK_INVALID_HANDLE) { SET_LAST_ERROR(ERR_PKCS_LOGIN); return ERR_PKCS_LOGIN; } ddocDebug(3, "decryptWithEstID", "OpenSession ok, hSession = %d", (int)hSession); // get private key for(l1 = 0; l1 < 20; l1++) { memset(keyId[l1], 0, 20); keyIdLen[l1] = 0; } err = LocatePrivateKey(hSession, keyId, keyIdLen, hKeys); hPrivateKey = hKeys[0]; //??? //ddocDebug(3, "decryptWithEstID", "Priv key: %s", keyId); //if (hPrivateKey == CK_INVALID_HANDLE) { SET_LAST_ERROR(ERR_PKCS_PK); return ERR_PKCS_PK; } // init decrypt rv = (*ckFunc->C_DecryptInit)(hSession, &Mechanism, hPrivateKey); ddocDebug(3, "decryptWithEstID", "DecryptInit: %d", (int)rv); if(rv != CKR_OK) SET_LAST_ERROR_RETURN(ERR_DENC_DECRYPT, ERR_DENC_DECRYPT) // decrypt data outlen = *decLen; rv = (*ckFunc->C_Decrypt)(hSession, (CK_BYTE_PTR)encData, (CK_ULONG)encLen, (CK_BYTE_PTR)decData, (CK_ULONG_PTR)&outlen); *decLen = outlen; ddocDebug(3, "decryptWithEstID", "RV: %d, dec-len: %d", (int)rv, *decLen); if(hSession) closePKCS11Library(pLibrary, hSession); if(rv != CKR_OK) SET_LAST_ERROR_RETURN(ERR_DENC_DECRYPT, ERR_DENC_DECRYPT) return err; } //============================================================ // Locates and reads users certificate from smartcard // slot - number of the slot for decryption key. On ID card allways 0 // ppCert - address for newly allocated certificate pointer // return error code or ERR_OK //============================================================ EXP_OPTION int findUsersCertificate(int slot, X509** ppCert) { int err = ERR_OK, l1, l2; LIBHANDLE pLibrary = 0; CK_RV rv = 0; CK_SLOT_ID slotids[20], slId; CK_OBJECT_HANDLE hCert; CK_SESSION_HANDLE hSession = 0; CK_ULONG certLen; CK_BYTE certData[2048]; char driver[100]; *ppCert = 0; snprintf(driver, sizeof(driver), "DIGIDOC_DRIVER_%d_FILE", ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1)); ddocDebug(3, "findUsersCertificate", "Slot: %d Driver nr: %d - %s", slot, ConfigItem_lookup_int("DIGIDOC_DEFAULT_DRIVER", 1), ConfigItem_lookup(driver)); err = loadAndTestDriver(ConfigItem_lookup(driver), &pLibrary, (CK_SLOT_ID*)slotids, 20, (CK_ULONG)slot); if(err) return err; //debug for(l1 = l2 = 0; l1 < 20; l1++) { if(slotids[l1] != INVALID_SLOTIID) { ddocDebug(3, "findUsersCertificate", "Slot1: %d, id %d", l1, slotids[l1]); } } // find the right slotid for(l1 = l2 = 0; l1 < 20; l1++) { if(slotids[l1] != INVALID_SLOTIID) { ddocDebug(3, "findUsersCertificate", "Slot2: %d, id %d", l1, slotids[l1]); if(l2 == slot) slId = slotids[l1]; l2++; } } // open session ddocDebug(3, "findUsersCertificate", "OpenSession slotid %d", slId); hSession = OpenSession(slId, NULL); if (hSession == CK_INVALID_HANDLE) { SET_LAST_ERROR(ERR_PKCS_LOGIN); return ERR_PKCS_LOGIN; } ddocDebug(3, "findUsersCertificate", "OpenSession ok, hSession = %d", (int)hSession); // get cert memset(certData, 0, sizeof(certData)); certLen = sizeof(certData); hCert = LocateCertificate(hSession, certData, &certLen, 0, 0, 0); ddocDebug(3, "findUsersCertificate", "hCert = %d, len: %d", (int)hCert, certLen); if (hCert == (CK_OBJECT_HANDLE)-1) { err = ERR_PKCS_CERT_LOC; SET_LAST_ERROR(err); } // set cert data if(certLen) err = ddocDecodeX509Data(ppCert, certData, certLen); ddocDebug(3, "findUsersCertificate", "RV: %d, cert: %s", (int)rv, (*ppCert ? "OK" : "NULL")); if(hSession) closePKCS11Library(pLibrary, hSession); return err; } libdigidoc-3.10.5/libdigidoc/DigiDocParser.h0000664000372000037200000001063713560273131020224 0ustar travistravis#ifndef __DIGIDOC_PARSER_H__ #define __DIGIDOC_PARSER_H__ //================================================== // FILE: DigiDocParser.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for xml parsing // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 10.07.2004 Veiko Sinivee // Creation // 22.08.2004 Veiko Sinivee // Renamed ddocExtractDataFile to ddocXRdrExtractDataFile // Renamed ddocGetDataFile to ddocXRdrGetDataFile // Renamed ddocCopyDataFile to ddocXRdrCopyDataFile // introduced ddocXRdrReadSignedDocFromFile() //================================================== #include #include #include #ifdef __cplusplus extern "C" { #endif //-------------------------------------------------- // Reads in signed XML document and extracts the desired data file // pSigDoc - signed document object if cached // szFileName - name of digidoc file // szDataFileName - name of new data file // szDocId - id if DataFile // szCharset - output charset // szFileNameCharset - digidoc filename charset //-------------------------------------------------- EXP_OPTION int ddocXRdrExtractDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDataFileName, const char* szDocId, const char* szCharset); //-------------------------------------------------- // Reads in signed XML document and returns the // desired DataFile-s content in a memory buffer. // caller is responsible for freeing the memory. // pSigDoc - signed document object if cached // szFileName - name of digidoc file // szDocId - id if DataFile // pBuf - address of buffer pointer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocXRdrGetDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDocId, DigiDocMemBuf* pBuf); //-------------------------------------------------- // Reads in signed XML document and extracts the desired data file // This function keeps also xml tags. It is used // internally to copy data content from an old digidoc file // to a temp file while saving a the file // pSigDoc - signed document object if cached // szFileName - name of digidoc file // szDataFileName - name of new data file // szDocId - id if DataFile // szCharset - output charset //-------------------------------------------------- int ddocXRdrCopyDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDataFileName, const char* szDocId, const char* szCharset); //-------------------------------------------------- // Reads in signed XML document // szFileName - name of digidoc file // ppSigDoc - address of new signed doc pointer // lMaxDFLen - maximum size of a cached DataFile //-------------------------------------------------- EXP_OPTION int ddocXRdrReadSignedDocFromFile(const char* szFileName, SignedDoc** pSigDoc, long lMaxDFLen); //-------------------------------------------------- // Reads in signed XML document from memory buffer // szXml - memory buffer that contains digidoc data // xmlLen - length of the input data // szFileNameCharset - digidoc filename charset // ppSigDoc - address of new signed doc pointer // lMaxDFLen - maximum size of a cached DataFile //-------------------------------------------------- EXP_OPTION int ddocXRdrReadSignedDocFromMemory(const char* szXml, int xmlLen, SignedDoc** pSigDoc, long lMaxDFLen); #ifdef __cplusplus } #endif #endif // __DIGIDOC_PARSER_H__ libdigidoc-3.10.5/libdigidoc/cdigidoc.1.cmake0000664000372000037200000004000513560273131020272 0ustar travistravis.TH CDIGIDOC 1 "${BUILD_DATE}" "${VERSION}" "cdigidoc man page" .SH NAME cdigidoc \- read, digitally sign, verify files in XAdES format and encrypt, decrypt files in XMLENC format .SH SYNOPSIS .B cdigidoc [ .I -in .B ] [ .I -out .B ] [ .I -config .B ] .SH DESCRIPTION .B cdigidoc is an utility which provides a command line interface to the CDigiDoc library, which is a library in C programming language offering the the functionality to create files in supported DigiDoc formats, sigitally sign the DigiDoc files using smart cards or other supported cryptographic tokens, add time marks and validity confirmations to digital signatures using OCSP protocol, verify the digital signatures, and digitally encrypt and decrypt the DigiDoc files. It is also possible to use cdigidoc utility as a CGI program in web applications created in environments that cannot easily use the JDigiDoc library or call the DigiDocService webservice for digital signature functionality. .PP For full documentation, see .nf https://svn.eesti.ee/projektid/idkaart_public/branches/3.6/libdigidoc/doc/SK-CDD-PRG-GUIDE.pdf .PP XAdES format .nf http://www.w3.org/TR/XAdES .PP XML-ENC format http://www.w3.org/TR/xmlenc-core .SH OPTIONS .IP "-?, -help" Displays help about command syntax. .IP "-in " Specifies the input file name. It is recommended to pass the full path to the file in this parameter. .IP "-out " Stores the newly created or modified document in a file. .IP "-config " Specifies the CDigiDoc configuration file name. If left unspecified, then the configuration file is looked up from default locations. .IP "-check-cert " Checks the certificate validity status. Used for checking the chosen certificate’s validity; returns an OCSP response from the certificate’s CA’s OCSP responder. Note that the command is currently not being tested. If the certificate is valid, then the return code’s (RC) value is 0. .IP "-new [format] [version]" Creates a new digidoc container with the specified format and version. The current digidoc format in CDigiDoc library is DIGIDOC-XML, default version is 1.3 (newest). By using the optional parameter - version - with this command, you can specify an alternative version to be created. Note: the older SK-XML format is supported only for backward compatibility. .IP "-add [] []" Adds a new data file to a digidoc document. If digidoc doesn't exist then creates one in the default format. .RS .TP Input file (required) Specifies the name of the data file (it is recommended to include full path in this parameter; the path is removed when writing to DigiDoc container file). .TP Mime type (required) Represents the MIME type of the original file like "text/plain" or "application/msword". .TP Content type Reflects how the original files are embedded in the container EMBEDDED_BASE64 (used by default). In previous versions cdigidoc allowed content type EMBEDDED to sign pure xml or text. .TP Charset UTF-8 encoding is supported and used by default. .RE .IP "-sign [[[manifest] [[city] [state] [zip] [country]] [slot(0)] [ocsp(1)] [token-type(PKCS11)] [pkcs12-file-name]]" Adds a digital signature to the digidoc document. You can use it with following parameters: .RS .TP pin code In case of Estonian ID cards, pin code2 is used for digital signing. If signing with a software token (PKCS#12 file), then the password of PKCS#12 file should be entered here. .TP manifest Role or resolution of the signer .TP city City where the signature is created .TP state State or province where the signature is created .TP zip Postal code of the place where the signature is created .TP country Country of origin. ISO 3166-type 2-character country codes are used (e.g. EE) .TP slot Identifier of the signer’s private key’s slot on a smartcard. When operating for example with a single Estonian ID card, its signature key can be found in slot 1 - which is used by default. The library makes some assumptions about PKCS#11 drivers and card layouts: - you have signature and/or authentication keys on the card - both key and certificate are in one slot - if you have many keys like 1 signature and 1 authentication key then they are in different slots - you can sign with signature key that has a corresponding certificate with "NonRepudiation" bit set. You may need to specify a different slot to be used when for example operating with multiple smart cards on the same system. If the slot needs to be specified during signing, then the 5 previous optional parameters (manifest, city, state, zip, country) should be filled first (either with the appropriate data or as "" for no value). .TP ocsp Specifies whether an OCSP confirmation is added to the signature that is being created. Possible values are 0 - confirmation is not added; 1 - confirmation is added. By default, the value is set to 1. Parameter value 0 can be used when creating a technical signature. Technical signature is a signature with no OCSP confirmation and no timestamp value. .TP token type Speciafies type of signature token to be use. - PKCS11 default value. Signs with a smart-card or software pkcs11 token - CNG on windows platforms uses CSP/CNG for signing - PKCS12 signs with a PKCS#12 key container that must be entered in the next parameter . TP pkcs12 file name Name of the PKCS#12 key container file to be used for signing. .RE .IP "-mid-sign [[(EE)] [(EST)] [(Testing)] [] [ ]]" Invokes mobile signing of a ddoc file using Mobile-ID and DigiDocService. Mobile-ID is a service based on Wireless PKI providing for mobile authentication and digital signing, currently supported by all Estonian and some Lithuanian mobile operators. The Mobile-ID user gets a special SIM card with private keys on it. Hash to be signed is sent over the GSM network to the phone and the user shall enter PIN code to sign. The signed result is sent back over the air. DigiDocService is a SOAP-based web service, access to the service is IP-based and requires a written contract with provider of DigiDocService. You can use Mobile-ID signing with the following parameters: .RS .TP phone-no Phone number of the signer with the country code in format +xxxxxxxxx (for example +3706234566) .TP per-code Identification number of the signer (personal national ID number). .TP country Country of origin. ISO 3166-type 2-character country codes are used (e.g. default is EE) .TP lang Language for user dialog in mobile phone. 3-character capitalized acronyms are used (e.g. default is EST) .TP service Name of the service – previously agreed with Application Provider and DigiDocService operator. Maximum length – 20 chars. (e.g. default is Testing) .TP manifest Role or resolution of the signer .TP city City where the signature is created .TP state State or province where the signature is created .TP zip Postal code of the place where the signature is created .RE .IP "-list" Displays the data file and signature info of a DigiDoc document just read in; verifies all signatures. .RS .HP Returns Digidoc container data, in format: SignedDoc | | .HP List of all data files, in format: DataFile | | | | | .HP List of all signatures (if existing), in format: Signature | | | | .HP Signer’s certificate information. .HP OCSP responder certificate information .RE .IP "-verify" Returns signature verification results (if signatures exist): .RS .HP Signature | | | | .HP Returns signer’s certificate and OCSP Responder certificate information. .RE .IP "-extract " Extracts the selected data file from the DigiDoc container and stores it in a file. Data file id represents the ID for data file to be extracted from inside the DigiDoc container (e.g. D0, D1…). Output file represents the name of the output file. .IP "-denc-list " Displays the encrypted data and recipient’s info of an encrypted document just read in. .IP "-encrecv [recipient] [KeyName] [CarriedKeyName]" Adds a new recipient certificate and other metadata to an encrypted document. Certificate file (required) specifies the file from which the public key component is fetched for encrypting the data. The decryption can be performed only by using private key corresponding to that certificate. The input certificate files for encryption must come from the file system (PEM encodings are supported). Possible sources where the certificate files can be obtained from include: Windows Certificate Store ("Other Persons"), LDAP directories, ID-card in smart-card reader. For example the certificate files for Estonian ID card owners can be retrieved from a LDAP directory at ldap://ldap.sk.ee. The query can be made in following format through the web browser (IE): ldap://ldap.sk.ee:389/c=EE??sub?(serialNumber= xxxxxxxxxxx) where serial Number is the recipient’s personal identification number, e,g.38307240240). Other parameters include: .RS .TP recipient If left unspecified, then the program assigns the CN value of the certificate passwed as first parameter. This is later used as a command line option to identify the recipient whose key and smart card is used to decrypt the data. Note: Although this parameter is optional, it is recommended to pass on the entire CN value from the recipient’s certificate as the recipient identifier here, especially when dealing with multiple recipients. .TP KeyName Sub-element can be added to better identify the key object. Optional, but can be used to search for the right recipient’s key or display its data in an application. .TP CarriedKeyName Sub-element can be added to better identify the key object. Optional, but can be used to search for the right recipient’s key or display its data in an application. .RE .IP "-encrypt-sk " Encrypts the data from the given input file and writes the completed encrypted document in a file. Recommended for providing cross-usability with other DigiDoc software components. This command places the data file to be encrypted in a new DigiDoc container. Therefore handling such encrypted documents later with other DigiDoc applications is fully supported (e.g. DigiDoc3 client). Input file (required) specifies the original data file to be encrypted. Note: There are also alternative encryption commands which are however not recommended for providing cross-usability with other DigiDoc software components: .RS .TP .I "-encrypt " Encrypts the data from the given input file and writes the completed encrypted document in a file. Should be used only for encrypting small documents, already in DIGIDOC-XML format. Input file (required) specifies the original data file to be encrypted. .TP .I "-encrypt-file " Encrypts the input file and writes to output file. Should be used only for encrypting large documents, already in DIGIDOC-XML format. Note that the command in not currently tested. Input file (required) specifies the original data file to be encrypted. Output file (required) specifies the name of the output file which will be created in the current encrypted document format (ENCDOC-XML ver 1.0), with file extension .cdoc. .RE .IP "-decrypt-sk [pkcs12-file] [slot(0)]" Decrypts and possibly decompresses the encrypted file just read in and writes to output file. Expects the encrypted file to be inside a DigiDoc container. Input file (required) specifies the input file’s name. Pin (required) represents the recipient’s pin1 (in context of Estonian ID cards). pkcs12-file (optional) specifies the PKCS#12 file if decrypting is done with a software token. slot default is slot 0 containing Estonian ID cards authentication keypair. This parameter can be used to decrypt with a key from the second id card attached to the computer etc. Note: There are also alternative commands for decryption, depending on the encrypted file’s format, size and the certificate type used for decrypting it. .RS .TP .I "-decrypt [pkcs12-file] [slot(0)]" Offers same functionality as -decrypt-sk, should be used for decrypting small files (which do not need to be inside a DigiDoc container). Input file (required) specifies the input file’s name. Pin (required) represents the recipient’s pin1 (in contexts of Estonian ID cards). pkcs12-file (optional) specifies the PKCS#12 file if decrypting is done with a software token. slot default is slot 0 containing Estonian ID cards authentication keypair. This parameter can be used to decrypt with a key from the second id card attached to the computer etc. .TP .I "-decrypt-file [pkcs12-file]" Offers same functionality as -decrypt for decrypting documents, should be used for decrypting large files (which do not need to be inside a DigiDoc container). Expects the encrypted data not to be compressed. Note that the command is not currently tested. Input file (required) specifies the encrypted file to be decrypted. Output file (required) specifies the output file name. Pin (required) represents the recipient’s pin1 (in contexts of Estonian ID cards). pkcs12-file (optional) specifies the PKCS#12 file if decrypting is done with a software token. .RE .IP "-calc-sign [] [ ]" Offers an alternative to \-sign command to be used in CGI pograms. Adds signers certificate in pem format and optionally manifest and signers address and calculates the final hash value to be signed. This value is hex-encoded and can now be sent to users computer to be signed using a web plugin. This command creates an incomplete signature that lacks the actual RSA signature value. It must be stored in a temporary file and later completed using the \-add-sign-value command. -IP "-add-sign-value " Offers an alternative to \-sign command to be used in CGI pograms. Adds an RSA signature hex-encoded value to an incomplete signature created using the \-calc-sign command. This signature is still lacking the ocsp timemark, that can now be obtained using the \-get-confirmation command producing a complete XAdES signature. .IP "-get-confirmation " Adds an OCSP confirmation to a DigiDoc file’s signature. .SH EXAMPLES .IP "cdigidoc -new DIGIDOC-XML 1.3 -add -sign -out Creates a new signed document in DIGIDOC-XML 1.3 format, adds one input file, signs with smartcard using the default signature slot and writes to a signed document file. .IP "cdigidoc -in -list" Reads in a signed document, verifies signatures and prints the results to console. .IP "cdigidoc -in -extract D0 " Reads in a signed document, finds the first signed document and writes it to output file. .IP "cdigidoc -encrecv -encrecv -encrypt-sk -out " Creates a new encypted file by encrypting input file that is encrypted using AES-128 and encrypts the generated randome transport key using RSA for two possible recipients identified by their certificates. Transport key is encrypted using RSA1.5. .IP "cdigidoc -decrypt-sk -out " Reads in encrypted file and decrypts it with smartcards first keypair (Estonian ID cards authentication key) and writes decrypted data to given putput file. .IP "cdigidoc -decrypt-sk -out " Reads in encrypted file and decrypts it with a PKCS#12 key-container and writes decrypted data to given putput file. .SH AUTHORS .B AS Sertifitseerimiskeskus (Certification Centre Ltd.) .SH "SEE ALSO" digidoc-tool(1), qesteidutil(1), qdigidocclient(1), qdigidoccrypto(1) libdigidoc-3.10.5/libdigidoc/DigiDocService.h0000664000372000037200000001037213560273131020364 0ustar travistravis#ifndef __DIGI_DOC_SRV_H__ #define __DIGI_DOC_SRV_H__ //================================================== // FILE: DigiDocService.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for DigiDocService access // AUTHOR: Veiko Sinivee, Sunset Software O //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //================================================== #include #include #include #ifdef __cplusplus extern "C" { #endif #define STATUS_UNKNOWN 0 #define STATUS_OUTSTANDING_TRANSACTION 1 #define STATUS_SIGNATURE 2 #define STATUS_ERROR 3 //------------------------------------------ // Gets DigiDocService session status and returns status code // If session is ready then signature will be returned // pSigDoc - signed document object to be modified // lSesscode - session code // url - dds service url // proxyHost - proxy hostname // proxyPort -proxy port // pStatus - buffer for returning status // pMBufSig - buffer for returning signature // returns DigiDocService session status code // deprecated use ddsGetStatus(pSigDoc, lSesscode, url, proxyHost, proxyPort, pStatus, szFileName) //------------------------------------------ DIGIDOC_DEPRECATED EXP_OPTION int ddsGetStatus(SignedDoc* pSigDoc, long lSesscode, char* url, char* proxyHost, char* proxyPort, int* pStatus); //------------------------------------------ // Gets DigiDocService session status and returns status code // If session is ready then signature will be returned // pSigDoc - signed document object to be modified // lSesscode - session code // url - dds service url // proxyHost - proxy hostname // proxyPort -proxy port // pStatus - buffer for returning status // szFileName - ddoc filename to add signature from dds (optional) // pMBufSig - buffer for returning signature // returns DigiDocService session status code //------------------------------------------ EXP_OPTION int ddsGetStatusWithFile(SignedDoc* pSigDoc, long lSesscode, char* url, char* proxyHost, char* proxyPort, int* pStatus, const char* szFileName); //-------------------------------------------------- // Signs the document and gets return status back // pSigDoc - signed document object // szIdCode - personal id code // szPhoneNo - users phone number // szLang - language code // manifest - manifest or role // city - signers address , city // state - signers address , state or province // zip - signers address , postal code // country - signers address , country name // pSesscode - pointer to long int buffer for returning session code // szChallenge - buffer for returning challenge code (char 4) // nChalLen - length of challenge buffer // return error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddsSign(SignedDoc* pSigDoc, const char* szIdCode, const char* szPhoneNo, const char* szLang, const char* szServiceName, const char* manifest, const char* city, const char* state, const char* zip, const char* country, char* url, char* proxyHost, char* proxyPort, long* pSesscode, char* szChallenge, int nChalLen); #ifdef __cplusplus } #endif #endif // __DIGI_DOC_CFG_H__ libdigidoc-3.10.5/libdigidoc/DigiDocMem.h0000664000372000037200000001072013560273131017477 0ustar travistravis#ifndef __DIGIDOC_MEM_H__ #define __DIGIDOC_MEM_H__ //================================================== // FILE: DigiDocMem.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for memory buffer management // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 09.09.2004 Veiko Sinivee // Creation //================================================== #include "DigiDocDefs.h" #ifdef __cplusplus extern "C" { #endif typedef struct DigiDocMemBuf_st { void* pMem; // functions will assign allocated memory address here long nLen; // length of data in number of bytes } DigiDocMemBuf; //-------------------------------------------------- // Helper function to append data to a memory buffer // and grow it as required. // pBuf - address of memory buffer pointer // data - new data to be appended // len - length of data or -1 for zero terminated strings //-------------------------------------------------- EXP_OPTION int ddocMemAppendData(DigiDocMemBuf* pBuf, const char* data, long len); //-------------------------------------------------- // Helper function to assign data to a memory buffer // and release old content if necessary // pBuf - address of memory buffer pointer // data - new data to be appended // len - length of data or -1 for zero terminated strings //-------------------------------------------------- EXP_OPTION int ddocMemAssignData(DigiDocMemBuf* pBuf, const char* data, long len); EXP_OPTION int ddocMemAssignData2(DigiDocMemBuf* pBuf, const char* data, long len); //-------------------------------------------------- // Helper function to set buffer length as required // It will fill acquired mem with zeros. // pBuf - address of memory buffer pointer // len - new length of buffer //-------------------------------------------------- EXP_OPTION int ddocMemSetLength(DigiDocMemBuf* pBuf, long len); //-------------------------------------------------- // Helper function to free/cleanup memory buffer // This does not attempt to release the buffer object // itself but only it's contents. // pBuf - memory buffer pointer //-------------------------------------------------- EXP_OPTION int ddocMemBuf_free(DigiDocMemBuf* pBuf); //-------------------------------------------------- // Helper function to assign zero terminated strings // and release old content if necessary // dest - destination address // src - new data to be assigned //-------------------------------------------------- EXP_OPTION int ddocMemAssignString(char** dest, const char* src); //-------------------------------------------------- // Replaces a substring with another substring // pBuf1 - memory buffer to search in // pBuf2 - memory buffer to write converted value to // search - search value // replacement - replacement value //-------------------------------------------------- EXP_OPTION int ddocMemReplaceSubstr(DigiDocMemBuf* pBuf1, DigiDocMemBuf* pBuf2, const char* search, const char* replacment); EXP_OPTION int ddocMemGetSubstr(DigiDocMemBuf* pBuf1, DigiDocMemBuf* pBuf2, const char* search, const char* replacment); EXP_OPTION char *replaceStr(char *str, char *orig, char *rep); //-------------------------------------------------- // Compares memory buffers // pBuf1 - memory buffer to value 1 // pBuf2 - memory buffer to value 2 // return 0 if both buffers are equal, 1 if not equal //-------------------------------------------------- EXP_OPTION int ddocMemCompareMemBufs(DigiDocMemBuf* pBuf1, DigiDocMemBuf* pBuf2); int ddocMemPush(DigiDocMemBuf* pBuf1, const char* tag); const char* ddocMemPop(DigiDocMemBuf* pBuf1); #ifdef __cplusplus } #endif #endif // __DIGIDOC_MEM_H__ libdigidoc-3.10.5/libdigidoc/DigiDocVerify.c0000664000372000037200000022040713560273131020225 0ustar travistravis//================================================== // FILE: DigiDocVerify.c // PROJECT: Digi Doc // DESCRIPTION: DigiDoc verification routines // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 26.04.2006 Veiko Sinivee // Creation //================================================== #include "DigiDocVerify.h" #include "DigiDocError.h" #include "DigiDocLib.h" #include "DigiDocDebug.h" #include "DigiDocConvert.h" #include "DigiDocError.h" #include "DigiDocCert.h" #include "DigiDocGen.h" #include "DigiDocObj.h" #include #ifdef WITH_ECDSA #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x10010000L static EVP_MD_CTX *EVP_MD_CTX_new() { return (EVP_MD_CTX*)OPENSSL_malloc(sizeof(EVP_MD_CTX)); } static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { OPENSSL_free(ctx); } static const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs) { return bs ? bs->signature : NULL; } static X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx) { return ctx ? ctx->param : NULL; } const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single) { return single ? single->certId : NULL; } #endif //--------------------< ddoc structure def >----------------------- const XmlElemDef eTransform = {"Transform", 'Y', NULL}; /* 1.0 */ const XmlElemDef* eTransformsCh[] = {&eTransform, NULL}; /* 1.0 */ const XmlElemDef eTransforms = {"Transforms", 'Y', (void**)&eTransformsCh}; /* 1.0 */ const XmlElemDef eDigestMethod = {"DigestMethod", 'N', NULL}; const XmlElemDef eDigestValue = {"DigestValue", 'N', NULL}; const XmlElemDef* eRefCh[] = {&eDigestMethod, &eDigestValue, &eTransforms, NULL}; const XmlElemDef eReference = {"Reference", 'Y', (void**)&eRefCh}; const XmlElemDef eSignatureMethod = {"SignatureMethod", 'N', NULL}; const XmlElemDef eCanonicalizationMethod = {"CanonicalizationMethod", 'N', NULL}; const XmlElemDef* eSigInfoCh[] = {&eCanonicalizationMethod, &eSignatureMethod, &eReference, NULL}; const XmlElemDef eSigInfo = {"SignedInfo", 'N', (void**)&eSigInfoCh}; const XmlElemDef eSigVal = {"SignatureValue", 'N', NULL}; const XmlElemDef eModulus = {"Modulus", 'N', NULL}; const XmlElemDef eExponent = {"Exponent", 'N', NULL}; const XmlElemDef* eRSAKeyValueCh[] = {&eModulus, &eExponent, NULL}; const XmlElemDef eRSAKeyValue = {"RSAKeyValue", 'N', (void**)&eRSAKeyValueCh}; const XmlElemDef* eKeyValueCh[] = {&eRSAKeyValue}; const XmlElemDef eKeyValue = {"KeyValue", 'N', (void**)&eKeyValueCh}; const XmlElemDef eX509Certificate = {"X509Certificate", 'N', NULL}; const XmlElemDef* eX509DataCh[] = {&eX509Certificate, NULL}; const XmlElemDef eX509Data = {"X509Data", 'N', (void**)&eX509DataCh}; const XmlElemDef* eKeyInfoCh[] = {&eKeyValue,&eX509Data, NULL}; const XmlElemDef eKeyInfo = {"KeyInfo", 'N', (void**)&eKeyInfoCh}; const XmlElemDef eEncapsulatedOCSPValue = {"EncapsulatedOCSPValue", 'Y', NULL}; const XmlElemDef* eOCSPValuesCh[] = {&eEncapsulatedOCSPValue, NULL}; const XmlElemDef eOCSPValues = {"OCSPValues", 'N', (void**)&eOCSPValuesCh}; const XmlElemDef* eRevocationValuesCh[] = {&eOCSPValues, &eEncapsulatedOCSPValue, NULL}; const XmlElemDef eRevocationValues = {"RevocationValues", 'N', (void**)&eRevocationValuesCh}; const XmlElemDef eEncapsulatedX509Certificate = {"EncapsulatedX509Certificate", 'Y', NULL}; const XmlElemDef* eCertificateValuesCh[] = {&eEncapsulatedX509Certificate, NULL}; const XmlElemDef eCertificateValues = {"CertificateValues", 'N', (void**)&eCertificateValuesCh}; const XmlElemDef eResponderID = {"ResponderID", 'N', NULL}; const XmlElemDef eProducedAt = {"ProducedAt", 'N', NULL}; const XmlElemDef* eOCSPIdentifierCh[] = {&eResponderID,&eProducedAt, NULL}; const XmlElemDef eOCSPIdentifier = {"OCSPIdentifier", 'N', (void**)&eOCSPIdentifierCh}; const XmlElemDef* eDigestAlgAndValueCh[] = {&eDigestMethod,&eDigestValue, NULL}; const XmlElemDef eDigestAlgAndValue = {"DigestAlgAndValue", 'N', (void**)&eDigestAlgAndValueCh}; const XmlElemDef* eOCSPRefCh[] = {&eOCSPIdentifier,&eDigestAlgAndValue, NULL}; const XmlElemDef eOCSPRef = {"OCSPRef", 'Y', (void**)&eOCSPRefCh}; const XmlElemDef* eOCSPRefsCh[] = {&eOCSPRef, NULL}; const XmlElemDef eOCSPRefs = {"OCSPRefs", 'N', (void**)&eOCSPRefsCh}; const XmlElemDef* eCompleteRevocationRefsCh[] = {&eOCSPRefs, NULL}; const XmlElemDef eCompleteRevocationRefs = {"CompleteRevocationRefs", 'N', (void**)&eCompleteRevocationRefsCh}; // const XmlElemDef eX509IssuerName = {"X509IssuerName", 'N', NULL}; const XmlElemDef eX509SerialNumber = {"X509SerialNumber", 'N', NULL}; const XmlElemDef* eIssuerSerialCh[] = {&eX509IssuerName,&eX509SerialNumber, NULL}; const XmlElemDef eIssuerSerial = {"IssuerSerial", 'N', (void**)&eIssuerSerialCh}; const XmlElemDef* eCertDigestCh[] = {&eDigestMethod,&eDigestValue, NULL}; const XmlElemDef eCertDigest = {"CertDigest", 'N', (void**)&eCertDigestCh}; const XmlElemDef* eCertCh[] = {&eCertDigest,&eIssuerSerial, NULL}; const XmlElemDef eCert = {"Cert", 'Y', (void**)&eCertCh}; const XmlElemDef* eCertRefsCh[] = {&eCert, NULL}; const XmlElemDef eCertRefs = {"CertRefs", 'N', (void**)&eCertRefsCh}; const XmlElemDef* eCompleteCertificateRefsCh[] = {&eCertRefs, &eCert, NULL };// 1.0 const XmlElemDef eCompleteCertificateRefs = {"CompleteCertificateRefs", 'N', (void**)&eCompleteCertificateRefsCh}; const XmlElemDef* eUnsignedSignaturePropertiesCh[] = {&eCompleteCertificateRefs,&eCompleteRevocationRefs,&eCertificateValues,&eRevocationValues, NULL}; const XmlElemDef eUnsignedSignatureProperties = {"UnsignedSignatureProperties", 'N', (void**)&eUnsignedSignaturePropertiesCh}; const XmlElemDef* eUnsignedPropertiesCh[] = {&eUnsignedSignatureProperties, NULL}; const XmlElemDef eUnsignedProperties = {"UnsignedProperties", 'N', (void**)&eUnsignedPropertiesCh}; const XmlElemDef* eSigningCertificateCh[] = {&eCert, NULL}; const XmlElemDef eSigningCertificate = {"SigningCertificate", 'N', (void**)&eSigningCertificateCh}; const XmlElemDef eSigningTime = {"SigningTime", 'N', NULL}; const XmlElemDef eSignaturePolicyImplied = {"SignaturePolicyImplied", 'N', NULL}; const XmlElemDef eCity = {"City", 'N', NULL}; const XmlElemDef eStateOrProvince = {"StateOrProvince", 'N', NULL}; const XmlElemDef ePostalCode = {"PostalCode", 'N', NULL}; const XmlElemDef eCountryName = {"CountryName", 'N', NULL}; const XmlElemDef* eSignatureProductionPlaceCh[] = {&eCity,&eStateOrProvince,&ePostalCode,&eCountryName, NULL}; const XmlElemDef eSignatureProductionPlace = {"SignatureProductionPlace", 'N', (void**)&eSignatureProductionPlaceCh}; const XmlElemDef eClaimedRole = {"ClaimedRole", 'Y', NULL}; const XmlElemDef* eClaimedRolesCh[] = {&eClaimedRole, NULL}; const XmlElemDef eClaimedRoles = {"ClaimedRoles", 'N', (void**)&eClaimedRolesCh}; const XmlElemDef* eSignerRoleCh[] = {&eClaimedRoles, NULL}; const XmlElemDef eSignerRole = {"SignerRole", 'N', (void**)&eSignerRoleCh}; const XmlElemDef* eSignaturePolicyIdentifierCh[] = {&eSignaturePolicyImplied, NULL}; const XmlElemDef eSignaturePolicyIdentifier = {"SignaturePolicyIdentifier", 'N', (void**)&eSignaturePolicyIdentifierCh}; const XmlElemDef* eSignedSignaturePropertiesCh[] = {&eSigningTime,&eSigningCertificate,&eSignaturePolicyIdentifier,&eSignatureProductionPlace,&eSignerRole, NULL}; const XmlElemDef eSignedSignatureProperties = {"SignedSignatureProperties", 'N', (void**)&eSignedSignaturePropertiesCh}; const XmlElemDef eSignedDataObjectProperties = {"SignedDataObjectProperties", 'N', NULL}; const XmlElemDef* eSignedPropertiesCh[] = {&eSignedSignatureProperties,&eSignedDataObjectProperties, NULL}; const XmlElemDef eSignedProperties = {"SignedProperties", 'N', (void**)&eSignedPropertiesCh}; const XmlElemDef* eQualifyingPropertiesCh[] = {&eSignedProperties,&eUnsignedProperties, NULL}; const XmlElemDef eQualifyingProperties = {"QualifyingProperties", 'N', (void**)&eQualifyingPropertiesCh}; const XmlElemDef* eObjectCh[] = {&eQualifyingProperties, NULL}; const XmlElemDef eObject = {"Object", 'N', (void**)&eObjectCh}; const XmlElemDef* eSignatureCh[] = {&eSigInfo,&eSigVal,&eKeyInfo,&eObject, NULL}; const XmlElemDef eSignature = {"Signature", 'Y', (void**)&eSignatureCh}; const XmlElemDef eDataFile = {"DataFile", 'Y', NULL}; const XmlElemDef* eSigDocCh[] = {&eDataFile, &eSignature, NULL}; const XmlElemDef eSignedDoc = {"SignedDoc", 'N', (void**)& eSigDocCh }; //-------------------------------------------------- int XmlElemInfo_new(XmlElemInfo **ppXi, const char* id, const char* tag) { XmlElemInfo* pXi = NULL; //RETURN_IF_NULL_PARAM(id); RETURN_IF_NULL_PARAM(tag); ddocDebug(5, "XmlElemInfo_new", "tag: %s id: %s", (tag ? tag : "NULL"), (id ? id : "NULL")); pXi = (XmlElemInfo*)malloc(sizeof(XmlElemInfo)); RETURN_IF_BAD_ALLOC(pXi); memset(pXi, 0, sizeof(XmlElemInfo)); if(id) setString(&(pXi->szId), id, -1); if(tag) setString(&(pXi->szTag), tag, -1); *ppXi = pXi; return ERR_OK; } void XmlElemInfo_free(XmlElemInfo* pXi) { XmlElemInfo** p = NULL; RETURN_VOID_IF_NULL(pXi); ddocDebug(5, "XmlElemInfo_free", "tag: %s id: %s children: %s", (pXi->szTag ? pXi->szTag : "NULL"), (pXi->szId ? pXi->szId : "NULL"), (pXi->pChildren ? "Y" : "N")); for(p = (XmlElemInfo**)pXi->pChildren; p && *p; p++) XmlElemInfo_free(*p); if(pXi->pChildren) free(pXi->pChildren); if(pXi->szId) free(pXi->szId); if(pXi->szTag) free(pXi->szTag); if(pXi) free(pXi); } int XmlElemInfo_countChildren(XmlElemInfo* pXi) { XmlElemInfo** p = NULL; int n = 0; if(pXi && pXi->pChildren) { for(p = (XmlElemInfo**)pXi->pChildren; p && *p; p++) n++; } return n; } int XmlElemInfo_addChild(XmlElemInfo* pParent, XmlElemInfo* pChild) { int n = 0; RETURN_IF_NULL(pParent); RETURN_IF_NULL(pChild); n = XmlElemInfo_countChildren(pParent); pParent->pChildren = (void**)realloc(pParent->pChildren, sizeof(XmlElemInfo*) * (n + 2)); ((XmlElemInfo**)pParent->pChildren)[n] = pChild; pChild->pParent = pParent; ((XmlElemInfo**)pParent->pChildren)[n+1] = NULL; return ERR_OK; } XmlElemInfo* XmlElemInfo_getRootElem(XmlElemInfo* pElem) { if(pElem) { if(!pElem->pParent) return pElem; else return XmlElemInfo_getRootElem(pElem->pParent); } return NULL; } int XmlElemInfo_getLevel(XmlElemInfo* pElem) { int n = 0; XmlElemInfo* p = pElem; while(p) { n++; p = p->pParent; } return n; } XmlElemInfo** XmlElemInfo_getPathElements(XmlElemInfo* pElem) { XmlElemInfo *p = 0, **pp = 0; int n = XmlElemInfo_getLevel(pElem); if(n > 0) { pp = (XmlElemInfo **)malloc(sizeof(XmlElemInfo *) * (n+1)); pp[n] = 0; p = pElem; while(p && n > 0) { pp[n-1] = p; n--; p = p->pParent; } } return pp; } int XmlElemInfo_getPath(XmlElemInfo* pElem, DigiDocMemBuf* pMbuf) { int err = ERR_OK; XmlElemInfo **pp1 = 0, **pp2 = 0; RETURN_IF_NULL(pElem); RETURN_IF_NULL(pMbuf); pp2 = XmlElemInfo_getPathElements(pElem); for(pp1 = pp2; pp1 && *pp1; pp1++) { err = ddocMemAppendData(pMbuf, "/", -1); err = ddocMemAppendData(pMbuf, (*pp1)->szTag, -1); } free(pp2); return err; } XmlElemDef* XmlElemDef_findChildByTag(XmlElemDef* pElem, const char* tag) { XmlElemDef **p = NULL, *pe = NULL; if(pElem && pElem->szTag && tag && !strcmp(pElem->szTag, tag)) return pElem; if(pElem && pElem->pChildren) { for(p = (XmlElemDef**)pElem->pChildren; p && *p; p++) { pe = XmlElemDef_findChildByTag(*p, tag); if(pe) return pe; } } return NULL; } XmlElemDef* XmlElemDef_findElemOrDirectChildByTag(XmlElemDef* pElem, const char* tag) { XmlElemDef **p = NULL; if(pElem && pElem->szTag && tag && !strcmp(pElem->szTag, tag)) return pElem; if(pElem && pElem->pChildren) { for(p = (XmlElemDef**)pElem->pChildren; p && *p; p++) { if(p && (*p)->szTag && tag && !strcmp((*p)->szTag, tag)) return *p; } } return NULL; } int XmlElemInfo_countChildrenWithTag(XmlElemInfo* pElem, const char* tag) { int n = 0; XmlElemInfo **p = NULL; if(pElem && pElem->pChildren) { for(p = (XmlElemInfo**)pElem->pChildren; p && *p; p++) { if(p && (*p)->szTag && tag && !strcmp((*p)->szTag, tag)) n++; } } return n; } int XmlElemDef_checkPath(XmlElemDef* pRoot, XmlElemInfo* pElem) { DigiDocMemBuf mbuf; XmlElemDef *p1 = pRoot, *p2 = 0; XmlElemInfo **pp1 = 0, **pp2 = 0; int err = ERR_OK; mbuf.pMem = 0; mbuf.nLen = 0; XmlElemInfo_getPath(pElem, &mbuf); ddocDebug(4, "XmlElemDef_checkPath", "Validate elem: %s path: %s", (pElem->szTag ? pElem->szTag : "NULL"), mbuf.pMem); ddocMemBuf_free(&mbuf); pp2 = XmlElemInfo_getPathElements(pElem); for(pp1 = pp2; pp1 && *pp1 && p1; pp1++) { p2 = XmlElemDef_findElemOrDirectChildByTag(p1, (*pp1)->szTag); ddocDebug(4, "XmlElemDef_checkPath", "Current: %s find: %s found: %s", (p1->szTag ? p1->szTag : "NULL"), ((*pp1)->szTag ? (*pp1)->szTag : "NULL"), (p2 ? "OK" : "NULL")); if(!p2) { ddocDebug(1, "XmlElemDef_checkPath", "Did not find: %s under %s", ((*pp1)->szTag ? (*pp1)->szTag : "NULL"), (p1->szTag ? p1->szTag : "NULL")); err = ERR_XML_VALIDATION; } p1 = p2; } free(pp2); return err; } int validateElementPath(XmlElemInfo* pElem) { XmlElemDef* pRoot = &eSignedDoc; XmlElemDef* pCurr = NULL; int err = ERR_OK, n; ddocDebug(3, "validateElementPath", "Validate elem: %s root: %s", (pElem->szTag ? pElem->szTag : "NULL"), (pRoot->szTag ? pRoot->szTag : "NULL")); pCurr = XmlElemDef_findChildByTag(pRoot, pElem->szTag); if(pCurr) { ddocDebug(3, "validateElementPath", "Elem: %s exists", (pElem->szTag ? pElem->szTag : "NULL")); err = XmlElemDef_checkPath(pRoot, pElem); ddocDebug(3, "validateElementPath", "Elem: %s path rc: %d", (pElem->szTag ? pElem->szTag : "NULL"), err); if(err) SET_LAST_ERROR(err); if(!err && pElem->pParent) { XmlElemInfo* pParent = (XmlElemInfo*)pElem->pParent; n = XmlElemInfo_countChildrenWithTag(pParent, pElem->szTag); ddocDebug(3, "validateElementPath", "Parent: %s elems: %s count: %d multiple: %c", (pParent->szTag ? pParent->szTag : "NULL"), (pElem->szTag ? pElem->szTag : "NULL"), n, pCurr->bMultiple); if(n > 1 && pCurr->bMultiple != 'Y') { ddocDebug(3, "validateElementPath", "Found: %d elems: %s under: %s but multiple not allowed", n, (pElem->szTag ? pElem->szTag : "NULL"), (pParent->szTag ? pParent->szTag : "NULL")); err = ERR_XML_VALIDATION; SET_LAST_ERROR(err); } } } else { ddocDebug(1, "validateElementPath", "Elem: %s does not exist", (pElem->szTag ? pElem->szTag : "NULL")); err = ERR_DIGIDOC_PARSE; } return err; } //-------------------------------------------------- //-------------------------------------------------- // Verifies files SHA1-RSA signature // szFileName - file name // nDigestType - digest type. Supports only SHA1 (0) // pSigBuf - buffer to store the signature // nSigLen - buffer size, must be at least 128 // will be updated by actual signature length // certfile - name of the certificate file // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int verifyFileSignature(const char* szFileName, int nDigestType, byte* pSigBuf, int nSigLen, const char *certfile) { int err = ERR_OK; EVP_MD_CTX *ctx; unsigned char buf[FILE_BUFSIZE]; int i; FILE *f; EVP_PKEY* pkey = NULL; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(pSigBuf); RETURN_IF_NULL_PARAM(certfile); if(nDigestType == DIGEST_SHA1) { if((err = ReadPublicKey(&pkey, certfile)) == ERR_OK) { if((f = fopen(szFileName,"rb")) != NULL) { ctx = EVP_MD_CTX_new(); EVP_VerifyInit(ctx, EVP_sha1()); for (;;) { i = fread(buf, sizeof(char), FILE_BUFSIZE, f); if (i <= 0) break; EVP_VerifyUpdate (ctx, buf, (unsigned long)i); } err = EVP_VerifyFinal(ctx, pSigBuf, nSigLen, pkey); EVP_MD_CTX_free(ctx); if(err == ERR_LIB_NONE) err = ERR_OK; fclose(f); EVP_PKEY_free(pkey); } // if - fopen else err = ERR_FILE_READ; } else err = ERR_CERT_READ; } else err = ERR_UNSUPPORTED_DIGEST; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Verifies files SHA1-RSA signature // szData - input data // dataLen - input data length // nDigestType - digest type // pSigBuf - buffer to store the signature // nSigLen - buffer size, must be at least 128 // will be updated by actual signature length // cert - certificate data // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int verifySignature(const char* szData, unsigned long dataLen, int nDigestType, byte* pSigBuf, int nSigLen, X509* cert) { int err = ERR_OK; EVP_MD_CTX *ctx; EVP_PKEY* pkey = NULL; RETURN_IF_NULL_PARAM(szData); RETURN_IF_NULL_PARAM(pSigBuf); RETURN_IF_NULL_PARAM(cert); if(nDigestType == DIGEST_SHA1) { if((err = GetPublicKey(&pkey, cert)) == ERR_OK) { checkErrors(); ctx = EVP_MD_CTX_new(); EVP_VerifyInit(ctx, EVP_sha1()); checkErrors(); EVP_VerifyUpdate (ctx, szData, dataLen); checkErrors(); err = EVP_VerifyFinal(ctx, pSigBuf, nSigLen, pkey); EVP_MD_CTX_free(ctx); if(err == ERR_LIB_NONE) err = ERR_OK; checkErrors(); EVP_PKEY_free(pkey); checkErrors(); } else err = ERR_CERT_READ; } else err = ERR_UNSUPPORTED_DIGEST; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // Compares two byte arrays and returns 0 for OK. // doesn't record an error on error stack // dig1 - byte array 1 // len1 - byte array 1 length // dig2 - byte array 2 // len2 - byte array 2 length //============================================================ EXP_OPTION int compareByteArraysNoErr(const byte* dig1, int len1, const byte* dig2, int len2) { int i; if(!dig1 || !dig2 || len1 != len2) return -1; for(i = 0; i < len1; i++) { if(dig1[i] != dig2[i]) return -2; } return 0; } //byte sigvalasn1[] = { 48, 33, 48, 9, 6, 5, 43, 14, 3, 2, 26, 5, 0, 4, 20 }; byte sigvalasn1[] = { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14 }; byte sigvalasn2[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; int verifySigValAsn1(byte* sigval, int len) { if(!sigval || (compareByteArraysNoErr(sigval, len, sigvalasn1, sizeof(sigvalasn1)) && compareByteArraysNoErr(sigval, len, sigvalasn2, sizeof(sigvalasn2)))) { ddocDebug(1, "verifySigValAsn1", "Invalid signature value asn.1 len: ", len); SET_LAST_ERROR(ERR_SIGVAL_ASN1); return ERR_SIGVAL_ASN1; } return ERR_OK; } //-------------------------------------------------- // Verifies files SHA1-RSA signature (EstID specific!!!) // digest - digest data // dataLen - digest data length // nDigestType - digest type // pSigBuf - buffer to store the signature // nSigLen - buffer size, must be at least 128 // will be updated by actual signature length // cert - certificate data // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int verifyEstIDSignature(const byte* digest, int digestLen, int nDigestType, byte* pSigBuf, int nSigLen, X509* cert) { int err = ERR_OK, nCheckSigValAsn1 = 1; EVP_PKEY* pkey = 0; RSA *rsa = 0; byte buf2[DIGEST_LEN+2], buf3[500], buf4[200], buf5[200],buf256[DIGEST_LEN256+2]; int l2 = 0, l1; //AM 11.02.09 ecdsa-sha1 support for LI #ifdef WITH_ECDSA ECDSA_SIG *ecsig; #endif RETURN_IF_NULL_PARAM(digest); RETURN_IF_NULL_PARAM(pSigBuf); RETURN_IF_NULL_PARAM(cert); ddocDebug(3, "verifyEstIDSignature", "start"); if(nDigestType == DIGEST_SHA1) { if((err = GetPublicKey(&pkey, cert)) == ERR_OK) { l2 = sizeof(buf3); memset(buf3, 0, sizeof(buf3)); ERR_clear_error(); //swapBytes(pSigBuf, nSigLen); #ifdef WITH_ECDSA if(pkey->type==NID_X9_62_id_ecPublicKey){ ecsig = ECDSA_SIG_new(); ecsig->r = BN_new(); ecsig->s = BN_new(); if (!BN_bin2bn(pSigBuf, nSigLen/2,ecsig->r) || !BN_bin2bn(pSigBuf + nSigLen/2, nSigLen/2, ecsig->s)){ ECDSA_SIG_free(ecsig); EVP_PKEY_free(pkey); return ERR_COMPARE; } l2 = ECDSA_do_verify(digest, digestLen, ecsig, pkey->pkey.ec); ECDSA_SIG_free(ecsig); if (l2 == -1){ /* error */ err = ERR_COMPARE; } else if (l2 == 0){ /* incorrect signature */ err = ERR_COMPARE; } else { /* ret == 1 */ /* signature ok */ err = ERR_OK; } }else #endif if(EVP_PKEY_base_id(pkey)==EVP_PKEY_RSA){ //clearErrors(); rsa = EVP_PKEY_get1_RSA(pkey); l2 = RSA_public_decrypt(nSigLen, pSigBuf, buf3, rsa, RSA_PKCS1_PADDING); //RSA_PKCS1_PADDING); //RSA_NO_PADDING); RSA_free(rsa); checkErrors(); ddocDebug(3, "verifyEstIDSignature", "decryted sig-hash len: %d", l2); // debug info l1 = sizeof(buf4); if(digestLen > 0) { memset(buf4, 0, sizeof(buf4)); encode((const byte*)digest, digestLen, (byte*)buf4, &l1); ddocDebug(3, "verifyEstIDSignature", "calculated hash: %s len: %d", buf4, digestLen); } l1 = sizeof(buf4); if(l2 > 0) { // TODO: lisa asn.1 prefixi kontroll memset(buf4, 0, sizeof(buf4)); encode((const byte*)buf3, l2, (byte*)buf4, &l1); ddocDebug(3, "verifyEstIDSignature", "decrypted hash: %s len: %d", buf4, l2); } memset(buf2, 0, DIGEST_LEN); checkErrors(); if(l2 > DIGEST_LEN) { err = verifySigValAsn1(buf3, l2 - DIGEST_LEN); memcpy(buf2, buf3 + l2 - DIGEST_LEN, DIGEST_LEN); } else { memcpy(buf2, buf3, DIGEST_LEN); err = ERR_SIGVAL_ASN1; SET_LAST_ERROR(err); ddocDebug(1, "verifyEstIDSignature", "Invalid rsa-sha1 siganture length: %d", l2); } if(!err) err = compareByteArrays(digest, digestLen, buf2, DIGEST_LEN); //debug l1 = sizeof(buf4); encode((const byte*)digest, digestLen, (byte*)buf4, &l1); l1 = sizeof(buf5); encode((const byte*)buf2, DIGEST_LEN, (byte*)buf5, &l1); ddocDebug(3, "verifyEstIDSignature", "comp-hash: %s sig-hash: %s, err: %d", buf4, buf5, err); } else err = ERR_UNSUPPORTED_SIGNATURE; EVP_PKEY_free(pkey); checkErrors(); } //AM 23.04.08 } else if(nDigestType == DIGEST_SHA256) { if((err = GetPublicKey(&pkey, cert)) == ERR_OK) { l2 = sizeof(buf3); memset(buf3, 0, sizeof(buf3)); ERR_clear_error(); //swapBytes(pSigBuf, nSigLen); rsa = EVP_PKEY_get1_RSA(pkey); l2 = RSA_public_decrypt(nSigLen, pSigBuf, buf3, rsa, RSA_PKCS1_PADDING); //RSA_PKCS1_PADDING); //RSA_NO_PADDING); RSA_free(rsa); checkErrors(); ddocDebug(3, "verifyEstIDSignature", "decryted sig-hash len: %d", l2); // debug info l1 = sizeof(buf4); if(digestLen > 0) { memset(buf4, 0, sizeof(buf4)); encode((const byte*)digest, digestLen, (byte*)buf4, &l1); ddocDebug(3, "verifyEstIDSignature", "calculated hash: %s len: %d", buf4, digestLen); } l1 = sizeof(buf4); if(l2 > 0) { memset(buf4, 0, sizeof(buf4)); encode((const byte*)buf3, l2, (byte*)buf4, &l1); ddocDebug(3, "verifyEstIDSignature", "decrypted hash: %s len: %d", buf4, l2); } memset(buf256, 0, DIGEST_LEN); if(l2 > DIGEST_LEN) memcpy(buf256, buf3 + l2 - DIGEST_LEN, DIGEST_LEN); else memcpy(buf256, buf3, DIGEST_LEN); checkErrors(); //err = compareByteArrays(digest, digestLen, buf256, DIGEST_LEN256); err = compareByteArrays(digest, DIGEST_LEN, buf256, DIGEST_LEN); //debug l1 = sizeof(buf4); encode((const byte*)digest, digestLen, (byte*)buf4, &l1); l1 = sizeof(buf5); encode((const byte*)buf256, DIGEST_LEN256, (byte*)buf5, &l1); ddocDebug(3, "verifyEstIDSignature", "comp-hash: %s sig-hash: %s, err: %d", buf4, buf5, err); EVP_PKEY_free(pkey); checkErrors(); } else err = ERR_CERT_READ; } else err = ERR_UNSUPPORTED_DIGEST; if (err != ERR_OK) SET_LAST_ERROR(err); ddocDebug(3, "verifyEstIDSignature", "end"); return err; } //============================================================ // Compares two byte arrays and returns 0 for OK // dig1 - byte array 1 // len1 - byte array 1 length // dig2 - byte array 2 // len2 - byte array 2 length //============================================================ EXP_OPTION int compareByteArrays(const byte* dig1, int len1, const byte* dig2, int len2) { int err = ERR_OK, i; RETURN_IF_NULL_PARAM(dig1); RETURN_IF_NULL_PARAM(dig2); RETURN_IF_NOT(len1 == len2, ERR_COMPARE); for(i = 0; i < len1; i++) { if(dig1[i] != dig2[i]) { err = ERR_COMPARE; break; } } return err; } //============================================================ // Checks and records the knowledge if one signature had // missing xmlns problem // pSigDoc - signed doc data // returns 1 if at least one signature had this problem //============================================================ EXP_OPTION int checkDdocWrongDigests(const SignedDoc* pSigDoc) { int i, d, j, l, m, k, err = 0, e = 0; SignatureInfo *pSigInfo = 0; DocInfo *pDi = NULL; DataFile *pDf = NULL; RETURN_IF_NULL_PARAM(pSigDoc); d = getCountOfSignatures(pSigDoc); m = getCountOfDataFiles(pSigDoc); //printf("checkDdocWrongDigests\n"); for(i = 0; i < d; i++) { pSigInfo = getSignature(pSigDoc, i); l = getCountOfDocInfos(pSigInfo); for(j = 0; j < l; j++) { pDi = getDocInfo(pSigInfo, j); for(k = 0; k < m; k++) { pDf = getDataFile(pSigDoc, k); //printf("DI: %s DF: %s content: %s\n", pDi->szDocId, pDf->szId, pDf->szContentType); if(!strcmp(pDi->szDocId, pDf->szId) && (!strcmp(pDf->szContentType, CONTENT_EMBEDDED) || !strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64))) { err = compareByteArrays(pDi->szDigest, pDi->nDigestLen, (byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen); if(err) { // check also the wrong digest err = compareByteArrays(pDi->szDigest, pDi->nDigestLen, (byte*)pDf->mbufWrongDigest.pMem, pDf->mbufWrongDigest.nLen); if(!err) { setString((char**)&(pDi->szDigestType), DIGEST_SHA1_WRONG, -1); e = 1; } } } } } } return e; } //============================================================ // Verifies the digest of the given doc in this signature // pSigDoc - signed doc data // pSigInfo - signature info object // filename - file name for not embedded files // szDataFile - name of the digidoc file //============================================================ // FIXME : Hard to understand the logic EXP_OPTION int verifySigDocDigest(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const DocInfo* pDocInfo, const char* szDataFile) { int err = ERR_OK; int l1 = 0, l2 = 0; DataFile *pDf = NULL ; byte buf1[DIGEST_LEN+2], buf2[100], buf3[100], buf4[100]; char *attNames = NULL, *attValues = NULL, *pTmp1 = NULL, *pTmp2 = NULL; //FILE *hFile; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pDocInfo); pDf = getDataFileWithId(pSigDoc, pDocInfo->szDocId); RETURN_IF_NULL(pDf); RETURN_IF_NULL(pDf->szContentType); RETURN_IF_NULL(pDf->szDigestType); RETURN_IF_NULL(pDocInfo->szDigestType); // verify detached file signature ddocDebug(3, "verifySigDocDigest", "SigDoc: %s DF: %s len1: %d len2: %d, ctype: %s", pSigDoc->szFormatVer, pDf->szId, pDf->mbufDigest.nLen, pDocInfo->nDigestLen, pDf->szContentType); // the new digest calculation on the fly doesn't // work for old 1.0 files //AM 29.10.09 if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED) && (!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME))) { attNames = "Id"; attValues = pDf->szId; err = readTagContents(&pTmp2, szDataFile, "DataFile", 1, (const char**)&attNames, (const char**)&attValues, 0); if(err == ERR_OK) { pTmp1 = pTmp2; //skip leading newlines while(*pTmp1 && *pTmp1 != '<') pTmp1++; l1 = sizeof(buf1); err = calculateDigest((const byte*)pTmp1, strlen(pTmp1), DIGEST_SHA1, (byte*)buf1, &l1); if(err == ERR_OK) { err = ddocDataFile_SetDigestValue(pDf, (const char*)buf1, DIGEST_LEN); encode((const byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, (byte*)buf3, &l2); ddocDebug(3, "verifySigDocDigest", "DF: %s calculated digest: %s", pDf->szId, buf3); } free(pTmp2); } } if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED) || !strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64)){ buf2[0] = buf3[0] = buf4[0] = 0; l2 = sizeof(buf2); if(pDocInfo->szDigest) bin2hex((const byte*)pDocInfo->szDigest, pDocInfo->nDigestLen, (char*)buf2, &l2); l2 = sizeof(buf3); if(pDf->mbufDigest.pMem) bin2hex((const byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, (char*)buf3, &l2); l2 = sizeof(buf4); if(pDf->mbufWrongDigest.pMem) bin2hex((const byte*)pDf->mbufWrongDigest.pMem, pDf->mbufWrongDigest.nLen, (char*)buf4, &l2); ddocDebug(3, "verifySigDocDigest", "DF: %s len1: %d len2: %d, type1: %s type2: %s, digest1: %s digest2: %s digest3: %s", pDf->szId, pDf->mbufDigest.nLen, pDocInfo->nDigestLen, pDocInfo->szDigestType, pDf->szDigestType, buf2, buf3, buf4); if(strcmp(pDocInfo->szDigestType, pDf->szDigestType)) err = ERR_DOC_DIGEST; else err = compareByteArrays(pDocInfo->szDigest, pDocInfo->nDigestLen, (byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen); if(err) { // check also the wrong digest err = compareByteArrays(pDocInfo->szDigest, pDocInfo->nDigestLen, (byte*)pDf->mbufWrongDigest.pMem, pDf->mbufWrongDigest.nLen); ddocDebug(3, "verifySigDocDigest", "wrong doc dig verify: %d", err); if(!err) { setString((char**)&(pDocInfo->szDigestType), DIGEST_SHA1_WRONG, -1); err = ERR_DF_WRONG_DIG; } } if(err != ERR_OK && err != ERR_DF_WRONG_DIG) err = ERR_DOC_DIGEST; } if (err != ERR_OK) SET_LAST_ERROR(err); ddocDebug(3, "verifySigDocDigest", "SigDoc DF: %s err: %d", pDf->szId, err); return err; } //============================================================ // Verifies the mime digest of the given doc in this signature // pSigDoc - signed doc data // pSigInfo - signature info object // filename - file name for not embedded files //============================================================ EXP_OPTION int verifySigDocMimeDigest(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const DocInfo* pDocInfo, const char* szFileName) { int err = ERR_OK; int l1; DataFile* pDf; byte buf1[DIGEST_LEN+2]; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pDocInfo); pDf = getDataFileWithId(pSigDoc, pDocInfo->szDocId); RETURN_IF_NULL(pDf); // we check mime digest only in ver 1.0 if(!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { l1 = sizeof(buf1); err = calculateDigest((const byte*)pDf->szMimeType, strlen(pDf->szMimeType), DIGEST_SHA1, buf1, &l1); RETURN_IF_NOT(err == ERR_OK, err); err = compareByteArrays(pDocInfo->szMimeDigest, pDocInfo->nMimeDigestLen, buf1, l1); if(err != ERR_OK) err = ERR_MIME_DIGEST; } if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // Verifies the SignedProperties digest // pSigInfo - signature info object // from original file and use it for hash function. // This is usefull if the file has been generated by // another library and possibly formats these elements // differently. //============================================================ EXP_OPTION int verifySigDocSigPropDigest(const SignatureInfo* pSigInfo) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pSigInfo); err = ddocCompareDigestValues(pSigInfo->pSigPropDigest, pSigInfo->pSigPropRealDigest); RETURN_IF_NOT(err == ERR_OK, ERR_SIGPROP_DIGEST); return err; } int verifyCertDnPart(const char* sDN, const char* sId, const X509* pCert, int nNid) { int err = ERR_OK; DigiDocMemBuf mbuf1, mbuf2; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; err = ddocCertGetDNPart(pCert, &mbuf1, nNid, 1); err = ddocGetDNPartFromString(sDN, sId, &mbuf2); ddocDebug(3, "verifyCertDnPart", "Search: %s from: %s got: %s cmp: %s", sId, sDN, (const char*)mbuf2.pMem, (const char*)mbuf1.pMem); if(mbuf1.pMem && mbuf2.pMem && strcmp((const char*)mbuf2.pMem, (const char*)mbuf1.pMem)) { ddocDebug(3, "verifyCertDnPart", "Not matching entry: %s cert: %s signed: %s", sId, (const char*)mbuf1.pMem, (const char*)mbuf2.pMem); err = ERR_WRONG_CERT; SET_LAST_ERROR(err); } ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); return err; } //============================================================ // Verifies the certificates signed attributes // pSigInfo - signature info object //============================================================ EXP_OPTION int verifySigCert(const SignatureInfo* pSigInfo) { int err = ERR_OK, e1; int l1, l2; char szOtherSerial[100]; byte buf1[DIGEST_LEN256+2], buf2[DIGEST_LEN256*2], buf3[DIGEST_LEN256*2]; DigiDocMemBuf* pMBuf; CertID* pCertID = 0; X509* pCert; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(ddocSigInfo_GetSignersCert(pSigInfo)); l1 = sizeof(buf1); pCertID = ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID); if(pCertID->szDigestType){ if(!strcmp(pCertID->szDigestType,DIGEST_SHA256_NAME)){ RETURN_IF_NOT(X509_digest(ddocSigInfo_GetSignersCert(pSigInfo), EVP_sha256(), buf1, (unsigned int*)&l1), ERR_X509_DIGEST); } else{ RETURN_IF_NOT(X509_digest(ddocSigInfo_GetSignersCert(pSigInfo), EVP_sha1(), buf1, (unsigned int*)&l1), ERR_X509_DIGEST); } }else{ RETURN_IF_NOT(X509_digest(ddocSigInfo_GetSignersCert(pSigInfo), EVP_sha1(), buf1, (unsigned int*)&l1), ERR_X509_DIGEST); } // debug memset(buf2, 0, sizeof(buf2)); memset(buf3, 0, sizeof(buf3)); pMBuf = ddocSigInfo_GetSignersCert_DigestValue(pSigInfo); RETURN_IF_NULL_PARAM(pMBuf); l2 = sizeof(buf2)-1; encode((const byte*)pMBuf->pMem, ((pMBuf->nLen < l2/2) ? pMBuf->nLen : l2/2), (byte*)buf2, &l2); l2 = sizeof(buf3)-1; encode((const byte*)buf1, l1, (byte*)buf3, &l2); ddocDebug(3, "verifySigCert", "SIG: %s cdig1: %d - %s cdig2: %d - %s - %d", pSigInfo->szId, pMBuf->nLen, buf2, l1, buf3, l2); err = compareByteArrays((const byte*)pMBuf->pMem, pMBuf->nLen, buf1, l1); RETURN_IF_NOT(err == ERR_OK, ERR_WRONG_CERT); err = ReadCertSerialNumber(szOtherSerial, sizeof(szOtherSerial), ddocSigInfo_GetSignersCert(pSigInfo)); ddocDebug(3, "verifySigCert", "SIG: %s signer-cert-serial: %s cert-serial2: %s", pSigInfo->szId, ddocSigInfo_GetSignersCert_IssuerSerial(pSigInfo), szOtherSerial); RETURN_IF_NOT(((err == ERR_OK) && !strcmp(ddocSigInfo_GetSignersCert_IssuerSerial(pSigInfo), szOtherSerial)), ERR_WRONG_CERT); // check key usage pCert = ddocSigInfo_GetSignersCert(pSigInfo); if(!ddocCertCheckKeyUsage(pCert, KUIDX_NON_REPUDIATION)) { ddocDebug(1, "verifySigCert", "SIG: %s cert has no non-repudiation key usage", pSigInfo->szId); SET_LAST_ERROR(ERR_SIGNERS_CERT_NON_REPU); return ERR_SIGNERS_CERT_NON_REPU; } else ddocDebug(3, "verifySigCert", "SIG: %s cert has non-repudiation key usage", pSigInfo->szId); // check cert parts if(pCertID && pCert) { e1 = verifyCertDnPart(pCertID->szIssuerName, "CN", pCert, NID_commonName); if(!err && e1) err = e1; e1 = verifyCertDnPart(pCertID->szIssuerName, "C", pCert, NID_countryName); if(!err && e1) err = e1; e1 = verifyCertDnPart(pCertID->szIssuerName, "O", pCert, NID_organization); if(!err && e1) err = e1; e1 = verifyCertDnPart(pCertID->szIssuerName, "OU", pCert, NID_organizationUnit); if(!err && e1) err = e1; } return err; } //============================================================ // Verifies this signature // pSigDoc - signed doc data // pSigInfo - signature info object // signerCA - direct signer CA certs filename // szDateFile - name of the digidoc file // bUseCA - use CA certs or not 1/0 // from original file and use it for hash function. // This is usefull if the file has been generated by // another library and possibly formats these elements // differently. //============================================================ EXP_OPTION int verifySignatureInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const char* signerCA, const char* szDataFile, int bUseCA) { int err = ERR_OK; int j, k; X509* cert = NULL; DocInfo* pDocInfo = NULL; DataFile* pDf = NULL; DigiDocMemBuf *pMBuf1 = 0, *pMBuf2 = 0; RETURN_IF_NULL_PARAM(pSigInfo); clearErrors(); pMBuf1 = ddocDigestValue_GetDigestValue(pSigInfo->pSigInfoRealDigest); RETURN_IF_NULL_PARAM(pMBuf1); pMBuf2 = ddocSigInfo_GetSignatureValue_Value((SignatureInfo*)pSigInfo); RETURN_IF_NULL_PARAM(pMBuf2); err = verifyEstIDSignature((const byte*)pMBuf1->pMem, pMBuf1->nLen, DIGEST_SHA1, (byte*)pMBuf2->pMem, pMBuf2->nLen, ddocSigInfo_GetSignersCert(pSigInfo)); if(err != ERR_OK) err = ERR_SIGNATURE; if(err == ERR_OK) { k = getCountOfDocInfos(pSigInfo); ddocDebug(4, "verifySignatureInfo", "DFs: %d", k); for(j = 0; (err == ERR_OK) && (j < k); j++) { pDocInfo = getDocInfo(pSigInfo, j); RETURN_IF_NULL(pDocInfo); ddocDebug(4, "verifySignatureInfo", "DocInfo: %s", pDocInfo->szDocId); pDf = getDataFileWithId(pSigDoc, pDocInfo->szDocId); RETURN_IF_NULL(pDf); ddocDebug(4, "verifySignatureInfo", "DF: %s", pDf->szId); err = verifySigDocDigest(pSigDoc, pSigInfo, pDocInfo, szDataFile); ddocDebug(4, "verifySignatureInfo", "DF: %s verify: %d", pDf->szId, err); if(err == ERR_OK) err = verifySigDocMimeDigest(pSigDoc, pSigInfo, pDocInfo, NULL); } } if(err == ERR_OK) err = verifySigDocSigPropDigest(pSigInfo); if(err == ERR_OK) { err = verifySigCert(pSigInfo); } if(err == ERR_OK) { cert = getSignCertData(pSigInfo); // VS: ver 2.2.4 - removed this check as OCSP check is sufficient //if(err == ERR_OK) // err = isCertValid(cert, convertStringToTimeT(pSigDoc, pSigInfo->szTimeStamp)); if(bUseCA && (err == ERR_OK)) err = isCertSignedBy(cert, signerCA); } if ( err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // Verifies the whole document, but returns on first error // Use the functions defined earlier to verify all contents // step by step. // pSigDoc - signed doc data // //============================================================ EXP_OPTION int verifySigDoc(const SignedDoc* pSigDoc, const char* signerCA, const char** caFiles, const char* caPath, const char* notCert, const char* szDataFile, int bUseCA) { SignatureInfo* pSigInfo; int i, d, err = ERR_OK; RETURN_IF_NULL_PARAM(pSigDoc); d = getCountOfSignatures(pSigDoc); for(i = 0; i < d; i++) { pSigInfo = getSignature(pSigDoc, i); err = verifySignatureInfo(pSigDoc, pSigInfo, signerCA, szDataFile, bUseCA); RETURN_IF_NOT(err == ERR_OK, err); err = verifyNotaryInfo(pSigDoc, pSigInfo, pSigInfo->pNotary, caFiles, caPath, notCert); RETURN_IF_NOT(err == ERR_OK, err); } return err; } //============================================================ // Verifies the certificates signed attributes // pNotInfo - notary info object //============================================================ EXP_OPTION int verifyNotCert(const SignatureInfo* pSigInfo, const NotaryInfo* pNotInfo) { int err = ERR_OK; int l1; char szOtherSerial[100]; byte buf1[DIGEST_LEN+2]; CertID* pCertID; DigiDocMemBuf* pMBuf; X509* pCert = 0; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pNotInfo); pCertID = ddocSigInfo_GetCertIDOfType((SignatureInfo*)pSigInfo, CERTID_TYPE_RESPONDERS_CERTID); RETURN_IF_NOT(pCertID, ERR_WRONG_CERT); pMBuf = ddocCertID_GetDigestValue(pCertID); RETURN_IF_NULL(pMBuf); l1 = sizeof(buf1); ddocDebug(9, "verifyNotCert", "ddocSigInfo_GetOCSPRespondersCert start"); pCert = ddocSigInfo_GetOCSPRespondersCert(pSigInfo); RETURN_IF_NOT(pCert, ERR_WRONG_CERT); if(pNotInfo->szDigestType!=NULL){ if(!strcmp(pNotInfo->szDigestType,DIGEST_SHA256_NAME)){ RETURN_IF_NOT(X509_digest(pCert, EVP_sha256(), buf1, (unsigned int*)&l1), ERR_X509_DIGEST); } else { RETURN_IF_NOT(X509_digest(pCert, EVP_sha1(), buf1, (unsigned int*)&l1), ERR_X509_DIGEST); } }else{ RETURN_IF_NOT(X509_digest(pCert, EVP_sha1(), buf1, (unsigned int*)&l1), ERR_X509_DIGEST); } err = compareByteArrays((const byte*)pMBuf->pMem, pMBuf->nLen, buf1, l1); RETURN_IF_NOT(err == ERR_OK, ERR_WRONG_CERT); err = ReadCertSerialNumber(szOtherSerial, sizeof(szOtherSerial), ddocSigInfo_GetOCSPRespondersCert(pSigInfo)); RETURN_IF_NOT(err == ERR_OK, err); RETURN_IF_NOT(!strcmp(ddocCertID_GetIssuerSerial(pCertID), szOtherSerial), ERR_WRONG_CERT); return ERR_OK; } //-------------------------------------------------- // Sets digest algorithm type object // type - SHA1 //-------------------------------------------------- X509_ALGOR* setCIDAlgorithm(const EVP_MD * type) { X509_ALGOR* alg = NULL; int nid; alg = X509_ALGOR_new(); RETURN_OBJ_IF_NULL(alg, 0); if((alg->parameter == NULL) || (alg->parameter->type != V_ASN1_NULL)) { ASN1_TYPE_free(alg->parameter); alg->parameter=ASN1_TYPE_new(); RETURN_OBJ_IF_NULL(alg->parameter, NULL); alg->parameter->type=V_ASN1_NULL; } ASN1_OBJECT_free(alg->algorithm); if ((nid = EVP_MD_type(type)) != NID_undef) { alg->algorithm=OBJ_nid2obj(nid); } return alg; } //-------------------------------------------------- // Sets signature algorithm type object // type - RSA+SHA1 //-------------------------------------------------- X509_ALGOR* setSignAlgorithm(const EVP_MD * type) { X509_ALGOR* alg; //int nid; alg = X509_ALGOR_new(); RETURN_OBJ_IF_NULL(alg, NULL); if((alg->parameter == NULL) || (alg->parameter->type != V_ASN1_NULL)) { ASN1_TYPE_free(alg->parameter); alg->parameter=ASN1_TYPE_new(); RETURN_OBJ_IF_NULL(alg->parameter, 0); alg->parameter->type=V_ASN1_NULL; } ASN1_OBJECT_free(alg->algorithm); /*if ((nid = EVP_MD_type(type)) != NID_undef) { alg->algorithm=OBJ_nid2obj(nid); }*/ alg->algorithm = OBJ_nid2obj(EVP_MD_pkey_type(type)); return alg; } #if OPENSSL_VERSION_NUMBER < 0x10010000L //-------------------------------------------------- // Helper function. Converts Notary info to an OCSP // response structure. Used in verify and file writing // functions // pNotInfo - NotaryInfo object // notCert - OCSP responder certificate // pBasResp - pointer to a pointer of the new response structure //-------------------------------------------------- int notary2ocspBasResp(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo, X509* notCert, OCSP_BASICRESP** pBasResp) { OCSP_SINGLERESP * single = 0; SignatureInfo* pSigInfo; CertID* pCertID; CertValue* pCertVal; // ASN1_GENERALIZEDTIME *tp = NULL; int err = ERR_OK; const DigiDocMemBuf *pMBuf; DigiDocMemBuf mbuf1; const char *p1 = NULL; mbuf1.pMem = 0; mbuf1.nLen = 0; RETURN_IF_NULL_PARAM(notCert); // new basic response *pBasResp = OCSP_BASICRESP_new(); RETURN_IF_NULL(*pBasResp); str2asn1time(pSigDoc, pNotInfo->timeProduced, (*pBasResp)->tbsResponseData->producedAt); p1 = ddocNotInfo_GetResponderId_Type(pNotInfo); RETURN_IF_NULL(p1); if(!strcmp(p1, RESPID_NAME_VALUE)) { (*pBasResp)->tbsResponseData->responderId->type = V_OCSP_RESPID_NAME; (*pBasResp)->tbsResponseData->responderId->value.byName = X509_NAME_dup(X509_get_subject_name(notCert)); } else { (*pBasResp)->tbsResponseData->responderId->type = V_OCSP_RESPID_KEY; (*pBasResp)->tbsResponseData->responderId->value.byKey = ASN1_OCTET_STRING_new(); pMBuf = ddocNotInfo_GetResponderId(pNotInfo); RETURN_IF_NULL(pMBuf); ASN1_OCTET_STRING_set((*pBasResp)->tbsResponseData->responderId->value.byKey, (unsigned char*)pMBuf->pMem, pMBuf->nLen); } // new single response single = OCSP_SINGLERESP_new(); single->certStatus->type = V_OCSP_CERTSTATUS_GOOD; single->certStatus->value.good = ASN1_NULL_new(); single->certId->hashAlgorithm = setCIDAlgorithm(EVP_sha1()); err = ddocNotInfo_GetIssuerNameHash(pNotInfo, &mbuf1); ASN1_OCTET_STRING_set(single->certId->issuerNameHash, (unsigned char*)mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); err = ddocNotInfo_GetIssuerKeyHash(pNotInfo, &mbuf1); ASN1_OCTET_STRING_set(single->certId->issuerKeyHash, (unsigned char*)mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); pSigInfo = ddocGetSignatureForNotary(pSigDoc, pNotInfo); RETURN_IF_NULL(pSigInfo); pCertID = ddocSigInfo_GetCertIDOfType(pSigInfo, CERTID_TYPE_RESPONDERS_CERTID); if(pCertID) { ddocDebug(9, "notary2ocspBasResp", "pCertID"); ddocMemAppendData(&mbuf1, ddocCertID_GetIssuerSerial(pCertID), -1); } else { ddocDebug(9, "notary2ocspBasResp", "no pCertID"); pCertVal = ddocCertValueList_GetCertValueOfType(pSigInfo->pCertValues, CERTID_VALUE_RESPONDERS_CERT); ddocDebug(9, "notary2ocspBasResp", "ddocCertValueList_GetCertValueOfType"); if(pCertVal) { ddocMemSetLength(&mbuf1, 100); ReadCertSerialNumber((char*)mbuf1.pMem, mbuf1.nLen-1, pCertVal->pCert); } } ASN1_INTEGER_set(single->certId->serialNumber, atol((const char*)mbuf1.pMem)); ddocMemBuf_free(&mbuf1); err = ddocNotInfo_GetThisUpdate(pNotInfo, &mbuf1); if(mbuf1.pMem && strlen((char*)mbuf1.pMem)) str2asn1time(pSigDoc, (char*)mbuf1.pMem, single->thisUpdate); ddocMemBuf_free(&mbuf1); err = ddocNotInfo_GetNextUpdate(pNotInfo, &mbuf1); if(mbuf1.pMem && strlen((char*)mbuf1.pMem)) str2asn1time(pSigDoc, (char*)mbuf1.pMem, single->nextUpdate); ddocMemBuf_free(&mbuf1); sk_OCSP_SINGLERESP_push((*pBasResp)->tbsResponseData->responses, single); // add nonce err = ddocNotInfo_GetOcspRealDigest(pSigDoc, pNotInfo, &mbuf1); if(!err) err = OCSP_basic_add1_nonce((*pBasResp), (unsigned char*)mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); if (err == ERR_LIB_NONE){ err = ERR_OK; // set signature (*pBasResp)->signatureAlgorithm = setSignAlgorithm(EVP_sha1()); err = ddocNotInfo_GetOcspSignatureValue(pNotInfo, &mbuf1); ASN1_OCTET_STRING_set((*pBasResp)->signature, (byte*)mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); } else { OCSP_BASICRESP_free(*pBasResp); // PR. avoid double free *pBasResp = 0; SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_NONCE); } ddocDebug(9, "notary2ocspBasResp", "end"); // checkErrors(); return ERR_OK; } #endif //-------------------------------------------------- // Verfies NotaryInfo signature // pSigDoc - signed doc object // pNotInfo - NotaryInfo object // caFiles - array of CA file names terminated with NULL // CApath - path to (directory) all certs // notCertFile - Notary (e.g. OCSP responder) cert file //-------------------------------------------------- EXP_OPTION int verifyNotaryInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const NotaryInfo* pNotInfo, const char** caFiles, const char *CApath, const char* notCertFile) { X509** caCerts; X509* notCert = NULL; int err = ERR_OK, l1, i; RETURN_IF_NULL_PARAM(caFiles); RETURN_IF_NULL_PARAM(CApath); RETURN_IF_NULL_PARAM(notCertFile); // find the chain length // VS - ver 1.67 for(l1 = 0; caFiles && caFiles[l1]; l1++); caCerts = (X509**)malloc(sizeof(void*) * (l1 + 1)); RETURN_IF_BAD_ALLOC(caCerts); memset(caCerts, 0, sizeof(void*) * (l1 + 1)); for(i = 0; i < l1; i++) { err = ReadCertificate(&(caCerts[i]),caFiles[i]); if (err != ERR_OK) { err = ERR_CERT_READ; goto cleanup; } } err = ReadCertificate(¬Cert, notCertFile); if (err != ERR_OK) { err = ERR_CERT_READ; goto cleanup; } err = verifyNotaryInfoCERT(pSigDoc, pSigInfo, pNotInfo, (const X509**)caCerts, CApath, notCert); if (err != ERR_OK) SET_LAST_ERROR(err); // cleanup cleanup: if(notCert) X509_free(notCert); for(i = 0; i < l1; i++) if(caCerts[i]) X509_free(caCerts[i]); free(caCerts); return err; } //-------------------------------------------------- // Setup X509 store for verification purposes // CApath - directory of all certs // CA1file - highest root cert // CA2file - actual parent cert //-------------------------------------------------- int setup_verifyCERT(X509_STORE **newX509_STORE, const char *CApath, const X509** certs) { X509_STORE *store; X509_LOOKUP *lookup; int i; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; if((store = X509_STORE_new()) == NULL) goto end; lookup = X509_STORE_add_lookup(store,X509_LOOKUP_file()); if (lookup == NULL) goto end; for(i = 0; certs && certs[i]; i++) { ddocDebug(3, "setup_verifyCERT", "add cert: %d cert: %s", i, (certs[i] ? "OK" : "NULL")); ddocCertGetSubjectDN((X509*)certs[i], &mbuf1); ddocDebug(3, "setup_verifyCERT", "add cert: %d cert: %s", i, (char*)mbuf1.pMem); X509_STORE_add_cert(store, (X509*)certs[i]); ddocMemBuf_free(&mbuf1); } ddocDebug(3, "setup_verifyCERT", "certs added"); lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()); if (lookup == NULL) goto end; if (CApath) { ddocDebug(3, "setup_verifyCERT", "lookup dir: %s", CApath); if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) { //BIO_printf(bp, "Error loading directory %s\n", CApath); goto end; } } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); *newX509_STORE = store; ERR_clear_error(); return ERR_OK; end: if (store) X509_STORE_free(store); SET_LAST_ERROR_RETURN_CODE(ERR_CERT_STORE_READ); } int verifyOcspCertId(OCSP_RESPONSE* pResp, X509* pCert, X509* pCaCert) { OCSP_RESPBYTES *rb = NULL; OCSP_BASICRESP *br = NULL; OCSP_RESPDATA *rd = NULL; OCSP_SINGLERESP *single = NULL; const OCSP_CERTID *cid = NULL; int err = ERR_OK; DigiDocMemBuf mbuf1, mbuf2, mbuf3; ASN1_OCTET_STRING *issuerNameHash = NULL, *issuerKeyHash = NULL; ASN1_INTEGER *serialNumber = NULL; RETURN_IF_NULL_PARAM(pResp); RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pCaCert); mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; mbuf3.pMem = 0; mbuf3.nLen = 0; if((br = OCSP_response_get1_basic(pResp)) == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_BASIC_RESP); ddocCertGetSubjectDN(pCert, &mbuf2); ddocCertGetSubjectDN(pCaCert, &mbuf3); ddocDebug(4, "verifyOcspCertId", "for cert: %ld, cn: %s, ca: %s", X509_get_serialNumber(pCert), mbuf2.pMem, mbuf3.pMem); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); if(OCSP_resp_count(br) != 1) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_ONE_RESPONSE); single = OCSP_resp_get0(br, 0); RETURN_IF_NULL(single); cid = OCSP_SINGLERESP_get0_id(single); RETURN_IF_NULL(cid); OCSP_id_get0_info(&issuerNameHash, NULL, &issuerKeyHash, &serialNumber, (OCSP_CERTID*)cid); // check serial number if(ASN1_INTEGER_cmp(serialNumber, X509_get_serialNumber(pCert)) != 0) { ddocDebug(4, "verifyOcspCertId", "Looking for cert-nr: %ld buf found %ld", X509_get_serialNumber(pCert), ASN1_INTEGER_get(serialNumber)); return ERR_WRONG_CERT; } // check issuer name hash err = ddocCertGetIssuerNameDigest(pCert, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); err = compareByteArrays((byte*)mbuf1.pMem, (unsigned int)mbuf1.nLen, issuerNameHash->data, issuerNameHash->length); mbuf2.pMem = issuerNameHash->data; mbuf2.nLen = issuerNameHash->length; ddocBin2Hex(&mbuf2, &mbuf3); mbuf2.pMem = 0; mbuf2.nLen = 0; ddocBin2Hex(&mbuf1, &mbuf2); ddocDebug(4, "verifyOcspCertId", "Looking for name-hash: %s found %s RC: %d", (char*)mbuf2.pMem, (char*)mbuf3.pMem, err); ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); RETURN_IF_NOT(err == ERR_OK, ERR_WRONG_CERT); // check issuer key hash err = ddocCertGetPubkeyDigest(pCaCert, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); err = compareByteArrays((byte*)mbuf1.pMem, (unsigned int)mbuf1.nLen, issuerKeyHash->data, issuerKeyHash->length); mbuf2.pMem = issuerKeyHash->data; mbuf2.nLen = issuerKeyHash->length; ddocBin2Hex(&mbuf2, &mbuf3); mbuf2.pMem = 0; mbuf2.nLen = 0; ddocBin2Hex(&mbuf1, &mbuf2); ddocDebug(4, "verifyOcspCertId", "Looking for key-hash: %s found %s RC: %d", (char*)mbuf2.pMem, (char*)mbuf3.pMem, err); ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); return err; } //-------------------------------------------------- // Verfies NotaryInfo signature // pSigDoc - signed doc object // pNotInfo - NotaryInfo object // caCerts - CA certificate pointer array terminated with NULL // CApath - path to (directory) all certs // notCertFile - Notary (e.g. OCSP responder) cert file //-------------------------------------------------- EXP_OPTION int verifyNotaryInfoCERT(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const NotaryInfo* pNotInfo, const X509** caCerts, const char *CApath, const X509* notCert) { return verifyNotaryInfoCERT2(pSigDoc, pSigInfo, pNotInfo, caCerts, CApath, notCert, NULL); } //-------------------------------------------------- // Verfies NotaryInfo signature // pSigDoc - signed doc object // pNotInfo - NotaryInfo object // caCerts - CA certificate pointer array terminated with NULL // CApath - path to (directory) all certs // notCertFile - Notary (e.g. OCSP responder) cert file // pSigCa - signers ca cert //-------------------------------------------------- EXP_OPTION int verifyNotaryInfoCERT2(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const NotaryInfo* pNotInfo, const X509** caCerts, const char *CApath, const X509* notCert, const X509* pSigCa) { X509_STORE *store; OCSP_RESPONSE* pResp = NULL; OCSP_BASICRESP* bs = NULL; ASN1_OCTET_STRING *signature = NULL; STACK_OF(X509)* ver_certs = NULL; int err = ERR_OK, l1; X509 *certNotaryDirectCA = 0, *pCert = 0, *pCaCert = 0; DigiDocMemBuf mbuf1; char buf1[100], buf3[500]; time_t tProdAt; mbuf1.pMem = 0; mbuf1.nLen = 0; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pNotInfo); RETURN_IF_NULL_PARAM(notCert); RETURN_IF_NULL_PARAM(caCerts); // find the chain length for(l1 = 0; caCerts && caCerts[l1]; l1++); if(l1 < 1) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_INVALID); certNotaryDirectCA = (X509*)caCerts[l1-1]; // do the signature values match? // not to be checked in format 1.4 if(err) return err; // now create an OCSP object and check its validity // VS - ver 1.66 pResp = ddocNotInfo_GetOCSPResponse_Value(pNotInfo); if(!pResp) { ddocDebug(3, "verifyNotaryInfoCERT", "OCSP missing"); SET_LAST_ERROR_RETURN_CODE(ERR_NO_OCSP); } // debug //WriteOCSPResponse("test2.resp", pResp); if((setup_verifyCERT(&store, CApath, caCerts)) == ERR_OK) { ddocNotInfo_GetProducedAt_timet(pNotInfo, &tProdAt); X509_VERIFY_PARAM_set_time(X509_STORE_get0_param(store), tProdAt); X509_STORE_set_flags(store, X509_V_FLAG_USE_CHECK_TIME); // new basic response // create OCSP basic response // in version 1.0 we calculated digest over tbsResponseData bs = OCSP_response_get1_basic(pResp); if (!bs) err = ERR_OCSP_WRONG_RESPID; if (err == ERR_OK) { ver_certs = sk_X509_new_null(); if (ver_certs) { ReadCertSerialNumber(buf1, sizeof(buf1), (X509*)notCert); ddocCertGetSubjectDN((X509*)notCert, &mbuf1); sk_X509_push(ver_certs, notCert); ddocDebug(3, "verifyNotaryInfoCERT", "OCSP verify err: %d, err1: %d format: %s", err, pSigInfo->nErr1, pSigDoc->szFormatVer); // fix invalid padding flag on ddoc 1.0 signatures signature = (ASN1_OCTET_STRING*)OCSP_resp_get0_signature(bs); if((!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) || (signature->flags & 0x07)) { ddocDebug(3, "verifyNotaryInfoCERT", "Reset ocsp flag %d", signature->flags); signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); } err = OCSP_basic_verify(bs, ver_certs, store, OCSP_NOCHECKS); ddocDebug(3, "verifyNotaryInfoCERT", "OCSP verify: %d, not cet: %s cn: %s", err, buf1, mbuf1.pMem); if(err == ERR_LIB_NONE) { err = ERR_OK; } else { err = ERR_NOTARY_SIG_MATCH; SET_LAST_ERROR(err); } // cleanup sk_X509_free(ver_certs); } if(bs) OCSP_BASICRESP_free(bs); } X509_STORE_free(store); } else { err = ERR_CERT_STORE_READ; SET_LAST_ERROR(err); } if(pSigInfo->nErr1 == ERR_VER_1_0) ((SignatureInfo*)pSigInfo)->nErr1 = 0; ddocDebug(3, "verifyNotaryInfoCERT", "OCSP verify final: %d, not cet: %s cn: %s", err, buf1, mbuf1.pMem); ddocMemBuf_free(&mbuf1); if(err == ERR_OK) { ddocDebug(9, "verifyNotaryInfoCERT", "ddocSigInfo_GetOCSPRespondersCert start"); //if(!notCert) // ??? notCert = ddocSigInfo_GetOCSPRespondersCert(pSigInfo); ddocDebug(9, "verifyNotaryInfoCERT", "ddocSigInfo_GetOCSPRespondersCert end"); if(notCert && pNotInfo->timeProduced) { // VS: ver 1.66 ddocDebug(9, "verifyNotaryInfoCERT", "notCert exists"); err = isCertValid((X509*)notCert, convertStringToTimeT(pSigDoc, pNotInfo->timeProduced)); //crash? if (err != ERR_OK) SET_LAST_ERROR(err); } else { ddocDebug(9, "verifyNotaryInfoCERT", "notCert invalid"); err = ERR_CERT_INVALID; SET_LAST_ERROR(err); } if(err == ERR_OK) { err = isCertSignedByCERT(notCert, certNotaryDirectCA); if (err != ERR_OK) SET_LAST_ERROR(err); } if(err == ERR_OK) { err = verifyNotCert(pSigInfo, pNotInfo); if (err != ERR_OK) SET_LAST_ERROR(err); } if(err == ERR_OK) { err = verifyNotaryDigest(pSigDoc, pNotInfo); if (err != ERR_OK && err != ERR_OCSP_NONCE_SIGVAL_NOMATCH) SET_LAST_ERROR(ERR_NOTARY_SIG_MATCH); } if(err == ERR_OK) { pCert = ddocSigInfo_GetSignersCert(pSigInfo); pCaCert = (pSigCa != NULL) ? (X509*)pSigCa : certNotaryDirectCA; err = verifyOcspCertId(pResp, pCert, pCaCert); if (err != ERR_OK) SET_LAST_ERROR(err); } if(err == ERR_OK) { ddocDebug(3, "verifyNotaryInfoCERT", "Not: %s time-ocsp: %s time-xml: %s", pNotInfo->szId, (pNotInfo->timeProduced ? pNotInfo->timeProduced : ""), (pNotInfo->szProducedAt ? pNotInfo->szProducedAt : "")); if(pNotInfo->timeProduced && pNotInfo->szProducedAt && strcmp(pNotInfo->timeProduced, pNotInfo->szProducedAt) && strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { err = ERR_OCSP_MALFORMED; SET_LAST_ERROR(err); } } } if(pResp) OCSP_RESPONSE_free(pResp); ddocDebug(3, "verifyNotaryInfoCERT", "Ocsp verify: %d", err); return err; } //-------------------------------------------------- // Verfies NotaryInfo digest // pNotInfo - NotaryInfo object //-------------------------------------------------- EXP_OPTION int verifyNotaryDigest(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo) { int err, l1, l2, l3; byte buf1[DIGEST_LEN256+2], buf2[40], buf3[40]; const DigiDocMemBuf *pMBuf; DigiDocMemBuf mbuf2; SignatureInfo* pSigInf = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; l1 = sizeof(buf1); err = calculateNotaryInfoDigest(pSigDoc, pNotInfo, buf1, &l1); RETURN_IF_NOT(err == ERR_OK, err); pMBuf = ddocNotInfo_GetOcspDigest(pNotInfo); RETURN_IF_NULL(pMBuf); err = compareByteArrays(buf1, l1, (byte*)pMBuf->pMem, pMBuf->nLen); RETURN_IF_NOT(err == ERR_OK, err); // verify ocsp nonce = signature value digest pSigInf = ddocGetSignatureForNotary(pSigDoc, pNotInfo); RETURN_IF_NULL(pSigInf); pMBuf = ddocSigInfo_GetSignatureValue_Value(pSigInf); RETURN_IF_NULL(pMBuf); l1 = sizeof(buf1); err = calculateDigest((const byte*)pMBuf->pMem, pMBuf->nLen, DIGEST_SHA1, (byte*)buf1, &l1); RETURN_IF_NOT(err == ERR_OK, err); err = ddocNotInfo_GetOcspRealDigest(pSigDoc, pNotInfo, &mbuf2); RETURN_IF_NOT(err == ERR_OK, err); err = compareByteArrays(buf1, l1, (byte*)mbuf2.pMem, mbuf2.nLen); // debug output l2 = sizeof(buf2); l3 = sizeof(buf3); encode((const byte*)buf1, l1, (byte*)buf2, &l2); encode((const byte*)mbuf2.pMem, mbuf2.nLen, (byte*)buf3, &l3); ddocDebug(3, "verifyNotaryDigest", "Signature: %s Notary: %s sig-val-dig: %s nonce: %s verify: %d", pSigInf->szId, pNotInfo->szId, buf2, buf3, err); RETURN_IF_NOT(err == ERR_OK, ERR_OCSP_NONCE_SIGVAL_NOMATCH); return ERR_OK; } //============================================================ // Verifies the whole document, but returns on first error // Use the functions defined earlier to verify all contents // step by step. // pSigDoc - signed doc data // signerCA - direct signer CA certs filename // szDateFile - name of the digidoc file // bUseCA - use CA certs or not 1/0 //============================================================ EXP_OPTION int verifySigDocCERT(const SignedDoc* pSigDoc, const void* signerCA, const X509** caCerts, const char* caPath, const X509* notCert, const char* szDataFile, int bUseCA) { SignatureInfo* pSigInfo; int i, d, err = ERR_OK; RETURN_IF_NULL_PARAM(pSigDoc); //assert(pSigDoc); d = getCountOfSignatures(pSigDoc); for(i = 0; i < d; i++) { pSigInfo = getSignature(pSigDoc, i); err = verifySignatureInfoCERT(pSigDoc, pSigInfo, signerCA, szDataFile, bUseCA); //RETURN_IF_NOT(err == ERR_OK, err); err = verifyNotaryInfoCERT(pSigDoc, pSigInfo, pSigInfo->pNotary, caCerts, caPath, notCert); //RETURN_IF_NOT(err == ERR_OK, err); } return err; } //============================================================ // Verifies this signature // pSigDoc - signed doc data // pSigInfo - signature info object // signerCA - direct signer CA certs filename // szDataFile - provide to read and // from original file and use it for hash function. // This is usefull if the file has been generated by // another library and possibly formats these elements // differently. // bUseCA - use CA certs or not 1/0 //============================================================ EXP_OPTION int verifySignatureInfoCERT(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const void* signerCACert, const char* szDataFile, int bUseCA) { int err = ERR_OK, err2 = ERR_OK; int j, k, i; X509* cert; DocInfo* pDocInfo = NULL; DataFile* pDf = NULL; DigiDocMemBuf *pMBuf1, *pMBuf2; NotaryInfo* pNot = NULL; RETURN_IF_NULL_PARAM(pSigInfo); pMBuf1 = ddocSigInfo_GetSigInfoRealDigest((SignatureInfo*)pSigInfo); RETURN_IF_NULL_PARAM(pMBuf1); pMBuf2 = ddocSigInfo_GetSignatureValue_Value((SignatureInfo*)pSigInfo); RETURN_IF_NULL_PARAM(pMBuf2); ddocDebug(3, "verifySignatureInfoCERT", "Sig: %s, CA: %s", ((pSigInfo && pSigInfo->szId) ? pSigInfo->szId : "NULL"), (signerCACert ? "OK" : "NULL")); if(pSigInfo->szDigestType){ if(!strcmp(pSigInfo->szDigestType,DIGEST_SHA256_NAME)) err = verifyEstIDSignature((const byte*)pMBuf1->pMem, pMBuf1->nLen, DIGEST_SHA256, (byte*)pMBuf2->pMem, pMBuf2->nLen, ddocSigInfo_GetSignersCert(pSigInfo)); else err = verifyEstIDSignature((const byte*)pMBuf1->pMem, pMBuf1->nLen, DIGEST_SHA1, (byte*)pMBuf2->pMem, pMBuf2->nLen, ddocSigInfo_GetSignersCert(pSigInfo)); }else{ err = verifyEstIDSignature((const byte*)pMBuf1->pMem, pMBuf1->nLen, DIGEST_SHA1, (byte*)pMBuf2->pMem, pMBuf2->nLen, ddocSigInfo_GetSignersCert(pSigInfo));} //RETURN_IF_NOT(err == ERR_OK, ERR_SIGNATURE); // check that this signature signs all DataFiles for(i = 0; i < getCountOfDataFiles(pSigDoc); i++) { pDf = getDataFile(pSigDoc, i); k = 0; // not found yet for(j = 0; j < getCountOfDocInfos(pSigInfo); j++) { pDocInfo = getDocInfo(pSigInfo, j); ddocDebug(4, "verifySignatureInfoCERT", "Check sig \'%s\' of doc: \'%s\'", pSigInfo->szId, pDocInfo->szDocId); if(!strcmp(pDocInfo->szDocId, pDf->szId)) { k = 1; // found break; } } if(!k) { //ddocDebug(1, "verifySignatureInfoCERT", "Signature \'%s\' does not sign doc: \'%s\'", pSigInfo->szId, pDocInfo->szDocId); err = ERR_DOC_DIGEST; SET_LAST_ERROR(err); //return err; } } // verify DataFile hashes k = getCountOfDocInfos(pSigInfo); ddocDebug(4, "verifySignatureInfoCERT", "DFs: %d", k); for(j = 0; (err == ERR_OK) && (j < k); j++) { pDocInfo = getDocInfo(pSigInfo, j); ddocDebug(4, "verifySignatureInfoCERT", "Verify doc: %d - \'%s\'", j, pDocInfo->szDocId); RETURN_IF_NULL(pDocInfo); pDf = getDataFileWithId(pSigDoc, pDocInfo->szDocId); SET_LAST_ERROR_RETURN_IF_NOT(pDf, ERR_BAD_DATAFILE_COUNT, ERR_BAD_DATAFILE_COUNT); //RETURN_IF_NULL(pDf); err = verifySigDocDigest(pSigDoc, pSigInfo, pDocInfo, szDataFile); //ddocDebug(4, "verifySignatureInfoCERT", "Verify doc: %s - %d", pDocInfo->szDocId, err); //RETURN_IF_NOT(err == ERR_OK, err); if(!err) err = verifySigDocMimeDigest(pSigDoc, pSigInfo, pDocInfo, NULL); //RETURN_IF_NOT(err == ERR_OK, err); } err2 = verifySigDocSigPropDigest(pSigInfo); if(!err) err = err2; err2 = verifySigCert(pSigInfo); if(!err) err = err2; cert = getSignCertData(pSigInfo); //#23789 - kontrollida allkirjastaja kehtivust OCSP producedAt ajal pNot = getNotaryWithSigId(pSigDoc, pSigInfo->szId); if(pNot && pNot->timeProduced) { err = isCertValid(cert, convertStringToTimeT(pSigDoc, pNot->timeProduced)); } if(bUseCA) err2 = isCertSignedByCERT((const X509*)cert, (const X509*)signerCACert); if(!err) err = err2; return err; } //-------------------------------------------------- // Checks if this element tag contains the // required attributes with the given values // data - input data, XML tags data (not content but the attributes) // nAttrs - number of attributes to check // attNames - array of attribute names // attValues - array of attribute values // returns 0 if OK (all atributes found or none desired) //-------------------------------------------------- int checkAttrs(const char* data, int nAttrs, const char** attNames, const char** attValues) { int remains = 0, i; char *pTmp1 = 0, *pTmp2 = 0; RETURN_IF_NULL_PARAM(data); if(nAttrs) { RETURN_IF_NULL_PARAM(attNames); RETURN_IF_NULL_PARAM(attValues); remains = nAttrs; // must find nAttrs values for(i = 0; i < nAttrs; i++) { RETURN_IF_NULL(attNames[i]); RETURN_IF_NULL(attValues[i]); if((pTmp1 = strstr(data, attNames[i])) != 0) { if((pTmp2 = strstr(pTmp1, "\"")) != 0) { if(!strncmp(pTmp2+1, attValues[i], strlen(attValues[i]))) remains--; // found one } } } } if (remains == 0) return ERR_OK; else return remains; } char* findString(char* mainBuf, char* search) { char* pTmp = NULL; // first find in the latest 2KB pTmp = strstr(mainBuf+2048, search); // if not found check the previous buffer // as well because the tag could have been broken // between two buffer borders if(!pTmp) pTmp = strstr(mainBuf, search); return pTmp; } //-------------------------------------------------- // Finds the contents of a given XML tag // in the given file. // data - buffer for tag content data (caller must deallocate) // tagName - tag name to search // nAttrs - number of attributes to check // attNames - array of attribute names // attValues - array of attribute values // withTags - 1 if include tags themselves, else 0 // returns 0 if tag was found and data read. //-------------------------------------------------- int readTagContents(char** data, const char* fileName, const char* tagName, int nAttrs, const char** attNames, const char** attValues, int withTags) { int err = ERR_OK, status, len, level; FILE *hFile = 0; char *pTmp1 = 0, *pTmp2 = 0, *pTmp3 = 0, *pBegin = 0, *pData = NULL; char buf1[4097], buf2[100]; RETURN_IF_NULL_PARAM(data); RETURN_IF_NULL_PARAM(fileName); RETURN_IF_NULL_PARAM(tagName); RETURN_IF_NULL_PARAM(attNames); RETURN_IF_NULL_PARAM(attValues); if((hFile = fopen(fileName, "rb")) != 0) { status = 0; // nothing found yet level = 0; memset(buf1, 0, sizeof(buf1)); // allways load the second half of the buffer // warning - assignment in conditional expression -> yes but the code seems clearer this way! while((len = fread(buf1+2048, 1, 2048, hFile)) && status < 2) { switch(status) { case 0: // find "); if(pTmp2) { *pTmp2 = 0; err = checkAttrs(pTmp1, nAttrs, attNames, attValues); *pTmp2 = '>'; if(!err) { // mark the found tag // in order not to later mistake this // for a new level. Take also buffer moving // in account pBegin = pTmp1-2048; status = 1; // now search for... if(withTags) { snprintf(buf2, sizeof(buf2), "", tagName); if((pTmp3 = strstr(pTmp1, buf2)) != 0) *(pTmp3+strlen(buf2)) = 0; len = strlen(pTmp1)+1; pData = (char*)malloc(len); memset(pData, 0, len); RETURN_IF_BAD_ALLOC(pData); strncpy(pData, pTmp1, len); if(pTmp3) { *data = pData; status = 2; } } else { pTmp2++; // first byte of content data // find snprintf(buf2, sizeof(buf2), "", tagName); if((pTmp3 = strstr(pTmp1, buf2)) != 0) *pTmp3 = 0; len = strlen(pTmp2); pData = (char*)malloc(len+1); RETURN_IF_BAD_ALLOC(pData); strncpy(pData, pTmp2, len); if(pTmp3) { *data = pData; status = 2; } } // else } // if(!err) else pTmp1 = strstr(pTmp2, buf2); } // if(pTmp2) else pTmp1++; } // if(pTmp1) break; case 1: snprintf(buf2, sizeof(buf2), "", tagName); pTmp3 = findString(buf1, buf2); // if the found end-tag is fully in the // previous buffer then if cannot be the right // one because I would have noticed it in // the last step if((pTmp3+strlen(buf2)) < (buf1+2048)) pTmp3 = NULL; snprintf(buf2, sizeof(buf2), "<%s ", tagName); pTmp1 = findString(buf1, buf2); if(pTmp1 && pTmp1 > pBegin && !pTmp3) level++; if(pTmp3 && !level) { if(withTags) { snprintf(buf2, sizeof(buf2), "", tagName); *(pTmp3 + strlen(buf2)) = 0; } else *pTmp3 = 0; *data = pData; status = 2; } if(pTmp3 && level > 0) level--; len = strlen(buf1+2048); if(len) { RETURN_IF_NULL(pData); pData = (char*)realloc(pData, strlen(pData)+len+1); strncpy(strchr(pData, 0), buf1+2048, strlen(pData)+len+1); *data = pData; } break; default: break; } memcpy(buf1, buf1+2048, 2048); memset(buf1+2048, 0, 2049); } // while fclose(hFile); } // if(hFile else err = ERR_FILE_READ; return (pData == NULL); } libdigidoc-3.10.5/libdigidoc/DigiDocError.h0000664000372000037200000002525713560273131020065 0ustar travistravis#ifndef __DIGI_DOC_ERROR_H__ #define __DIGI_DOC_ERROR_H__ //================================================== // FILE: DigiDocError.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc error codes and functions // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details.ode // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= //================================================== #ifdef WIN32 #include #endif #ifdef __cplusplus extern "C" { #endif //==========< error codes >======================= #define ERR_OK 0 #define ERR_UNSUPPORTED_DIGEST 1 #define ERR_FILE_READ 2 #define ERR_FILE_WRITE 3 #define ERR_DIGEST_LEN 4 #define ERR_BUF_LEN 5 #define ERR_SIGNATURE_LEN 6 #define ERR_PRIVKEY_READ 7 #define ERR_PUBKEY_READ 8 #define ERR_CERT_READ 9 #define ERR_SIGNEDINFO_CREATE 10 #define ERR_SIGNEDINFO_DATA 11 #define ERR_SIGNEDINFO_FINAL 12 #define ERR_UNSUPPORTED_FORMAT 13 #define ERR_BAD_INDEX 14 #define ERR_TIMESTAMP_DECODE 15 #define ERR_DIGIDOC_PARSE 16 #define ERR_UNSUPPORTED_SIGNATURE 17 #define ERR_CERT_STORE_READ 18 #define ERR_SIGPROP_DIGEST 19 #define ERR_COMPARE 20 #define ERR_DOC_DIGEST 21 #define ERR_MIME_DIGEST 22 #define ERR_SIGNATURE 23 #define ERR_CERT_INVALID 24 #define ERR_OCSP_UNSUCCESSFUL 25 #define ERR_OCSP_UNKNOWN_TYPE 26 #define ERR_OCSP_NO_BASIC_RESP 27 #define ERR_OCSP_WRONG_VERSION 28 #define ERR_OCSP_WRONG_RESPID 29 #define ERR_OCSP_ONE_RESPONSE 30 #define ERR_OCSP_RESP_STATUS 31 #define ERR_OCSP_NO_SINGLE_EXT 32 #define ERR_OCSP_NO_NONCE 33 #define ERR_NOTARY_NO_SIGNATURE 34 #define ERR_NOTARY_SIG_MATCH 35 #define ERR_SIGNERS_CERT_NOT_TRUSTED 36 #define ERR_WRONG_CERT 37 #define ERR_NULL_POINTER 38 #define ERR_NULL_CERT_POINTER 39 #define ERR_NULL_SER_NUM_POINTER 40 #define ERR_NULL_KEY_POINTER 41 #define ERR_EMPTY_STRING 42 #define ERR_BAD_DATAFILE_INDEX 43 #define ERR_BAD_DATAFILE_COUNT 44 #define ERR_BAD_ATTR_COUNT 45 #define ERR_BAD_ATTR_INDEX 46 #define ERR_BAD_SIG_INDEX 47 #define ERR_BAD_SIG_COUNT 48 #define ERR_BAD_ROLE_INDEX 49 #define ERR_BAD_DOCINFO_COUNT 50 #define ERR_BAD_DOCINFO_INDEX 51 #define ERR_BAD_NOTARY_INDEX 52 #define ERR_BAD_NOTARY_ID 53 #define ERR_BAD_NOTARY_COUNT 54 #define ERR_X509_DIGEST 55 #define ERR_CERT_LENGTH 56 #define ERR_PKCS_LIB_LOAD 57 #define ERR_PKCS_SLOT_LIST 58 #define ERR_PKCS_WRONG_SLOT 59 #define ERR_PKCS_LOGIN 60 #define ERR_PKCS_PK 61 #define ERR_PKCS_CERT_LOC 62 #define ERR_PKCS_CERT_DECODE 63 #define ERR_PKCS_SIGN_DATA 64 #define ERR_PKCS_CARD_READ 65 #define ERR_CSP_NO_CARD_DATA 66 #define ERR_CSP_OPEN_STORE 67 #define ERR_CSP_CERT_FOUND 68 #define ERR_CSP_SIGN 69 #define ERR_CSP_NO_HASH_START 70 #define ERR_CSP_NO_HASH 71 #define ERR_CSP_NO_HASH_RESULT 72 #define ERR_CSP_OPEN_KEY 73 #define ERR_CSP_READ_KEY 74 #define ERR_OCSP_SIGN_NOT_SUPPORTED 75 #define ERR_OCSP_SIGN_CSP_NAME 76 #define ERR_CSP_CERT_DECODE 77 #define ERR_OCSP_SIGN_PKCS_NAME 78 #define ERR_OCSP_SIGN_OSLL_CERT 79 #define ERR_OCSP_SIGN 80 #define ERR_CERT_ISSUER 81 #define ERR_OCSP_PKCS12_CONTAINER 82 #define ERR_MODIFY_SIGNED_DOC 83 #define ERR_NOTARY_EXISTS 84 #define ERR_UNSUPPORTED_CERT_SEARCH 85 #define ERR_INCORRECT_CERT_SEARCH 86 #define ERR_BAD_OCSP_RESPONSE_DIGEST 87 #define ERR_LAST_ESTID_CACHED 88 #define ERR_BAD_DATAFILE_XML 89 #define ERR_UNSUPPORTED_VERSION 90 #define ERR_UNSUPPORTED_CHARSET 91 #define ERR_PKCS12_EXPIRED 92 #define ERR_CSP_USER_CANCEL 93 #define ERR_CSP_NODEFKEY_CONTAINER 94 #define ERR_CONNECTION_FAILURE 95 #define ERR_WRONG_URL_OR_PROXY 96 #define ERR_NULL_PARAM 97 #define ERR_BAD_ALLOC 98 #define ERR_CONF_FILE 99 #define ERR_CONF_LINE 100 #define ERR_OCSP_CERT_REVOKED 101 #define ERR_OCSP_CERT_UNKNOWN 102 #define ERR_OCSP_PKCS12_NO_FILE 103 #define ERR_OCSP_PKCS12_NO_PASSWD 104 #define ERR_BAD_DATAFILE_CONTENT_TYPE 105 #define ERR_OCSP_WRONG_URL 106 #define ERR_OCSP_MALFORMED 107 #define ERR_OCSP_INTERNALERR 108 #define ERR_OCSP_TRYLATER 109 #define ERR_OCSP_SIGREQUIRED 110 #define ERR_OCSP_UNAUTHORIZED 111 #define ERR_UNKNOWN_CA 112 // DigiDocEnc errors #define ERR_DENC_ENC_METHOD 113 #define ERR_DENC_ENC_XMLNS 114 #define ERR_DENC_BAD_PROP_IDX 115 #define ERR_DENC_BAD_KEY_IDX 116 #define ERR_DENC_KEY_STATUS 117 #define ERR_DENC_DATA_STATUS 118 #define ERR_DENC_DECRYPT 119 #define ERR_CHARSET_CONVERT 120 #define ERR_COMPRESS 121 #define ERR_DECOMPRESS 122 #define ERR_OCSP_CERT_NOTFOUND 123 #define ERR_INVALID_CONTENT 124 #define ERR_DENC_NO_KEY_FOUND 125 #define ERR_OCSP_RESP_NOT_TRUSTED 126 #define ERR_PRIV_CERT_NOT_FOUND 127 #define ERR_NO_OCSP 128 #define ERR_OCSP_WRONG_SIGNATURE 129 #define ERR_BAD_PARAM 130 #define ERR_GENERIC_SOAP_ERR 131 #define ERR_TS_TIMESTAMPINFO_TYPE 132 #define ERR_TS_BAD_INCLUDEINFO_IDX 133 #define ERR_TS_BAD_TIMESTAMPINFO_IDX 134 #define ERR_TS_CREATE_TS_REQ 135 #define ERR_CREATE_NONCE 136 #define ERR_TXT2OID 137 #define ERR_HTTP_ERR 138 #define ERR_BAD_CERTID_IDX 139 #define ERR_BAD_CERTVALUE_IDX 140 #define ERR_TS_VERIFY 141 #define ERR_TS_REQUEST 142 #define ERR_TSA_NOT_TRUSTED 143 #define ERR_ORPHONED_SIGNATURE 144 #define ERR_WPKI_UNKNOWN_USER 145 #define ERR_WPKI_INVALID_PHONE_NO 146 #define ERR_WPKI_UNTRUSTED_SRVICE 147 #define ERR_WPKI_UNTRUSTED_USER 148 #define ERR_WPKI_UNUSABLE_PHONE 149 #define ERR_WPKI_TIMEOUT 150 #define ERR_WPKI_CANCELLED 151 #define ERR_WPKI_MID_NOT_READY 152 #define ERR_WPKI_PHONE_NOT_REACHABLE 153 #define ERR_WPKI_SENDING_ERROR 154 #define ERR_WPKI_SIM_ERROR 155 #define ERR_WPKI_SERVICE_ERR 156 //AM 18.03.08 #define ERR_ZIP_FILE_READ 157 #define ERR_ZIP 158 #define ERR_MANIFEST 159 #define ERR_DATAFILE_NOT_MANIFEST 160 #define ERR_SIG_INVALID_PROFILE 161 #define ERR_SIGNERS_CERT_NON_REPU 162 #define ERR_OCSP_NONCE_SIGVAL_NOMATCH 163 #define ERR_VALIDATE 164 #define ERR_OCSP_NONCE_INVALID 165 #define ERR_SIGVAL_ASN1 166 #define ERR_MAX_1_ROLES 167 #define ERR_DF_NAME 168 #define ERR_DF_WRONG_DIG 169 #define ERR_ISSUER_XMLNS 170 #define ERR_OLD_VERSION 171 #define ERR_TEST_SIGNATURE 172 #define ERR_UNKNOWN_ERROR 173 #define ERR_TRANSFORM_UNSUPPORTED 174 #define ERR_NETWORK_SYNC 175 #define ERR_XML_VALIDATION 176 #define ERROR_BUF_LENGTH 20 typedef struct ErrorMessage_st { char *errorMessage; int errorClass; } ErrorMessage; typedef int ErrorClass; // Error classes // Wasn't an error at all, no reaction neccessary #define NO_ERRORS 0 // Various problems of technical nature #define TECHNICAL 1 // User-repairable errors #define USER 2 // Bug in DigiDoc library (?) #define LIBRARY 3 //==========< error info structure >============== typedef struct ErrorInfo_st { int code; char *fileName; int line; char *assertion; } ErrorInfo; #ifdef WIN32 extern CRITICAL_SECTION cs_ddocErrors; #endif // checks and prints errors EXP_OPTION long checkErrors(); //returns textual explanation of the error code EXP_OPTION char* getErrorString(int code); //returns the classification for the error code EXP_OPTION ErrorClass getErrorClass(int code); //returns the code of the error that occurred in the library EXP_OPTION ErrorInfo* getErrorInfo(void); //returns 1, if all errors are read and 0 otherwise EXP_OPTION int hasUnreadErrors(void); //resets error information EXP_OPTION void clearErrors(void); EXP_OPTION void addError(int code, char *fileName, int line, char *assertion); EXP_OPTION int checkDigiDocErrors(void); EXP_OPTION int getLastError(); //returns -1, if all errors are read and valid index otherwise EXP_OPTION int getLastErrorsIdx(); //returns NULL, if all errors are read and valid ErrorInfo structre pointer otherwise // does not mark error as read so it can be found again EXP_OPTION ErrorInfo* getErrorsInfo(int nIdx); // return ERR_UNKNOWN_ERROR if multiple different errors exist, otherwise first error code EXP_OPTION int checkUnknownErr(); //==========< macros >==================== #define SET_LAST_ERROR(code) (addError((code), __FILE__, __LINE__, "")) #define SET_LAST_ERROR_IF_NOT(expr, code) { if(!(expr)) addError((code), __FILE__, __LINE__, #expr); } #define SET_LAST_ERROR_RETURN(code, retVal) { SET_LAST_ERROR(code); return (retVal); } #define SET_LAST_ERROR_RETURN_IF_NOT(expr, code, retVal) { if(!(expr)) { addError((code), __FILE__, __LINE__, #expr); return (retVal); } } #define SET_LAST_ERROR_RETURN_VOID_IF_NOT(expr, code) { if(!(expr)) { addError((code), __FILE__, __LINE__, #expr); return; } } #define SET_LAST_ERROR_RETURN_VOID_IF(expr, code) { if(expr) { addError((code), __FILE__, __LINE__, #expr); return; } } #define RETURN_IF_NOT(expr, code) SET_LAST_ERROR_RETURN_IF_NOT((expr), (code), (code)); #define RETURN_IF_NULL(p) RETURN_IF_NOT((p), ERR_NULL_POINTER); #define RETURN_VOID_IF_NULL(p) SET_LAST_ERROR_RETURN_VOID_IF_NOT((p), ERR_NULL_POINTER); #define RETURN_OBJ_IF_NULL(p, obj) SET_LAST_ERROR_RETURN_IF_NOT((p), ERR_NULL_POINTER, (obj)); #define SET_LAST_ERROR_RETURN_CODE(code) { SET_LAST_ERROR(code); return (code); } #define RETURN_IF_NULL_PARAM(p) RETURN_IF_NOT((p), ERR_NULL_PARAM); #define RETURN_IF_BAD_ALLOC(p) RETURN_IF_NOT((p), ERR_BAD_ALLOC) #define RETURN_VOID_IF_BAD_ALLOC(p) SET_LAST_ERROR_RETURN_VOID_IF_NOT((p), ERR_BAD_ALLOC); //======================================== #ifdef __cplusplus } #endif #endif libdigidoc-3.10.5/libdigidoc/DlgUnit.h0000664000372000037200000000020413560273131017100 0ustar travistravis#define IDD_DLG_UNIT 220 #define IDC_GROUPBOX 201 #define IDC_LISTVIEW 202 libdigidoc-3.10.5/libdigidoc/DigiDocGen.c0000664000372000037200000022325613560273131017477 0ustar travistravis//================================================== // FILE: DigiDocGen.c // PROJECT: Digi Doc // DESCRIPTION: DigiDoc helper routines for XML generation // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 11.04.2006 Veiko Sinivee // Creation //================================================== #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* only for xmlNewInputFromFile() */ #include #include #include #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x10010000L static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new() { return (EVP_ENCODE_CTX*)OPENSSL_malloc(sizeof(EVP_ENCODE_CTX)); } static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) { OPENSSL_free(ctx); } static void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { if (n) *n = r->n; if (e) *e = r->e; if (d) *d = r->d; } #endif //-----------< helper functions >---------------------------- //-------------------------------------------------- // Appends an xml element start to buffer, but no ">" // pBuf - memory buffer to store xml [REQUIRED] // elemName - xml element name [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_startElemBegin(DigiDocMemBuf* pBuf, const char* elemName) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(elemName) err = ddocMemAppendData(pBuf, "<", -1); if(err) return err; err = ddocMemAppendData(pBuf, elemName, -1); return err; } //-------------------------------------------------- // Appends an xml element start tag end to buffer - ">" // pBuf - memory buffer to store xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_startElemEnd(DigiDocMemBuf* pBuf) { RETURN_IF_NULL_PARAM(pBuf) return ddocMemAppendData(pBuf, ">", -1); } //-------------------------------------------------- // Appends an xml element start to buffer - // pBuf - memory buffer to store xml [REQUIRED] // elemName - xml element name [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_startElem(DigiDocMemBuf* pBuf, const char* elemName) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(elemName) err = ddocMemAppendData(pBuf, "<", -1); if(err) return err; err = ddocMemAppendData(pBuf, elemName, -1); if(err) return err; err = ddocMemAppendData(pBuf, ">", -1); return err; } //-------------------------------------------------- // Appends an xml element end to buffer // pBuf - memory buffer to store xml [REQUIRED] // elemName - xml element name [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_endElem(DigiDocMemBuf* pBuf, const char* elemName) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(elemName) err = ddocMemAppendData(pBuf, "", -1); return err; } //-------------------------------------------------- // Appends an xml element's atribute to buffer // pBuf - memory buffer to store xml [REQUIRED] // name - xml atribute name [REQUIRED] // value - xml atribute value [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocGen_addAtribute(DigiDocMemBuf* pBuf, const char* name, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(name) RETURN_IF_NULL_PARAM(value) err = ddocMemAppendData(pBuf, " ", -1); if(err) return err; err = ddocMemAppendData(pBuf, name, -1); if(err) return err; err = ddocMemAppendData(pBuf, "=\"", -1); if(err) return err; err = ddocMemAppendData(pBuf, value, -1); if(err) return err; err = ddocMemAppendData(pBuf, "\"", -1); return err; } //================< functions Timestamp_st > ================================= #ifdef WITH_TIMETSTAMP_STRUCT //=================================================================== // converts string to timestamp // IN const char* szTimestamp - timestamp string // OUT Timestamp* pTimestamp //=================================================================== EXP_OPTION int convertStringToTimestamp(const SignedDoc* pSigDoc, const char* szTimestamp, Timestamp* pTimestamp) { RETURN_IF_NULL_PARAM(szTimestamp); RETURN_IF_NULL_PARAM(pTimestamp); RETURN_IF_NULL_PARAM(pSigDoc); // in version 1.3 we use format CCYY-MM-DDTHH:MM:SS-TZ if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) ) { sscanf(szTimestamp, "%04d-%02d-%04dT%02d:%02d:%02dZ", &(pTimestamp->year), &(pTimestamp->mon), &(pTimestamp->day), &(pTimestamp->hour), &(pTimestamp->min), &(pTimestamp->sec)); pTimestamp->tz = 0; } else // in version 1.0 we use format CCYY.MM.DDTHH:MM:SS-TZ if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) { sscanf(szTimestamp, "%04d.%02d.%04dT%02d:%02d:%02d%3d:00", &(pTimestamp->year), &(pTimestamp->mon), &(pTimestamp->day), &(pTimestamp->hour), &(pTimestamp->min), &(pTimestamp->sec), &(pTimestamp->tz)); } else { // in version 1.1 we use format CCYY.MM.DDTHH:MM:SSZ and allways UTC time sscanf(szTimestamp, "%04d.%02d.%04dT%02d:%02d:%02dZ", &(pTimestamp->year), &(pTimestamp->mon), &(pTimestamp->day), &(pTimestamp->hour), &(pTimestamp->min), &(pTimestamp->sec)); pTimestamp->tz = 0; } return ERR_OK; } //=================================================================== // converts string to timestamp // IN const char* szTimestamp - timestamp string // OUT Timestamp* pTimestamp //=================================================================== EXP_OPTION int convertTimestampToString(const SignedDoc* pSigDoc, const Timestamp* pTimestamp, char* szTimestamp, int len) { RETURN_IF_NULL_PARAM(szTimestamp); RETURN_IF_NULL_PARAM(pTimestamp); //RETURN_IF_NULL_PARAM(pSigDoc); // if null then latest format is used // in version 1.3 we use format CCYY-MM-DDTHH:MM:SS-TZ //AM 30.04.08 also in bdoc if(!pSigDoc || (pSigDoc && ( !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) ))) { snprintf(szTimestamp, len, "%04d-%02d-%02dT%02d:%02d:%02dZ",pTimestamp->year, pTimestamp->mon, pTimestamp->day, pTimestamp->hour , pTimestamp->min, pTimestamp->sec); } else // in version 1.0 we use format CCYY.MM.DDTHH:MM:SS-TZ if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) { snprintf(szTimestamp, len, "%04d.%02d.%02dT%02d:%02d:%02d%+03d:00",pTimestamp->year, pTimestamp->mon, pTimestamp->day, pTimestamp->hour , pTimestamp->min, pTimestamp->sec, pTimestamp->tz); } else { // in version 1.1 we use format CCYY.MM.DDTHH:MM:SSZ and allways UTC time snprintf(szTimestamp, len, "%04d.%02d.%02dT%02d:%02d:%02dZ",pTimestamp->year, pTimestamp->mon, pTimestamp->day, pTimestamp->hour , pTimestamp->min, pTimestamp->sec); } return ERR_OK; } // converts date integers to timestamp object EXP_OPTION int Timestamp_new(Timestamp **ppTimestamp, int year,int month,int day,int hour,int minute,int second,int timezone){ Timestamp* pTimestamp; pTimestamp = (Timestamp*)malloc(sizeof(Timestamp)); RETURN_IF_BAD_ALLOC(pTimestamp); memset(pTimestamp, 0, sizeof(Timestamp)); pTimestamp->year=year; pTimestamp->mon=month; pTimestamp->day=day; pTimestamp->hour=hour; pTimestamp->min=minute; pTimestamp->sec=second; pTimestamp->tz=timezone; *ppTimestamp = pTimestamp; return ERR_OK; } //====================================================================== // frees timestamp object //====================================================================== EXP_OPTION void Timestamp_free(Timestamp* pTimestamp){ free(pTimestamp); } #endif //=================================================================== // converts timestamp string to time_t value // IN const char* szTimestamp - timestamp string // OUT Timestamp* pTimestamp //=================================================================== EXP_OPTION time_t convertStringToTimeT(const SignedDoc* pSigDoc, const char* szTimestamp) { struct tm tm1; int tz, dmz = 0; time_t t2; memset(&tm1, 0, sizeof(tm1)); tzset(); t2 = 0; // in version 1.0 we use format CCYY.MM.DDTHH:MM:SS-TZ if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) { sscanf(szTimestamp, "%04d.%02d.%02dT%02d:%02d:%02d+%03d:00", &(tm1.tm_year), &(tm1.tm_mon), &(tm1.tm_mday), &(tm1.tm_hour) , &(tm1.tm_min), &(tm1.tm_sec), &tz); } else if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) { // in version 1.1 we use format CCYY.MM.DDTHH:MM:SSZ and allways UTC time sscanf(szTimestamp, "%04d.%02d.%02dT%02d:%02d:%02dZ", //crash? &(tm1.tm_year), &(tm1.tm_mon), &(tm1.tm_mday), &(tm1.tm_hour), &(tm1.tm_min), &(tm1.tm_sec)); } else { // in version 1.3 we use format CCYY-MM-DDTHH:MM:SSZ and allways UTC time sscanf(szTimestamp, "%04d-%02d-%02dT%02d:%02d:%02dZ", &(tm1.tm_year), &(tm1.tm_mon), &(tm1.tm_mday), &(tm1.tm_hour), &(tm1.tm_min), &(tm1.tm_sec)); } tm1.tm_year -= 1900; tm1.tm_mon -= 1; tm1.tm_isdst = _daylight; t2 = mktime(&tm1); if(_daylight != 0) { if(_timezone < 0) dmz = (_timezone / 3600) - _daylight; else dmz = (_timezone / 3600) + _daylight; } else dmz = _timezone / 3600; t2 -= (dmz * 3600); return t2; } //================< functions generating DigiDoc formats 1.0 - 1.3 > ================================= //============================================================ // Creates a timestamp string // buf - output buffer // len - length of output buffer // returns number of output bytes written //============================================================ int createTimestamp(const SignedDoc* pSigDoc, char* buf, int len) { time_t t; struct tm tm1; Timestamp *pTimestamp; int dmz=0; RETURN_OBJ_IF_NULL(buf, 0); _tzset(); time(&t); // in version 1.0 we use format CCYY.MM.DDTHH:MM:SS-TZ if(pSigDoc && pSigDoc->szFormatVer && !strcmp(pSigDoc->szFormatVer, "1.0")) { ddocLocalTime(&t, &tm1, 1); if(_daylight != 0) { /*if(_timezone<0){*/ dmz=(_timezone - (_daylight*3600))/ 3600; /*}else{ dmz=(_timezone + (_daylight*3600))/ 3600; }*/ }else{ dmz = _timezone / 3600; } } else { // in version 1.1 we use UTC time ddocLocalTime(&t, &tm1, 0); } (void)Timestamp_new(&pTimestamp, tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec, dmz); (void)convertTimestampToString(pSigDoc, pTimestamp, buf, len); Timestamp_free(pTimestamp); return strlen(buf); } //============================================================ // Canonicalizes XML // source - input data // len - input length // returns a newly allocated buffer with canonicalized XML // Caller must free() the result. //============================================================ char* canonicalizeXML(char* source, int len) { xmlDocPtr doc = NULL; xmlChar* pBuf = NULL; int rc, n; char* dest = NULL; ddocDebug(5, "canonicalizeXML", "Canonicalizing: %d bytes", len); if((doc = xmlParseMemory(source, len)) != NULL) { ddocDebug(5, "canonicalizeXML", "Canonicalizing parse: %s", (doc ? "OK" : "ERROR")); rc = xmlC14NDocDumpMemory(doc, NULL, 0, NULL, 0, &pBuf); ddocDebug(5, "canonicalizeXML", "Canonicalizing RC: %d: BUF: %s", rc, (pBuf ? "OK" : "ERROR")); if(pBuf) { n = strlen((char*)pBuf); dest = (char*)malloc(n + 1); if(dest) { strncpy(dest, (char*)pBuf, n); dest[n] = 0; } else SET_LAST_ERROR_IF_NOT(dest, ERR_BAD_ALLOC); xmlFree(pBuf); } xmlFreeDoc(doc); } return dest; } //============================================================ // Canonicalizes XML // source - input data // len - input length // returns a newly allocated buffer with canonicalized XML // Caller must free() the result. //============================================================ char* canonicalizeXMLBlock(char* source, int len, char* block, char* prefix) { xmlDocPtr doc = NULL; xmlChar* pBuf = NULL; int rc, n; char* dest = NULL; xmlXPathContextPtr xpathCtx; xmlXPathObjectPtr xpathObj; //xmlChar* incpref[] = {(xmlChar*)"ds", (xmlChar*)"xades", NULL}; ddocDebug(5, "canonicalizeXMLBlock", "Canonicalizing: %d bytes", len); if((doc = xmlParseMemory(source, len)) != NULL) { ddocDebug(5, "canonicalizeXMLBlock", "Canonicalizing parse: %s", (doc ? "OK" : "ERROR")); /* Create xpath evaluation context */ xpathCtx = xmlXPathNewContext(doc); if(xpathCtx == NULL) { ddocDebug(5, "canonicalizeXMLBlock", "Error: unable to create new XPath context"); xmlFreeDoc(doc); return NULL; } if(prefix && strlen(prefix)){ ddocDebug(5, "canonicalizeXMLBlock","xmlXPathRegisterNs"); if(xmlXPathRegisterNs(xpathCtx, prefix, "http://www.w3.org/2000/09/xmldsig#") != 0) { ddocDebug(5, "canonicalizeXMLBlock","Error: failed to register namespace"); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return NULL; } } ddocDebug(5, "canonicalizeXMLBlock","xmlXPathRegisterNs123"); if(xmlXPathRegisterNs(xpathCtx, "xs", "http://uri.etsi.org/01903/v1.3.2#") != 0) { ddocDebug(5, "canonicalizeXMLBlock","Error: failed to register namespace2\n"); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return NULL; } /* Evaluate xpath expression */ xpathObj = xmlXPathEvalExpression(block, xpathCtx); if(xpathObj == NULL) { ddocDebug(5, "canonicalizeXMLBlock","Error: unable to evaluate xpath expression \"%s\"\n", block); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); } rc = xmlC14NDocDumpMemory(doc, xpathObj->nodesetval, 0, NULL, 0, &pBuf); ddocDebug(5, "canonicalizeXMLBlock", "Canonicalizing RC: %d: BUF: %s", rc, (pBuf ? "OK" : "ERROR")); if(pBuf) { n = strlen((char*)pBuf); dest = (char*)malloc(n + 1); if(dest) strncpy(dest, (char*)pBuf, n+1); else SET_LAST_ERROR_IF_NOT(dest, ERR_BAD_ALLOC); xmlFree(pBuf); } xmlFreeDoc(doc); } return dest; } //-------------------------------------------------- // Helper function that escapes XML special chars in xml element body // src - input data // srclen - length of input data. Use -1 for 0 terminated strings // dest - address of output buffer. Caller is responsible for deallocating it! // returns error code or ERR_OK //-------------------------------------------------- int escapeTextNode(const char* src, int srclen, char** dest) { int j, i, n = srclen, l; char *p = 0; RETURN_IF_NULL_PARAM(src); RETURN_IF_NULL_PARAM(dest); *dest = 0; if(n < 0) n = strlen(src); if(n > 0 && ConfigItem_lookup_int("DEBUG_LEVEL", 1) >= 5) { p = (char*)malloc(n+1); if(p) { memset(p, 0, n+1); memcpy(p, src, n); ddocDebug(5, "escapeTextNode", "src: \"%s\" len: %d", p, n); free(p); } } else ddocDebug(5, "escapeTextNode", "src: \"%s\" len: %d", src, n); // count the amount of memory needed for conversion for(i = l = 0; i < n; i++) { switch(src[i]) { case '<': l += 4; break; case '>': l += 4; break; case '&': l += 5; break; case '\r': l += 5; break; default: l ++; break; } } // count the last terminator char l++; ddocDebug(5, "escapeTextNode", "allocating: %d bytes", l); *dest = (char*)malloc(l); memset(*dest, 0, l); // now convert the data for(i = j = 0; i < n; i++) { switch(src[i]) { case '<': strncat(*dest, "<", l - strlen(*dest)); j += 4; break; case '>': strncat(*dest, ">", l - strlen(*dest)); j += 4; break; case '&': if(src[i+3] != ';' && src[i+4] != ';' && src[i+5] != ';') { if(src[i+1] != '#') { strncat(*dest, "&", l - strlen(*dest)); j += 5; break; } else { if(!strncmp(src+i, "&", 5)) { strncat(*dest, "&", l - strlen(*dest)); j += 5; i += 4; break; } // but others? } } else { (*dest)[j] = src[i]; j++; } break; case '\r': strncat(*dest, " ", l - strlen(*dest)); j += 5; break; default: (*dest)[j] = src[i]; j++; break; } } ddocDebug(4, "escapeTextNode", "Src: %s Converted: \'%s\' len: %d", src, *dest, j); return ERR_OK; } //-------------------------------------------------- // Helper function that escapes XML special chars // src - input data // srclen - length of input data. Use -1 for 0 terminated strings // dest - address of output buffer. Caller is responsible for deallocating it! // returns error code or ERR_OK //-------------------------------------------------- int escapeXMLSymbols(const char* src, int srclen, char** dest) { int j, i, n = srclen, l; char *p = 0; RETURN_IF_NULL_PARAM(src); RETURN_IF_NULL_PARAM(dest); *dest = 0; if(n < 0) n = strlen(src); if(n > 0 && ConfigItem_lookup_int("DEBUG_LEVEL", 1) >= 5) { p = (char*)malloc(n+1); if(p) { memset(p, 0, n+1); memcpy(p, src, n); ddocDebug(5, "escapeXMLSymbols", "src: \"%s\" len: %d", p, n); free(p); } } else ddocDebug(5, "escapeXMLSymbols", "src: \"%s\" len: %d", src, n); // count the amount of memory needed for conversion for(i = l = 0; i < n; i++) { switch(src[i]) { case '<': l += 4; break; case '>': l += 4; break; case '&': l += 5; break; case '\r': l += 5; break; case '\'': l += 6; break; case '\"': l += 6; break; default: l ++; break; } } // count the last terminator char l++; ddocDebug(5, "escapeXMLSymbols", "allocating: %d bytes", l); *dest = (char*)malloc(l); memset(*dest, 0, l); // now convert the data for(i = j = 0; i < n; i++) { switch(src[i]) { case '<': strncat(*dest, "<", l - strlen(*dest)); j += 4; break; case '>': strncat(*dest, ">", l - strlen(*dest)); j += 4; break; case '&': if(src[i+3] != ';' && src[i+4] != ';' && src[i+5] != ';') { if(src[i+1] != '#') { strncat(*dest, "&", l - strlen(*dest)); j += 5; break; } else { if(!strncmp(src+i, "&", 5)) { strncat(*dest, "&", l - strlen(*dest)); j += 5; i += 4; break; } // but others? } } else { (*dest)[j] = src[i]; j++; } break; case '\r': strncat(*dest, " ", l - strlen(*dest)); j += 5; break; case '\'': strncat(*dest, "'", l - strlen(*dest)); j += 6; break; case '\"': strncat(*dest, """, l - strlen(*dest)); j += 6; break; default: (*dest)[j] = src[i]; j++; break; } } ddocDebug(4, "escapeXMLSymbols", "Src: %s Converted: \'%s\' len: %d", src, *dest, j); return ERR_OK; } //============================================================ // Creates a XML block // pSigDoc - signed document pointer // pSigInfo - signature info data // bWithEscapes - 1=escape xml symbols, 0=don't escape // returns new node //============================================================ char* createXMLSignedProperties(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, int bWithEscapes) { char buf1[1024], *pRet = 0, *p1, *p2; int len1, i, err; xmlNodePtr pSigProp, pSigSigProp, pSigCert, pN1, pN2, pN3; static xmlChar nl[] = "\n"; xmlDocPtr doc; DigiDocMemBuf *pMBuf1; xmlChar *pBuf = NULL; // XML doc doc = xmlNewDoc((const xmlChar*)"1.0"); // pSigProp = doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"SignedProperties", NULL); // Ver 1.76 - in format 1.3 xmlns atribute is not used // in ver 1.1 we need this namespace def if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) { xmlNewNs(pSigProp, (const xmlChar*)NAMESPACE_XML_DSIG, NULL); } else if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) { // in 1.3 we use the correct etsi namespace xmlNewNs(pSigProp, (const xmlChar*)NAMESPACE_XADES_111, NULL); } // in 1.0 we had this buggy URI if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) snprintf(buf1, sizeof(buf1), "#%s-SignedProperties", pSigInfo->szId); else // current version is 1.1 snprintf(buf1, sizeof(buf1), "%s-SignedProperties", pSigInfo->szId); xmlSetProp(pSigProp, (const xmlChar*)"Id", (const xmlChar*)buf1); // Ver 1.76 - in format 1.3 Target atribute is not used if(strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) ) { snprintf(buf1, sizeof(buf1), "#%s", pSigInfo->szId); xmlSetProp(pSigProp, (const xmlChar*)"Target", (const xmlChar*)buf1); } // pSigSigProp = xmlNewChild(pSigProp, NULL, (const xmlChar*)"SignedSignatureProperties", nl); // pN1 = xmlNewChild(pSigSigProp, NULL, (const xmlChar*)"SigningTime", (const xmlChar*)pSigInfo->szTimeStamp); xmlNodeAddContent(pSigSigProp, nl); // pSigCert = xmlNewChild(pSigSigProp, NULL, (const xmlChar*)"SigningCertificate", nl); // pN1 = xmlNewChild(pSigCert, NULL, (const xmlChar*)"Cert", nl); // Ver 1.76 - in format 1.3 Id atribute is not used if(strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) ) { // in 1.0 we had this buggy URI if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) snprintf(buf1, sizeof(buf1), "#%s-CERTINFO", pSigInfo->szId); else snprintf(buf1, sizeof(buf1), "%s-CERTINFO", pSigInfo->szId); xmlSetProp(pN1, (const xmlChar*)"Id", (const xmlChar*)buf1); } // pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"CertDigest", nl); // pN3 = xmlNewChild(pN2, NULL, (const xmlChar*)"DigestMethod", nl); xmlNodeAddContent(pN2, nl); xmlSetProp(pN3, (const xmlChar*)"Algorithm", (const xmlChar*)DIGEST_METHOD_SHA1); // len1 = sizeof(buf1); buf1[0] = 0; pMBuf1 = ddocSigInfo_GetSignersCert_DigestValue(pSigInfo); if(pMBuf1) encode((const byte*)pMBuf1->pMem, pMBuf1->nLen, (byte*)buf1, &len1); pN3 = xmlNewChild(pN2, NULL, (const xmlChar*)"DigestValue", (const xmlChar*)buf1); xmlNodeAddContent(pN2, nl); // xmlNodeAddContent(pN1, nl); // In 1.3 we use subelements of if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) ) { pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"IssuerSerial", nl); pN3 = xmlNewChild(pN2, NULL, (const xmlChar*)"X509IssuerName", (const xmlChar*)ddocSigInfo_GetSignersCert_IssuerName((SignatureInfo*)pSigInfo)); xmlSetProp(pN3, (const xmlChar*)"xmlns", (const xmlChar*)NAMESPACE_XML_DSIG); xmlNodeAddContent(pN2, nl); pN3 = xmlNewChild(pN2, NULL, (const xmlChar*)"X509SerialNumber", (const xmlChar*)ddocSigInfo_GetSignersCert_IssuerSerial((SignatureInfo*)pSigInfo)); xmlSetProp(pN3, (const xmlChar*)"xmlns", (const xmlChar*)NAMESPACE_XML_DSIG); xmlNodeAddContent(pN2, nl); } else { pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"IssuerSerial", (const xmlChar*)ddocSigInfo_GetSignersCert_IssuerSerial((SignatureInfo*)pSigInfo)); } // if((!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) { xmlNodeAddContent(pSigSigProp, nl); pN1 = xmlNewChild(pSigSigProp, NULL, (const xmlChar*)"SignaturePolicyIdentifier", nl); // pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"SignaturePolicyImplied", nl); xmlNodeAddContent(pN1, nl); } // if(pSigInfo->sigProdPlace.szCity || pSigInfo->sigProdPlace.szStateOrProvince || pSigInfo->sigProdPlace.szPostalCode || pSigInfo->sigProdPlace.szCountryName) { xmlNodeAddContent(pSigSigProp, nl); pN1 = xmlNewChild(pSigSigProp, NULL, (const xmlChar*)"SignatureProductionPlace", nl); if(pSigInfo->sigProdPlace.szCity) { if(bWithEscapes) { escapeTextNode(pSigInfo->sigProdPlace.szCity, -1, &p2); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"City", (const xmlChar*)p2); free(p2); } else pN2 = xmlNewTextChild(pN1, NULL, (const xmlChar*)"City", (const xmlChar*)pSigInfo->sigProdPlace.szCity); xmlNodeAddContent(pN1, nl); } if(pSigInfo->sigProdPlace.szStateOrProvince) { if(bWithEscapes) { escapeTextNode(pSigInfo->sigProdPlace.szStateOrProvince, -1, &p2); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"StateOrProvince", (const xmlChar*)p2); free(p2); } else pN2 = xmlNewTextChild(pN1, NULL, (const xmlChar*)"StateOrProvince", (const xmlChar*)pSigInfo->sigProdPlace.szStateOrProvince); xmlNodeAddContent(pN1, nl); } if(pSigInfo->sigProdPlace.szPostalCode) { if(bWithEscapes) { escapeTextNode(pSigInfo->sigProdPlace.szPostalCode, -1, &p2); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"PostalCode", (const xmlChar*)p2); free(p2); } else pN2 = xmlNewTextChild(pN1, NULL, (const xmlChar*)"PostalCode", (const xmlChar*)pSigInfo->sigProdPlace.szPostalCode); xmlNodeAddContent(pN1, nl); } if(pSigInfo->sigProdPlace.szCountryName) { if(bWithEscapes) { escapeTextNode(pSigInfo->sigProdPlace.szCountryName, -1, &p2); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"CountryName", (const xmlChar*)p2); free(p2); } else pN2 = xmlNewTextChild(pN1, NULL, (const xmlChar*)"CountryName", (const xmlChar*)pSigInfo->sigProdPlace.szCountryName); xmlNodeAddContent(pN1, nl); } xmlNodeAddContent(pSigSigProp, nl); } // if(pSigInfo->signerRole.nClaimedRoles || pSigInfo->signerRole.nCertifiedRoles) { pN1 = xmlNewChild(pSigSigProp, NULL, (const xmlChar*)"SignerRole", nl); // if(pSigInfo->signerRole.nClaimedRoles) { pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"ClaimedRoles", nl); for(i = 0; i < pSigInfo->signerRole.nClaimedRoles; i++) { if(bWithEscapes) { escapeTextNode(pSigInfo->signerRole.pClaimedRoles[i], -1, &p2); ddocDebug(4, "createXMLSignedProperties", "role: %s --> %s", pSigInfo->signerRole.pClaimedRoles[i], p2); pN3 = xmlNewChild(pN2, NULL, (const xmlChar*)"ClaimedRole", (const xmlChar*)p2); free(p2); } else pN3 = xmlNewTextChild(pN2, NULL, (const xmlChar*)"ClaimedRole", (const xmlChar*)pSigInfo->signerRole.pClaimedRoles[i]); xmlNodeAddContent(pN2, nl); } xmlNodeAddContent(pN1, nl); } // if(pSigInfo->signerRole.nCertifiedRoles) { pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"CertifiedRoles", nl); for(i = 0; i < pSigInfo->signerRole.nClaimedRoles; i++) { p2 = NULL; escapeXMLSymbols(pSigInfo->signerRole.pCertifiedRoles[i], -1, &p2); if(p2) pN3 = xmlNewChild(pN2, NULL, (const xmlChar*)"CertifiedRole", (const xmlChar*)p2); free(p2); p2 = NULL; xmlNodeAddContent(pN2, nl); } xmlNodeAddContent(pN1, nl); } xmlNodeAddContent(pSigSigProp, nl); } // xmlNodeAddContent(pSigProp, nl); pN1 = xmlNewChild(pSigProp, NULL, (const xmlChar*)"SignedDataObjectProperties", nl); xmlNodeAddContent(pSigProp, nl); // convert to string err = xmlC14NDocDumpMemory(doc, NULL, 0, NULL, 0, &pBuf); if(pBuf) { len1 = strlen((char*)pBuf); pRet = malloc(len1+1); if(pRet) { strncpy(pRet, (char*)pBuf, len1); pRet[len1] = 0; } xmlFree(pBuf); } xmlFreeDoc(doc); // return node return pRet; } //============================================================ // Creates a XML block for a signature // This is the actual data to be signed // pSigInfo - signature info data // buf - output buffer // returns number of output bytes written //============================================================ EXP_OPTION char* createXMLSignedInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo) { char buf1[300], *pRet = 0, *p1, *p2; int i, err, l1; xmlNodePtr pnSigInfo, pN1, pN2, pN3; static xmlChar nl[] = "\n"; xmlDocPtr doc; xmlChar* pBuf; //FILE* hFile; DataFile* pDF; DigiDocMemBuf mbuf1; //AM 13.02.09 ecdsa-sha1 support EVP_PKEY* pubKey = NULL; mbuf1.pMem = 0; mbuf1.nLen = 0; RETURN_OBJ_IF_NULL(pSigInfo, 0); // XML doc doc = xmlNewDoc((const xmlChar*)"1.0"); doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"", NULL); // pnSigInfo = xmlNewChild(doc->children, NULL, (const xmlChar*)"SignedInfo", nl); // in ver 1.1 we need this namespace def xmlNewNs(pnSigInfo, (const xmlChar*)NAMESPACE_XML_DSIG, NULL); // pN1 = xmlNewChild(pnSigInfo, NULL, (const xmlChar*)"CanonicalizationMethod", nl); xmlSetProp(pN1, (const xmlChar*)"Algorithm", (const xmlChar*)"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); xmlNodeAddContent(pnSigInfo, nl); // pN1 = xmlNewChild(pnSigInfo, NULL, (const xmlChar*)"SignatureMethod", nl); err = GetPublicKey(&pubKey, ddocSigInfo_GetSignersCert(pSigInfo)); if(pubKey) { #ifdef WITH_ECDSA if(pubKey->type==NID_X9_62_id_ecPublicKey) xmlSetProp(pN1, (const xmlChar*)"Algorithm", (const xmlChar*)"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"); else #endif xmlSetProp(pN1, (const xmlChar*)"Algorithm", (const xmlChar*)"http://www.w3.org/2000/09/xmldsig#rsa-sha1"); EVP_PKEY_free(pubKey); } xmlNodeAddContent(pnSigInfo, nl); // for(i = 0; i < pSigInfo->nDocs; i++) { // documents digest pN1 = xmlNewChild(pnSigInfo, NULL, (const xmlChar*)"Reference", nl); snprintf(buf1, sizeof(buf1), "#%s", pSigInfo->pDocs[i]->szDocId); xmlSetProp(pN1, (const xmlChar*)"URI", (const xmlChar*)buf1); pDF = getDataFileWithId(pSigDoc, pSigInfo->pDocs[i]->szDocId); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"DigestMethod", nl); xmlSetProp(pN2, (const xmlChar*)"Algorithm", (const xmlChar*)"http://www.w3.org/2000/09/xmldsig#sha1"); xmlNodeAddContent(pN1, nl); // in ver 1.0 we use Transforms if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) { pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"Transforms", NULL); pN3 = xmlNewChild(pN2, NULL, (const xmlChar*)"Transform", NULL); xmlSetProp(pN3, (const xmlChar*)"Algorithm", (const xmlChar*)"http://www.w3.org/2000/09/xmldsig#enveloped-signature"); xmlNodeAddContent(pN1, nl); } l1 = sizeof(buf1); encode(pSigInfo->pDocs[i]->szDigest, pSigInfo->pDocs[i]->nDigestLen, (byte*)buf1, &l1); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"DigestValue", (const xmlChar*)buf1); xmlNodeAddContent(pN1, nl); xmlNodeAddContent(pnSigInfo, nl); // in ver 1.1 we don't use mime digest Reference blocks //AM 29.08.10 if(!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { // document mime type digest pN1 = xmlNewChild(pnSigInfo, NULL, (const xmlChar*)"Reference", nl); if(!strcmp(pSigDoc->szFormatVer, "1.0")) snprintf(buf1, sizeof(buf1), "#%s-MIME", pSigInfo->pDocs[i]->szDocId); else // current version is 1.1 snprintf(buf1, sizeof(buf1), "#%s@MimeType", pSigInfo->pDocs[i]->szDocId); xmlSetProp(pN1, (const xmlChar*)"URI", (const xmlChar*)buf1); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"DigestMethod", nl); xmlSetProp(pN2, (const xmlChar*)"Algorithm", (const xmlChar*)DIGEST_METHOD_SHA1); xmlNodeAddContent(pN1, nl); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"Transforms", NULL); pN3 = xmlNewChild(pN2, NULL, (const xmlChar*)"Transform", NULL); xmlSetProp(pN3, (const xmlChar*)"Algorithm", (const xmlChar*)"http://www.w3.org/2000/09/xmldsig#enveloped-signature"); xmlNodeAddContent(pN1, nl); l1 = sizeof(buf1); encode(pSigInfo->pDocs[i]->szMimeDigest, pSigInfo->pDocs[i]->nMimeDigestLen, (byte*)buf1, &l1); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"DigestValue", (const xmlChar*)buf1); xmlNodeAddContent(pN1, nl); } } // signed properties digest pN1 = xmlNewChild(pnSigInfo, NULL, (const xmlChar*)"Reference", nl); snprintf(buf1, sizeof(buf1), "#%s-SignedProperties", pSigInfo->szId); xmlSetProp(pN1, (const xmlChar*)"URI", (const xmlChar*)buf1); // in version 1.2 we ise the Type atribute // for References that contain digest if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) { xmlSetProp(pN1, (const xmlChar*)"Type", (const xmlChar*)"http://uri.etsi.org/01903/v1.1.1#SignedProperties"); } pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"DigestMethod", nl); xmlSetProp(pN2, (const xmlChar*)"Algorithm", (const xmlChar*)DIGEST_METHOD_SHA1); xmlNodeAddContent(pN1, nl); // in 1.0 we used transforms here if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) { pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"Transforms", NULL); pN3 = xmlNewChild(pN2, NULL, (const xmlChar*)"Transform", NULL); xmlSetProp(pN3, (const xmlChar*)"Algorithm", (const xmlChar*)"http://www.w3.org/2000/09/xmldsig#enveloped-signature"); xmlNodeAddContent(pN1, nl); } ddocEncodeBase64(ddocDigestValue_GetDigestValue(pSigInfo->pSigPropDigest), &mbuf1); pN2 = xmlNewChild(pN1, NULL, (const xmlChar*)"DigestValue", (const xmlChar*)mbuf1.pMem); ddocMemBuf_free(&mbuf1); xmlNodeAddContent(pN1, nl); xmlNodeAddContent(pnSigInfo, nl); // convert to string pBuf = NULL; err = xmlC14NDocDumpMemory(doc, NULL, 0, NULL, 0, &pBuf); p1 = strstr((const char*)pBuf, ""); if(p2) { p2[strlen("")] = 0; pRet = malloc(l1); if(pRet) { memset(pRet, 0, l1); strncpy(pRet, p1, strlen(p1)); //pRet = strdup(p1); } } } xmlFree(pBuf); xmlFreeDoc(doc); return pRet; } //============================================================ // Calculates the digest of OCSP_RESPONSE // pResp - OCSP_RESPONSE data // digBuf - signature buffer // digLen - signature buffer length // returns error code //============================================================ int calculateOcspBasicResponseDigest(OCSP_BASICRESP* pBsResp, byte* digBuf, int* digLen) { int err = ERR_OK, l1; byte *buf, *p; RETURN_IF_NULL_PARAM(pBsResp); l1 = i2d_OCSP_BASICRESP(pBsResp, NULL); buf = (byte*)malloc(l1+10); RETURN_IF_BAD_ALLOC(buf); p = buf; i2d_OCSP_BASICRESP(pBsResp, &p); err = calculateDigest(buf, l1, DIGEST_SHA1, digBuf, digLen); free(buf); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // Writes OCSP_RESPONSE to file without the usual PEM headers // bout - output file // pResp - OCSP_RESPONSE // returns error code //============================================================ /*int writeOcspToXMLFile(DigiDocMemBuf* pBuf, OCSP_RESPONSE* pResp) { int l1, l2; char *p1, *p2; RETURN_IF_NULL_PARAM(pBuf); RETURN_IF_NULL_PARAM(pResp); l1 = i2d_OCSP_RESPONSE(pResp, NULL); p1 = (char*)malloc(l1+10); RETURN_IF_BAD_ALLOC(p1); p2 = p1; i2d_OCSP_RESPONSE(pResp, (unsigned char**)&p2); l2 = l1 * 2; p2 = (char*)malloc(l2); if(p2 == NULL) { free(p1); RETURN_IF_BAD_ALLOC(p2); } encode((const byte*)p1, l1, (byte*)p2, &l2); ddocMemAppendData(pBuf, p2, -1); free(p2); free(p1); return ERR_OK; }*/ //============================================================ // Adds a notary signature to signed document buffer // pMBufXML - output buffer // pSigDoc - signed doc pointer // pNotInfo - notary signature info // returns error code //============================================================ int addNotaryInfoXML(DigiDocMemBuf *pMBufXML, const SignedDoc *pSigDoc, const SignatureInfo* pSigInfo, const NotaryInfo* pNotInfo) { int err = ERR_OK, i; DigiDocMemBuf mbuf1; const DigiDocMemBuf *pMBuf; CertValue *pCertValue = 0; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pNotInfo); RETURN_IF_NULL_PARAM(pMBufXML); mbuf1.pMem = 0; mbuf1.nLen = 0; // unsigned prop begin // Ver 1.76 - in format 1.3 we don't use the Target atribute if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) { ddocMemAppendData(pMBufXML,"\n", -1); } else { ddocMemAppendData(pMBufXML,"szId, -1); ddocMemAppendData(pMBufXML,"\">\n", -1); } // err = ddocCompleteCertificateRefs_toXML((SignedDoc*)pSigDoc, (SignatureInfo*)pSigInfo, &mbuf1); ddocMemAppendData(pMBufXML,(const char*)mbuf1.pMem, -1); ddocMemBuf_free(&mbuf1); // err = ddocCompleteRevocationRefs_toXML((SignedDoc*)pSigDoc, (SignatureInfo*)pSigInfo, &mbuf1); ddocMemAppendData(pMBufXML,(const char*)mbuf1.pMem, -1); ddocMemBuf_free(&mbuf1); // responder cert ddocMemAppendData(pMBufXML,"\n", -1); // TODO format cert without header for(i = 0; i < ddocCertValueList_GetCertValuesCount(pSigInfo->pCertValues); i++) { pCertValue = ddocCertValueList_GetCertValue(pSigInfo->pCertValues, i); if(pCertValue && pCertValue->nType != CERTID_VALUE_SIGNERS_CERT) { ddocDebug(3, "addNotaryInfoXML", "Write CertVal-type: %d cert: %s", pCertValue->nType, (pCertValue->pCert ? "OK" : "NULL")); ddocCertValue_toXML(pCertValue, &mbuf1); ddocMemAppendData(pMBufXML, (const char*)mbuf1.pMem, -1); ddocMemAppendData(pMBufXML, "\n", -1); ddocMemBuf_free(&mbuf1); } } ddocMemAppendData(pMBufXML, "\n", -1); // revocation values ddocMemAppendData(pMBufXML, "", -1); // Ver 1.76 - in format 1.3 we use here additionally element if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) ddocMemAppendData(pMBufXML, "", -1); // OCSP response ddocMemAppendData(pMBufXML, "szId, -1); ddocMemAppendData(pMBufXML, "\">\n", -1); pMBuf = ddocNotInfo_GetOCSPResponse(pNotInfo); RETURN_IF_NULL(pMBuf); // fix for backward compatibility with 2.1.5 // remove trailing \n after base64 content if(mbuf1.pMem && ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] == '\n') ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] = 0; ddocEncodeBase64(pMBuf, &mbuf1); ddocMemAppendData(pMBufXML, (const char*)mbuf1.pMem, -1); ddocMemBuf_free(&mbuf1); ddocMemAppendData(pMBufXML, "\n", -1); // Ver 1.76 - in format 1.3 we use here additionally element if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) ddocMemAppendData(pMBufXML,"", -1); ddocMemAppendData(pMBufXML,"", -1); // unsigned prop end ddocMemAppendData(pMBufXML, "\n", -1); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // Swaps bytes in this byte array. Length must be an even number // used for big-endian <--> small-endian conversion //============================================================ void swapBytes(byte* src, int len) { byte b; int i; if(len % 2 == 0) { for(i = 0; i < (len / 2); i++) { b = src[i]; src[i] = src[len - i - 1]; src[len - i - 1] = b; } } } //============================================================ // Adds a signature to signed document file // hFile - output file // pSigInfo - signature info // cert - signers certificate // returns error code //============================================================ int addSignatureInfoXML(DigiDocMemBuf *pMBufXML, SignedDoc* pSigDoc, SignatureInfo* pSigInfo) { int err = ERR_OK; unsigned char buf2[500], *buf1 = 0; int len2, len1; EVP_PKEY* pubKey = NULL; const RSA *rsa = NULL; const BIGNUM *n = NULL, *e = NULL; SignatureValue *pSigVal; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pMBufXML); RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pSigInfo); mbuf1.pMem = 0; mbuf1.nLen = 0; //TODO: xmlns = http://uri.etsi.org/01903/v1.3.2# ddocMemAppendData(pMBufXML,"szId, -1); ddocMemAppendData(pMBufXML,"\" xmlns=\"http://www.w3.org/2000/09/xmldsig#\">\n", -1); buf1 = (unsigned char*)createXMLSignedInfo(pSigDoc, pSigInfo); RETURN_IF_NULL(buf1); ddocMemAppendData(pMBufXML,(const char*)buf1, -1); free(buf1); buf1 = 0; // mark free len1 = 1024; buf1 = (unsigned char*)malloc(len1); RETURN_IF_BAD_ALLOC(buf1); memset(buf1, 0, len1); // pSigVal = ddocSigInfo_GetSignatureValue(pSigInfo); //RETURN_IF_NULL(pSigVal); ddocSignatureValue_toXML(pSigVal, &mbuf1); ddocMemAppendData(pMBufXML,(const char*)mbuf1.pMem, -1); ddocMemBuf_free(&mbuf1); // cert data... if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) { ddocMemAppendData(pMBufXML,"szId, -1); ddocMemAppendData(pMBufXML,"-CERT\">\n", -1); } else { // RSA KEY value ddocMemAppendData(pMBufXML,"\n", -1); err = GetPublicKey(&pubKey, ddocSigInfo_GetSignersCert(pSigInfo)); // FIXME // modulus //AM 11.02.09 if(!err && EVP_PKEY_base_id(pubKey)==EVP_PKEY_RSA) { ddocMemAppendData(pMBufXML,"\n\n", -1); rsa = EVP_PKEY_get1_RSA(pubKey); RSA_get0_key(rsa, &n, &e, NULL); len1 = BN_bn2bin(n, buf1); // in version 1.1 we output modulus as it is // starting from 1.2 we convert it to big-endian /*len2 = sizeof(buf2); memset(buf2, 0, len2); encode(buf1, len1, buf2, &len2); printf("Old modulus: %s\n", buf2); if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER)) { swapBytes((byte*)buf1, len1); }*/ len2 = sizeof(buf2); memset(buf2, 0, len2); encode(buf1, len1, buf2, &len2); //printf("New modulus: %s len: %d\n", buf2, len1); ddocMemAppendData(pMBufXML, "", -1); ddocMemAppendData(pMBufXML, (char*)buf2, -1); ddocMemAppendData(pMBufXML,"\n", -1); // exponent memset(buf1, 0, len1); len1 = BN_bn2bin(e, buf1); len2 = sizeof(buf2); memset(buf2, 0, len2); encode(buf1, len1, buf2, &len2); ddocMemAppendData(pMBufXML,"", -1); ddocMemAppendData(pMBufXML, (char*)buf2, -1); ddocMemAppendData(pMBufXML,"\n", -1); ddocMemAppendData(pMBufXML,"\n\n", -1); RSA_free(rsa); } // cert data ddocMemAppendData(pMBufXML,"\n", -1); } free(buf1); buf1 = 0; // mark freed RETURN_IF_NOT(err == ERR_OK, err); // check sig-value encode errors err = getCertPEM(ddocSigInfo_GetSignersCert(pSigInfo), 0, (char**)&buf1); RETURN_IF_NULL(buf1); ddocMemAppendData(pMBufXML, (char*)buf1, -1); free(buf1); ddocMemAppendData(pMBufXML,"\n", -1); // VS in releases prior to 1.76 we had incorrect atributes if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) { ddocMemAppendData(pMBufXML,"szId, -1); ddocMemAppendData(pMBufXML,"\">\n", -1); } else { ddocMemAppendData(pMBufXML,"\n", -1); } EVP_PKEY_free(pubKey); // signed properties buf1 = (unsigned char*)createXMLSignedProperties(pSigDoc, pSigInfo, 1); RETURN_IF_NULL(buf1); ddocMemAppendData(pMBufXML,(const char*)buf1, -1); free(buf1); // unsigned properties if(pSigInfo->pNotary) addNotaryInfoXML(pMBufXML, pSigDoc, pSigInfo, pSigInfo->pNotary); // qualifying properties end ddocMemAppendData(pMBufXML,"\n", -1); // signature end ddocMemAppendData(pMBufXML,"\n", -1); if (err != ERR_OK) SET_LAST_ERROR(err); ddocMemBuf_free(&mbuf1); return err; } //============================================================ // Canonicalizes PCDATA text value. Simple caninicalization // only that replaces "\n\r" with "\n", by removing the "\r" // and shifting the data left. Modification is done in place. // src - input data. will be modified // return error code or ERR_OK //============================================================ int ddocCanonicalizePCDATA(char * src) { int i, j; RETURN_IF_NULL_PARAM(src); for(i = j = 0; src[j]; ) { if(src[j] == '\r') { j++; } else { if(i != j) src[i] = src[j]; i++; j++; } } src[i] = 0; return ERR_OK; } //============================================================ // Generates DataFile elements XML form and stores it in a file // pSigDoc - signed document // pDataFile - data file object to be converted // szDataFile - input file name // hFile - output file handle // pMBufDigest - pointer to buffer for digest if we only want the digest // pMBufXML - output buffer if we want data to be returned in mem buf //============================================================ EXP_OPTION int generateDataFileXML(SignedDoc* pSigDoc, DataFile* pDataFile, const char* szDataFile, FILE* hFile, DigiDocMemBuf* pMBufXML) { int err = ERR_OK, len1, len2, j, k; char buf1[2050], buf2[5000], fixedFileName[1024], *p = 0; char *name, *value, *fName; FILE *fIn = 0; EVP_ENCODE_CTX *ectx; SHA_CTX sctx; DigiDocMemBuf mbuf1, mbuf2, mbuf3; #ifdef WIN32 wchar_t *convFileName = 0; #endif RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pDataFile); //RETURN_IF_NULL_PARAM(szDataFile); mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; len1 = sizeof(buf1); ddocDebug(3, "generateDataFileXML", "DF: %s in-df-file: %s out-file: %s mbuf: %s", pDataFile->szId, szDataFile, (hFile ? "Y" : "N"), (pMBufXML ? "Y" : "N")); // replaces '&' with '&' memset(fixedFileName, 0, sizeof(fixedFileName)); fName = (char*)getSimpleFileName(pDataFile->szFileName); escapeXMLSymbols(fName, -1, &p); if(p) strncpy(fixedFileName, p, sizeof(fixedFileName)); free(p); p = 0; //in versions 1.0, 1.1 and 1.2 we used bad encoding if((!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) { #ifdef WIN32 utf82oem(fixedFileName, buf1, sizeof(buf1)); len2 = sizeof(buf2); ascii2utf8(buf1, buf2, &len2); #else convFNameToWin(fixedFileName, buf2, sizeof(buf2)); #endif strncpy(fixedFileName, buf2, sizeof(fixedFileName)); } // in version 1.0 we use DigestType and DigestValue attributes, PR. - size fix ddocMemSetLength(&mbuf2, 1024); if((!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER))) { ddocEncodeBase64(ddocDataFile_GetDigestValue(pDataFile), &mbuf1); //AM 17.11.08 moved these 2 lines after ddocEncodeBase64 if(mbuf1.pMem && ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] == '\n') ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] = 0; snprintf((char*)mbuf2.pMem, mbuf2.nLen, "szContentType, fixedFileName, pDataFile->szId, pDataFile->szMimeType, pDataFile->nSize, pDataFile->szDigestType, (char*)mbuf1.pMem); ddocMemBuf_free(&mbuf1); } else { snprintf((char*)mbuf2.pMem, mbuf2.nLen, "szContentType, fixedFileName, pDataFile->szId, pDataFile->szMimeType, pDataFile->nSize); } mbuf2.nLen = strlen((const char*)mbuf2.pMem); k = getCountOfDataFileAttributes(pDataFile); for(j = 0; j < k; j++) { getDataFileAttribute(pDataFile, j, &name, &value); escapeXMLSymbols(value, -1, &p); ddocMemAppendData(&mbuf2, " ", -1); ddocMemAppendData(&mbuf2, name, -1); ddocMemAppendData(&mbuf2, "=\"", -1); if(p) ddocMemAppendData(&mbuf2, p, -1); ddocMemAppendData(&mbuf2, "\"", -1); free(p); p = NULL; } // VS - ver 1.80 - in format 1.3 we started using SignedDoc schema if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) ddocMemAppendData(&mbuf2, " xmlns=\"http://www.sk.ee/DigiDoc/v1.3.0#\"", -1); ddocMemAppendData(&mbuf2, ">", -1); // end of generating header // if DataFile content is already in memory then convert to base64 and use it if(pDataFile->mbufContent.pMem && pDataFile->mbufContent.nLen && pMBufXML) { if(!strcmp(pDataFile->szContentType, CONTENT_EMBEDDED) || !strcmp(pDataFile->szContentType, CONTENT_EMBEDDED_BASE64)) { //allready in base64 ddocMemAppendData(&mbuf2, pDataFile->mbufContent.pMem, pDataFile->mbufContent.nLen); } ddocMemAppendData(&mbuf2, "", -1); p = canonicalizeXML((char*)mbuf2.pMem, mbuf2.nLen); RETURN_IF_NULL(p); ddocDebug(3, "generateDataFileXML", "canonicalized df: \'%s\'", p); //ddocDebugWriteFile(3, "df-data0.txt", &mbuf2); SHA1_Init(&sctx); SHA1_Update(&sctx, (const char*)p, strlen(p)); free(p); p = 0; len2 = sizeof(buf2); SHA1_Final((unsigned char*)buf2, &sctx); ddocDataFile_SetDigestValue(pDataFile, buf2, DIGEST_LEN); if(pMBufXML) ddocMemAppendData(pMBufXML, mbuf2.pMem, mbuf2.nLen); if(hFile) fwrite(mbuf2.pMem, sizeof(char), mbuf2.nLen, hFile); ddocMemBuf_free(&mbuf2); len1 = sizeof(buf1); bin2hex(pDataFile->mbufDigest.pMem, pDataFile->mbufDigest.nLen, buf1, &len1); ddocDebug(3, "generateDataFileXML", "DataFile: %s calc-digest: %s", pDataFile->szId, buf1); len1 = sizeof(buf1); encode((const byte*)pDataFile->mbufDigest.pMem, pDataFile->mbufDigest.nLen, (byte*)buf1, &len1); ddocDebug(3, "generateDataFileXML", "DataFile: %s calc-digest: %s", pDataFile->szId, buf1); return err; } if(hFile) fputs((const char*)mbuf2.pMem, hFile); #ifdef WITH_BASE64_HASHING_HACK SHA1_Init(&sctx); if(!strcmp(pDataFile->szContentType, CONTENT_EMBEDDED_BASE64) && strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { // in ddoc 1.0 we calculate hash over original data ddocMemAppendData(&mbuf2, "", -1); p = canonicalizeXML((char*)mbuf2.pMem, mbuf2.nLen); RETURN_IF_NULL(p); p[strlen(p)-11] = 0; ddocDebug(4, "generateDataFileXML", "sha1 initial update: \'%s\'", p); mbuf3.pMem = p; mbuf3.nLen = strlen(p); ddocDebugWriteFile(4, "df-data0.txt", &mbuf3); SHA1_Update(&sctx, (const char*)p, strlen(p)); free(p); p = 0; } #endif // in base64 hashing hack mode we don't keep DF content constantly in memory #ifdef WITH_BASE64_HASHING_HACK if(!strcmp(pDataFile->szContentType, CONTENT_EMBEDDED_BASE64)) ddocMemBuf_free(&mbuf2); #endif //err = ddocConvertFileName(fixedFileName, sizeof(fixedFileName), pDataFile->szFileName); //if(err) return err; strncpy(fixedFileName, pDataFile->szFileName, sizeof(fixedFileName)); // if this is our temp file not a real input file // then don't change anything in it. if(strcmp(pDataFile->szFileName, szDataFile) != 0) { #ifdef WIN32 len2 = 0; err = utf82unicode((const char*)szDataFile, (char**)&convFileName, &len2); fIn = _wfopen(convFileName, L"rb"); ddocDebug(3, "generateDataFileXML", "Opening FILE1: %s, conv-file: %s len: %d, RC: %d", szDataFile, convFileName, len2, (fIn != NULL)); free(convFileName); // now I don't need it any more if(fIn != NULL) { #else if((fIn = fopen(szDataFile, "rb")) != NULL) { #endif ddocDebug(4, "generateDataFileXML", "Opened FILE01: %s", szDataFile); if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { ectx = EVP_ENCODE_CTX_new(); EVP_DecodeInit(ectx); } while((len1 = fread(buf1, 1, sizeof(buf1)-2, fIn)) > 0) { #ifdef WITH_BASE64_HASHING_HACK if(!strcmp(pDataFile->szContentType, CONTENT_EMBEDDED_BASE64)) { buf1[len1] = 0; #ifdef WIN32 // must remove \r that was generated during data file extact if(strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { ddocCanonicalizePCDATA(buf1); len1 = strlen(buf1); } #endif if(strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { ddocDebug(4, "generateDataFileXML", "sha1 update: \'%s\'", buf1); SHA1_Update(&sctx, (const char*)buf1, len1); mbuf3.pMem = buf1; mbuf3.nLen = len1; ddocDebugWriteFile(4, "df-data0.txt", &mbuf3); } else { // in ddoc 1.0 we calculate hash over original data p = buf1; while(*p == ' ' || *p == '\n' || *p == '\r') p++; ddocDebug(4, "generateDataFileXML", "decode: %s", p); len2 = sizeof(buf2); EVP_DecodeUpdate(ectx, (unsigned char*)buf2, &len2, (unsigned char*)p, strlen(p)); ddocDebug(4, "generateDataFileXML", "sha1 update orig: %d: dec: %d", len1, len2); SHA1_Update(&sctx, (const char*)buf2, len2); //ddocDebugWriteFile(4, "df-data0.txt", &mbuf3); } } else { #endif ddocMemAppendData(&mbuf2, buf1, len1); #ifdef WITH_BASE64_HASHING_HACK } #endif if(hFile) fwrite(buf1, sizeof(char), len1, hFile); } fclose(fIn); ddocDebug(4, "generateDataFileXML", "Closed FILE01: %s", szDataFile); fIn = 0; if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { len2 = sizeof(buf2); EVP_DecodeFinal(ectx, (unsigned char*)buf2, &len2); EVP_ENCODE_CTX_free(ectx); SHA1_Update(&sctx, (const char*)buf2, len2); ddocDebug(4, "generateDataFileXML", "sha1 final dec: %d", len1, len2); len2 = sizeof(buf2); SHA1_Final((unsigned char*)buf2, &sctx); ddocDataFile_SetDigestValue(pDataFile, buf2, DIGEST_LEN); len1 = sizeof(buf1); bin2hex(pDataFile->mbufDigest.pMem, pDataFile->mbufDigest.nLen, buf1, &len1); ddocDebug(3, "generateDataFileXML", "DataFile: %s calc-digest: %s", pDataFile->szId, buf1); } } } else { // if the file must be embedded if(!strcmp(pDataFile->szContentType, CONTENT_EMBEDDED_BASE64) || !strcmp(pDataFile->szContentType, CONTENT_EMBEDDED)) { #ifdef WIN32 len2 = 0; err = utf82unicode((const char*)fixedFileName, (char**)&convFileName, &len2); fIn = _wfopen(convFileName, L"rb"); ddocDebug(3, "generateDataFileXML", "Opening FILE2: %s, conv-file: %s len: %d, RC: %d", fixedFileName, convFileName, len2, (fIn != NULL)); free(convFileName); // now I don't need it any more if(fIn != NULL) { #else if((fIn = fopen(fixedFileName, "rb")) != NULL) { #endif ddocDebug(4, "generateDataFileXML", "Opened FILE2: %s", fixedFileName); // if encoded if(!strcmp(pDataFile->szContentType, CONTENT_EMBEDDED_BASE64)) { ectx = EVP_ENCODE_CTX_new(); EVP_EncodeInit(ectx); while((len1 = fread(buf1, 1, sizeof(buf1), fIn)) > 0) { len2 = sizeof(buf2); EVP_EncodeUpdate(ectx, (unsigned char*)buf2, &len2, (unsigned char*)buf1, len1); buf2[len2] = 0; #ifdef WITH_BASE64_HASHING_HACK ddocCanonicalizePCDATA(buf2); len2 = strlen(buf2); ddocDebug(4, "generateDataFileXML", "sha1 update: \'%s\'", buf2); SHA1_Update(&sctx, (const char*)buf2, len2); mbuf3.pMem = buf2; mbuf3.nLen = len2; ddocDebugWriteFile(4, "df-data0.txt", &mbuf3); #else ddocMemAppendData(&mbuf2, buf2, len2); #endif if(hFile) fwrite(buf2, sizeof(char), len2, hFile); } EVP_EncodeFinal(ectx, (unsigned char*)buf2, &len2); EVP_ENCODE_CTX_free(ectx); buf2[len2] = 0; #ifdef WITH_BASE64_HASHING_HACK ddocCanonicalizePCDATA(buf2); len2 = strlen(buf2); ddocDebug(4, "generateDataFileXML", "sha1 update: \'%s\'", buf2); SHA1_Update(&sctx, (const char*)buf2, len2); mbuf3.pMem = buf2; mbuf3.nLen = len2; ddocDebugWriteFile(4, "df-data0.txt", &mbuf3); #else ddocMemAppendData(&mbuf2, buf2, len2); #endif if(hFile) fwrite(buf2, sizeof(char), len2, hFile); } else if(!strcmp(pDataFile->szContentType, CONTENT_EMBEDDED)) { while((len1 = fread(buf1, 1, sizeof(buf1), fIn)) > 0) { if(!strcmp(pDataFile->szCharset, CHARSET_UTF_8)) { ddocMemAppendData(&mbuf2, buf1, len1); if(hFile) fwrite(buf1, sizeof(char), len1, hFile); } else if(!strcmp(pDataFile->szCharset, CHARSET_ISO_8859_1)) { len2 = sizeof(buf2); memset(buf2, 0, len2); isolat1ToUTF8((unsigned char*)buf2, &len2, (const unsigned char*)buf1, &len1); ddocMemAppendData(&mbuf2, buf2, len2); if(hFile) fwrite(buf2, sizeof(char), len2, hFile); //if(pMBufXML) // ddocMemAppendData(pMBufXML, buf2, len2); } else SET_LAST_ERROR(ERR_UNSUPPORTED_CHARSET); } if(!strcmp(pDataFile->szCharset, CHARSET_UTF_8)) { ddocMemAppendData(&mbuf2, buf1, len1); if(hFile) fwrite(buf1, sizeof(char), len1, hFile); //if(pMBufXML) // ddocMemAppendData(pMBufXML, buf1, len1); } else if(!strcmp(pDataFile->szCharset, CHARSET_ISO_8859_1)) { len2 = sizeof(buf2); memset(buf2, 0, len2); isolat1ToUTF8((unsigned char*)buf2, &len2, (const unsigned char*)buf1, &len1); ddocMemAppendData(&mbuf2, buf2, len2); if(hFile) fwrite(buf2, sizeof(char), len2, hFile); //if(pMBufXML) // ddocMemAppendData(pMBufXML, buf2, len2); } else SET_LAST_ERROR(ERR_UNSUPPORTED_CHARSET); } fclose(fIn); ddocDebug(4, "generateDataFileXML", "Closed FILE2: %s", szDataFile); fIn = 0; } else { ddocDebug(1, "generateDataFileXML", "Error reading FILE2: %s", szDataFile); err = ERR_FILE_READ; } } } // not temp file // print suffix-whitespace //if(pDataFile->szDataSuffix) // BIO_puts(bOutFile, pDataFile->szDataSuffix); setString(&(pDataFile->szDigestType), DIGEST_SHA1_NAME, -1); #ifdef WITH_BASE64_HASHING_HACK if(!strcmp(pDataFile->szContentType, CONTENT_EMBEDDED_BASE64)) { if(strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { // in ddoc 1.0 we calculate hash over original data ddocDebug(4, "generateDataFileXML", "sha1 update: \'%s\'", ""); SHA1_Update(&sctx, "", 11); mbuf3.pMem = ""; mbuf3.nLen = strlen(""); ddocDebugWriteFile(4, "df-data0.txt", &mbuf3); } memset(buf2, 0, sizeof(buf2)); SHA1_Final((unsigned char*)buf2, &sctx); ddocDataFile_SetDigestValue(pDataFile, buf2, DIGEST_LEN); ddocEncodeBase64(ddocDataFile_GetDigestValue(pDataFile), &mbuf2); if(pMBufXML) { if(((char*)mbuf2.pMem)[strlen((char*)mbuf2.pMem)-1] == '\n') ((char*)mbuf2.pMem)[strlen((char*)mbuf2.pMem)-1] = 0; ddocMemAppendData(pMBufXML, (const char*)mbuf2.pMem, -1); } ddocDebug(4, "generateDataFileXML", "DF digest: %s", (char*)mbuf2.pMem); ddocMemBuf_free(&mbuf2); } else { #endif ddocMemAppendData(&mbuf2, "", -1); memset(buf2, 0, sizeof(buf2)); p = canonicalizeXML((char*)mbuf2.pMem, mbuf2.nLen); ddocMemBuf_free(&mbuf2); RETURN_IF_NULL(p); SHA1((const unsigned char*)p, strlen(p), (unsigned char*)buf2); ddocDebug(4, "generateDataFileXML", "CANONICAL XML: \'%s\'", p); free(p); ddocDebug(4, "generateDataFileXML", "will update DF digest as ctype is %s", pDataFile->szContentType); ddocDataFile_SetDigestValue(pDataFile, buf2, DIGEST_LEN); ddocEncodeBase64(ddocDataFile_GetDigestValue(pDataFile), &mbuf2); if(pMBufXML) { if(((char*)mbuf2.pMem)[strlen((char*)mbuf2.pMem)-1] == '\n') ((char*)mbuf2.pMem)[strlen((char*)mbuf2.pMem)-1] = 0; ddocMemAppendData(pMBufXML, (const char*)mbuf2.pMem, -1); } ddocDebug(4, "generateDataFileXML", "DF digest: %s", (char*)mbuf2.pMem); ddocMemBuf_free(&mbuf2); #ifdef WITH_BASE64_HASHING_HACK } #endif if(hFile) fputs("", hFile); if(pMBufXML) { ddocMemAppendData(pMBufXML, (const char*)"\">", -1); ddocMemAppendData(pMBufXML, "", -1); } if (err != ERR_OK) SET_LAST_ERROR(err); ddocDebug(4, "generateDataFileXML", "done: %d", err); return err; } #define DD_TEMP_FILE_MAX 200 //-------------------------------------------------- // Creates a new signed XML document // pSigDoc - signed doc info // szSigDocFile - output XML file name. If the file exists, // pMBufXML - output buffer if required to pass back in memory // then it will be used to read in embedded DataFile contents. // returns error code or ERR_OK for success //-------------------------------------------------- int createSignedXMLDoc(SignedDoc* pSigDoc, const char* szOldFile, const char* szSigDocFile, DigiDocMemBuf* pMBufXML) { int err = ERR_OK, i, nFiles; FILE *hFile = 0; DataFile* pDf = NULL; char ** arrTempFiles = NULL; char buf1[1024]; DigiDocMemBuf mbuf1; #ifdef WIN32 wchar_t *convFileName = 0; #endif RETURN_IF_NULL_PARAM(pSigDoc); //RETURN_IF_NULL_PARAM(szSigDocFile || pMBufXML); mbuf1.pMem = 0; mbuf1.nLen = 0; buf1[0] = 0; nFiles = getCountOfDataFiles(pSigDoc); ddocDebug(3, "createSignedXMLDoc", "Old file: %s new file: %s mbuf: %s, DFs: %d", szOldFile, (szSigDocFile ? szSigDocFile : "NULL"), (pMBufXML ? "Y" : "N"), nFiles); // check if the file exists allready // and extracts data files. They // will be used later to construct // a new document and then removed if(szOldFile && checkFileExists(szOldFile)) { arrTempFiles = (char**)malloc(nFiles * sizeof(void*)); RETURN_IF_BAD_ALLOC(arrTempFiles); memset(arrTempFiles, 0, nFiles * sizeof(void*)); for(i = 0; i < nFiles; i++) { pDf = getDataFile(pSigDoc, i); ddocDebug(3, "createSignedXMLDoc", "DataFile: %s - %s", pDf->szId, pDf->szFileName); arrTempFiles[i] = (char*)malloc(DD_TEMP_FILE_MAX); arrTempFiles[i][0] = 0; // do not copy newly added files if(!strchr((const char*)pDf->szFileName, '/') && !strchr((const char*)pDf->szFileName, '\\')) { err = getTempFileName(arrTempFiles[i], DD_TEMP_FILE_MAX); // VS: test the new parser based on xmlReader interface //err = ddocXRdrCopyDataFile(pSigDoc, szOldFile, (const char*)arrTempFiles[i], pDf->szId, CHARSET_ISO_8859_1, CHARSET_ISO_8859_1); ddocDebug(3, "createSignedXMLDoc", "Store DataFile: %s to: %s size: %d", pDf->szId, (const char*)arrTempFiles[i], pDf->nSize); err = ddocExtractDataFile(pSigDoc, szOldFile, (const char*)arrTempFiles[i], pDf->szId, "NO-CHANGE"); } } } if(szSigDocFile) { #ifdef WIN32 i = 0; err = utf82unicode((const char*)szSigDocFile, (char**)&convFileName, &i); ddocDebug(3, "createSignedXMLDoc", "Opening FILE: %s, conv-file: %s len: %d", szSigDocFile, convFileName, i); if(err) return err; #else err = ddocConvertFileName(buf1, sizeof(buf1), szSigDocFile); ddocDebug(3, "createSignedXMLDoc", "Opening FILE: %s", buf1); if(err) return err; #endif } // now create the new document #ifdef WIN32 if((szSigDocFile && (hFile = _wfopen(convFileName, L"wb")) != NULL) || pMBufXML) { #else if((szSigDocFile && (hFile = fopen(buf1, "wb")) != NULL) || pMBufXML) { #endif if(szSigDocFile) fputs("\n", hFile); if(pMBufXML) ddocMemAppendData(pMBufXML, "\n", -1); // VS: ver 1.80 - in version 1.3 we started using SignedDoc namespace if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) { if(szSigDocFile) fprintf(hFile, "\n", pSigDoc->szFormat, pSigDoc->szFormatVer); if(pMBufXML) { ddocMemAppendData(pMBufXML, "szFormat, -1); ddocMemAppendData(pMBufXML, "\" version=\"", -1); ddocMemAppendData(pMBufXML, pSigDoc->szFormatVer, -1); ddocMemAppendData(pMBufXML, "\" xmlns=\"http://www.sk.ee/DigiDoc/v1.3.0#\">\n", -1); } } else { if(szSigDocFile) fprintf(hFile, "\n", pSigDoc->szFormat, pSigDoc->szFormatVer); if(pMBufXML) { ddocMemAppendData(pMBufXML, "szFormat, -1); ddocMemAppendData(pMBufXML, "\" version=\"", -1); ddocMemAppendData(pMBufXML, pSigDoc->szFormatVer, -1); ddocMemAppendData(pMBufXML, "\">\n", -1); } } // DataFile objects for(i = 0; i < nFiles; i++) { pDf = getDataFile(pSigDoc, i); ddocDebug(3, "createSignedXMLDoc", "DF: %d file: %s temp: %s", i, pDf->szFileName, (arrTempFiles ? arrTempFiles[i] : "NONE")); // if the file must be embedded if(arrTempFiles && arrTempFiles[i] && checkFileExists(arrTempFiles[i])) { ddocDebug(3, "createSignedXMLDoc", "Use temp file: %s", arrTempFiles[i]); err = generateDataFileXML(pSigDoc, pDf, (const char*)arrTempFiles[i], hFile, &mbuf1); ddocDebug(3, "createSignedXMLDoc", "Use temp file: %s rc: %d", arrTempFiles[i], err); if(!err && pMBufXML) ddocMemAppendData(pMBufXML, mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); ddocDebug(3, "createSignedXMLDoc", "Used temp file: %s", arrTempFiles[i]); } else if(checkFileExists(pDf->szFileName) || pDf->mbufContent.pMem) { // TODO: test id out-mem sign works ddocDebug(3, "createSignedXMLDoc", "Create new data file: %s", pDf->szFileName); err = generateDataFileXML(pSigDoc, pDf, (const char*)pDf->szFileName, hFile, &mbuf1); ddocDebug(3, "createSignedXMLDoc", "Create new data file: %s rc: %d", pDf->szFileName, err); if(!err && pMBufXML) ddocMemAppendData(pMBufXML, mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); ddocDebug(3, "createSignedXMLDoc", "Created new data file: %s", pDf->szFileName); } if(szSigDocFile) fputs("\n", hFile); if(pMBufXML) ddocMemAppendData(pMBufXML, "\n", -1); } ddocDebug(3, "createSignedXMLDoc", "Gen sigs"); for(i = 0; i < pSigDoc->nSignatures; i++) { ddocDebug(3, "createSignedXMLDoc", "Gen sig: %d", i); // VS: if Signature has been read from file then // use the original content if(pSigDoc->pSignatures[i]->mbufOrigContent.pMem) { if(szSigDocFile) fwrite(pSigDoc->pSignatures[i]->mbufOrigContent.pMem, sizeof(char), pSigDoc->pSignatures[i]->mbufOrigContent.nLen, hFile); if(pMBufXML) err = ddocMemAppendData(pMBufXML, (const char*)pSigDoc->pSignatures[i]->mbufOrigContent.pMem, pSigDoc->pSignatures[i]->mbufOrigContent.nLen); } else { err = addSignatureInfoXML(&mbuf1, pSigDoc, pSigDoc->pSignatures[i]); if(szSigDocFile) fputs((char*)mbuf1.pMem, hFile); if(pMBufXML) err = ddocMemAppendData(pMBufXML, (const char*)mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); } } // for i < pSigDoc->nSignatures if(szSigDocFile) { fputs("", hFile); } if(hFile) { ddocDebug(3, "createSignedXMLDoc", "Closing FILE: %s", buf1); fclose(hFile); } if(pMBufXML) ddocMemAppendData(pMBufXML, "", -1); ddocDebug(3, "createSignedXMLDoc", "Generated"); // delete temporary files we created when // extracting the data files from original XML signed doc // VS: fix the bug of deleting input files // This happened because prefix was empty and // thus doc names where the same as original // input file names if(szOldFile && arrTempFiles) { // check if temp files were created for(i = 0; i < nFiles; i++) { pDf = getDataFile(pSigDoc, i); // ignore not being able to delete temp file. It returns -1 //_unlink((const char*)arrTempFiles[i]); free(arrTempFiles[i]); } free(arrTempFiles); } } else { err = ERR_FILE_WRITE; #ifdef WIN32 ddocDebug(1, "createSignedXMLDoc", "Error1: %d opening file: %s errno: %d doserrno: %d perror: %s", err, szSigDocFile, _errno, _doserrno, strerror(_errno)); if(_errno == 1933280595) { err = ERR_NETWORK_SYNC; ddocDebug(1, "createSignedXMLDoc", "Error2 %d opening file for writing. Network sync err?", err); } #endif } ddocDebug(3, "createSignedXMLDoc", "Cleanup1"); #ifdef WIN32 if(convFileName) free(convFileName); #endif if (err != ERR_OK) SET_LAST_ERROR(err); ddocDebug(3, "createSignedXMLDoc", "Done"); return err; } //-------------------------------------------------- // Creates a new signed document // pSigDoc - signed doc info // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int createSignedDoc(SignedDoc* pSigDoc, const char* szOldFile, const char* szOutputFile) { int err = ERR_OK; int nWait, nRetries, i; long lSize = 0; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(szOutputFile); RETURN_IF_NULL_PARAM(pSigDoc->szFormat); if(szOldFile && strlen(szOldFile)) { calculateFileSize(szOldFile, &lSize); ddocDebug(3, "createSignedDoc", "Old file: %s ddoc-size: %ld", szOldFile, lSize); if(lSize == 0) { ddocDebug(1, "createSignedDoc", "Invalid old file: %s ddoc-size: %ld", szOldFile, lSize); SET_LAST_ERROR(ERR_FILE_READ); return ERR_FILE_READ; } } clearErrors(); if(hasSignatureWithWrongDataFileHash(pSigDoc)) { ddocDebug(1, "createSignedDoc", "Cannot save ddoc: %s size: %ld with invalid DataFile hashes!", szOldFile, lSize); return ERR_FILE_WRITE; } if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) && !strcmp(pSigDoc->szFormat, DIGIDOC_XML_1_1_NAME)) { err = createSignedXMLDoc(pSigDoc, szOldFile, szOutputFile, NULL); ddocDebug(3, "createSignedDoc", "Done, rc: %d", err); #ifdef WIN32 if(err = ERR_NETWORK_SYNC) { nWait = 1; // oli parameeter NETWORK_SYNC_WAIT nRetries = 3; // oli parameeter NETWORK_SYNC_RETRIES ddocDebug(3, "createSignedDoc", "Network sync wait: %d retries: %d", nWait, nRetries); for(i = 0; (err == ERR_NETWORK_SYNC) && (i < nRetries); i++) { ddocDebug(3, "createSignedDoc", "Network sync wait: %d", nWait); Sleep(1000 * nWait); ddocDebug(3, "createSignedDoc", "Network sync write: %d of: %d retries", i, nRetries); clearErrors(); // reset errors from past failed write attempt err = createSignedXMLDoc(pSigDoc, szOldFile, szOutputFile, NULL); } } #endif } else err = ERR_UNSUPPORTED_FORMAT; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Creates a new signed document in memory buffer // pSigDoc - signed doc info // szOldFile - name of old file on disk to copy DataFile contents // pMBuf - buffer for new digidoc document // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int createSignedDocInMemory(SignedDoc* pSigDoc, const char* szOldFile, DigiDocMemBuf* pMBuf) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pMBuf); RETURN_IF_NULL_PARAM(pSigDoc->szFormat); clearErrors(); if(hasSignatureWithWrongDataFileHash(pSigDoc)) { ddocDebug(1, "createSignedDocInMemory", "Cannot save ddoc: %s with invalid DataFile hashes!", szOldFile); return ERR_FILE_WRITE; } if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) && !strcmp(pSigDoc->szFormat, DIGIDOC_XML_1_1_NAME)) { err = createSignedXMLDoc(pSigDoc, szOldFile, NULL, pMBuf); } else err = ERR_UNSUPPORTED_FORMAT; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Removes incomplete or orphoned signatures. // Signature is incomplete if it hasn't got the signature // value // pSigDoc - signed doc info // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int removeIncompleteSignatures(SignedDoc* pSigDoc) { int err = ERR_OK, i, n, b; SignatureInfo *pSigInfo; RETURN_IF_NULL_PARAM(pSigDoc); do { b = 0; n = getCountOfSignatures(pSigDoc); for(i = 0; i < n; i++){ pSigInfo = getSignature(pSigDoc, i); if(!pSigInfo->pSigValue || (pSigInfo->pSigValue && !pSigInfo->pSigValue->mbufSignatureValue.pMem)) { SignatureInfo_free(pSigInfo); // remove incomplete signature break; } } } while(b); return err; } //-------------------------------------------------- // Checks for incomplete or orphoned signatures. // Signature is incomplete if it hasn't got the signature // value // pSigDoc - signed doc info // returns error code if DigiDoc has orphoned signature or ERR_OK for success //-------------------------------------------------- EXP_OPTION int hasIncompleteSignatures(SignedDoc* pSigDoc) { int i; SignatureInfo *pSigInfo; RETURN_IF_NULL_PARAM(pSigDoc); for(i = 0; i < getCountOfSignatures(pSigDoc); i++){ pSigInfo = getSignature(pSigDoc, i); if(!pSigInfo->pSigValue || (pSigInfo->pSigValue && !pSigInfo->pSigValue->mbufSignatureValue.pMem)) { return ERR_ORPHONED_SIGNATURE; } } return ERR_OK; } libdigidoc-3.10.5/libdigidoc/DigiDocEncGen.h0000664000372000037200000000601013560273131020115 0ustar travistravis#ifndef __DIGIDOC_ENC_GEN_H__ #define __DIGIDOC_ENC_GEN_H__ //================================================== // FILE: DigiDocEncGen.h // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDocEnc XML generation // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 11.10.2004 Veiko Sinivee // Creation //================================================== #include #include #ifdef __cplusplus extern "C" { #endif //-------------------------------------------------- // Generates XML for element // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencGenEncryptedData_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf); //-------------------------------------------------- // Writes encrypted data to a file // pEncData - encrypted data object [REQUIRED] // szFileName - name of the file to write the data [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencGenEncryptedData_writeToFile(DEncEncryptedData* pEncData, const char* szFileName); //-------------------------------------------------- // Generates the header of XML for element // This contains everything upto the start of base64 encoded cipher data // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptedData_header_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf); //-------------------------------------------------- // Generates the trailer of XML for element // These are all the XML constructs following the // base64 encoded cipher data. // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptedData_trailer_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf); #ifdef __cplusplus } #endif #endif // __DIGIDOC_ENC_GEN_H__ libdigidoc-3.10.5/libdigidoc/resource.h0000664000372000037200000000066613560273131017375 0ustar travistravis//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by DlgUnit.rc // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif libdigidoc-3.10.5/libdigidoc/DigiDocEncSAXParser.h0000664000372000037200000000551613560273131021226 0ustar travistravis#ifndef __DIGIDOC_ENC_SAX_PARSER_H__ #define __DIGIDOC_ENC_SAX_PARSER_H__ //================================================== // FILE: DigiDocEncSAXParser.h // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDocEnc XML SAX parsing // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 11.10.2004 Veiko Sinivee // Creation //================================================== #include #include #ifdef __cplusplus extern "C" { #endif //-------------------------------------------------- // Reads in encrypted XML document. // ppEncData - address for new encrypted data object [REQUIRED] // szFileName - input file name // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencSaxReadEncryptedData(DEncEncryptedData** ppEncData, const char* szFileName); //-------------------------------------------------- // Reads in encrypted XML document. // ppEncData - address for new encrypted data object [REQUIRED] // pData - input data [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencSaxReadEncryptedDataFromMemory(DEncEncryptedData** ppEncData, DigiDocMemBuf* pData); //-------------------------------------------------- // Decrypts an encrypted XML document and stores the // cleartext data in another document. Please note that szCertCN // parameter is no longer required as the users cert will // bea read from smartcard using PKCS#11 // szInputFileName - input file name [REQUIRED] // szOutputFileName - output file name [REQUIRED] // szPin - PIN1 of the id-card to decrypt the transport key [REQUIRED] // szPkcs12File - pkcs12 key container filename [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencSaxReadDecryptFile(const char* szInputFileName, const char* szOutputFileName, const char* szPin, const char* szPkcs12File); #ifdef __cplusplus } #endif #endif // __DIGIDOC_ENC_SAX_PARSER_H__ libdigidoc-3.10.5/libdigidoc/DigiDocCert.h0000664000372000037200000003546513560273131017673 0ustar travistravis#ifndef __DIGI_DOC_CERT_H__ #define __DIGI_DOC_CERT_H__ //================================================== // FILE: DigiDocCert.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for certificate handling // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details.ode // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= //================================================== #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include // structure for reading certificate policies typedef struct PolicyIdentifier_st { char* szOID; // stringified OID char* szCPS; // CPS URL char* szUserNotice; // user notice } PolicyIdentifier; EXP_OPTION int ReadPrivateKey(EVP_PKEY **privKey, const char *keyfile, const char* passwd, int format); EXP_OPTION int WritePrivateKey(EVP_PKEY *privKey, const char *keyfile, const char* passwd, int format); int ReadPublicKey(EVP_PKEY **pkey, const char *certfile); int GetPublicKey(EVP_PKEY **pubKey, const X509* x509); //-------------------------------------------------- // Writes a private key and cert to a PEM file // privKey - private key // pCert - certificate // keyfile - name of the private key file // passwd - key password (problems with encrypted passwwords!) //-------------------------------------------------- EXP_OPTION int ddocWriteKeyAndCertPem(EVP_PKEY *privKey, X509* pCert, const char *keyfile, const char* passwd); EXP_OPTION int ReadCertificate(X509 **x509, const char *certfile); EXP_OPTION int ReadCertificateNoErr(X509 **x509, const char *szCertfile); EXP_OPTION int ReadCertSerialNumber(char* szSerial, int nMaxLen, X509 *x509); EXP_OPTION int ReadCertificateByPKCS12(X509 **x509, const char *pkcs12file, const char *passwd, EVP_PKEY **pkey); // Decodes binary (DER) cert data and returns a cert object EXP_OPTION int ddocDecodeX509Data(X509 **ppX509, const byte* certData, int certLen); // Decodes base64 (PEM) cert data and returns a cert object EXP_OPTION int ddocDecodeX509PEMData(X509 **ppX509, const char* certData, int certLen); // get certificate PEM form EXP_OPTION int getCertPEM(X509* cert, int bHeaders, char** buf); // retrieves this certificates serial number EXP_OPTION int GetCertSerialNumber(char* szSerial, int nMaxLen, const char *szCertfile); // Returns the certificates validity first date EXP_OPTION int getCertNotBefore(const SignedDoc* pSigDoc, X509* cert, char* timestamp, int len); // Retrieves the certificates first validity time as tim_t in GMT zone EXP_OPTION time_t getCertNotBeforeTimeT(X509* pCert); // Retrieves the certificates last validity time as tim_t in GMT zone EXP_OPTION time_t getCertNotAfterTimeT(X509* pCert); // Returns the certificates validity last date EXP_OPTION int getCertNotAfter(const SignedDoc* pSigDoc, X509* cert, char* timestamp, int len); // Saves the certificate in a file EXP_OPTION int saveCert(X509* cert, const char* szFileName, int nFormat); // decodes PEM cert data EXP_OPTION void* decodeCert(const char* pemData); // encodes certificate EXP_OPTION void encodeCert(const X509* x509, char * encodedCert, int* encodedCertLen); // Reads certificates PolicyIdentifiers and returns // them in a newly allocated structure EXP_OPTION int readCertPolicies(X509* pX509, PolicyIdentifier** pPolicies, int* nPols); // Frees policy identifiers array EXP_OPTION void PolicyIdentifiers_free(PolicyIdentifier* pPolicies, int nPols); // Checks if this is a company CPS policy EXP_OPTION int isCompanyCPSPolicy(PolicyIdentifier* pPolicy); EXP_OPTION int isCertValid(X509* cert, time_t tDate); EXP_OPTION int isCertSignedBy(X509* cert, const char* cafile); int writeCertToXMLFile(BIO* bout, X509* cert); //-------------------------------------------------- // Verifys a certificate by sending an OCSP_REQUEST object // to the notary server and checking the response. // Uses servers timestamps hash code as nonce value. // pCert - certificate to test // caCerts - responder CA certs chain // notaryCert - notarys cert search // proxyHost - proxy servers name // proxyPort - proxy servers port // notaryURL - notarys URL // ppResp - address to return OCSP response. Use NULL if // you don't want OCSP response to be returned // return 0 for OK, or error code //-------------------------------------------------- EXP_OPTION int verifyCertificateByOCSP(X509* pCert, const X509** caCerts, const X509* notaryCert, char* notaryURL, char* proxyHost, char* proxyPort, const char* pkcs12file, const char* pkcs12paswd, OCSP_RESPONSE **ppResp); //-------------------------------------------------- // Verifys a certificate by sending an OCSP_REQUEST object // to the notary server and checking the response. // Uses servers timestamps hash code as nonce value. // pCert - certificate to test // caCerts - responder CA certs chain // notaryCert - notarys cert search // proxyHost - proxy servers name // proxyPort - proxy servers port // notaryURL - notarys URL // ppResp - address to return OCSP response. Use NULL if // you don't want OCSP response to be returned // return 0 for OK, or error code //-------------------------------------------------- EXP_OPTION int verifyCertificateByOCSPWithIp(X509* pCert, const X509** caCerts, const X509* notaryCert, char* notaryURL, char* proxyHost, char* proxyPort, const char* pkcs12file, const char* pkcs12paswd, OCSP_RESPONSE **ppResp, unsigned long ip); //-------------------------------------------------- // Returns the certificates sha1 hash. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetDigest(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates public key sha1 hash. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetPubkeyDigest(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates issuer name. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetIssuerDN(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates subject name. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectDN(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates subject name sha1 hash. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetSubjectNameDigest(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates issuer name sha1 hash. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetIssuerNameDigest(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates DN. // Do not call directly, subject to change // pName - certificate X509 name // pMemBuf - memory buffer object for storing DN // bIssuer - 1=issuer, 0=subject // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetDNFromName(X509_NAME* pName, DigiDocMemBuf* pMemBuf); #define KUIDX_DIGITAL_SIGNATURE 0 #define KUIDX_NON_REPUDIATION 1 #define KUIDX_KEY_ENCIPHERMENT 2 #define KUIDX_DATA_ENCIPHERMENT 3 #define KUIDX_KEY_AGREEMENT 4 #define KUIDX_KEY_CERT_SIGN 5 #define KUIDX_CRL_SIGN 6 #define KUIDX_ENCIPHERMENT_ONLY 7 #define KUIDX_DECIPHERMENT_ONLY 8 #define NID_firstName 99 #define NID_lastName 100 #define NID_perCode 105 #define NID_countryName 14 #define NID_serialNumber 105 #define NID_organization 17 #define NID_organizationUnit 18 #define NID_commonName 13 #define NID_emailAddress 48 //-------------------------------------------------------- // Checks if the desired key-usage bit is set on a given cert // pCert - certificate // nBit - flag index // return 1 if bit is set //-------------------------------------------------------- EXP_OPTION int ddocCertCheckKeyUsage(X509 *pCert, int nBit); //-------------------------------------------------- // Returns the certificates subject CN // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectCN(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates issuer CN // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetIssuerCN(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates subject first name // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectFirstName(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates subject last name // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectLastName(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates subject personal code // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectPerCode(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates subject country code // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectCountryName(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates subject organization // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectOrganization(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Returns the certificates subject organization unit // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectOrganizationUnit(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Reads certificates authority key identifier // pCert - certificate // pMemBuf - memory buffer to return data //-------------------------------------------------- EXP_OPTION int readAuthorityKeyIdentifier(X509* pCert, DigiDocMemBuf* pMemBuf); //-------------------------------------------------- // Reads certificates subject key identifier // pCert - certificate // pMemBuf - memory buffer to return data //-------------------------------------------------- EXP_OPTION int readSubjectKeyIdentifier(X509* pCert, DigiDocMemBuf* pMemBuf); EXP_OPTION int ddocCertGetDNPart(X509* pCert, DigiDocMemBuf* pMemBuf, int nNid, int bIssuer); EXP_OPTION int ddocCertGetDN(X509* pCert, DigiDocMemBuf* pMemBuf, int bIssuer); //================< deprecated functions> ================================= // these functions are deprecated. Use the replacements in DigiDocCert.h // these functions will be removed in future releases! #ifdef WITH_DEPRECATED_FUNCTIONS // decodes cert data - deprecated! // USE ddocDecodeX509PEMData() instead! EXP_OPTION int decodeCertificateData(X509 **newX509, const byte* certData, int certLen); // Returns the certificates issuer name // USE: ddocCertGetIssuerDN() EXP_OPTION int getCertIssuerName(X509* cert, char* buf, int* buflen); // Returns the certificates subject name // USE: ddocCertGetSubjectDN() EXP_OPTION int getCertSubjectName(X509* cert, char* buf, int* buflen); // reads cert issuers CN // USE: ddocCertGetIssuerCN() EXP_OPTION int getCertIssuerCN(X509* cert, char* buf, int* buflen, int bUTF8); // Returns the certificates subjects DN // USE: ddocCertGetSubjectDN() EXP_OPTION int getCertSubjectDN(X509* cert, char* buf, int* buflen, int bUTF8); // reads cert subjects CN // USE: ddocCertGetSubjectCN() EXP_OPTION int getCertSubjectCN(X509* cert, char* buf, int* buflen, int bUTF8); // get certificate owners id-code // USE: ddocCertGetSubjectPerCode() EXP_OPTION int getCertOwnerCode(const X509* pCert, char* buf, int len); //-------------------------------------------------- // Returns the desired item from string rep of DN // sDn - certificate DN // sId - searched DN part // pMBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocGetDNPartFromString(const char* sDn, const char* sId, DigiDocMemBuf* pMBuf); #endif // WITH_DEPRECATED_FUNCTIONS #ifdef __cplusplus } #endif #endif // __DIGI_DOC_CERT_H__ libdigidoc-3.10.5/libdigidoc/DlgUnit.c0000664000372000037200000005060513560273131017105 0ustar travistravis//================================================== // FILE: DlgUnit.c // PROJECT: Digi Doc // DESCRIPTION: Low-level built dialog with list selection capability // UPDATES: // // Created by Aare Amenberg 06/10/2003 //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //================================================== #include #include #include #include #include "DlgUnit.h" HINSTANCE hInstanceCOM = NULL; extern int RunDialogUnitSimple(char *psList[], char *psCaption, char *psHeader, char *psOkButton, char *psCancelButton, int iWinWidth, int iWinHeight); EXTERN_C IMAGE_DOS_HEADER __ImageBase; #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) //min and max sizes for dialog window #define dDLGWIN_MINWIDTH 170 #define dDLGWIN_MAXWIDTH 800 #define dDLGWIN_MINHEIGHT 150 #define dDLGWIN_MAXHEIGHT 600 //maximum items in the listbox //Developer can change the value #define dDLGMAXLISTBOXSIZE 1024 //maximum item length //Developer can change the value #define dDLGMAXITEMSIZE 512 //temporary messagebox buffer len #define dDLGTEMPBUFLEN 64 //internal errors #define dDLGNOERRORS 0 #define dDLGERROR -1 #define dDLGNOSELECTION -9 //output error #define dDLGERROR_OUT -2 //can't initiate dialog #define dDLGNOSELECTION_OUT -1 //no selection, cancel //if output result >= 0, then item is selected //User texts max length (headers,title,tooltips,etc.) #define dDLGUSERTEXTMAXLEN 128 //Dialog functions static BOOL CALLBACK WndDlgUnitProc(HWND, UINT, WPARAM, LPARAM); static void CalculateDialogSize(HWND hDlg); static void SetDialogItemSize(HWND hWnd, int iWOffs, int iHOffs); static void SetDialogItemPosition(HWND hWnd, int iWOffs, int iHOffs); static void CenterDialogOnScreen(HWND hDlg, HWND hMain); static void Dialog_End(HWND hDlg, BOOL fCancel); static int Dialog_Init(HWND hDlg); static void DispError(char *psError); //ListView functions static BOOL ListViewSetHeaderColumn(HWND hWndList, int iIndex, int iSize, char *psHeader); static int ListViewCalcColumnSize(HWND hWndList, int iIndex, int iSizePercent); static BOOL ListViewInserRow(HWND hWndList, int iIndex, char *psVal1, char *psVal2, char *psVal3, char *psVal4, char *psVal5); static BOOL ListViewInsertItem(HWND hWndListView, int iIndex, char *psData); //Tooltip functions static void ToolTipInitiate(HWND hWndDlg); static HWND ToolTipCreate (HWND hParent); static void ToolTipForItem (HWND hwnd,char *psText,HWND hTip); //User defined texts static char sDlgCaption[dDLGUSERTEXTMAXLEN+1] ="DigiDoc"; static char sGrpHeader[dDLGUSERTEXTMAXLEN+1] ="Select certificate:"; static char sOkButtonText[dDLGUSERTEXTMAXLEN+1] ="&Ok"; static char sCancelButtonText[dDLGUSERTEXTMAXLEN+1] ="&Cancel"; //ListView headers static char sListColumn1[dDLGUSERTEXTMAXLEN+1] ="Issuer"; static char sListColumn2[dDLGUSERTEXTMAXLEN+1] ="Friendly name"; static char sListColumn3[dDLGUSERTEXTMAXLEN+1] ="Valid from"; static char sListColumn4[dDLGUSERTEXTMAXLEN+1] ="Valid to"; static char sListColumn5[dDLGUSERTEXTMAXLEN+1] ="CSP"; //User defined tooltips static char sDlgToolTip[dDLGUSERTEXTMAXLEN+1] ="Certificate selection"; static char sListToolTip[dDLGUSERTEXTMAXLEN+1] ="Selecting certificate press \nor click button\nor mouse double-click"; static char sOkButtonToolTip[dDLGUSERTEXTMAXLEN+1] ="Select and close dialog"; static char sCancelButtonToolTip[dDLGUSERTEXTMAXLEN+1]="Cancel selection"; static char **psListItems=NULL; //Listbox items static HWND hToolTipWnd=NULL; //ToolTip window static int iDlgWidth = 800; static int iDlgHeight = 170; // //Set texts // //psCaption - dialog caption/title // if NULL, then no caption //psHeader - listbox header // if NULL, then no header //psOkButton - Ok button label // if NULL or zero length string, then "&Ok" //psCancelButton - Cancel button label // if NULL or zero length string, then "&Cancel" EXP_OPTION int DialogUnitSetTexts(char *psCaption, char *psHeader, char *psOkButton, char *psCancelButton) { if (psCaption != NULL) lstrcpyn(sDlgCaption,psCaption,dDLGUSERTEXTMAXLEN); if (psHeader != NULL) lstrcpyn(sGrpHeader,psHeader,dDLGUSERTEXTMAXLEN); if (psOkButton != NULL) lstrcpyn(sOkButtonText,psOkButton,dDLGUSERTEXTMAXLEN); if (psCancelButton != NULL) lstrcpyn(sCancelButtonText,psCancelButton,dDLGUSERTEXTMAXLEN); //if not specified, then Ok string if (lstrlen(sOkButtonText) == 0) lstrcpy(sOkButtonText,"&Ok"); //if not specified, then Ok string if (lstrlen(sCancelButtonText) == 0) lstrcpy(sCancelButtonText,"&Cancel"); return(0); } EXP_OPTION int DialogUnitSetHeaders(char *psCol1, char *psCol2, char *psCol3, char *psCol4, char *psCol5) { if (psCol1 != NULL) lstrcpyn(sListColumn1,psCol1,dDLGUSERTEXTMAXLEN); if (psCol2 != NULL) lstrcpyn(sListColumn2,psCol2,dDLGUSERTEXTMAXLEN); if (psCol3 != NULL) lstrcpyn(sListColumn3,psCol3,dDLGUSERTEXTMAXLEN); if (psCol4 != NULL) lstrcpyn(sListColumn4,psCol4,dDLGUSERTEXTMAXLEN); if (psCol5 != NULL) lstrcpyn(sListColumn5,psCol5,dDLGUSERTEXTMAXLEN); return(0); } EXP_OPTION int DialogUnitSetToolTips(char *psCommon, char *psListView, char *psOkButton, char *psCancelButton) { if (psCommon != NULL) lstrcpyn(sDlgToolTip,psCommon,dDLGUSERTEXTMAXLEN); else sDlgToolTip[0] = 0; if (psListView != NULL) lstrcpyn(sListToolTip,psListView,dDLGUSERTEXTMAXLEN); else sListToolTip[0] = 0; if (psOkButton != NULL) lstrcpyn(sOkButtonToolTip,psOkButton,dDLGUSERTEXTMAXLEN); else sOkButtonToolTip[0] = 0; if (psCancelButton != NULL) lstrcpyn(sCancelButtonToolTip,psCancelButton,dDLGUSERTEXTMAXLEN); else sCancelButtonToolTip[0] = 0; return(0); } // //Dialog main function // //Limitations: // Max. items in the listbox dDLGMAXLISTBOXSIZE // Max. item size in the listbox dDLGMAXITEMSIZE // Dialogbox sizes dDLGWIN_* values // //No dynamic memory allocation // //Selection is accepted if, list item is selected and // - user pressed "Ok" button // - user double-clicks on the listbox item // - user pressed key // //If no items in the psList or psList is NULL, //then Ok button is disabled // //psList - pointer arrays of listbox elements // last item must be NULL //psCaption - dialog caption/title // if NULL, then no caption //psHeader - listbox header // if NULL, then no header //psOkButton - Ok button label // if NULL or zero length string, then "&Ok" //psCancelButton - Cancel button label // if NULL or zero length string, then "&Cancel" //iWinWidth - dialogbox width, if 0 then default size // //iWinHeight - dialogbox height, if 0 then default size // //returns -2 (dDLGERROR_OUT) if dialog error //returns -1 (dDLGNOSELECTION_OUT) if listbox item not selected (Cancel button) // >=0 selected item index in the psList array // // int RunDialogUnit(char *psList[], int iWinWidth, int iWinHeight) { char sTemp[dDLGTEMPBUFLEN]; DWORD dwRes; int iRes = dDLGERROR_OUT; INITCOMMONCONTROLSEX iccex; //LPTSTR lpName; //HRSRC hRes; //HGLOBAL hGlobal; iDlgWidth = iWinWidth; iDlgHeight = iWinHeight; //if not allowed value, then default size if (iDlgWidth < dDLGWIN_MINWIDTH || iDlgWidth > dDLGWIN_MAXWIDTH) iDlgWidth = 0; //if not allowed value, then default size if (iDlgHeight < dDLGWIN_MINHEIGHT || iDlgHeight > dDLGWIN_MAXHEIGHT) iDlgHeight = 0; //set items psListItems = psList; //Init common control iccex.dwICC = ICC_WIN95_CLASSES; iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); if (InitCommonControlsEx(&iccex) == TRUE) //InitCommonControls(); { //Starts dialog, return value from function Dialog_End //hRes = FindResource(NULL,"#220", RT_DIALOG); //hRes = FindResource(NULL,MAKEINTRESOURCE(IDD_DLG_UNIT), RT_DIALOG); //hGlobal = LoadResource(NULL,hRes); //dwRes = IDD_DLG_UNIT; //lpName = MAKEINTRESOURCE(IDD_DLG_UNIT); iRes = DialogBox(HINST_THISCOMPONENT, MAKEINTRESOURCE(IDD_DLG_UNIT), NULL, (DLGPROC)WndDlgUnitProc); //iRes = DialogBox(hInstanceCOM, MAKEINTRESOURCE(IDD_DLG_UNIT), NULL, (DLGPROC)WndDlgUnitProc); if (iRes == dDLGERROR) iRes = dDLGERROR_OUT; } //if GetLastError returns nonzero, then dialog opening error if (iRes == dDLGERROR_OUT) { dwRes = GetLastError(); if (dwRes != 0) { //prints Windows errorcode snprintf(sTemp, sizeof(sTemp), "DigiDoc Dialog Error=%d",dwRes); //DispError(sTemp); } #ifdef WIN32_CSP iRes = RunDialogUnitSimple(psList, sDlgCaption, sGrpHeader, sOkButtonText, sCancelButtonText, iDlgWidth, iDlgHeight); #endif } if (iRes == dDLGNOSELECTION) iRes = dDLGNOSELECTION_OUT; return(iRes); } //Dialog callback functions static BOOL CALLBACK WndDlgUnitProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { BOOL fRes = FALSE; DWORD dwNotifyCode; LPNMHDR pnmh; switch (message) { case WM_INITDIALOG: //dialog init Dialog_Init(hDlg); fRes = TRUE; break; case WM_CLOSE: //user closes dialog from the system menu Dialog_End(hDlg, TRUE); fRes = TRUE; break; case WM_NOTIFY: pnmh = (LPNMHDR)lParam; if (pnmh != NULL && pnmh->code == NM_DBLCLK) { Dialog_End(hDlg,FALSE); fRes = TRUE; } break; case WM_COMMAND: { dwNotifyCode = HIWORD(wParam); //user presses dblclick in the listbox if (dwNotifyCode == LBN_DBLCLK) { Dialog_End(hDlg,FALSE); fRes = TRUE; break; } switch (wParam) { case IDOK: //user pressed OK button Dialog_End(hDlg,FALSE); fRes = TRUE; break; case IDCANCEL: //user pressed Cancel button Dialog_End(hDlg, TRUE); fRes = TRUE; break; } } } return(fRes); } //Dialog end function //fCancel - TRUE, if user pressed Cancel button // static void Dialog_End(HWND hDlg, BOOL fCancel) { int iRes = dDLGNOSELECTION; //if TRUE, then always (dDLGNOSELECTION) if (fCancel == FALSE) { //if listbox item selected, then retuns selected item index iRes = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_LISTVIEW)); } if (hToolTipWnd != NULL) { DestroyWindow(hToolTipWnd); hToolTipWnd = NULL; } EndDialog(hDlg, iRes); } //Dialog init // static int Dialog_Init(HWND hDlg) { int iRes = dDLGNOERRORS; UINT iState; UINT iMask; DWORD dwStyle; int iItems = 0; HWND hWndListView; //Set dialog caption SetWindowText(hDlg, (LPTSTR)sDlgCaption); //Set listbox header SetDlgItemText(hDlg,IDC_GROUPBOX,(LPTSTR)sGrpHeader); //Set Ok button label SetDlgItemText(hDlg,IDOK,(LPTSTR)sOkButtonText); //Set Cancel button label SetDlgItemText(hDlg,IDCANCEL,(LPTSTR)sCancelButtonText); //Calculate dialog size CalculateDialogSize(hDlg); //Center dialog CenterDialogOnScreen(hDlg,NULL); //Set topmost SetWindowPos(hDlg,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); //Set ListView params hWndListView = GetDlgItem(hDlg,IDC_LISTVIEW); dwStyle = (LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP); SendMessage(hWndListView,LVM_SETEXTENDEDLISTVIEWSTYLE,0,dwStyle); // ToolTipInitiate(hDlg); ToolTipForItem (GetDlgItem(hDlg,IDOK), sOkButtonToolTip, hToolTipWnd); ToolTipForItem (GetDlgItem(hDlg,IDCANCEL), sCancelButtonToolTip, hToolTipWnd); ToolTipForItem (hWndListView, sListToolTip, hToolTipWnd); ToolTipForItem (hDlg, sDlgToolTip, hToolTipWnd); ToolTipForItem (ListView_GetHeader(hWndListView), sDlgToolTip, hToolTipWnd); // //Set ListView headers ListViewSetHeaderColumn(hWndListView, 0, 25, sListColumn1); ListViewSetHeaderColumn(hWndListView, 1, 25, sListColumn2); ListViewSetHeaderColumn(hWndListView, 2, 15, sListColumn3); ListViewSetHeaderColumn(hWndListView, 3, 15, sListColumn4); ListViewSetHeaderColumn(hWndListView, 4, 20, sListColumn5); //Set ListView rows while (psListItems != NULL && *psListItems != NULL && iItems < dDLGMAXLISTBOXSIZE) { if (lstrlen(*psListItems) < dDLGMAXITEMSIZE) { ListViewInsertItem(hWndListView,iItems,*psListItems); ++iItems; } else iRes = dDLGERROR; ++psListItems; } if (iRes != dDLGNOERRORS) DispError("DigiDoc Dialog data error"); if (iItems > 0) { EnableWindow(GetDlgItem(hDlg, IDOK),TRUE); iState = LVIS_FOCUSED | LVIS_SELECTED; iMask = LVIS_FOCUSED | LVIS_SELECTED; ListView_SetItemCount(hWndListView,iItems); ListView_SetItemState(hWndListView, 0, iState, iMask); //iState = ListView_GetItemCount(hWndListView); //iMask = ListView_GetNextItem(hWndListView,-1,LVNI_FOCUSED); //SetFocus(hWndList); } else EnableWindow(GetDlgItem(hDlg, IDOK),FALSE); return(iRes); } //Parse \t separated texts and add to the ListView static BOOL ListViewInsertItem(HWND hWndListView, int iIndex, char *psData) { BOOL fRes = TRUE; int iI=0; char sVal[5][dDLGMAXITEMSIZE+1]; char *psBeg; char *psEnd; sVal[0][0] = 0; sVal[1][0] = 0; sVal[2][0] = 0; sVal[3][0] = 0; sVal[4][0] = 0; psBeg = psData; while (psBeg != NULL && *psBeg != 0) { psEnd = strchr(psBeg,'\t'); if (psEnd != NULL) { lstrcpyn(sVal[iI],psBeg,(psEnd-psBeg)+1); psBeg=psEnd+1; } else { lstrcpyn(sVal[iI],psBeg,dDLGMAXITEMSIZE); break; } ++iI; } // ListViewInserRow(hWndListView, iIndex, sVal[0], sVal[1], sVal[2], sVal[3], sVal[4]); return(fRes); } //Calculate dialog size // static void CalculateDialogSize(HWND hDlg) { RECT rcDlg; // Dialog window rect int iWOffs; int iHOffs; if (iDlgWidth > 0 && iDlgHeight > 0) { GetWindowRect(hDlg,&rcDlg); iWOffs = iDlgWidth - (rcDlg.right - rcDlg.left); iHOffs = iDlgHeight - (rcDlg.bottom - rcDlg.top); SetDialogItemSize(hDlg,iWOffs,iHOffs); SetDialogItemSize(GetDlgItem(hDlg,IDC_LISTVIEW),iWOffs,iHOffs); SetDialogItemSize(GetDlgItem(hDlg,IDC_GROUPBOX),iWOffs,iHOffs); SetDialogItemPosition(GetDlgItem(hDlg,IDOK),iWOffs,iHOffs); SetDialogItemPosition(GetDlgItem(hDlg,IDCANCEL),iWOffs,iHOffs); } } //Set dialog item size // static void SetDialogItemSize(HWND hWnd, int iWOffs, int iHOffs) { RECT rcItm; // Dialog window rect int iWidth, iHeight; // Width and height GetWindowRect(hWnd, &rcItm); iWidth = rcItm.right - rcItm.left; iHeight = rcItm.bottom - rcItm.top; SetWindowPos(hWnd,NULL,0,0,iWidth+iWOffs, iHeight+iHOffs,SWP_NOMOVE|SWP_NOZORDER); } //Set dialog item pos // static void SetDialogItemPosition(HWND hWnd, int iWOffs, int iHOffs) { RECT rcCln; RECT rcItm; // Dialog item rect RECT rcParent; // Parent item rect int iLeft; int iTop; int iTitleW; // GetWindowRect retrieves screen coordinates GetWindowRect(hWnd, &rcItm); //GetClientRect(hWnd, &rcItm); //Changed by A.Amenberg 27.06.2003 //GetAncestor supported from Win98 and WinNT SP4 //GetWindowRect(GetAncestor(hWnd, GA_PARENT), &rcParent); GetWindowRect(GetParent(hWnd), &rcParent); GetClientRect(GetParent(hWnd), &rcCln); iTitleW = rcParent.bottom - rcCln.bottom; // for SetWindowPos we need left and right on PARENT. iLeft = (rcItm.left - rcParent.left) + iWOffs; iTop = (rcItm.top - rcParent.top) + iHOffs - iTitleW; // move, don't resize SetWindowPos(hWnd, NULL, iLeft, iTop, 0, 0, SWP_NOSIZE|SWP_NOZORDER); } //Center dialog //hMain - parent window, if NULL, then center in desktop // static void CenterDialogOnScreen(HWND hDlg, HWND hMain) { RECT rcParent; // Parent window client rect RECT rcDlg; // Dialog window rect int iLeft, iTop; // Top-left coordinates int iWidth, iHeight; // Width and height HWND hwnd; // Get frame window client rect in screen coordinates if (hMain == NULL) hwnd = GetDesktopWindow(); else hwnd = hMain; GetWindowRect(hwnd, &rcParent); // Determine the top-left point for the dialog to be centered GetWindowRect(hDlg, &rcDlg); iWidth = rcDlg.right - rcDlg.left; iHeight = rcDlg.bottom - rcDlg.top; iLeft = rcParent.left + (((rcParent.right - rcParent.left) - iWidth ) / 2); iTop = rcParent.top + (((rcParent.bottom - rcParent.top ) - iHeight) / 2); if (iLeft < 0) iLeft = 0; if (iTop < 0) iTop = 0; // Place the dialog MoveWindow(hDlg, iLeft, iTop, iWidth, iHeight, TRUE); } //Error messagebox // static void DispError(char *psError) { MessageBox(NULL,psError, "Dialog Unit Error",MB_OK|MB_SYSTEMMODAL|MB_ICONERROR); } static BOOL ListViewSetHeaderColumn(HWND hWndList, int iIndex, int iSize, char *psHeader) { BOOL fRes = TRUE; LV_COLUMN lvC; lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvC.fmt = LVCFMT_LEFT; //LVCFMT_CENTER; lvC.cx = ListViewCalcColumnSize(hWndList,iIndex,iSize); lvC.pszText = psHeader; lvC.iSubItem = iIndex; if (ListView_InsertColumn (hWndList, iIndex, &lvC) == -1) fRes = FALSE; return(fRes); } static int ListViewCalcColumnSize(HWND hWndList, int iIndex, int iSizePercent) { RECT rcRec; int iListSize; int iUsedSize=0; int iRes; int iI; double dPercUnit; GetClientRect(hWndList, &rcRec); iListSize = rcRec.right; for(iI=0; iI < iIndex;++iI) iUsedSize+=ListView_GetColumnWidth(hWndList,iI); if (iIndex < 4) { dPercUnit = (double)iListSize/(double)100; iRes = (int)((double)iSizePercent*dPercUnit); } else iRes = iListSize-iUsedSize; return(iRes); } static BOOL ListViewInserRow(HWND hWndList, int iIndex, char *psVal1, char *psVal2, char *psVal3, char *psVal4, char *psVal5) { BOOL fRes = TRUE; LV_ITEM lvI; lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE; lvI.state = 0; lvI.stateMask = 0; lvI.iItem = iIndex; lvI.iSubItem = 0; lvI.pszText = ""; lvI.cchTextMax = 200; if (ListView_InsertItem (hWndList, &lvI) == -1) fRes = FALSE; ListView_SetItemText (hWndList, iIndex, 0, psVal1); ListView_SetItemText (hWndList, iIndex, 1, psVal2); ListView_SetItemText (hWndList, iIndex, 2, psVal3); ListView_SetItemText (hWndList, iIndex, 3, psVal4); ListView_SetItemText (hWndList, iIndex, 4, psVal5); return(fRes); } static void ToolTipInitiate(HWND hWndDlg) { if (hToolTipWnd == NULL) { hToolTipWnd = ToolTipCreate(hWndDlg); SendMessage(hToolTipWnd,TTM_SETMAXTIPWIDTH,0,300); } } static HWND ToolTipCreate (HWND hParent) { HWND hWnd = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hParent, NULL, NULL, //oPrm.hAppInstance, NULL ); SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); SendMessage(hWnd,TTM_SETMAXTIPWIDTH,0,300); return(hWnd); } static void ToolTipForItem (HWND hwnd, char *psText, HWND hTip) { HWND hWnd = hTip; // struct specifying info about tool in ToolTip control TOOLINFO ti; unsigned int uid = 0; // for ti initialization LPTSTR lptstr = (LPTSTR)psText; RECT rect; // for client area coordinates /* GET COORDINATES OF THE MAIN CLIENT AREA */ GetClientRect (hwnd, &rect); /* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */ ti.cbSize = sizeof(TOOLINFO); ti.uFlags = TTF_SUBCLASS; //ti.uFlags = 0; ti.hwnd = hwnd; ti.hinst = NULL; //oPrm.hAppInstance; ti.uId = uid; ti.lpszText = lptstr; // ToolTip control will cover the whole window ti.rect.left = rect.left; ti.rect.top = rect.top; ti.rect.right = rect.right; ti.rect.bottom = rect.bottom; if (hWnd == NULL) hWnd = hToolTipWnd; /* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */ SendMessage(hWnd, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti); } EXP_OPTION int RunDialogTestLow(void) { int iRes = 0; /* int iI; int iT = 0; char *psTemp; char sTemp[5000]; char sVal[128]; */ char sTest[] = {'\x8E','\x9e','\x8A','\x9A','\x00'}; char *aCertList[] = { NULL, "11111111111111111111111111111111111111111\t222\t333\t4444\t5555", "11111111111111111111111111111111111111111\t222\t333\t4444\t5555", "11111111111111111111111111111111111111111\t222\t333\t4444\t5555", NULL}; aCertList[0]=sTest; iRes = RunDialogUnit(aCertList, 500, 300); return(iRes); } libdigidoc-3.10.5/libdigidoc/DigiDocHTTP.c0000664000372000037200000000234213560273131017534 0ustar travistravis#include #include #include #include #include //-------------------------------------------------- // Returns HTTP return code // pBuf- buffer with HTTP response // returns error code or HTTP response code //-------------------------------------------------- int ddocGetHttpResponseCode(DigiDocMemBuf* pBuf) { int rc = ERR_OK; char *p = (char*)pBuf->pMem; RETURN_IF_NULL_PARAM(pBuf); if(p && !strncmp(p, "HTTP", 4)) { while(*p && *p != ' ') p++; while(*p && !isdigit(*p)) p++; rc = atoi(p); } else return ERR_HTTP_ERR; return rc; } //-------------------------------------------------- // Returns HTTP response body // pInBuf- buffer with HTTP response // pOutBuf - buffer for response body // returns error code or ERR_OK //-------------------------------------------------- int ddocGetHttpPayload(DigiDocMemBuf* pInBuf, DigiDocMemBuf* pOutBuf) { int err = ERR_OK; char *p; RETURN_IF_NULL_PARAM(pInBuf); RETURN_IF_NULL_PARAM(pOutBuf); if((p = strstr((char*)pInBuf->pMem, "\r\n\r\n")) != NULL) { p += 4; err = ddocMemAssignData(pOutBuf, p, pInBuf->nLen - (int)(p - (char*)pInBuf->pMem)); } else return ERR_HTTP_ERR; return err; } libdigidoc-3.10.5/libdigidoc/cdigidoc.rc0000664000372000037200000000163613560273131017466 0ustar travistravis#ifndef Q_CC_BOR # if defined(UNDER_CE) && UNDER_CE >= 400 # include # else # include # endif #endif #include VS_VERSION_INFO VERSIONINFO FILEVERSION VERSION_COMMA PRODUCTVERSION VERSION_COMMA FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0x0L #endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "RIA" VALUE "FileDescription", "cdigidoc" VALUE "FileVersion", VERSION VALUE "InternalName", "cdigidoc" VALUE "LegalCopyright", "Copyright (C) 2009-2018 Estonian Information System Authority" VALUE "OriginalFilename", "cdigidoc.exe" VALUE "ProductName", "cdigidoc" VALUE "ProductVersion", VERSION END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x425, 1200 END END /* End of Version info */ libdigidoc-3.10.5/libdigidoc/DigiDocMem.c0000664000372000037200000002236513560273131017502 0ustar travistravis//================================================== // FILE: DigiDocMem.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for memory buffer management // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 09.09.2004 Veiko Sinivee // Creation //================================================== #include #include #include #include #include //-------------------------------------------------- // Helper function to append data to a memory buffer // and grow it as required. // pBuf - address of memory buffer pointer // data - new data to be appended // len - length of data or -1 for zero terminated strings //-------------------------------------------------- EXP_OPTION int ddocMemAppendData(DigiDocMemBuf* pBuf, const char* data, long len) { long addLen = len; RETURN_IF_NULL_PARAM(pBuf); RETURN_IF_NULL_PARAM(data); if(addLen == -1) addLen = strlen(data); // ddocDebug(7, "ddocAppendData", "Len: %ld data: \'%s\'", addLen, data); pBuf->pMem = realloc(pBuf->pMem, pBuf->nLen + addLen + 1); if(!pBuf->pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC); memset((char*)pBuf->pMem + pBuf->nLen, 0, addLen+1); memcpy((char*)pBuf->pMem + pBuf->nLen, data, addLen); pBuf->nLen += addLen; // ddocDebug(8, "ddocAppendData", "BUFFER Len: %ld data:\'%s\'", pBuf->nLen, pBuf->pMem); return ERR_OK; } //-------------------------------------------------- // Helper function to set buffer length as required // It will fill acquired mem with zeros. // pBuf - address of memory buffer pointer // len - new length of buffer //-------------------------------------------------- EXP_OPTION int ddocMemSetLength(DigiDocMemBuf* pBuf, long len) { long addLen = len; RETURN_IF_NULL_PARAM(pBuf); addLen = len - pBuf->nLen; // ddocDebug(7, "ddocMemSetLength", "Len: %ld", addLen); pBuf->pMem = realloc(pBuf->pMem, pBuf->nLen + addLen + 1); if(!pBuf->pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC); memset((char*)pBuf->pMem + pBuf->nLen, 0, addLen+1); pBuf->nLen += addLen; // ddocDebug(8, "ddocMemSetLength", "BUFFER Len: %ld data:\'%s\'", pBuf->nLen, pBuf->pMem); return ERR_OK; } //-------------------------------------------------- // Helper function to assign data to a memory buffer // and release old content if necessary // pBuf - address of memory buffer pointer // data - new data to be appended // len - length of data or -1 for zero terminated strings //-------------------------------------------------- EXP_OPTION int ddocMemAssignData(DigiDocMemBuf* pBuf, const char* data, long len) { RETURN_IF_NULL_PARAM(pBuf); RETURN_IF_NULL_PARAM(data); // ddocDebug(7, "ddocAssignData", "Len: %d data: \'%s\'", len, data); if(pBuf->pMem) free(pBuf->pMem); pBuf->pMem = 0; pBuf->nLen = 0; return ddocMemAppendData(pBuf, data, len); } EXP_OPTION int ddocMemAssignData2(DigiDocMemBuf* pBuf, const char* data, long len) { RETURN_IF_NULL_PARAM(pBuf); RETURN_IF_NULL_PARAM(data); // ddocDebug(7, "ddocAssignData", "Len: %d data: \'%s\'", len, data); pBuf->pMem = 0; pBuf->nLen = 0; return ddocMemAppendData(pBuf, data, len); } //-------------------------------------------------- // Helper function to free/cleanup memory buffer // This does not attempt to release the buffer object // itself but only it's contents. // pBuf - memory buffer pointer //-------------------------------------------------- EXP_OPTION int ddocMemBuf_free(DigiDocMemBuf* pBuf) { RETURN_IF_NULL_PARAM(pBuf); if(pBuf->pMem) free(pBuf->pMem); pBuf->pMem = 0; pBuf->nLen = 0; return ERR_OK; } //-------------------------------------------------- // Helper function to assign zero terminated strings // and release old content if necessary // dest - destination address // src - new data to be assigned //-------------------------------------------------- EXP_OPTION int ddocMemAssignString(char** dest, const char* src) { int i; RETURN_IF_NULL_PARAM(dest); RETURN_IF_NULL_PARAM(src); if(*dest) free(*dest); i = strlen(src) + 10; *dest = malloc(i); if(*dest) { memset(*dest, 0, i); strncpy(*dest, src, strlen(src)); } //*dest = (char*)strdup(src); if(!dest) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) else return ERR_OK; } //-------------------------------------------------- // Replaces a substring with another substring // pBuf1 - memory buffer to search in // pBuf2 - memory buffer to write converted value to // search - search value // replacement - replacement value //-------------------------------------------------- EXP_OPTION int ddocMemReplaceSubstr(DigiDocMemBuf* pBuf1, DigiDocMemBuf* pBuf2, const char* search, const char* replacement) { int err = ERR_OK, i, n; RETURN_IF_NULL_PARAM(pBuf1); RETURN_IF_NULL_PARAM(pBuf1->pMem); RETURN_IF_NULL_PARAM(pBuf2); RETURN_IF_NULL_PARAM(search); RETURN_IF_NULL_PARAM(replacement); //ddocDebug(7, "ddocMemReplaceSubstr", "Replace: \'%s\' with: \'%s\' in: \'%s\'", // search, replacement, (const char*)pBuf1->pMem); ddocMemBuf_free(pBuf2); n = strlen(search); for(i = 0; !err && (i < pBuf1->nLen); i++) { if(!strncmp((char*)pBuf1->pMem + i, search, n)) { // match err = ddocMemAppendData(pBuf2, replacement, -1); i += strlen(search) - 1; } else { // no match err = ddocMemAppendData(pBuf2, (char*)pBuf1->pMem + i, 1); } } return err; } //AM SMARTLINK EXP_OPTION int ddocMemGetSubstr(DigiDocMemBuf* pBuf1, DigiDocMemBuf* pBuf2, const char* search, const char* replacement) { int err = ERR_OK, i, n,found=0; RETURN_IF_NULL_PARAM(pBuf1); RETURN_IF_NULL_PARAM(pBuf1->pMem); RETURN_IF_NULL_PARAM(pBuf2); RETURN_IF_NULL_PARAM(search); RETURN_IF_NULL_PARAM(replacement); //ddocDebug(7, "ddocMemReplaceSubstr", "Replace: \'%s\' with: \'%s\' in: \'%s\'", // search, replacement, (const char*)pBuf1->pMem); ddocMemBuf_free(pBuf2); n = strlen(search); for(i = 0; !err && (i < pBuf1->nLen); i++) { if(!strncmp((char*)pBuf1->pMem + i, search, n) && !found) { // match err = ddocMemAppendData(pBuf2, search, -1); i += strlen(search) - 1; found = 1; } else if (found){ if(!strncmp((char*)pBuf1->pMem + i, replacement, n) && found) { // match err = ddocMemAppendData(pBuf2, replacement, -1); i += strlen(replacement) - 1; break; } err = ddocMemAppendData(pBuf2, (char*)pBuf1->pMem + i, 1); } } return err; } //-------------------------------------------------- // Replaces a substring with another substring // pBuf1 - memory buffer to search in // pBuf2 - memory buffer to write converted value to // search - search value // replacement - replacement value //-------------------------------------------------- EXP_OPTION char *replaceStr(char *str, char *orig, char *rep) { static char buffer[4096]; char *p; if(!(p = strstr(str, orig))) return str; strncpy(buffer, str, p-str); buffer[p-str] = '\0'; sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig)); return buffer; } //-------------------------------------------------- // Compares memory buffers // pBuf1 - memory buffer to value 1 // pBuf2 - memory buffer to value 2 // return 0 if both buffers are equal, 1 if not equal //-------------------------------------------------- EXP_OPTION int ddocMemCompareMemBufs(DigiDocMemBuf* pBuf1, DigiDocMemBuf* pBuf2) { int i; RETURN_IF_NULL_PARAM(pBuf1); RETURN_IF_NULL_PARAM(pBuf1->pMem); RETURN_IF_NULL_PARAM(pBuf2); RETURN_IF_NULL_PARAM(pBuf2->pMem); if(pBuf1->nLen != pBuf2->nLen) return 1; for(i = 0; (i < pBuf1->nLen); i++) { if(((char*)pBuf1->pMem)[i] != ((char*)pBuf2->pMem)[i]) return 1; } return 0; } int ddocMemPush(DigiDocMemBuf* pBuf, const char* tag) { RETURN_IF_NULL_PARAM(pBuf); RETURN_IF_NULL_PARAM(tag); //ddocDebug(3, "ddocMemPush", "Len: %ld data: \'%s\'", strlen(tag), tag); ddocMemAppendData(pBuf, "/", -1); ddocMemAppendData(pBuf, tag, -1); //ddocDebug(3, "ddocMemPush", "BUFFER Len: %ld data:\'%s\'", pBuf->nLen, pBuf->pMem); return ERR_OK; } const char* ddocMemPop(DigiDocMemBuf* pBuf) { char* p = 0; int n = 0; // set prt to end if(pBuf && pBuf->nLen > 0) { n = pBuf->nLen - 1; p = &((char*)pBuf->pMem)[pBuf->nLen-1]; while(n > 0 && ((char*)pBuf->pMem)[n] != '/') { p--; n--; } if(n >= 0 && *p == '/') { *p = 0; pBuf->nLen = n; p++; // return popped value } } return p; } libdigidoc-3.10.5/libdigidoc/DigiDocParser.c0000664000372000037200000013375613560273131020227 0ustar travistravis//================================================== // FILE: DigiDocParser.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for xml parsing // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 10.07.2004 Veiko Sinivee // Creation //================================================== // config data comes from there #ifndef WIN32 #if HAVE_CONFIG_H #include #endif #endif // no win32 #include #include #include #include #include #include #include #include #include #include #include #define MAX_FILENAME 255 //=====================< DataFile extraction function >============================= #define EXTRACT_OP_WITH_TAGS 1 // copy with enclosing XML tags #define EXTRACT_OP_NO_TAGS 2 // copy content, no changes, no decoding but no tags #define EXTRACT_OP_BODY_ONLY 3 // copy only the content and base64 decode if necessary #define EXTRACT_OP_BODY_MEM 4 // return the content in memory and base64 decode if necessary #define MAX_CONTENT_TYPE 50 // maximum length for ContentType atribute extern char* canonicalizeXML(char* source, int len); //-------------------------------------------------- // Processes node contents. This function is used // internally and not meant to be called directly // by the users of this library! // reader - XML reader cursor to current node // phFile - address of FILE pointer. Used also as flag: searching/storing // szDocId - Id atribute value of to extract // szDataFile - name of file to stor it in // operation - operation code: // EXTRACT_OP_WITH_TAGS = copy with enclosing XML tags // EXTRACT_OP_BODY_ONLY = copy only the content and base64 decode if necessary // pszContentType - address of DataFile content type atribute value // pBuf - address of memory buffer for EXTRACT_OP_BODY_MEM //-------------------------------------------------- int ddocExtractProcessNode(xmlTextReaderPtr reader, FILE** phFile, const char* szDocId, const char* szDataFile, int operation, char* pszContentType, DigiDocMemBuf* pBuf) { int err = ERR_OK, n; xmlChar *name = 0, *value = 0, *an, *av, *p; RETURN_IF_NULL_PARAM(reader); RETURN_IF_NULL_PARAM(phFile); RETURN_IF_NULL_PARAM(szDocId); RETURN_IF_NULL_PARAM(pszContentType); name = xmlTextReaderName(reader); ddocDebug(4, "ddocExtractProcessNode", "Node %d, name: %s depth: %d", xmlTextReaderNodeType(reader), (name ? (char*)name : "-"), xmlTextReaderDepth(reader)); if(name) { xmlFree(name); name = 0; } switch(xmlTextReaderNodeType(reader)) { case XML_READER_TYPE_ELEMENT: name = xmlTextReaderName(reader); if(name) { if(!xmlStrcmp(name, (xmlChar*)"DataFile") && !*phFile) { // possible start value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"Id"); if(value) { ddocDebug(4, "ddocExtractProcessNode", "DataFile Id=%s, search: %s", (const char*)value, szDocId); if(!xmlStrcmp(value, (xmlChar*)szDocId)) { // found it ddocDebug(4, "ddocExtractProcessNode", "open file: %s", szDataFile); if(operation == EXTRACT_OP_BODY_MEM) { *phFile = (FILE*)1; // we return in memory. Set this dummy value to indicate start of searched data } else { RETURN_IF_NULL_PARAM(szDataFile); *phFile = fopen(szDataFile, "wb"); // open file for it } if(!*phFile) { ddocDebug(1, "ddocExtractProcessNode", "Failed to open file: %s", szDataFile); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); } else if(operation != EXTRACT_OP_BODY_MEM) ddocDebug(4, "ddocExtractProcessNode", "Successfully opened file: %s", szDataFile); } xmlFree(value); value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"ContentType"); if(value) { ddocDebug(4, "ddocExtractProcessNode", "ContentType=%s", (const char*)value); strncpy(pszContentType, (const char*)value, MAX_CONTENT_TYPE-1); pszContentType[MAX_CONTENT_TYPE-1] = 0; xmlFree(value); } } if(*phFile && ((operation == EXTRACT_OP_WITH_TAGS && !xmlStrcmp(name, (xmlChar*)"DataFile")) || xmlStrcmp(name, (xmlChar*)"DataFile"))) { if(operation == EXTRACT_OP_BODY_MEM) { RETURN_IF_NULL_PARAM(pBuf); err = ddocMemAppendData(pBuf, "<", -1); err = ddocMemAppendData(pBuf, (const char*)name, -1); } else { fprintf(*phFile, "<%s", name); } while(xmlTextReaderMoveToNextAttribute(reader)) { an = av = 0; an = xmlTextReaderName(reader); av = xmlTextReaderValue(reader); if(operation == EXTRACT_OP_BODY_MEM) { RETURN_IF_NULL_PARAM(pBuf); err = ddocMemAppendData(pBuf, " ", -1); err = ddocMemAppendData(pBuf, (const char*)an, -1); err = ddocMemAppendData(pBuf, "=\"", -1); err = ddocMemAppendData(pBuf, (const char*)av, -1); err = ddocMemAppendData(pBuf, "\"", -1); } else fprintf(*phFile, " %s=\"%s\"", (const char*)an, (const char*)av); if(an) xmlFree(an); if(av) xmlFree(av); } if(operation == EXTRACT_OP_BODY_MEM) { RETURN_IF_NULL_PARAM(pBuf); err = ddocMemAppendData(pBuf, ">", -1); } else { fputs(">", *phFile); } } } if(name) xmlFree(name); } break; case XML_READER_TYPE_END_ELEMENT: name = xmlTextReaderName(reader); // handle end element if(*phFile && ((operation == EXTRACT_OP_WITH_TAGS && !xmlStrcmp(name, (xmlChar*)"DataFile")) || xmlStrcmp(name, (xmlChar*)"DataFile"))) { if(operation == EXTRACT_OP_BODY_MEM) { RETURN_IF_NULL_PARAM(pBuf); err = ddocMemAppendData(pBuf, "", -1); } else { fprintf(*phFile, "", name); } } // check if it's the correct end element if(!xmlStrcmp(name, (xmlChar*)"DataFile")) { // possible end if(*phFile && *phFile != (FILE*)1) { // file opened then it's the correct end element err = -1; ddocDebug(4, "ddocExtractProcessNode", "close file: %s", szDataFile); fclose(*phFile); } if(*phFile) *phFile = 0; } // PR. fix mem leak if(name) xmlFree(name); break; case XML_READER_TYPE_ATTRIBUTE: break; case XML_READER_TYPE_TEXT: // handle text node if(*phFile) { value = xmlTextReaderValue(reader); if(value) { ddocDebug(4, "ddocExtractProcessNode", "TEXT: \'%s\'", (const char*)value); if(operation != EXTRACT_OP_WITH_TAGS && operation != EXTRACT_OP_NO_TAGS && !strcmp(pszContentType, CONTENT_EMBEDDED_BASE64)) { n = strlen((const char*)value)+1; // decoding will make it 25% smaller, so this must be enough p = (xmlChar*)malloc(n); if(p) { decode((const byte*)value, strlen((const char*)value), p, &n); ddocDebug(4, "ddocExtractProcessNode", "Decoded: %d bytes", n); if(operation == EXTRACT_OP_BODY_MEM) { RETURN_IF_NULL_PARAM(pBuf); err = ddocMemAppendData(pBuf, (const char*)p, n); } else { n = fwrite(p, 1, n, *phFile); ddocDebug(4, "ddocExtractProcessNode", "Wrote: %d bytes", n); } free(p); } } else { // in memory we don't really want the escapes or do we ? if(operation == EXTRACT_OP_BODY_MEM) { RETURN_IF_NULL_PARAM(pBuf); err = ddocMemAppendData(pBuf, (const char*)value, -1); } else { // convert xml special symbols to escapes on output for(n = 0; value[n]; n++) { switch(value[n]) { case '<': fputs("<", *phFile); break; case '>': fputs(">", *phFile); break; case '&': fputs("&", *phFile); break; case '\'': fputs("'", *phFile); break; case '\"': fputs(""", *phFile); break; default: fputc(value[n], *phFile); break; } } } } xmlFree(value); } } break; case XML_READER_TYPE_CDATA: case XML_READER_TYPE_ENTITY_REFERENCE: case XML_READER_TYPE_ENTITY: case XML_READER_TYPE_PROCESSING_INSTRUCTION: case XML_READER_TYPE_COMMENT: case XML_READER_TYPE_DOCUMENT: case XML_READER_TYPE_DOCUMENT_TYPE: case XML_READER_TYPE_DOCUMENT_FRAGMENT: case XML_READER_TYPE_NOTATION: break; } ddocDebug(4, "ddocExtractProcessNode", "Err %d", err); return err; } //-------------------------------------------------- // Reads in signed XML document and extracts the desired data file // pSigDoc - signed document object if cached // szFileName - name of digidoc file // szDataFileName - name of new data file // szDocId - id if DataFile // szCharset - output charset //-------------------------------------------------- EXP_OPTION int ddocXRdrExtractDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDataFileName, const char* szDocId, const char* szCharset) { char szConvDigiDocName[MAX_FILENAME+1]; char szConvDataFileName[MAX_FILENAME+1]; char szContentType[MAX_CONTENT_TYPE+1]; xmlTextReaderPtr reader; FILE* hFile = 0; int ret; long len; void* pBuf; // check input params ddocDebug(3, "ddocXRdrExtractDataFile", "SigDoc: %s, digidoc: %s, datafile: %s, output file: %s, charset: %s", (pSigDoc ? "OK" : "NULL"), szFileName, szDocId, szDataFileName, szCharset); RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(szDataFileName); RETURN_IF_NULL_PARAM(szDocId); RETURN_IF_NULL_PARAM(szCharset); szContentType[0] = 0; clearErrors(); // converts file names if necessary ddocConvertFileName(szConvDataFileName, sizeof(szConvDataFileName), szDataFileName); ddocConvertFileName(szConvDigiDocName, sizeof(szConvDigiDocName), szFileName); // try reading from memory if already cached? ret = ddocGetDataFileCachedData(pSigDoc, szDocId, &pBuf, &len); if(pBuf) { // gotcha ddocDebug(4, "ddocXRdrExtractDataFile", "Using cached data: %d bytes", len); if((hFile = fopen(szConvDataFileName, "wb")) != NULL) { fwrite(pBuf, 1, len, hFile); fclose(hFile); } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); free(pBuf); return ERR_OK; } // read digidoc reader = xmlNewTextReaderFilename(szConvDigiDocName); if(reader != NULL) { ret = xmlTextReaderRead(reader); // loop over all nodes... while(ret == 1) { ret = ddocExtractProcessNode(reader, &hFile, szDocId, szConvDataFileName, EXTRACT_OP_BODY_ONLY, szContentType, 0); if(ret == -1) { // found all what I need but no errs. Stop parsing ret = 0; break; } ret = xmlTextReaderRead(reader); } // cleanup xmlFreeTextReader(reader); if (ret != 0) ddocDebug(1, "ddocXRdrExtractDataFile", "Error parsing file: %s parsing err: %d", szConvDigiDocName, ret); return ret; } else { SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); ddocDebug(1, "ddocXRdrExtractDataFile", "Error reading file: %s", szConvDigiDocName); } return ERR_OK; } //-------------------------------------------------- // Reads in signed XML document and returns the // desired DataFile-s content in a memory buffer. // caller is responsible for freeing the memory. // pSigDoc - digidoc object in case already read in // szFileName - name of digidoc file // szDocId - id if DataFile // pBuf - address of buffer pointer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocXRdrGetDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDocId, DigiDocMemBuf* pBuf) { char szConvDigiDocName[MAX_FILENAME+1]; char szContentType[MAX_CONTENT_TYPE+1]; xmlTextReaderPtr reader; FILE* hFile = 0; int ret; // check input params ddocDebug(3, "ddocXRdrGetDataFile", "SigDoc: %s, digidoc: %s, docid: %s", (pSigDoc ? "OK" : "NULL"), szFileName, szDocId); RETURN_IF_NULL_PARAM(pBuf); RETURN_IF_NULL_PARAM(szDocId); memset(pBuf, 0, sizeof(DigiDocMemBuf)); clearErrors(); ret = ddocGetDataFileCachedData(pSigDoc, szDocId, &(pBuf->pMem), &pBuf->nLen); if(pBuf->pMem){ // gotcha ddocDebug(4, "ddocXRdrGetDataFile", "Using cached data: %d bytes", pBuf->nLen); return ERR_OK; } RETURN_IF_NULL_PARAM(szFileName); szContentType[0] = 0; // converts file names if necessary ddocConvertFileName(szConvDigiDocName, sizeof(szConvDigiDocName), szFileName); // read digidoc reader = xmlNewTextReaderFilename(szConvDigiDocName); if(reader != NULL) { ret = xmlTextReaderRead(reader); // loop over all nodes... while(ret == 1) { ret = ddocExtractProcessNode(reader, &hFile, szDocId, 0, EXTRACT_OP_BODY_MEM, szContentType, pBuf); if(ret == -1) { // found all what I need but no errs. Stop parsing ret = 0; break; } ret = xmlTextReaderRead(reader); } // cleanup xmlFreeTextReader(reader); if (ret != 0) ddocDebug(1, "ddocXRdrGetDataFile", "%s : failed to parse, err: %d", szConvDigiDocName, ret); return ret; } else { SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); ddocDebug(1, "ddocXRdrGetDataFile", "Error reading file: %s", szConvDigiDocName); } return ERR_OK; } //-------------------------------------------------- // Reads in signed XML document and extracts the desired data file // This function removes xml tags but doesn't // otherwise change or decode the data. It is used // internally to copy data content from an old digidoc file // to a temp file while saving a the file // szFileName - name of digidoc file // szDataFileName - name of new data file // szDocId - id if DataFile // szCharset - output charset //-------------------------------------------------- int ddocXRdrCopyDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDataFileName, const char* szDocId, const char* szCharset) { char szConvDigiDocName[MAX_FILENAME+1]; char szConvDataFileName[MAX_FILENAME+1]; char szContentType[MAX_CONTENT_TYPE+1]; xmlTextReaderPtr reader; FILE* hFile = 0; int ret; long len; void* pBuf = 0; // check input params ddocDebug(3, "ddocXRdrCopyDataFile", "SigDoc: %s, digidoc: %s, datafile: %s, output file: %s, charset: %s", (pSigDoc ? "OK" : "NULL"), szFileName, szDocId, szDataFileName, szCharset); RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(szDataFileName); RETURN_IF_NULL_PARAM(szDocId); RETURN_IF_NULL_PARAM(szCharset); szContentType[0] = 0; clearErrors(); // converts file names if necessary ddocConvertFileName(szConvDataFileName, sizeof(szConvDataFileName), szDataFileName); ddocConvertFileName(szConvDigiDocName, sizeof(szConvDigiDocName), szFileName); // try reading from memory if already cached? ret = ddocGetDataFileCachedData(pSigDoc, szDocId, &pBuf, &len); if(pBuf) { // gotcha ddocDebug(4, "ddocXRdrCopyDataFile", "Using cached data: %d bytes", len); if((hFile = fopen(szConvDataFileName, "wb")) != NULL) { fwrite(pBuf, 1, len, hFile); fclose(hFile); } else SET_LAST_ERROR(ERR_FILE_WRITE); free(pBuf); return ERR_OK; } // read digidoc reader = xmlNewTextReaderFilename(szConvDigiDocName); if(reader != NULL) { ret = xmlTextReaderRead(reader); // loop over all nodes... while(ret == 1) { ret = ddocExtractProcessNode(reader, &hFile, szDocId, szConvDataFileName, EXTRACT_OP_NO_TAGS, szContentType, 0); if(ret == -1) { // found all what I need but no errs. Stop parsing ret = 0; break; } ret = xmlTextReaderRead(reader); } // cleanup xmlFreeTextReader(reader); if (ret != 0) ddocDebug(1, "ddocXRdrCopyDataFile", "Error parsing file: %s, err: %d", szConvDigiDocName, ret); return ret; } else { SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); ddocDebug(1, "ddocXRdrCopyDataFile", "Error reading file: %s", szConvDigiDocName); } return ERR_OK; } //=====================< digidoc parsing function >============================= //-------------------------------------------------- // Records elements start tag to given buffer // Used internally and not meant to be called directly // by the users of this library! // reader - XML reader cursor to current node // pCurrElem - current element stack entry // pBuf - address of buffer for collection certain portions of digidoc //-------------------------------------------------- void ddocXRdrRecordElementStart(xmlTextReaderPtr reader, ElementEntry* pCurrElem, DigiDocMemBuf* pBuf) { int n; xmlChar *an, *av; // if we are collecting some xml content if(pBuf->pMem || pBuf->nLen) { ddocMemAppendData(pBuf, "<", -1); ddocMemAppendData(pBuf, (const char*)pCurrElem->tag, -1); for(n = 0; xmlTextReaderMoveToAttributeNo(reader, n); n++) { an = xmlTextReaderLocalName(reader); av = xmlTextReaderValue(reader); ddocMemAppendData(pBuf, " ", -1); ddocMemAppendData(pBuf, (const char*)an, -1); ddocMemAppendData(pBuf, "=\"", -1); ddocMemAppendData(pBuf, (const char*)av, -1); ddocMemAppendData(pBuf, "\"", -1); xmlFree(an); xmlFree(av); } xmlTextReaderMoveToElement(reader); ddocMemAppendData(pBuf, ">", -1); } } //-------------------------------------------------- // Records elements end tag to given buffer // Used internally and not meant to be called directly // by the users of this library! // pCurrElem - current element stack entry // pBuf - address of buffer for collection certain portions of digidoc //-------------------------------------------------- void ddocXRdrRecordElementEnd(ElementEntry* pCurrElem, DigiDocMemBuf* pBuf) { // if we are collecting some xml content if(pBuf->pMem || pBuf->nLen) { ddocMemAppendData(pBuf, "tag, -1); ddocMemAppendData(pBuf, ">", -1); } } //-------------------------------------------------- // Records elements content to given buffer // Used internally and not meant to be called directly // by the users of this library! // value - element content // pBuf - address of buffer for collection certain portions of digidoc //-------------------------------------------------- void ddocXRdrRecordElementContent(xmlChar* value, DigiDocMemBuf* pBuf) { // if we are collecting some xml content if(pBuf->pMem || pBuf->nLen) ddocMemAppendData(pBuf, (const char*)value, -1); } //-------------------------------------------------- // Starts recording xml content // Used internally and not meant to be called directly // by the users of this library! // pBuf - address of buffer for collection certain portions of digidoc // szTag - name of new tag thatwe start collecting for //-------------------------------------------------- void ddocXRdrStartCollecting(DigiDocMemBuf* pBuf, const char* szTag) { if(pBuf->pMem) { ddocDebug(2, "ddocXRdrStartCollecting", "Warning: old buffer not released when starting collecting: %s", szTag); free(pBuf->pMem); } ddocDebug(4, "ddocXRdrStartCollecting", "Starting collecting: %s", szTag); pBuf->pMem = malloc(16); // dummy buf to start recording pBuf->nLen = 0; } //-------------------------------------------------- // Stops recording xml content, calculates digest and stores it // Used internally and not meant to be called directly // by the users of this library! // pBuf - address of buffer for collection certain portions of digidoc // szTag - name of new tag thatwe start collecting for // pDigestBuf - address of pointer receiving the digest value // pDigestLen - address of length variable for digest length //-------------------------------------------------- int ddocXRdrStopCollectingAndCalcDigest(DigiDocMemBuf* pBuf, const char* szTag, char** pDigestBuf, long* pDigestLen ) { char dig[DIGEST_LEN+2]; char *p; SHA_CTX sctx; ddocDebug(7, "ddocXRdrStopCollectingAndCalcDigest", "Tag: %s Canonicalise:---------\n%s\n---------", szTag, pBuf->pMem); p = canonicalizeXML((char*)pBuf->pMem, strlen((const char*)pBuf->pMem)); if(p) { SHA1_Init(&sctx); SHA1_Update(&sctx, p, strlen(p)); SHA1_Final((unsigned char*)dig, &sctx); setString(pDigestBuf, dig, DIGEST_LEN); (*pDigestLen) = DIGEST_LEN; free(p); p = 0; } // stop recording xml content ddocDebug(4, "ddocParseProcessNode", "End recording: %s", szTag); if(pBuf->pMem) free(pBuf->pMem); pBuf->pMem = 0; pBuf->nLen = 0; return ERR_OK; } //-------------------------------------------------- // Stops recording xml content, calculates digest and stores it // Used internally and not meant to be called directly // by the users of this library! // pBuf - address of buffer for collection certain portions of digidoc // szTag - name of new tag thatwe start collecting for // pDigestValue - address of DigestValue structure // pDigestBuf - address of pointer receiving the digest value // pDigestLen - address of length variable for digest length //-------------------------------------------------- int ddocXRdrStopCollectingAndAssignDigest(DigiDocMemBuf* pBuf, const char* szTag, DigiDocMemBuf* pDigestBuf) { int err = ERR_OK; char dig[DIGEST_LEN+2]; char *p; SHA_CTX sctx; ddocDebug(7, "ddocXRdrStopCollectingAndCalcDigest", "Tag: %s Canonicalise:---------\n%s\n---------", szTag, pBuf->pMem); p = canonicalizeXML((char*)pBuf->pMem, strlen((const char*)pBuf->pMem)); if(p) { SHA1_Init(&sctx); SHA1_Update(&sctx, p, strlen(p)); SHA1_Final((unsigned char*)dig, &sctx); err = ddocMemAssignData(pDigestBuf, dig, DIGEST_LEN); free(p); p = 0; } // stop recording xml content ddocDebug(4, "ddocParseProcessNode", "End recording: %s", szTag); if(pBuf->pMem) free(pBuf->pMem); pBuf->pMem = 0; pBuf->nLen = 0; return err; } //-------------------------------------------------- // Processes node contents. This function is used // internally and not meant to be called directly // by the users of this library! // reader - XML reader cursor to current node // pSigDoc - address of signed doc pointer // pStack - element stack pointer used to keep track of parsing position // pBuf1 - address of first buffer for collection certain portions of digidoc // pBuf2 - address of second buffer for collection certain portions of digidoc // lMaxDFLen - maximum size of a cached DataFile //-------------------------------------------------- int ddocParseProcessNode(xmlTextReaderPtr reader, SignedDoc **ppSigDoc, ElementEntry* pStack, DigiDocMemBuf* pBuf1, DigiDocMemBuf* pBuf2, long lMaxDFLen) { int err = ERR_OK, n, l; xmlChar *name = 0, *value = 0; char* p; ElementEntry* pCurrElem = 0; DataFile *pDF = 0; CertID* pCertID; X509* pCert; const DigiDocMemBuf *pMBuf; RETURN_IF_NULL_PARAM(reader); RETURN_IF_NULL_PARAM(ppSigDoc); RETURN_IF_NULL_PARAM(pStack); RETURN_IF_NULL_PARAM(pBuf1); name = xmlTextReaderName(reader); ddocDebug(7, "ddocParseProcessNode", "Node %d, name: %s depth: %d", xmlTextReaderNodeType(reader), (name ? (char*)name : "-"), xmlTextReaderDepth(reader)); if(name) { xmlFree(name); name = 0; } switch(xmlTextReaderNodeType(reader)) { case XML_READER_TYPE_ELEMENT: err = ddocStackPushElement(pStack, reader,&pCurrElem); if(pCurrElem) { // not in recording mode //if(!(*pBuf1)) { ddocDebug(5, "ddocParseProcessNode", "Start element: %s", (const char*)pCurrElem->tag); // start of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"SignedDoc")) { xmlChar* format = xmlTextReaderGetAttribute(reader, (const xmlChar*)"format"); xmlChar* version = xmlTextReaderGetAttribute(reader, (const xmlChar*)"version"); if(ddocCheckFormatAndVer((const char*)format, (const char*)version)) SET_LAST_ERROR_RETURN(ERR_UNSUPPORTED_FORMAT, ERR_UNSUPPORTED_FORMAT); err = SignedDoc_new(ppSigDoc, (const char*)format, (const char*)version); ddocDebug(4, "ddocParseProcessNode", "Create SignedDoc format: %s ver: %s", (const char*)format, (const char*)version); xmlFree(format); xmlFree(version); } // if not inside other if(!ddocStackHasParentWithName(pStack, (xmlChar*)"DataFile", pCurrElem)) { // start of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"DataFile")) { xmlChar *an, *av; DataFile *pDF = 0; err = DataFile_new(&pDF, *ppSigDoc, NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL); for(n = 0; xmlTextReaderMoveToAttributeNo(reader, n); n++) { an = xmlTextReaderLocalName(reader); av = xmlTextReaderValue(reader); ddocDebug(5, "ddocParseProcessNode", "DF attr: %s value: %s", (const char*)an, (const char*)av); if(!xmlStrcmp(an, (const xmlChar*)"Id")) setString(&(pDF->szId), (const char*)av, -1); else if(!xmlStrcmp(an, (const xmlChar*)"ContentType")) setString(&(pDF->szContentType), (const char*)av, -1); else if(!xmlStrcmp(an, (const xmlChar*)"MimeType")) setString(&(pDF->szMimeType), (const char*)av, -1); else if(!xmlStrcmp(an, (const xmlChar*)"Filename")) setString(&(pDF->szFileName), (const char*)av, -1); else if(!xmlStrcmp(an, (const xmlChar*)"DigestType")) setString(&(pDF->szDigestType), (const char*)av, -1); else if(!xmlStrcmp(an, (const xmlChar*)"DigestValue")) { l = xmlStrlen(av) + 1; p = (char*)malloc(l); RETURN_IF_BAD_ALLOC(p); decode((const byte*)av, strlen((const char*)av), (byte*)p, &l); ddocDataFile_SetDigestValue(pDF, p, l); //??? set binary or base64 ??? } else if(!xmlStrcmp(an, (const xmlChar*)"Size")) pDF->nSize = atol((const char*)av); else { // all other are optional atributes err = addDataFileAttribute(pDF, (const char*)an, (const char*)av); } xmlFree(an); xmlFree(av); } xmlTextReaderMoveToElement(reader); ddocXRdrStartCollecting(pBuf1, "DataFile"); } // start if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"Signature")) { SignatureInfo *pSig = 0; value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"Id"); ddocDebug(4, "ddocParseProcessNode", "SIG:%s", (const char*)value); err = SignatureInfo_new(&pSig, *ppSigDoc, (const char*)value); xmlFree(value); ddocXRdrStartCollecting(pBuf2, "Signature"); } // start if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"Reference")) { DocInfo *pDi = 0; xmlChar *uri, *type; SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); uri = xmlTextReaderGetAttribute(reader, (const xmlChar*)"URI"); type = xmlTextReaderGetAttribute(reader, (const xmlChar*)"Type"); ddocDebug(4, "ddocParseProcessNode", "Reference URI: %s Type: %s", (const char*)uri, (const char*)type); // DataFile digest if(uri[0] == '#' && uri[1] == 'D') err = addDocInfo(&pDi, pSig, (const char*)(uri+1), NULL, NULL, 0, NULL, 0); // TODO: ver 1.x mime digest handling xmlFree(uri); xmlFree(type); } // start if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"DigestMethod")) { ElementEntry* pParent = 0; value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"Algorithm"); // if inside if((pParent = ddocStackGetParentWithName(pStack, (xmlChar*)"Reference", pCurrElem)) != NULL) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); // DataFile reference if(pParent->uri && pParent->uri[1] == 'D') { DocInfo *pDi = ddocGetLastDocInfo(pSig); if(pDi && !xmlStrcmp(value, (xmlChar*)DIGEST_METHOD_SHA1)) setString((char**)&(pDi->szDigestType), DIGEST_SHA1_NAME, -1); // what if something else ? } // SignedProperties reference } // inside xmlFree(value); } // start of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"SignedInfo")) ddocXRdrStartCollecting(pBuf1, "SignedInfo"); // start of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"SignedProperties")) ddocXRdrStartCollecting(pBuf1, "SignedProperties"); // start of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"UnsignedProperties")) { NotaryInfo* pNot = 0; SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); ddocDebug(4, "ddocParseProcessNode", "Start of UnsignedProperties"); err = NotaryInfo_new(&pNot, *ppSigDoc, pSig); } } // if not inside other // if we are collecting some xml content (, , etc.) ddocXRdrRecordElementStart(reader, pCurrElem, pBuf1); // if we are collecting xml content ddocXRdrRecordElementStart(reader, pCurrElem, pBuf2); } break; case XML_READER_TYPE_END_ELEMENT: // get current element pCurrElem = ddocStackFindEnd(pStack); if(pCurrElem) { ddocDebug(5, "ddocParseProcessNode", "End element: %s", pCurrElem->tag); // if we are collecting some xml content (, , etc.) ddocXRdrRecordElementEnd(pCurrElem, pBuf1); // if we are collecting xml content ddocXRdrRecordElementEnd(pCurrElem, pBuf2); // if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"DataFile") && !ddocStackHasParentWithName(pStack, (xmlChar*)"DataFile", pCurrElem)) { ddocDebug(4, "ddocParseProcessNode", "End recording DataFile"); pDF = ddocGetLastDataFile(*ppSigDoc); if(pDF) { err = ddocXRdrStopCollectingAndAssignDigest(pBuf1, "DataFile", &(pDF->mbufDigest)); setString((char**)&(pDF->szDigestType), DIGEST_SHA1_NAME, -1); // TODO: Version 1.0 buggy digest calculation... } } // // if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"SignedInfo") && !ddocStackHasParentWithName(pStack, (xmlChar*)"DataFile", pCurrElem)) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); if(!pSig->pSigInfoRealDigest) ddocDigestValue_new(&(pSig->pSigInfoRealDigest), 0, 0, 0); err = ddocXRdrStopCollectingAndAssignDigest(pBuf1, "SignedInfo", &(pSig->pSigInfoRealDigest->mbufDigestValue)); } // // if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"SignedProperties") && !ddocStackHasParentWithName(pStack, (xmlChar*)"DataFile", pCurrElem)) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); if(!pSig->pSigPropRealDigest) ddocDigestValue_new(&(pSig->pSigPropRealDigest), 0, 0, 0); ddocXRdrStopCollectingAndAssignDigest(pBuf1, "SignedProperties", &(pSig->pSigPropRealDigest->mbufDigestValue)); } // // if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"Signature") && !ddocStackHasParentWithName(pStack, (xmlChar*)"DataFile", pCurrElem)) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); ddocDebug(4, "ddocParseProcessNode", "End recording Signature"); // DO NOT FREE THE MEM! Just take ownership ddocMemBuf_free(&(pSig->mbufOrigContent)); pSig->mbufOrigContent.pMem = (byte*)pBuf2->pMem; pSig->mbufOrigContent.nLen = pBuf2->nLen; pBuf2->pMem = 0; pBuf2->nLen = 0; } // } // if(pCurrElem) err = ddocStackPopElement(pStack, 0, NULL); break; case XML_READER_TYPE_ATTRIBUTE: break; case XML_READER_TYPE_TEXT: value = xmlTextReaderValue(reader); if(value) { ddocDebug(8, "ddocParseProcessNode", "TEXT:\'%s\'", (const char*)value, -1); // if we are collecting some xml content (, , etc.) ddocXRdrRecordElementContent(value, pBuf1); // if we are collecting xml content ddocXRdrRecordElementContent(value, pBuf2); // get current tag pCurrElem = ddocStackFindEnd(pStack); // content of if(pCurrElem && !xmlStrcmp(pCurrElem->tag, (xmlChar*)"DataFile") && !ddocStackHasParentWithName(pStack, (xmlChar*)"DataFile", pCurrElem)) { DataFile *pDF = ddocGetLastDataFile(*ppSigDoc); // collect contents ddocAppendDataFileData(pDF, lMaxDFLen, (void*)value, strlen((const char*)value), !strcmp(pDF->szContentType, CONTENT_EMBEDDED_BASE64)); } // content of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"DigestValue")) { ElementEntry* pParent = 0; ddocDebug(4, "ddocParseProcessNode", "DigestValue: %s", (const char*)value); l = strlen((const char*)value); p = (char*)malloc(l+1); RETURN_IF_BAD_ALLOC(p); memset(p, 0, l+1); decode((const byte*)value, l, (byte*)p, &l); // if inside if((pParent = ddocStackGetParentWithName(pStack, (xmlChar*)"Reference", pCurrElem)) != NULL) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); // DataFile digest value if(pParent->uri && pParent->uri[1] == 'D') { DocInfo *pDi = ddocGetLastDocInfo(pSig); if(pDi) { ddocDebug(4, "ddocParseProcessNode", "SIG: %s DocInfo: %s digest", pSig->szId, pDi->szDocId); setString((char**)&(pDi->szDigest), p, l); pDi->nDigestLen = l; } } // SignedProperties digest value if(pParent->uri && pParent->uri[1] == 'S') { ddocDebug(4, "ddocParseProcessNode", "SIG: %s SignedProperties digest", pSig->szId); ddocSigInfo_SetSigPropDigest(pSig, p, l); } } // inside // if inside if((pParent = ddocStackGetParentWithName(pStack, (xmlChar*)"SigningCertificate", pCurrElem)) != NULL) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSig, CERTID_TYPE_SIGNERS_CERTID); RETURN_IF_NULL(pCertID); // Certificate digest value ddocDebug(4, "ddocParseProcessNode", "SIG: %s signers certificate digest", pSig->szId); ddocCertID_SetDigestValue(pCertID, p, l); } // inside // if inside if((pParent = ddocStackGetParentWithName(pStack, (xmlChar*)"CompleteCertificateRefs", pCurrElem)) != NULL) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSig, CERTID_TYPE_RESPONDERS_CERTID); RETURN_IF_NULL(pCertID); // Certificate digest value ddocDebug(4, "ddocParseProcessNode", "Sig: %s responders certificate digest", pSig->szId); ddocCertID_SetDigestValue(pCertID, p, l); } // inside // if inside if((pParent = ddocStackGetParentWithName(pStack, (xmlChar*)"CompleteRevocationRefs", pCurrElem)) != NULL) { NotaryInfo* pNot = ddocGetLastNotaryInfo(*ppSigDoc); RETURN_IF_NULL(pNot); // Certificate digest value ddocDebug(4, "ddocParseProcessNode", "NOT: %s OCSP digest", pNot->szId); ddocNotInfo_SetOcspDigest(pNot, p, l); } // inside free(p); } // DigestVlue // content of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"SignatureValue")) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); ddocDebug(4, "ddocParseProcessNode", "SignatureValue: %s", (const char*)value); RETURN_IF_NULL(pSig); l = strlen((const char*)value); p = (char*)malloc(l+1); RETURN_IF_BAD_ALLOC(p); memset(p, 0, l+1); decode((const byte*)value, l, (byte*)p, &l); ddocSigInfo_SetSignatureValue(pSig, p, l); free(p); } // SignatureValue // content of or if((!xmlStrcmp(pCurrElem->tag, (xmlChar*)"IssuerSerial") && strcmp((*ppSigDoc)->szFormatVer, DIGIDOC_XML_1_3_VER)) || !xmlStrcmp(pCurrElem->tag, (xmlChar*)"X509SerialNumber")) { if(ddocStackHasParentWithName(pStack, (xmlChar*)"SigningCertificate", pCurrElem)) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); ddocDebug(4, "ddocParseProcessNode", "X509IssuerSerial: %s", (const char*)value); pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSig, CERTID_TYPE_SIGNERS_CERTID); RETURN_IF_NULL(pCertID); ddocCertID_SetIssuerSerial(pCertID, (const char*)value); } if(ddocStackHasParentWithName(pStack, (xmlChar*)"CompleteCertificateRefs", pCurrElem)) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); ddocDebug(4, "ddocParseProcessNode", "X509IssuerSerial: %s", (const char*)value); pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSig, CERTID_TYPE_RESPONDERS_CERTID); RETURN_IF_NULL(pCertID); ddocCertID_SetIssuerSerial(pCertID, (const char*)value); } } // IssuerSerial // content of if(!strcmp((*ppSigDoc)->szFormatVer, DIGIDOC_XML_1_3_VER) && !xmlStrcmp(pCurrElem->tag, (xmlChar*)"X509IssuerName")) { if(ddocStackHasParentWithName(pStack, (xmlChar*)"SigningCertificate", pCurrElem)) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); ddocDebug(4, "ddocParseProcessNode", "X509IssuerName: %s", (const char*)value); pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSig, CERTID_TYPE_SIGNERS_CERTID); RETURN_IF_NULL(pCertID); ddocCertID_SetIssuerName(pCertID, (const char*)value); } if(ddocStackHasParentWithName(pStack, (xmlChar*)"CompleteCertificateRefs", pCurrElem)) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); ddocDebug(4, "ddocParseProcessNode", "X509IssuerName: %s", (const char*)value); pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSig, CERTID_TYPE_RESPONDERS_CERTID); RETURN_IF_NULL(pCertID); ddocCertID_SetIssuerName(pCertID, (const char*)value); } } // IssuerSerial // content of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"X509Certificate")) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); l = strlen((const char*)value); ddocDebug(4, "ddocParseProcessNode", "X509Certificate: %s len: %d", (const char*)value, l); RETURN_IF_NULL(pSig); ddocDecodeX509PEMData((X509**)&pCert, (const char*)value, l); ddocSigInfo_SetSignersCert(pSig, pCert); } // X509Certificate // content of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"SigningTime")) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); ddocDebug(4, "ddocParseProcessNode", "SigningTime: %s", (const char*)value); RETURN_IF_NULL(pSig); setString((char**)&(pSig->szTimeStamp), (const char*)value, -1); } // SigningTime // content of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"ClaimedRole")) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); ddocDebug(4, "ddocParseProcessNode", "ClaimedRole: %s", (const char*)value); RETURN_IF_NULL(pSig); addSignerRole(pSig, 0, (const char*)value, strlen((const char*)value), 0); } // ClaimedRole // content of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"ResponderID")) { NotaryInfo* pNot = ddocGetLastNotaryInfo(*ppSigDoc); RETURN_IF_NULL(pNot); ddocDebug(4, "ddocParseProcessNode", "ResponderID: %s", (const char*)value); ddocNotInfo_SetResponderId(pNot, (const char*)value, -1); } // ResponderID // content of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"ProducedAt")) { NotaryInfo* pNot = ddocGetLastNotaryInfo(*ppSigDoc); RETURN_IF_NULL(pNot); ddocDebug(4, "ddocParseProcessNode", "ProducedAt: %s", (const char*)value); setString((char**)&(pNot->timeProduced), (const char*)value, -1); } // ProducedAt // content of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"EncapsulatedX509Certificate")) { SignatureInfo *pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); ddocDebug(4, "ddocParseProcessNode", "EncapsulatedX509Certificate: %s", (const char*)value); l = strlen((const char*)value); ddocDecodeX509PEMData((X509**)&pCert, (const char*)value, l); ddocSigInfo_SetOCSPRespondersCert(pSig, pCert); } // EncapsulatedX509Certificate // content of if(!xmlStrcmp(pCurrElem->tag, (xmlChar*)"EncapsulatedOCSPValue")) { OCSP_RESPONSE* pResp = 0; byte buf1[DIGEST_LEN+2]; int len1; NotaryInfo* pNot; SignatureInfo *pSig; pNot = ddocGetLastNotaryInfo(*ppSigDoc); RETURN_IF_NULL(pNot); pSig = ddocGetLastSignature(*ppSigDoc); RETURN_IF_NULL(pSig); ddocDebug(4, "ddocParseProcessNode", "EncapsulatedOCSPValue: %s", (const char*)value); err = ddocDecodeOCSPResponsePEMData(&pResp, (const byte*)value, strlen((const char*)value)); if(pResp) { // in ver 1.2 we have correct OCP digest // VS 1.76 - add 1.3 version too if(!strcmp((*ppSigDoc)->szFormatVer, DIGIDOC_XML_1_2_VER) || !strcmp((*ppSigDoc)->szFormatVer, DIGIDOC_XML_1_3_VER)) err = initializeNotaryInfoWithOCSP(*ppSigDoc, pNot, pResp, ddocSigInfo_GetOCSPRespondersCert(pSig), 0); else // in older versions the digest was incorrect err = initializeNotaryInfoWithOCSP(*ppSigDoc, pNot, pResp, ddocSigInfo_GetOCSPRespondersCert(pSig), 1); } else ddocDebug(1, "ddocParseProcessNode", "error decoding OCSP response"); // check OCSP digest len1 = sizeof(buf1); err = calculateNotaryInfoDigest(*ppSigDoc, pNot, buf1, &len1); pMBuf = ddocNotInfo_GetOcspDigest(pNot); RETURN_IF_NULL(pMBuf); if(err || compareByteArrays(buf1, len1, (byte*)pMBuf->pMem, pMBuf->nLen)) { SET_LAST_ERROR(ERR_BAD_OCSP_RESPONSE_DIGEST); err = ERR_BAD_OCSP_RESPONSE_DIGEST; ddocDebug(1, "ddocParseProcessNode", "Incorrect OCSP digest, len1: %d, len2: %d", len1, pMBuf->nLen); } } // EncapsulatedOCSPValue xmlFree(value); value = 0; } break; case XML_READER_TYPE_WHITESPACE: case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: case XML_READER_TYPE_CDATA: value = xmlTextReaderValue(reader); if(value) { // if we are collecting some xml content (, , etc.) ddocXRdrRecordElementContent(value, pBuf1); // if we are collecting xml content ddocXRdrRecordElementContent(value, pBuf2); xmlFree(value); value = 0; } break; case XML_READER_TYPE_ENTITY_REFERENCE: case XML_READER_TYPE_ENTITY: case XML_READER_TYPE_PROCESSING_INSTRUCTION: case XML_READER_TYPE_COMMENT: case XML_READER_TYPE_DOCUMENT: case XML_READER_TYPE_DOCUMENT_TYPE: case XML_READER_TYPE_DOCUMENT_FRAGMENT: case XML_READER_TYPE_NOTATION: break; } //ddocDebug(4, "ddocParseProcessNode", "Err %d", err); return err; } //-------------------------------------------------- // Reads in signed XML document // szFileName - name of digidoc file // ppSigDoc - address of new signed doc pointer // lMaxDFLen - maximum size of a cached DataFile //-------------------------------------------------- EXP_OPTION int ddocXRdrReadSignedDocFromFile(const char* szFileName, SignedDoc** pSigDoc, long lMaxDFLen) { char szConvDigiDocName[MAX_FILENAME+1]; xmlTextReaderPtr reader; ElementEntry stack; DigiDocMemBuf memBuf1, memBuf2; int ret; ddocDebug(3, "ddocXRdrReadSignedDocFromFile", "digidoc: %s, filename charset %s, max df: %ld", szFileName, lMaxDFLen); // check input params RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(pSigDoc); memset(&stack, 0, sizeof(ElementEntry)); *pSigDoc = NULL; // mark as not read in ddocDebug(3, "ddocXRdrReadSignedDocFromFile", "digidoc: %s", szFileName); clearErrors(); memBuf1.pMem = 0; memBuf1.nLen = 0; memBuf2.pMem = 0; memBuf2.nLen = 0; // converts file names if necessary ddocConvertFileName(szConvDigiDocName, sizeof(szConvDigiDocName), szFileName); // read digidoc reader = xmlNewTextReaderFilename(szConvDigiDocName); if(reader != NULL) { ret = xmlTextReaderRead(reader); // loop over all nodes... while(ret == 1) { ret = ddocParseProcessNode(reader, pSigDoc, &stack, &memBuf1, &memBuf2, lMaxDFLen); if(ret == ERR_OK) ret = 1; ret = xmlTextReaderRead(reader); } // cleanup ret = ddocStackPopElement(&stack, 1, NULL); if(memBuf1.pMem) free(memBuf1.pMem); if(memBuf2.pMem) free(memBuf2.pMem); xmlFreeTextReader(reader); if (ret != 0) ddocDebug(1, "ddocXRdrReadSignedDocFromFile", "%s : failed to parse: %d", szConvDigiDocName, ret); return ret; } else { SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); ddocDebug(1, "ddocXRdrReadSignedDocFromFile", "Error reading file: %s", szConvDigiDocName); } return ERR_OK; } //-------------------------------------------------- // Reads in signed XML document from memory buffer // szXml - memory buffer that contains digidoc data // xmlLen - length of the input data // szFileNameCharset - digidoc filename charset // ppSigDoc - address of new signed doc pointer // lMaxDFLen - maximum size of a cached DataFile //-------------------------------------------------- EXP_OPTION int ddocXRdrReadSignedDocFromMemory(const char* szXml, int xmlLen, SignedDoc** pSigDoc, long lMaxDFLen) { xmlTextReaderPtr reader; ElementEntry stack; DigiDocMemBuf memBuf1, memBuf2; int ret; ddocDebug(3, "ddocXRdrReadSignedDocFromMemory", "data len: %d, max df: %ld", xmlLen, lMaxDFLen); // check input params RETURN_IF_NULL_PARAM(szXml); RETURN_IF_NULL_PARAM(pSigDoc); memset(&stack, 0, sizeof(ElementEntry)); *pSigDoc = NULL; // mark as not read in clearErrors(); memBuf1.pMem = 0; memBuf1.nLen = 0; memBuf2.pMem = 0; memBuf2.nLen = 0; // read digidoc reader = xmlReaderForMemory(szXml, xmlLen, "http://www.sk.ee/DigiDoc/", "UTF-8", 0); if(reader != NULL) { ret = xmlTextReaderRead(reader); // loop over all nodes... while(ret == 1) { ret = ddocParseProcessNode(reader, pSigDoc, &stack, &memBuf1, &memBuf2, lMaxDFLen); if(ret == ERR_OK) ret = 1; ret = xmlTextReaderRead(reader); } // cleanup ret = ddocStackPopElement(&stack, 1, NULL); if(memBuf1.pMem) free(memBuf1.pMem); if(memBuf2.pMem) free(memBuf2.pMem); xmlFreeTextReader(reader); if (ret != 0) ddocDebug(1, "ddocXRdrReadSignedDocFromMemory", "failed to parse: %d", ret); return ret; } else { SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); ddocDebug(1, "ddocXRdrReadSignedDocFromMemory", "Error parsing digidoc"); } return ERR_OK; } libdigidoc-3.10.5/libdigidoc/DigiDocConvert.h0000664000372000037200000002623413560273131020410 0ustar travistravis#ifndef __DIGIDOC_CONVERT_H__ #define __DIGIDOC_CONVERT_H__ //================================================== // FILE: DigiDocEnc.h // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDoc character conversion routines // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 22.09.2004 Veiko Sinivee // Creation //================================================== #include #include #ifdef __cplusplus extern "C" { #endif //==========< general functions >============ //-------------------------------------------------- // Decodes a single hex digit // h - hex digit // return binary value //-------------------------------------------------- byte h2b(char h); //-------------------------------------------------- // Converts a single byte to two hex characters // b - binary value // dest - destination buffer //-------------------------------------------------- void b2h(byte b, char* dest); //-------------------------------------------------- // Converts correct filename to incorrect encoding // used in formats 1.0, 1.1 and 1.2 // src - input data // dest - buffer for converted data // len - length of destination buffer //-------------------------------------------------- EXP_OPTION void convFNameToWin(const char* src, char* dest, int len); //-------------------------------------------------- // Converts bad UTF-8 filename used in formats 1.0, // 1.1 and 1.2 to correct encoding // src - input data // dest - buffer for converted data // len - length of destination buffer //-------------------------------------------------- EXP_OPTION void convWinToFName(const char* src, char* dest, int len); // Converts a hex number (string) to binary value EXP_OPTION void hex2bin(const char* hex, byte* bin, int* len); // Converts a binary value to hex string EXP_OPTION void bin2hex(const byte* bin, int blen, char* hex, int* len); //============================================================ // Encodes input data in hex format. // pMBufSrc - input data // pMBufDest - destination buffer //============================================================ EXP_OPTION int ddocBin2Hex(const DigiDocMemBuf* pMBufSrc, DigiDocMemBuf* pMBufDest); // Helper function that converts ISO Latin1 to UTF8 EXP_OPTION char* ascii2utf8(const char* ascii, char* utf8out, int* outlen); // Helper function that converts UTF8 to ISO Latin1 EXP_OPTION char* utf82ascii(const char* utf8in, char* asciiout, int* outlen); // converts string from unicode to ascii EXP_OPTION void unicode2ascii(const char* uni, char* dest); // converts unicode escapes string to UTF8 EXP_OPTION void unicodeEscapes2utf8(const char* uni, char* dest); char* escape2xmlsym(const char* src); int hasUmlauts(const char* str); int str2asn1time(const SignedDoc* pSigDoc, const char* str, ASN1_GENERALIZEDTIME* asn1tm); //-------------------------------------------------- // Converts xml symbols to corresponding escapes // src - string with xml special sybols // returns string with esacpes //-------------------------------------------------- char* escape2xmlsym(const char* src); char* unescapeXmlsym(const char* src); //-------------------------------------------------- // Converts input data to UTF-8 // src - input data // returns converted string or NULL. Caller must free it. //-------------------------------------------------- EXP_OPTION int ddocConvertInput(const char* src, char** dest); // Base64 encode some data EXP_OPTION void encode(const byte* raw, int rawlen, byte* buf, int* buflen); // Base64 decode some data EXP_OPTION void decode(const byte* raw, int rawlen, byte* buf, int* buflen); //============================================================ // Decodes input data in Base64 format. // pMBufSrc - input data // pMBufDest - destination buffer //============================================================ EXP_OPTION int ddocDecodeBase64(DigiDocMemBuf* pMBufSrc, DigiDocMemBuf* pMBufDest); //============================================================ // Decodes input data in Base64 format. // data - input data // len - length of input data. Use -1 for zero terminated strings // pMBufDest - destination buffer //============================================================ EXP_OPTION int ddocDecodeBase64Data(void* data, long lLen, DigiDocMemBuf* pMBufDest); //============================================================ // Encodes input data in Base64 format. // pMBufSrc - input data // pMBufDest - destination buffer //============================================================ EXP_OPTION int ddocEncodeBase64(const DigiDocMemBuf* pMBufSrc, DigiDocMemBuf* pMBufDest); //=======< time convesrion >======================= //-------------------------------------------------- // Decodes an ASN1 generalized time // tm - ASN1 generalized time // y - year // M - month // d - day of month // h - hour // m - minute // s - second // returns error code or ERR_OK //-------------------------------------------------- int decodeGeneralizedTime(ASN1_GENERALIZEDTIME *tm, int* y, int* M, int* d, int* h, int* m, int* s); //-------------------------------------------------- // Decodes an ASN1 UTC time // tm - ASN1 generalized time // y - year // M - month // d - day of month // h - hour // m - minute // s - second // returns error code or ERR_OK //-------------------------------------------------- int decodeUTCTime(ASN1_UTCTIME *tm, int* y, int* M, int* d, int* h, int* m, int* s); //========================================================== // converts ASN1 time to time_t //========================================================== int asn1time2time_t(ASN1_TIME* tm, time_t* pT); int asn1time2time_t_local(ASN1_TIME* tm, time_t* pT); //========================================================== // converts ASN1 time to string //========================================================== int asn1time2strYear(const SignedDoc* pSigDoc, ASN1_TIME* tm, char* buf, int year, int len); //========================================================== // converts ASN1 time to string //========================================================== int asn1time2str(const SignedDoc* pSigDoc, ASN1_TIME* tm, char* buf, int len); //=================================================================== // converts time_t to timestamp string // t - time_t input value // szTimestamp - output buffer // len - length of buffer // returns error code or ERR_OK //=================================================================== EXP_OPTION int time_t2str(time_t t, char* szTimestamp, int len); //=================================================================== // converts string to time_t // szTimestamp - input buffer // pT - address time_t output value // returns error code or ERR_OK //=================================================================== EXP_OPTION int str2time_t(char* szTimestamp, time_t* pT); //-------------------------------------------------- // Converts a filename according to platform rules // dest - destination buffer // destlen - destination buffer length // src - source filename // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocConvertFileName(char* dest, int destlen, const char* src); //==========< only win32 fucntions >============ #ifdef WIN32 //-------------------------------------------------- // Converts input OEM charset data to 16 bit unicode. // oem - 8 bit oem charset input data // unicode - address of pointer for allocated unicode string. Caller must free() ! // outlen - address of length variable for unicode string // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int oem2unicode(const char* oem, char** unicode, int* outlen); //-------------------------------------------------- // Converts input 16 bit unicode data to UTF8. // unicode - 16 bit unicode input data // utf8 - address of pointer for allocated utf8 string. Caller must free() ! // outlen - address of length variable for utf8 string // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int unicode2utf8(const char* unicode, char** utf8, int* outlen); //-------------------------------------------------- // Converts input OEM charset data to UTF-8 // oem - 8 bit oem charset input data // utf8 - address of buffer allocated utf8 string. // len - size of buffer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int oem2utf8(const char* oem, char* utf8, int len); //-------------------------------------------------- // Converts input UTF-8 data to 16 bit unicode data. // utf8 - UTF-8 input data // unicode - address of pointer for allocated unicode string. Caller must free() ! // outlen - address of length variable for unicode string // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int utf82unicode(const char* utf8, char** unicode, int* outlen); //-------------------------------------------------- // Converts input 16 bit unicode data to oem charset data. // unicode - 16 bit unicode input data // oem - address of pointer for allocated oem string. Caller must free() ! // outlen - address of length variable for oem string // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int unicode2oem(const char* unicode, char** oem, int* outlen); //-------------------------------------------------- // Converts input UTF-8 data to OEM charset data // utf8 - UTF-8 input data // oem - address of buffer for oem string. // len - size of buffer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int utf82oem(const char* utf8, char* oem, int len); //-------------------------------------------------- // Converts input UTF-8 data to OEM charset data // pSigDoc - signed doc object // pDf - data file obejct // outFileName - output buffer // len - length of output buffer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int getDataFileFileName(SignedDoc* pSigDoc, DataFile* pDf, char* outFileName, int len); #endif // WIN32 //-------------------------------------------------- // Releases mem-block allocated by lib. In win32 // this must be done since the mem was allocated by dll // and must also be released by dll that allocated it. // p - mem to be freed //-------------------------------------------------- EXP_OPTION void freeLibMem(void* p); #ifdef __cplusplus } #endif #endif // __DIGIDOC_CONVERT_H__ libdigidoc-3.10.5/libdigidoc/DigiDocCsp.c0000664000372000037200000021165613560273131017514 0ustar travistravis//================================================== // FILE: DigiDocCsp.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for creating // and reading signed documents. // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 20.10.2004 Changed createOCSPRequest, added SignedDoc parameeter // 10.02.2004 Changed decodeCertificateData // ReadCertSerialNumber // ReadCertificate // NotaryInfo_new // 01.02.2004 Aare Amenberg // from comments "Functions from EstIDLib.c" // functions from EstIdLib.c file // 20.11.2003 Aare Amenberg // removed tes2.resp file creating // 29.10.2003 Created by AA // //================================================== #ifdef WIN32 #define WIN32_PKCS 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* only for xmlNewInputFromFile() */ #include #include #include #include #include "DigiCrypt.h" #include "DigiDocCert.h" #include "DigiDocCsp.h" CSProvider * cCSProvider; CSProvider * knownCSProviders[3]; //AARE01102003 typedef struct StoreHandle_st { HCERTSTORE hHandle; BOOL fRoot; } StoreHandle; BOOL Digi_OpenStore(StoreHandle *hStore); void Digi_CloseStore(StoreHandle *hStore); BOOL Digi_IsValidResponderCert(PCCERT_CONTEXT pCert); X509 * Digi_FindX509CopyFromStore(StoreHandle *hStore, X509 *pX509cert); X509 *Digi_FindResponderCert(StoreHandle *hStore, X509 *poSignerCert); char *Digi_GetName(X509_NAME *pName); BOOL Digi_CheckEnhancedKeyUsage(PCCERT_CONTEXT pCert, char *psValue); X509 *Digi_FindCertByResponse(StoreHandle *hStore, OCSP_RESPONSE *poResponse); PCCERT_CONTEXT Digi_FindCertBySubject(StoreHandle *hStore,char *psCN, BOOL bCheckValid, const char* szSerialNr, BOOL bCA); BOOL Digi_CompareCN(char *psSub1, char *psSub2); X509 **Digi_MakeCertList(X509 *poX509Main, StoreHandle *hStore); X509 **Digi_MakeCertListLow(X509 *poX509Main, StoreHandle *hStore); BOOL Digi_CheckResponderCertByResponse(X509 *poX509Responder, OCSP_RESPONSE *poResponse); void Digi_FreeCertList(X509 **caCerts); BOOL Digi_IsCert1SubjectDNEqualCert2IssuerDN(X509 *pCert1, X509 *pCert2); int ReadTestAare(char *pkcs12file); int Test_ReadCertData(X509 *poX509); int Test_ReadCertDataC(PCCERT_CONTEXT pCert); // Reads a certificate from pkcs12 container EXP_OPTION int Digi_readCertificateByPKCS12OnlyCertHandle(const char *pkcs12file, const char * passwd, X509 **x509); int Digi_getConfirmationWithCertSearch(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, char* pkcs12File, char* password, char* notaryURL, char* proxyHost, char* proxyPort); //int Digi_setNotaryCertificate(NotaryInfo* pNotary, X509* notCert); int Digi_verifyNotaryInfoWithCertSearch(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo); // verifies this one signature int Digi_verifySignatureInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const char* szDataFile); // verifies the whole document (returns on first err) int Digi_verifySigDoc(const SignedDoc* pSigDoc, const char* szDataFile); int Digi_verifySigDocWithCertSearch(const SignedDoc* pSigDoc, const char* szDataFile); int Digi_verifyNotaryInfoCERT(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo, const X509** caCerts, const X509* notCert, const X509* pSigCA); //int Digi_initializeNotaryInfoWithOCSP(SignedDoc* pSigDoc, NotaryInfo* pNotary, // OCSP_RESPONSE* resp, X509* notCert, int initDigest); // verifies signed doc int verifySigDoc_ByCertStore(const SignedDoc* pSigDoc, const char* szDataFile); // Verifies this signature int verifySignatureInfo_ByCertStore(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const char* szDataFile); // Verfies NotaryInfo signature int verifyNotaryInfo_ByCertStore(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo); // resolves certificate chain from MS CertStore upto root cert int resolveCertChain_ByCertStore(CertItem* pListStart); int GetAllCertificatesFromStore(const CertSearchStore *sS, CertItem **certList, int *numberOfCerts); void prepareString(const char * strIN,char * strOUT); void reverseArray(unsigned char *array, unsigned long arrayLen); extern int setup_verifyCERT(X509_STORE **newX509_STORE, const char *CApath, const X509** certs); extern X509_ALGOR* setSignAlgorithm(const EVP_MD * type); extern EXP_OPTION int signOCSPRequestPKCS12(OCSP_REQUEST *req, const char* filename, const char* passwd); extern LPBYTE getDefaultKeyName(CSProvider * cProvider); //extern CERT_PUBLIC_KEY_INFO * getCardKeyInfo(const char * ppContainerName); extern int GetCertificateFromStore(const CertSearchStore *sS, X509 **x509); extern int GetSignedHashWithEstIdCSPkey(const char * dataToBeSigned,unsigned long dataLen,unsigned char *pbKeyBlob, unsigned long *pbKeyBlobLen,unsigned char *hash, unsigned long *hashLen, unsigned char * hashedSignature,unsigned long * sigLen); extern int GetSignedHashWithKeyAndCSP(char *psKeyName, char *psCSPName, const char * dataToBeSigned,unsigned long dataLen,unsigned char *pbKeyBlob, unsigned long *pbKeyBlobLen,unsigned char *hash, unsigned long *hashLen, unsigned char * hashedSignature,unsigned long * sigLen, const char* ); extern X509 * findIssuerCertificatefromStore(X509 *x509); X509* Digi_FindDirectCA(X509 *poX509Main, StoreHandle *hStore); X509* Digi_FindCertBySubjectAndHash(StoreHandle *hStore, char *psCN, BOOL bCheckValid, const char* szSerialNr, BOOL bCA, DigiDocMemBuf *pHash); //==========< macros >==================== #define SET_LAST_ERROR(code) (addError((code), __FILE__, __LINE__, "")) #define SET_LAST_ERROR_IF_NOT(expr, code) { if(!(expr)) addError((code), __FILE__, __LINE__, #expr); } #define SET_LAST_ERROR_RETURN(code, retVal) { SET_LAST_ERROR(code); return (retVal); } #define SET_LAST_ERROR_RETURN_IF_NOT(expr, code, retVal) { if(!(expr)) { addError((code), __FILE__, __LINE__, #expr); return (retVal); } } #define SET_LAST_ERROR_RETURN_VOID_IF_NOT(expr, code) { if(!(expr)) { addError((code), __FILE__, __LINE__, #expr); return; } } #define RETURN_IF_NOT(expr, code) SET_LAST_ERROR_RETURN_IF_NOT((expr), (code), (code)); #define RETURN_IF_NULL(p) RETURN_IF_NOT((p), ERR_NULL_POINTER); #define RETURN_VOID_IF_NULL(p) SET_LAST_ERROR_RETURN_VOID_IF_NOT((p), ERR_NULL_POINTER); #define RETURN_OBJ_IF_NULL(p, obj) SET_LAST_ERROR_RETURN_IF_NOT((p), ERR_NULL_POINTER, (obj)); #define SET_LAST_ERROR_RETURN_CODE(code) { SET_LAST_ERROR(code); return (code); } //======================================== BOOL Digi_OpenStore(StoreHandle *hStore) { BOOL fRes = FALSE; if (hStore != NULL) { memset(hStore,0,sizeof(StoreHandle)); hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"CA"); if (hStore->hHandle != NULL) fRes = TRUE; } return(fRes); } void Digi_CloseStore(StoreHandle *hStore) { if (hStore != NULL && hStore->hHandle) CertCloseStore(hStore->hHandle,CERT_CLOSE_STORE_FORCE_FLAG); hStore->hHandle = NULL; hStore->fRoot = FALSE; } X509 * Digi_FindX509CopyFromStore(StoreHandle *hStore, X509 *pX509cert) { X509 *pResultCert = NULL; char* certBlob; int certBlobLen; PCCERT_CONTEXT pCertFindContext = NULL; PCCERT_CONTEXT pCertContext = NULL; char *psValue = "1.3.6.1.5.5.7.3.9"; if (hStore == NULL || pX509cert == NULL) return(pResultCert); certBlobLen = i2d_X509(pX509cert, NULL) + 1000; certBlob = malloc(certBlobLen); encodeCert(pX509cert,certBlob,&certBlobLen); if (!certBlob) return(pResultCert); pCertFindContext = CertCreateCertificateContext(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,certBlob,certBlobLen); if (!pCertFindContext) return(pResultCert); pCertContext = CertFindCertificateInStore(hStore->hHandle, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertFindContext, NULL); if (pCertContext) { //cert found if (Digi_CheckEnhancedKeyUsage(pCertContext,psValue) != TRUE) return(pResultCert); ddocDecodeX509Data(&pResultCert,pCertContext->pbCertEncoded,pCertContext->cbCertEncoded); } else { char schultz[300]; snprintf(schultz, sizeof(schultz), "CertFindCertificateInStore open failed with 0x%0lx ", GetLastError()); return(pResultCert); } if (certBlob) free(certBlob); return pResultCert; } X509 *Digi_FindResponderCert(StoreHandle *hStore, X509 *poSignerCert) { X509 *poResultCert = NULL; FILETIME oResultTime; X509 *poX509; BOOL fSet; PCCERT_CONTEXT pCert = NULL; X509_NAME *poX509SignerName = NULL; X509_NAME *poX509CurrentName = NULL; poX509SignerName = X509_get_issuer_name(poSignerCert); while (pCert = CertEnumCertificatesInStore(hStore->hHandle, pCert)) { fSet = FALSE; //get handle //AA100204 ddocDecodeX509Data(&poX509, pCert->pbCertEncoded,pCert->cbCertEncoded); if (poX509 != NULL) { //get current cert issuer poX509CurrentName = X509_get_issuer_name(poX509); //TEST //psTemp = Digi_GetName(poX509CurrentName); //Digi_CheckEnhancedKeyUsage(pCert,"1.3.6.1.5.5"); //Test_ReadCertData(poX509); //END TEST // if issuer match if (poX509SignerName != NULL && poX509CurrentName != NULL && X509_NAME_cmp(poX509SignerName, poX509CurrentName) == 0) { // check date // NULL, if current time if (Digi_IsValidResponderCert(pCert) == TRUE) { if (poResultCert == NULL) fSet = TRUE; else { if (CompareFileTime(&pCert->pCertInfo->NotBefore, &oResultTime) > 0) fSet = TRUE; } if (fSet == TRUE) { //delete previous if exists if (poResultCert != NULL) X509_free(poResultCert); //set result value poResultCert = poX509; memmove(&oResultTime,&pCert->pCertInfo->NotBefore,sizeof(FILETIME)); } } } } if (poX509 != NULL && fSet == FALSE) X509_free(poX509); } return(poResultCert); } int Test_ReadCertDataC(PCCERT_CONTEXT pCert) { int iRes = 0; X509 *poX509 = NULL; if (pCert != NULL); //AA100204 ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded); if (poX509 != NULL) iRes = Test_ReadCertData(poX509); return(iRes); } int Test_ReadCertData(X509 *poX509) { int iRes; DigiDocMemBuf mbuf1; DigiDocMemBuf mbuf2; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; // get issuer DN iRes = ddocCertGetIssuerDN(poX509, &mbuf1); iRes = ddocMemAppendData(&mbuf1, "\n", -1); // get subject DN iRes = ddocCertGetSubjectDN(poX509, &mbuf2); iRes = ddocMemAppendData(&mbuf1, (const char*)mbuf2.pMem, mbuf2.nLen); // display it MessageBox(NULL,(const char*)mbuf1.pMem,"TEST",0); ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); return(0); } BOOL Digi_IsValidResponderCert(PCCERT_CONTEXT pCert) { BOOL fIsValid = FALSE; char *psValue = "1.3.6.1.5.5.7.3.9"; if (pCert != NULL) { fIsValid = Digi_CheckEnhancedKeyUsage(pCert,psValue); if (fIsValid == TRUE) { if (CertVerifyTimeValidity(NULL,pCert->pCertInfo) != 0) fIsValid = FALSE; } } return(fIsValid); } BOOL Digi_CheckEnhancedKeyUsage(PCCERT_CONTEXT pCert, char *psValue) { BOOL fRes = FALSE; DWORD dwFlags = CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG; PCERT_ENHKEY_USAGE pUsage = NULL; //DWORD cUsageIdentifier - number of elements in rgpszUsageIdentifier //LPSTR *rgpszUsageIdentifier - array; DWORD cbUsage = 0; BOOL fCallRes; int iI; char *psValueCurrent; fCallRes = CertGetEnhancedKeyUsage(pCert,dwFlags,NULL, &cbUsage); if (fCallRes == TRUE) { pUsage = (PCERT_ENHKEY_USAGE)malloc(cbUsage); fCallRes = CertGetEnhancedKeyUsage(pCert,dwFlags,pUsage, &cbUsage); if (fCallRes == TRUE) { for (iI=0; iI < (int)pUsage->cUsageIdentifier;++iI) { psValueCurrent = pUsage->rgpszUsageIdentifier[iI]; if (psValueCurrent != NULL && psValue != NULL) { if (strstr(psValueCurrent,psValue) != NULL) { fRes = TRUE; break; } } } } } if (pUsage != NULL) free(pUsage); return(fRes); } X509 *Digi_FindCertByResponse(StoreHandle *hStore, OCSP_RESPONSE *poResponse) { X509 *poX509 = NULL; PCCERT_CONTEXT pCert = NULL; OCSP_BASICRESP *br = NULL; const X509_NAME *name = NULL; int iLen; char sCN[255]; if (poResponse != NULL) { if ((br = OCSP_response_get1_basic(poResponse)) == NULL) return(poX509); OCSP_resp_get0_id(br, NULL, &name); if (!name) { if(br) OCSP_BASICRESP_free(br); return(poX509); } iLen = X509_NAME_get_text_by_NID(name,NID_commonName,sCN,sizeof(sCN)); if (iLen > 0) //VS: 18.03.2006 - use only currently valid cert for new notary pCert = Digi_FindCertBySubject(hStore, sCN, TRUE, 0, TRUE); if(pCert != NULL) //AA100204 ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded); } if(br) OCSP_BASICRESP_free(br); return(poX509); } //Added by AA 09/10/2003 BOOL Digi_CheckResponderCertByResponse(X509 *poX509Responder, OCSP_RESPONSE *poResponse) { BOOL fRes = FALSE; OCSP_BASICRESP *br = NULL; const X509_NAME *name = NULL; int iLen; char sCNResp[255]; char sCNCert[255]; if (poResponse != NULL) { if ((br = OCSP_response_get1_basic(poResponse)) == NULL) return(fRes); OCSP_resp_get0_id(br, NULL, &name); if (!name) return(fRes); iLen = X509_NAME_get_text_by_NID(name,NID_commonName,sCNResp,sizeof(sCNResp)); if (iLen > 0) { iLen = X509_NAME_get_text_by_NID(X509_get_subject_name(poX509Responder),NID_commonName, sCNCert,sizeof(sCNCert)); if (iLen > 0) { fRes = Digi_CompareCN(sCNResp,sCNCert); } } } return(fRes); } //VS: 18.03.2006 - use only currently valid cert for new notary PCCERT_CONTEXT Digi_FindCertBySubject(StoreHandle *hStore, char *psCN, BOOL bCheckValid, const char* szSerialNr, BOOL bCA) { PCCERT_CONTEXT pCert = NULL; BOOL fFind = FALSE; X509 *poX509; char sSerial[255]; time_t tNow; DigiDocMemBuf mbuf; mbuf.pMem = 0; mbuf.nLen = 0; if (hStore == NULL || psCN == NULL) return(pCert); Digi_CloseStore(hStore); hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG, (bCA ? L"CA" : L"My")); if (hStore->hHandle == NULL) return(pCert); //get signer issuer while (fFind == FALSE && (pCert = CertEnumCertificatesInStore(hStore->hHandle,pCert))) { //AA100204 ddocDecodeX509Data(&poX509, pCert->pbCertEncoded,pCert->cbCertEncoded); if (poX509 != NULL) { //iLen = X509_NAME_get_text_by_NID(X509_get_subject_name(poX509),NID_commonName, sSubject,255); ddocCertGetSubjectCN(poX509, &mbuf); if(mbuf.nLen > 0) { fFind = Digi_CompareCN((char*)mbuf.pMem, psCN); if(fFind) { if(szSerialNr) { //VS: 18.03.2006 - look for a cert with specific serial nr ReadCertSerialNumber(sSerial, sizeof(sSerial)-1, poX509); fFind = !strcmp(szSerialNr, sSerial); } else if(bCheckValid) { //VS: 18.03.2006 - use only currently valid cert for new notary time(&tNow); fFind = !isCertValid(poX509, tNow); } } } X509_free(poX509); } } if (fFind == FALSE) pCert = NULL; return(pCert); } X509* Digi_FindCertBySubjectAndHash(StoreHandle *hStore, char *psCN, BOOL bCheckValid, const char* szSerialNr, BOOL bCA, DigiDocMemBuf *pHash) { PCCERT_CONTEXT pCert = NULL; BOOL fFind = FALSE; X509 *poX509 = NULL, *pSCert = NULL; char sSerial[255]; time_t tNow; DigiDocMemBuf mbuf1, mbuf2, mbuf3; //, mbuf4, mbuf5; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; mbuf3.pMem = 0; mbuf3.nLen = 0; /*mbuf4.pMem = 0; mbuf4.nLen = 0; mbuf5.pMem = 0; mbuf5.nLen = 0;*/ if (hStore == NULL || psCN == NULL) return NULL; Digi_CloseStore(hStore); hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG, (bCA ? L"CA" : L"My")); if (hStore->hHandle == NULL) return NULL; ddocEncodeBase64(pHash, &mbuf3); ddocDebug(3, "Digi_FindCertBySubjectAndHash", "Find CN: %s serial: %s subj-hash: %s", psCN, szSerialNr, (char*)mbuf3.pMem); ddocMemBuf_free(&mbuf3); //get signer issuer while (fFind == FALSE && (pCert = CertEnumCertificatesInStore(hStore->hHandle,pCert))) { //AA100204 ddocDecodeX509Data(&poX509, pCert->pbCertEncoded,pCert->cbCertEncoded); if (poX509 != NULL) { //iLen = X509_NAME_get_text_by_NID(X509_get_subject_name(poX509),NID_commonName, sSubject,255); ddocCertGetSubjectCN(poX509, &mbuf1); if(mbuf1.nLen > 0) { fFind = Digi_CompareCN((char*)mbuf1.pMem, psCN); if(fFind) { if(szSerialNr) { //VS: 18.03.2006 - look for a cert with specific serial nr ReadCertSerialNumber(sSerial, sizeof(sSerial)-1, poX509); fFind = !strcmp(szSerialNr, sSerial); } else if(bCheckValid) { //VS: 18.03.2006 - use only currently valid cert for new notary time(&tNow); fFind = !isCertValid(poX509, tNow); } } if(fFind && pHash && poX509) { readSubjectKeyIdentifier(poX509, &mbuf2); ddocEncodeBase64(&mbuf2, &mbuf3); //readAuthorityKeyIdentifier(poX509, &mbuf4); //ddocEncodeBase64(&mbuf4, &mbuf5); if(!ddocMemCompareMemBufs(pHash, &mbuf2)) { pSCert = poX509; fFind = TRUE; //break; } else fFind = FALSE; } } //ddocDebug(3, "Digi_FindCertBySubjectAndHash", "Compare CN: %s serial: %s subj-hash: %s auth-hash: %s rc: %d", (char*)mbuf1.pMem, sSerial, (char*)mbuf3.pMem, (char*)mbuf5.pMem, fFind); ddocDebug(3, "Digi_FindCertBySubjectAndHash", "Compare CN: %s serial: %s subj-hash: %s rc: %d", (char*)mbuf1.pMem, sSerial, (char*)mbuf3.pMem, fFind); if(!pSCert) { X509_free(poX509); poX509 = NULL; } ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); //ddocMemBuf_free(&mbuf4); //ddocMemBuf_free(&mbuf5); } } if(fFind == FALSE) pCert = NULL; ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); //ddocMemBuf_free(&mbuf4); //ddocMemBuf_free(&mbuf5); return pSCert; } //---------------------------------------------------- // Returns a list of certificates based on the // search criteria // szCN - CN of certs to search for // tValid - check validity on the given date (if not 0) // szSerialNr - serach for certs with this serial nr // pMBuf - public key hash to search //---------------------------------------------------- X509 **Digi_FindCACerts(StoreHandle *hStore, const char* szCN, time_t tValid, const char* szSerialNr, DigiDocMemBuf* pMBuf) { int iMaxCerts = 512; int iRes = 0, l1, l2; X509 **caCerts = NULL; X509 *poX509; PCCERT_CONTEXT pCert = NULL; BOOL fAdd; char buf1[255], buf2[100]; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; //ddocDebug(3, "Digi_FindCACerts", "CN: %s tValid: %ld serial: %s, // open CA store if(!hStore) return NULL; Digi_CloseStore(hStore); hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"CA"); if (hStore->hHandle == NULL) { return NULL; } // alloc list and initalize all positions to NULL caCerts = (X509**)malloc(sizeof(void*) * (iMaxCerts+1)); if(caCerts == NULL) { return(caCerts); } memset(caCerts,0,sizeof(void*) * (iMaxCerts+1)); if(hStore->hHandle != NULL) { while(pCert= CertEnumCertificatesInStore(hStore->hHandle, pCert)) { fAdd = FALSE; ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded); if(poX509 != NULL) { // check CN if(szCN) { buf1[0] = 0; X509_NAME_get_text_by_NID(X509_get_subject_name(poX509), NID_commonName, buf1, sizeof(buf1)); fAdd = Digi_CompareCN((char*)szCN, buf1); } // check serial nr if(szSerialNr) { buf1[0] = 0; ReadCertSerialNumber(buf1, sizeof(buf1)-1, poX509); fAdd = !strcmp(szSerialNr, (const char*)buf1); } // check pubkey hash if(pMBuf) { ddocCertGetPubkeyDigest(poX509, &mbuf1); l1 = sizeof(buf1); l2 = sizeof(buf2); bin2hex((const byte*)mbuf1.pMem, mbuf1.nLen, buf1, &l1); bin2hex((const byte*)pMBuf->pMem, pMBuf->nLen, buf2, &l2); ddocDebug(3, "Digi_FindCACerts", "Compare cert-hash: %s with searched-hash %s", buf1, buf2); fAdd = !ddocMemCompareMemBufs(&mbuf1, pMBuf); ddocMemBuf_free(&mbuf1); } if(tValid) fAdd = !isCertValid(poX509, tValid); } // if any of the conditiones matched then add cert to list if (fAdd == TRUE) { caCerts[iRes] = poX509; ++iRes; } else X509_free(poX509); } } // if no certs found then free the array caCerts[iRes] = NULL; if(iRes == 0) { free(caCerts); caCerts = NULL; } return(caCerts); } X509 **Digi_MakeCertList(X509 *poX509Main, StoreHandle *hStore) { X509 **caCerts = NULL; memset(hStore,0,sizeof(StoreHandle)); hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"CA"); if (hStore->hHandle != NULL) { caCerts = Digi_MakeCertListLow(poX509Main, hStore); if (caCerts == NULL) { CertCloseStore(hStore->hHandle,CERT_CLOSE_STORE_FORCE_FLAG); hStore->hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"ROOT"); if (hStore->hHandle != NULL) { hStore->fRoot = TRUE; caCerts = Digi_MakeCertListLow(poX509Main, hStore); } } } return(caCerts); } X509 **Digi_MakeCertListLow(X509 *poX509Main, StoreHandle *hStore) { int iMaxCerts = 512; int iRes = 0; X509 **caCerts = NULL; X509 *poX509; PCCERT_CONTEXT pCert = NULL; BOOL fAdd; if (poX509Main == NULL) return(caCerts); caCerts = (X509**)malloc(sizeof(void*) * (iMaxCerts+1)); if (caCerts == NULL) return(caCerts); memset(caCerts,0,sizeof(void*) * (iMaxCerts+1)); if (hStore->hHandle != NULL) { while( pCert= CertEnumCertificatesInStore( hStore->hHandle,pCert)) { fAdd = FALSE; ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded); //TEST //Test_ReadCertData(poX509); //ENDTEST if (poX509 != NULL) fAdd = Digi_IsCert1SubjectDNEqualCert2IssuerDN(poX509,poX509Main); if (fAdd == TRUE) { caCerts[iRes] = poX509; ++iRes; } else X509_free(poX509); } } //Added by AA 2004/03/15 caCerts[iRes] = NULL; if (iRes == 0) { free(caCerts); caCerts = NULL; } return(caCerts); } X509* Digi_FindDirectCA(X509 *poX509Main, StoreHandle *hStore) { X509 *poX509; PCCERT_CONTEXT pCert = NULL; if (poX509Main == NULL) return NULL; if (hStore->hHandle != NULL) { while(pCert = CertEnumCertificatesInStore( hStore->hHandle, pCert)) { ddocDecodeX509Data(&poX509,pCert->pbCertEncoded,pCert->cbCertEncoded); if(poX509 != NULL) { if(Digi_IsCert1SubjectDNEqualCert2IssuerDN(poX509, poX509Main)) { return poX509; } } else X509_free(poX509); } } return NULL; } void Digi_FreeCertList(X509 **caCerts) { int iMaxCerts = 512; int i; if (caCerts != NULL) { for(i = 0; i < iMaxCerts; i++) { if(caCerts[i] != NULL) X509_free(caCerts[i]); } free(caCerts); } } BOOL Digi_CompareCN(char *psSub1, char *psSub2) { BOOL fRes = FALSE; if (psSub1 != NULL && psSub2 != NULL ) { if (strlen(psSub1) > 0 || strlen(psSub2) > 0) { if (strcmp(psSub1,psSub2) == 0) fRes = TRUE; } } return(fRes); } int countCerts(const X509** certs) { int i = 0; while(certs && certs[i]) i++; return i; } BOOL Digi_IsCert1SubjectDNEqualCert2IssuerDN(X509 *pCert1, X509 *pCert2) { BOOL fEqual = FALSE; unsigned long ulHash1; unsigned long ulHash2; ulHash1 = X509_subject_name_hash(pCert1); ulHash2 = X509_issuer_name_hash(pCert2); if (ulHash1 == ulHash2) fEqual = TRUE; return(fEqual); } //29/09/2003 //31/05/2006 - (g_current_TSAProfile->g_bAddTimeStamp) enables timestamping int Digi_getConfirmationWithCertSearch(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, char* pkcs12File, char *password, char* notaryURL, char* proxyHost, char* proxyPort) { int err = ERR_OK, err2 = ERR_OK, i, l1; StoreHandle hStore; NotaryInfo* pNotInf = NULL; X509 *pNotCert = NULL, *pNotCertFound = NULL, *pSigCa = 0; X509 **caCerts = NULL; X509 **respCerts = NULL; const DigiDocMemBuf *pMBuf = 0; char szCN[255], buf1[100]; // set default values from config file if(ConfigItem_lookup_bool("SIGN_OCSP", 1)) { if(!pkcs12File || !strlen(pkcs12File)) pkcs12File = (char*)ConfigItem_lookup("DIGIDOC_PKCS_FILE"); if(!password || !strlen(password)) password = (char*)ConfigItem_lookup("DIGIDOC_PKCS_PASSWD"); } if(!notaryURL || !strlen(notaryURL)) notaryURL = (char*)ConfigItem_lookup("DIGIDOC_OCSP_URL"); if(ConfigItem_lookup_bool("USE_PROXY", 1)) { proxyHost = (char*)ConfigItem_lookup("DIGIDOC_PROXY_HOST"); RETURN_IF_NOT(proxyHost, ERR_WRONG_URL_OR_PROXY); proxyPort = (char*)ConfigItem_lookup("DIGIDOC_PROXY_PORT"); RETURN_IF_NOT(proxyPort, ERR_WRONG_URL_OR_PROXY); } if (Digi_OpenStore(&hStore) == FALSE) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_STORE_READ); // we need to find some CA-s of signer before asking for // confirmation in order to be able to construct certid // we need this because of users direct CA respCerts = Digi_MakeCertListLow(ddocSigInfo_GetSignersCert(pSigInfo), &hStore); if(respCerts) { for(i = 0; respCerts[i]; i++) // find lowest (middle) ca - direct ca of signers cert pSigCa = respCerts[i]; } // VS: ver 1.5.33 - make this decision lower if confirmation can still be retrieved //if(!respCerts) SET_LAST_ERROR_RETURN_CODE(ERR_SIGNERS_CERT_NOT_TRUSTED); err = getConfirmation(pSigDoc, pSigInfo, respCerts, NULL, pkcs12File, password, notaryURL, proxyHost, proxyPort); //Digi_FreeCertList(respCerts); if(respCerts) { for(i = 0; respCerts[i]; i++) { if(respCerts[i] && respCerts[i] != pSigCa) { X509_free(respCerts[i]); respCerts[i] = 0; } } } if(err) return err; pNotInf = pSigInfo->pNotary; pMBuf = ddocNotInfo_GetResponderId(pNotInf); RETURN_IF_NOT(pMBuf != NULL, ERR_NOTARY_SIG_MATCH); if(pNotInf->nRespIdType == RESPID_NAME_TYPE) { szCN[0] = 0; if(pMBuf && pMBuf->pMem) findCN((char*)pMBuf->pMem, szCN, sizeof(szCN)); pMBuf = NULL; // don't look for pubkey hash ddocDebug(3, "Digi_getConfirmationWithCertSearch", "Find OCSP resp CA-s by key %s", szCN); } else if(pNotInf->nRespIdType == RESPID_KEY_TYPE) { // look for pubkey hash in Digi_FindCACerts pMBuf = &(pNotInf->mbufRespId); szCN[0] = 0; l1 = sizeof(buf1); bin2hex((const byte*)pNotInf->mbufRespId.pMem, pNotInf->mbufRespId.nLen, buf1, &l1); ddocDebug(3, "Digi_getConfirmationWithCertSearch", "Find OCSP resp CA-s by hash %s", buf1); } RETURN_IF_NOT(pNotInf != NULL, ERR_NOTARY_SIG_MATCH); // find a list of potential responder certificates // search only by responder id = CN. Should I check also validity on current time ? respCerts = Digi_FindCACerts(&hStore, (szCN[0] ? szCN : NULL), 0, 0, (DigiDocMemBuf*)pMBuf); clearErrors(); if(!err && respCerts) { i = 0; do { pNotCert = respCerts[i]; // get the next potential notary cert if(pNotCert) { // find CA certs for it Digi_CloseStore(&hStore); caCerts = Digi_MakeCertList(pNotCert, &hStore); if (caCerts != NULL) { err2 = finalizeAndVerifyNotary2(pSigDoc, pSigInfo, pNotInf, (const X509**)caCerts, (const X509*)pNotCert, pSigCa); // if this didn't verify then free the cert and mark the slot as freed if(err2) { // remove certid and certvalue created for verification removeNotaryInfoCert(pSigInfo); // mark slot as freed (was done above) respCerts[i] = 0; } // found one cert, save it for later if(!err2) { // if one cert was already found // then pick the freshes one - one were not-after-date is latest if(pNotCertFound) { if(getCertNotAfterTimeT(pNotCert) > getCertNotAfterTimeT(pNotCertFound)) { // release older cert X509_free(pNotCertFound); pNotCertFound = pNotCert; } } pNotCertFound = pNotCert; } // else don't free, give ownership to new Notary! // mark the slot as freed respCerts[i] = 0; } else { err = ERR_CERT_STORE_READ; //fprintf(hFile, "No CA-s found, err: %d\n", err); } // free CA certs Digi_FreeCertList(caCerts); } i++; } while(pNotCert); // free the remaining responder certs Digi_FreeCertList(respCerts); } // else clear verifying errors clearErrors(); // final check with the selected responders certificate if(pNotCertFound) { Digi_CloseStore(&hStore); caCerts = Digi_MakeCertList(pNotCertFound, &hStore); err = finalizeAndVerifyNotary2(pSigDoc, pSigInfo, pNotInf, (const X509**)caCerts, (const X509*)pNotCertFound, pSigCa); Digi_FreeCertList(caCerts); } else err = ERR_OCSP_CERT_NOTFOUND; //fprintf(hFile, "OCSP finalize RC: %d\n", err); // reset original signature content if(pSigInfo->mbufOrigContent.pMem) ddocMemBuf_free(&(pSigInfo->mbufOrigContent)); Digi_CloseStore(&hStore); if(err != ERR_OK) SET_LAST_ERROR(err); return(err); } //-------------------------------------------------- // Verfies NotaryInfo signature // pSigDoc - signed doc object // pNotInfo - NotaryInfo object // caFiles - array of CA file names terminated with NULL // CApath - path to (directory) all certs // notCertFile - Notary (e.g. OCSP responder) cert file //-------------------------------------------------- int Digi_verifyNotaryInfoWithCertSearch(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo) { X509** caCerts = NULL; X509* notCert = NULL; X509* cert = NULL, *pSigCA = NULL, *pSigCert = NULL; StoreHandle hStore; SignatureInfo *pSigInfo = NULL; int err = ERR_OK; if(pNotInfo) pSigInfo = ddocGetSignatureForNotary(pSigDoc, pNotInfo); if(pSigInfo != NULL) { cert = ddocSigInfo_GetOCSPRespondersCert(pSigInfo); } caCerts = Digi_MakeCertList(cert,&hStore); if(caCerts == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_STORE_READ); //siin leitakse responderi cert vastavalt kirjeldusele //notCert = Digi_FindResponderCert(&hStore,cert); //08.03.2005 leitakse responderi koopia win certstoorest if(!err) { notCert = Digi_FindX509CopyFromStore(&hStore,cert); pSigCert = ddocSigInfo_GetSignersCert(pSigInfo); pSigCA = Digi_FindDirectCA(pSigCert, &hStore); if((!notCert || !pSigCA) && hStore.fRoot == 1) { // try also CA store Digi_CloseStore(&hStore); memset(&hStore,0,sizeof(StoreHandle)); hStore.hHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,L"CA"); if(!notCert) notCert = Digi_FindX509CopyFromStore(&hStore,cert); if(!pSigCA) pSigCA = Digi_FindDirectCA(pSigCert, &hStore); } if (notCert) err = Digi_verifyNotaryInfoCERT(pSigDoc, pNotInfo, (const X509**)caCerts, notCert, pSigCA); else err = ERR_OCSP_CERT_NOTFOUND; } Digi_CloseStore(&hStore); Digi_FreeCertList(caCerts); //AM 23.05.08 where notCert is freed? if(notCert) X509_free(notCert); if(pSigCA) X509_free(pSigCA); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // Verifies the whole document, but returns on first error // Use the functions defined earlier to verify all contents // step by step. // pSigDoc - signed doc data // //============================================================ int Digi_verifySigDocWithCertSearch(const SignedDoc* pSigDoc, const char* szDataFile) { SignatureInfo* pSigInfo; NotaryInfo* pNotInfo; int i, d, err = ERR_OK; RETURN_IF_NULL(pSigDoc); //assert(pSigDoc); d = getCountOfSignatures(pSigDoc); for(i = 0; i < d; i++) { pSigInfo = getSignature(pSigDoc, i); err = Digi_verifySignatureInfo(pSigDoc, pSigInfo, szDataFile); RETURN_IF_NOT(err == ERR_OK, err); pNotInfo = pSigInfo->pNotary; err = Digi_verifyNotaryInfoWithCertSearch(pSigDoc, pNotInfo); RETURN_IF_NOT(err == ERR_OK, err); } return err; } //-------------------------------------------------- // Reads a certificate from pkcs12 conteiner //-------------------------------------------------- // AA 18/09/2003 EXP_OPTION int Digi_readCertificateByPKCS12OnlyCertHandle(const char *pkcs12file, const char * passwd, X509 **x509) { int err = ERR_OK; EVP_PKEY *pkey; // VS: 26.01.2010 - initialize (*x509) = 0; //AM 16.09.08 DigiDocClient calling it with empty strings even ocsp request signing is off if(!strcmp(pkcs12file, "")) return ERR_OK; err = ReadCertificateByPKCS12(x509,pkcs12file,passwd,&pkey); //AM 22.05.08 pKey should be freed if(err == 0 && pkey) EVP_PKEY_free(pkey); RETURN_IF_NOT(err == ERR_OK, err); return ERR_OK; } //============================================================ // Verifies this signature // pSigDoc - signed doc data // pSigInfo - signature info object // signerCA - direct signer CA certs filename // szDateFile - name of the digidoc file // bUseCA - use CA certs or not 1/0 // from original file and use it for hash function. // This is usefull if the file has been generated by // another library and possibly formats these elements // differently. //============================================================ int Digi_verifySignatureInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const char* szDataFile) { char buf2[100], *p1 = 0; X509* pCaCert = 0; int err = ERR_OK, k = 0; StoreHandle hStore; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; buf2[0] = 0; if(!Digi_OpenStore(&hStore)) return ERR_CERT_STORE_READ; //p1 = ddocSigInfo_GetSignersCert_IssuerName(pSigInfo); p1 = (char*)ddocSigInfo_GetSignersCert_IssuerNameAndHash(pSigInfo, &mbuf1); //strncpy(buf1, ddocSigInfo_GetSignersCert_IssuerName(pSigInfo), sizeof(buf1)); if(p1) findCN((char*)p1, buf2, sizeof(buf2)); pCaCert = Digi_FindCertBySubjectAndHash(&hStore, buf2, FALSE, 0, TRUE, &mbuf1); if(!pCaCert) { ddocDebug(1, "Digi_verifySignatureInfo", "ERR112 cert: %s", buf2); //AM 02.03.09 teadmata olek kui leia CA serti return ERR_UNKNOWN_CA; } err = verifySignatureInfoCERT(pSigDoc, pSigInfo, pCaCert, szDataFile, (pCaCert != NULL)); if(pCaCert) X509_free(pCaCert); Digi_CloseStore(&hStore); ddocMemBuf_free(&mbuf1); if((k = getCountOfSignerRoles(pSigInfo, 0)) > 1) { ddocDebug(1, "Digi_verifySignatureInfo", "Number of roles: %d, Currently supports max 1 roles", k); SET_LAST_ERROR(ERR_MAX_1_ROLES); err = ERR_MAX_1_ROLES; } return err; } //============================================================ // Verifies the whole document, but returns on first error // Use the functions defined earlier to verify all contents // step by step. // pSigDoc - signed doc data // //============================================================ int Digi_verifySigDoc(const SignedDoc* pSigDoc, const char* szDataFile) { SignatureInfo* pSigInfo; NotaryInfo* pNotInfo; int i, d, err = ERR_OK; RETURN_IF_NULL_PARAM(pSigDoc); //assert(pSigDoc); d = getCountOfSignatures(pSigDoc); for(i = 0; i < d; i++) { pSigInfo = getSignature(pSigDoc, i); err = Digi_verifySignatureInfo(pSigDoc, pSigInfo, szDataFile); RETURN_IF_NOT(err == ERR_OK, err); } d = getCountOfNotaryInfos(pSigDoc); for(i = 0;i < d; i++) { pNotInfo = getNotaryInfo(pSigDoc, i); err = Digi_verifyNotaryInfoWithCertSearch(pSigDoc, pNotInfo); RETURN_IF_NOT(err == ERR_OK, err); } return ERR_OK; } //-------------------------------------------------- // Verfies NotaryInfo signature // pSigDoc - signed doc object // pNotInfo - NotaryInfo object // caCerts - CA certificate pointer array terminated with NULL // CApath - path to (directory) all certs // notCertFile - Notary (e.g. OCSP responder) cert file //-------------------------------------------------- int Digi_verifyNotaryInfoCERT(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo, const X509** caCerts, const X509* notCert, const X509* pSigCA) { SignatureInfo* pSigInfo = NULL; pSigInfo = ddocGetSignatureForNotary(pSigDoc, pNotInfo); RETURN_IF_NOT(pSigInfo != NULL, ERR_NOTARY_NO_SIGNATURE); return verifyNotaryInfoCERT2(pSigDoc, pSigInfo, pNotInfo, caCerts, 0, notCert, pSigCA); } //==================================================================== // Finds issuer certificate of given certificate // returns NULL if not found or any error occures // The stores "My","CA" and "Root" will be scanned. //==================================================================== EXP_OPTION X509 * findIssuerCertificatefromMsStore(X509 *x509){ return findIssuerCertificatefromStore(x509); } //Functions from EstIDLib.c //============================================================ // Calculates and stores a signature for this SignatureInfo object // Uses EstEID card as CSP to sign the info // pSigInfo - signature info object //============================================================ EXP_OPTION int calculateSigInfoSignatureWithCSPEstID(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, int iByKeyContainer, const char* szPin) { int err = ERR_OK, l1; PCCERT_CONTEXT pCert; char buf1[300]; unsigned long sigLen; int digLen, len=0; char sigDig[300],signature[2084], *p1; char *psKeyName = NULL; char *psCSPName = NULL; //long tmpSerial; //HCRYPTPROV hProvider; DWORD dwRes; X509 *pX509; DigiDocMemBuf *pMBuf1; ddocDebug(3, "calculateSigInfoSignatureWithCSPEstID", "Sign id: %s", pSigInfo->szId); pCert = DigiCrypt_FindContext((BOOL) iByKeyContainer, &dwRes); if(pCert == NULL) { if (dwRes == dDigiCrypt_Error_NotFoundCSP) err = ERR_CSP_NO_CARD_DATA; if(dwRes == dDigiCrypt_Error_UserCancel) err = ERR_CSP_USER_CANCEL; if (dwRes == dDigiCrypt_Error_NoDefaultKey) err = ERR_CSP_NODEFKEY_CONTAINER; if (dwRes == dDIgiCrypt_Error_NotFoundCert) err = ERR_CSP_CERT_FOUND; SET_LAST_ERROR_RETURN_CODE(err); } psKeyName = DigiCrypt_FindContext_GetKeyName(); psCSPName = DigiCrypt_FindContext_GetCSPName(); //AA100204 ddocDecodeX509Data(&pX509,pCert->pbCertEncoded,pCert->cbCertEncoded); err = setSignatureCert(pSigInfo, pX509); RETURN_IF_NOT(err == ERR_OK, err); //AA-Viimase minuti jama createTimestamp(pSigDoc, sigDig, sizeof(sigDig)); setString(&(pSigInfo->szTimeStamp), sigDig, -1); // Signed properties digest // now calculate signed properties digest err = calculateSignedPropertiesDigest(pSigDoc, pSigInfo); // TODO: replace later pMBuf1 = ddocDigestValue_GetDigestValue(pSigInfo->pSigPropDigest); ddocSigInfo_SetSigPropRealDigest(pSigInfo, (const char*)pMBuf1->pMem, pMBuf1->nLen); // signature type & val ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, SIGN_RSA_NAME, 0, 0); // calc signed-info digest l1 = sizeof(buf1); err = calculateSignedInfoDigest(pSigDoc, pSigInfo, (byte*)buf1, &l1); err = ddocSigInfo_SetSigInfoRealDigest(pSigInfo, buf1, l1); sigLen = sizeof(signature); memset(signature, 0, sizeof(signature)); p1 = createXMLSignedInfo(pSigDoc, pSigInfo); len = strlen(p1); // sign the hash with CSP digLen = sizeof(sigDig); err = GetSignedHashWithKeyAndCSP(psKeyName,psCSPName, p1, len, NULL, NULL, sigDig, &digLen,&signature[0],&sigLen,szPin); if(p1) free(p1); RETURN_IF_NOT(err == ERR_OK, err); // set signature value ddocSigInfo_SetSignatureValue(pSigInfo, signature, (int)sigLen); ddocDebug(3, "calculateSigInfoSignatureWithCSPEstID", "End signing Sign id: %s, rc: %d", pSigInfo->szId, err); return ERR_OK; } X509* findCertificate(const CertSearch * cS){ //debugPrint("findCertificate"); X509* poCert = NULL; if(cS==NULL){ return NULL; }else if(cS->searchType==CERT_SEARCH_BY_X509){ ReadCertificate(&poCert,cS->x509FileName); return(poCert); }else if(cS->searchType==CERT_SEARCH_BY_PKCS12){ X509 * x509=NULL; EVP_PKEY * pKey=NULL; int err=0; err=ReadCertificateByPKCS12(&x509,cS->pkcs12FileName,cS->pswd,&pKey); EVP_PKEY_free(pKey); if(err==ERR_OK){ return x509; }else{ SET_LAST_ERROR(err); return NULL; } }else if(cS->searchType==CERT_SEARCH_BY_STORE){ #ifdef WIN32_CSP X509 * x509=NULL; int err=0; RETURN_OBJ_IF_NULL(cS->certSearchStore, NULL); err=GetCertificateFromStore(cS->certSearchStore,&x509); //debugPrint("return from findCertificate (MS Store)"); if(err==ERR_OK){ return x509; }else{ SET_LAST_ERROR(err); return NULL; } #else return NULL; #endif }else{ return NULL; } } EXP_OPTION int findAllCertificates(const CertSearchStore *sS, X509 ***certsArray, int *numberOfCerts){ #ifdef WIN32_CSP int rc=0,i; X509 **array; CertItem *certItem, *certItem2; rc=GetAllCertificatesFromStore(sS,&certItem,numberOfCerts); if(rc==ERR_OK){ array=malloc(sizeof(X509*)*(*numberOfCerts)); RETURN_IF_BAD_ALLOC(array); for(i=0;i< *numberOfCerts ;i++){ array[i]=certItem->pCert; certItem2=certItem; certItem=certItem->nextItem; free(certItem2); } *certsArray=array; } if (rc != ERR_OK) SET_LAST_ERROR(rc); return rc; #else SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_CERT_SEARCH); #endif // WIN32_CSP } /***********************************************************************/ //========================================================================= // Returns pointer to current CSP. If current CSP was not initialized (i.e // NULL ) and input parameter is TRUE then active CSP is asked from // function getActiveProvider() and if CSP is "EST ID CSP" then // signature flag in CSP structure will turned to true //========================================================================= EXP_OPTION CSProvider * getCurrentCSProvider(BOOL tryToFindIfMissing){ if(tryToFindIfMissing==FALSE){ return cCSProvider; } // so tryToFindIfMissing was true, we need to find out if not found yet if(cCSProvider==NULL ){ //cCSProvider=getActiveProvider(); if(cCSProvider!=NULL){ if(strcmp(cCSProvider->CSPName,EST_EID_CSP)==0) cCSProvider->at_sig=TRUE; else cCSProvider->at_sig=FALSE; } } return cCSProvider; } EXP_OPTION void setCurrentCSProvider(CSProvider * newProvider){ cCSProvider=newProvider; } //===================================================== EXP_OPTION CertSearchStore* CertSearchStore_new() { CertSearchStore* certSearch; certSearch=(CertSearchStore*)malloc(sizeof(CertSearchStore)); memset(certSearch, 0, sizeof(CertSearchStore)); return certSearch; } EXP_OPTION void CertSearchStore_free(CertSearchStore* certSearchStore){ int i=0; RETURN_VOID_IF_NULL(certSearchStore); if (certSearchStore->subDNCriterias) { for(; i < certSearchStore->numberOfSubDNCriterias ; i++ ){ if(certSearchStore->subDNCriterias[i] != NULL){ free(certSearchStore->subDNCriterias[i]); } } free(certSearchStore->subDNCriterias); } certSearchStore->numberOfSubDNCriterias=0; if (certSearchStore->issDNCriterias) { for(; i < certSearchStore->numberOfIssDNCriterias ; i++ ){ if(certSearchStore->issDNCriterias[i] != NULL){ free(certSearchStore->issDNCriterias[i]); } } free(certSearchStore->issDNCriterias); } certSearchStore->numberOfIssDNCriterias=0; if(certSearchStore->storeName != NULL){ free(certSearchStore->storeName); } if(certSearchStore->publicKeyInfo){ free(certSearchStore->publicKeyInfo); } free(certSearchStore); certSearchStore=NULL; } EXP_OPTION CertSearch* CertSearch_new(){ CertSearch* certSearch; certSearch=(CertSearch*)malloc(sizeof(CertSearch)); memset(certSearch, 0, sizeof(CertSearch)); return certSearch; } EXP_OPTION void CertSearch_free(CertSearch* certSearch){ if(certSearch->certSearchStore != NULL){ CertSearchStore_free(certSearch->certSearchStore); } if(certSearch->pkcs12FileName != NULL){ free(certSearch->pkcs12FileName); } if(certSearch->pswd != NULL){ free(certSearch->pswd); } if(certSearch->x509FileName != NULL){ free(certSearch->x509FileName); } if(certSearch->keyFileName != NULL){ free(certSearch->keyFileName); } free(certSearch); certSearch=NULL; } EXP_OPTION void CertSearch_setX509FileName(CertSearch* certSearch, const char* str) { if(certSearch && str) { setString((char**)&certSearch->x509FileName, str, -1); } } EXP_OPTION void CertSearch_setKeyFileName(CertSearch* certSearch, const char* str) { if(certSearch && str) { setString((char**)&certSearch->keyFileName, str, -1); } } EXP_OPTION void CertSearch_setPkcs12FileName(CertSearch* certSearch, const char* str) { if(certSearch && str) { setString((char**)&certSearch->pkcs12FileName, str, -1); } } EXP_OPTION void CertSearch_setPasswd(CertSearch* certSearch, const char* str) { if(certSearch && str) { setString((char**)&certSearch->pswd, str, -1); } } // Frees cert handles and items in this list. // WARNING! when caller does not own the first cert in chain, // then pass pListStart->nextItem instead of pListStart itself. EXP_OPTION void CertList_free(CertItem* pListStart) { if (pListStart) { CertItem* pItem = pListStart; CertItem* pTmp; while (pItem) { pTmp = pItem->nextItem; X509_free((X509*)pItem->pCert); free(pItem); pItem = pTmp; } } } //===================================================================== // reads certificate from system store // IN CertSearchStore *sS - search criterias // OUT x509 certificate //===================================================================== int GetAllCertificatesFromStore(const CertSearchStore *sS, CertItem ** certList, int *numberOfCerts) { int retCode=ERR_OK; /* int retCode1=ERR_UNSUPPORTED_CERT_SEARCH; // Unknown search type int retCode2=ERR_CSP_OPEN_STORE; // Can not open system store int retCode3=ERR_CSP_CERT_FOUND; // Certificate not found from store, probably cetificate not registered int retCode4=ERR_INCORRECT_CERT_SEARCH; // search type Sub DN but mismatch of parameters int retCode5=ERR_PKCS_CERT_DECODE; */ int i=0,certCounter=0; int initSize=10; X509 *x509; CertItem *certFirst,*certCurrent,*certIt; BOOL certFound=FALSE; BOOL useSerial=FALSE; BOOL useSubDN=FALSE; BOOL useIssDN=FALSE; HCERTSTORE hCertStore = NULL; PCCERT_CONTEXT pCert=NULL; char defaultName[]="My"; char* storeName; char buf[4000]; char buf1[4000]; long tmpSerial; int err; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; RETURN_IF_NOT(numberOfCerts !=NULL, ERR_NULL_SER_NUM_POINTER); if((sS->searchType&(CERT_STORE_SEARCH_BY_SERIAL|CERT_STORE_SEARCH_BY_SUBJECT_DN|CERT_STORE_SEARCH_BY_ISSUER_DN)) == 0) SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_CERT_SEARCH); if((sS->searchType&CERT_STORE_SEARCH_BY_SERIAL) != 0){ useSerial=TRUE; } if((sS->searchType&CERT_STORE_SEARCH_BY_SUBJECT_DN) != 0){ useSubDN=TRUE; if(sS->numberOfSubDNCriterias<1) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); if (sS->subDNCriterias == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); for(i=0;inumberOfSubDNCriterias;i++){ if(sS->subDNCriterias[i]==NULL) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); } } if((sS->searchType&CERT_STORE_SEARCH_BY_ISSUER_DN) != 0){ useIssDN=TRUE; if(sS->numberOfIssDNCriterias<1) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); if (sS->issDNCriterias == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); for(i=0;inumberOfIssDNCriterias;i++){ if(sS->issDNCriterias[i]==NULL) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); } } if(sS->storeName!=NULL){ storeName=sS->storeName; }else{ storeName=defaultName; } certFirst = malloc(sizeof(CertItem)); RETURN_IF_BAD_ALLOC(certFirst); // memset(certFirst,0,sizeof(certFirst)); <-- Andrus: fills with zeros only first 32 bits memset(certFirst,0,sizeof(CertItem)); *certList=certFirst; certCurrent=certFirst; /////******************** start task *********************************** while(TRUE){ hCertStore=CertOpenSystemStore(0,storeName); if(!hCertStore){ retCode=ERR_CSP_OPEN_STORE; SET_LAST_ERROR(retCode); break; } while(TRUE){ pCert = CertEnumCertificatesInStore( hCertStore,pCert); if(!pCert) break; //AA100204 ddocDecodeX509Data(&x509,pCert->pbCertEncoded,pCert->cbCertEncoded); RETURN_IF_NOT(x509 != NULL, ERR_PKCS_CERT_DECODE); // if serial is a criteria check it if(useSerial){ //AA-viimase minuti jama //ReadCertSerialNumber(&tmpSerial,x509); ReadCertSerialNumber(buf,sizeof(buf),x509); tmpSerial = atol(buf); if(tmpSerial == sS->certSerial){ certFound=TRUE; }else{ certFound=FALSE; X509_free(x509); continue; } }//if(useSerial){ // if issuer name is a criteria check it if(useIssDN){ int len=0; X509_NAME * x509name; x509name = X509_get_issuer_name(x509); len=sizeof(buf); memset(buf,0,len); memset(buf1,0,sizeof(buf1)); //AM 26.09.08 //X509_NAME_oneline(x509name,buf,len); err = ddocCertGetIssuerDN(x509, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); len=strlen((char*)mbuf1.pMem); prepareString((char*)mbuf1.pMem,buf1); for(i=0;inumberOfIssDNCriterias;i++){ memset(buf,0,sizeof(buf)); prepareString(sS->issDNCriterias[i],buf); if(strstr(buf1,buf)){ certFound=TRUE; }else{ certFound=FALSE; //X509_free(x509); <-- Andrus: free operation performed in the end of useIssDN block break; } } if(!certFound){ X509_free(x509); continue; } }//if(useIssDN){ // if subject name is a criteria check it if(useSubDN){ int len=0; X509_NAME * x509name; x509name = X509_get_subject_name(x509); len=sizeof(buf); memset(buf,0,len); memset(buf1,0,sizeof(buf1)); //AM 26.09.08 //X509_NAME_oneline(x509name,buf,len); err = ddocCertGetSubjectDN(x509, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); len=strlen((char*)mbuf1.pMem); prepareString((char*)mbuf1.pMem,buf1); for(i=0;inumberOfSubDNCriterias;i++){ memset(buf,0,sizeof(buf)); prepareString(sS->subDNCriterias[i],buf); if(strstr(buf1,buf)){ certFound=TRUE; }else{ certFound=FALSE; break; } } // did we find ? if(!certFound){ X509_free(x509); continue; } }//if(useSubDN){ ddocMemBuf_free(&mbuf1); // did we find ? if(certFound){ certCounter++; if(certCounter==1){ certFirst->pCert=x509; continue; } certIt = malloc(sizeof(CertItem)); RETURN_IF_BAD_ALLOC(certIt); // memset(certIt,0,sizeof(certIt)); <-- Andrus: fills with zeros only first 32 bits memset(certIt,0,sizeof(CertItem)); certIt->pCert=x509; certCurrent->nextItem=certIt; certCurrent=certIt; }else{ X509_free(x509); continue; } }//while(pCertt=CertEnumCertificatesInStore(hCertStore,pCert)) *numberOfCerts=certCounter; if( certCounter<1 ){ retCode = ERR_CSP_CERT_FOUND; SET_LAST_ERROR(retCode); break; } break; }//while(TRUE){ /////******************** close and free objects *********************************** if(pCert) {CertFreeCertificateContext(pCert); } if(hCertStore) {CertCloseStore(hCertStore,CERT_CLOSE_STORE_FORCE_FLAG);hCertStore=0;} return retCode; /////******************************************************************************* } //========================================================== // removes all spaces and tabs and makes all characters uppercase //========================================================== void prepareString(const char * strIN,char * strOUT){ int len=0; int i=0; int tempLen=0; len=strlen(strIN); if(len==0){ return; } for (;i0x60 && strIN[i]<0x7B ){ strOUT[tempLen++] = (strIN[i]-0x20); }else { strOUT[tempLen++] = strIN[i]; } } } //===================================================================== // reads certificate from system store // IN CertSearchStore *sS - search criterias // OUT x509 certificate //===================================================================== int GetCertificateFromStore(const CertSearchStore *sS, X509 **cert){ int retCode=ERR_OK; int retCode1=ERR_UNSUPPORTED_CERT_SEARCH; // Unknown search type int retCode2=ERR_CSP_OPEN_STORE; // Can not open system store int retCode3=ERR_CSP_CERT_FOUND; // Certificate not found from store, probably cetificate not registered int retCode4=ERR_INCORRECT_CERT_SEARCH; // search type Sub DN but mismatch of parameters int retCode5=ERR_PKCS_CERT_DECODE; int i=0; X509 *x509; BOOL certFound=FALSE; BOOL useKeyInfo=FALSE; BOOL useSerial=FALSE; BOOL useSubDN=FALSE; BOOL useIssDN=FALSE; HCERTSTORE hCertStore = NULL; CERT_PUBLIC_KEY_INFO* pKeyInfo; PCCERT_CONTEXT pCert=NULL; char defaultName[]="My"; char* storeName; char buf[3000]; char buf1[3000]; long tmpSerial; int err=0; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; //--------------------------------- // TODO: it's just a test - remove it //--------------------------------- /* char* pSelArr[] = {"Good reader", "Better reader", "The best reader", NULL}; int iRes = runDigiDocDialogUnit(pSelArr, "Please select smartcard reader:"); if (iRes != -1) { // handle picked element char resultAsText[128]; //sprintf(resultAsText, "Selected item with index=%d", iRes); MessageBox(NULL, resultAsText, "DigiDoc", MB_OK|MB_ICONEXCLAMATION); } else { // if possible, handle Cancel operation } */ //--------------------------------- // End of TODO //--------------------------------- if((sS->searchType&(CERT_STORE_SEARCH_BY_SERIAL|CERT_STORE_SEARCH_BY_SUBJECT_DN|CERT_STORE_SEARCH_BY_ISSUER_DN|CERT_STORE_SEARCH_BY_KEY_INFO)) == 0) SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_CERT_SEARCH); if((sS->searchType&CERT_STORE_SEARCH_BY_KEY_INFO) != 0){ useKeyInfo=TRUE; pKeyInfo=sS->publicKeyInfo; if(pKeyInfo==NULL){ SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); } } if((sS->searchType&CERT_STORE_SEARCH_BY_SERIAL) != 0){ useSerial=TRUE; } if((sS->searchType&CERT_STORE_SEARCH_BY_SUBJECT_DN) != 0){ useSubDN=TRUE; if(sS->numberOfSubDNCriterias<1) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); if (sS->subDNCriterias == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); for(i=0;inumberOfSubDNCriterias;i++){ if(sS->subDNCriterias[i]==NULL) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); } } if((sS->searchType&CERT_STORE_SEARCH_BY_ISSUER_DN) != 0){ useIssDN=TRUE; if(sS->numberOfIssDNCriterias<1) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); if (sS->issDNCriterias == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); for(i=0;inumberOfIssDNCriterias;i++){ if(sS->issDNCriterias[i]==NULL) SET_LAST_ERROR_RETURN_CODE(ERR_INCORRECT_CERT_SEARCH); } } if(sS->storeName!=NULL){ storeName=sS->storeName; }else{ storeName=&defaultName[0]; } /////******************** start task *********************************** while(TRUE){ hCertStore=CertOpenSystemStore(0,storeName); if(!hCertStore){ retCode = ERR_CSP_OPEN_STORE; SET_LAST_ERROR(retCode); break; } if(useKeyInfo){ pCert=CertFindCertificateInStore(hCertStore,X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,0,CERT_FIND_PUBLIC_KEY,pKeyInfo,NULL ); if(pCert){ //AA100204 ddocDecodeX509Data(&x509,pCert->pbCertEncoded,pCert->cbCertEncoded); certFound=TRUE; //memcpy(cert,x509,sizeof(x509)); //X509_free(x509); *cert=x509; break; } }//if(useSerial){ while( pCert= CertEnumCertificatesInStore( hCertStore,pCert)){ //AA100204 ddocDecodeX509Data(&x509,pCert->pbCertEncoded,pCert->cbCertEncoded); RETURN_IF_NOT(x509 != NULL, ERR_PKCS_CERT_DECODE); if(useSerial){ //AA-Viimase minuti jama //ReadCertSerialNumber(&tmpSerial,x509); ReadCertSerialNumber(buf,sizeof(buf),x509); tmpSerial = atol(buf); if(tmpSerial == sS->certSerial){ certFound=TRUE; }else{ certFound=FALSE; X509_free(x509); continue; } }//if(useSerial){ if(useIssDN){ int len=0; X509_NAME * x509name; x509name = X509_get_issuer_name(x509); len=sizeof(buf); memset(buf,0,len); memset(buf1,0,sizeof(buf1)); //AM 26.09.08 //X509_NAME_oneline(x509name,buf,len); err = ddocCertGetIssuerDN(x509, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); len=strlen((char*)mbuf1.pMem); prepareString((char*)mbuf1.pMem,buf1); for(i=0;inumberOfIssDNCriterias;i++){ memset(buf,0,sizeof(buf)); prepareString(sS->issDNCriterias[i],buf); if(strstr(buf1,buf)){ certFound=TRUE; }else{ certFound=FALSE; X509_free(x509); break; } } if(!certFound){ X509_free(x509); continue; } }//if(useIssDN){ if(useSubDN){ int len=0; X509_NAME * x509name; x509name = X509_get_subject_name(x509); len=sizeof(buf); memset(buf,0,len); memset(buf1,0,sizeof(buf1)); //AM 26.09.08 //X509_NAME_oneline(x509name,buf,len); err = ddocCertGetSubjectDN(x509, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); len=strlen((char*)mbuf1.pMem); prepareString((char*)mbuf1.pMem,buf1); for(i=0;inumberOfSubDNCriterias;i++){ memset(buf,0,sizeof(buf)); prepareString(sS->subDNCriterias[i],buf); if(strstr(buf1,buf)){ certFound=TRUE; }else{ certFound=FALSE; break; } } // did we find ? if(!certFound){ X509_free(x509); continue; } }//if(useSubDN){ ddocMemBuf_free(&mbuf1); // did we find ? if(certFound){ break; }else{ X509_free(x509); continue; } }//while(pCertt=CertEnumCertificatesInStore(hCertStore,pCert)) if( certFound ){ //memcpy(cert,x509,sizeof(x509)); //X509_free(x509); *cert=x509; }else{ retCode=ERR_CSP_CERT_FOUND; SET_LAST_ERROR(retCode); break; } break; }//while(TRUE){ /////******************** close and free objects *********************************** if(pCert) {CertFreeCertificateContext(pCert); } if(hCertStore) {CertCloseStore(hCertStore,CERT_CLOSE_STORE_FORCE_FLAG);hCertStore=0;} return retCode; /////******************************************************************************* } //======================================================= //Asks and returns key name or NULL if can not be found. //Key name must be freed. Name will be like "AUT_VIISAKAS,VILLU,19901012020" //IN cProvider - crypto provider name, "EstEID Card CSP" in // EstID's case. //======================================================= LPBYTE getDefaultKeyName(CSProvider * cCSP){ BOOL fRes; HCRYPTPROV hProv = 0; LPBYTE pbContName = NULL;//string, key name to be stored DWORD dwContName; if(cCSP==NULL){ cCSP=getCurrentCSProvider(TRUE); } if(cCSP==NULL){ return NULL; } if(cCSP->rsa_full){ fRes = CryptAcquireContext(&hProv,NULL,cCSP->CSPName, PROV_RSA_FULL, 0); }else{ fRes = CryptAcquireContext(&hProv,NULL,cCSP->CSPName, PROV_RSA_SIG, 0); } if (RCRYPT_FAILED(fRes)){ return NULL; } // asks keypair name, in auth case it is AUT_ // first size and the the keyname itself fRes = CryptGetProvParam(hProv,PP_CONTAINER,NULL,&dwContName,0); if (RCRYPT_FAILED(fRes)){ return NULL; } //pbContName =(LPBYTE) LocalAlloc(0,dwContName); pbContName =(LPBYTE) malloc(dwContName); if(pbContName != NULL ){ fRes = CryptGetProvParam(hProv,PP_CONTAINER,pbContName,&dwContName,0); } //in pbContName-s there is now ASCII string fRes = CryptReleaseContext(hProv,0); if (RCRYPT_FAILED(fRes)){ return NULL; } hProv =0; return pbContName; } //======================================================================== // Returns issuer certificate context //======================================================================== const CERT_CONTEXT * findCertFromStore(const CERT_CONTEXT *cert, const char *storeName) { HCERTSTORE hCertStore = NULL; const CERT_CONTEXT *issuer = NULL; DWORD flag=CERT_STORE_SIGNATURE_FLAG; hCertStore=CertOpenSystemStore(0,storeName); if(!hCertStore){ return NULL; } issuer = CertGetIssuerCertificateFromStore(hCertStore,cert,NULL,&flag); CertCloseStore(hCertStore,0); return issuer; } //========================================================================= X509 * findIssuerCertificatefromStore(X509 *x509) { const CERT_CONTEXT *cert = NULL; const CERT_CONTEXT *issuer = NULL; char * storeNames[] = {"CA","Root","My"}; unsigned char certBlob[5000]; int i, certBlobLen = sizeof(certBlob); X509 *x509issuer = NULL; RETURN_OBJ_IF_NULL(x509, NULL); //encode( memset(certBlob,0,sizeof(certBlob)); encodeCert(x509,(char *)certBlob,&certBlobLen); cert = CertCreateCertificateContext(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,certBlob,certBlobLen); if(cert == NULL){ return NULL; } for( i=0;i<3;i++){ issuer=findCertFromStore(cert,storeNames[i]); if(issuer){ break; } } if(issuer){ //AA100204 ddocDecodeX509Data(&x509issuer,issuer->pbCertEncoded,issuer->cbCertEncoded); CertFreeCertificateContext(issuer); } CertFreeCertificateContext(cert); return x509issuer; } //===================================================================== // hashes and signes data with EstId card, returns also public_key_blob // which can be used in order to verify signature // IN dataToBeSigned - source data buffer // IN dataLen - how many bytes will be read from source buffer // OUT pbKeyBlob - public key buffer( corresponding private key was used to sign. // OUT pbKeyBlobLen - public key length in buffer // OUT hash - output data buffer for hash // OUT hashLen - data length in output buffer // OUT hashedSignature - output data buffer for hashed and signed data // OUT sigLen - data length in output buffer // IN szPin - PIN2 [optional] //===================================================================== int GetSignedHashWithKeyAndCSP( char *psKeyName, char *psCSPName, const char * dataToBeSigned,unsigned long dataLen, unsigned char *pbKeyBlob, unsigned long *pbKeyBlobLen, unsigned char *hash, unsigned long *hashLen, unsigned char * hashedSignature,unsigned long * sigLen, const char* szPin) { int retCode=ERR_OK, l1; HCRYPTPROV hProv = 0; HCRYPTHASH sha1 = 0; HCRYPTKEY hKey = 0; PCCERT_CONTEXT pCert=NULL; BOOL fRes; DWORD dwRes; char *p1 = 0; ddocDebug(3, "GetSignedHashWithKeyAndCSP", "key: %s csp: %s, pin-len: %d", psKeyName, psCSPName, (szPin ? strlen(szPin) : 0)); // debug ddocDebug(3, "GetSignedHashWithKeyAndCSP", "data to sign: \'%s\' len: %d tlen: %d", dataToBeSigned, dataLen, strlen(dataToBeSigned)); //////******************** start task ************************************* while(TRUE){ // //sprintf(sTemp,"CSP=%s \nCON=%s\n%d",psCSPName,psKeyName,DigiCrypt_FindContext_GetCSPType(psCSPName)); //MessageBox(NULL,sTemp,"TEST",MB_OK); // fRes=CryptAcquireContext(&hProv,psKeyName,psCSPName,DigiCrypt_FindContext_GetCSPType(psCSPName),0);//CRYPT_VERIFYCONTEXT); ddocDebug(1, "GetSignedHashWithKeyAndCSP", "CryptAcquireContext: \'%s\' rc: %d", psKeyName, fRes); if(fRes==FALSE){ dwRes = GetLastError(); ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in CryptAcquireContext: %ld hex: %x", dwRes, dwRes); retCode=ERR_CSP_NO_CARD_DATA; break; } fRes=CryptCreateHash(hProv,CALG_SHA1,0,0,&sha1); if(fRes==FALSE){ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "CryptCreateHash RC (bool): %d", (int)fRes); retCode=ERR_CSP_NO_HASH_START; SET_LAST_ERROR(retCode); break; } // start hash fRes=CryptHashData(sha1,dataToBeSigned,dataLen,0); if(fRes==FALSE){ retCode=ERR_CSP_NO_HASH; SET_LAST_ERROR(retCode); break; } if(hash!=NULL){ ddocDebug(3, "GetSignedHashWithKeyAndCSP", "caling CryptGetHashParam hash: %s len: %ld", hash, *hashLen); fRes=CryptGetHashParam(sha1,HP_HASHVAL, hash,hashLen ,0); if(fRes==FALSE){ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "CryptGetHashParam RC (bool): %d", (int)fRes); retCode=ERR_CSP_NO_HASH_RESULT; SET_LAST_ERROR(retCode); break; } // debug l1 = *hashLen * 2 + 10; p1 = (char*)malloc(l1); if(p1) { memset(p1, 0, l1); encode((const byte*)hash, *hashLen, (byte*)p1, &l1); ddocDebug(3, "GetSignedHashWithKeyAndCSP", "hash: %s len: %d", p1, l1); free(p1); p1 = 0; } } if(hashedSignature != NULL) { //use by standard way is not allways possible -- AT_SIGNATURE -- main thing is that cert is ok nor the keyspec //instead of that we should use CryptAcquireCertificatePrivateKey function. But then we must change basic context of this function. //workaround -- we try with both keyspecs // set PIN2 for signing if possible if(szPin && strlen(szPin)) { ddocDebug(3, "GetSignedHashWithKeyAndCSP", "Setting PIN len: %d", strlen(szPin)); fRes = CryptSetProvParam(hProv, PP_SIGNATURE_PIN, (const BYTE*)szPin, 0 ); ddocDebug(3, "GetSignedHashWithKeyAndCSP", "PIN setting: %d", fRes); } fRes=CryptSignHash(sha1,AT_SIGNATURE ,NULL,0, hashedSignature,sigLen); if(fRes==FALSE) { dwRes = GetLastError(); //try again with keyspec AT_KEYEXCHANGE if(dwRes==0x8009000d) // wrong keyspec { fRes=CryptSignHash(sha1,AT_KEYEXCHANGE ,NULL,0, NULL,sigLen); //*sigLen should be 128... this can be avoided whi fRes=CryptSignHash(sha1,AT_KEYEXCHANGE ,NULL,0, hashedSignature,sigLen); if(fRes==FALSE) { dwRes = GetLastError(); ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in CryptSignHash: %ld", dwRes); retCode=ERR_CSP_SIGN; SET_LAST_ERROR(retCode); break; } } else if(dwRes == 0x8010006e) { ddocDebug(2, "GetSignedHashWithKeyAndCSP", "user cancelled signing"); retCode=ERR_CSP_USER_CANCEL; SET_LAST_ERROR(ERR_CSP_USER_CANCEL); break; } else { ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in signing: %uld hex: %x", dwRes, dwRes); retCode=ERR_CSP_SIGN; SET_LAST_ERROR(retCode); break; } } } else ddocDebug(1, "GetSignedHashWithKeyAndCSP", "hashed signature is NULL"); // we must switsh end and begining // because windows uses little-endian but verification // assumes big-endian reverseArray(hashedSignature, *sigLen); if(pbKeyBlob!=NULL){ fRes=CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hKey); if(fRes==FALSE){ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in CryptGetUserKey"); retCode=ERR_CSP_OPEN_KEY; SET_LAST_ERROR(retCode); break; } fRes=CryptExportKey(hKey,0,PUBLICKEYBLOB,0,pbKeyBlob,pbKeyBlobLen); if(fRes==FALSE){ ddocDebug(1, "GetSignedHashWithKeyAndCSP", "error in CryptExportKey"); retCode=ERR_CSP_READ_KEY; SET_LAST_ERROR(retCode); break; } } break; }//while(TRUE) ///********************** free objects ************************************ if(hKey){ CryptDestroyKey(hKey);hKey=0; } if(sha1){ CryptDestroyHash(sha1);sha1= 0; } if(hProv){ CryptReleaseContext(hProv,0); } ddocDebug(3, "GetSignedHashWithKeyAndCSP", "end of signing RC: %d", retCode); return retCode; /////******************************************************************************* } //=============================================================== // This function is used to change order in a massive. Last byte // becomes first and so on. // IN/OUT array - massive to be changed // IN arrayLen - array's length //=============================================================== void reverseArray(unsigned char *array, unsigned long arrayLen) { int ri, rj; unsigned char t; for (ri = 0, rj = arrayLen - 1; ri < rj; ++ri, --rj) { t = array[ri]; array[ri] = array[rj]; array[rj] = t; } } #endif libdigidoc-3.10.5/libdigidoc/libdigidoc.pc.cmake0000664000372000037200000000046513560273131021066 0ustar travistravisprefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_FULL_BINDIR@ libdir=@CMAKE_INSTALL_FULL_LIBDIR@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ Name: libdigidoc Description: Libdigidoc library for handling digitally signed documents Version: @VERSION@ Libs: -L${libdir} -ldigidoc Cflags: -I${includedir} libdigidoc-3.10.5/libdigidoc/DigiDocHTTP.h0000664000372000037200000000023513560273131017540 0ustar travistravis#include int ddocGetHttpResponseCode(DigiDocMemBuf* pBuf); int ddocGetHttpPayload(DigiDocMemBuf* pInBuf, DigiDocMemBuf* pOutBuf); libdigidoc-3.10.5/libdigidoc/DigiDocConvert.c0000664000372000037200000011757413560273131020413 0ustar travistravis//================================================== // FILE: DigiDocEnc.c // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDoc character conversion routines // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 22.09.2004 Veiko Sinivee // Creation //================================================== #include #include #include #include #include #ifdef WIN32 #include #endif #include #include #include #include /* only for xmlNewInputFromFile() */ #include #include #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x10010000L static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new() { return (EVP_ENCODE_CTX*)OPENSSL_malloc(sizeof(EVP_ENCODE_CTX)); } static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) { OPENSSL_free(ctx); } #endif //==========< general fucntions >============ //-------------------------------------------------- // Helper function that converts ISO Latin1 to UTF8 // ascii - input data in ISO Latin1 // utf8out - output buffer for UTF8 text // outlen - output buffer length // returns output buffer //-------------------------------------------------- EXP_OPTION char* ascii2utf8(const char* ascii, char* utf8out, int* outlen) { int inlen = strlen(ascii); memset(utf8out, 0, *outlen); isolat1ToUTF8((unsigned char*)utf8out, outlen, (const unsigned char*)ascii, &inlen); return utf8out; } //-------------------------------------------------- // Helper function that converts UTF8 to ISO Latin1 // utf8in - input data in UTF8 // asciiout - output buffer for ISO Latin1 text // outlen - output buffer length // returns output buffer //-------------------------------------------------- EXP_OPTION char* utf82ascii(const char* utf8in, char* asciiout, int* outlen) { int inlen = strlen(utf8in); memset(asciiout, 0, *outlen); UTF8Toisolat1((unsigned char*)asciiout, outlen, (const unsigned char*)utf8in, &inlen); return asciiout; } int hex2char(char c) { static char unidigits[] = "0123456789ABCDEF"; unsigned int i, k = 0; for(i = 0; i < sizeof(unidigits); i++) { if(unidigits[i] == c) { k = i; break; } } return k; } struct u2w { long uni; unsigned char cp1252; // cp 1252 charset unsigned char cp1257; // baltic charset unsigned char utf8_1; // UTF8 1. byte unsigned char utf8_2; // UTF8 2. byte }; struct u2w uni2cp1252 [] = { { 8364, 128, 0, 0, 0 }, // euro sign { 8218, 130, 0, 0, 0 }, // SINGLE LOW-9 QUOTATION MARK { 402, 131, 0, 0, 0 }, // LATIN SMALL LETTER F WITH HOOK { 8222, 132, 0, 0, 0 }, // DOUBLE LOW-9 QUOTATION MARK { 8230, 133, 0, 0, 0 }, // HORIZONTAL ELLIPSIS { 8224, 134, 0, 0, 0 }, // DAGGER { 8225, 135, 0, 0, 0 }, // DOUBLE DAGGER { 710, 136, 0, 0, 0 }, // MODIFIER LETTER CIRCUMFLEX ACCENT { 8240, 137, 0, 0, 0 }, // PER MILLE SIGN { 352, 138, 208, 197, 160 }, // LATIN CAPITAL LETTER S WITH CARON { 8249, 139, 0, 0, 0 }, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK { 338, 140, 0, 0, 0 }, // LATIN CAPITAL LIGATURE OE { 381, 142, 222, 197, 189 }, // LATIN CAPITAL LETTER Z WITH CARON { 8216, 145, 0, 0, 0 }, // LEFT SINGLE QUOTATION MARK { 8217, 146, 0, 0, 0 }, // RIGHT SINGLE QUOTATION MARK { 8220, 147, 0, 0, 0 }, // LEFT DOUBLE QUOTATION MARK { 8221, 148, 0, 0, 0 }, // RIGHT DOUBLE QUOTATION MARK { 8226, 149, 0, 0, 0 }, // BULLET { 8211, 150, 0, 0, 0 }, // EN DASH { 8212, 151, 0, 0, 0 }, // EM DASH { 732, 152, 0, 0, 0 }, // SMALL TILDE { 8482, 153, 0, 0, 0 }, // TRADE MARK SIGN { 353, 154, 240, 197, 161 }, // LATIN SMALL LETTER S WITH CARON { 8250, 155, 0, 0, 0 }, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK { 339, 156, 0, 0, 0 }, // LATIN SMALL LIGATURE OE { 382, 158, 254, 197, 190 }, // LATIN SMALL LETTER Z WITH CARON { 376, 159, 0, 0, 0 }, // LATIN CAPITAL LETTER Y WITH DIAERESIS { 196, 196, 196, 195, 132}, // Capital A with umlaut { 214, 214, 214, 195, 150}, // Calital O with umlaut { 220, 220, 220, 195, 156}, // Capital U with umlaut { 213, 213, 213, 195, 149}, // Capital O with tilde { 228, 228, 228, 195, 164}, // small a with umlaut { 246, 246, 246, 195, 132}, // small o with umlaut { 245, 245, 245, 195, 181}, // small o with tilde { 252, 252, 252, 195, 188}, // small u with umlaut { 0, 0, 0, 0, 0 } // table end marker }; int isUmlaut(unsigned char c) { int i; for(i = 0; uni2cp1252[i].uni; i++) { if(uni2cp1252[i].cp1252 == c) { return 1; } } return 0; } int hasUmlauts(const char* str) { int i; for(i = 0; str[i]; i++) { if(isUmlaut((unsigned char)str[i])) return 1; } return 0; } int uni2char(long c) { int i, k = 0x20; // use space for all undisplayable unicode chars for(i = 0; uni2cp1252[i].uni; i++) { if(uni2cp1252[i].uni == c) { if(uni2cp1252[i].cp1257) k = uni2cp1252[i].cp1257; else k = uni2cp1252[i].cp1252; break; } } return k; } int uni2utf8(long c, int utfidx) { int i, k = 0x20; // use space for all undisplayable unicode chars for(i = 0; uni2cp1252[i].uni; i++) { if(uni2cp1252[i].uni == c) { if(uni2cp1252[i].utf8_1) { if(utfidx) k = uni2cp1252[i].utf8_2; else k = uni2cp1252[i].utf8_1; } else k = uni2cp1252[i].cp1252; break; } } return k; } EXP_OPTION void unicode2ascii(const char* uni, char* dest) { int len, i, j, k; long c; RETURN_VOID_IF_NULL(uni); RETURN_VOID_IF_NULL(dest); len = strlen(uni); memset(dest, 0, len+1); for(i = j = 0; i < len; i++) { if(uni[i] == '\\' && uni[i+1] == 'x') { if(uni[i+2] == '0' && uni[i+3] == '0') { if(uni[i+4] >= 'A' && uni[i+4] <= 'Z') { // simple char in form \x00A dest[j] = (unsigned char)uni[i+4]; i += 4; j++; continue; } else { i += 3; continue; } } if(uni[i+2] == '0' && uni[i+3] != '0') { // more complex char like \x0}1 c = 0; // first pos k = uni[i+2]; k = (((k >= '0') && (k <= '9')) ? k - '0' : k); k *= 4096; c += k; // second pos k = uni[i+3]; k = (((k >= '0') && (k <= '9')) ? k - '0' : k); k *= 256; c += k; // third pos k = uni[i+4]; k = (((k >= '0') && (k <= '9')) ? k - '0' : k); c += k; if(c >= 0 && c <= 9) c+= '0'; // get corresponding cp1252 char if(c > 256) { #ifdef WIN32 dest[j] = (unsigned char)uni2char(c); j++; #else dest[j] = uni2utf8(c, 0); j++; dest[j] = uni2utf8(c, 1); j++; #endif } else { dest[j] = (unsigned char)c; j++; } i += 4; continue; } if(uni[i+2] != '0' && uni[i+3] != '0') { // hex char code like \xC4 c = hex2char(uni[i+2]) * 16 + hex2char(uni[i+3]); if(c > 256) { #ifdef WIN32 dest[j] = (unsigned char)uni2char(c); j++; #else dest[j] = uni2utf8(c, 0); j++; dest[j] = uni2utf8(c, 1); j++; #endif } else { dest[j] = (unsigned char)c; j++; } i += 3; continue; } } else { dest[j] = uni[i]; j++; } } } typedef struct xmlsym_st { char sym; char* escape; } xmlsym; int g_xmlsyms = 6, g_xmlsyms2 = 7; xmlsym g_xmlsym[] = { { '\n', " " }, { '\r', " " }, { '<', "<" }, { '>', ">" }, { '"', """ }, { '&', "&" }, // VS: test if really necessary! { '&', "&" } }; int findEscape(const char* src, char* sym) { int i; *sym = 0; for(i = 0; i < g_xmlsyms; i++) { if(!strncmp(g_xmlsym[i].escape, src, strlen(g_xmlsym[i].escape))) { *sym = g_xmlsym[i].sym; return strlen(g_xmlsym[i].escape); } } return 0; } char findSym(const char* sym, int len) { int i; for(i = 0; i < g_xmlsyms2; i++) { if(!strncmp(g_xmlsym[i].escape, sym, len)) { return g_xmlsym[i].sym; } } return 0; } //-------------------------------------------------- // Converts xml symbols to corresponding escapes // src - string with xml special sybols // returns string with esacpes //-------------------------------------------------- char* escape2xmlsym(const char* src) { char* dest = 0, c; int i, j, l, k; l = strlen(src); dest = (char*)malloc(l+1); SET_LAST_ERROR_RETURN_IF_NOT(dest, ERR_BAD_ALLOC, NULL); memset(dest, 0, l+1); for(i = j = 0; i < l; i++, j++) { if(src[i] == '&') { k = findEscape(src + i, &c); if(k && c) { dest[j] = c; i += k - 1; } else dest[j] = src[i]; } else dest[j] = src[i]; } ddocDebug(4, "escape2xmlsym", "%s --> %s", src, dest); return dest; } //-------------------------------------------------- // Converts xml symbols to corresponding escapes // src - string with xml special sybols // returns string with esacpes //-------------------------------------------------- char* unescapeXmlsym(const char* src) { char* dest = 0, c; int i, j, l, k; l = strlen(src); dest = (char*)malloc(l+1); SET_LAST_ERROR_RETURN_IF_NOT(dest, ERR_BAD_ALLOC, NULL); memset(dest, 0, l+1); for(i = j = 0; i < l; i++, j++) { if(src[i] == '&') { if(src[i+1] == ';') k = 1; if(src[i+2] == ';') k = 2; if(src[i+3] == ';') k = 3; if(src[i+4] == ';') k = 4; c = findSym(src + i, k); if(k && c) { dest[j] = c; i += k; } else dest[j] = src[i]; } else dest[j] = src[i]; } ddocDebug(4, "unescapeXmlsym", "%s --> %s", src, dest); return dest; } char g_hexChars[] = "0123456789ABCDEF"; //-------------------------------------------------- // Decodes a single hex digit // h - hex digit // return binary value //-------------------------------------------------- byte h2b(char h) { int i; for(i = 0; i < 16; i++) { if(g_hexChars[i] == h || g_hexChars[i] == toupper(h)) return (byte)i; } // if not found then return an error ddocDebug(1, "h2b", "Invalid hex byte: %c", h); SET_LAST_ERROR(ERR_BAD_PARAM); return 0; // MSTERN: incorrect, VS - yes return -1 if not found. This is an error code } //-------------------------------------------------- // Converts a hex number (string) to binary value // hex - hex number // bin - buffer for binary value // len - buffer length //-------------------------------------------------- EXP_OPTION void hex2bin(const char* hex, byte* bin, int* len) { int i, l; byte b; RETURN_VOID_IF_NULL(hex); RETURN_VOID_IF_NULL(bin); RETURN_VOID_IF_NULL(len); memset(bin, 0, *len); l = strlen(hex); for(i = 0; i < l; i += 2) { b = (byte) ((h2b(hex[i]) << 4) | h2b(hex[i+1])); bin[i/2] = b; } *len = i / 2; } //-------------------------------------------------- // Converts a single byte to two hex characters // b - binary value // dest - destination buffer //-------------------------------------------------- void b2h(byte b, char* dest) { dest[0] = g_hexChars[(b & 0xF0) >> 4]; dest[1] = g_hexChars[b & 0x0F]; } //-------------------------------------------------- // Converts a binary value to hex string // bin - binary value // blen - binary value length // hex - buffer for hex string // len - buffer length //-------------------------------------------------- EXP_OPTION void bin2hex(const byte* bin, int blen, char* hex, int* len) { int i; byte b; RETURN_VOID_IF_NULL(hex); RETURN_VOID_IF_NULL(bin); RETURN_VOID_IF_NULL(len); memset(hex, 0, *len); for(i = 0; i < blen; i++) { b = bin[i]; hex[i*2] = g_hexChars[(b & 0xF0) >> 4]; hex[i*2+1] = g_hexChars[b & 0x0F]; } *len = i / 2; } //============================================================ // Encodes input data in hex format. // pMBufSrc - input data // pMBufDest - destination buffer //============================================================ EXP_OPTION int ddocBin2Hex(const DigiDocMemBuf* pMBufSrc, DigiDocMemBuf* pMBufDest) { int err = ERR_OK, n; RETURN_IF_NULL(pMBufSrc); RETURN_IF_NULL(pMBufDest); pMBufDest->pMem = 0; pMBufDest->nLen = 0; // alloc mem for result if(pMBufSrc->pMem && pMBufSrc->nLen) { err = ddocMemSetLength(pMBufDest, pMBufSrc->nLen * 2 + 10); n = pMBufSrc->nLen * 2 + 10; if(err) return err; bin2hex((const byte*)pMBufSrc->pMem, pMBufSrc->nLen, (char*)pMBufDest->pMem, &n); pMBufDest->nLen = n; } return err; } //-------------------------------------------------- // Converts correct filename to incorrect encoding // used in formats 1.0, 1.1 and 1.2 // src - input data // dest - buffer for converted data // len - length of destination buffer //-------------------------------------------------- EXP_OPTION void convFNameToWin(const char* src, char* dest, int len) { int i, j; for(i = j = 0; src[i] && (j < len - 1); i++, j++) { if(((unsigned char)src[i]) == 197 && ((unsigned char)src[i+1]) == 161) { dest[j] = (unsigned char)195; dest[j+1] = (unsigned char)176; j++, i++; continue; } else if(((unsigned char)src[i]) == 197 && ((unsigned char)src[i+1]) == 160) { dest[j] = (unsigned char)195; dest[j+1] = (unsigned char)144; j++, i++; continue; } else if(((unsigned char)src[i]) == 197 && ((unsigned char)src[i+1]) == 190) { dest[j] = (unsigned char)195; dest[j+1] = (unsigned char)190; j++, i++; continue; } else if(((unsigned char)src[i]) == 197 && ((unsigned char)src[i+1]) == 189) { dest[j] = (unsigned char)195; dest[j+1] = (unsigned char)158; j++, i++; continue; } else { dest[j] = src[i]; } } dest[j] = 0; } //-------------------------------------------------- // Converts bad UTF-8 filename used in formats 1.0, // 1.1 and 1.2 to correct encoding // src - input data // dest - buffer for converted data // len - length of destination buffer //-------------------------------------------------- EXP_OPTION void convWinToFName(const char* src, char* dest, int len) { int i, j; for(i = j = 0; src[i] && (j < len - 1); i++, j++) { if(((unsigned char)src[i]) == 195 && ((unsigned char)src[i+1]) == 176) { dest[j] = (unsigned char)197; dest[j+1] = (unsigned char)161; j++, i++; continue; } else if(((unsigned char)src[i]) == 195 && ((unsigned char)src[i+1]) == 144) { dest[j] = (unsigned char)197; dest[j+1] = (unsigned char)160; j++, i++; continue; } else if(((unsigned char)src[i]) == 195 && ((unsigned char)src[i+1]) == 190) { dest[j] = (unsigned char)197; dest[j+1] = (unsigned char)190; j++, i++; continue; } else if(((unsigned char)src[i]) == 195 && ((unsigned char)src[i+1]) == 158) { dest[j] = (unsigned char)197; dest[j+1] = (unsigned char)189; j++, i++; continue; } else { dest[j] = src[i]; } } dest[j] = 0; } //==========< only win32 fucntions >============ #ifdef WIN32 //-------------------------------------------------- // Converts input OEM charset data to 16 bit unicode. // oem - 8 bit oem charset input data // unicode - address of pointer for allocated unicode string. Caller must free() ! // outlen - address of length variable for unicode string // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int oem2unicode(const char* oem, char** unicode, int* outlen) { int len; *unicode = 0; // convert oem to unicode if(!oem || !strlen(oem)) return ERR_OK; ddocDebug(4, "oem2unicode", "Convert: \'%s\' len: %d", oem, strlen(oem)); len = MultiByteToWideChar(CP_ACP, 0, oem, -1, NULL, 0) * 2 + 10; ddocDebug(5, "oem2unicode", "Alloc: %d", len); *unicode = (char*)malloc(len); RETURN_IF_BAD_ALLOC(*unicode); memset(*unicode, 0, len); *outlen = MultiByteToWideChar(CP_ACP, 0, oem, -1, (LPWSTR)(*unicode), len); if(!(*outlen)) { SET_LAST_ERROR(ERR_CHARSET_CONVERT); return ERR_CHARSET_CONVERT; } else return ERR_OK; } //-------------------------------------------------- // Converts input 16 bit unicode data to UTF8. // unicode - 16 bit unicode input data // utf8 - address of pointer for allocated utf8 string. Caller must free() ! // outlen - address of length variable for utf8 string // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int unicode2utf8(const char* unicode, char** utf8, int* outlen) { int len; *utf8 = 0; // now convert unicode to UTF8 if(!unicode || !strlen(unicode)) return ERR_OK; len = WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)unicode, -1, NULL, 0, NULL, NULL) + 10; ddocDebug(5, "unicode2utf8", "Alloc: %d", len); *utf8 = (char*)malloc(len); RETURN_IF_BAD_ALLOC(*utf8); memset(*utf8, 0, len); *outlen = WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)unicode, -1, *utf8, len, NULL, NULL); ddocDebug(5, "unicode2utf8", "Convert: \'%s\' len: %d", *utf8, strlen(*utf8)); if(!(*outlen)) { SET_LAST_ERROR(ERR_CHARSET_CONVERT); return ERR_CHARSET_CONVERT; } else return ERR_OK; } //-------------------------------------------------- // Converts input OEM charset data to UTF-8 // oem - 8 bit oem charset input data // utf8 - address of buffer allocated utf8 string. // len - size of buffer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int oem2utf8(const char* oem, char* utf8, int len) { int err = ERR_OK, len1, len2; char *pTmp1 = 0, *pTmp2 = 0; ddocDebug(5, "oem2utf8", "oem2utf8"); // Kaido: 2.1.13 - initialize return value *utf8 = 0; // convert oem to unicode if(!oem || !strlen(oem)) return ERR_OK; err = oem2unicode(oem, &pTmp1, &len1); if(err) return err; // now convert unicode to UTF8 err = unicode2utf8(pTmp1, &pTmp2, &len2); if(len2 < len) memcpy(utf8, pTmp2, len2); else err = ERR_CHARSET_CONVERT; if(pTmp1) free(pTmp1); if(pTmp2) free(pTmp2); return err; } //-------------------------------------------------- // Converts input UTF-8 data to 16 bit unicode data. // utf8 - UTF-8 input data // unicode - address of pointer for allocated unicode string. Caller must free() ! // outlen - address of length variable for unicode string // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int utf82unicode(const char* utf8, char** unicode, int* outlen) { int len; *unicode = 0; // convert unicode to UTF-8 if(!utf8 || !strlen(utf8)) return ERR_OK; ddocDebug(5, "utf82unicode", "Convert: \'%s\' len: %d", utf8, strlen(utf8)); len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0) * 2 + 10; ddocDebug(5, "utf82unicode", "Alloc: %d", len); *unicode = (char*)malloc(len); RETURN_IF_BAD_ALLOC(*unicode); memset(*unicode, 0, len); *outlen = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, (LPWSTR)(*unicode), len); ddocDebug(5, "utf82unicode", "Converted: \'%s\' to \'%s\' len: %d", utf8, *unicode, *outlen); if(!(*outlen)) { SET_LAST_ERROR(ERR_CHARSET_CONVERT); return ERR_CHARSET_CONVERT; } else return ERR_OK; } //-------------------------------------------------- // Converts input 16 bit unicode data to oem charset data. // unicode - 16 bit unicode input data // oem - address of pointer for allocated oem string. Caller must free() ! // outlen - address of length variable for oem string // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int unicode2oem(const char* unicode, char** oem, int* outlen) { int len; *oem = 0; if(!unicode || !strlen(unicode)) return ERR_OK; // now convert unicode to OEM len = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)unicode, -1, NULL, 0, NULL, NULL) + 10; ddocDebug(5, "unicode2oem", "Alloc: %d", len); *oem = (char*)malloc(len); RETURN_IF_BAD_ALLOC(*oem); memset(*oem, 0, len); *outlen = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)unicode, -1, *oem, len, NULL, NULL); ddocDebug(5, "unicode2oem", "Convert: \'%s\' len: %d", *oem, strlen(*oem)); if(!(*outlen)) { SET_LAST_ERROR(ERR_CHARSET_CONVERT); return ERR_CHARSET_CONVERT; } else return ERR_OK; } //-------------------------------------------------- // Converts input UTF-8 data to OEM charset data // utf8 - UTF-8 input data // oem - address of buffer for oem string. // len - size of buffer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int utf82oem(const char* utf8, char* oem, int len) { int err = ERR_OK, len1, len2; char *pTmp1 = 0, *pTmp2 = 0; // Kaido: 2.1.13 - initialize return value *oem = 0; // convert utf8 to unicode if(!utf8 || !strlen(utf8)) return ERR_OK; memset(oem, 0, len); err = utf82unicode(utf8, &pTmp1, &len1); if(err) return err; // now convert unicode to OEM err = unicode2oem(pTmp1, &pTmp2, &len2); if(len2 < len) memcpy(oem, pTmp2, len2); else err = ERR_CHARSET_CONVERT; if(pTmp1) free(pTmp1); if(pTmp2) free(pTmp2); return err; } //-------------------------------------------------- // Converts input UTF-8 data to OEM charset data // pSigDoc - signed doc object // pDf - data file obejct // outFileName - output buffer // len - length of output buffer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int getDataFileFileName(SignedDoc* pSigDoc, DataFile* pDf, char* outFileName, int len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pDf); RETURN_IF_NULL_PARAM(outFileName); // Kaido: 2.1.13 - initialize return value *outFileName = 0; if(!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) ) { //utf82oem(pDf->szFileName, buf1, 300); //convFNameToWin(buf1, outFileName, len); strncpy(outFileName, pDf->szFileName, len); } else { convWinToFName(pDf->szFileName, outFileName, len); } return err; } #endif //-------------------------------------------------- // Converts input data to UTF-8 // src - input data // returns converted string or NULL. Caller must free it. //-------------------------------------------------- EXP_OPTION int ddocConvertInput(const char* src, char** dest) { int l1, err = ERR_OK; *dest = 0; l1 = strlen(src) * 2 + 3; *dest = (char*)malloc(l1); if(*dest) { memset(*dest, 0, l1); #ifdef WIN32 RETURN_IF_NULL(*dest); err = oem2utf8(src, *dest, l1); #else strncpy(*dest, src, l1); #endif } return err; } //-------------------------------------------------- // Releases mem-block allocated by lib. In win32 // this must be done since the mem was allocated by dll // and must also be released by dll that allocated it. // p - mem to be freed //-------------------------------------------------- EXP_OPTION void freeLibMem(void* p) { if(p) free(p); } //-------------------------------------------------- // Converts a filename according to platform rules // dest - destination buffer // destlen - destination buffer length // src - source filename // returns error code or ERR_OK //-------------------------------------------------- int ddocConvertFileName(char* dest, int destlen, const char* src) { int err = ERR_OK; RETURN_IF_NULL_PARAM(dest); RETURN_IF_NULL_PARAM(src); *dest = 0; // initialize #ifdef WIN32 err = utf82oem(src, dest, destlen); #else SET_LAST_ERROR_IF_NOT((int)strlen(src) < destlen, ERR_BUF_LEN); strncpy(dest, src, destlen); #endif return err; } //==========< Base64 functions >================ //============================================================ // Encode a byte array in Base64 format. // raw - input data // rawlen - length of input data // buf - destination buffer // buflen - destination buffer length (will be modified by catual number of bytes) //============================================================ EXP_OPTION void encode(const byte* raw, int rawlen, byte* buf, int* buflen) { EVP_ENCODE_CTX *ectx; RETURN_VOID_IF_NULL(raw); RETURN_VOID_IF_NULL(buf); RETURN_VOID_IF_NULL(buflen); memset(buf, 0, *buflen); ectx = EVP_ENCODE_CTX_new(); EVP_EncodeInit(ectx); EVP_EncodeUpdate(ectx, buf, buflen, (byte*)raw, rawlen); EVP_EncodeFinal(ectx, (unsigned char*)strchr((const char*)buf, 0), buflen); EVP_ENCODE_CTX_free(ectx); *buflen = strlen((const char*)buf); while(buf[*buflen-1] == '\n' || buf[*buflen-1] == '\r' || buf[*buflen-1] == '-') { if(buf[*buflen-1] == '-') ddocDebug(1, "encode", "Found - at the end of base64 code: %s", buf); buf[*buflen-1] = 0; *buflen = *buflen - 1; } *buflen = strlen((const char*)buf); } byte* breakToLinesOf64(byte* raw, int rawlen) { int i, l1, j; byte* p = raw; // if it's not divide in lines l1 = rawlen; j = l1 + (l1/64) * 3; p = (byte*)malloc(j); if (!p) return NULL; memset(p, 0, j); for(i = j = 0; i < l1; i += 64) { strncpy(strchr((const char*)p,0), (const char*)raw+i, ((i+64 64) { p = breakToLinesOf64((byte*)raw, rawlen); l1 = strlen((const char*)p); EVP_DecodeUpdate(ectx, (unsigned char*)buf, &l1, (unsigned char*)p, strlen((const char*)p)); *buflen += l1; free(p); } else EVP_DecodeUpdate(ectx, buf, buflen, (byte*)raw, rawlen); EVP_DecodeFinal(ectx, buf, &l1); EVP_ENCODE_CTX_free(ectx); *buflen += l1; } //============================================================ // Helper function to determine if this is a base64 char //============================================================ int isb64char(int c) { return ( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '+') || (c == '/') || (c == '=') ); } //============================================================ // Decodes input data in Base64 format. // pMBufSrc - input data // pMBufDest - destination buffer //============================================================ EXP_OPTION int ddocDecodeBase64(DigiDocMemBuf* pMBufSrc, DigiDocMemBuf* pMBufDest) { int err = ERR_OK, n; long lPos1 = 0, lPos2 = 0; EVP_ENCODE_CTX *ectx; char buf1[70]; RETURN_IF_NULL(pMBufSrc); RETURN_IF_NULL(pMBufDest); pMBufDest->pMem = 0; pMBufDest->nLen = 0; // alloc mem for result - it will get smaller so original length must be enough err = ddocMemSetLength(pMBufDest, pMBufSrc->nLen); if(err) return err; ectx = EVP_ENCODE_CTX_new(); EVP_DecodeInit(ectx); // decode base64 while(lPos1 < pMBufSrc->nLen) { // copy next input row memset(buf1, 0, sizeof(buf1)); n = 0; while(n < 64 && lPos1 < pMBufSrc->nLen) { if(isb64char(((char*)pMBufSrc->pMem)[lPos1])) { buf1[n] = ((char*)pMBufSrc->pMem)[lPos1]; n++; } lPos1++; } strncat(buf1, "\n", sizeof(buf1) - strlen(buf1)); // decode this chunk n = pMBufDest->nLen - lPos2; EVP_DecodeUpdate(ectx, (unsigned char*)((char*)pMBufDest->pMem + lPos2), &n, (unsigned char*)buf1, strlen((const char*)buf1)); lPos2 += n; } memset(buf1, 0, sizeof(buf1)); n = sizeof(buf1); EVP_DecodeFinal(ectx, (unsigned char*)buf1, &n); EVP_ENCODE_CTX_free(ectx); lPos2 += n; pMBufDest->nLen = lPos2; return err; } //============================================================ // Decodes input data in Base64 format. // data - input data // len - length of input data. Use -1 for zero terminated strings // pMBufDest - destination buffer //============================================================ EXP_OPTION int ddocDecodeBase64Data(void* data, long len, DigiDocMemBuf* pMBufDest) { DigiDocMemBuf mbuf1; mbuf1.pMem = data; if(len == -1) mbuf1.nLen = strlen((const char*)data); else mbuf1.nLen = len; return ddocDecodeBase64(&mbuf1, pMBufDest); } //============================================================ // Encodes input data in Base64 format. // pMBufSrc - input data // pMBufDest - destination buffer //============================================================ EXP_OPTION int ddocEncodeBase64(const DigiDocMemBuf* pMBufSrc, DigiDocMemBuf* pMBufDest) { int err = ERR_OK, nLen; EVP_ENCODE_CTX *ectx; RETURN_IF_NULL(pMBufSrc); RETURN_IF_NULL(pMBufDest); pMBufDest->pMem = 0; pMBufDest->nLen = 0; // alloc mem for result err = ddocMemSetLength(pMBufDest, pMBufSrc->nLen * 2 + 10); if(err) return err; ectx = EVP_ENCODE_CTX_new(); EVP_EncodeInit(ectx); // encode base64 nLen = pMBufDest->nLen; EVP_EncodeUpdate(ectx, (unsigned char*)pMBufDest->pMem, &nLen, (byte*)pMBufSrc->pMem, pMBufSrc->nLen); pMBufDest->nLen = nLen; nLen = (pMBufSrc->nLen * 2 + 10) - pMBufDest->nLen; EVP_EncodeFinal(ectx, (unsigned char*)pMBufDest->pMem + pMBufDest->nLen, &nLen); EVP_ENCODE_CTX_free(ectx); pMBufDest->nLen += nLen; //strlen((const char*)pMBufDest->pMem); return err; } //==========< conversion fucntions >================ //-------------------------------------------------- // Decodes an ASN1 generalized time // tm - ASN1 generalized time // y - year // M - month // d - day of month // h - hour // m - minute // s - second // returns error code or ERR_OK //-------------------------------------------------- int decodeGeneralizedTime(ASN1_GENERALIZEDTIME *tm, int* y, int* M, int* d, int* h, int* m, int* s) { char *v = NULL; int gmt=0; int i, err = ERR_OK; RETURN_IF_NULL_PARAM(tm); RETURN_IF_NULL_PARAM(y); RETURN_IF_NULL_PARAM(M); RETURN_IF_NULL_PARAM(d); RETURN_IF_NULL_PARAM(h); RETURN_IF_NULL_PARAM(m); RETURN_IF_NULL_PARAM(s); i=tm->length; v=(char *)tm->data; if (i < 12) err = ERR_TIMESTAMP_DECODE; if (v[i-1] == 'Z') gmt=1; for (i=0; i<12; i++) if ((v[i] > '9') || (v[i] < '0')) err = ERR_TIMESTAMP_DECODE; *y= (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0'); *M= (v[4]-'0')*10+(v[5]-'0'); if ((*M > 12) || (*M < 1)) err = ERR_TIMESTAMP_DECODE; *d= (v[6]-'0')*10+(v[7]-'0'); *h= (v[8]-'0')*10+(v[9]-'0'); *m= (v[10]-'0')*10+(v[11]-'0'); if ( (v[12] >= '0') && (v[12] <= '9') && (v[13] >= '0') && (v[13] <= '9')) *s= (v[12]-'0')*10+(v[13]-'0'); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Decodes an ASN1 UTC time // tm - ASN1 generalized time // y - year // M - month // d - day of month // h - hour // m - minute // s - second // returns error code or ERR_OK //-------------------------------------------------- int decodeUTCTime(ASN1_UTCTIME *tm, int* y, int* M, int* d, int* h, int* m, int* s) { char *v; int gmt=0; int i, err = 0; RETURN_IF_NULL_PARAM(tm); RETURN_IF_NULL_PARAM(y); RETURN_IF_NULL_PARAM(M); RETURN_IF_NULL_PARAM(d); RETURN_IF_NULL_PARAM(h); RETURN_IF_NULL_PARAM(m); RETURN_IF_NULL_PARAM(s); i=tm->length; v=(char *)tm->data; if (i < 10) err = ERR_TIMESTAMP_DECODE; if (v[i-1] == 'Z') gmt=1; for (i=0; i<10; i++) if ((v[i] > '9') || (v[i] < '0')) err = ERR_TIMESTAMP_DECODE; *y= (v[0]-'0')*10+(v[1]-'0'); if (*y < 50) *y+=100; *M= (v[2]-'0')*10+(v[3]-'0'); if ((*M > 12) || (*M < 1)) err = ERR_TIMESTAMP_DECODE; *d= (v[4]-'0')*10+(v[5]-'0'); *h= (v[6]-'0')*10+(v[7]-'0'); *m= (v[8]-'0')*10+(v[9]-'0'); if ( (v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9')) *s= (v[10]-'0')*10+(v[11]-'0'); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //========================================================== // converts ASN1 time to time_t //========================================================== int asn1time2time_t(ASN1_TIME* tm, time_t* pT) { int err = ERR_OK; struct tm tm1; //int dmz=0; RETURN_IF_NULL_PARAM(tm); RETURN_IF_NULL_PARAM(pT); _tzset(); memset(&tm1, 0, sizeof(tm1)); if(tm->type == V_ASN1_UTCTIME) err = decodeUTCTime(tm, &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday, &tm1.tm_hour, &tm1.tm_min, &tm1.tm_sec); if(tm->type == V_ASN1_GENERALIZEDTIME) err = decodeGeneralizedTime(tm, &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday, &tm1.tm_hour, &tm1.tm_min, &tm1.tm_sec); tm1.tm_year -= 1900; tm1.tm_mon -= 1; tm1.tm_isdst = _daylight; (*pT) = mktime(&tm1); /* if(_daylight!=0) { if(_timezone<0){ dmz = (_timezone / 3600) - _daylight; }else{ dmz = (_timezone / 3600) + _daylight; } }else{ dmz=_timezone / 3600; } (*pT) = (*pT) - (dmz * 3600); */ if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //========================================================== // converts ASN1 time to time_t //========================================================== int asn1time2time_t_local(ASN1_TIME* tm, time_t* pT) { int err = ERR_OK; struct tm tm1; int dmz=0; RETURN_IF_NULL_PARAM(tm); RETURN_IF_NULL_PARAM(pT); _tzset(); memset(&tm1, 0, sizeof(tm1)); if(tm->type == V_ASN1_UTCTIME) err = decodeUTCTime(tm, &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday, &tm1.tm_hour, &tm1.tm_min, &tm1.tm_sec); if(tm->type == V_ASN1_GENERALIZEDTIME) err = decodeGeneralizedTime(tm, &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday, &tm1.tm_hour, &tm1.tm_min, &tm1.tm_sec); if(tm1.tm_year > 1900) tm1.tm_year -= 1900; tm1.tm_mon -= 1; tm1.tm_isdst = _daylight; (*pT) = mktime(&tm1); if(_daylight != 0) { if(_timezone<0){ dmz = (_timezone / 3600) - _daylight; }else{ dmz = (_timezone / 3600) + _daylight; } }else{ dmz=_timezone / 3600; } (*pT) = (*pT) - (dmz * 3600); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //========================================================== // converts ASN1 time to string //========================================================== int asn1time2strYear(const SignedDoc* pSigDoc, ASN1_TIME* tm, char* buf, int year, int len) { int err = ERR_OK; struct tm tm1, tm2; time_t t2; int dmz=0; RETURN_IF_NULL_PARAM(tm); RETURN_IF_NULL_PARAM(buf); //RETURN_IF_NULL_PARAM(pSigDoc); _tzset(); memset(&tm1, 0, sizeof(tm1)); if(tm->type == V_ASN1_UTCTIME) err = decodeUTCTime(tm, &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday, &tm1.tm_hour, &tm1.tm_min, &tm1.tm_sec); if(tm->type == V_ASN1_GENERALIZEDTIME) err = decodeGeneralizedTime(tm, &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday, &tm1.tm_hour, &tm1.tm_min, &tm1.tm_sec); // V 1.76 - in format 1.3 we use CCYY-MM-DDTHH:MM:SSZ if(!pSigDoc || (pSigDoc && !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER) )) { snprintf(buf, len, "%04d-%02d-%02dT%02d:%02d:%02dZ", year + tm1.tm_year, tm1.tm_mon, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec); } else // in version 1.0 we use format CCYY.MM.DDTHH:MM:SS-TZ if(pSigDoc && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) { tm1.tm_year -= 1900 - year; tm1.tm_mon -= 1; tm1.tm_isdst = _daylight; t2 = mktime(&tm1); if (err == ERR_OK) { if (_daylight!=0) { if (_timezone<0) { dmz = (_timezone / 3600) - _daylight; } else { dmz = (_timezone / 3600) + _daylight; } } else { dmz=_timezone / 3600; } t2 -= (dmz * 3600); ddocLocalTime(&t2, &tm2, 1); snprintf(buf, len, "%04d.%02d.%02dT%02d:%02d:%02d%+03d:00", tm2.tm_year + 1900, tm2.tm_mon + 1, tm2.tm_mday, tm2.tm_hour, tm2.tm_min, tm2.tm_sec, dmz * -1); ddocDebug(5, "asn1time2strYear", "ASN1 time: %s, tz: %d, string: %s\n", tm->data, dmz * -1, buf); } } else { // in version 1.1 we use format CCYY.MM.DDTHH:MM:SSZ and allways UTC time snprintf(buf, len, "%04d.%02d.%02dT%02d:%02d:%02dZ", year + tm1.tm_year, tm1.tm_mon, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec); } if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //========================================================== // converts ASN1 time to string //========================================================== int asn1time2str(const SignedDoc* pSigDoc, ASN1_TIME* tm, char* buf, int len) { return asn1time2strYear(pSigDoc, tm, buf, 0, len); } //============================================================================== // converts ASN1_GENERALIZEDTOME object to string //============================================================================== int str2asn1time(const SignedDoc* pSigDoc, const char* str, ASN1_GENERALIZEDTIME* asn1tm) { char buf[50]; int rc, dmz = 0; struct tm tm1, tm2; time_t t2; RETURN_IF_NULL_PARAM(str); RETURN_IF_NULL_PARAM(asn1tm); _tzset(); memset(&tm1, 0, sizeof(tm1)); // in version 1.0 we use format CCYY.MM.DDTHH:MM:SS-TZ if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) { sscanf(str, "%04d.%02d.%04dT%02d:%02d:%02d%3d:00", &(tm1.tm_year), &(tm1.tm_mon), &(tm1.tm_mday), &(tm1.tm_hour), &(tm1.tm_min), &(tm1.tm_sec), &dmz); tm1.tm_year -= 1900; tm1.tm_mon -= 1; tm1.tm_isdst = _daylight; t2 = mktime(&tm1); t2 -= (dmz * 3600); ddocLocalTime(&t2, &tm2, 1); snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ", tm2.tm_year + 1900, tm2.tm_mon + 1, tm2.tm_mday, tm2.tm_hour, tm2.tm_min, tm2.tm_sec); } else { // in version 1.1 we use format CCYY.MM.DDTHH:MM:SSZ and allways UTC time sscanf(str, "%04d.%02d.%04dT%02d:%02d:%02dZ", &(tm1.tm_year), &(tm1.tm_mon), &(tm1.tm_mday), &(tm1.tm_hour), &(tm1.tm_min), &(tm1.tm_sec)); snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ", tm1.tm_year, tm1.tm_mon, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec); } rc = ASN1_GENERALIZEDTIME_set_string(asn1tm, buf); //printf("String: %s, tz: %d, ASN1 time: %s\n", str, dmz, asn1tm->data); return ERR_OK; } //=================================================================== // converts time_t to timestamp string // t - time_t input value // szTimestamp - output buffer // len - length of buffer // returns error code or ERR_OK //=================================================================== EXP_OPTION int time_t2str(time_t t, char* szTimestamp, int len) { struct tm tm1; RETURN_IF_NULL_PARAM(szTimestamp); ddocLocalTime(&t, &tm1, 0); snprintf(szTimestamp, len, "%04d-%02d-%02dT%02d:%02d:%02dZ", tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec); return ERR_OK; } //=================================================================== // converts string to time_t // szTimestamp - input buffer // pT - address time_t output value // returns error code or ERR_OK //=================================================================== EXP_OPTION int str2time_t(char* szTimestamp, time_t* pT) { struct tm tm1; time_t t1 = 0; //int dmz = 0; RETURN_IF_NULL_PARAM(szTimestamp); RETURN_IF_NULL_PARAM(pT); _tzset(); memset(&tm1, 0, sizeof(tm1)); sscanf(szTimestamp, "%04d.%02d.%04dT%02d:%02d:%02dZ", &(tm1.tm_year), &(tm1.tm_mon), &(tm1.tm_mday), &(tm1.tm_hour), &(tm1.tm_min), &(tm1.tm_sec) /*, &dmz*/); tm1.tm_year -= 1900; tm1.tm_mon -= 1; tm1.tm_isdst = _daylight; t1 = mktime(&tm1); //t1 -= (dmz * 3600); (*pT) = t1; return ERR_OK; } libdigidoc-3.10.5/libdigidoc/DigiDocConfig.h0000664000372000037200000004321113560273131020167 0ustar travistravis#ifndef __DIGI_DOC_CFG_H__ #define __DIGI_DOC_CFG_H__ //================================================== // FILE: DigiDocCfonfig.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for configuration management // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 08.01.2004 Veiko Sinivee // Creation // 20.03.2004 Added functions createOrReplacePrivateConfigItem() // writeConfigFile() and writePrivateConfigFile() // 20.03.2004 changed function notarizeSignature to check for PKCS12 arguments //================================================== #include #include #include #ifdef __cplusplus extern "C" { #endif #include // item type #define ITEM_TYPE_UNKNOWN 0 #define ITEM_TYPE_GLOBAL 1 #define ITEM_TYPE_PRIVATE 2 // used to mark modified items to then store all together in private config file #define ITEM_STATUS_UNKNOWN 0 #define ITEM_STATUS_OK 1 #define ITEM_STATUS_MODIFIED 2 // holds one configuration item typedef struct ConfigItem_st { char* szKey; // items key char* szValue; // items value int nType; // items type (system wide or private) int nStatus; // item status - clean/modified } ConfigItem; // holds one certificate item typedef struct CertificateItem_st { char* szKey; // items key X509* pCert; // certificate } CertificateItem; // array of configration items typedef struct ConfigurationStore_st { int nItems; ConfigItem** pItems; int nCerts; CertificateItem** pCerts; } ConfigurationStore; //-------------------------------------------------- // Returns true (not 0) if config store structure has been inited //-------------------------------------------------- EXP_OPTION int isConfigInited(); //-------------------------------------------------- // Initializes configuration store // szConfigFile - name of config file. Use NULL for default //-------------------------------------------------- EXP_OPTION int initConfigStore(const char* szConfigFile); //-------------------------------------------------- // Cleans memory of configuration store // pConfStore - configuration collection (use NULL for default) //-------------------------------------------------- EXP_OPTION void cleanupConfigStore(ConfigurationStore *pConfStore); //-------------------------------------------------- // Adds a new configration item // pConfStore - configuration collection (use NULL for default) // key - items key // value - items value // type - item type // status - item status // returns ERR_OK on success //-------------------------------------------------- EXP_OPTION int addConfigItem(ConfigurationStore *pConfStore, const char* key, const char* value, int type, int status); //-------------------------------------------------- // Read ca and ocsp responder certs from files and cache in memory //-------------------------------------------------- int initCertificateItems(); //-------------------------------------------------- // Deletes configration item // key - items key // returns ERR_OK on success //-------------------------------------------------- EXP_OPTION int ConfigItem_delete(const char* key); //-------------------------------------------------- // Adds a new private configration item or modifies // pConfStore - configuration collection (use NULL for default) // an existing one // key - items key // value - items value // returns ERR_OK on success //-------------------------------------------------- EXP_OPTION int createOrReplacePrivateConfigItem(ConfigurationStore *pConfStore, const char* key, const char* value); //-------------------------------------------------- // Finds a new configration items value by key // key - items key // returns value of config item or NULL if not found //-------------------------------------------------- EXP_OPTION const char* ConfigItem_lookup(const char* key); //-------------------------------------------------- // Finds a new configration items value by key from the store // key - items key // pConfStore - store to search in // returns value of config item or NULL if not found //-------------------------------------------------- EXP_OPTION const char* ConfigItem_lookup_fromStore(ConfigurationStore *pConfStore, const char* key); //-------------------------------------------------- // Finds a all configration items that start with this prefix // pConfStore - collection of found items // prefix - item keys prefix // returns error code or ERR_OK //-------------------------------------------------- int ConfigItem_findByPrefix(ConfigurationStore *pConfStore, const char* prefix); //-------------------------------------------------- // Finds a numeric configration items value by key // key - items key // defValue - default value to be returned // returns value of config item or defValue if not found //-------------------------------------------------- EXP_OPTION int ConfigItem_lookup_int(const char* key, int defValue); //-------------------------------------------------- // Finds a bolean configration items value by key // key - items key // defValue - default value to be returned // returns value of config item or defValue if not found //-------------------------------------------------- EXP_OPTION int ConfigItem_lookup_bool(const char* key, int defValue); //-------------------------------------------------- // Finds a new configration items value by key // key - items key // returns value of config item or NULL if not found //-------------------------------------------------- EXP_OPTION const char* ConfigItem_lookup_str(const char* key, const char* defValue); //-------------------------------------------------- // Reads and parses configuration file // fileName - configuration file name // type - type of config file global/private // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int readConfigFile(const char* fileName, int type); //-------------------------------------------------- // Writes a configuration file // fileName - configuration file name // type - type of config file global/private // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int writeConfigFile(const char* fileName, int type); //-------------------------------------------------- // Saves all private config items in correct file // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int writePrivateConfigFile(); //-------------------------------------------------- // Sets a new name for private config file. Can be // used to override default of env(HOME)/.digidoc.conf // Use NULL to restore default value //-------------------------------------------------- EXP_OPTION void setPrivateConfigFile(const char* fileName); //-------------------------------------------------- // Finds CA certificate of the given certificate // ppCA - address of found CA // pCert - certificate whose CA we are looking for // return error code or 0 for success // deprecated use findCAForCertificateAndSigTime() //-------------------------------------------------- DIGIDOC_DEPRECATED EXP_OPTION int findCAForCertificate(X509** ppCA, const X509* pCert); //-------------------------------------------------- // Finds CA certificate of the given certificate // ppCA - address of found CA // pCert - certificate whose CA we are looking for // tSigTime - signature timestamp // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findCAForCertificateAndSigTime(X509** ppCA, const X509* pCert, time_t tSigTime); //-------------------------------------------------- // Finds CA certificate by CN // ppCA - address of found CA // szCN - CA certs common name // pHash - authority-key-identifier to search for CA // return error code or 0 for success // deprecated use findCAForCNAndSigTime() //-------------------------------------------------- DIGIDOC_DEPRECATED EXP_OPTION int findCAForCN(X509** ppCA, const char* szCN, DigiDocMemBuf *pHash); //-------------------------------------------------- // Finds CA certificate by CN // ppCA - address of found CA // szCN - CA certs common name // pHash - authority-key-identifier to search for CA // tSigTime - signing time or 0 // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findCAForCNAndSigTime(X509** ppCA, const char* szCN, DigiDocMemBuf *pHash, time_t tSigTime); //-------------------------------------------------- // Finds CA chain // ppChain - address of cert pointer array // nMaxChain - index of last cert in returned array - 0 based // szCN - CN of the first CA cert (not the child cert!) // pCert - certificate to search ca-s for // return error code or 0 for success // deprecated use findCAChainForCNAndSigTime() //-------------------------------------------------- DIGIDOC_DEPRECATED EXP_OPTION int findCAChainForCN(X509** ppChain, int* nMaxChain, const char* szCN, X509* pCert); //-------------------------------------------------- // Finds CA chain // ppChain - address of cert pointer array // nMaxChain - index of last cert in returned array - 0 based // szCN - CN of the first CA cert (not the child cert!) // pCert - certificate to search ca-s for // tSigTime - signature timestamp // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findCAChainForCNAndSigTime(X509** ppChain, int* nMaxChain, const char* szCN, X509* pCert, time_t tSigTime); //-------------------------------------------------- // Finds Responders certificate by CN // ppResp - address of found cert // szCN - Responder certs common name // hash - responder certs hash in base64 form // szCertSerial - specific serial number to search // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findResponder(X509** ppResp, const char* szCN, const char* szHash, char* szCertSerial); //-------------------------------------------------- // Finds Responders certificate by CN and index // ppResp - address of found cert // szCN - Responder certs common name // hash - responder certs hash in base64 // nIdx - index of the certificate for this respnder. Starts at 0 // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findResponderByCNAndHashAndIndex(X509** ppResp, const char* szCN, const char* hash, int nIdx); //-------------------------------------------------- // Finds Responder certificates CA certs CN // caCN - buffer for responders CA CN // len - length of buffer for CA CN // szCN - responder certs common name // hash - responder certs hash in base64 form // return error code or 0 for success //-------------------------------------------------- EXP_OPTION int findResponderCA(char* caCN, int len, const char* szCN, const char* hash); //------------------------------------------ // Get a notary confirmation for signature // pSigDoc - signed document pointer // pSigInfo - signature to notarize // returns error code //------------------------------------------ EXP_OPTION int notarizeSignature(SignedDoc* pSigDoc, SignatureInfo* pSigInfo); //------------------------------------------ // Get a notary confirmation for signature // pSigDoc - signed document pointer // pSigInfo - signature to notarize // ip - callers ip address if known // returns error code //------------------------------------------ EXP_OPTION int notarizeSignatureWithIp(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, unsigned long ip); //-------------------------------------------------- // Signs the document and gets configrmation // pSigDoc - signed document pointer // ppSigInfo - address of new signature pointer // pin - smart card PIN // manifest - manifest / resolution (NULL) // city - signers city (NULL) // state - signers state (NULL) // zip - signers postal code (NULL) // country - signers country (NULL) //-------------------------------------------------- EXP_OPTION int signDocument(SignedDoc* pSigDoc, SignatureInfo** ppSigInfo, const char* pin, const char* manifest, const char* city, const char* state, const char* zip, const char* country); //-------------------------------------------------- // Signs the document and gets configrmation // pSigDoc - signed document pointer // ppSigInfo - address of new signature pointer // pin - smart card PIN // manifest - manifest / resolution (NULL) // city - signers city (NULL) // state - signers state (NULL) // zip - signers postal code (NULL) // country - signers country (NULL) // signs with PKCS11 //-------------------------------------------------- EXP_OPTION int signDocumentWithSlot(SignedDoc* pSigDoc, SignatureInfo** ppSigInfo, const char* pin, const char* manifest, const char* city, const char* state, const char* zip, const char* country, int nSlot, int nOcsp, int nSigner); //-------------------------------------------------- // Signs the document and gets configrmation // pSigDoc - signed document pointer // ppSigInfo - address of new signature pointer // pin - smart card PIN // manifest - manifest / resolution (NULL) // city - signers city (NULL) // state - signers state (NULL) // zip - signers postal code (NULL) // country - signers country (NULL) // nSigner - 1=PKCS11, 2=CNG (Microsoft CAPI), 3=PKCS#12 // szPkcs12FileName - PKCS#12 file name to be used for signing (required if nSigner=3) //-------------------------------------------------- EXP_OPTION int signDocumentWithSlotAndSigner(SignedDoc* pSigDoc, SignatureInfo** ppSigInfo, const char* pin, const char* manifest, const char* city, const char* state, const char* zip, const char* country, int nSlot, int nOcsp, int nSigner, const char* szPkcs12FileName); //-------------------------------------------------- // Verify this notary // pSigDoc - signed document pointer // pNotInfo - notary to verify // returns error code //-------------------------------------------------- int verifyNotary(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, NotaryInfo* pNotInfo); //-------------------------------------------------- // Verify this signature and it's notary // pSigDoc - signed document pointer // pSigInfo - signature to verify // szFileName - input digidoc filename // returns error code //-------------------------------------------------- EXP_OPTION int verifySignatureAndNotary(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const char* szFileName); //-------------------------------------------------- // Extract common name from cert DN or responder id // src - DN // dest - buffer for CN // destLen - size of output buffer in bytes //-------------------------------------------------- int findCN(char* src, char* dest, int destLen); //------------------------------------------ // Verify certificate by OCSP // pCert - certificate to check // ppResp - address to return OCSP response. Use NULL if // you don't want OCSP response to be returned // returns error code //------------------------------------------ EXP_OPTION int ddocVerifyCertByOCSP(X509* pCert, OCSP_RESPONSE **ppResp); //------------------------------------------ // Verify certificate by OCSP // pCert - certificate to check // ppResp - address to return OCSP response. Use NULL if // you don't want OCSP response to be returned // returns error code //------------------------------------------ EXP_OPTION int ddocVerifyCertByOCSPWithIp(X509* pCert, OCSP_RESPONSE **ppResp, unsigned long ip); //------------------------------------------ // Reads an arbitrary file into memory buffer // szFileName - file name and path // pData - memory buffer object // returns error code //------------------------------------------ EXP_OPTION int ddocReadFile(const char* szFileName, DigiDocMemBuf* pData); //------------------------------------------ // Writes an arbitrary file into memory buffer // szFileName - file name and path // pData - memory buffer object // returns error code //------------------------------------------ EXP_OPTION int ddocWriteFile(const char* szFileName, DigiDocMemBuf* pData); #ifdef __cplusplus } #endif #endif // __DIGI_DOC_CFG_H__ libdigidoc-3.10.5/libdigidoc/DigiDocSAXParser.c0000664000372000037200000035263013560273131020575 0ustar travistravis//================================================== // FILE: DigiDocSAXParser.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for xml parsing using SAX interface // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 12.08.2004 Veiko Sinivee // Creation //================================================== #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* only for xmlNewInputFromFile() */ #include #include #include #include // string used to force parser to flush it's buffers static char g_szDataFileFlush1[] = ""; static char g_szDataFileFlush2[] = ""; #ifdef WIN32 #define snprintf _snprintf #include #endif #if OPENSSL_VERSION_NUMBER < 0x10010000L static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new() { return (EVP_ENCODE_CTX*)OPENSSL_malloc(sizeof(EVP_ENCODE_CTX)); } static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) { OPENSSL_free(ctx); } #endif extern int ddocCheckFormatAndVer(const char* format, const char* version); extern char* canonicalizeXML(char* source, int len); extern int escapeXMLSymbols(const char* src, int srclen, char** dest); #define FLAG_XML_ELEM 1 #define FLAG_SIGNATURE 2 #define FLAG_SIG_PART 3 #define FLAG_TS_INP 4 //===============< SAX handlers >============================== /* * Working area for XML parsing with SAX */ typedef struct SigDocParse_st { SignedDoc* pSigDoc; // document file to be filled with data char tag[300]; // current tag char ctx1[300]; // context1 char ctx2[300]; // context2 char ctx3[300]; // context3 char ctx4[300]; char ctx5[300]; BIO* bDataFile; EVP_ENCODE_CTX *ectx; SHA_CTX sctx, sctx2; // sha1 digest context and alternat dig context int errcode; char* szInputFileName; int checkFileDigest; int nIgnoreDataFile; // incremented each time when EMBEDDED XML content is found. // used to ignore such content DigiDocMemBuf mbufElemData; char bCollectElemData; char bNoXMLElemData; int checkUTF8; DigiDocMemBuf mbufSigData; // char bCollectSigData; DigiDocMemBuf mbufSigPartData; // and char bCollectSigPartData; long lMaxDFLen; time_t tStartParse; long lSize; char bCollectDFData; DigiDocMemBuf *pMemBufDF; int bKeepBase64; char b64line[66]; int b64pos; DigiDocMemBuf mbufTags; XmlElemInfo *eRoot, *eCurr; } SigDocParse; //-------------------------------------------------- // Releases memory that might have been allocated during // the parsing process. // pctx - pointer to parsing context //-------------------------------------------------- void ddocSAXCleanup(SigDocParse* pctx) { // field: szInputFileName is not allocated in parser! ddocMemBuf_free(&(pctx->mbufElemData)); ddocMemBuf_free(&(pctx->mbufSigData)); ddocMemBuf_free(&(pctx->mbufSigPartData)); ddocMemBuf_free(&(pctx->mbufTags)); if(pctx->pMemBufDF) ddocMemBuf_free(pctx->pMemBufDF); if(pctx->bDataFile) BIO_free(pctx->bDataFile); if(pctx->eRoot) XmlElemInfo_free(pctx->eRoot); memset(pctx, 0, sizeof(SigDocParse)); } //-------------------------------------------------- // Starts collecting some element data. // pctx - pointer to parsing context // nFlag - 1=element, 2=signature, 3=sigprop, 4=ts-input // bNoXml - no-xml flag //-------------------------------------------------- int ddocSaxParseStartCollecting(SigDocParse* pctx, int nFlag, int bNoXml) { RETURN_IF_NULL_PARAM(pctx); switch(nFlag) { case FLAG_XML_ELEM: pctx->bCollectElemData = 1; pctx->errcode = ddocMemBuf_free(&(pctx->mbufElemData)); break; case FLAG_SIGNATURE: pctx->bCollectSigData = 1; pctx->errcode = ddocMemBuf_free(&(pctx->mbufSigData)); break; case FLAG_SIG_PART: pctx->bCollectSigPartData = 1; pctx->errcode = ddocMemBuf_free(&(pctx->mbufSigPartData)); break; } pctx->bNoXMLElemData = bNoXml; return pctx->errcode; } //-------------------------------------------------- // Ends collecting some element data. // pctx - pointer to parsing context // nFlag - 1=element, 2=signature, 3=sigprop, 4=ts-input // bNoXml - no-xml flag //-------------------------------------------------- int ddocSaxParseEndCollecting(SigDocParse* pctx, int nFlag, int bNoXml) { RETURN_IF_NULL_PARAM(pctx); switch(nFlag) { case FLAG_XML_ELEM: pctx->bCollectElemData = 0; pctx->errcode = ddocMemBuf_free(&(pctx->mbufElemData)); break; case FLAG_SIGNATURE: pctx->bCollectSigData = 0; pctx->errcode = ddocMemBuf_free(&(pctx->mbufSigData)); break; case FLAG_SIG_PART: pctx->bCollectSigPartData = 0; pctx->errcode = ddocMemBuf_free(&(pctx->mbufSigPartData)); break; } pctx->bNoXMLElemData = bNoXml; return pctx->errcode; } //-------------------------------------------------- // Finds the desired atribute value. // atts - attributes array // name - name of searched atribute // defval - default value if not found //-------------------------------------------------- const char* ddocSaxParseFindAttrib(const xmlChar **atts, const char* name, const char* defval) { int i; for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { if(!strcmp((const char*)atts[i], name)) return (const char*)atts[i+1]; } return defval; } //-------------------------------------------------- // Decodes a URI value in form #- or #@ // into its components // uri - URI value // id - buffer for id // nIdLen - id buffer length // adr - buffer for adr // nAdrLen - adr buffer length //-------------------------------------------------- void decodeURI(const char* uri, char* id, int nIdLen, char* adr, int nAdrLen) { int j, b, i, a; RETURN_VOID_IF_NULL(uri); RETURN_VOID_IF_NULL(id); RETURN_VOID_IF_NULL(adr); id[0] = adr[0] = 0; for(i = j = a = b = 0; uri[j] && (a < nAdrLen-1) && (i < nIdLen-1); j++) { switch(uri[j]) { case '#': continue; case '@': // same as the next case '-': b = 1; continue; default: if(b) adr[a++] = uri[j]; else id[i++] = uri[j]; } } adr[a] = 0; id[i] = 0; } //-------------------------------------------------- // handles the start of a element. // Creates SignedDoc structure to read in the info. // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartSignedDoc(SigDocParse* pctx, const xmlChar *name, const xmlChar **atts) { int i; const char *key = NULL, *value = NULL; //RETURN_VOID_IF_NULL(pctx); //RETURN_VOID_IF_NULL(name); //RETURN_VOID_IF_NULL(atts); strncpy(pctx->ctx1, (const char*)name, sizeof(pctx->ctx1)-1); for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { key = (const char*)atts[i]; value = (const char*)atts[i+1]; if(!strcmp(key, "format")) setString(&(pctx->pSigDoc->szFormat), value, -1); if(!strcmp(key, "version")) setString(&(pctx->pSigDoc->szFormatVer), value, -1); } if(ddocCheckFormatAndVer(pctx->pSigDoc->szFormat, pctx->pSigDoc->szFormatVer)) SET_LAST_ERROR(ERR_UNSUPPORTED_FORMAT); } void unescapeFilename(char** szFileName, const char* str1, const char* str2) { DigiDocMemBuf mbuf1, mbuf2; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; ddocDebug(4, "unescapeFilename", "In: %s replace: %s with: %s", *szFileName, str1, str2); if(szFileName && strstr((const char*)(*szFileName), str1)) { mbuf1.pMem = *szFileName; mbuf1.nLen = strlen(*szFileName); ddocMemReplaceSubstr(&mbuf1, &mbuf2, str1, str2); setString(szFileName, (const char*)mbuf2.pMem, -1); ddocMemBuf_free(&mbuf2); ddocDebug(4, "unescapeFilename", "Escaped: %s", *szFileName); } } int utf8strlen(const char* src) { int i, j; unsigned char uc; for(i = 0, j = 0; src && src[i]; i++) { uc = (unsigned char)(0x000000FF & src[i]); if(uc <= 0x7F || uc >= 0xC0) j++; } ddocDebug(4, "utf8strlen", "Str: %s, len: %d", src, j); return j; } //-------------------------------------------------- // handles the start of a element. // Reads in id, filename, mime_type and embedded attributes // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartDataFile(SigDocParse* pctx, const xmlChar *name, const xmlChar **atts) { int i, err = ERR_OK, j; long size = -1; const char *id = 0, *mime = 0, *dtype = 0, *dvalue = 0, *ctype = 0; char *p = 0; DigiDocMemBuf mbuf1, mbuf2; DataFile* pDataFile = NULL; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; ddocDebug(4, "handleStartDataFile", "Ignore: %d", pctx->nIgnoreDataFile); strncpy(pctx->ctx1, (const char*)name, sizeof(pctx->ctx1)); id = mime = dtype = dvalue = 0; size = 0; // allocate mem dynamically and calculate required size as necessary if(!pctx->nIgnoreDataFile) { pctx->bCollectElemData = 1; } for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { if(!strcmp((const char*)atts[i], "Id")) id = (const char*)atts[i+1]; if(!strcmp((const char*)atts[i], "Filename")) { escapeXMLSymbols((const char*)atts[i+1], -1, &p); if(p) err = ddocMemAppendData(&mbuf1, p, -1); free(p); p = 0; ddocDebug(4, "handleStartDataFile", "Filename in: \'%s\' out: \'%s\'", atts[i+1], (char*)mbuf1.pMem); if(strchr((char*)mbuf1.pMem, '/') || strchr((char*)mbuf1.pMem, '\\')) { ddocDebug(1, "handleStartDataFile", "Invalid filename: \'%s\'", (char*)mbuf1.pMem); SET_LAST_ERROR(ERR_DF_NAME); return; } } if(!strcmp((const char*)atts[i], "MimeType")) mime = (const char*)atts[i+1]; if(!strcmp((const char*)atts[i], "ContentType")) ctype = (const char*)atts[i+1]; if(!strcmp((const char*)atts[i], "DigestType")) dtype = (const char*)atts[i+1]; if(!strcmp((const char*)atts[i], "DigestValue")) dvalue = (const char*)atts[i+1]; if(!strcmp((const char*)atts[i], "Size")) size = atol((const char*)atts[i+1]); } if (!id || (strlen(id) > 21)) { SET_LAST_ERROR(ERR_DIGIDOC_PARSE); ddocDebug(1, "handleStartDataFile", "Arr err id: %s", id); return; } // VS: check id uniqueness for(j = 0; j < getCountOfDataFiles(pctx->pSigDoc); j++) { pDataFile = getDataFile(pctx->pSigDoc, j); if(pDataFile && pDataFile->szId && !strcmp(pDataFile->szId, id)) { ddocDebug(1, "handleStartDataFile", "DF %d has same id: %s", j, id); SET_LAST_ERROR(ERR_DIGIDOC_PARSE); return; } } if (!mime || (strlen(mime) > 255)) { SET_LAST_ERROR(ERR_DIGIDOC_PARSE); ddocDebug(1, "handleStartDataFile", "Arr err mime: %s", mime); return; } if (!mbuf1.pMem || (utf8strlen(mbuf1.pMem) > 255)) { SET_LAST_ERROR(ERR_DIGIDOC_PARSE); return; } if (size < 0) { SET_LAST_ERROR(ERR_DIGIDOC_PARSE); ddocDebug(1, "handleStartDataFile", "Arr err size: %d", size); return; } if (!ctype || (strlen(ctype) > 40)) { SET_LAST_ERROR(ERR_DIGIDOC_PARSE); ddocDebug(1, "handleStartDataFile", "Arr err ctype: %s", ctype); return; } if (!pctx->pSigDoc->szFormatVer) { SET_LAST_ERROR(ERR_DIGIDOC_PARSE); ddocDebug(1, "handleStartDataFile", "Arr err sigdoc missing"); return; } if ((dtype && (strlen(dtype) > 10)) || (dvalue && (strlen(dvalue) > 100))) { SET_LAST_ERROR(ERR_DIGIDOC_PARSE); ddocDebug(1, "handleStartDataFile", "Arr err - dtype: %s dvalue: %s", dtype, dvalue); return; } if((!ctype || strcmp(ctype, CONTENT_EMBEDDED_BASE64)) && !ConfigItem_lookup_bool("EMBEDDED_XML_SUPPORT", 0)) { SET_LAST_ERROR(ERR_BAD_DATAFILE_CONTENT_TYPE); return; } ddocDebug(4, "handleStartDataFile", "Check ignore"); // if not in ignore mode / level if(!pctx->nIgnoreDataFile) { strncpy(pctx->ctx2, id, sizeof(pctx->ctx2)-1); ddocDebug(4, "handleStartDataFile", "Start DF: %s", id); if(ctype && !strcmp(ctype, CONTENT_EMBEDDED_BASE64)) { pctx->ectx = EVP_ENCODE_CTX_new(); EVP_DecodeInit(pctx->ectx); ddocDebug(3, "handleStartDataFile", "Init sha1"); SHA1_Init(&(pctx->sctx)); SHA1_Init(&(pctx->sctx2)); } if(pctx->bDataFile) pctx->bDataFile = BIO_new_file((char*)mbuf1.pMem, "w"); strncpy(pctx->ctx3, ctype, sizeof(pctx->ctx3)-1); if(strcmp(pctx->pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) { // copy value first err = ddocMemAssignData(&mbuf2, (const char*)mbuf1.pMem, mbuf1.nLen+1); // apply conversion - no length change convWinToFName((const char*)mbuf1.pMem, (char*)mbuf2.pMem, mbuf2.nLen); err = DataFile_new(&pDataFile, pctx->pSigDoc, id, (char*)mbuf2.pMem, ctype, mime, size, NULL, 0, dtype, CHARSET_UTF_8); } else err = DataFile_new(&pDataFile, pctx->pSigDoc, id, (char*)mbuf1.pMem, ctype, mime, size, NULL, 0, dtype, CHARSET_UTF_8); // RETURN_IF_NULL(pDataFile); ddocDebug(4, "handleStartDataFile", "Create DF: \'%s\' - err: %d", id, err); if(dvalue) { err = ddocMemBuf_free(&mbuf2); err = ddocDecodeBase64Data((void*)dvalue, -1, &mbuf2); ddocDataFile_SetDetachedDigestValue(pDataFile, (const char*)mbuf2.pMem, mbuf2.nLen); } // add other attributes for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { if(strcmp((const char*)atts[i], "Id") && strcmp((const char*)atts[i], "Filename") && strcmp((const char*)atts[i], "MimeType") && strcmp((const char*)atts[i], "DigestValue") && strcmp((const char*)atts[i], "Size") && strcmp((const char*)atts[i], "ContentType") && strcmp((const char*)atts[i], "DigestType") && strcmp((const char*)atts[i], "xmlns")) err = addDataFileAttribute(pDataFile, (const char*)atts[i], (const char*)atts[i+1]); } } // is it pure XML ? if(!strcmp(ctype, CONTENT_EMBEDDED) || pctx->nIgnoreDataFile) pctx->nIgnoreDataFile++; // cleanup err = ddocMemBuf_free(&mbuf2); err = ddocMemBuf_free(&mbuf1); // replace & with & if necessary unescapeFilename(&(pDataFile->szFileName), "&", "&"); unescapeFilename(&(pDataFile->szFileName), "'", "'"); unescapeFilename(&(pDataFile->szFileName), """, "\""); ddocDebug(4, "handleStartDataFile", "Final filename: \'%s\'", pDataFile->szFileName); } //-------------------------------------------------- // handles the content of a element. // Reads in data file (Base64) data, decodes it // and writes to a file // pctx - pointer to XML parsing work-area // value - character values read from file // len - length of chars ??? //-------------------------------------------------- void handleDataFile(SigDocParse* pctx, const xmlChar *value, int len) { int l, i, j; char buf[1024], ch; DataFile* pDf = 0; DigiDocMemBuf mbuf1; // decode the content data ddocDebug(4, "handleDataFile", "DF: %s, append len: %d", pctx->ctx2, len); pDf = getDataFileWithId(pctx->pSigDoc, pctx->ctx2); RETURN_VOID_IF_NULL(pDf); ddocAppendDataFileData(pDf, pctx->lMaxDFLen, (void*)value, len, !strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64)); if(!strcmp(pctx->ctx3, CONTENT_EMBEDDED_BASE64)) { // if using DataFile Base64 hack #ifdef WITH_BASE64_HASHING_HACK if(pctx->pSigDoc->szFormatVer && strcmp(pctx->pSigDoc->szFormatVer, SK_XML_1_VER) && pctx->pSigDoc->szFormat && strcmp(pctx->pSigDoc->szFormat, SK_XML_1_NAME)) { ch = ((char*)value)[len]; ((char*)value)[len] = 0; ddocDebug(4, "handleDataFile", "sha1 update: \'%s\' len: %d", value, len); mbuf1.pMem = (char*)value; mbuf1.nLen = len; ddocDebugWriteFile(4, "df-data.txt", &mbuf1); ((char*)value)[len] = ch; SHA1_Update(&(pctx->sctx), (char*)value, len); SHA1_Update(&(pctx->sctx2), (char*)value, len); ddocMemBuf_free(&(pctx->mbufElemData)); if(pctx->bDataFile) { i = j = 0; while(i < len) { i = (i + 512 > len) ? len : i + 512; l = sizeof(buf); memset(buf, 0, sizeof(buf)); EVP_DecodeUpdate(pctx->ectx, (unsigned char*)buf, &l, (unsigned char*)value + j, i - j); BIO_write(pctx->bDataFile, buf, l); j = i; } } } else { #endif i = j = 0; while(i < len) { i = (i + 512 > len) ? len : i + 512; l = sizeof(buf); memset(buf, 0, sizeof(buf)); EVP_DecodeUpdate(pctx->ectx, (unsigned char*)buf, &l, (unsigned char*)value + j, i - j); if(pctx->bDataFile) BIO_write(pctx->bDataFile, buf, l); buf[l] = 0; ddocDebug(4, "handleDataFile", "update sha1: %s", buf); SHA1_Update(&(pctx->sctx), buf, l); SHA1_Update(&(pctx->sctx2), buf, l); j = i; } #ifdef WITH_BASE64_HASHING_HACK } #endif } else if(!strcmp(pctx->ctx3, CONTENT_EMBEDDED)) { if(pctx->bDataFile) BIO_write(pctx->bDataFile, value, len); } } //-------------------------------------------------- // handles the end of a element. // Finishes writing file data // pctx - pointer to XML parsing work-area // name - tag name //-------------------------------------------------- void handleEndDataFile(SigDocParse* pctx, const xmlChar *name) { int l1, err; long l; char buf[1024], *pTmp1 = 0, *pTmp2 = 0; DataFile* pDf = 0; time_t t1, t2; DigiDocMemBuf mbuf1; ddocDebug(4, "handleEndDataFile", "DF: %s", pctx->ctx2); if(pctx->nIgnoreDataFile > 0 && !strcmp(pctx->ctx3, CONTENT_EMBEDDED)) pctx->nIgnoreDataFile--; if(pctx->nIgnoreDataFile) return; pDf = getDataFileWithId(pctx->pSigDoc, pctx->ctx2); RETURN_VOID_IF_NULL(pDf); RETURN_VOID_IF_NULL(pDf->szContentType); // if store file data if(pctx->bDataFile && !strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64)) { l1 = sizeof(buf); EVP_DecodeFinal(pctx->ectx, (unsigned char*)buf, &l1); EVP_ENCODE_CTX_free(pctx->ectx); BIO_write(pctx->bDataFile, buf, l1); BIO_free(pctx->bDataFile); pctx->bDataFile = NULL; } // in version 1.0 we calculate digest over original data if(pctx->pSigDoc->szFormat && !strcmp(pctx->pSigDoc->szFormat, SK_XML_1_NAME)) { if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64)) { ddocDebug(3, "handleEndDataFile", "final sha1"); SHA1_Final((unsigned char*)buf, &(pctx->sctx)); checkErrors(); ddocDataFile_SetDigestValue(pDf, buf, DIGEST_LEN); SHA1_Final((unsigned char*)buf, &(pctx->sctx2)); ddocDataFile_SetWrongDigestValue(pDf, buf, DIGEST_LEN); // debug l1 = sizeof(buf); bin2hex(pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, buf, &l1); ddocDebug(3, "handleEndDataFile", "DF: %s calc digest: %s len: %d", pDf->szId, buf, l1); } else if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED)) { if(pctx->mbufElemData.pMem) { l1 = sizeof(buf); // remove the tag end marker pTmp2 = (char*)(pctx->mbufElemData.pMem) + pctx->mbufElemData.nLen - 1; while(*pTmp2 != '<' && pTmp2 > (char*)pctx->mbufElemData.pMem) pTmp2--; if(*pTmp2 == '<') *pTmp2 = 0; //skip leading newlines pTmp1 = (char*)pctx->mbufElemData.pMem; while(*pTmp1 && *pTmp1 != '<') pTmp1++; if(pctx->bDataFile) { BIO_write(pctx->bDataFile, pTmp1, strlen(pTmp1)); BIO_free(pctx->bDataFile); pctx->bDataFile = 0; } err = calculateDigest((const byte*)pTmp1, strlen(pTmp1), DIGEST_SHA1, (byte*)buf, &l1); if(!err) ddocDataFile_SetDigestValue(pDf, buf, DIGEST_LEN); // free collected data // and mark the end of data collecting mode ddocMemBuf_free(&(pctx->mbufElemData)); pctx->bCollectElemData = 0; } } else if(pctx->checkFileDigest) { l1 = sizeof(buf); err = calculateFileDigest(pDf->szFileName, DIGEST_SHA1, (byte*)buf, &l1, &l); if(!err) ddocDataFile_SetDigestValue(pDf, buf, DIGEST_LEN); else ddocMemBuf_free(&(pDf->mbufDigest)); } } // in version 1.1 we calculate digest over the whole // in canonicalized form else { // if use base64 hack of datafile #ifdef WITH_BASE64_HASHING_HACK if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64)) { strncpy(buf, "", sizeof(buf)); ddocDebug(3, "handleEndDataFile", "final sha1 update: \'%s\'", buf); mbuf1.pMem = ""; mbuf1.nLen = strlen(""); ddocDebugWriteFile(4, "df-data.txt", &mbuf1); SHA1_Update(&(pctx->sctx), buf, strlen(buf)); SHA1_Update(&(pctx->sctx2), buf, strlen(buf)); memset(buf, 0, sizeof(buf)); SHA1_Final((unsigned char*)buf, &(pctx->sctx)); ddocDataFile_SetDigestValue(pDf, buf, DIGEST_LEN); SHA1_Final((unsigned char*)buf, &(pctx->sctx2)); ddocDataFile_SetWrongDigestValue(pDf, buf, DIGEST_LEN); setString((char**)&(pDf->szDigestType), DIGEST_SHA1_NAME, -1); // debug l1 = sizeof(buf); encode((const byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, (byte*)buf, &l1); ddocDebug(3, "handleEndDataFile", "DF: %s calc digest: %s len: %d", pDf->szId, buf, l1); ddocMemBuf_free(&(pctx->mbufElemData)); pctx->bCollectElemData = 0; // wrong digest l1 = sizeof(buf); encode((const byte*)pDf->mbufWrongDigest.pMem, pDf->mbufWrongDigest.nLen, (byte*)buf, &l1); ddocDebug(3, "handleEndDataFile", "DF: %s alt calc digest: %s len: %d", pDf->szId, buf, l1); } else { #endif // debug time(&t1); ddocDebug(4, "handleEndDataFile", "DF: %s data-len: %ld, parsing time: %d [sek]", (const char*)name, pctx->mbufElemData.nLen, (t1 - pctx->tStartParse)); ddocDebug(8, "handleEndDataFile", "DF: %s data:\n%s", (const char*)name, pctx->mbufElemData.pMem); if(pctx->mbufElemData.pMem) { pTmp2 = canonicalizeXML((char*)pctx->mbufElemData.pMem, pctx->mbufElemData.nLen); time(&t2); ddocDebug(4, "handleEndDataFile", "Canonicalizing: %s, time: %d [sek]", (pTmp2 ? "OK" : "ERROR"), (t2 - t1)); if(pTmp2) { SHA1_Init(&(pctx->sctx)); SHA1_Update(&(pctx->sctx), pTmp2, strlen(pTmp2)); SHA1_Final((unsigned char*)buf,&(pctx->sctx)); ddocDataFile_SetDigestValue(pDf, buf, DIGEST_LEN); setString((char**)&(pDf->szDigestType), DIGEST_SHA1_NAME, -1); ddocDebug(4, "handleEndDataFile", "DF: %s digest updated", pDf->szId); l1 = sizeof(buf); encode((byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, (byte*)buf, &l1); ddocDebug(4, "handleEndDataFile", "DF: %s calc digest: %s len: %d", pDf->szId, buf, l1); // P.R ends ddocDebug(4, "handleEndDataFile", "DF: %s canonical XML: \'%s\'", pDf->szId, pTmp2); ddocDebug(4, "handleEndDataFile", "DF: %s calc digest: %s len: %d", pDf->szId, buf, l1); ddocDebug(4, "handleEndDataFile", "DF: %s canonical XML: \'%s\'", pDf->szId, pTmp2); free(pTmp2); } // if(pTmp2) ddocMemBuf_free(&(pctx->mbufElemData)); pctx->bCollectElemData = 0; } // if(pctx->mbufElemData.pMem) #ifdef WITH_BASE64_HASHING_HACK } // else not base64 hack #endif } // else } //-------------------------------------------------- // handles the start of a element. // Adds a SignatureInfo struct to SignedDoc structure. // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartSignature(SigDocParse* pctx, const xmlChar **atts) { int i, j; SignatureInfo *pSignatureInfo; if(!pctx->pSigDoc || !pctx->pSigDoc->szFormat) { pctx->errcode = ERR_DIGIDOC_PARSE; addError(pctx->errcode, __FILE__, __LINE__, "Signature not in ddoc container!"); // ddocDebug(1, "handleStartSignature", "Signature has no ddoc container"); // SET_LAST_ERROR(ERR_DIGIDOC_PARSE); return; } for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { if(!strcmp((const char*)atts[i], "Id")) { memset(pctx->ctx1, 0, sizeof(pctx->ctx1)); memset(pctx->ctx2, 0, sizeof(pctx->ctx2)); memset(pctx->ctx3, 0, sizeof(pctx->ctx3)); strncpy(pctx->ctx1, (const char*)atts[i+1], /*sizeof(pctx->ctx1)-*/50); // check id uniqueness for(j = 0; j < getCountOfSignatures(pctx->pSigDoc); j++) { pSignatureInfo = getSignature(pctx->pSigDoc, j); if(pSignatureInfo && pSignatureInfo->szId && !strcmp(pSignatureInfo->szId, (const char*)atts[i+1])) { ddocDebug(1, "handleStartSignature", "Signature: %d has same id: %s", j, (const char*)atts[i+1]); SET_LAST_ERROR(ERR_DIGIDOC_PARSE); return; } } SignatureInfo_new(&pSignatureInfo, pctx->pSigDoc, (const char*)atts[i+1]); // MEMLEAK: ??? } } } //-------------------------------------------------- // handles the start of a element. // Records the reference URI attribute // pctx - pointer to XML parsing work-area // atts - attributes //-------------------------------------------------- void handleStartReference(SigDocParse* pctx, const xmlChar **atts) { strncpy(pctx->ctx2, ddocSaxParseFindAttrib(atts, "URI", ""), sizeof(pctx->ctx2)-1); } //-------------------------------------------------- // handles the start of a element. // Records the signature method // pctx - pointer to XML parsing work-area // atts - attributes //-------------------------------------------------- void handleStartSignatureMethod(SigDocParse* pctx, const xmlChar **atts) { SignatureInfo *pSigInfo; const char *alg; alg = ddocSaxParseFindAttrib(atts, "Algorithm", NULL); pSigInfo = ddocGetLastSignature(pctx->pSigDoc); if((alg != NULL) && (pSigInfo != NULL) && !strcmp(alg+strlen(alg)-8, "rsa-sha1") && (pctx->ctx1[0] == 'S')) { ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, SIGN_RSA_NAME, 0, 0); } #ifdef WITH_ECDSA else if((alg != NULL) && (pSigInfo != NULL) && !strcmp(alg+strlen(alg)-10, "ecdsa-sha1") && (pctx->ctx1[0] == 'S')) { ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, SIGN_ECDSA_NAME, 0, 0); } #endif } //-------------------------------------------------- // handles the start of a element. // Records the digest method // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartDigestMethod(SigDocParse* pctx, const xmlChar **atts) { SignatureInfo *pSigInfo; const char *alg; alg = ddocSaxParseFindAttrib(atts, "Algorithm", NULL); pSigInfo = ddocGetLastSignature(pctx->pSigDoc); if((alg != NULL) && (pSigInfo != NULL) && !strcmp(alg+strlen(alg)-4, "sha1")) strncpy(pctx->ctx3, DIGEST_SHA1_NAME, sizeof(pctx->ctx3)); else pctx->ctx3[0] = 0; } //-------------------------------------------------- // This function should be called at the end of // to determine the correct // types of CertID and CertValue objects. // pSigInfo - signature object //-------------------------------------------------- int selectCertIdAndValueTypes(SignatureInfo* pSigInfo) { int err = ERR_OK, i, j, l1; CertID* cid; CertValue *cval1, *cval2; X509* pCert; char buf1[300]; DigiDocMemBuf mbuf1, mbuf2; const DigiDocMemBuf *pMBuf = 0; RETURN_IF_NULL_PARAM(pSigInfo); mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; for(i = 0; pSigInfo->pCertIDs && i < ddocCertIDList_GetCertIDsCount(pSigInfo->pCertIDs); i++) { cid = ddocCertIDList_GetCertID(pSigInfo->pCertIDs, i); ddocDebug(3, "selectCertIdAndValueTypes", "CID type: %d serial %s - %s", cid->nType, cid->szIssuerSerial, cid->szIssuerName); if(cid && cid->nType == CERTID_TYPE_UNKNOWN) { ddocDebug(3, "selectCertIdAndValueTypes", "Find type for cid: %s - %s", cid->szIssuerSerial, cid->szIssuerName); // find corresponding CertValue cval1 = NULL; for(j = 0; pSigInfo->pCertValues && (j < ddocCertValueList_GetCertValuesCount(pSigInfo->pCertValues)); j++) { cval2 = ddocCertValueList_GetCertValue(pSigInfo->pCertValues, j); if(cval2) { pCert = ddocCertValue_GetCert(cval2); l1 = sizeof(buf1); memset(buf1, 0, l1); ReadCertSerialNumber(buf1, l1, pCert); //AM 19.09.08 if(cid->szIssuerSerial){ if(!strcmp(cid->szIssuerSerial, buf1)) { cval1 = cval2; break; // found it } } // should I check also hash value? } } // for certValues // if found matching CertID and CertValue if(cval1) { ddocDebug(3, "selectCertIdAndValueTypes", "CertID: %s - %s -> CertValue: %s", cid->szIssuerSerial, cid->szIssuerName, cval1->szId); // Test1: is this an OCSP responders cert? if(pSigInfo->pNotary) pMBuf = (DigiDocMemBuf*)ddocNotInfo_GetResponderId(pSigInfo->pNotary); if(pMBuf) { if(pSigInfo->pNotary->nRespIdType == RESPID_NAME_TYPE) { err = ddocCertGetSubjectCN(ddocCertValue_GetCert(cval1), &mbuf1); memset(buf1, 0, sizeof(buf1)); findCN((char*)pMBuf->pMem, buf1, sizeof(buf1)); // defined in DigiDocConfig.c if(!strcmp(buf1, (const char*)mbuf1.pMem)) { // yes this is a responders cert ddocDebug(3, "selectCertIdAndValueTypes", "cert: %s responder %s -> RESPONDER", (const char*)mbuf1.pMem, buf1); cid->nType = CERTID_TYPE_RESPONDERS_CERTID; cval1->nType = CERTID_VALUE_RESPONDERS_CERT; snprintf(buf1, sizeof(buf1), "%s-RESPONDERS_CERTINFO", pSigInfo->szId); ddocCertID_SetId(cid, buf1); } ddocMemBuf_free(&mbuf1); } // ByName if(pSigInfo->pNotary->nRespIdType == RESPID_KEY_TYPE) { err = ddocCertGetPubkeyDigest(ddocCertValue_GetCert(cval1), &mbuf1); l1 = sizeof(buf1); memset(buf1, 0, l1); bin2hex((const byte*)mbuf1.pMem, mbuf1.nLen, buf1, &l1); ddocDebug(3, "selectCertIdAndValueTypes", "cert hash: %s", buf1); l1 = sizeof(buf1); memset(buf1, 0, l1); bin2hex((const byte*)pMBuf->pMem, pMBuf->nLen, buf1, &l1); ddocDebug(3, "selectCertIdAndValueTypes", "respid: %s", buf1); ddocEncodeBase64(&mbuf1, &mbuf2); ddocMemBuf_free(&mbuf1); ddocEncodeBase64(pMBuf, &mbuf1); ddocDebug(3, "selectCertIdAndValueTypes", "cert: %s responder %s", (const char*)mbuf2.pMem, (const char*)mbuf1.pMem); if(!strcmp((const char*)mbuf2.pMem, (const char*)mbuf1.pMem)) { // yes this is a responders cert ddocDebug(3, "selectCertIdAndValueTypes", "cert: %s responder %s -> RESPONDER", (const char*)mbuf2.pMem, (const char*)mbuf1.pMem); cid->nType = CERTID_TYPE_RESPONDERS_CERTID; cval1->nType = CERTID_VALUE_RESPONDERS_CERT; snprintf(buf1, sizeof(buf1), "%s-RESPONDERS_CERTINFO", pSigInfo->szId); ddocCertID_SetId(cid, buf1); } ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); } // ByKey } // if pMBuf } } // for certids } return err; } //-------------------------------------------------- // handles the start of a element. // Records the OCSP response data // pctx - pointer to XML parsing work-area // name - tag name //-------------------------------------------------- // FIXME : error handling void handleEndEncapsulatedOCSPValue(SigDocParse* pctx) { OCSP_RESPONSE* pResp; NotaryInfo* pNotInfo = 0; SignatureInfo* pSig = 0; // convert the X509 cert data to // cert and replace the pointer value RETURN_VOID_IF_NULL(pctx->pSigDoc->szFormatVer); pNotInfo = ddocGetLastNotaryInfo(pctx->pSigDoc); RETURN_VOID_IF_NULL(pNotInfo); // VS: 1.76 correct the check pSig = ddocGetLastSignature(pctx->pSigDoc); RETURN_VOID_IF_NULL(pSig); /*pctx->errcode =*/ ddocDecodeOCSPResponsePEMData(&pResp, (const byte*)pctx->mbufElemData.pMem, (int)pctx->mbufElemData.nLen); // cleanup ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); if(pResp) { // in ver 1.2 we have correct OCSP digest // VS 1.76 - add 1.3 version too if(!strcmp(pctx->pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER) || !strcmp(pctx->pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) pctx->errcode = initializeNotaryInfoWithOCSP(pctx->pSigDoc, pNotInfo, pResp, ddocSigInfo_GetOCSPRespondersCert(pSig), 0); else // in older versions the digest was incorrect /*pctx->errcode =*/ initializeNotaryInfoWithOCSP(pctx->pSigDoc, pNotInfo, pResp, ddocSigInfo_GetOCSPRespondersCert(pSig), 1); OCSP_RESPONSE_free(pResp); } /*else checkErrors();*/ ddocDebug(3, "handleEndEncapsulatedOCSPValue", "RC: %d", pctx->errcode); if(pctx->errcode) return; // now we have OCSP value too // determine the correct types of certid and certvalue objects now /*pctx->errcode =*/ selectCertIdAndValueTypes(pSig); } //-------------------------------------------------- // handles the start of a element. // Records the id and target attributes // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartSignedProperties(SigDocParse* pctx, const xmlChar **atts) { if(!pctx->nIgnoreDataFile) ddocSaxParseStartCollecting(pctx, FLAG_SIG_PART, 0); strncpy(pctx->ctx2, ddocSaxParseFindAttrib(atts, "Id", ""), sizeof(pctx->ctx2)-1); strncpy(pctx->ctx3, ddocSaxParseFindAttrib(atts, "Target", ""), sizeof(pctx->ctx3)-1); } //-------------------------------------------------- // handles the end of a element. // Records the digest of this element // pctx - pointer to XML parsing work-area // name - tag name //-------------------------------------------------- void handleEndSignedProperties(SigDocParse* pctx) { char* pTmp2; char buf[DIGEST_LEN+3], buf2[40]; int l2; SignatureInfo* pSigInfo; DigiDocMemBuf mbuf1; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); if(pctx->mbufSigPartData.pMem && pSigInfo) { ddocDebug(5, "handleEndSignedProperties", "DATA: %d ->%s", pctx->mbufSigPartData.nLen, (char*)pctx->mbufSigPartData.pMem); ddocDebugWriteFile(4, "sigprop-can1.txt", &(pctx->mbufSigPartData)); pTmp2 = canonicalizeXML((char*)pctx->mbufSigPartData.pMem, pctx->mbufSigPartData.nLen); //dumpInFile("sigprop-can2.txt", pTmp2); if(pTmp2) { mbuf1.pMem = pTmp2; mbuf1.nLen = strlen(pTmp2); ddocDebugWriteFile(4, "sigprop-can2.txt", &mbuf1); ddocDebug(5, "handleEndSignedProperties", "HASH over: \n---\n%s\n---\n", pTmp2); SHA1_Init(&(pctx->sctx)); SHA1_Update(&(pctx->sctx), pTmp2, strlen(pTmp2)); SHA1_Final((unsigned char*)buf,&(pctx->sctx)); ddocSigInfo_SetSigPropRealDigest(pSigInfo, buf, DIGEST_LEN); l2 = 40; encode((const byte*)buf, DIGEST_LEN, (byte*)buf2, &l2); ddocDebug(5, "handleEndSignedProperties", "SigProp hash: %s", buf2); free(pTmp2); } ddocSaxParseEndCollecting(pctx, FLAG_SIG_PART, 0); pctx->checkUTF8 = 0; } } //-------------------------------------------------- // handles the start of a element. // Starts recording data for digest calculation // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartSignedInfo(SigDocParse* pctx) { if(!pctx->nIgnoreDataFile) { // mark the start of data collect mode pctx->errcode = ddocSaxParseStartCollecting(pctx, FLAG_SIG_PART, 0); pctx->checkUTF8 = 1; } } //-------------------------------------------------- // handles the end of a element. // Records the digest of this element // pctx - pointer to XML parsing work-area // name - tag name //-------------------------------------------------- void handleEndSignedInfo(SigDocParse* pctx) { char* pTmp; char buf[DIGEST_LEN+3]; SignatureInfo* pSigInfo; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); if(pctx->mbufSigPartData.pMem && pSigInfo) { ddocDebug(5, "handleEndSignedInfo", "DATA: %d ->%s", pctx->mbufSigPartData.nLen, (char*)pctx->mbufSigPartData.pMem); pTmp = canonicalizeXML((char*)pctx->mbufSigPartData.pMem, pctx->mbufSigPartData.nLen); ddocDebug(5, "handleEndSignedInfo", "CANONICALIZED: %d ->%s", strlen(pTmp), (char*)pTmp); if(pTmp) { SHA1_Init(&(pctx->sctx)); SHA1_Update(&(pctx->sctx), pTmp, strlen(pTmp)); SHA1_Final((unsigned char*)buf,&(pctx->sctx)); ddocSigInfo_SetSigInfoRealDigest(pSigInfo, buf, DIGEST_LEN); free(pTmp); } pctx->errcode = ddocSaxParseEndCollecting(pctx, FLAG_SIG_PART, 0); pctx->checkUTF8 = 0; } } //-------------------------------------------------- // handles the start of a element. // Records the id attribute // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartCert(SigDocParse* pctx, const xmlChar **atts) { char *p = 0, buf1[50]; SignatureInfo* pSigInfo = NULL; CertID *pCertID = NULL; // used in old formats p = (char*)ddocSaxParseFindAttrib(atts, "Id", NULL); if(p) strncpy(pctx->ctx2, p, sizeof(pctx->ctx2)-1); pSigInfo = ddocGetLastSignature(pctx->pSigDoc); ddocDebug(3, "handleStartCert", "Sig: %s", (pSigInfo ? pSigInfo->szId : "NULL")); RETURN_VOID_IF_NULL(pSigInfo); // only if we are in Notary since signers cert-id is handled by if(pSigInfo->pNotary) { // don't know what cert-id it's going to be ddocCertID_new(&pCertID, CERTID_TYPE_UNKNOWN, 0, 0, 0, 0, 0); if(!pSigInfo->pCertIDs) ddocCertIDList_new(&(pSigInfo->pCertIDs)); ddocCertIDList_addCertID(pSigInfo->pCertIDs, pCertID); snprintf(buf1, sizeof(buf1), "%s-UNKNOWN_CERTINFO", pSigInfo->szId); strncpy(pctx->ctx2, buf1, sizeof(pctx->ctx2)-1); } } //-------------------------------------------------- // handles the start of a element. // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartSigningCertificate(SigDocParse* pctx) { SignatureInfo* pSigInfo = NULL; CertID *pCertID = NULL; X509* x509 = NULL; int ret = 0; DigiDocMemBuf mbuf1, mbuf2; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); ddocDebug(3, "handleStartSigningCertificate", "Sig: %s", (pSigInfo ? pSigInfo->szId : "NULL")); RETURN_VOID_IF_NULL(pSigInfo); pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSigInfo, CERTID_TYPE_SIGNERS_CERTID); snprintf(pctx->ctx2, sizeof(pctx->ctx2)-1, "%s-CERTINFO", pSigInfo->szId); x509 = ddocSigInfo_GetSignersCert(pSigInfo); if(x509){ ret = ddocCertGetIssuerDN(x509, &mbuf1); if(ret == 0) { if(pCertID && mbuf1.pMem) ddocCertID_SetIssuerName(pCertID, (char*)mbuf1.pMem); } } } //-------------------------------------------------- // handles the start of a element. // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartUnsignedSignatureProperties(SigDocParse* pctx) { SignatureInfo* pSigInfo = NULL; NotaryInfo *pNotaryInfo; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); ddocDebug(3, "handleStartUnsignedSignatureProperties", "Sig: %s", (pSigInfo ? pSigInfo->szId : "NULL")); RETURN_VOID_IF_NULL(pSigInfo); (void)NotaryInfo_new(&pNotaryInfo, pctx->pSigDoc, pSigInfo); } //-------------------------------------------------- // handles the start of a element. // Records the signature id so that we can later // capture responders cert digest // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartCompleteCertificateRefs(SigDocParse* pctx) { SignatureInfo* pSigInfo = 0; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); ddocDebug(3, "handleStartCompleteCertificateRefs", "Sig: %s", (pSigInfo ? pSigInfo->szId : "NULL")); RETURN_VOID_IF_NULL(pSigInfo); snprintf(pctx->ctx2, sizeof(pctx->ctx2)-1, "%s-RESPONDER_CERTINFO", pSigInfo->szId); } //-------------------------------------------------- // handles the start of a element. // Records the id attribute // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartOCSPIdentifier(SigDocParse* pctx, const xmlChar **atts) { strncpy(pctx->ctx2, ddocSaxParseFindAttrib(atts, "URI", ""), sizeof(pctx->ctx2)-1); } //-------------------------------------------------- // handles the start of a element. // Records the digest method // pctx - pointer to XML parsing work-area // name - tag name //-------------------------------------------------- void handleEndX509Certificate(SigDocParse* pctx) { X509* x509 = 0; SignatureInfo* pSigInfo = 0; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); // convert the X509 cert data to // cert and replace the pointer value if(pSigInfo && pctx->mbufElemData.pMem) { pctx->errcode = ddocDecodeX509PEMData(&x509, (const char*)pctx->mbufElemData.pMem, (int)pctx->mbufElemData.nLen); if(x509) ddocSigInfo_SetSignersCert(pSigInfo, x509); // cleanup pctx->errcode = ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); } } //-------------------------------------------------- // handles the start of a element. // Records the signature id so that we can later // capture responders cert digest // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleStartEncapsulatedX509Certificate(SigDocParse* pctx, const xmlChar **atts) { SignatureInfo* pSigInfo = 0; const char *p1 = 0; CertValue *pCertValue; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); p1 = ddocSaxParseFindAttrib(atts, "Id", NULL); ddocDebug(3, "handleStartEncapsulatedX509Certificate", "Sig: %s, type: %s", (pSigInfo ? pSigInfo->szId : "NULL"), (p1 ? p1 : "NULL")); RETURN_VOID_IF_NULL(pSigInfo); if(p1) { if(strstr(p1, "TSA_CERT")) pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_TSA_CERT); if(strstr(p1, "RESPONDER_CERT")) pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_RESPONDERS_CERT); } snprintf(pctx->ctx2, sizeof(pctx->ctx2)-1, "%s-RESPONDER_CERTINFO", pSigInfo->szId); pctx->errcode = ddocSaxParseStartCollecting(pctx, FLAG_XML_ELEM, 1); } //-------------------------------------------------- // handles the end of a element. // Records the digest method // pctx - pointer to XML parsing work-area // name - tag name //-------------------------------------------------- void handleEndEncapsulatedX509Certificate(SigDocParse* pctx) { X509* x509 = 0; NotaryInfo* pNotInf = 0; SignatureInfo* pSigInfo = 0; CertValue* pCertValue = 0; // convert the X509 cert data to cert< pNotInf = ddocGetLastNotaryInfo(pctx->pSigDoc); pSigInfo = ddocGetLastSignature(pctx->pSigDoc); pctx->errcode = ddocDecodeX509PEMData(&x509, (const char*)pctx->mbufElemData.pMem, (int)pctx->mbufElemData.nLen); if(x509 && pSigInfo) { pCertValue = ddocSigInfo_GetLastCertValue(pSigInfo); if(pCertValue) ddocCertValue_SetCert(pCertValue, x509); else X509_free(x509); // not found, free it } // cleanup ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); } char* PATH_DIGEST_VALUE_SIGNED_INFO = "/SignedDoc/Signature/SignedInfo/Reference"; char* PATH_DIGEST_VALUE_SIG_CERT = "/SignedDoc/Signature/Object/QualifyingProperties/SignedProperties/SignedSignatureProperties/SigningCertificate/Cert/CertDigest"; char* PATH_DIGEST_VALUE_CERT_REF = "/SignedDoc/Signature/Object/QualifyingProperties/UnsignedProperties/UnsignedSignatureProperties/CompleteCertificateRefs/CertRefs/Cert/CertDigest"; char* PATH_DIGEST_VALUE_CERT_REF_1_0 = "/SignedDoc/Signature/Object/QualifyingProperties/UnsignedProperties/UnsignedSignatureProperties/CompleteCertificateRefs/Cert/CertDigest"; char* PATH_DIGEST_VALUE_RVOK_REFS = "/SignedDoc/Signature/Object/QualifyingProperties/UnsignedProperties/UnsignedSignatureProperties/CompleteRevocationRefs/OCSPRefs/OCSPRef/DigestAlgAndValue"; int checkValidDigestValPath(SigDocParse* pctx, SignatureInfo* pSigInfo) { if(pctx && pctx->mbufTags.pMem) { if(!strcmp((const char*)pctx->mbufTags.pMem, PATH_DIGEST_VALUE_CERT_REF_1_0)) { pSigInfo->nErr1 = ERR_VER_1_0; ddocDebug(1, "VER 1.0", "Ver 1.0 signature! Found element DigestValue in path: %s format: %s ver: %s", (const char*)pctx->mbufTags.pMem, pctx->pSigDoc->szFormat, pctx->pSigDoc->szFormatVer); if(strcmp(pctx->pSigDoc->szFormat, SK_XML_1_NAME) && (strcmp(pctx->pSigDoc->szFormat, DIGIDOC_XML_1_1_NAME) || !strcmp(pctx->pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER))) { ddocDebug(1, "checkValidDigestValPath10-12", "Invalid XML! Found element DigestValue in path: %s format: %s ver: %s", (const char*)pctx->mbufTags.pMem, pctx->pSigDoc->szFormat, pctx->pSigDoc->szFormatVer); SET_LAST_ERROR(ERR_DIGIDOC_PARSE); if(pSigInfo && !pSigInfo->nErr1) pSigInfo->nErr1 = ERR_DIGIDOC_PARSE; return ERR_DIGIDOC_PARSE; } } else { if(strcmp((const char*)pctx->mbufTags.pMem, PATH_DIGEST_VALUE_SIGNED_INFO) && strcmp((const char*)pctx->mbufTags.pMem, PATH_DIGEST_VALUE_SIG_CERT) && strcmp((const char*)pctx->mbufTags.pMem, PATH_DIGEST_VALUE_CERT_REF) && strcmp((const char*)pctx->mbufTags.pMem, PATH_DIGEST_VALUE_RVOK_REFS)) { ddocDebug(1, "checkValidDigestValPath", "Invalid XML! Found element DigestValue in path: %s format: %s ver: %s", (const char*)pctx->mbufTags.pMem, pctx->pSigDoc->szFormat, pctx->pSigDoc->szFormatVer); SET_LAST_ERROR(ERR_DIGIDOC_PARSE); if(pSigInfo && !pSigInfo->nErr1) pSigInfo->nErr1 = ERR_DIGIDOC_PARSE; return ERR_DIGIDOC_PARSE; } } } return 0; } char* PATH_CLAIMED_ROLE = "/SignedDoc/Signature/Object/QualifyingProperties/SignedProperties/SignedSignatureProperties/SignerRole/ClaimedRoles"; int checkValidClaimedRolePath(SigDocParse* pctx, SignatureInfo* pSigInfo) { if(pctx && pctx->mbufTags.pMem) { if(strcmp((const char*)pctx->mbufTags.pMem, PATH_CLAIMED_ROLE)) { ddocDebug(1, "checkValidClaimedRolePath", "Invalid XML! Found element ClaimedRole in path: %s", (const char*)pctx->mbufTags.pMem); SET_LAST_ERROR(ERR_DIGIDOC_PARSE); if(pSigInfo && !pSigInfo->nErr1) pSigInfo->nErr1 = ERR_DIGIDOC_PARSE; return ERR_DIGIDOC_PARSE; } } return 0; } //-------------------------------------------------- // handles the content of a element. // Decodes and reads in digest value // pctx - pointer to XML parsing work-area // name - tag name // atts - attributes //-------------------------------------------------- void handleEndDigestValue(SigDocParse* pctx) { char id[100], type[100]; SignatureInfo* pSigInfo = NULL; NotaryInfo* pNotInfo = NULL; DocInfo* pDocInfo = NULL; CertID* pCertID = NULL; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); ddocDebug(4, "handleDigestValue", "DF: %s value: %s len: %d", pctx->ctx2, (char*)pctx->mbufElemData.pMem, pctx->mbufElemData.nLen); // decode digest value ddocDecodeBase64(&(pctx->mbufElemData), &mbuf1); ddocDebug(4, "handleDigestValue", "decoded len: %ld", mbuf1.nLen); // cleanup ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); // find current signature pSigInfo = ddocGetLastSignature(pctx->pSigDoc); RETURN_VOID_IF_NULL(pSigInfo); if(checkValidDigestValPath(pctx, pSigInfo)) return; decodeURI(pctx->ctx2, id, sizeof(id), type, sizeof(type)); ddocDebug(4, "handleDigestValue", "ctx2: %s id: %s type: %s", pctx->ctx2, id, type); if(id[0] == 'D' || !strcmp(id, "null")) { RETURN_VOID_IF_NULL(pSigInfo); pDocInfo = getDocInfoWithId(pSigInfo, id); if(!strcmp(type, "MimeType") || !strcmp(type, "MIME")) { if(pDocInfo == NULL) { addDocInfo(&pDocInfo, pSigInfo, id, pctx->ctx3, NULL, 0, (const byte*)mbuf1.pMem, mbuf1.nLen); } else setDocInfoMimeDigest(pDocInfo, (const byte*)mbuf1.pMem, mbuf1.nLen); } else { if(pDocInfo == NULL) { addDocInfo(&pDocInfo, pSigInfo, id, pctx->ctx3, (const byte*)mbuf1.pMem, mbuf1.nLen, NULL, 0); // MEMLEAK: ??? } else setDocInfoDigest(pDocInfo, (const byte*)mbuf1.pMem, mbuf1.nLen, pctx->ctx3); } } if(id[0] == 'S') { if(!strcmp(type, "SignedProperties")) { RETURN_VOID_IF_NULL(pSigInfo); ddocSigInfo_SetSigPropDigest(pSigInfo, (const char*)mbuf1.pMem, mbuf1.nLen); } if(!strcmp(type, "CERTINFO")) { RETURN_VOID_IF_NULL(pSigInfo); pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSigInfo, CERTID_TYPE_SIGNERS_CERTID); RETURN_VOID_IF_NULL(pCertID); ddocCertID_SetDigestValue(pCertID, (const char*)mbuf1.pMem, mbuf1.nLen); } if(!strcmp(type, "UNKNOWN_CERTINFO")) { pCertID = ddocCertIDList_GetLastCertID(pSigInfo->pCertIDs); RETURN_VOID_IF_NULL(pCertID); ddocCertID_SetDigestValue(pCertID, (const char*)mbuf1.pMem, mbuf1.nLen); } } if(id[0] == 'N') { pNotInfo = getNotaryWithId(pctx->pSigDoc, id); SET_LAST_ERROR_RETURN_VOID_IF_NOT(pNotInfo, ERR_OCSP_WRONG_RESPID); ddocNotInfo_SetOcspDigest(pNotInfo, (const char*)mbuf1.pMem, mbuf1.nLen); } ddocMemBuf_free(&mbuf1); } //-------------------------------------------------- // handles the content of a element. // Reads in timestamp data // pctx - pointer to XML parsing work-area // value - character values read from file // len - length of chars ??? //-------------------------------------------------- void handleEndSigningTime(SigDocParse* pctx) { SignatureInfo *pSigInfo; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); RETURN_VOID_IF_NULL(pSigInfo); if(pctx->mbufElemData.pMem) { setString(&(pSigInfo->szTimeStamp), (char*)pctx->mbufElemData.pMem, -1); ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); } } #define ADR_ENTRY_CITY 1 #define ADR_ENTRY_STATE 2 #define ADR_ENTRY_COUNTRY 3 #define ADR_ENTRY_ZIP 4 //-------------------------------------------------- // Handles address entry // pctx - pointer to XML parsing work-area // // value - character values read from file // len - length of chars ??? //-------------------------------------------------- void handleAdrEntry(SigDocParse* pctx, int nAdr) { SignatureInfo* pSigInfo; pSigInfo = ddocGetLastSignature(pctx->pSigDoc); if(pSigInfo && pctx->mbufElemData.pMem) { switch(nAdr) { case ADR_ENTRY_CITY: setString(&(pSigInfo->sigProdPlace.szCity), (const char*)pctx->mbufElemData.pMem, -1); break; case ADR_ENTRY_STATE: setString(&(pSigInfo->sigProdPlace.szStateOrProvince), (const char*)pctx->mbufElemData.pMem, -1); break; case ADR_ENTRY_COUNTRY: setString(&(pSigInfo->sigProdPlace.szCountryName), (const char*)pctx->mbufElemData.pMem, -1); break; case ADR_ENTRY_ZIP: setString(&(pSigInfo->sigProdPlace.szPostalCode), (const char*)pctx->mbufElemData.pMem, -1); break; } } ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); } //-------------------------------------------------- // handles the start of a element. // Stores the collected claimed role // pctx - pointer to XML parsing work-area // name - tag name //-------------------------------------------------- void handleEndClaimedRole(SigDocParse* pctx) { SignatureInfo* pSigInfo; if(pctx->mbufElemData.pMem) { pSigInfo = ddocGetLastSignature(pctx->pSigDoc); if(checkValidClaimedRolePath(pctx, pSigInfo)) return; RETURN_VOID_IF_NULL(pSigInfo); addSignerRole(pSigInfo, 0, (const char*)pctx->mbufElemData.pMem, -1, 0); ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); pctx->bNoXMLElemData = 0; } } //-------------------------------------------------- // handles the start of a element. // Stores the collected certified role // pctx - pointer to XML parsing work-area // name - tag name //-------------------------------------------------- void handleEndCertifiedRole(SigDocParse* pctx) { SignatureInfo* pSigInfo; if(pctx->mbufElemData.pMem) { pSigInfo = ddocGetLastSignature(pctx->pSigDoc); RETURN_VOID_IF_NULL(pSigInfo); addSignerRole(pSigInfo, 1, (const char*)pctx->mbufElemData.pMem, -1, 0); ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); } } //-------------------------------------------------- // handles the end of a element. // Reads in cert isseur serial number // pctx - pointer to XML parsing work-area // value - character values read from file // len - length of chars ??? //-------------------------------------------------- void handleEndIssuerSerial(SigDocParse* pctx) { SignatureInfo* pSigInfo; char id[20], type[20]; CertID* pCertID; decodeURI(pctx->ctx2, id, sizeof(id), type, sizeof(type)); if(!strcmp(type, "CERTINFO")) { pSigInfo = ddocGetLastSignature(pctx->pSigDoc); pCertID = ddocSigInfo_GetCertIDOfType(pSigInfo, CERTID_TYPE_SIGNERS_CERTID); if(pCertID && pctx->mbufElemData.pMem) ddocCertID_SetIssuerSerial(pCertID, (char*)pctx->mbufElemData.pMem); } if(!strcmp(type, "UNKNOWN_CERTINFO")) { pSigInfo = ddocGetLastSignature(pctx->pSigDoc); pCertID = ddocCertIDList_GetLastCertID(pSigInfo->pCertIDs); if(pCertID && pctx->mbufElemData.pMem) ddocCertID_SetIssuerSerial(pCertID, (char*)pctx->mbufElemData.pMem); } ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); } //-------------------------------------------------- // handles the end of a element. // Reads in cert isseur serial number // pctx - pointer to XML parsing work-area // value - character values read from file // len - length of chars ??? //-------------------------------------------------- void handleEndIssuerName(SigDocParse* pctx) { SignatureInfo* pSigInfo; char id[20], type[20]; CertID* pCertID; decodeURI(pctx->ctx2, id, sizeof(id), type, sizeof(type)); if(!strcmp(type, "CERTINFO")) { pSigInfo = ddocGetLastSignature(pctx->pSigDoc); pCertID = ddocSigInfo_GetCertIDOfType(pSigInfo, CERTID_TYPE_SIGNERS_CERTID); ddocDebug(3, "handleEndIssuerName", "Issuer name: %s", pctx->mbufElemData.pMem); if(pCertID && pctx->mbufElemData.pMem) ddocCertID_SetIssuerName(pCertID, (char*)pctx->mbufElemData.pMem); } if(!strcmp(type, "UNKNOWN_CERTINFO")) { pSigInfo = ddocGetLastSignature(pctx->pSigDoc); pCertID = ddocCertIDList_GetLastCertID(pSigInfo->pCertIDs); if(pCertID && pctx->mbufElemData.pMem) ddocCertID_SetIssuerName(pCertID, (char*)pctx->mbufElemData.pMem); } ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); } //-------------------------------------------------- // tests if this is a textform responder id // we base the test on existence of certain // key elements in a DN. // return 1 if it is text form //-------------------------------------------------- int isTextResponderId(const char* szRespId) { return strstr(szRespId, "CN=") && strstr(szRespId, "C="); } //-------------------------------------------------- // handles the end of a or element. // Reads in ResponderId data // pctx - pointer to XML parsing work-area // value - character values read from file // len - length of chars ??? //-------------------------------------------------- void handleEndResponderID(SigDocParse* pctx) { NotaryInfo* pNotInf; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; RETURN_VOID_IF_NULL(pctx->pSigDoc->szFormatVer); pNotInf = ddocGetLastNotaryInfo(pctx->pSigDoc); ddocDebug(3, "handleEndResponderId", "notary: %s id: %s, len: %d", (pNotInf ? pNotInf->szId : "NULL"), (const char*)pctx->mbufElemData.pMem, pctx->mbufElemData.nLen); if(pNotInf && pctx->mbufElemData.pMem) { // in earlier format we din't have and // so we must detect if this is text or base64 if(isTextResponderId((const char*)pctx->mbufElemData.pMem)) { pctx->errcode = ddocNotInfo_SetResponderId(pNotInf, (const char*)pctx->mbufElemData.pMem, pctx->mbufElemData.nLen); pNotInf->nRespIdType = RESPID_NAME_TYPE; } else { ddocDecodeBase64Data(pctx->mbufElemData.pMem, pctx->mbufElemData.nLen, &mbuf1); pctx->errcode = ddocNotInfo_SetResponderId(pNotInf, (const char*)mbuf1.pMem, mbuf1.nLen); pNotInf->nRespIdType = RESPID_KEY_TYPE; } pctx->errcode = ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); } } //-------------------------------------------------- // handles the end of a // Reads in OCSP ProducedAt timestamp // pctx - pointer to XML parsing work-area // value - character values read from file // len - length of chars ??? //-------------------------------------------------- void handleEndProducedAt(SigDocParse* pctx) { NotaryInfo* pNotInf = NULL; RETURN_VOID_IF_NULL(pctx->pSigDoc); pNotInf = ddocGetLastNotaryInfo(pctx->pSigDoc); RETURN_VOID_IF_NULL(pNotInf); ddocDebug(3, "handleEndProducedAt", "notary: %s produced at: %s len: %d", (pNotInf ? pNotInf->szId : "NULL"), (const char*)pctx->mbufElemData.pMem, pctx->mbufElemData.nLen); if(pNotInf && pctx->mbufElemData.pMem) { setString(&(pNotInf->szProducedAt), (const char*)pctx->mbufElemData.pMem, -1 /* pctx->mbufElemData.nLen*/); pctx->errcode = ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); } } //-------------------------------------------------- // handles the end of a element. // Reads in ResponderId data // pctx - pointer to XML parsing work-area // value - character values read from file // len - length of chars ??? //-------------------------------------------------- void handleEndByKey(SigDocParse* pctx) { NotaryInfo* pNotInf; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; pNotInf = ddocGetLastNotaryInfo(pctx->pSigDoc); ddocDebug(3, "handleEndByKey", "notary: %s id: %s, len: %d", (pNotInf ? pNotInf->szId : "NULL"), (const char*)pctx->mbufElemData.pMem, pctx->mbufElemData.nLen); if(pNotInf && pctx->mbufElemData.pMem) { ddocDecodeBase64Data(pctx->mbufElemData.pMem, pctx->mbufElemData.nLen, &mbuf1); pctx->errcode = ddocNotInfo_SetResponderId(pNotInf, (const char*)mbuf1.pMem, mbuf1.nLen); pctx->errcode = ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); pNotInf->nRespIdType = RESPID_KEY_TYPE; } ddocMemBuf_free(&mbuf1); } //-------------------------------------------------- // handles the end of a element.< // Decodes the base64 data in a buffer and assigns // to signature value // pctx - pointer to XML parsing work-area // name - tag name //-------------------------------------------------- void handleEndSignatureValue(SigDocParse* pctx) { SignatureInfo* pSigInfo; DigiDocMemBuf mbuf1, mbuf2; char *p1 = 0, *p2 = 0; int l1; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; RETURN_VOID_IF_NULL(pctx->pSigDoc->szFormatVer); pSigInfo = ddocGetLastSignature(pctx->pSigDoc); // decode signature value p1 = strchr((const char*)pctx->mbufElemData.pMem, '>'); if(p1) p2 = strchr((const char*)p1, '<'); if(p1 && p2) { p1++; *p2 = 0; l1 = strlen(p1) + 10; ddocMemSetLength(&mbuf1, l1); decode((const byte*)p1, strlen(p1), (byte*)mbuf1.pMem, &l1); mbuf1.nLen = l1; if(pSigInfo && mbuf1.nLen > 0) ddocSigInfo_SetSignatureValue(pSigInfo, (char*)mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); } // cleanup ddocSaxParseEndCollecting(pctx, FLAG_TS_INP, 0); } //-------------------------------------------------- // Collects elements start-tag // pctx - pointer to XML parsing work-area // name - xml element tag name // atts - xml atributes // pcFlag - pointer to flag governing collection of this element // pMBuf - DigiDocMemBuf to collect it in //-------------------------------------------------- int ddocSaxParseCollectStartTag(SigDocParse* pctx, const xmlChar *name, const xmlChar **atts, char *pcFlag, DigiDocMemBuf* pMBuf) { int i, addXmlns = 0, addXmlns3 = 0; char *p = 0; // if we are in collect data mode then // record this tag data if(*pcFlag) { // don't use this attribute for 1.0 format if(pctx->pSigDoc->szFormatVer && (!strcmp(pctx->pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pctx->pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) && (!strcmp((const char*)name, "SignedProperties") || !strcmp((const char*)name, "SignedInfo"))) // must have this attribute addXmlns = 1; else addXmlns = 0; // don't need this atribute ddocDebug(3, "ddocSaxParseCollectStartTag", "Format: %s name: %s", pctx->pSigDoc->szFormatVer, (const char*)name); if(pctx->pSigDoc->szFormatVer && !strcmp((const char*)name, "DataFile")) { if(!strcmp(pctx->pSigDoc->szFormatVer, DIGIDOC_XML_1_3_VER)) // must have this attribute addXmlns3 = 1; } pctx->errcode = ddocMemAppendData(pMBuf, "<", -1); if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, (const char*)name, -1); for (i = 0; !pctx->errcode && (atts != NULL) && (atts[i] != NULL); i += 2) { pctx->errcode = ddocMemAppendData(pMBuf, " ", -1); if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, (const char*)atts[i], -1); if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, "=\"", -1); if(!pctx->errcode) { escapeXMLSymbols((const char*)atts[i+1], -1, &p); if(p) { pctx->errcode = ddocMemAppendData(pMBuf, p, -1); free(p); } } if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, "\"", -1); if(!strcmp((const char*)atts[i], "xmlns")) { addXmlns = 0; // already has this atribute addXmlns3 = 0; } } // for if(addXmlns && !pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, " xmlns=\"http://www.w3.org/2000/09/xmldsig#\"", -1); if(addXmlns3 && !pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, " xmlns=\"http://www.sk.ee/DigiDoc/v1.3.0#\"", -1); if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, ">", -1); ddocDebug(3, "ddocSaxParseCollectStartTag", "Element tag collected: %d - %s", pMBuf->nLen, (char*)pMBuf->pMem); } return pctx->errcode; } //-------------------------------------------------- // Collects elements start-tag. Used for ddoc 1.3 alternate DataFile hash calc // pctx - pointer to XML parsing work-area // name - xml element tag name // atts - xml atributes // pMBuf - DigiDocMemBuf to collect it in //-------------------------------------------------- int ddocSaxParseCollectDf3AltStartTag(SigDocParse* pctx, const xmlChar *name, const xmlChar **atts, DigiDocMemBuf* pMBuf) { int i; char *p = 0; // if we are in collect data mode then // record this tag data pctx->errcode = ddocMemAppendData(pMBuf, "<", -1); if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, (const char*)name, -1); for (i = 0; !pctx->errcode && (atts != NULL) && (atts[i] != NULL); i += 2) { pctx->errcode = ddocMemAppendData(pMBuf, " ", -1); if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, (const char*)atts[i], -1); if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, "=\"", -1); if(!pctx->errcode) { escapeXMLSymbols((const char*)atts[i+1], -1, &p); if(p) { pctx->errcode = ddocMemAppendData(pMBuf, p, -1); free(p); } } if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, "\"", -1); } // for if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, ">", -1); ddocDebug(3, "ddocSaxParseCollectDf3AltStartTag", "Element tag collected: %d - %s", pMBuf->nLen, (char*)pMBuf->pMem); return pctx->errcode; } /** * startElementHandler: * @ctxt: An XML parser context * @name: The element name * * called when an opening tag has been processed. */ static void startElementHandler(void *ctx, const xmlChar *name, const xmlChar **atts) { SigDocParse* pctx = (SigDocParse*)ctx; char *pTmp1 = NULL; const char *sXmlns; DigiDocMemBuf mbuf1, mbuf2; SignatureInfo* pSig; XmlElemInfo* eEl = NULL; mbuf2.pMem = 0; mbuf2.nLen = 0; strncpy(pctx->tag, (const char*)name, sizeof(pctx->tag)); XmlElemInfo_new(&eEl, NULL, (const char*)name); if(!pctx->eRoot) pctx->eRoot = eEl; if(pctx->eCurr) { XmlElemInfo_addChild(pctx->eCurr, eEl); } pctx->eCurr = eEl; pctx->errcode = validateElementPath(pctx->eCurr); // do nothing if error has ocurred if(pctx->errcode) return; ddocMemPush(&(pctx->mbufTags), (const char*)name); ddocDebug(4, "startElementHandler", "<%s> path: %s", (const char*)name, (const char*)pctx->mbufTags.pMem); //printf("<%s>\n", (const char*)name); if(!strcmp((const char*)name, "DataFile")) { pctx->bCollectDFData++; // increment bypass mode if(pctx->bCollectDFData == 1) // only the first time handleStartDataFile(pctx, name, atts); // collect wrong/alternate digest for ddoc 1.3 ddocSaxParseCollectDf3AltStartTag(pctx, name, atts, &mbuf2); } if(!strcmp((const char*)name, "SignedProperties")) handleStartSignedProperties(pctx, atts); if(!strcmp((const char*)name, "SignedInfo")) handleStartSignedInfo(pctx); // if we are not in a and we encounter // the tag then start collecting original content if(!pctx->nIgnoreDataFile && (!strcmp((const char*)name, "Signature") || pctx->bCollectSigData)) { if(!strcmp((const char*)name, "Signature")) pctx->errcode = ddocSaxParseStartCollecting(pctx, FLAG_SIGNATURE, 0); // collect general data< ddocSaxParseCollectStartTag(pctx, name, atts, &(pctx->bCollectSigData), &(pctx->mbufSigData)); } // we need the tags here because of hash value calculation // collect general tag data if(!strcmp((const char*)name, "SignatureValue")) pctx->errcode = ddocSaxParseStartCollecting(pctx, FLAG_XML_ELEM, 0); ddocSaxParseCollectStartTag(pctx, name, atts, &(pctx->bCollectElemData), &(pctx->mbufElemData)); // use base64 DataFile parsing optimization // only possible if: a) not 1.0 format b) base64 content c) check config settings #ifdef WITH_BASE64_HASHING_HACK if((pctx->bCollectDFData == 1) && pctx->pSigDoc->szFormatVer && pctx->pSigDoc->szFormat && (strcmp(pctx->pSigDoc->szFormatVer, SK_XML_1_VER) && strcmp(pctx->pSigDoc->szFormat, SK_XML_1_NAME))&& !strcmp(pctx->ctx3, CONTENT_EMBEDDED_BASE64) ) { // append end tag ddocMemAppendData(&(pctx->mbufElemData), "", -1); pTmp1 = canonicalizeXML((char*)pctx->mbufElemData.pMem, pctx->mbufElemData.nLen); if(pTmp1) { // remove end tag again after canonicalization pTmp1[strlen(pTmp1) - 11] = 0; ddocDebug(4, "startElementHandler", "Initial sha1 update: \'%s\'", pTmp1); mbuf1.pMem = pTmp1; mbuf1.nLen = strlen(pTmp1); ddocDebugWriteFile(4, "df-data.txt", &mbuf1); SHA1_Update(&(pctx->sctx), pTmp1, strlen(pTmp1)); free(pTmp1); pTmp1 = NULL; } // handle alternate digest ddocMemAppendData(&mbuf2, "", -1); pTmp1 = canonicalizeXML((char*)mbuf2.pMem, mbuf2.nLen); if(pTmp1) { // remove end tag again after canonicalization pTmp1[strlen(pTmp1) - 11] = 0; ddocDebug(4, "startElementHandler", "Initial alt sha1 update: \'%s\'", pTmp1); SHA1_Update(&(pctx->sctx2), pTmp1, strlen(pTmp1)); free(pTmp1); } ddocMemBuf_free(&(pctx->mbufElemData)); } #endif if(mbuf2.pMem) ddocMemBuf_free(&mbuf2); // collect general data ddocSaxParseCollectStartTag(pctx, name, atts, &(pctx->bCollectSigPartData), &(pctx->mbufSigPartData)); // check other start-tag-actions if(!pctx->nIgnoreDataFile) { if(!strcmp((const char*)name, "SignedDoc")) handleStartSignedDoc(pctx, name, atts); if(!strcmp((const char*)name, "Signature")) handleStartSignature(pctx, atts); if(!strcmp((const char*)name, "Reference")) handleStartReference(pctx, atts); if(!strcmp((const char*)name, "SignatureMethod")) handleStartSignatureMethod(pctx, atts); if(!strcmp((const char*)name, "DigestMethod")) handleStartDigestMethod(pctx, atts); if(!strcmp((const char*)name, "Cert")) handleStartCert(pctx, atts); /*if(!strcmp((const char*)name, "ResponderID")) // TODO: do we need it ??? handleStartResponderId(pctx, name, atts);*/ /* if(!strcmp((const char*)name, "Certificate")) // TODO: do we need it ??? handleStartCertificate(pctx, name, atts);*/ if(!strcmp((const char*)name, "UnsignedSignatureProperties")) handleStartUnsignedSignatureProperties(pctx); if(!strcmp((const char*)name, "OCSPIdentifier")) handleStartOCSPIdentifier(pctx, atts); if(!strcmp((const char*)name, "SigningCertificate")) handleStartSigningCertificate(pctx); if(!strcmp((const char*)name, "CompleteCertificateRefs")) handleStartCompleteCertificateRefs(pctx); if(!strcmp((const char*)name, "EncapsulatedX509Certificate")) handleStartEncapsulatedX509Certificate(pctx, atts); // start collecting but release old if exists if(!strcmp((const char*)name, "X509SerialNumber") || !strcmp((const char*)name, "X509IssuerName")) { // check xmlns sXmlns = ddocSaxParseFindAttrib(atts, "xmlns", NULL); if(sXmlns == NULL || strcmp(sXmlns, NAMESPACE_XML_DSIG)) { ddocDebug(1, "startElementHandler", "Invalid namespace %s for element: %s", sXmlns, name); SET_LAST_ERROR(ERR_ISSUER_XMLNS); //pctx->errcode = ERR_ISSUER_XMLNS; pSig = ddocGetLastSignature(pctx->pSigDoc); if(pSig && !pSig->nErr1) pSig->nErr1 = ERR_ISSUER_XMLNS; // store this erro code by signature because it can't be found after parsing } ddocSaxParseEndCollecting(pctx, FLAG_XML_ELEM, 0); pctx->errcode = ddocSaxParseStartCollecting(pctx, FLAG_XML_ELEM, 1); } // start collecting but release old if exists if((!strcmp((const char*)name, "Transform") || !strcmp((const char*)name, "Transforms")) && pctx->pSigDoc->szFormat && !strcmp(pctx->pSigDoc->szFormat, DIGIDOC_XML_1_1_NAME)) { SET_LAST_ERROR(ERR_TRANSFORM_UNSUPPORTED); pSig = ddocGetLastSignature(pctx->pSigDoc); if(pSig && !pSig->nErr1) pSig->nErr1 = ERR_TRANSFORM_UNSUPPORTED; // store this erro code } // start collecting data of these elements if(!strcmp((const char*)name, "CertifiedRole") || !strcmp((const char*)name, "ClaimedRole") || !strcmp((const char*)name, "DigestValue") || !strcmp((const char*)name, "EncapsulatedOCSPValue") || !strcmp((const char*)name, "EncapsulatedTimeStamp") || !strcmp((const char*)name, "X509Certificate") || !strcmp((const char*)name, "SigningTime") || !strcmp((const char*)name, "ResponderID") || !strcmp((const char*)name, "ProducedAt") || !strcmp((const char*)name, "ByName") || !strcmp((const char*)name, "ByKey") || !strcmp((const char*)name, "City") || !strcmp((const char*)name, "StateOrProvince") || !strcmp((const char*)name, "PostalCode") || !strcmp((const char*)name, "CountryName") || !strcmp((const char*)name, "IssuerSerial") ) pctx->errcode = ddocSaxParseStartCollecting(pctx, FLAG_XML_ELEM, 1); } } //-------------------------------------------------- // Collects elements end-tag // pctx - pointer to XML parsing work-area // name - xml element tag name // pcFlag - pointer to flag governing collection of this element // pMBuf - DigiDocMemBuf to collect it in //-------------------------------------------------- int ddocSaxParseCollectEndElement(SigDocParse* pctx, const xmlChar *name, char* pcFlag, DigiDocMemBuf* pMBuf) { if(*pcFlag) { if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, "errcode) pctx->errcode = ddocMemAppendData(pMBuf, (const char*)name, -1); if(!pctx->errcode) pctx->errcode = ddocMemAppendData(pMBuf, ">", -1); } return pctx->errcode; } /** * endElementHandler: * @ctxt: An XML parser context * @name: The element name * * called when the end of an element has been detected. */ static void endElementHandler(void *ctx, const xmlChar *name) { SignatureInfo* pSigInfo = NULL; SigDocParse* pctx = (SigDocParse*)ctx; const char* pTag = 0; // do nothing if error has ocurred if(pctx->errcode) return; pTag = ddocMemPop(&(pctx->mbufTags)); if(pctx->eCurr) pctx->eCurr =pctx->eCurr->pParent; ddocDebug(4, "endElementHandler", ", popped: %s path: %s", (const char*)name, pTag, (const char*)pctx->mbufTags.pMem); // if we are in collect data mode then // collect the tag end if(!pctx->bNoXMLElemData) ddocSaxParseCollectEndElement(pctx, name, &(pctx->bCollectElemData), &(pctx->mbufElemData)); if(!strcmp((const char*)name, "DataFile")) { pctx->bCollectDFData--; // decrement bypass mode if(pctx->bCollectDFData == 0) handleEndDataFile(pctx, name); } // collect separately and data ddocSaxParseCollectEndElement(pctx, name, &(pctx->bCollectSigData), &(pctx->mbufSigData)); ddocSaxParseCollectEndElement(pctx, name, &(pctx->bCollectSigPartData), &(pctx->mbufSigPartData)); if(pctx->mbufSigData.pMem && !strcmp((const char*)name, "Signature")) { pSigInfo = ddocGetLastSignature(pctx->pSigDoc); if(pSigInfo) { // MEMLEAK: possible memleak if old content would not be released ??? ddocDebug(3, "endElementHandler", "Set orig-content %s old-mem-used: %s new-content: %d", pSigInfo->szId, (pSigInfo->mbufOrigContent.pMem ? "TRUE" : "FALSE"), pctx->mbufSigData.nLen); ddocMemBuf_free(&(pSigInfo->mbufOrigContent)); pSigInfo->mbufOrigContent.pMem = (byte*)pctx->mbufSigData.pMem; pSigInfo->mbufOrigContent.nLen = pctx->mbufSigData.nLen; pctx->mbufSigData.pMem = 0; pctx->mbufSigData.nLen = 0; } } if(!pctx->nIgnoreDataFile) { if(!strcmp((const char*)name, "EncapsulatedX509Certificate")) handleEndEncapsulatedX509Certificate(pctx); if(!strcmp((const char*)name, "EncapsulatedOCSPValue")) handleEndEncapsulatedOCSPValue(pctx); if(!strcmp((const char*)name, "ClaimedRole")) handleEndClaimedRole(pctx); if(!strcmp((const char*)name, "CertifiedRole")) handleEndCertifiedRole(pctx); if(!strcmp((const char*)name, "X509Certificate")) handleEndX509Certificate(pctx); if(!strcmp((const char*)name, "SignedProperties")) handleEndSignedProperties(pctx); if(!strcmp((const char*)name, "SignedInfo")) handleEndSignedInfo(pctx); if(!strcmp((const char*)name, "SignatureValue")) handleEndSignatureValue(pctx); if(!strcmp((const char*)name, "ResponderID")) handleEndResponderID(pctx); if(!strcmp((const char*)name, "ProducedAt")) handleEndProducedAt(pctx); if(!strcmp((const char*)name, "ByName")) handleEndResponderID(pctx); if(!strcmp((const char*)name, "ByKey")) handleEndByKey(pctx); if(!strcmp((const char*)name, "DigestValue")) handleEndDigestValue(pctx); if(!strcmp((const char*)name, "SigningTime")) handleEndSigningTime(pctx); if(!strcmp((const char*)name, "IssuerSerial")) handleEndIssuerSerial(pctx); if(!strcmp((const char*)name, "X509SerialNumber")) handleEndIssuerSerial(pctx); if(!strcmp((const char*)name, "X509IssuerName")) handleEndIssuerName(pctx); //if(!strcmp((const char*)name, "Cert")) // handleEndCert(pctx, name); if(!strcmp((const char*)name, "City")) handleAdrEntry(pctx, ADR_ENTRY_CITY); if(!strcmp((const char*)name, "StateOrProvince")) handleAdrEntry(pctx, ADR_ENTRY_STATE); if(!strcmp((const char*)name, "PostalCode")) handleAdrEntry(pctx, ADR_ENTRY_ZIP); if(!strcmp((const char*)name, "CountryName")) handleAdrEntry(pctx, ADR_ENTRY_COUNTRY); } // reset tag, but not the context because used pctx->tag[0] = 0; } /** * charactersHandler: * @ctxt: An XML parser context * @ch: a xmlChar string * @len: the number of xmlChar * * receiving some chars from the parser. * Question: how much at a time ??? */ static void charactersHandler(void *ctx, const xmlChar *ch, int len) { SigDocParse* pctx = (SigDocParse*)ctx; char *p = 0; // do nothing if error has ocurred if(pctx->errcode) return; // if we are in collect data mode then // collect this data ddocDebug(4, "charactersHandler", "tag: %s len: %d, elem-data: %s, sig-data: %s, collected: %d", pctx->tag, len, (pctx->mbufElemData.pMem ? "Y" : "N"), (pctx->mbufSigData.pMem ? "Y" : "N"), pctx->mbufElemData.nLen); //#ifndef WITH_BASE64_HASHING_HACK if(pctx->bCollectElemData) { if(!pctx->errcode) { if(pctx->bNoXMLElemData) { pctx->errcode = ddocMemAppendData(&(pctx->mbufElemData), (const char*)ch, len); } else { pctx->errcode = escapeXMLSymbols((const char*)ch, len, &p); pctx->errcode = ddocMemAppendData(&(pctx->mbufElemData), (const char*)p, -1); free(p); } } } //#endif if(pctx->bCollectSigData) { if(!pctx->errcode) { p = 0; pctx->errcode = escapeTextNode((const char*)ch, len, &p); pctx->errcode = ddocMemAppendData(&(pctx->mbufSigData), p, -1); free(p); } } if(pctx->bCollectSigPartData) { if(!pctx->errcode) { p = 0; pctx->errcode = escapeXMLSymbols((const char*)ch, len, &p); pctx->errcode = ddocMemAppendData(&(pctx->mbufSigPartData), p, -1); free(p); } } ddocDebug(5, "charactersHandler", "End collecting"); if(!strcmp(pctx->tag, "DataFile")) handleDataFile(pctx, ch, len); //else printf("Ignoring: (%s, %d)\n", ch, len); ddocDebug(5, "charactersHandler", "End"); } /** * startElementHandler: * @ctxt: An XML parser context * @name: The element name * * called when an opening tag has been processed. */ static void extractStartElementHandler(void *ctx, const xmlChar *name, const xmlChar **atts) { const char* id = 0, *ctype = 0; int i, l1; char *p1 = 0; SigDocParse* pctx = (SigDocParse*)ctx; strncpy(pctx->tag, (const char*)name, sizeof(pctx->tag)); ddocDebug(5, "extractStartElementHandler", "tag: %s", pctx->tag); // do nothing if error has ocurred if(pctx->errcode) return; if(!strcmp((const char*)name, "DataFile")) { for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { if(!strcmp((const char*)atts[i], "Id")) id = (const char*)atts[i+1]; if(!strcmp((const char*)atts[i], "ContentType")) ctype = (const char*)atts[i+1]; } if(!pctx->nIgnoreDataFile) { strncpy(pctx->ctx2, id, sizeof(pctx->ctx2)); strncpy(pctx->ctx4, ctype, sizeof(pctx->ctx4)); if(!strcmp(pctx->ctx2, pctx->ctx3)) { pctx->bCollectDFData++; // increment bypass mode ddocDebug(4, "extractStartElementHandler", "Start DF: %s mode: %s skip: %d", pctx->ctx3, pctx->ctx1, pctx->bCollectDFData); if(pctx->bCollectDFData == 1) { // only the first time ddocDebug(4, "extractStartElementHandler", "Init collecting DF: %s mode: %s", pctx->ctx3, pctx->ctx1); if(!strcmp(pctx->ctx4, CONTENT_EMBEDDED_BASE64) && !pctx->bKeepBase64) { pctx->ectx = EVP_ENCODE_CTX_new(); EVP_DecodeInit(pctx->ectx); pctx->b64pos = 0; pctx->lSize = 0; } // open output file if necessary if(!pctx->bDataFile && !pctx->pMemBufDF) { pctx->bDataFile = BIO_new_file(pctx->ctx5, "w"); ddocDebug(4, "extractStartElementHandler", "Opening file: %s", pctx->ctx5); if(!pctx->bDataFile) SET_LAST_ERROR(ERR_FILE_WRITE); } } } } if(!strcmp(ctype, CONTENT_EMBEDDED) || pctx->nIgnoreDataFile) pctx->nIgnoreDataFile++; } if(!strcmp(pctx->ctx2, pctx->ctx3) && !strcmp(pctx->ctx4, CONTENT_EMBEDDED) && strcmp((const char*)name, "DataFile")) { if(!strcmp(pctx->ctx1, CHARSET_ISO_8859_1)) { // if must convert // begining of the tag l1 = strlen((char*)name) + 10; p1 = (char*)malloc(l1); RETURN_VOID_IF_BAD_ALLOC(p1); if(pctx->pMemBufDF) { ddocMemAppendData(pctx->pMemBufDF, "<", -1); ddocMemAppendData(pctx->pMemBufDF, utf82ascii((const char*)name, p1, &l1), -1); } else BIO_printf(pctx->bDataFile, "<%s", utf82ascii((const char*)name, p1, &l1)); free(p1); p1 = 0; for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { l1 = strlen((char*)atts[i]) + 10; p1 = (char*)malloc(l1); RETURN_VOID_IF_BAD_ALLOC(p1); if(pctx->pMemBufDF) { ddocMemAppendData(pctx->pMemBufDF, " ", -1); ddocMemAppendData(pctx->pMemBufDF, utf82ascii((const char*)atts[i], p1, &l1), -1); ddocMemAppendData(pctx->pMemBufDF, "=", -1); } else BIO_printf(pctx->bDataFile, " %s=", utf82ascii((const char*)atts[i], p1, &l1)); free(p1); p1 = 0; l1 = strlen((char*)atts[i+1]) + 10; p1 = (char*)malloc(l1); RETURN_VOID_IF_BAD_ALLOC(p1); if(pctx->pMemBufDF) { ddocMemAppendData(pctx->pMemBufDF, "\"", -1); ddocMemAppendData(pctx->pMemBufDF, utf82ascii((const char*)atts[i+1], p1, &l1), -1); ddocMemAppendData(pctx->pMemBufDF, "\"", -1); } else BIO_printf(pctx->bDataFile, "\"%s\"", utf82ascii((const char*)atts[i+1], p1, &l1)); free(p1); p1 = 0; } // for - atributes if(pctx->pMemBufDF) ddocMemAppendData(pctx->pMemBufDF, ">", -1); else BIO_puts(pctx->bDataFile, ">"); } // if - must convert else { // no need to convert if(pctx->pMemBufDF) { ddocMemAppendData(pctx->pMemBufDF, "<", -1); ddocMemAppendData(pctx->pMemBufDF, (const char*)name, -1); for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { ddocMemAppendData(pctx->pMemBufDF, " ", -1); ddocMemAppendData(pctx->pMemBufDF, (const char*)atts[i], -1); p1 = 0; ddocMemAppendData(pctx->pMemBufDF, "=\"", -1); pctx->errcode = escapeXMLSymbols((const char*)atts[i+1], strlen((const char*)atts[i+1]), &p1); ddocMemAppendData(pctx->pMemBufDF, p1, -1); free(p1); ddocMemAppendData(pctx->pMemBufDF, "\"", -1); } ddocMemAppendData(pctx->pMemBufDF, ">", -1); } else { BIO_printf(pctx->bDataFile, "<%s", name); for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { BIO_printf(pctx->bDataFile, " %s=\"%s\"", (const char*)atts[i], (const char*)atts[i+1]); } BIO_puts(pctx->bDataFile, ">"); } } // else no conversion } // if strcmp(DataFile) } //-------------------------------------------------- // handles decoding base64 content. Removes all // whitespace and breaks the data in 64 symbol lines // to ensure correct decoding // pctx - pointer to XML parsing work-area // ch - input data // len - length of input data // lastBlock - 1=last base64 block //-------------------------------------------------- void extractDecodeB64(SigDocParse* pctx, const char* ch, int len, int lastBlock) { int l = 0, j; char decData[70]; ddocDebug(4, "extractDecodeB64", "line: %d last: %d", len, lastBlock); do { // compose a 64 char base64 line for OpenSSL's decoder while(pctx->b64pos < 64 && l < len) { if(!isspace(ch[l])) { pctx->b64line[pctx->b64pos] = ch[l]; pctx->b64pos++; } l++; } // if line is ready then terminate and use it if(pctx->b64pos == 64 || (l == len && lastBlock)) { pctx->b64line[pctx->b64pos] = '\n'; pctx->b64line[pctx->b64pos + 1] = 0; j = sizeof(decData); memset(decData, 0, j); ddocDebug(5, "extractDecodeB64", "decoding: %s", pctx->b64line); EVP_DecodeUpdate(pctx->ectx, (unsigned char*)decData, &j, (unsigned char*)pctx->b64line, pctx->b64pos + 1); ddocDebug(4, "extractDecodeB64", "decoding: %d -> got: %d", pctx->b64pos, j); if(pctx->pMemBufDF) ddocMemAppendData(pctx->pMemBufDF, decData, j); else { if(!pctx->pMemBufDF) SET_LAST_ERROR_RETURN_VOID_IF_NOT(pctx->bDataFile, ERR_FILE_WRITE); BIO_write(pctx->bDataFile, decData, j); } pctx->lSize += j; if(l == len && lastBlock) { j = sizeof(decData); memset(decData, 0, j); EVP_DecodeFinal(pctx->ectx, (unsigned char*)decData, &j); EVP_ENCODE_CTX_free(pctx->ectx); ddocDebug(4, "extractDecodeB64", "decoding final got: %d", j); if(j > 0) { if(pctx->pMemBufDF) ddocMemAppendData(pctx->pMemBufDF, decData, j); else { if(!pctx->pMemBufDF) SET_LAST_ERROR_RETURN_VOID_IF_NOT(pctx->bDataFile, ERR_FILE_WRITE); BIO_write(pctx->bDataFile, decData, j); } pctx->lSize += j; } } // ready for next line pctx->b64pos = 0; //memset(&(pctx->b64line), 0, sizeof(pctx->b64line)); } } while(l < len); } /** * extractBodyHandler: * @ctxt: An XML parser context * @name: The element name * * called when bypassing xml parser for base64 data and extracting to file */ void extractBodyHandler(SigDocParse* pctx, const char* ch, int len) { ddocDebug(4, "extractBodyHandler", "DF: %s data: %d", pctx->ctx2, len); if(!pctx->pMemBufDF) SET_LAST_ERROR_RETURN_VOID_IF_NOT(pctx->bDataFile, ERR_FILE_WRITE); if(!pctx->bKeepBase64) { extractDecodeB64(pctx, ch, len, 0); } else { if(pctx->pMemBufDF) { ddocMemAppendData(pctx->pMemBufDF, ch, len); }else { ddocDebug(4, "extractBodyHandler", "Writing: %s len: %d", ch, len); BIO_write(pctx->bDataFile, ch, len); } pctx->lSize += len; } } /** * extractBodyHandler: * @ctxt: An XML parser context * @name: The element name * * called when bypassing xml parser for bas64 data and extracting to file */ void extractNoChangeHandler(SigDocParse* pctx, const char* ch, int len) { int l; char *p = 0; ddocDebug(4, "extractNoChangeHandler", "DF: %s data: %d", pctx->ctx2, len); if(pctx->errcode) { return; } if(!pctx->pMemBufDF) SET_LAST_ERROR_RETURN_VOID_IF_NOT(pctx->bDataFile, ERR_FILE_WRITE); if(!strcmp(pctx->ctx4, CONTENT_EMBEDDED_BASE64)) { BIO_write(pctx->bDataFile, ch, len); pctx->lSize += len; } else { pctx->errcode = escapeXMLSymbols((const char*)ch, len, &p); l = strlen(p); pctx->lSize += l; if(pctx->pMemBufDF) { ddocMemAppendData(pctx->pMemBufDF,p, l); } else { ddocDebug(5, "extractNoChangeHandler", "Writing: %s len: %d", p, l); BIO_write(pctx->bDataFile, p, l); } free(p); p = 0; } } /** * charactersHandler: * @ctxt: An XML parser context * @ch: a xmlChar string * @len: the number of xmlChar * * receiving some chars from the parser. * Question: how much at a time ??? */ static void extractCharactersHandler(void *ctx, const xmlChar *ch, int len) { int l; char *p = 0, *p2 = 0; SigDocParse* pctx = (SigDocParse*)ctx; ddocDebug(5, "extractCharactersHandler", "tag: %s, data: %d - \'%s\'", pctx->tag, len, (char*)ch); // do nothing if error has ocurred if(pctx->errcode) { return; } if(!strcmp(pctx->ctx2, pctx->ctx3)) { if(!strcmp(pctx->ctx1, "NO-CHANGE")) { // NO-CHANGE extractNoChangeHandler(pctx, (const char*)ch, len); } else { // NOT NO-CHANGE if(!strcmp(pctx->ctx4, CONTENT_EMBEDDED_BASE64)) { extractBodyHandler(pctx, (const char*)ch, len); } if(!strcmp(pctx->ctx4, CONTENT_EMBEDDED)) { if(!strcmp(pctx->ctx1, CHARSET_ISO_8859_1)) { l = len + 10; p = (char*)malloc(l); RETURN_VOID_IF_BAD_ALLOC(p); memset(p, 0, l); UTF8Toisolat1((unsigned char*)p, &l, (const unsigned char*)ch, &len); escapeXMLSymbols((const char*)p, l, &p2); free(p); p = 0; l = strlen(p2); if(pctx->pMemBufDF) ddocMemAppendData(pctx->pMemBufDF, p, l); else BIO_write(pctx->bDataFile, (unsigned char*)p, l); free(p2); p2 = 0; } else { escapeXMLSymbols((const char*)ch, len, &p); l = strlen(p); if(pctx->pMemBufDF) ddocMemAppendData(pctx->pMemBufDF, p, l); else BIO_write(pctx->bDataFile, (unsigned char*)p, l); free(p); } } } // NOT NO-CHANGE } ddocDebug(5, "extractCharactersHandler", "done, errs: %d", pctx->errcode); } /** * extractEndElementHandler: * @ctxt: An XML parser context * @name: The element name * * called when the end of an element has been detected. */ static void extractEndElementHandler(void *ctx, const xmlChar *name) { time_t t1; SigDocParse* pctx = (SigDocParse*)ctx; ddocDebug(5, "extractEndElementHandler", "tag: %s", (char*)name); // do nothing if error has ocurred if(pctx->errcode) { return; } if(!strcmp((const char*)name, "DataFile")) { if(pctx->nIgnoreDataFile > 0) pctx->nIgnoreDataFile--; ddocDebug(3, "extractEndElementHandler", "DF: %s end ignore: %d skip: %d", pctx->ctx2, pctx->nIgnoreDataFile, pctx->bCollectDFData); if(!strcmp(pctx->ctx2, pctx->ctx3) && !pctx->nIgnoreDataFile) { pctx->bCollectDFData--; if(!pctx->bCollectDFData) { if(!strcmp(pctx->ctx4, CONTENT_EMBEDDED_BASE64) && strcmp(pctx->ctx1, "NO-CHANGE")) { if(!pctx->bKeepBase64) extractDecodeB64(pctx, NULL, 0, 1); } if(!strcmp(pctx->ctx1, "NO-CHANGE")) { // todo ? } time(&t1); ddocDebug(3, "extractEndElementHandler", "DF: %s mode: %s, time: %d [sek] total: %ld bytes", pctx->ctx3, pctx->ctx1, (t1 - pctx->tStartParse), pctx->lSize); // mark the end of data collecting pctx->ctx3[0] = 0; pctx->lSize = 0; } // if bCollectDFData == 0 } // if not ignore DataFile } // if "DataFile" if(pctx->ctx3[0] && !strcmp(pctx->ctx4, CONTENT_EMBEDDED)) { if(pctx->pMemBufDF) { ddocDebug(5, "extractEndElementHandler", "Last name: %s collected: \'%s\'", (char*)name, (char*)pctx->pMemBufDF->pMem); ddocMemAppendData(pctx->pMemBufDF, "pMemBufDF, (char*)name, -1); ddocMemAppendData(pctx->pMemBufDF, ">", -1); ddocDebug(5, "extractEndElementHandler", "Result: \'%s\'", (char*)pctx->pMemBufDF->pMem); } else { BIO_printf(pctx->bDataFile, "", name); } } // reset tag pctx->tag[0] = 0; } /** * cdataBlockHandler: * @ctx: the user data (XML parser context) * @value: The pcdata content * @len: the block length * * called when a pcdata block has been parsed */ static void cdataBlockHandler(void * ctx, const xmlChar *value, int len) { fprintf(stdout, "SAX.pcdata(%.20s, %d)\n", (char *) value, len); } /** * warningHandler: * @ctxt: An XML parser context * @msg: the message to display/transmit * @...: extra parameters for the message display * * Display and format a warning messages, gives file, line, position and * extra parameters. */ static void warningHandler(void * ctx, const char *msg, ...) { va_list args; va_start(args, msg); ddocDebugVaArgs(2, "warningHandler", msg, args); va_end(args); } /** * errorHandler: * @ctxt: An XML parser context * @msg: the message to display/transmit * @...: extra parameters for the message display * * Display and format a error messages, gives file, line, position and * extra parameters. */ static void errorHandler(void *ctx, const char *msg, ...) { va_list args; SigDocParse* pctx = (SigDocParse*)ctx; va_start(args, msg); pctx->errcode = ERR_DIGIDOC_PARSE; ddocDebugVaArgs(1, "errorHandler", msg, args); addError(pctx->errcode, __FILE__, __LINE__, "XML parsing error"); va_end(args); } /** * fatalErrorHandler: * @ctxt: An XML parser context * @msg: the message to display/transmit * @...: extra parameters for the message display * * Display and format a fatalError messages, gives file, line, position and * extra parameters. */ static void fatalErrorHandler(void *ctx, const char *msg, ...) { va_list args; SigDocParse* pctx = (SigDocParse*)ctx; va_start(args, msg); pctx->errcode = ERR_DIGIDOC_PARSE; ddocDebugVaArgs(1, "fatalErrorHandler", msg, args); addError(pctx->errcode, __FILE__, __LINE__, "XML parsing error"); va_end(args); } xmlSAXHandler debugSAXHandlerStruct = { NULL, //internalSubsetHandler, NULL, //isStandaloneHandler, NULL, //hasInternalSubsetHandler, NULL, //hasExternalSubsetHandler, NULL, //resolveEntityHandler, NULL, //getEntityHandler, NULL, //entityDeclHandler, NULL, //notationDeclHandler, NULL, //attributeDeclHandler, NULL, //elementDeclHandler, NULL, //unparsedEntityDeclHandler, NULL, //setDocumentLocatorHandler, NULL, //startDocumentHandler, NULL, //endDocumentHandler, startElementHandler, endElementHandler, NULL, //referenceHandler, charactersHandler, NULL, //ignorableWhitespaceHandler, NULL, //processingInstructionHandler, NULL, //commentHandler, warningHandler, errorHandler, fatalErrorHandler, NULL, //getParameterEntityHandler, cdataBlockHandler, NULL, //externalSubsetHandler, 1 }; xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct; xmlSAXHandler extractSAXHandlerStruct = { NULL, //internalSubsetHandler, NULL, //isStandaloneHandler, NULL, //hasInternalSubsetHandler, NULL, //hasExternalSubsetHandler, NULL, //resolveEntityHandler, NULL, //getEntityHandler, NULL, //entityDeclHandler, NULL, //notationDeclHandler, NULL, //attributeDeclHandler, NULL, //elementDeclHandler, NULL, //unparsedEntityDeclHandler, NULL, //setDocumentLocatorHandler, NULL, //startDocumentHandler, NULL, //endDocumentHandler, extractStartElementHandler, extractEndElementHandler, NULL, //referenceHandler, extractCharactersHandler, NULL, //ignorableWhitespaceHandler, NULL, //processingInstructionHandler, NULL, //commentHandler, warningHandler, errorHandler, fatalErrorHandler, NULL, //getParameterEntityHandler, NULL, //cdataBlockHandler, NULL, //externalSubsetHandler, 1 }; xmlSAXHandlerPtr extractSAXHandler = &extractSAXHandlerStruct; //-------------------------------------------------- // Reads in signed XML document info from digidoc file // ppSigDoc - pointer to the buffer of newly read info pointer // szFileName - documents filename // checkFileDigest - indicates if digests of datafiles referred by the document must be checked // lMaxDFLen - maximum size for a DataFile whose contents will be // kept in memory //-------------------------------------------------- EXP_OPTION int ddocSaxReadSignedDocFromFile(SignedDoc** ppSigDoc, const char* szFileName, int checkFileDigest, long lMaxDFLen) { int err = ERR_OK, ret, n; FILE *f; char chars[1028], *p, buf1[16385]; xmlParserCtxtPtr ctxt; SigDocParse pctx; DigiDocMemBuf mbuf1; #ifdef WIN32 wchar_t *convFileName = 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &ret); ddocDebug(3, "ddocSaxReadSignedDocFromFile", "file: %s, conv-file: %s", szFileName, convFileName); #endif ddocDebug(3, "ddocSaxReadSignedDocFromFile", "digidoc: %s, checkDig: %d, maxDF: %ld", szFileName, checkFileDigest, lMaxDFLen); RETURN_IF_NULL_PARAM(ppSigDoc); RETURN_IF_NULL_PARAM(szFileName); clearErrors(); memset(&pctx, 0, sizeof(pctx)); pctx.pSigDoc = (SignedDoc*)malloc(sizeof(SignedDoc)); RETURN_IF_BAD_ALLOC(pctx.pSigDoc); memset(pctx.pSigDoc, 0, sizeof(SignedDoc)); #ifdef WIN32 ddocDebug(3, "ddocSaxReadSignedDocFromFile", "Opening file: %s", convFileName); if(!err && ((f = _wfopen(convFileName, L"rb")) != NULL)) { #else ddocDebug(3, "ddocSaxReadSignedDocFromFile", "Opening file: %s", szFileName); if(!err && ((f = fopen(szFileName, "rb")) != NULL)) { #endif ddocDebug(4, "ddocSaxReadSignedDocFromFile", "file opened"); n=0; if(ftell(f) > 0) { ddocDebug(5, "ddocSaxReadSignedDocFromFile", "File position after open is: %d err: %d eof: %d, move to begin!", ftell(f), ferror(f), feof(f)); fseek(f, 0, SEEK_SET); } //memset(chars,0,sizeof(chars)); ret = fread(chars, 1, 100, f); if (ret > 0) { chars[ret] = 0; // zero terminate block data p = strstr(chars, "= 0) { chars[ret] = 0; // zero terminate block data } else { ddocDebug(1, "ddocSaxReadSignedDocFromFile", "No data could be read from: %s pos: %d", szFileName, ftell(f)); break; } n++; ddocDebug(5, "ddocSaxReadSignedDocFromFile", "parse block: %d len: %d fpos: %d \n---\n%s\n---\n", n, ret, ftell(f), chars); if(pctx.bCollectDFData > 0 && !strcmp(pctx.ctx4, CONTENT_EMBEDDED_BASE64)) { // bypass mode // look for new element start "<" p = strchr(chars, '<'); // if we just enetered the bypass mode then send flush command // but increment bypass mode in order not to fall out of it if(pctx.bCollectDFData == 1 && !p) { // start bypass mode pctx.bCollectDFData += 2; // increment with 2 so we dont return to flushing ddocDebug(4, "ddocSaxReadSignedDocFromFile", "Starting bypass mode, skip: %d", pctx.bCollectDFData); // force the parser to release element content // before entering into bypass mode ddocDebug(5, "ddocSaxReadSignedDocFromFile", "parse bypass data %s", g_szDataFileFlush1); xmlParseChunk(ctxt, g_szDataFileFlush1, strlen(g_szDataFileFlush1), 0); ddocDebug(4, "ddocSaxReadSignedDocFromFile", "Entering bypass mode, skip: %d", pctx.bCollectDFData); } if(pctx.bCollectDFData >=2 && !p /*pctx.bCollectElemData*/) { // parse in bypass mode ddocDebug(4, "ddocSaxReadSignedDocFromFile", "Parsing in bypass mode, skip: %d len: %d", pctx.bCollectDFData, ret); #ifdef WITH_BASE64_HASHING_HACK ddocDebug(4, "ddocSaxReadSignedDocFromFile", "update sha1: %d - %s", ret, chars); SHA1_Update(&(pctx.sctx), chars, ret); mbuf1.pMem = chars; mbuf1.nLen = ret; ddocDebugWriteFile(4, "df-data.txt", &mbuf1); #else pctx.errcode = ddocMemAppendData(&(pctx.mbufElemData), chars, ret); // update sha1 l1 = sizeof(buf1); EVP_DecodeUpdate(&(pctx.ectx), (unsigned char*)buf1, &l1, (unsigned char*)chars, ret); ddocDebug(4, "ddocSaxReadSignedDocFromFile", "update sha1: %d - %s", l1, buf1); SHA1_Update(&(pctx.sctx), buf1, l1); #endif } if(p) { // finish bypass mode ddocDebug(4, "ddocSaxReadSignedDocFromFile", "Ending bypass mode len: %d, skip: %d", ret, pctx.bCollectDFData); snprintf(buf1, sizeof(buf1), g_szDataFileFlush2, pctx.ctx3, pctx.ctx4); // send finish command ddocDebug(5, "ddocSaxReadSignedDocFromFile", "parse finish data %s", buf1); xmlParseChunk(ctxt, buf1, strlen(buf1), 0); pctx.bCollectDFData = 1; // parse the normal chunk that caused end xmlParseChunk(ctxt, chars, ret, 0); } } else { // normal mode ddocDebug(4, "ddocSaxReadSignedDocFromFile", "parsing normal chunk"); xmlParseChunk(ctxt, chars, ret, 0); } } while(ret > 0/* && pctx.ctx3[0]*/); ddocDebug(5, "ddocSaxReadSignedDocFromFile", "parse end0 \n---\n%s\n---\n", chars); xmlParseChunk(ctxt, chars, 0, 1); xmlFreeParserCtxt(ctxt); } *ppSigDoc = pctx.pSigDoc; fclose(f); } else { err = ERR_FILE_READ; ddocDebug(1, "ddocSaxReadSignedDocFromFile", "error reading file: %s, err: %d", szFileName, err); } if (err != ERR_OK) SET_LAST_ERROR(err); if(!err) err = getLastError(); ddocDebug(3, "ddocSaxReadSignedDocFromFile", "success reading file: %s, err: %d", szFileName, err); // cleanup parser context ddocSAXCleanup(&pctx); // check ddoc xmlns problem checkDdocWrongDigests(*ppSigDoc); #ifdef WIN32 free(convFileName); #endif return checkUnknownErr(); } //-------------------------------------------------- // Reads in signed XML document info // ppSigDoc - pointer to the buffer of newly read info pointer // szFileName - documents filename // checkFileDigest - indicates if digests of datafiles referred by the document must be checked // lMaxDFLen - maximum size for a DataFile whose contents will be // kept in memory //-------------------------------------------------- EXP_OPTION int ddocSaxReadSignedDocFromMemory(SignedDoc** ppSigDoc, const void* pData, int len, long lMaxDFLen) { int err = ERR_OK; int ret, l2; SigDocParse pctx; char * p = 0; ddocDebug(3, "ddocSaxReadSignedDocFromMemory", "data len: %d, maxDF: %ld", len, lMaxDFLen); RETURN_IF_NULL_PARAM(ppSigDoc); RETURN_IF_NULL_PARAM(pData); clearErrors(); memset(&pctx, 0, sizeof(pctx)); pctx.pSigDoc = (SignedDoc*)malloc(sizeof(SignedDoc)); RETURN_IF_BAD_ALLOC(pctx.pSigDoc); memset(pctx.pSigDoc, 0, sizeof(SignedDoc)); //pctx.bDataFile = (BIO*)1; pctx.szInputFileName = 0; pctx.checkFileDigest = 0; pctx.lMaxDFLen = lMaxDFLen; // skip any BOM marks or other non-xml chars at the beginning if(pData) p = strstr((const char*)pData, " 0) { p = strstr(chars, " 0 && !strcmp(pctx.ctx4, CONTENT_EMBEDDED_BASE64)) { // bypass mode // look for new element start "<" p = strchr(chars, '<'); // if we just entered the bypass mode then send flush command // but increment bypass mode in order not to fall out of it if(pctx.bCollectDFData == 1 && !p) { // start bypass mode pctx.bCollectDFData += 2; // increment with 2 so we dont return to flushing ddocDebug(4, "ddocSaxExtractDataFile", "Starting bypass mode, skip: %d", pctx.bCollectDFData); // force the parser to release element content // before entering into bypass mode xmlParseChunk(ctxt, g_szDataFileFlush1, strlen(g_szDataFileFlush1), 0); ddocDebug(4, "ddocSaxExtractDataFile", "Entering bypass mode, skip: %d", pctx.bCollectDFData); } if(pctx.bCollectDFData >=2 && !p) { // parse in bypass mode ddocDebug(4, "ddocSaxExtractDataFile", "Parsing in bypass mode, skip: %d len: %d", pctx.bCollectDFData, ret); if(!strcmp(pctx.ctx1, "NO-CHANGE")) { // NO-CHANGE extractNoChangeHandler(&pctx, (const char*)chars, ret); } else { extractBodyHandler(&pctx, (const char*)chars, ret); } } if(p) { // finish bypass mode *p = 0; ddocDebug(3, "ddocSaxExtractDataFile", "Last block %d bytes: \n%s\n", ret, chars); pctx.bCollectDFData = 1; //xmlParseChunk(ctxt, chars, strlen((const char*)chars), 0); if(!strcmp(pctx.ctx1, "NO-CHANGE")) { // NO-CHANGE extractNoChangeHandler(&pctx, (const char*)chars, strlen(chars)); } else { extractBodyHandler(&pctx, (const char*)chars, strlen(chars)); extractDecodeB64(&pctx, NULL, 0, 1); } pctx.bCollectDFData = 0; // stopp bypass attempts memset(chars, 0, sizeof(chars)); ret = 0; // stop parsing } } else { // normal mode ddocDebug(3, "ddocSaxExtractDataFile", "parsing normal chunk \n%s\n", chars); xmlParseChunk(ctxt, chars, ret, 0); memset(chars, 0, sizeof(chars)); } } while(ret > 0 && pctx.ctx3[0]); ddocDebug(3, "ddocSaxExtractDataFile", "parsing last chunk\n---%s\n---", chars); if(strlen(chars)) xmlParseChunk(ctxt, chars, 0, 1); xmlFreeParserCtxt(ctxt); } ddocDebug(5, "ddocSaxExtractDataFile", "parsing complete"); fclose(f); } else { ddocDebug(1, "ddocSaxExtractDataFile", "Error reading file: %s", szFileName); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } if(!err) err = getLastError(); // cleanup parser context ddocSAXCleanup(&pctx); return err; } //-------------------------------------------------- // Reads in signed XML document and returns the // desired DataFile-s content in a memory buffer. // caller is responsible for freeing the memory. // pSigDoc - signed document object if cached // szFileName - name of digidoc file // szDocId - id if DataFile // pOutBuf - address of buffer pointer // bKeepBase64 - 1=don't decode base64, 0=decode base64 // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSAXGetDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDocId, DigiDocMemBuf* pOutBuf, int bKeepBase64) { FILE *f; int ret, err = ERR_OK; char chars[1025], convFileName[1024], *p, buf1[200]; xmlParserCtxtPtr ctxt; SigDocParse pctx; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(szDocId); clearErrors(); ddocDebug(3, "ddocSAXGetDataFile", "SigDoc: %s, docid: %s, digidoc: %s, keepb64: %d", (pSigDoc ? "OK" : "NULL"), szDocId, szFileName, bKeepBase64); // try reading from memory if already cached? pOutBuf->pMem = 0; pOutBuf->nLen = 0; ret = ddocGetDataFileCachedData(pSigDoc, szDocId, &(pOutBuf->pMem), &pOutBuf->nLen); if(pOutBuf->pMem) { // gotcha ddocDebug(3, "ddocSAXGetDataFile", "Using cached data: %d bytes", pOutBuf->nLen); return ret; } memset(&pctx, 0, sizeof(pctx)); ddocConvertFileName( convFileName, sizeof(convFileName), szFileName ); if ((f = fopen(convFileName, "r")) != NULL) { pctx.pSigDoc = NULL; pctx.bDataFile = NULL; pctx.ctx1[0] = pctx.ctx2[0] = pctx.ctx3[0] = pctx.tag[0] = pctx.ctx4[0] = 0; pctx.errcode = ERR_OK; pctx.bKeepBase64 = bKeepBase64; pOutBuf->pMem = 0; pOutBuf->nLen = 0; pctx.pMemBufDF = pOutBuf; time(&(pctx.tStartParse)); pctx.bDataFile = NULL; //BIO_new_file(szDataFileName, "w"); //strcpy(pctx.ctx1, szCharset); pctx.szInputFileName = (char*)szFileName; strncpy(pctx.ctx3, szDocId, sizeof(pctx.ctx3)); memset(chars, 0, sizeof(chars)); ret = fread(chars, 1, 100, f); if (ret > 0) { p = strstr(chars, " 0 && ret < sizeof(chars)) chars[ret] = 0; if(pctx.bCollectDFData > 0) { // bypass mode // look for new element start "<" p = strchr(chars, '<'); // if we just enetered the bypass mode then send flush command // but increment bypass mode in order not to fall out of it if(pctx.bCollectDFData == 1 && !p) { // start bypass mode pctx.bCollectDFData += 2; // increment with 2 so we dont return to flushing ddocDebug(4, "ddocSAXGetDataFile", "Starting bypass mode, skip: %d", pctx.bCollectDFData); // force the parser to release element content // before entering into bypass mode xmlParseChunk(ctxt, g_szDataFileFlush1, strlen(g_szDataFileFlush1), 0); ddocDebug(4, "ddocSAXGetDataFile", "Entering bypass mode, skip: %d", pctx.bCollectDFData); } if(pctx.bCollectDFData >=2 && !p) { // parse in bypass mode ddocDebug(4, "ddocSAXGetDataFile", "Parsing in bypass mode, skip: %d len: %d", pctx.bCollectDFData, ret); extractBodyHandler(&pctx, (const char*)chars, ret); } if(p) { // finish bypass mode ddocDebug(4, "ddocSAXGetDataFile", "Ending bypass mode len: %d, skip: %d", ret, pctx.bCollectDFData); snprintf(buf1, sizeof(buf1), g_szDataFileFlush2, pctx.ctx3, pctx.ctx4); // send finish command xmlParseChunk(ctxt, buf1, strlen(buf1), 0); pctx.bCollectDFData = 1; // parse the normal chunk that caused end xmlParseChunk(ctxt, chars, ret, 0); } } else { // normal mode ddocDebug(4, "ddocSAXGetDataFile", "parsing normal chunk"); xmlParseChunk(ctxt, chars, ret, 0); } } while(ret > 0); xmlParseChunk(ctxt, chars, 0, 1); xmlFreeParserCtxt(ctxt); } fclose(f); } else { ddocDebug(1, "ddocSAXGetDataFile", "Error reading file: %s", szFileName); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } if(!err) err = getLastError(); // cleanup parser context ddocSAXCleanup(&pctx); return err; } //-------------------------------------------------- // Reads new signatures from another digidoc file // and adds to existing digidoc. Adds only those // signatures that don't exist in old digidoc. // pSigDoc - signed document object // szFileName - name of digidoc file // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocReadNewSignaturesFromDdoc(SignedDoc* pSigDoc, const char* szFileName) { SignedDoc *pSigDoc2 = 0; int err = ERR_OK, n1 = 0, n2 = 0, i; SignatureInfo** pSignatures = NULL; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(szFileName); // read in digidoc file err = ddocSaxReadSignedDocFromFile(&pSigDoc2, szFileName, 0, 0); if(err) { if(pSigDoc2) SignedDoc_free(pSigDoc2); return err; } // copy new signatures from digidoc just read in // assumes that new signatures are at the end n1 = getCountOfSignatures(pSigDoc); n2 = getCountOfSignatures(pSigDoc2); if(n2 > n1) { pSignatures = (SignatureInfo**)realloc(pSigDoc->pSignatures, n2 * sizeof(void *)); if(!pSignatures) { if(pSigDoc2) SignedDoc_free(pSigDoc2); RETURN_IF_BAD_ALLOC(pSignatures); } pSigDoc->pSignatures = pSignatures; for(i = n1; i < n2; i++) { pSigDoc->pSignatures[i] = pSigDoc2->pSignatures[i]; // take ownership pSigDoc2->pSignatures[i] = 0; // set to NULL to prevent deallocation // VS destroy hash - debug ((char*)pSigDoc->pSignatures[i]->pDocs[0]->szDigest)[0] = 0x0A; } pSigDoc->nSignatures = n2; pSigDoc2->nSignatures = n1; } // delete new digidoc object no longer necessary SignedDoc_free(pSigDoc2); return err; } char* pHdr1 = "\n"; char* pHdr2 = "\n"; char* pHdr3 = "\n"; //-------------------------------------------------- // Adds new signature to existing ddoc // szFileName - ddoc file name // pSigBuf - buffer with new signature data // nSigLen - new signature data length //-------------------------------------------------- EXP_OPTION int ddocAddSignatureFromMemory(SignedDoc* pSigDoc, const char* szFileName, const void* pSigBuf, int nSigLen) { int err = ERR_OK, n1 = 0, n2 = 0, i; SignatureInfo** pSignatures = NULL; SignedDoc *pSigDoc2 = 0; char buf1[102], *p1; FILE* f; DigiDocMemBuf mbuf1; #ifdef WIN32 wchar_t *convFileName = 0; int ret = 0; #endif RETURN_IF_NULL_PARAM(pSigDoc); //RETURN_IF_NULL_PARAM(szFileName && strlen(szFileName)); RETURN_IF_NULL_PARAM(pSigBuf); mbuf1.pMem = 0; mbuf1.nLen = 0; clearErrors(); ddocDebug(3, "ddocAddSignatureFromMemory", "SigDoc: %s, file: %s, sig: %s, slen: %d", (pSigDoc ? "OK" : "NULL"), szFileName, (pSigBuf ? "OK" : "NULL"), nSigLen); // read in digidoc buffer ddocMemAssignData(&mbuf1, pHdr1, -1); ddocMemAppendData(&mbuf1, pHdr2, -1); ddocMemAppendData(&mbuf1, pSigBuf, nSigLen); ddocMemAppendData(&mbuf1, pHdr3, -1); err = ddocSaxReadSignedDocFromMemory(&pSigDoc2, mbuf1.pMem, mbuf1.nLen, mbuf1.nLen); ddocMemBuf_free(&mbuf1); if(err) { ddocDebug(1, "ddocAddSignatureFromMemory", "Error: %d reading signature", err); if(pSigDoc2) SignedDoc_free(pSigDoc2); return err; } // copy new signatures from digidoc just read in // assumes that new signatures are at the end n1 = getCountOfSignatures(pSigDoc); n2 = getCountOfSignatures(pSigDoc2); if(n2 > n1) { pSignatures = (SignatureInfo**)realloc(pSigDoc->pSignatures, n2 * sizeof(void *)); if(!pSignatures) { if(pSigDoc2) SignedDoc_free(pSigDoc2); RETURN_IF_BAD_ALLOC(pSignatures); } pSigDoc->pSignatures = pSignatures; for(i = n1; i < n2; i++) { pSigDoc->pSignatures[i] = pSigDoc2->pSignatures[i]; // take ownership pSigDoc2->pSignatures[i] = 0; // set to NULL to prevent deallocation } pSigDoc->nSignatures = n2; pSigDoc2->nSignatures = n1; } // delete new digidoc object no longer necessary SignedDoc_free(pSigDoc2); ddocDebug(3, "ddocAddSignatureFromMemory", "RC: %d adding signature", err); // now append new signature to existing ddoc file if(szFileName && strlen(szFileName)) { // if we have to update ddoc on disc #ifdef WIN32 err = utf82unicode((const char*)szFileName, (char**)&convFileName, &ret); ddocDebug(3, "ddocAddSignatureFromMemory", "file: %s, conv-file: %s", szFileName, convFileName); ddocDebug(3, "ddocSaxReadSignedDocFromFile", "Opening file: %s", convFileName); if(!err && ((f = _wfopen(convFileName, L"r+b")) != NULL)) { #else ddocDebug(3, "ddocSaxReadSignedDocFromFile", "Opening file: %s", szFileName); if(!err && ((f = fopen(szFileName, "r+b")) != NULL)) { #endif ddocDebug(3, "ddocSaxReadSignedDocFromFile", "file opened, pos: %d", ftell(f)); // seek to file end -100 bytes anf find ddoc end tag err = fseek(f, -30, SEEK_END); ddocDebug(3, "ddocSaxReadSignedDocFromFile", "seek: %d new pos: %d", err, ftell(f)); memset(buf1, 0, sizeof(buf1)); n1 = fread(buf1, 1, 30, f); ddocDebug(3, "ddocSaxReadSignedDocFromFile", "read: %d data: %s", n1, buf1); p1 = strstr(buf1, ""); if(p1) { *p1 = 0; n2 = strlen(buf1); ddocDebug(3, "ddocSaxReadSignedDocFromFile", "distance: %d", n2); err = fseek(f, -1 * (30 - n2), SEEK_END); ddocDebug(3, "ddocSaxReadSignedDocFromFile", "seek: %d new pos: %d", err, ftell(f)); n1 = fwrite(pSigBuf, 1, nSigLen, f); ddocDebug(3, "ddocSaxReadSignedDocFromFile", "wrote: %d", n1); fputs("", f); } fclose(f); } } // if szFileName return err; } libdigidoc-3.10.5/libdigidoc/DlgUnitS.c0000664000372000037200000003450313560273131017227 0ustar travistravis//================================================== // FILE: DlgUnitS.c // PROJECT: Digi Doc // DESCRIPTION: Low-level built dialog with list selection capability // Simple dialog // 09/10/2003 Changed by AA //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //================================================== #include #include //#include //Control ID's #define IDD_DLG_UNIT 1000 #define IDC_GROUPBOX 1001 #define IDC_LISTVIEW 1002 //min and max sizes for dialog window #define dDLGWIN_MINWIDTH 170 #define dDLGWIN_MAXWIDTH 800 #define dDLGWIN_MINHEIGHT 150 #define dDLGWIN_MAXHEIGHT 600 //maximum items in the listbox //Developer can change the value #define dDLGMAXLISTBOXSIZE 1024 //maximum item length //Developer can change the value #define dDLGMAXITEMSIZE 512 //temporary messagebox buffer len #define dDLGTEMPBUFLEN 64 #define dDLGNOSELECTION -2 #define dDLGERROR -1 static BOOL CALLBACK WndDlgUnitProc(HWND, UINT, WPARAM, LPARAM); static void CalculateDialogSize(HWND hDlg); static void SetDialogItemSize(HWND hWnd, int iWOffs, int iHOffs); static void SetDialogItemPosition(HWND hWnd, int iWOffs, int iHOffs); static void SetDialogItemPosition_Old(HWND hWnd, int iWOffs, int iHOffs); static void CenterDialogOnScreen(HWND hDlg, HWND hMain); static void Dialog_End(HWND hDlg, BOOL fCancel); static void Dialog_Init(HWND hDlg); static void DispError(char *psError); static LPWORD lpwAlign (LPWORD lpIn); static BOOL Dialog_Create(void); static HGLOBAL hgbl; //Dialog template static char *psDlgCaption=NULL; //Dialog Title static char *psGrpHeader=NULL; //Groupbox Header static char *psOkButtonText=NULL; //Ok button label static char *psCancelButtonText=NULL; //Cancel button label static char **psListItems=NULL; //Listbox items static int iDlgWidth = 800; static int iDlgHeight = 170; // //Dialog main function // //Limitations: // Max. items in the listbox dDLGMAXLISTBOXSIZE // Max. item size in the listbox dDLGMAXITEMSIZE // Dialogbox sizes dDLGWIN_* values // //No dynamic memory allocation // //Selection is accepted if, list item is selected and // - user pressed "Ok" button // - user double-clicks on the listbox item // - user pressed key // //If no items in the psList or psList is NULL, //then Ok button is disabled // //psList - pointer arrays of listbox elements // last item must be NULL //psCaption - dialog caption/title // if NULL, then no caption //psHeader - listbox header // if NULL, then no header //psOkButton - Ok button label // if NULL or zero length string, then "&Ok" //psCancelButton - Cancel button label // if NULL or zero length string, then "&Cancel" //iWinWidth - dialogbox width, if 0 then default size // //iWinHeight - dialogbox height, if 0 then default size // //returns -1 (dDLGNOSELECTION) if listbox item not selected (Cancel button) // >=0 selected item index in the psList array // // int RunDialogUnitSimple(char *psList[], char *psCaption, char *psHeader, char *psOkButton, char *psCancelButton, int iWinWidth, int iWinHeight) { char sTemp[dDLGTEMPBUFLEN]; DWORD dwRes; int iRes = dDLGNOSELECTION; //Set global data psDlgCaption = psCaption; psGrpHeader = psHeader; psOkButtonText = psOkButton; psCancelButtonText = psCancelButton; iDlgWidth = iWinWidth; iDlgHeight = iWinHeight; //if not allowed value, then default size if (iDlgWidth < dDLGWIN_MINWIDTH || iDlgWidth > dDLGWIN_MAXWIDTH) iDlgWidth = 0; //if not allowed value, then default size if (iDlgHeight < dDLGWIN_MINHEIGHT || iDlgHeight > dDLGWIN_MAXHEIGHT) iDlgHeight = 0; //if not specified, then empty string if (psDlgCaption == NULL) psDlgCaption = ""; //if not specified, then empty string if (psGrpHeader == NULL) psGrpHeader = ""; //if not specified, then Ok string if (psOkButtonText == NULL || lstrlen(psOkButtonText) == 0) psOkButtonText = "&Ok"; //if not specified, then Ok string if (psCancelButtonText == NULL || lstrlen(psCancelButtonText) == 0) psCancelButtonText = "&Cancel"; //set items psListItems = psList; //Starts dialog, return value from function Dialog_End if (Dialog_Create() == TRUE) iRes = DialogBoxIndirect(NULL, (LPDLGTEMPLATE) hgbl, GetActiveWindow(), (DLGPROC) WndDlgUnitProc); else iRes = dDLGERROR; //iRes = DialogBox(NULL, MAKEINTRESOURCE(IDD_DLG_UNIT), NULL,(DLGPROC)WndDlgUnitProc); //if GetLastError returns nonzero, then dialog opening error if (iRes == dDLGERROR) { dwRes = GetLastError(); if (dwRes != 0) { //prints Windows errorcode _snprintf(sTemp, sizeof(sTemp), "Windows Error=%d",dwRes); DispError(sTemp); } } if (iRes == dDLGNOSELECTION) iRes = dDLGERROR; if (hgbl != NULL) GlobalFree(hgbl); return(iRes); } //Dialog callback functions static BOOL CALLBACK WndDlgUnitProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { BOOL fRes = FALSE; DWORD dwNotifyCode; switch (message) { case WM_INITDIALOG: //dialog init Dialog_Init(hDlg); fRes = TRUE; break; case WM_CLOSE: //user closes dialog from the system menu Dialog_End(hDlg, TRUE); fRes = TRUE; break; case WM_COMMAND: { dwNotifyCode = HIWORD(wParam); //user presses dblclick in the listbox if (dwNotifyCode == LBN_DBLCLK) { Dialog_End(hDlg,FALSE); fRes = TRUE; break; } switch (wParam) { case IDOK: //user pressed OK button Dialog_End(hDlg,FALSE); fRes = TRUE; break; case IDCANCEL: //user pressed Cancel button Dialog_End(hDlg, TRUE); fRes = TRUE; break; } } } return(fRes); } //Dialog end function //fCancel - TRUE, if user pressed Cancel button // static void Dialog_End(HWND hDlg, BOOL fCancel) { int iRes = dDLGNOSELECTION; int iSelection; //if TRUE, then always returns -1 (dDLGNOSELECTION) if (fCancel == FALSE) { //if listbox item selected, then retuns selected item index iSelection = SendMessage(GetDlgItem(hDlg,IDC_LISTVIEW), LB_GETCURSEL,0,0); if (iSelection != LB_ERR) iRes = iSelection; } EndDialog(hDlg, iRes); } //Dialog init // static void Dialog_Init(HWND hDlg) { int iItems = 0; BOOL fError = FALSE; HWND hWndLst = GetDlgItem(hDlg,IDC_LISTVIEW); //Set dialog caption SetWindowText(hDlg, (LPTSTR)psDlgCaption); //Set listbox header SetDlgItemText(hDlg,IDC_GROUPBOX,(LPTSTR)psGrpHeader); //Set Ok button label SetDlgItemText(hDlg,IDOK,(LPTSTR)psOkButtonText); //Set Cancel button label SetDlgItemText(hDlg,IDCANCEL,(LPTSTR)psCancelButtonText); //Calculate dialog size CalculateDialogSize(hDlg); //Center dialog CenterDialogOnScreen(hDlg,NULL); //Deletes listbox SendMessage(hWndLst, LB_RESETCONTENT, 0, 0); //Set hor scrollbar SendMessage(hWndLst, LB_SETHORIZONTALEXTENT, 1200,0); //Add items to the listbox while (psListItems != NULL && *psListItems != NULL && iItems < dDLGMAXLISTBOXSIZE) { if (lstrlen(*psListItems) < dDLGMAXITEMSIZE) { SendMessage(hWndLst, LB_ADDSTRING, 0, (LONG) (LPTSTR)*psListItems); ++iItems; } else fError = TRUE; ++psListItems; } if (fError == TRUE) DispError("Listbox item error"); //if at least one item, then select first item if (iItems > 0) { EnableWindow(GetDlgItem(hDlg, IDOK),TRUE); SendMessage(hWndLst, LB_SETCURSEL, 0, (LONG) 0); } else EnableWindow(GetDlgItem(hDlg, IDOK),FALSE); } //Calculate dialog size // static void CalculateDialogSize(HWND hDlg) { RECT rcDlg; // Dialog window rect int iWOffs, iHOffs; // Offsets if (iDlgWidth > 0 && iDlgHeight > 0) { GetWindowRect(hDlg, &rcDlg); iWOffs = iDlgWidth - (rcDlg.right - rcDlg.left); iHOffs = iDlgHeight - (rcDlg.bottom - rcDlg.top); SetDialogItemSize(hDlg,iWOffs,iHOffs); SetDialogItemSize(GetDlgItem(hDlg,IDC_LISTVIEW),iWOffs,iHOffs); SetDialogItemSize(GetDlgItem(hDlg,IDC_GROUPBOX),iWOffs,iHOffs); SetDialogItemPosition(GetDlgItem(hDlg,IDOK),iWOffs,iHOffs); SetDialogItemPosition(GetDlgItem(hDlg,IDCANCEL),iWOffs,iHOffs); } } //Set dialog item size // static void SetDialogItemSize(HWND hWnd, int iWOffs, int iHOffs) { RECT rcItm; // Dialog window rect int iWidth, iHeight; // Width and height GetWindowRect(hWnd, &rcItm); iWidth = rcItm.right - rcItm.left; iHeight = rcItm.bottom - rcItm.top; SetWindowPos(hWnd,NULL,0,0,iWidth+iWOffs, iHeight+iHOffs,SWP_NOMOVE|SWP_NOZORDER); } //Set dialog item pos //Not in use static void SetDialogItemPosition_Old(HWND hWnd, int iWOffs, int iHOffs) { RECT rcItm; // Dialog window rect int iLeft, iTop; // Left and top int iWidth, iHeight; // Width and height GetWindowRect(hWnd, &rcItm); iWidth = rcItm.right - rcItm.left; iHeight= rcItm.bottom - rcItm.top; iLeft = rcItm.left+iWOffs; iTop = rcItm.top+iHOffs-20; SetWindowPos(hWnd,NULL,iLeft,iTop,iWidth,iHeight,SWP_NOZORDER); } //Set dialog item pos // static void SetDialogItemPosition(HWND hWnd, int iWOffs, int iHOffs) { RECT rcItm; // Dialog item rect RECT rcParent; // Parent item rect int iLeft, iTop; // Left and top // GetWindowRect retrieves screen coordinates GetWindowRect(hWnd, &rcItm); //Changed by A.Amenberg 27.06.2003 //GetAncestor supported from Win98 and WinNT SP4 //GetWindowRect(GetAncestor(hWnd, GA_PARENT), &rcParent); GetWindowRect(GetParent(hWnd), &rcParent); // for SetWindowPos we need left and right on PARENT. iLeft = (rcItm.left - rcParent.left) + iWOffs; iTop = (rcItm.top - rcParent.top) + iHOffs - 20; // subtract titlebar height // move, don't resize SetWindowPos(hWnd, NULL, iLeft, iTop, 0, 0, SWP_NOSIZE|SWP_NOZORDER); } //Center dialog //hMain - parent window, if NULL, then center in desktop // static void CenterDialogOnScreen(HWND hDlg, HWND hMain) { RECT rcParent; // Parent window client rect RECT rcDlg; // Dialog window rect int iLeft, iTop; // Top-left coordinates int iWidth, iHeight; // Width and height HWND hwnd; // Get frame window client rect in screen coordinates if (hMain == NULL) hwnd = GetDesktopWindow(); else hwnd = hMain; GetWindowRect(hwnd, &rcParent); // Determine the top-left point for the dialog to be centered GetWindowRect(hDlg, &rcDlg); iWidth = rcDlg.right - rcDlg.left; iHeight = rcDlg.bottom - rcDlg.top; iLeft = rcParent.left + (((rcParent.right - rcParent.left) - iWidth ) / 2); iTop = rcParent.top + (((rcParent.bottom - rcParent.top ) - iHeight) / 2); if (iLeft < 0) iLeft = 0; if (iTop < 0) iTop = 0; // Place the dialog MoveWindow(hDlg, iLeft, iTop, iWidth, iHeight, TRUE); } //Error messagebox // static void DispError(char *psError) { MessageBox(NULL,psError, "Dialog Unit Error",MB_OK|MB_SYSTEMMODAL|MB_ICONERROR); } //Helper routine. Take an input pointer, return closest //pointer that is aligned on a DWORD (4 byte) boundary. // static LPWORD lpwAlign (LPWORD lpIn) { ULONG ul; ul = (ULONG) lpIn; ul +=3; ul >>=2; ul <<=2; return((LPWORD)ul); } static BOOL Dialog_Create(void) { BOOL fRes = FALSE; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; int nchar; hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024); if (hgbl == NULL) return(fRes); lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Define a dialog box. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_SETFONT; lpdt->cdit = 4; // number of controls lpdt->x = 0; lpdt->y = 0; lpdt->cx = 205; lpdt->cy = 204; lpw = (LPWORD) (lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) *lpw++ = 0; // no caption text *lpw++ = 0x0008; // font size lpwsz = (LPWSTR) lpw; nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "MS Sans Serif", -1, lpwsz, 50); lpw += nchar; // Define an OK button. lpw = lpwAlign (lpw); lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->x = 152; lpdit->y = 182; lpdit->cx = 50; lpdit->cy = 14; lpdit->id = IDOK; // OK button identifier lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP; lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class *lpw++ = 0x0000; // no caption *lpw++ = 0; // no creation data // Define a Cancel button. lpw = lpwAlign (lpw); lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->x = 97; lpdit->y = 182; lpdit->cx = 50; lpdit->cy = 14; lpdit->id = IDCANCEL; //Cancel button identifier lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP; lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class atom *lpw++ = 0x0000; // no caption *lpw++ = 0; // no creation data // Define a groupbox control. lpw = lpwAlign (lpw); lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->x = 0; lpdit->y = 2; lpdit->cx = 205; lpdit->cy = 173; lpdit->id = IDC_GROUPBOX; // groupbox identifier lpdit->style = BS_GROUPBOX | WS_VISIBLE; lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // listbox *lpw++ = 0x0000; // no caption *lpw++ = 0; // no creation data // Define a listbox control. lpw = lpwAlign (lpw); lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->x = 4; lpdit->y = 12; lpdit->cx = 197; lpdit->cy = 158; lpdit->id = IDC_LISTVIEW; // listbox identifier lpdit->style = LBS_USETABSTOPS | LBS_NOTIFY | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP | LBS_NOINTEGRALHEIGHT | WS_BORDER; lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0083; // listbox *lpw++ = 0x0000; // no caption //if caption exist, delete previous line and remove next 3 lines comments //lpwsz = (LPWSTR) lpw; //nchar = 1+MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 50); //lpw += nchar; *lpw++ = 0; // no creation data GlobalUnlock(hgbl); fRes = TRUE; return(fRes); } libdigidoc-3.10.5/libdigidoc/DigiDocLib.c0000664000372000037200000011102613560273131017463 0ustar travistravis//================================================== // FILE: DigiDocLib.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for creating // and reading signed documents. // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 20.09.2004 Changed createOCSPRequest() to use custom functions for adding // OCSP nonce to OCSP request for digidoc formats 1.0, 1.1 and 1.2 // thereby guaranteing that in case of those formats only 20 bytes are sent. // This is necessary to guarantee backward compatibility with OpenSSL 0.9.6 // 22.08.2004 Added DataFile content caching, function ddocGetDataFileCachedData() // and modified functions readSignedDoc(), extractDataFile(), // ddocExtractDataFile(), ddocGetDataFile() and ddocCopyDataFile() to use it. // Added function ddocSaxReadSignedDocFromMemory() // New debugging interface ddocDebug() // 12.08.2004 Moved all SAX xml parsing functions to DigiDocSAXParser.c // and fixed some memory problems // 03.08.2004 Added check to initializeNotaryInfoWithOCSP() to handle 22 byte ASN.1 // encoded nonce with OpenSSL 0.9.7d // added a check on output filename for extractDataFile() function. // added a check for verifyNotaryInfoCERT() function to check empty certificate array size. // Added back the function verifyCertificateByOCSP() // 14.06.2004 Changed generateDataFileXML() to replaces '&' with '&' // int file names. Changed handleStartDataFile() acordingly. // 20.05.2004 Added new error codes to handle OCSP response // status and fixed initializeNotaryInfoWithOCSP() // 19.05.2004 Added a nullpointer test to checkFileExists() // 12.05.2004 Fixed convertStringToTimeT() by changing // timestamp format pattern according to 1.3 format version // 11.05.2004 Added error code ERR_OCSP_WRONG_URL to sendOCSPRequest // to indicate that the given server is not an OCSP server // 23.03.2004 fixed setSignatureValueFromFile() that was affected // by siganture caching. Fixed getConfirmation() to // allowe sending not signed OCSP requests. // 17.03.2004 fixed getSignerCode() to handle certs that // have no comma in CN. Fixed NotaryInfo_new to // reset szOrigContent of signature. Added function // handleOCSPCertStatus() to check cert status // and modified initializeNotaryInfoWithOCSP() and // checkNonceAndCertbyOCSP() // 11.03.2004 added SignedDoc namespace in format 1.3 // generateDataFileXML(), createSignedXMLDoc() // handleStartDataFile(), // bugs in emptying buffers // unicode2ascii(), getSignerLastName() // Veiko Sinivee // 25.11.2003 added functions calculateFileLength(), // verifyCertificateByOCSP() and helper functions // 21.11.2003 Fixed SignatureValue decoding problem // Veiko Sinivee // 17.11.2003 Aare Amenberg // Changed error texts // Changed sendOCSPRequest // (added more error checkings) // 14.11.2003 Aare Amenberg // Removed WriteOCSPResponse // Changed addNotaryInfoXML by Veiko // 11.11.2003 Aare Amenberg // Added CorrectCharacters // Added error 96 ERR_WRONG_URL_OR_PROXY // 31.10.2003 Aare Amenberg // Added error text 95 // Removed if(single->singleExtensions) // SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_SINGLE_EXT); // Function initializeNotaryInfoWithOCSP // 29.10.2003 Aare Amenberg // WIN32_CSP functions moved // to module DigiDocCsp // 1.0 09.04.2002 Veiko Sinivee // Supports XML format (Type: SK-XML-1.0) //================================================== #include #define WIN32_PKCS 1 #ifdef WIN32 #include #endif #include #include #include #include #include #include #include #include //AM #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x10010000L static EVP_MD_CTX *EVP_MD_CTX_new() { return (EVP_MD_CTX*)OPENSSL_malloc(sizeof(EVP_MD_CTX)); } static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { OPENSSL_free(ctx); } #else # define BIO_R_BAD_HOSTNAME_LOOKUP 102 # define OCSP_R_SERVER_WRITE_ERROR 116 #endif long int tzone = -7200; /* default for Estonia, but see initDigiDocLib() */ int daylight = 0; /* default, but see initDigiDocLib() */ //==========< global constants >==================== char g_szLibName[] = "CDigiDoc"; char g_szLibVer[] = DIGIDOC_VERSION; //char g_szLibVer[] = VERSION; char* g_szSupportedVersions[] = { "1.0", "1.1", "1.2", "1.3", "0.7" }; char* g_arrFormats[] = { SK_XML_1_NAME, DIGIDOC_XML_1_1_NAME, 0 }; FormatAndVer g_supportedFormatsAndVersions[] = { { SK_XML_1_NAME, SK_XML_1_VER }, { DIGIDOC_XML_1_1_NAME, DIGIDOC_XML_1_1_VER }, { DIGIDOC_XML_1_1_NAME, DIGIDOC_XML_1_2_VER }, { DIGIDOC_XML_1_1_NAME, DIGIDOC_XML_1_3_VER }, { NULL, NULL } // list end marker }; // static buffer for name & version of the program using this library #define GUI_VERSION_LEN 100 char g_szGUIVersion[GUI_VERSION_LEN]; //==========< global variables >==================== // forward deklaratsioon int notary2ocspBasResp(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo, X509* notCert, OCSP_BASICRESP** pBasResp); int calculateOcspBasicResponseDigest(OCSP_BASICRESP* pBsResp, byte* digBuf, int* digLen); int createOCSPRequest(SignedDoc* pSigDoc, OCSP_REQUEST **req, X509 *cert, X509 *pCA, byte* nonce, int nlen); EXP_OPTION int signOCSPRequestPKCS12(OCSP_REQUEST *req, const char* filename, const char* passwd); int verifyOCSPResponse(OCSP_RESPONSE* pResp, const X509** caCerts, const char *CApath, const X509* notCert); int checkNonceAndCertbyOCSP(OCSP_RESPONSE* resp, X509* cert, byte* nonce1, int nonceLen); int verifyResp(OCSP_BASICRESP* bs, const char *CA2file, const char *CA1file, const char *CApath, const char* notCertFile); extern int writeCertToXMLFile(BIO* bout, X509* cert); //==========< utility functions >==================== #ifdef WIN32 CRITICAL_SECTION cs_ddocLocaltime; #endif //-------------------------------------------------- // Converts timestamp (time_t) value to a struct // tm value. Caller must provide address of tm struct. // This function is used because loacltime() is not // thread-safe and win32 has no equvalent of localtime_r(). // pTime - time_t value address // pTmStruct - struct tm address // bLocal - 1=localtime_r, 0=gmtime_r // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocLocalTime(time_t* pTime, struct tm* pTmStruct, int bLocal) { #ifdef WIN32 struct tm *pTm; #endif RETURN_IF_NULL_PARAM(pTime); RETURN_IF_NULL_PARAM(pTmStruct); #ifdef WIN32 EnterCriticalSection(&cs_ddocLocaltime); if(bLocal) pTm = localtime(pTime); else pTm = gmtime(pTime); *pTmStruct = *pTm; LeaveCriticalSection(&cs_ddocLocaltime); #else if(bLocal) localtime_r(pTime, pTmStruct); else gmtime_r(pTime, pTmStruct); #endif return ERR_OK; } //==========< admin functions >==================== //-------------------------------------------------- // returns the library name //-------------------------------------------------- EXP_OPTION const char* getLibName() { return g_szLibName; } //-------------------------------------------------- // returns the library version //-------------------------------------------------- EXP_OPTION const char* getLibVersion() { return g_szLibVer; } //-------------------------------------------------- // returns an array of supported formats terminated by NULL //-------------------------------------------------- EXP_OPTION const char** getSupportedFormats() { return (const char**)g_arrFormats; } //-------------------------------------------------- // returns an array of supported formats and versions terminated by NULL //-------------------------------------------------- EXP_OPTION FormatAndVer* getSupportedFormatsAndVersions() { return g_supportedFormatsAndVersions; } //-------------------------------------------------- // Cheks a combination of format and version for validity // format - digidoc format name // version - version name // returns error code or ERR_OK //-------------------------------------------------- int ddocCheckFormatAndVer(const char* format, const char* version) { int i; if(!format || !version) return ERR_UNSUPPORTED_FORMAT; for(i = 0; i < SUPPORTED_VERSION_COUNT; i++) if(!strcmp(g_supportedFormatsAndVersions[i].szFormat, format) && !strcmp(g_supportedFormatsAndVersions[i].szVersion, version)) return ERR_OK; return ERR_UNSUPPORTED_FORMAT; } //-------------------------------------------------- // initializes DigiDoc library //-------------------------------------------------- EXP_OPTION void initDigiDocLib() { memset(g_szGUIVersion, 0, sizeof(g_szGUIVersion)); #if defined(__FreeBSD__) struct tm local_tm; time_t t; time(&t); ddocLocalTime(&t, &local_tm, 1); // Extract timezone info from struct tm _timezone = - local_tm.tm_gmtoff; _daylight = local_tm.tm_isdst; #endif //ddocDebug(1, "initDigiDocLib", "init openssl & digidoc lib"); ERR_load_ERR_strings(); ERR_load_crypto_strings(); ERR_clear_error(); OpenSSL_add_all_algorithms(); SSL_library_init(); #ifdef WIN32 InitializeCriticalSection(&cs_ddocErrors); InitializeCriticalSection(&cs_ddocLocaltime); #endif } //-------------------------------------------------- // returns the GUI version //-------------------------------------------------- EXP_OPTION const char* getGUIVersion() { return g_szGUIVersion; } //-------------------------------------------------- // sets the GUI version //-------------------------------------------------- EXP_OPTION void setGUIVersion(const char* szVer) { strncpy(g_szGUIVersion, szVer, sizeof(g_szGUIVersion)-1); } //-------------------------------------------------- // cleanup of DigiDoc library //-------------------------------------------------- EXP_OPTION void finalizeDigiDocLib() { ERR_free_strings(); EVP_cleanup(); } //==========< general crypto fucntions >============ //-------------------------------------------------- // Checks and prints errors //-------------------------------------------------- EXP_OPTION long checkErrors() { char buf[200]; long e=0; while((ERR_peek_error()) > ERR_LIB_NONE) { e = ERR_get_error(); ERR_error_string_n(e, buf, sizeof(buf)); // VS: keep silent !!! printf("ERROR: %ld - %s \n", e, buf); } ERR_clear_error(); return e; } //-------------------------------------------------- // Calculates files SHA1 digest // szFileName - file name // nDigestType - digest type. Supports only SHA1 (0) // pDigestBuf - buffer to store the digest // nDigestLen - buffer size, must be at least 20 // will be updated by actual digest length // lFileLen - pointer to a buffer where to store the file length // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int calculateFileDigest(const char* szFileName, int nDigestType, byte* pDigestBuf, int* nDigestLen, long* lFileLen) { int err = ERR_OK; byte buf[FILE_BUFSIZE]; int i; FILE *f = NULL; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(pDigestBuf); RETURN_IF_NULL_PARAM(nDigestLen); RETURN_IF_NULL_PARAM(lFileLen); memset(pDigestBuf, 0, *nDigestLen); if(nDigestType == DIGEST_SHA1) { if(*nDigestLen >= SHA_DIGEST_LENGTH) { SHA_CTX ctx; *nDigestLen = SHA_DIGEST_LENGTH; if((f = fopen(szFileName,"rb")) != NULL) { //byte *data,*temp_data; SHA1_Init(&ctx); *lFileLen = 0; for (;;) { i = fread(buf, sizeof(char), FILE_BUFSIZE, f); if (i <= 0) break; *lFileLen += i; SHA1_Update(&ctx, buf, (unsigned long)i); } SHA1_Final(pDigestBuf,&ctx); fclose(f); } // if - fopen else err = ERR_FILE_READ; } else err = ERR_DIGEST_LEN; } //AM 22.04.08 else if(nDigestType == DIGEST_SHA256){ if(*nDigestLen >= SHA_DIGEST_LENGTH) { SHA256_CTX ctx; *nDigestLen = SHA256_DIGEST_LENGTH; if((f = fopen(szFileName,"rb")) != NULL) { //byte *data,*temp_data; SHA256_Init(&ctx); *lFileLen = 0; for (;;) { i = fread(buf, sizeof(char), FILE_BUFSIZE, f); if (i <= 0) break; *lFileLen += i; SHA256_Update(&ctx, buf, (unsigned long)i); } SHA256_Final(pDigestBuf,&ctx); fclose(f); } // if - fopen else err = ERR_FILE_READ; } else err = ERR_DIGEST_LEN; } else err = ERR_UNSUPPORTED_DIGEST; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Calculates file size // szFileName - file name // lFileLen - pointer to a buffer where to store the file length // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int calculateFileSize(const char* szFileName, long* lFileLen) { FILE* hFile = 0; #ifdef WIN32 int i = 0, err = ERR_OK; wchar_t *convFileName = 0; #endif RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(lFileLen); if(!szFileName || !strlen(szFileName)) return 0; #ifdef WIN32 err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "calculateFileSize", "Opening FILE: %s, conv-file: %s len: %d", szFileName, convFileName, i); if((hFile = _wfopen(convFileName,L"rb")) != NULL) { #else if((hFile = fopen(szFileName,"rb")) != NULL) { #endif fseek(hFile, 0, SEEK_END); (*lFileLen) = ftell(hFile); ddocDebug(3, "calculateFileSize", "Closing FILE: %s, size: %ld", szFileName, (*lFileLen)); fclose(hFile); } // if - fopen else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); #ifdef WIN32 if(convFileName) free(convFileName); #endif return ERR_OK; } //-------------------------------------------------- // Calculates files SHA1-RSA signature // szFileName - file name // nDigestType - digest type. Supports only SHA1 (0) // pSigBuf - buffer to store the signature // nSigLen - buffer size, must be at least 128 // will be updated by actual signature length // keyfile - name of the private key file // passwd - private key password // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int calculateFileSignature(const char* szFileName, int nDigestType, byte* pSigBuf, int* nSigLen, const char *keyfile, const char* passwd) { int err = ERR_OK; EVP_MD_CTX *ctx; byte buf[FILE_BUFSIZE]; int i; FILE *f = NULL; EVP_PKEY* pkey = NULL; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(pSigBuf); RETURN_IF_NULL_PARAM(nSigLen); RETURN_IF_NULL_PARAM(keyfile); RETURN_IF_NULL_PARAM(passwd); memset(pSigBuf, 0, *nSigLen); if(nDigestType == DIGEST_SHA1) { if(*nSigLen >= SIGNATURE_LEN) { if((err = ReadPrivateKey(&pkey, keyfile, passwd, FILE_FORMAT_PEM)) == ERR_OK) { if((f = fopen(szFileName,"rb")) != NULL) { ctx = EVP_MD_CTX_new(); EVP_SignInit(ctx, EVP_sha1()); for (;;) { i = fread(buf, sizeof(char), FILE_BUFSIZE, f); if (i <= 0) break; EVP_SignUpdate (ctx, buf, (unsigned long)i); } err = EVP_SignFinal(ctx, pSigBuf, (unsigned int*)nSigLen, pkey); EVP_MD_CTX_free(ctx); if(err == ERR_LIB_NONE) err = ERR_OK; fclose(f); EVP_PKEY_free(pkey); } // if - fopen else err = ERR_FILE_READ; } else err = ERR_PRIVKEY_READ; } else err = ERR_SIGNATURE_LEN; } else err = ERR_UNSUPPORTED_DIGEST; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Calculates input datas SHA1-RSA signature // data - input data // dlen - input data length // nDigestType - digest type. Supports only SHA1 (0) // pSigBuf - buffer to store the signature // nSigLen - buffer size, must be at least 128 // will be updated by actual signature length // keyfile - name of the private key file // passwd - private key password // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int signData(const byte* data, int dlen, byte* pSigBuf, int* nSigLen, int nDigestType, const char *keyfile, const char* passwd) { int err = ERR_OK; EVP_MD_CTX *ctx; EVP_PKEY* pkey; RETURN_IF_NULL_PARAM(data); RETURN_IF_NULL_PARAM(pSigBuf); RETURN_IF_NULL_PARAM(nSigLen); RETURN_IF_NULL_PARAM(keyfile); RETURN_IF_NULL_PARAM(passwd); memset(pSigBuf, 0, *nSigLen); if(nDigestType == DIGEST_SHA1) { if(*nSigLen >= SIGNATURE_LEN) { if((err = ReadPrivateKey(&pkey, keyfile, passwd, FILE_FORMAT_PEM)) == ERR_OK) { ctx = EVP_MD_CTX_new(); EVP_SignInit(ctx, EVP_sha1()); EVP_SignUpdate (ctx, data, (unsigned long)dlen); err = EVP_SignFinal(ctx, pSigBuf, (unsigned int*)nSigLen, pkey); EVP_MD_CTX_free(ctx); if(err == ERR_LIB_NONE) err = ERR_OK; EVP_PKEY_free(pkey); } else err = ERR_PRIVKEY_READ; } else err = ERR_SIGNATURE_LEN; } else err = ERR_UNSUPPORTED_DIGEST; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Calculates files SHA1 digest // szFileName - file name // nDigestType - digest type. Supports only SHA1 (0) // pDigestBuf - buffer to store the digest // nDigestLen - buffer size, must be at least 20 // will be updated by actual digest length // returns error code or ERR_OK for success //-------------------------------------------------- EXP_OPTION int calculateDigest(const byte* data, int nDataLen, int nDigestType, byte* pDigestBuf, int* nDigestLen) { int err = ERR_OK; RETURN_IF_NULL_PARAM(data); RETURN_IF_NULL_PARAM(pDigestBuf); RETURN_IF_NULL_PARAM(nDigestLen); memset(pDigestBuf, 0, *nDigestLen); if(nDigestType == DIGEST_SHA1) { if(*nDigestLen >= SHA_DIGEST_LENGTH) { *nDigestLen = SHA_DIGEST_LENGTH; SHA1(data, nDataLen, pDigestBuf); } }//AM 22.04.08 else if(nDigestType == DIGEST_SHA256) { if(*nDigestLen >= SHA256_DIGEST_LENGTH) { *nDigestLen = SHA256_DIGEST_LENGTH; SHA256(data, nDataLen, pDigestBuf); } else err = ERR_DIGEST_LEN; } else err = ERR_UNSUPPORTED_DIGEST; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //==========< signed doc fucntions >================ //============================================================ // Get the filename part of full file name //============================================================ EXP_OPTION const char* getSimpleFileName(const char* szFileName) { const char *p; RETURN_OBJ_IF_NULL(szFileName, NULL); for(p = szFileName + strlen(szFileName) -1; (p > szFileName) && (*p != '\\') && (*p != '/'); p--); if((*p == '\\') || (*p == '/')) p++; return p; } //============================================================ // Get the absolute filename with path //============================================================ EXP_OPTION int getFullFileName(const char* szFileName, char* szDest, int len) { int err = ERR_OK; memset(szDest, 0, len); // if this is a filename with path then we are ready if(strchr(szFileName, '/') || strchr(szFileName, '\\')) { strncpy(szDest, szFileName, len); } else { // local filename, must prepend directory _getcwd(szDest, len); #ifdef WIN32 if(strlen(szDest) < (size_t)(len - 2)) strncat(szDest, "\\", sizeof(szDest) - strlen(szDest)); #else if(strlen(szDest) < (size_t)(len - 2)) strncat(szDest, "/", sizeof(szDest) - strlen(szDest)); #endif if(strlen(szDest) + strlen(szFileName) < (size_t)(len - 2)) strncat(szDest, szFileName, sizeof(szDest) - strlen(szDest)); } return err; } //============================================================ // Get the path part of full file name //============================================================ EXP_OPTION int getFileNamePath(const char* szFileName, char* szPath, int len) { int nFound = 0, i, err = ERR_OK; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(szPath); strncpy(szPath, szFileName, len); for(i = strlen(szPath); i >= 0; i--) { if(szPath[i] == '\\') { szPath[i+1] = 0; nFound = 1; break; } } if(!nFound) szPath[0] = 0; return err; } //============================================================ // Gets a new temporary filename // buf - filename buffer //============================================================ EXP_OPTION int getTempFileName(char* szFileName, int len) { int f = 0; char* pFileName = 0; RETURN_IF_NULL_PARAM(szFileName); memset(szFileName, 0, len); #ifdef WIN32 pFileName = _tempnam(0, "ddoc"); #else pFileName = tempnam(0, "ddoc"); #endif strncpy(szFileName, pFileName, len); free(pFileName); return ERR_OK; } //============================================================ // Sets the signatures certificate and calculates // certificate digest & serial number // pSigInfo - signature info object // cert - certficate //============================================================ EXP_OPTION int setSignatureCert(SignatureInfo* pSigInfo, X509* cert) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(cert); err = ddocSigInfo_addCert(pSigInfo, cert, CERTID_TYPE_SIGNERS_CERTID); // release old content if it exists ddocMemBuf_free(&(pSigInfo->mbufOrigContent)); return ERR_OK; } //============================================================ // Sets the signatures certificate and calculates // certificate digest & serial number // pSigInfo - signature info object // certFile - certficate file in PEM //============================================================ EXP_OPTION int setSignatureCertFile(SignatureInfo* pSigInfo, const char* certFile) { X509 *cert = NULL; int err = ERR_OK; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(certFile); err = ReadCertificate(&cert, certFile); RETURN_IF_NOT(err == ERR_OK, err); return setSignatureCert(pSigInfo, cert);; } //-------------------------------------------------- // Checks if this file exists // szFileName - file name // returns 1 if exists // AA 2004/05/20 debuggeri all viga, kui null pikkus //-------------------------------------------------- EXP_OPTION int checkFileExists(const char* szFileName) { FILE* hFile = 0; int exists = 0; #ifdef WIN32 int i = 0, err = ERR_OK; wchar_t *convFileName = 0; #endif if(szFileName && strlen(szFileName) > 0) { #ifdef WIN32 err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); if((hFile = _wfopen(convFileName, L"r")) != NULL) { #else if((hFile = fopen(szFileName, "r")) != NULL) { #endif exists = 1; fclose(hFile); } } #ifdef WIN32 if(convFileName) free(convFileName); #endif return exists; } //================< certficate info functions> ================================= //-------------------------------------------------- // Returns the user signatures certificate data // pSignInfo - signature object // returns cert data. This is actually X509*. Obsolete function //-------------------------------------------------- EXP_OPTION X509* getSignCertData(const SignatureInfo* pSignInfo) { RETURN_OBJ_IF_NULL(pSignInfo, 0); return ddocSigInfo_GetSignersCert(pSignInfo); } //-------------------------------------------------- // sends an OCSP_REQUES object to remore server and // retrieves the OCSP_RESPONSE object // resp - buffer to store the new responses pointer // req - request objects pointer // url - OCSP responder URL //-------------------------------------------------- int ddocPullUrl(const char* url, DigiDocMemBuf* pSendData, DigiDocMemBuf* pRecvData, const char* proxyHost, const char* proxyPort) { BIO* cbio = 0, *sbio = 0; SSL_CTX *ctx = NULL; char *host = NULL, *port = NULL, *path = "/", buf[200]; int err = ERR_OK, use_ssl = -1, rc; long e; //RETURN_IF_NULL_PARAM(pSendData); // may be null if nothing to send? RETURN_IF_NULL_PARAM(pRecvData); RETURN_IF_NULL_PARAM(url); ddocDebug(4, "ddocPullUrl", "URL: %s, in: %d bytes", url, pSendData->nLen); //there is an HTTP proxy - connect to that instead of the target host if (proxyHost != 0 && *proxyHost != '\0') { host = (char*)proxyHost; if(proxyPort != 0 && *proxyPort != '\0') port = (char*)proxyPort; path = (char*)url; } else { if(OCSP_parse_url((char*)url, &host, &port, &path, &use_ssl) == 0) { ddocDebug(1, "ddocPullUrl", "Failed to parse the URL"); return ERR_WRONG_URL_OR_PROXY; } } if((cbio = BIO_new_connect(host)) != 0) { ddocDebug(4, "ddocPullUrl", "Host: %s port: %s", host, port); if(port != NULL) { BIO_set_conn_port(cbio, port); } if(use_ssl == 1) { ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); sbio = BIO_new_ssl(ctx, 1); cbio = BIO_push(sbio, cbio); } if ((rc = BIO_do_connect(cbio)) > 0) { ddocDebug(4, "ddocPullUrl", "Connected: %d", rc); if(pSendData && pSendData->nLen && pSendData->pMem) { rc = BIO_write(cbio, pSendData->pMem, pSendData->nLen); ddocDebug(4, "ddocPullUrl", "Sent: %d bytes, got: %d", pSendData->nLen, rc); } do { memset(buf, 0, sizeof(buf)); rc = BIO_read(cbio, buf, sizeof(buf)-1); ddocDebug(4, "ddocPullUrl", "Received: %d bytes\n", rc); if(rc > 0) err = ddocMemAppendData(pRecvData, buf, rc); } while(rc > 0); ddocDebug(4, "ddocPullUrl", "Total received: %d bytes\n", pRecvData->nLen); } else { //if no connection e = checkErrors(); if(ERR_GET_REASON(e) == BIO_R_BAD_HOSTNAME_LOOKUP || ERR_GET_REASON(e) == OCSP_R_SERVER_WRITE_ERROR) err = ERR_CONNECTION_FAILURE; else err = (host != NULL) ? ERR_WRONG_URL_OR_PROXY : ERR_CONNECTION_FAILURE; } BIO_free_all(cbio); if (use_ssl != -1) { OPENSSL_free(host); OPENSSL_free(port); OPENSSL_free(path); SSL_CTX_free(ctx); } } else err = ERR_CONNECTION_FAILURE; return(err); } // ASN1 structure prefix - RSA-SHA1 signature with 20 bytes follows char g_sigPrefix[] = { 48, 33, 48, 9, 6, 5, 43, 14, 3, 2, 26, 5, 0, 4, 20 }; //-------------------------------------------------- // Prepares a new signature for signing and calculates // the final hash value to sign. // pSigDoc - signed document object // ppSigInfo - pointer for address of newly allocated signature // manifest - manifest or role // city - signers address , city // state - signers address , state or province // zip - signers address , postal code // country - signers address , country name // id - id for new signature. Optional, use NULL for default // return returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocPrepareSignature(SignedDoc* pSigDoc, SignatureInfo** ppSigInfo, const char* manifest, const char* city, const char* state, const char* zip, const char* country, X509* pCert, const char* id) { int err = ERR_OK, l1; DigiDocMemBuf mbuf1, *pMBuf1; char buf1[50]; mbuf1.pMem = 0; mbuf1.nLen = 0; ddocDebug(3, "ddocPrepareSignature", "Preparing signature manifest: %s country: %s, state: %s, city: %s, zip: %s, cert: %s, id: %s", (manifest ? manifest : "NULL"), (country ? country : "NULL"), (state ? state : "NULL"), (city ? city : "NULL"), (zip ? zip : "NULL"), (pCert ? "OK" : "ERROR"), (id ? id : "NULL")); // check mandator fields RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(ppSigInfo); RETURN_IF_NULL_PARAM(pCert); clearErrors(); // add new signature err = SignatureInfo_new(ppSigInfo, pSigDoc, id); RETURN_IF_NOT(err == ERR_OK, err); // automatically calculate doc-info elements for this signature addAllDocInfos(pSigDoc, *ppSigInfo); // add signature production place if (city || state || zip || country) err = setSignatureProductionPlace(*ppSigInfo, city, state, zip, country); // add user roles/manifests if (manifest) err = addSignerRole(*ppSigInfo, 0, manifest, -1, 0); RETURN_IF_NOT(err == ERR_OK, err); // add signers certificate err = setSignatureCert(*ppSigInfo, pCert); RETURN_IF_NOT(err == ERR_OK, err); // timestamp createTimestamp(pSigDoc, (char*)buf1, sizeof(buf1)); setString((char**)&((*ppSigInfo)->szTimeStamp), (const char*)buf1, -1); // now calculate signed properties digest err = calculateSignedPropertiesDigest(pSigDoc, *ppSigInfo); // TODO: replace later pMBuf1 = ddocDigestValue_GetDigestValue((*ppSigInfo)->pSigPropDigest); ddocSigInfo_SetSigPropRealDigest(*ppSigInfo, (const char*)pMBuf1->pMem, pMBuf1->nLen); // signature type & val ddocSignatureValue_new(&((*ppSigInfo)->pSigValue), 0, SIGN_RSA_NAME, 0, 0); // calc signed-info digest l1 = sizeof(buf1); err = calculateSignedInfoDigest(pSigDoc, *ppSigInfo, (byte*)buf1, &l1); err = ddocSigInfo_SetSigInfoRealDigest(*ppSigInfo, buf1, l1); // debug output - final hash to sign pMBuf1 = ddocDigestValue_GetDigestValue((*ppSigInfo)->pSigInfoRealDigest); ddocEncodeBase64(pMBuf1, &mbuf1); ddocDebug(3, "ddocPrepareSignature", "signing hash %s len: %d b64len: %d", (char*)mbuf1.pMem, mbuf1.nLen, l1); ddocMemBuf_free(&mbuf1); return err; } //-------------------------------------------------- // Returns the hash to be signed with or without ASN1 // prefix and with or without base64 encoding // pSigInfo - signature address // pBuf - buffer for hash value with or without prefix // pBufLen - pointer to buffer length // enc - return 0=unencoded, 1=base64, 2=hex // bWithAsn1Prefix - return with or without ASN1 prefix 1/0 // return returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocGetSignedHash(SignatureInfo* pSigInfo, char* pBuf, int* pBufLen, int enc, int bWithAsn1Prefix) { int err = ERR_OK, l1 = 0; char buf1[50]; DigiDocMemBuf *pMBuf; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pBuf); //RETURN_IF_NOT(err == ERR_OK, err); // TODO: check buflen pMBuf = ddocDigestValue_GetDigestValue(pSigInfo->pSigInfoRealDigest); RETURN_IF_NULL_PARAM(pMBuf); memset(buf1, 0, sizeof(buf1)); if(enc == 2) { // hex mode if(bWithAsn1Prefix) { if(sizeof(buf1) > sizeof(g_sigPrefix) + pMBuf->nLen) { memcpy(buf1, g_sigPrefix, sizeof(g_sigPrefix)); memcpy(buf1 + sizeof(g_sigPrefix), pMBuf->pMem, pMBuf->nLen); l1 = pMBuf->nLen + sizeof(g_sigPrefix); } else err = ERR_BUF_LEN; } else { if(sizeof(buf1) > (size_t)pMBuf->nLen) { memcpy(buf1, pMBuf->pMem, pMBuf->nLen); l1 = pMBuf->nLen; } else err = ERR_BUF_LEN; } bin2hex((const byte*)buf1, l1, (char*)pBuf, pBufLen); } else if(enc == 1) { // base64 mode if(bWithAsn1Prefix) { if(sizeof(buf1) > sizeof(g_sigPrefix) + (size_t)pMBuf->nLen) { memcpy(buf1, g_sigPrefix, sizeof(g_sigPrefix)); memcpy(buf1 + sizeof(g_sigPrefix), pMBuf->pMem, pMBuf->nLen); l1 = pMBuf->nLen + sizeof(g_sigPrefix); } else err = ERR_BUF_LEN; } else { if(sizeof(buf1) > (size_t)pMBuf->nLen) { memcpy(buf1, pMBuf->pMem, pMBuf->nLen); l1 = pMBuf->nLen; } else err = ERR_BUF_LEN; } encode((const byte*)buf1, l1, (byte*)pBuf, pBufLen); } else { if(bWithAsn1Prefix) { if(*pBufLen > (int)sizeof(g_sigPrefix) + pMBuf->nLen) { memcpy(pBuf, g_sigPrefix, sizeof(g_sigPrefix)); memcpy(pBuf + sizeof(g_sigPrefix), pMBuf->pMem, pMBuf->nLen); *pBufLen = pMBuf->nLen + sizeof(g_sigPrefix); } else err = ERR_BUF_LEN; } else { if(*pBufLen > pMBuf->nLen) { *pBufLen = pMBuf->nLen; memcpy(pBuf, pMBuf->pMem, pMBuf->nLen); } else err = ERR_BUF_LEN; } } return err; } //================< deprecated functions> ================================= #ifdef WITH_DEPRECATED_FUNCTIONS // get signers id-code EXP_OPTION int getSignerCode(const SignatureInfo* pSigInfo, char* buf) { int err, l1; X509* cert; char buf1[500], *p; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(buf); cert = getSignCertData(pSigInfo); if (!cert) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_INVALID); l1 = sizeof(buf1); err = getCertSubjectName(cert, buf1, &l1); if (err != ERR_OK) SET_LAST_ERROR_RETURN_CODE(err); err = ERR_CERT_READ; p = strstr(buf1, "CN="); if (p) { p = strchr(p, ','); if(p) { p = strchr(p+1, ','); if(p) { strncpy(buf, p+1, 11); buf[11] = 0; err = ERR_OK; } } else { // no comma -> no id-code ! buf[0] = 0; // is this really an error ? err = ERR_WRONG_CERT; } } if (err != ERR_OK) SET_LAST_ERROR(err); return err; } // get signers first name EXP_OPTION int getSignerFirstName(const SignatureInfo* pSigInfo, char* buf) { int err = ERR_OK, l1; X509* cert; char buf1[500], *p, *p2, *p1; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(buf); cert = getSignCertData(pSigInfo); if (!cert) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_INVALID); l1 = sizeof(buf1); err = getCertSubjectName(cert, buf1, &l1); if (err != ERR_OK) SET_LAST_ERROR_RETURN_CODE(err); p = strstr(buf1, "CN="); if (p) { p1 = strchr(p, ','); if(!p1) p1 = strchr(p, '/'); if (p1) { p1 += 1; p2 = strchr(p1, ','); if(!p2) p2 = strchr(p1, '/'); if(p2) { strncpy(buf, p1, p2-p1); buf[p2-p1] = 0; err = ERR_OK; } } } if (err != ERR_OK) SET_LAST_ERROR(err); return err; } // get signers last name EXP_OPTION int getSignerLastName(const SignatureInfo* pSigInfo, char* buf) { int err = ERR_OK, l1; X509* cert; char buf1[500], *p, *p2; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(buf); cert = getSignCertData(pSigInfo); if (!cert) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_INVALID); l1 = sizeof(buf1); err = getCertSubjectName(cert, buf1, &l1); if (err != ERR_OK) SET_LAST_ERROR_RETURN_CODE(err); p = strstr(buf1, "CN="); if(p) { p += 3; p2 = strchr(p, ','); if(!p2) p2 = strchr(p, '/'); if(p2) { strncpy(buf, p, p2-p); buf[p2-p] = 0; err = ERR_OK; } else { strncpy(buf, p, strlen(p)); } } if (err != ERR_OK) SET_LAST_ERROR(err); return err; } EXP_OPTION int getSignerCN(const SignatureInfo* pSigInfo, char* buf, int bUTF8) { int err = ERR_OK, l1; X509* cert; char buf1[500], *p, *p2, buf2[500]; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(buf); cert = getSignCertData(pSigInfo); if (!cert) SET_LAST_ERROR_RETURN_CODE(ERR_CERT_INVALID); l1 = sizeof(buf1); err = getCertSubjectName(cert, buf1, &l1); if (err != ERR_OK) SET_LAST_ERROR_RETURN_CODE(err); if(!bUTF8) { l1 = sizeof(buf2); utf82ascii(buf1, buf2, &l1); strncpy(buf1, buf2, sizeof(buf1)); } err = ERR_CERT_READ; p = strstr(buf1, "CN="); if (p) { p += 3; p2 = strchr(p, '/'); if(!p2) p2 = p + strlen(p); if (p2) { strncpy(buf, p, p2-p); buf[p2-p] = 0; err = ERR_OK; } } if (err != ERR_OK) SET_LAST_ERROR(err); return err; } #endif // WITH_DEPRECATED_FUNCTIONS libdigidoc-3.10.5/libdigidoc/DigiDocDfExtract.h0000664000372000037200000000354513560273131020654 0ustar travistravis#ifndef __DIGIDOC_DF_EXTRACT_H__ #define __DIGIDOC_DF_EXTRACT_H__ //================================================== // FILE: DigiDocDfExtract.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for extracting contents // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 03.03.2008 Veiko Sinivee // Creation //================================================== #include #ifdef __cplusplus extern "C" { #endif //-------------------------------------------------- // Reads in signed XML document and extracts the desired data file // pSigDoc - signed document object if exists. Can be NULL // szFileName - digidoc filename // szDataFileName - name of the file where to store embedded data. // szDocId - DataFile Id atribute value // szCharset - convert DataFile content to charset //-------------------------------------------------- EXP_OPTION int ddocExtractDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDataFileName, const char* szDocId, const char* szCharset); #ifdef __cplusplus } #endif #endif libdigidoc-3.10.5/libdigidoc/res.rc0000664000372000037200000000471013560273131016506 0ustar travistravis//Microsoft Developer Studio generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.K.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_DLG_UNIT34 DIALOGEX 0, 0, 300, 155 STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "DigiDoc" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN DEFPUSHBUTTON "&OK",IDOK,240,136,50,14 GROUPBOX "Select certificate:",IDC_GROUPBOX,2,2,296,126 PUSHBUTTON "&Cancel",IDCANCEL,180,136,50,14 CONTROL "List1",IDC_LISTVIEW,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | WS_BORDER | WS_TABSTOP,6,12,288,110,WS_EX_CLIENTEDGE END #endif // English (U.K.) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Unknown language: 0x25, 0x1 resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ETI) #ifdef _WIN32 LANGUAGE 0x25, 0x1 #pragma code_page(1257) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #endif // Unknown language: 0x25, 0x1 resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED libdigidoc-3.10.5/libdigidoc/CMakeLists.txt0000664000372000037200000001015413560273131020126 0ustar travistravisconfigure_file( ${CMAKE_SOURCE_DIR}/etc/digidoc.conf.cmake ${CMAKE_CURRENT_BINARY_DIR}/${DIGIDOC_CONF_NAME} @ONLY ) FILE( GLOB CERTS ${CMAKE_SOURCE_DIR}/etc/certs/*.crt ) set( PUBLIC_HEADER DigiDocCert.h DigiDocConfig.h DigiDocConvert.h DigiDocDebug.h DigiDocDefs.h DigiDocDfExtract.h DigiDocEncGen.h DigiDocEnc.h DigiDocEncSAXParser.h DigiDocError.h DigiDocGen.h DigiDocLib.h DigiDocMem.h DigiDocObj.h DigiDocOCSP.h DigiDocParser.h # DigiDocPKCS11.h DigiDocSAXParser.h DigiDocStack.h DigiDocVerify.h DigiDocHTTP.h DigiDocService.h ) if( WIN32 ) add_definitions( -DWITH_SOAPDEFS_H -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS ) list( APPEND libdigidoc_SRCS DigiDocGlobals.c DigiDocCSP.c DigiCrypt.c DlgUnit.c DlgUnitS.c ) set( EXT_LIBRARIES Crypt32 Comctl32 ) endif() add_library( digidoc ${BUILD_TYPE} ${PUBLIC_HEADER} ${CMAKE_CURRENT_BINARY_DIR}/${DIGIDOC_CONF_NAME} ${libdigidoc_SRCS} ${CERTS} libdigidoc.rc DigiDocConfig.c DigiDocLib.c DigiDocObj.c DigiDocPKCS11.c DigiDocError.c DigiDocParser.c DigiDocDebug.c DigiDocSAXParser.c DigiDocMem.c DigiDocStack.c DigiDocEnc.c DigiDocEncGen.c DigiDocEncSAXParser.c DigiDocCert.c DigiDocConvert.c DigiDocGen.c DigiDocVerify.c DigiDocOCSP.c DigiDocDfExtract.c DigiDocHTTP.c DigiDocService.c ) target_link_libraries( digidoc ${CMAKE_DL_LIBS} ${LIBXML2_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${EXT_LIBRARIES} ) set_target_properties( digidoc PROPERTIES VERSION ${MAJOR_VER}.${MINOR_VER}.${RELEASE_VER} SOVERSION 2 PUBLIC_HEADER "${PUBLIC_HEADER}" RESOURCE ${CMAKE_CURRENT_BINARY_DIR}/${DIGIDOC_CONF_NAME} FRAMEWORK_VERSION 2 FRAMEWORK "${FRAMEWORK}" MACOSX_FRAMEWORK_IDENTIFIER "ee.ria.libdigidoc" MACOSX_RPATH YES ) if( BUILD_TOOLS ) add_executable(cdigidoc cdigidoc.c cdigidoc.rc) target_link_libraries(cdigidoc digidoc) endif() install( TARGETS digidoc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RESOURCE DESTINATION ${CMAKE_INSTALL_SYSCONFDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libdigidoc FRAMEWORK DESTINATION /Library/Frameworks ) if(WIN32) install(FILES $ $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) endif() if( FRAMEWORK ) set_target_properties( digidoc PROPERTIES OUTPUT_NAME "libdigidoc" COMPILE_DEFINITIONS "FRAMEWORK" LINK_FLAGS "-framework CoreFoundation -framework Security" RESOURCE "${CERTS};${CMAKE_CURRENT_BINARY_DIR}/${DIGIDOC_CONF_NAME}" ) add_custom_command( TARGET cdigidoc POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ $/Resources ) add_custom_target( codesign DEPENDS cdigidoc COMMAND codesign -f -s ${SIGNCERT} $/Resources/cdigidoc $/../.. COMMAND touch $ ) if(INSTCERT) set(PKGEXTRA --sign ${INSTCERT}) endif() add_custom_target( pkgbuild DEPENDS cdigidoc COMMAND make install DESTDIR=install COMMAND pkgbuild --root install ${PKGEXTRA} ${CMAKE_BINARY_DIR}/libdigidoc_${VERSION}$ENV{VER_SUFFIX}.pkg ) add_custom_target( zipdebug DEPENDS cdigidoc COMMAND dsymutil -o libdigidoc.dSYM $ COMMAND dsymutil -o libdigidoc.dSYM $ COMMAND zip -r ${CMAKE_BINARY_DIR}/libdigidoc-dbg_${VERSION}$ENV{VER_SUFFIX}.zip libdigidoc.dSYM ) else() configure_file( libdigidoc.pc.cmake libdigidoc.pc @ONLY ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libdigidoc.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) install( FILES ${CERTS} DESTINATION ${CMAKE_INSTALL_FULL_DATADIR}/libdigidoc ) if( BUILD_TOOLS ) install( TARGETS cdigidoc DESTINATION ${CMAKE_INSTALL_BINDIR} ) configure_file( cdigidoc.1.cmake cdigidoc.1 ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/cdigidoc.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 ) endif() endif() #install( FILES # pkcs11/pkcs11.h # pkcs11/pkcs11f.h # pkcs11/pkcs11t.h # pkcs11/unix.h # pkcs11/cryptoki.h # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libdigidoc/pkcs11 #) libdigidoc-3.10.5/libdigidoc/DigiDocError.c0000664000372000037200000006107013560273131020051 0ustar travistravis#ifdef WIN32 #include #else #ifdef USEPTHREADS #include #endif #include #include #endif #include #include #include #define ERR_MAX 179 //number of error codes. Increment, if you add a new error code ErrorMessage g_ddocErrorStrings[ERR_MAX] = { /* ERR_OK */ {"No errors", NO_ERRORS}, /* ERR_UNSUPPORTED_DIGEST */ {"Digest type is not supported", LIBRARY}, /* ERR_FILE_READ */ {"Could not open file for reading", USER}, /* ERR_FILE_WRITE */ {"Could not open file for writing", USER}, /* ERR_DIGEST_LEN */ {"Wrong digest length", LIBRARY}, /* ERR_BUF_LEN */ {"Insufficient target buffer length", LIBRARY}, /* ERR_SIGNATURE_LEN */ {"Wrong signature length", LIBRARY}, /* ERR_PRIVKEY_READ */ {"Failed to read the private key", TECHNICAL}, /* ERR_PUBKEY_READ */ {"Failed to read the public key", TECHNICAL}, /* ERR_CERT_READ */ {"Failed to read certificate", USER}, /* ERR_SIGNEDINFO_CREATE */ {"Could not create SignedInfo object", LIBRARY}, /* ERR_SIGNEDINFO_DATA */ {"Could not create SignedInfo object", LIBRARY}, /* ERR_SIGNEDINFO_FINAL */ {"Could not create SignedInfo object", LIBRARY}, /* ERR_UNSUPPORTED_FORMAT */ {"Wrong signed document format", TECHNICAL}, /* ERR_BAD_INDEX */ {"Bad index", LIBRARY}, /* ERR_TIMESTAMP_DECODE */ {"Failed to decode timestamp", TECHNICAL}, /* ERR_DIGIDOC_PARSE */ {"Error in document parsing", USER}, /* ERR_UNSUPPORTED_SIGNATURE */ {"Signature type is not supported", LIBRARY}, /* ERR_CERT_STORE_READ */ {"Could not read read certificate from certificate store", TECHNICAL}, /* ERR_SIGPROP_DIGEST */ {"Wrong signature properties digest", TECHNICAL}, /* ERR_COMPARE */ {"Wrong signature", USER}, /* ERR_DOC_DIGEST */ {"Wrong document digest", USER}, /* ERR_MIME_DIGEST */ {"Wrong document mime digest", TECHNICAL}, /* ERR_SIGNATURE */ {"Wrong signature", TECHNICAL}, /* ERR_CERT_INVALID */ {"Invalid certificate", TECHNICAL}, /* ERR_OCSP_UNSUCCESSFUL */ {"OCSP request unsuccessful", TECHNICAL}, /* ERR_OCSP_UNKNOWN_TYPE */ {"Unknown OCSP type", TECHNICAL}, /* ERR_OCSP_NO_BASIC_RESP */ {"No OCSP basic responce", TECHNICAL}, /* ERR_OCSP_WRONG_VERSION */ {"Wrong OCSP version", TECHNICAL}, /* ERR_OCSP_WRONG_RESPID */ {"Wrong OCSP response id", TECHNICAL}, /* ERR_OCSP_ONE_RESPONSE */ {"Incorrect OCSP response count", TECHNICAL}, /* ERR_OCSP_RESP_STATUS */ {"Incorrect OCSP response status", USER}, /* ERR_OCSP_NO_SINGLE_EXT */ {"No single OCSP responce", TECHNICAL}, /* ERR_OCSP_NO_NONCE */ {"NONCE is missing", LIBRARY}, /* ERR_NOTARY_NO_SIGNATURE */ {"Missing signature for Notary", TECHNICAL}, /* ERR_NOTARY_SIG_MATCH */ {"Notary signature mismatch", USER}, /* ERR_SIGNERS_CERT_NOT_TRUSTED */ {"Signers cert not trusted, missing CA cert!", USER}, /* ERR_WRONG_CERT */ {"Wrong certificate", USER}, /* ERR_NULL_POINTER */ {"Null pointer exception", LIBRARY}, /* ERR_NULL_CERT_POINTER */ {"Certificate pointer is null", LIBRARY}, /* ERR_NULL_SER_NUM_POINTER */ {"Certificate Number pointer is null", LIBRARY}, /* ERR_NULL_KEY_POINTER */ {"Key pointer is null", LIBRARY}, /* ERR_EMPTY_STRING */ {"Empty string", LIBRARY}, /* ERR_BAD_DATAFILE_INDEX */ {"Datafile index out of range", LIBRARY}, /* ERR_BAD_DATAFILE_COUNT */ {"Datafile count is out of sync", LIBRARY}, /* ERR_BAD_ATTR_COUNT */ {"Attribute counter is out of sync", LIBRARY}, /* ERR_BAD_ATTR_INDEX */ {"Attribute index is out of range", LIBRARY}, /* ERR_BAD_SIG_INDEX */ {"Signature index is out of range", LIBRARY}, /* ERR_BAD_SIG_COUNT */ {"Signature count is out of sync", LIBRARY}, /* ERR_BAD_ROLE_INDEX */ {"Role index is out of range", LIBRARY}, /* ERR_BAD_DOCINFO_COUNT */ {"Document info count is out of sync", LIBRARY}, /* ERR_BAD_DOCINFO_INDEX */ {"Document info index is out of range", LIBRARY}, /* ERR_BAD_NOTARY_INDEX */ {"Notary index is out of range", LIBRARY}, /* ERR_BAD_NOTARY_ID */ {"Bad notary ID", LIBRARY}, /* ERR_BAD_NOTARY_COUNT */ {"Notary count is out of sync", LIBRARY}, /* ERR_X509_DIGEST */ {"X509 digest creation failed", LIBRARY}, /* ERR_CERT_LENGTH */ {"Wrong certificate length", LIBRARY}, /* ERR_PKCS_LIB_LOAD */ {"PKCS #11 DLL load failed", TECHNICAL}, /* ERR_PKCS_SLOT_LIST */ {"Getting PKCS #11 slot list failed", TECHNICAL}, /* ERR_PKCS_WRONG_SLOT */ {"No such PKCS #11 slot", TECHNICAL}, /* ERR_PKCS_LOGIN */ {"No EstID card, wrong PIN or PIN blocked", USER}, /* ERR_PKCS_PK */ {"Locating private key from EstID failed", TECHNICAL}, /* ERR_PKCS_CERT_LOC */ {"Reading certificate from EstID failed", TECHNICAL}, /* ERR_PKCS_CERT_DECODE */ {"Decoding certificate failed", LIBRARY}, /* ERR_PKCS_SIGN_DATA */ {"Signing data with EstID failed", USER}, /* ERR_PKCS_CARD_READ */ {"Reading EstID card failed", USER}, /* ERR_CSP_NO_CARD_DATA */ {"No EstID card, or card can not be read", USER}, /* ERR_CSP_OPEN_STORE */ {"Can not open system store", TECHNICAL}, /* ERR_CSP_CERT_FOUND*/ {"Certificate not found from store, probably cetificate not registered", USER}, /* ERR_CSP_SIGN */ {"CSP signing failed", USER}, /* ERR_CSP_NO_HASH_START */ {"Can not start CSP hashing", TECHNICAL}, /* ERR_CSP_NO_HASH */ {"CSP hash failed", LIBRARY}, /* ERR_CSP_NO_HASH_RESULT */ {"Can not read CSP's hashing result", LIBRARY}, /* ERR_CSP_OPEN_KEY */ {"Can not open key", TECHNICAL}, /* ERR_CSP_READ_KEY */ {"Can not read key", TECHNICAL}, /* ERR_OCSP_SIGN_NOT_SUPPORTED */ {"Requuested OCSP sign method not suported", LIBRARY}, /* ERR_OCSP_SIGN_CSP_NAME */ {"Can not add Signer's name to requst", LIBRARY}, /* ERR_CSP_CERT_DECODE */ {"Decoding certificate failed", TECHNICAL}, /* ERR_OCSP_SIGN_PKCS_NAME */ {"Can not add Signer's name to requst", TECHNICAL}, /* ERR_OCSP_SIGN_OSLL_CERT */ {"Cannot add cert to OCSP request", TECHNICAL}, /* ERR_OCSP_SIGN */ {"Can not sign OCSP request", USER}, /* ERR_CERT_ISSUER */ {"Cert not issued by this CA, or wrong cert signature", USER}, /* ERR_OCSP_PKCS12_CONTAINER */ {"Can not open pkcs12 container", USER}, /* ERR_MODIFY_SIGNED_DOC */ {"Cannot modify signed doc. Remove signatures first.", USER}, /* ERR_NOTARY_EXISTS */ {"Cannot remove signature if notary exists", USER}, /* ERR_UNSUPPORTED_CERT_SEARCH */ {"Unsuported CERT_SEARCH method", LIBRARY}, /* ERR_INCORRECT_CERT_SEARCH */ {"Incorrct CERT_SEARCH pattern", LIBRARY}, /* ERR_BAD_OCSP_RESPONSE_DIGEST */{"Incorrect Notary signature digest", USER}, /* ERR_LAST_ESTID_CACHED */ {"Wrong certificate in cache. Please try again.", USER}, /* ERR_BAD_DATAFILE_XML */ {"XML content cannot contain the first XML line", USER}, /* ERR_UNSUPPORTED_VERSION */ {"Unsupported SK-XML version. Please upgrade!", TECHNICAL}, /* ERR_UNSUPPORTED_CHARSET */ {"Unsupported charset", TECHNICAL}, /* ERR_PKCS12_EXPIRED */ {"PKCS#12 certificate has expired. Please get a new onew from www.sk.ee", USER}, /* ERR_CSP_USER_CANCEL */ {"User canceled certificate selection", USER}, /* ERR_CSP_NODEFKEY_CONTAINER */ {"Can't find default key container", TECHNICAL}, /* ERR_CONNECTION_FAILURE */ {"Connection error", USER}, /* ERR_WRONG_URL_OR_PROXY */ {"Wrong URL or Proxy", USER}, /* ERR_NULL_PARAM */ {"Mandatory parameter is NULL", LIBRARY}, /* ERR_BAD_ALLOC */ {"Memory allocation error", LIBRARY}, /* ERR_CONF_FILE */ {"Error opening configuration file", USER}, /* ERR_CONF_LINE */ {"Error in configuration file", USER}, /* ERR_OCSP_CERT_REVOKED */ { "Certificate has been revoked!", USER}, /* ERR_OCSP_CERT_UNKNOWN */ { "Certificate status unknow! Not supported by this CA?", USER}, /* ERR_OCSP_PKCS12_NO_FILE */ { "PKCS#12 token file not defined!", USER}, /* ERR_OCSP_PKCS12_NO_PASSWD */ { "PKCS#12 token file password not defined!", USER}, /* ERR_BAD_DATAFILE_CONTENT_TYPE */ { "Invalid DataFile content type!", TECHNICAL}, /* ERR_OCSP_WRONG_URL */ { "Wrong OCSP responder URL!", USER}, /* ERR_OCSP_MALFORMED */ { "Malformed OCSP request!", TECHNICAL}, /* ERR_OCSP_INTERNALERR */ { "Internal error in OCSP responder!", USER}, /* ERR_OCSP_TRYLATER */ { "Try later! OCSP responder is busy", USER}, /* ERR_OCSP_SIGREQUIRED */ { "Must sign OCSP requests!", USER}, /* ERR_OCSP_UNAUTHORIZED */ { "Unauthorized OCSP request!", USER}, /* ERR_UNKNOWN_CA */ { "Unknown Certificate issuer!", USER}, /* ERR_DENC_ENC_METHOD */ { "Invalid encryption method!", TECHNICAL}, /* ERR_DENC_ENC_XMLNS */ { "Invalid xml namespace!", TECHNICAL}, /* ERR_DENC_BAD_PROP_IDX */ { "Invalid EncryptionProperty index!", TECHNICAL}, /* ERR_DENC_BAD_KEY_IDX */ { "Invalid EncryptedKey index!", TECHNICAL}, /* ERR_DENC_KEY_STATUS */ { "Transport key not ready!", USER}, /* ERR_DENC_DATA_STATUS */ { "Invalid data status for this operation!", USER}, /* ERR_DENC_DECRYPT */ { "Failed to decrypt the data!", USER}, /* ERR_CHARSET_CONVERT */ { "Error converting charsets!", TECHNICAL }, /* ERR_COMPRESS */ { "Error compressing the data!", TECHNICAL }, /* ERR_DECOMPRESS */ { "Error decompressing the data!", TECHNICAL }, /* ERR_OCSP_CERT_NOTFOUND */ { "OCSP Responders cetificate not found!", USER }, /* ERR_INVALID_CONTENT */ { "Invalid characters in manifest or addres!", USER }, /* ERR_DENC_NO_KEY_FOUND */ { "No transport key for this smartcard!", USER }, /* ERR_OCSP_RESP_NOT_TRUSTED */ { "OCSP responder is not trusted! No certificate for this responder in local certstore!", USER }, /* ERR_PRIV_CERT_NOT_FOUND */ { "Certificate not found!", USER }, /* ERR_NO_OCSP */ { "Signature has no OCSP confirmation!", USER }, /* ERR_OCSP_WRONG_SIGNATURE */ { "OCSP signature is wrong!", USER }, /* ERR_BAD_PARAM */ { "Invalid parameter!", TECHNICAL }, /* ERR_GENERIC_SOAP_ERR */ { "Generic SOAP error", TECHNICAL }, /* ERR_TS_TIMESTAMPINFO_TYPE */ { "Invalid Timestamp type", TECHNICAL }, /* ERR_TS_BAD_INCLUDEINFO_IDX */ { "Invalid Include index", TECHNICAL }, /* ERR_TS_BAD_TIMESTAMPINFO_IDX */ { "Invalid TimestampInfo index", TECHNICAL }, /* ERR_TS_CREATE_TS_REQ */ { "Error creating timestamp request", TECHNICAL }, /* ERR_CREATE_NONCE */ { "Error creating nonce", TECHNICAL }, /* ERR_TXT2OID */ { "Error converting text to OID", TECHNICAL }, /* ERR_HTTP_ERR */ { "Invalid HTTP response code", TECHNICAL }, /* ERR_BAD_CERTID_IDX */ { "Invalid Include index", TECHNICAL }, /* ERR_BAD_CERTVALUE_IDX */ { "Invalid Include index", TECHNICAL }, /* ERR_TS_VERIFY */ { "Timestamp verification error", USER }, /* ERR_TS_REQUEST */ { "Error getting timestamp", USER }, /* ERR_TSA_NOT_TRUSTED */ { "TSA is not trusted! No certificate for this TSA in local certstore!", USER }, /* ERR_ORPHONED_SIGNATURE */ { "Incomplete or orphoned signature!", TECHNICAL }, /* ERR_WPKI_UNKNOWN_USER */ { "Unknown WPKI user!", USER }, /* ERR_WPKI_INVALID_PHONE_NO */ { "Invalid phone number for this WPKI user!", USER }, /* ERR_WPKI_UNTRUSTED_SRVICE */ { "WPKI service is not trusted!", USER }, /* ERR_WPKI_UNTRUSTED_USER */ { "Service demands customer authentication!", USER }, /* ERR_WPKI_UNUSABLE_PHONE */ { "Error signing with customers mobile phone! Unusable phone type?", USER }, /* ERR_WPKI_TIMEOUT */ { "Timeout during mobile signing!", USER }, /* ERR_WPKI_CANCELLED */ { "User cancelled mobile signing!", USER }, /* ERR_WPKI_MID_NOT_READY */ { "MID not ready!", USER }, /* ERR_WPKI_PHONE_NOT_REACHABLE */ { "Users phone is not reachable!", USER }, /* ERR_WPKI_SENDING_ERROR */ { "Error sending signing request to users mobile phone!", USER }, /* ERR_WPKI_SIM_ERROR */ { "SIM card error!", USER }, /* ERR_WPKI_SERVICE_ERR */ { "Mobile signing service internal error!", USER }, //AM 18.03.08 /* ERR_ZIP_FILE_READ */ { "File not found in BDOC!", USER }, /* ERR_ZIP */ { "Error in BDocZip!", USER }, /* ERR_MANIFEST */ { "Can't parse manifest!", USER }, /* ERR_DATAFILE_NOT_MANIFEST */ { "Datafile is not described in manifest.xml!", USER }, /* ERR_SIG_INVALID_PROFILE */ { "Signature does not correspond to profile in manifest.xml!", USER }, /* ERR_SIGNERS_CERT_NON_REPU */ { "Signers cert does not have non-repudiation bit set!", USER }, /* ERR_OCSP_NONCE_SIGVAL_NOMATCH */ { "Calculated signature hash doesn't match to OCSP responder nonce field!", USER }, /* ERR_VALIDATE */ { "Validation error! Invalid ddoc or cdoc document.", USER }, /* ERR_OCSP_NONCE_INVALID */ { "Invalid nonce length!", TECHNICAL }, /* ERR_SIGVAL_ASN1 */ { "Invalid signature value! Missing or wrong asn.1 signature structure", TECHNICAL }, /* ERR_MAX_1_ROLES */ { "Currently supports no more than 1 ClaimedRoles!", USER }, /* ERR_DF_NAME */ { "Failed to parse DataFile name. Invalid file name!", USER }, /* ERR_DF_WRONG_DIG */ { "Invalid DataFile digest! Alternate digest matches.", USER }, /* ERR_ISSUER_XMLNS */ { "X509IssuerName or X509IssuerSerial missing xmlns atribute", USER }, /* ERR_OLD_VERSION */ { "SK-XML 1.0 and DIGIDOC-XML 1.1 and 1.2 are old signature formats and schould not be used for new documents", USER }, /* ERR_TEST_SIGNATURE */ { "Test signature!", USER }, /* ERR_UNKNOWN_ERROR */ { "Multiple errors. Check the error list!", USER }, /* ERR_TRANSFORM_UNSUPPORTED */ { "Transform elements are currently not supported!", USER }, /* ERR_NETWORK_SYNC */ { "Error writing file! Network synchronize timeout.", USER }, /* ERR_XML_VALIDATION */ { "Signature xml structure validation error", USER }, /* */ {"", NO_ERRORS} }; //==========< global variables >==================== //int g_ddocLastError = ERR_OK; #define INITIAL_MAX_THREADS 1 #define NOT_FOUND -1 #if defined(WIN32) #define THREAD_ID DWORD #elif defined(USEPTHREADS) #define THREAD_ID pthread_t #else #define THREAD_ID pid_t #endif typedef struct ThreadErrors_st { THREAD_ID tid; int currentErrorIdx; int readErrorIdx; ErrorInfo ddocLastErrors[ERROR_BUF_LENGTH]; } ThreadErrors; static int g_threads = 0; static ThreadErrors **ddocErrors = NULL; // Following mutual exclusion objects are here to // protect access to ddocErrors and g_threads; whenever we access these variables // we have to use lock/unlock. #if defined(USEPTHREADS) pthread_mutex_t m_ddocErrors = PTHREAD_MUTEX_INITIALIZER; #elif defined(WIN32) //My bad, no static initializer for critical sections; initialized in DigiDocLib.c CRITICAL_SECTION cs_ddocErrors; #endif // Returns unique thread identifier static THREAD_ID getTid(void) { #if defined(WIN32) return GetCurrentThreadId(); #elif defined(USEPTHREADS) return pthread_self(); #else return getpid(); #endif } static void lock(void) { #if defined WIN32 EnterCriticalSection(&cs_ddocErrors); #elif defined USEPTHREADS pthread_mutex_lock(&m_ddocErrors); #else // Hope it will be optimized away.. #endif } static void unlock(void) { #if defined WIN32 LeaveCriticalSection(&cs_ddocErrors); #elif defined USEPTHREADS pthread_mutex_unlock(&m_ddocErrors); #else // Hope it will be optimized away.. #endif } // Grows or creates the array of pointers to ThreadErrors // Will be always called with locked mutex. static int growErrorTable(void) { int slotsToAllocate; int i; ThreadErrors **tmpErrors; // printf("growErrorTable init : g_threads=%d, ddocErrors=%p\n", g_threads, ddocErrors); if (g_threads == 0) slotsToAllocate = INITIAL_MAX_THREADS; // We have no table so far at all else slotsToAllocate = g_threads * 2; // We'll double the table size everytime tmpErrors = (ThreadErrors**)realloc(ddocErrors, slotsToAllocate * sizeof(ThreadErrors *)); // MEMLEAK: ??? if (tmpErrors == NULL) return ERR_BAD_ALLOC; ddocErrors = tmpErrors; for (i = g_threads; i < slotsToAllocate; i++) // Initialize new entries; ddocErrors[i] = NULL; g_threads = slotsToAllocate; // printf("growErrorTable leave : g_threads=%d, ddocErrors=%p\n", g_threads, ddocErrors); return ERR_OK; } static int isThreadEqual(THREAD_ID tid1, THREAD_ID tid2) { #if defined(WIN32) return tid1 == tid2; #elif defined(USETHREADS) return pthread_equal(tid1, tid2); #else return tid1 == tid2; #endif } // Finds slot number in ddocErrors[] whose pointer points to ThreadErrors belonging to threadID // or returns NOT_FOUND; static int findSlotByTid(THREAD_ID threadID) { int i; lock(); if (ddocErrors == NULL) { unlock(); return NOT_FOUND; } for (i = 0; i < g_threads; i++) if (ddocErrors[i] && isThreadEqual(ddocErrors[i]->tid,threadID)) { unlock(); return i; } unlock(); return NOT_FOUND; } // Finds thread's ThreadError structure address, returns NULL if the thread doesn't have it (yet). static ThreadErrors *findThreadErrorsByTid(THREAD_ID threadID) { ThreadErrors *tmpThreadErrors; int slot = findSlotByTid(threadID); if (slot == NOT_FOUND) return NULL; lock(); tmpThreadErrors = ddocErrors[slot]; unlock(); return tmpThreadErrors; } // Creates ThreadErrors structure for thread Tid, returns pointer to // created object; returns NULL if the object wasn't created. static ThreadErrors *addThreadErrorsByTid(THREAD_ID Tid) { int i, slot = NOT_FOUND; ThreadErrors *threadErrors = findThreadErrorsByTid(Tid); if (threadErrors != NULL) // Already present, do nothing return threadErrors; lock(); for (i = 0; i < g_threads; i++) { if (ddocErrors[i] == NULL) // Won't enter here if g_threads == 0 slot = i; // first free slot found } if (slot == NOT_FOUND) { if (growErrorTable() == ERR_OK) { for (i = 0; i < g_threads; i++) { //Try again... if (ddocErrors[i] == NULL) slot = i; } } else { unlock(); return NULL; } } threadErrors = (ThreadErrors*)malloc(sizeof(ThreadErrors)); // MEMLEAK: ??? if (threadErrors == NULL) { unlock(); return NULL; } memset(threadErrors, 0, sizeof(ThreadErrors)); threadErrors->tid = Tid; threadErrors->readErrorIdx = -1; threadErrors->currentErrorIdx = -1; ddocErrors[slot] = threadErrors; unlock(); return threadErrors; } // Releases memory allocated for ThreadError structure of thread threadID EXP_OPTION void freeThreadErrorsByTid(THREAD_ID threadID) { ThreadErrors *threadErrors; int slot = findSlotByTid(threadID); if (slot == NOT_FOUND) return; threadErrors = findThreadErrorsByTid(threadID); lock(); free(threadErrors); ddocErrors[slot] = NULL; unlock(); } //================< error handling functions> ================================= //returns textual explanation of the error code EXP_OPTION char* getErrorString(int code) { if(code < ERR_MAX && code >= 0) return g_ddocErrorStrings[code].errorMessage; else return "No error message defined for this error"; } EXP_OPTION ErrorClass getErrorClass(int code) { if(code < ERR_MAX && code >= 0) return g_ddocErrorStrings[code].errorClass; else return NO_ERRORS; } //returns the last EXP_OPTION ErrorInfo* getErrorInfo() { ErrorInfo *pErrInfo = 0; THREAD_ID Tid = getTid(); ThreadErrors *threadErrors = findThreadErrorsByTid(Tid); if (threadErrors == NULL) return 0; if(threadErrors->readErrorIdx >= 0 && threadErrors->ddocLastErrors[threadErrors->readErrorIdx].code != ERR_OK) { pErrInfo = &(threadErrors->ddocLastErrors[threadErrors->readErrorIdx]); threadErrors->readErrorIdx--; if(threadErrors->readErrorIdx < 0) //roll over threadErrors->readErrorIdx = ERROR_BUF_LENGTH - 1; } else pErrInfo = 0; return pErrInfo; } //returns 1, if all errors are read and 0 otherwise EXP_OPTION int hasUnreadErrors() { THREAD_ID Tid = getTid(); ThreadErrors *threadErrors = findThreadErrorsByTid(Tid); if (threadErrors == NULL) return 0; return (threadErrors->readErrorIdx >= 0 ? threadErrors->ddocLastErrors[threadErrors->readErrorIdx].code : ERR_OK); } //returns -1, if all errors are read and valid index otherwise EXP_OPTION int getLastErrorsIdx() { THREAD_ID Tid = getTid(); ThreadErrors *threadErrors = findThreadErrorsByTid(Tid); if (threadErrors == NULL) return -1; return threadErrors->readErrorIdx; } //returns NULL, if all errors are read and valid ErrorInfo structre pointer otherwise // does not mark error as read so it can be found again EXP_OPTION ErrorInfo* getErrorsInfo(int nIdx) { ErrorInfo *pErrInfo = 0; THREAD_ID Tid = getTid(); ThreadErrors *threadErrors = findThreadErrorsByTid(Tid); if (threadErrors == NULL) return 0; if(nIdx >= 0 && threadErrors->ddocLastErrors[nIdx].code != ERR_OK) { pErrInfo = &(threadErrors->ddocLastErrors[nIdx]); } else pErrInfo = 0; return pErrInfo; } EXP_OPTION void clearErrors() { THREAD_ID Tid = getTid(); ThreadErrors *threadErrors = findThreadErrorsByTid(Tid); if (threadErrors == NULL) return; memset(threadErrors->ddocLastErrors, 0, sizeof(ErrorInfo) * ERROR_BUF_LENGTH); threadErrors->readErrorIdx = -1; threadErrors->currentErrorIdx = -1; } EXP_OPTION void resetError(ErrorInfo *pErrInfo) { pErrInfo->code = ERR_OK; pErrInfo->fileName = ""; pErrInfo->line = 0; pErrInfo->assertion = ""; } EXP_OPTION void addError(int code, char *fileName, int line, char *assertion) { //no errors found yet. Set a trace-back mark to the end of array. //printf("Error : %d at %s line %d, assertion %s\n", code, fileName, line, assertion); ThreadErrors *threadErrors; THREAD_ID Tid = getTid(); //Find our identity threadErrors = findThreadErrorsByTid(Tid); // printf("addError init: tid=%ld, threadErrors=%p\n", Tid, threadErrors); if (threadErrors == NULL) { //This Tid has no entry in ThreadErrors table threadErrors = addThreadErrorsByTid(Tid); // MEMLEAK: ??? if (threadErrors == NULL) return; // What else can we do? } // printf("addError step 1 : tid=%ld, threadErrors=%p\n", Tid, threadErrors); if(threadErrors->currentErrorIdx < 0) resetError(&(threadErrors->ddocLastErrors[ERROR_BUF_LENGTH - 1])); threadErrors->currentErrorIdx++; //index at the end -> roll it over to the beginning if(threadErrors->currentErrorIdx == ERROR_BUF_LENGTH-1) threadErrors->currentErrorIdx = 0; //set the information ddocDebug(4, "addError", "Index: %d Error : %d at %s line %d, assertion %s", threadErrors->currentErrorIdx, code, fileName, line, assertion); threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].code = code; threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].fileName = fileName; threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].line = line; threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].assertion = assertion; //index at the end? Set the traceback mark to the beginning if(threadErrors->currentErrorIdx == ERROR_BUF_LENGTH - 1) resetError(&(threadErrors->ddocLastErrors[0])); else //set the traceback mark to the next position resetError(&(threadErrors->ddocLastErrors[threadErrors->currentErrorIdx + 1])); threadErrors->readErrorIdx = threadErrors->currentErrorIdx; } //-------------------------------------------------- // Checks DigiDoc library internal errors //-------------------------------------------------- EXP_OPTION int checkDigiDocErrors() { char *errorClass[] = {"NO_ERRORS", "TECHNICAL", "USER", "LIBRARY"}; int err = ERR_OK; while(hasUnreadErrors()) { ErrorInfo* pErr = getErrorInfo(); char* pErrStr = getErrorString(pErr->code); printf("Error: %d - %s; file: %s line: %d; failed condition: %s, error class : %s\n", pErr->code, pErrStr, pErr->fileName, pErr->line, pErr->assertion, errorClass[getErrorClass(pErr->code)]); err = pErr->code; } clearErrors(); return err; } EXP_OPTION int getLastError() { THREAD_ID Tid = getTid(); ThreadErrors *threadErrors = findThreadErrorsByTid(Tid); if (threadErrors == NULL) return 0; return (threadErrors->readErrorIdx >= 0 ? threadErrors->ddocLastErrors[threadErrors->readErrorIdx].code : ERR_OK); } EXP_OPTION int checkUnknownErr(SignedDoc* pSigDoc) { int n, m = getLastErrorsIdx(), err1 = 0, err2 = 0; ErrorInfo* pErr; // list all errors for(n = m; n >= 0; n--) { pErr = getErrorsInfo(n); if(!err1 && pErr) { err1 = pErr->code; } else if(!err2 && pErr && pErr->code != err1) err2 = pErr->code; } return ((err1 != err2 && err2) ? ERR_UNKNOWN_ERROR : err1); } libdigidoc-3.10.5/libdigidoc/DigiDocDebug.c0000664000372000037200000001247713560273131020015 0ustar travistravis//================================================== // FILE: DigiDocDebug.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for debug output // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 10.08.2004 Veiko Sinivee // Creation //================================================== #include #include #include #if defined(GNUCPP) || !defined(WIN32) #include #define _mkdir mkdir #define _rmdir rmdir #define _unlink unlink #define _tzset tzset #define _getcwd getcwd #endif //----------------------------------------- // Formats debug output // level - debug level to output this message on // func - name of the function // format - message format and arguments //----------------------------------------- EXP_OPTION void ddocDebug(int level, const char* func, const char* format, ...) { time_t tNow; struct tm tm1; int nLevel = ConfigItem_lookup_int("DEBUG_LEVEL", 1); const char * szDebugFile = ConfigItem_lookup("DEBUG_FILE"); va_list args; FILE* hFile = 0; if(level <= nLevel) { time(&tNow); ddocLocalTime(&tNow, &tm1, 1); va_start(args, format); if(szDebugFile && ((hFile = fopen(szDebugFile, "ab")) != NULL)) { fprintf(hFile, "%s\t[%04d-%02d-%02d %02d:%02d:%02d] ", func, tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec); vfprintf(hFile, format, args); fprintf(hFile, "\n"); fclose(hFile); } else { fprintf(stderr, "%s\t[%04d-%02d-%02d %02d:%02d:%02d] ", func, tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec); vfprintf(stderr, format, args); fprintf(stderr, "\n"); } } } //----------------------------------------- // Writes debug data in a file // level - debug level to write on // szFileName - target file name // pMemBuf - buffer for log data //----------------------------------------- EXP_OPTION int ddocDebugWriteFile(int level, const char* szFileName, DigiDocMemBuf *pMemBuf) { int err = ERR_OK; FILE* hFile; int nLevel = ConfigItem_lookup_int("DEBUG_LEVEL", 1); RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(pMemBuf); if(level <= nLevel) { if((hFile = fopen(szFileName, "ab")) != NULL) { fwrite(pMemBuf->pMem, 1, pMemBuf->nLen, hFile); fclose(hFile); } } return err; } //----------------------------------------- // Formats debug output // level - debug level to output this message on // func - name of the function // msg - message format and arguments // args - va_list struct //----------------------------------------- EXP_OPTION void ddocDebugVaArgs(int level, const char* func, const char* msg, va_list args) { time_t tNow; struct tm tm1; int nLevel = ConfigItem_lookup_int("DEBUG_LEVEL", 1); const char * szDebugFile = ConfigItem_lookup("DEBUG_FILE"); FILE* hFile = 0; if(level <= nLevel) { time(&tNow); ddocLocalTime(&tNow, &tm1, 1); if(szDebugFile && ((hFile = fopen(szDebugFile, "ab")) != NULL)) { fprintf(hFile, "%s\t[%04d-%02d-%02d %02d:%02d:%02d] ", func, tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec); vfprintf(hFile, msg, args); fprintf(hFile, "\n"); fclose(hFile); } else { fprintf(stderr, "%s\t[%04d-%02d-%02d %02d:%02d:%02d] ", func, tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec); vfprintf(stderr, msg, args); fprintf(stderr, "\n"); } } } //----------------------------------------- // Deletes the log file if it exists. //----------------------------------------- EXP_OPTION void ddocDebugTruncateLog() { char * szDebugFile = (char*)ConfigItem_lookup("DEBUG_FILE"); if(szDebugFile && checkFileExists(szDebugFile)) { _unlink(szDebugFile); } } //----------------------------------------- // Reads the contents of the log file // pMemBuf - buffer for log data //----------------------------------------- EXP_OPTION int ddocDebugReadLog(DigiDocMemBuf *pMemBuf) { char * szDebugFile = (char*)ConfigItem_lookup("DEBUG_FILE"); FILE *hFile; int err = ERR_OK, l2, l1; char buf1[1025]; RETURN_IF_NULL_PARAM(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; if(szDebugFile) { if((hFile = fopen(szDebugFile, "rt")) != NULL) { l1 = sizeof(buf1); do { l2 = fread(buf1, 1, l1, hFile); err = ddocMemAppendData(pMemBuf, buf1, l2); } while(l2 > 0); fclose(hFile); } } else err = ERR_FILE_READ; return err; } libdigidoc-3.10.5/libdigidoc/DigiDocSAXParser.h0000664000372000037200000001120713560273131020572 0ustar travistravis#ifndef __DIGIDOC_SAX_PARSER_H__ #define __DIGIDOC_SAX_PARSER_H__ //================================================== // FILE: DigiDocSAXParser.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for xml parsing using SAX interface // This is the older parser and will probably // be removed in new versions // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 12.08.2004 Veiko Sinivee // Creation // 22.08.2004 Veiko Sinivee // Renamed readSignedDoc() to ddocSaxReadSignedDocFromFile(). Params changed. // Renamed extractDataFile() to ddocSaxExtractDataFile(). Uses chached content. //================================================== #include #include #ifdef __cplusplus extern "C" { #endif //-------------------------------------------------- // Reads in signed XML document info from digidoc file // ppSigDoc - pointer to the buffer of newly read info pointer // szFileName - documents filename // checkFileDigest - indicates if digests of datafiles referred by the document must be checked // lMaxDFLen - maximum size for a DataFile whose contents will be // kept in memory //-------------------------------------------------- EXP_OPTION int ddocSaxReadSignedDocFromFile(SignedDoc** ppSigDoc, const char* szFileName, int checkFileDigest, long lMaxDFLen); //-------------------------------------------------- // Reads in signed XML document and extracts the desired data file // pSigDoc - signed document object if exists. Can be NULL // szFileName - digidoc filename // szDataFileName - name of the file where to store embedded data. // szDocId - DataFile Id atribute value // szCharset - convert DataFile content to charset //-------------------------------------------------- EXP_OPTION int ddocSaxExtractDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDataFileName, const char* szDocId, const char* szCharset); //-------------------------------------------------- // Reads in signed XML document and returns the // desired DataFile-s content in a memory buffer. // caller is responsible for freeing the memory. // pSigDoc - signed document object if cached // szFileName - name of digidoc file // szDocId - id if DataFile // pBuf - address of buffer pointer // bKeepBase64 - 1=don't decode base64, 0=decode base64 // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSAXGetDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDocId, DigiDocMemBuf* pBuf, int bKeepBase64); //-------------------------------------------------- // Reads in signed XML document info from memory buffer // ppSigDoc - pointer to the buffer of newly read info pointer // szFileName - documents filename // checkFileDigest - indicates if digests of datafiles referred by the document must be checked // lMaxDFLen - maximum size for a DataFile whose contents will be // kept in memory //-------------------------------------------------- EXP_OPTION int ddocSaxReadSignedDocFromMemory(SignedDoc** ppSigDoc, const void* pData, int len, long lMaxDFLen); //-------------------------------------------------- // Reads new signatures from another digidoc file // and adds to existing digidoc. Adds only those // signatures that don't exist in old digidoc. // pSigDoc - signed document object // szFileName - name of digidoc file // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocReadNewSignaturesFromDdoc(SignedDoc* pSigDoc, const char* szFileName); //AM 13.03.2008 void decodeURI(const char* uri, char* id, int nIdLen, char* adr, int nAdrLen); EXP_OPTION int ddocAddSignatureFromMemory(SignedDoc* pSigDoc, const char* szFileName, const void* pSigBuf, int nSigLen); #ifdef __cplusplus } #endif #endif // __DIGIDOC_SAX_PARSER_H__ libdigidoc-3.10.5/libdigidoc/DigiDocPKCS11.h0000664000372000037200000000634313560273131017671 0ustar travistravis#ifndef __DIGI_DOC_PKCS11_H__ #define __DIGI_DOC_PKCS11_H__ //================================================== // FILE: DigiDocPKCS11.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for signing using PKCS#11 API // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 13.01.2004 Veiko Sinivee // Creation //================================================== #include #ifdef __cplusplus extern "C" { #endif #ifdef WIN32 #include #define LIBHANDLE HANDLE #include "pkcs11/cryptoki.h" #else #include // Linux .so loading interface #define LIBHANDLE void* #include "pkcs11/pkcs11.h" #endif #include #include EXP_OPTION LIBHANDLE initPKCS11Library(const char* libName); EXP_OPTION void closePKCS11Library(LIBHANDLE pLibrary, CK_SESSION_HANDLE hSession); EXP_OPTION int calculateSignatureWithEstID(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, int slot, const char* passwd); EXP_OPTION CK_RV GetSlotIds(CK_SLOT_ID_PTR pSlotids, CK_ULONG_PTR pLen); EXP_OPTION CK_RV GetTokenInfo(CK_TOKEN_INFO_PTR pTokInfo, CK_SLOT_ID id); int loadAndTestDriver(const char* driver, LIBHANDLE* pLibrary, CK_SLOT_ID* slotids, int slots, CK_ULONG slot); EXP_OPTION CK_RV getDriverInfo(CK_INFO_PTR pInfo); EXP_OPTION CK_RV GetSlotInfo(CK_SLOT_INFO_PTR pSlotInfo, CK_SLOT_ID id); //============================================================ // Decrypts RSA encrypted data with the private key // slot - number of the slot for decryption key. On ID card allways 0 // pin - corresponding pin for the key. On ID card - PIN1 // encData - encrypted data // encLen - length of encrypted data // decData - buffer for decrypted data // encLen - length of buffer. Will be modified by amount of decrypted data // return error code or ERR_OK //============================================================ EXP_OPTION int decryptWithEstID(int slot, const char* pin, const char* encData, int encLen, char* decData, int *decLen); //============================================================ // Locates and reads users certificate from smartcard // slot - number of the slot for decryption key. On ID card allways 0 // ppCert - address for newly allocated certificate pointer // return error code or ERR_OK //============================================================ EXP_OPTION int findUsersCertificate(int slot, X509** ppCert); #ifdef __cplusplus } #endif #endif // __DIGI_DOC_PKCS11_H__ libdigidoc-3.10.5/libdigidoc/DigiDocStack.c0000664000372000037200000002414113560273131020023 0ustar travistravis//================================================== // FILE: DigiDocStack.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for simple stack // to keep track of xml parsing // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 09.09.2004 Veiko Sinivee // Creation //================================================== #include #include #include #include #include //-------------------------------------------------- // Finds the last element on stack // reader - XML reader cursor to current node // pStack - address of stack begin. This one elemnt // must exist, but might be initially empty // return error code or ERR_OK //-------------------------------------------------- ElementEntry* ddocStackFindEnd(ElementEntry* pStack) { ElementEntry* pElem = pStack; while(pElem->pNext) pElem = (ElementEntry*)pElem->pNext; return pElem; } //-------------------------------------------------- // Push a new element info onto stack // reader - XML reader cursor to current node // pStack - address of stack begin. This one elemnt // must exist, but might be initially empty // pLastElem - address for new elements pointer. // If not NULL then will be used to return the // newly allocated elemnt, so you don't have to // do a new search. // return error code or ERR_OK //-------------------------------------------------- int ddocStackPushElement(ElementEntry* pStack, xmlTextReaderPtr reader, ElementEntry** pLastElem) { ElementEntry* pElem; RETURN_IF_NULL_PARAM(reader); RETURN_IF_NULL_PARAM(pStack); pElem = ddocStackFindEnd(pStack); if(pElem->tag && !pElem->pNext) { // check if this entry is used pElem->pNext = (ElementEntry*)malloc(sizeof(ElementEntry)); if(!pElem) SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); memset(pElem->pNext, 0, sizeof(ElementEntry)); pElem = (ElementEntry*)pElem->pNext; } if(!pElem) return ERR_NULL_POINTER; pElem->tag = xmlTextReaderLocalName(reader); pElem->prefix = xmlTextReaderPrefix(reader); pElem->nsUri = xmlTextReaderNamespaceUri(reader); // atributes pElem->id = xmlTextReaderGetAttribute(reader, (const xmlChar*)"Id"); pElem->uri = xmlTextReaderGetAttribute(reader, (const xmlChar*)"URI"); pElem->content = xmlTextReaderGetAttribute(reader, (const xmlChar*)"ContentType"); if(pLastElem) // this may be NULL if users doesn't want the last elem. *pLastElem = pElem; return ERR_OK; } //-------------------------------------------------- // Push a new element info onto stack // tagName - elements tag name, Possibly with ns-prefix // atts - array of atributa names and values // pStack - address of stack begin. This one elemnt // must exist, but might be initially empty // pLastElem - address for new elements pointer. // If not NULL then will be used to return the // newly allocated elemnt, so you don't have to // do a new search. // return error code or ERR_OK //-------------------------------------------------- int ddocStackPushElementSAX(ElementEntry* pStack, const xmlChar* tagName, const xmlChar** atts, ElementEntry** pLastElem) { ElementEntry* pElem; char *p1, *p2; xmlChar *n, *v; int i; ddocDebug(5, "ddocStackPushElementSAX", "tag: %s", (char*)tagName); RETURN_IF_NULL_PARAM(tagName) RETURN_IF_NULL_PARAM(pStack) pElem = ddocStackFindEnd(pStack); if(pElem->tag && !pElem->pNext) { // check if this entry is used pElem->pNext = (ElementEntry*)malloc(sizeof(ElementEntry)); if(!pElem) SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); memset(pElem->pNext, 0, sizeof(ElementEntry)); pElem = (ElementEntry*)pElem->pNext; } if(!pElem) return ERR_NULL_POINTER; p1 = (char*)strdup((char*)tagName); if(!p1) SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC) // check for ns-prefix p2 = strchr(p1, ':'); if(p2) { *p2 = 0; p2++; pElem->prefix = xmlStrdup((xmlChar*)p1); if(!pElem->prefix) { free(p1); SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); } pElem->tag = xmlStrdup((const xmlChar*)p2); } else pElem->tag = xmlStrdup((const xmlChar*)p1); free(p1); if(!pElem->tag) SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { n = (xmlChar*)atts[i]; v = (xmlChar*)atts[i+1]; if(n && !strncmp((char*)n, "xmlns", 5) && v) pElem->nsUri = xmlStrdup((xmlChar*)v); if(n && !strncmp((char*)n, "Id", 2) && v) pElem->id = xmlStrdup((xmlChar*)v); if(n && !strncmp((char*)n, "URI", 3) && v) pElem->uri = xmlStrdup((xmlChar*)v); if(n && !strncmp((char*)n, "ContentType", 11) && v) pElem->content = xmlStrdup((xmlChar*)v); } if(pLastElem) // this may be NULL if users doesn't want the last elem. *pLastElem = pElem; return ERR_OK; } //-------------------------------------------------- // Pop the last element from the stack // pStack - address of stack begin. This one elemnt // must exist, and will never be deleted. // bCleanup - flag: 1=cleanup the whole stack, 0=just the last element // return error code or ERR_OK // pLastElem - address for new elements pointer. // If not NULL then will be used to return the // last element on stack. //-------------------------------------------------- int ddocStackPopElement(ElementEntry* pStack, int bCleanup, ElementEntry** pLastElem) { ElementEntry *pElem = 0, *pOldElem = 0; RETURN_IF_NULL_PARAM(pStack); do { pOldElem = pElem = pStack; while(pElem->pNext) { pOldElem = pElem; pElem = (ElementEntry *)pElem->pNext; } if(pElem && pElem != pStack) { ddocDebug(5, "ddocStackPopElement", "Pop: %s, cleanup: %d", pElem->tag, bCleanup); xmlFree(pElem->tag); pElem->tag = 0; xmlFree(pElem->prefix); pElem->prefix = 0; xmlFree(pElem->nsUri); pElem->nsUri = 0; xmlFree(pElem->id); pElem->id = 0; xmlFree(pElem->uri); pElem->uri = 0; xmlFree(pElem->content); pElem->content = 0; free(pElem); pElem = 0; // mark freed pOldElem->pNext = 0; if(!bCleanup) break; // remove just the last one? } } while(pElem && pElem != pStack); if(bCleanup) { // now free up also the final first elements // dynamically allocated part xmlFree(pStack->tag); pStack->tag = 0; xmlFree(pStack->prefix); pStack->prefix = 0; xmlFree(pStack->nsUri); pStack->nsUri = 0; xmlFree(pStack->id); pStack->id = 0; xmlFree(pStack->uri); pStack->uri = 0; xmlFree(pStack->content); pStack->content = 0; pStack->pNext = 0; } if(pLastElem && pElem) // this may be NULL if users doesn't want the last elem. *pLastElem = pElem; return ERR_OK; } //-------------------------------------------------- // Retrieve the current/last/stack top elements tag (localname) // pStack - address of stack begin. //-------------------------------------------------- const xmlChar* ddocStackCurrentTag(ElementEntry* pStack) { ElementEntry* pElem = 0; const xmlChar* pTag = 0; if(pStack) { pElem = ddocStackFindEnd(pStack); if(pElem) pTag = (const xmlChar*)pElem->tag; } return pTag; } //-------------------------------------------------- // Retrieve the current/last/stack top elements ns prefix // pStack - address of stack begin. //-------------------------------------------------- const xmlChar* ddocStackCurrentNsPrefix(ElementEntry* pStack) { ElementEntry* pElem = 0; const xmlChar* pPrefix = 0; if(pStack) { pElem = ddocStackFindEnd(pStack); if(pElem) pPrefix = (const xmlChar*)pElem->prefix; } return pPrefix; } //-------------------------------------------------- // Retrieve the current/last/stack top elements ns prefix // pStack - address of stack begin. //-------------------------------------------------- const xmlChar* ddocStackCurrentNsUri(ElementEntry* pStack) { ElementEntry* pElem = 0; const xmlChar* pUri = 0; if(pStack) { pElem = ddocStackFindEnd(pStack); if(pElem) pUri = (const xmlChar*)pElem->nsUri; } return pUri; } //-------------------------------------------------- // Checks if there is a parent element with the given // localname on the stack. // pStack - address of stack begin. // return 1 if there is such a parent elem or 0 if not. //-------------------------------------------------- int ddocStackHasParentWithName(ElementEntry* pStack, const xmlChar* parentsName, ElementEntry* pCurrElem) { int bFound = 0; ElementEntry *pElem = pStack; while(pElem && pElem != pCurrElem) { if(pElem->tag && !xmlStrcmp(pElem->tag, parentsName)) { bFound = 1; break; } else pElem = (ElementEntry *)pElem->pNext; } return bFound; } //-------------------------------------------------- // Checks if there is a parent element with the given // localname on the stack. // pStack - address of stack begin. // return 1 if there is such a parent elem or 0 if not. //-------------------------------------------------- ElementEntry* ddocStackGetParentWithName(ElementEntry* pStack, const xmlChar* parentsName, ElementEntry* pCurrElem) { ElementEntry *pParent = 0; ElementEntry *pElem = pStack; while(pElem && pElem != pCurrElem) { if(pElem->tag && !xmlStrcmp(pElem->tag, parentsName)) { pParent = pElem; break; } else pElem = (ElementEntry *)pElem->pNext; } return pParent; } libdigidoc-3.10.5/libdigidoc/DigiDocVerify.h0000664000372000037200000001542213560273131020231 0ustar travistravis#ifndef __DIGIDOC_VERIFY_H__ #define __DIGIDOC_VERIFY_H__ //================================================== // FILE: DigiDocVerify.h // PROJECT: Digi Doc // DESCRIPTION: DigiDoc verification routines // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 26.04.2006 Veiko Sinivee // Creation //================================================== #include "DigiDocDefs.h" #include "DigiDocObj.h" #include "DigiDocMem.h" #include #include //==========< XML generation routines >======================== #ifdef __cplusplus extern "C" { #endif // Holds info of an xml element used in signature format typedef struct XmlElemDef_st { char* szTag; // element tag char bMultiple; // 'Y' if multiple elements allowed, 'N' if not void** pChildren; // list of children terminated by NULL } XmlElemDef; // Holds info of an xml element used in signature format typedef struct XmlElemInfo_st { char* szId; // element tag char* szTag; // element tag void* pParent; // parent emenent info if exists void** pChildren; // list of children terminated by NULL } XmlElemInfo; int XmlElemInfo_new(XmlElemInfo **ppXi, const char* id, const char* tag); void XmlElemInfo_free(XmlElemInfo* pXi); int XmlElemInfo_countChildren(XmlElemInfo* pXi); int XmlElemInfo_addChild(XmlElemInfo* pParent, XmlElemInfo* pChild); XmlElemInfo* XmlElemInfo_getRootElem(XmlElemInfo* pElem); // verifies files signature EXP_OPTION int verifyFileSignature(const char* szFileName, int nDigestType, byte* pSigBuf, int nSigLen, const char *certfile); // Compares two byte arrays and returns 0 for OK EXP_OPTION int compareByteArrays(const byte* dig1, int len1, const byte* dig2, int len2); // verifies one doc's check digests in this signature EXP_OPTION int verifySigDocDigest(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const DocInfo* pDocInfo, const char* szDataFile); // verifies the mime digest of this doc in this signature EXP_OPTION int verifySigDocMimeDigest(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const DocInfo* pDocInfo, const char* szFileName); // verifies this one signature EXP_OPTION int verifySignatureInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const char* signerCA, const char* szDataFile, int bUseCA); // verifies the whole document (returns on first err) EXP_OPTION int verifySigDoc(const SignedDoc* pSigDoc, const char* signerCA, const char** caFiles, const char* caPath, const char* notCert, const char* szDataFile, int bUseCA); // Verifies the certificates signed attributes EXP_OPTION int verifySigCert(const SignatureInfo* pSigInfo); // Verfies NotaryInfo signature EXP_OPTION int verifyNotaryInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const NotaryInfo* pNotInfo, const char ** caFiles, const char *CApath, const char* notCertFile); // Verifies the certificates signed attributes EXP_OPTION int verifyNotCert(const SignatureInfo* pSigInfo, const NotaryInfo* pNotInfo); // Verfies NotaryInfo digest EXP_OPTION int verifyNotaryDigest(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo); // verifies signed doc EXP_OPTION int verifySigDocCERT(const SignedDoc* pSigDoc, const void* signerCA, const X509** caCerts, const char* caPath, const X509* notCert, const char* szDataFile, int bUseCA); // Verifies this signature EXP_OPTION int verifySignatureInfoCERT(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const void* signerCACert, const char* szDataFile, int bUseCA); // Checks if the cert has been signed by this CA-cert EXP_OPTION int isCertSignedByCERT(const X509* cert, const X509* caCert); // Verfies NotaryInfo signature EXP_OPTION int verifyNotaryInfoCERT(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const NotaryInfo* pNotInfo, const X509** caCerts, const char *CApath, const X509* notCert); //-------------------------------------------------- // Verfies NotaryInfo signature // pSigDoc - signed doc object // pNotInfo - NotaryInfo object // caCerts - CA certificate pointer array terminated with NULL // CApath - path to (directory) all certs // notCertFile - Notary (e.g. OCSP responder) cert file // pSigCa - signers ca cert //-------------------------------------------------- EXP_OPTION int verifyNotaryInfoCERT2(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const NotaryInfo* pNotInfo, const X509** caCerts, const char *CApath, const X509* notCert, const X509* pSigCa); EXP_OPTION int verifySigDocSigPropDigest(const SignatureInfo* pSigInfo); // Calculates the digest of NotaryInfo EXP_OPTION int calculateNotaryInfoDigest(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo, byte* digBuf, int* digLen); int readTagContents(char** data, const char* fileName, const char* tagName, int nAttrs, const char** attNames, const char** attValues, int withTags); X509_ALGOR* setSignAlgorithm(const EVP_MD * type); int setup_verifyCERT(X509_STORE **newX509_STORE, const char *CApath, const X509** certs); EXP_OPTION int verifyEstIDSignature(const byte* digest, int digestLen, int nDigestType, byte* pSigBuf, int nSigLen, X509* cert); EXP_OPTION int verifyEstIDSignature2(const byte* digest, int digestLen, int nDigestType, byte* pSigBuf, int nSigLen, X509* cert); //=========================================================== // Checks and records the knowledge if one signature had // missing xmlns problem // pSigDoc - signed doc data // returns 1 if at least one signature had this problem //============================================================ EXP_OPTION int checkDdocWrongDigests(const SignedDoc* pSigDoc); EXP_OPTION int validateElementPath(XmlElemInfo* pElem); #ifdef __cplusplus } #endif #endif // __DIGIDOC_VERIFY_H__ libdigidoc-3.10.5/libdigidoc/pkcs11/0000775000372000037200000000000013560273131016467 5ustar travistravislibdigidoc-3.10.5/libdigidoc/pkcs11/pkcs11f.h0000664000372000037200000006572313560273131020125 0ustar travistravis/* pkcs11f.h include file for PKCS #11. 2001 June 25 */ /* This function contains pretty much everything about all the */ /* Cryptoki function prototypes. Because this information is */ /* used for more than just declaring function prototypes, the */ /* order of the functions appearing herein is important, and */ /* should not be altered. */ /* General-purpose */ /* C_Initialize initializes the Cryptoki library. */ CK_PKCS11_FUNCTION_INFO(C_Initialize) #ifdef CK_NEED_ARG_LIST ( CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets * cast to CK_C_INITIALIZE_ARGS_PTR * and dereferenced */ ); #endif /* C_Finalize indicates that an application is done with the * Cryptoki library. */ CK_PKCS11_FUNCTION_INFO(C_Finalize) #ifdef CK_NEED_ARG_LIST ( CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */ ); #endif /* C_GetInfo returns general information about Cryptoki. */ CK_PKCS11_FUNCTION_INFO(C_GetInfo) #ifdef CK_NEED_ARG_LIST ( CK_INFO_PTR pInfo /* location that receives information */ ); #endif /* C_GetFunctionList returns the function list. */ CK_PKCS11_FUNCTION_INFO(C_GetFunctionList) #ifdef CK_NEED_ARG_LIST ( CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to * function list */ ); #endif /* Slot and token management */ /* C_GetSlotList obtains a list of slots in the system. */ CK_PKCS11_FUNCTION_INFO(C_GetSlotList) #ifdef CK_NEED_ARG_LIST ( CK_BBOOL tokenPresent, /* only slots with tokens? */ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */ CK_ULONG_PTR pulCount /* receives number of slots */ ); #endif /* C_GetSlotInfo obtains information about a particular slot in * the system. */ CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo) #ifdef CK_NEED_ARG_LIST ( CK_SLOT_ID slotID, /* the ID of the slot */ CK_SLOT_INFO_PTR pInfo /* receives the slot information */ ); #endif /* C_GetTokenInfo obtains information about a particular token * in the system. */ CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo) #ifdef CK_NEED_ARG_LIST ( CK_SLOT_ID slotID, /* ID of the token's slot */ CK_TOKEN_INFO_PTR pInfo /* receives the token information */ ); #endif /* C_GetMechanismList obtains a list of mechanism types * supported by a token. */ CK_PKCS11_FUNCTION_INFO(C_GetMechanismList) #ifdef CK_NEED_ARG_LIST ( CK_SLOT_ID slotID, /* ID of token's slot */ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */ CK_ULONG_PTR pulCount /* gets # of mechs. */ ); #endif /* C_GetMechanismInfo obtains information about a particular * mechanism possibly supported by a token. */ CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) #ifdef CK_NEED_ARG_LIST ( CK_SLOT_ID slotID, /* ID of the token's slot */ CK_MECHANISM_TYPE type, /* type of mechanism */ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */ ); #endif /* C_InitToken initializes a token. */ CK_PKCS11_FUNCTION_INFO(C_InitToken) #ifdef CK_NEED_ARG_LIST /* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */ ( CK_SLOT_ID slotID, /* ID of the token's slot */ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */ CK_ULONG ulPinLen, /* length in bytes of the PIN */ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */ ); #endif /* C_InitPIN initializes the normal user's PIN. */ CK_PKCS11_FUNCTION_INFO(C_InitPIN) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */ CK_ULONG ulPinLen /* length in bytes of the PIN */ ); #endif /* C_SetPIN modifies the PIN of the user who is logged in. */ CK_PKCS11_FUNCTION_INFO(C_SetPIN) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */ CK_ULONG ulOldLen, /* length of the old PIN */ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */ CK_ULONG ulNewLen /* length of the new PIN */ ); #endif /* Session management */ /* C_OpenSession opens a session between an application and a * token. */ CK_PKCS11_FUNCTION_INFO(C_OpenSession) #ifdef CK_NEED_ARG_LIST ( CK_SLOT_ID slotID, /* the slot's ID */ CK_FLAGS flags, /* from CK_SESSION_INFO */ CK_VOID_PTR pApplication, /* passed to callback */ CK_NOTIFY Notify, /* callback function */ CK_SESSION_HANDLE_PTR phSession /* gets session handle */ ); #endif /* C_CloseSession closes a session between an application and a * token. */ CK_PKCS11_FUNCTION_INFO(C_CloseSession) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession /* the session's handle */ ); #endif /* C_CloseAllSessions closes all sessions with a token. */ CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions) #ifdef CK_NEED_ARG_LIST ( CK_SLOT_ID slotID /* the token's slot */ ); #endif /* C_GetSessionInfo obtains information about the session. */ CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_SESSION_INFO_PTR pInfo /* receives session info */ ); #endif /* C_GetOperationState obtains the state of the cryptographic operation * in a session. */ CK_PKCS11_FUNCTION_INFO(C_GetOperationState) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pOperationState, /* gets state */ CK_ULONG_PTR pulOperationStateLen /* gets state length */ ); #endif /* C_SetOperationState restores the state of the cryptographic * operation in a session. */ CK_PKCS11_FUNCTION_INFO(C_SetOperationState) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pOperationState, /* holds state */ CK_ULONG ulOperationStateLen, /* holds state length */ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */ ); #endif /* C_Login logs a user into a token. */ CK_PKCS11_FUNCTION_INFO(C_Login) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_USER_TYPE userType, /* the user type */ CK_UTF8CHAR_PTR pPin, /* the user's PIN */ CK_ULONG ulPinLen /* the length of the PIN */ ); #endif /* C_Logout logs a user out from a token. */ CK_PKCS11_FUNCTION_INFO(C_Logout) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession /* the session's handle */ ); #endif /* Object management */ /* C_CreateObject creates a new object. */ CK_PKCS11_FUNCTION_INFO(C_CreateObject) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */ CK_ULONG ulCount, /* attributes in template */ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */ ); #endif /* C_CopyObject copies an object, creating a new object for the * copy. */ CK_PKCS11_FUNCTION_INFO(C_CopyObject) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject, /* the object's handle */ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */ CK_ULONG ulCount, /* attributes in template */ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */ ); #endif /* C_DestroyObject destroys an object. */ CK_PKCS11_FUNCTION_INFO(C_DestroyObject) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject /* the object's handle */ ); #endif /* C_GetObjectSize gets the size of an object in bytes. */ CK_PKCS11_FUNCTION_INFO(C_GetObjectSize) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject, /* the object's handle */ CK_ULONG_PTR pulSize /* receives size of object */ ); #endif /* C_GetAttributeValue obtains the value of one or more object * attributes. */ CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject, /* the object's handle */ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */ CK_ULONG ulCount /* attributes in template */ ); #endif /* C_SetAttributeValue modifies the value of one or more object * attributes */ CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject, /* the object's handle */ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */ CK_ULONG ulCount /* attributes in template */ ); #endif /* C_FindObjectsInit initializes a search for token and session * objects that match a template. */ CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */ CK_ULONG ulCount /* attrs in search template */ ); #endif /* C_FindObjects continues a search for token and session * objects that match a template, obtaining additional object * handles. */ CK_PKCS11_FUNCTION_INFO(C_FindObjects) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */ CK_ULONG ulMaxObjectCount, /* max handles to get */ CK_ULONG_PTR pulObjectCount /* actual # returned */ ); #endif /* C_FindObjectsFinal finishes a search for token and session * objects. */ CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession /* the session's handle */ ); #endif /* Encryption and decryption */ /* C_EncryptInit initializes an encryption operation. */ CK_PKCS11_FUNCTION_INFO(C_EncryptInit) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */ CK_OBJECT_HANDLE hKey /* handle of encryption key */ ); #endif /* C_Encrypt encrypts single-part data. */ CK_PKCS11_FUNCTION_INFO(C_Encrypt) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pData, /* the plaintext data */ CK_ULONG ulDataLen, /* bytes of plaintext */ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */ ); #endif /* C_EncryptUpdate continues a multiple-part encryption * operation. */ CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pPart, /* the plaintext data */ CK_ULONG ulPartLen, /* plaintext data len */ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */ ); #endif /* C_EncryptFinal finishes a multiple-part encryption * operation. */ CK_PKCS11_FUNCTION_INFO(C_EncryptFinal) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session handle */ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */ ); #endif /* C_DecryptInit initializes a decryption operation. */ CK_PKCS11_FUNCTION_INFO(C_DecryptInit) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */ CK_OBJECT_HANDLE hKey /* handle of decryption key */ ); #endif /* C_Decrypt decrypts encrypted data in a single part. */ CK_PKCS11_FUNCTION_INFO(C_Decrypt) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pEncryptedData, /* ciphertext */ CK_ULONG ulEncryptedDataLen, /* ciphertext length */ CK_BYTE_PTR pData, /* gets plaintext */ CK_ULONG_PTR pulDataLen /* gets p-text size */ ); #endif /* C_DecryptUpdate continues a multiple-part decryption * operation. */ CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pEncryptedPart, /* encrypted data */ CK_ULONG ulEncryptedPartLen, /* input length */ CK_BYTE_PTR pPart, /* gets plaintext */ CK_ULONG_PTR pulPartLen /* p-text size */ ); #endif /* C_DecryptFinal finishes a multiple-part decryption * operation. */ CK_PKCS11_FUNCTION_INFO(C_DecryptFinal) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pLastPart, /* gets plaintext */ CK_ULONG_PTR pulLastPartLen /* p-text size */ ); #endif /* Message digesting */ /* C_DigestInit initializes a message-digesting operation. */ CK_PKCS11_FUNCTION_INFO(C_DigestInit) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */ ); #endif /* C_Digest digests data in a single part. */ CK_PKCS11_FUNCTION_INFO(C_Digest) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* data to be digested */ CK_ULONG ulDataLen, /* bytes of data to digest */ CK_BYTE_PTR pDigest, /* gets the message digest */ CK_ULONG_PTR pulDigestLen /* gets digest length */ ); #endif /* C_DigestUpdate continues a multiple-part message-digesting * operation. */ CK_PKCS11_FUNCTION_INFO(C_DigestUpdate) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pPart, /* data to be digested */ CK_ULONG ulPartLen /* bytes of data to be digested */ ); #endif /* C_DigestKey continues a multi-part message-digesting * operation, by digesting the value of a secret key as part of * the data already digested. */ CK_PKCS11_FUNCTION_INFO(C_DigestKey) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hKey /* secret key to digest */ ); #endif /* C_DigestFinal finishes a multiple-part message-digesting * operation. */ CK_PKCS11_FUNCTION_INFO(C_DigestFinal) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pDigest, /* gets the message digest */ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */ ); #endif /* Signing and MACing */ /* C_SignInit initializes a signature (private key encryption) * operation, where the signature is (will be) an appendix to * the data, and plaintext cannot be recovered from the *signature. */ CK_PKCS11_FUNCTION_INFO(C_SignInit) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ CK_OBJECT_HANDLE hKey /* handle of signature key */ ); #endif /* C_Sign signs (encrypts with private key) data in a single * part, where the signature is (will be) an appendix to the * data, and plaintext cannot be recovered from the signature. */ CK_PKCS11_FUNCTION_INFO(C_Sign) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* the data to sign */ CK_ULONG ulDataLen, /* count of bytes to sign */ CK_BYTE_PTR pSignature, /* gets the signature */ CK_ULONG_PTR pulSignatureLen /* gets signature length */ ); #endif /* C_SignUpdate continues a multiple-part signature operation, * where the signature is (will be) an appendix to the data, * and plaintext cannot be recovered from the signature. */ CK_PKCS11_FUNCTION_INFO(C_SignUpdate) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pPart, /* the data to sign */ CK_ULONG ulPartLen /* count of bytes to sign */ ); #endif /* C_SignFinal finishes a multiple-part signature operation, * returning the signature. */ CK_PKCS11_FUNCTION_INFO(C_SignFinal) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSignature, /* gets the signature */ CK_ULONG_PTR pulSignatureLen /* gets signature length */ ); #endif /* C_SignRecoverInit initializes a signature operation, where * the data can be recovered from the signature. */ CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ CK_OBJECT_HANDLE hKey /* handle of the signature key */ ); #endif /* C_SignRecover signs data in a single operation, where the * data can be recovered from the signature. */ CK_PKCS11_FUNCTION_INFO(C_SignRecover) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* the data to sign */ CK_ULONG ulDataLen, /* count of bytes to sign */ CK_BYTE_PTR pSignature, /* gets the signature */ CK_ULONG_PTR pulSignatureLen /* gets signature length */ ); #endif /* Verifying signatures and MACs */ /* C_VerifyInit initializes a verification operation, where the * signature is an appendix to the data, and plaintext cannot * cannot be recovered from the signature (e.g. DSA). */ CK_PKCS11_FUNCTION_INFO(C_VerifyInit) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ CK_OBJECT_HANDLE hKey /* verification key */ ); #endif /* C_Verify verifies a signature in a single-part operation, * where the signature is an appendix to the data, and plaintext * cannot be recovered from the signature. */ CK_PKCS11_FUNCTION_INFO(C_Verify) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* signed data */ CK_ULONG ulDataLen, /* length of signed data */ CK_BYTE_PTR pSignature, /* signature */ CK_ULONG ulSignatureLen /* signature length*/ ); #endif /* C_VerifyUpdate continues a multiple-part verification * operation, where the signature is an appendix to the data, * and plaintext cannot be recovered from the signature. */ CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pPart, /* signed data */ CK_ULONG ulPartLen /* length of signed data */ ); #endif /* C_VerifyFinal finishes a multiple-part verification * operation, checking the signature. */ CK_PKCS11_FUNCTION_INFO(C_VerifyFinal) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSignature, /* signature to verify */ CK_ULONG ulSignatureLen /* signature length */ ); #endif /* C_VerifyRecoverInit initializes a signature verification * operation, where the data is recovered from the signature. */ CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ CK_OBJECT_HANDLE hKey /* verification key */ ); #endif /* C_VerifyRecover verifies a signature in a single-part * operation, where the data is recovered from the signature. */ CK_PKCS11_FUNCTION_INFO(C_VerifyRecover) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSignature, /* signature to verify */ CK_ULONG ulSignatureLen, /* signature length */ CK_BYTE_PTR pData, /* gets signed data */ CK_ULONG_PTR pulDataLen /* gets signed data len */ ); #endif /* Dual-function cryptographic operations */ /* C_DigestEncryptUpdate continues a multiple-part digesting * and encryption operation. */ CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pPart, /* the plaintext data */ CK_ULONG ulPartLen, /* plaintext length */ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ ); #endif /* C_DecryptDigestUpdate continues a multiple-part decryption and * digesting operation. */ CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pEncryptedPart, /* ciphertext */ CK_ULONG ulEncryptedPartLen, /* ciphertext length */ CK_BYTE_PTR pPart, /* gets plaintext */ CK_ULONG_PTR pulPartLen /* gets plaintext len */ ); #endif /* C_SignEncryptUpdate continues a multiple-part signing and * encryption operation. */ CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pPart, /* the plaintext data */ CK_ULONG ulPartLen, /* plaintext length */ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ ); #endif /* C_DecryptVerifyUpdate continues a multiple-part decryption and * verify operation. */ CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_BYTE_PTR pEncryptedPart, /* ciphertext */ CK_ULONG ulEncryptedPartLen, /* ciphertext length */ CK_BYTE_PTR pPart, /* gets plaintext */ CK_ULONG_PTR pulPartLen /* gets p-text length */ ); #endif /* Key management */ /* C_GenerateKey generates a secret key, creating a new key * object. */ CK_PKCS11_FUNCTION_INFO(C_GenerateKey) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* key generation mech. */ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */ CK_ULONG ulCount, /* # of attrs in template */ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */ ); #endif /* C_GenerateKeyPair generates a public-key/private-key pair, * creating new key objects. */ CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session * handle */ CK_MECHANISM_PTR pMechanism, /* key-gen * mech. */ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template * for pub. * key */ CK_ULONG ulPublicKeyAttributeCount, /* # pub. * attrs. */ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template * for priv. * key */ CK_ULONG ulPrivateKeyAttributeCount, /* # priv. * attrs. */ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. * key * handle */ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets * priv. key * handle */ ); #endif /* C_WrapKey wraps (i.e., encrypts) a key. */ CK_PKCS11_FUNCTION_INFO(C_WrapKey) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */ CK_OBJECT_HANDLE hKey, /* key to be wrapped */ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */ ); #endif /* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new * key object. */ CK_PKCS11_FUNCTION_INFO(C_UnwrapKey) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */ CK_BYTE_PTR pWrappedKey, /* the wrapped key */ CK_ULONG ulWrappedKeyLen, /* wrapped key len */ CK_ATTRIBUTE_PTR pTemplate, /* new key template */ CK_ULONG ulAttributeCount, /* template length */ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ ); #endif /* C_DeriveKey derives a key from a base key, creating a new key * object. */ CK_PKCS11_FUNCTION_INFO(C_DeriveKey) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* session's handle */ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */ CK_OBJECT_HANDLE hBaseKey, /* base key */ CK_ATTRIBUTE_PTR pTemplate, /* new key template */ CK_ULONG ulAttributeCount, /* template length */ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ ); #endif /* Random number generation */ /* C_SeedRandom mixes additional seed material into the token's * random number generator. */ CK_PKCS11_FUNCTION_INFO(C_SeedRandom) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSeed, /* the seed material */ CK_ULONG ulSeedLen /* length of seed material */ ); #endif /* C_GenerateRandom generates random data. */ CK_PKCS11_FUNCTION_INFO(C_GenerateRandom) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR RandomData, /* receives the random data */ CK_ULONG ulRandomLen /* # of bytes to generate */ ); #endif /* Parallel function management */ /* C_GetFunctionStatus is a legacy function; it obtains an * updated status of a function running in parallel with an * application. */ CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession /* the session's handle */ ); #endif /* C_CancelFunction is a legacy function; it cancels a function * running in parallel. */ CK_PKCS11_FUNCTION_INFO(C_CancelFunction) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession /* the session's handle */ ); #endif /* Functions added in for Cryptoki Version 2.01 or later */ /* C_WaitForSlotEvent waits for a slot event (token insertion, * removal, etc.) to occur. */ CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent) #ifdef CK_NEED_ARG_LIST ( CK_FLAGS flags, /* blocking/nonblocking flag */ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */ ); #endif libdigidoc-3.10.5/libdigidoc/pkcs11/pkcs11t.h0000664000372000037200000014021413560273131020130 0ustar travistravis/* pkcs11t.h include file for PKCS #11. 2001 June 25 */ /* See top of pkcs11.h for information about the macros that * must be defined and the structure-packing conventions that * must be set before including this file. */ #ifndef _PKCS11T_H_ #define _PKCS11T_H_ 1 #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE (!FALSE) #endif /* an unsigned 8-bit value */ typedef unsigned char CK_BYTE; /* an unsigned 8-bit character */ typedef CK_BYTE CK_CHAR; /* an 8-bit UTF-8 character */ typedef CK_BYTE CK_UTF8CHAR; /* a BYTE-sized Boolean flag */ typedef CK_BYTE CK_BBOOL; /* an unsigned value, at least 32 bits long */ typedef unsigned long int CK_ULONG; /* a signed value, the same size as a CK_ULONG */ /* CK_LONG is new for v2.0 */ typedef long int CK_LONG; /* at least 32 bits; each bit is a Boolean flag */ typedef CK_ULONG CK_FLAGS; /* some special values for certain CK_ULONG variables */ #define CK_UNAVAILABLE_INFORMATION (~0UL) #define CK_EFFECTIVELY_INFINITE 0 typedef CK_BYTE CK_PTR CK_BYTE_PTR; typedef CK_CHAR CK_PTR CK_CHAR_PTR; typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; typedef CK_ULONG CK_PTR CK_ULONG_PTR; typedef void CK_PTR CK_VOID_PTR; /* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */ typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; /* The following value is always invalid if used as a session */ /* handle or object handle */ #define CK_INVALID_HANDLE 0 typedef struct CK_VERSION { CK_BYTE major; /* integer portion of version number */ CK_BYTE minor; /* 1/100ths portion of version number */ } CK_VERSION; typedef CK_VERSION CK_PTR CK_VERSION_PTR; typedef struct CK_INFO { /* manufacturerID and libraryDecription have been changed from * CK_CHAR to CK_UTF8CHAR for v2.10 */ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS flags; /* must be zero */ /* libraryDescription and libraryVersion are new for v2.0 */ CK_UTF8CHAR libraryDescription[32]; /* blank padded */ CK_VERSION libraryVersion; /* version of library */ } CK_INFO; typedef CK_INFO CK_PTR CK_INFO_PTR; /* CK_NOTIFICATION enumerates the types of notifications that * Cryptoki provides to an application */ /* CK_NOTIFICATION has been changed from an enum to a CK_ULONG * for v2.0 */ typedef CK_ULONG CK_NOTIFICATION; #define CKN_SURRENDER 0 typedef CK_ULONG CK_SLOT_ID; typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; /* CK_SLOT_INFO provides information about a slot */ typedef struct CK_SLOT_INFO { /* slotDescription and manufacturerID have been changed from * CK_CHAR to CK_UTF8CHAR for v2.10 */ CK_UTF8CHAR slotDescription[64]; /* blank padded */ CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS flags; /* hardwareVersion and firmwareVersion are new for v2.0 */ CK_VERSION hardwareVersion; /* version of hardware */ CK_VERSION firmwareVersion; /* version of firmware */ } CK_SLOT_INFO; /* flags: bit flags that provide capabilities of the slot * Bit Flag Mask Meaning */ #define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */ #define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/ #define CKF_HW_SLOT 0x00000004 /* hardware slot */ typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; /* CK_TOKEN_INFO provides information about a token */ typedef struct CK_TOKEN_INFO { /* label, manufacturerID, and model have been changed from * CK_CHAR to CK_UTF8CHAR for v2.10 */ CK_UTF8CHAR label[32]; /* blank padded */ CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_UTF8CHAR model[16]; /* blank padded */ CK_CHAR serialNumber[16]; /* blank padded */ CK_FLAGS flags; /* see below */ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount, * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been * changed from CK_USHORT to CK_ULONG for v2.0 */ CK_ULONG ulMaxSessionCount; /* max open sessions */ CK_ULONG ulSessionCount; /* sess. now open */ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ CK_ULONG ulRwSessionCount; /* R/W sess. now open */ CK_ULONG ulMaxPinLen; /* in bytes */ CK_ULONG ulMinPinLen; /* in bytes */ CK_ULONG ulTotalPublicMemory; /* in bytes */ CK_ULONG ulFreePublicMemory; /* in bytes */ CK_ULONG ulTotalPrivateMemory; /* in bytes */ CK_ULONG ulFreePrivateMemory; /* in bytes */ /* hardwareVersion, firmwareVersion, and time are new for * v2.0 */ CK_VERSION hardwareVersion; /* version of hardware */ CK_VERSION firmwareVersion; /* version of firmware */ CK_CHAR utcTime[16]; /* time */ } CK_TOKEN_INFO; /* The flags parameter is defined as follows: * Bit Flag Mask Meaning */ #define CKF_RNG 0x00000001 /* has random # * generator */ #define CKF_WRITE_PROTECTED 0x00000002 /* token is * write- * protected */ #define CKF_LOGIN_REQUIRED 0x00000004 /* user must * login */ #define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's * PIN is set */ /* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set, * that means that *every* time the state of cryptographic * operations of a session is successfully saved, all keys * needed to continue those operations are stored in the state */ #define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020 /* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means * that the token has some sort of clock. The time on that * clock is returned in the token info structure */ #define CKF_CLOCK_ON_TOKEN 0x00000040 /* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is * set, that means that there is some way for the user to login * without sending a PIN through the Cryptoki library itself */ #define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100 /* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true, * that means that a single session with the token can perform * dual simultaneous cryptographic operations (digest and * encrypt; decrypt and digest; sign and encrypt; and decrypt * and sign) */ #define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 /* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the * token has been initialized using C_InitializeToken or an * equivalent mechanism outside the scope of PKCS #11. * Calling C_InitializeToken when this flag is set will cause * the token to be reinitialized. */ #define CKF_TOKEN_INITIALIZED 0x00000400 /* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is * true, the token supports secondary authentication for * private key objects. */ #define CKF_SECONDARY_AUTHENTICATION 0x00000800 /* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an * incorrect user login PIN has been entered at least once * since the last successful authentication. */ #define CKF_USER_PIN_COUNT_LOW 0x00010000 /* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true, * supplying an incorrect user PIN will it to become locked. */ #define CKF_USER_PIN_FINAL_TRY 0x00020000 /* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the * user PIN has been locked. User login to the token is not * possible. */ #define CKF_USER_PIN_LOCKED 0x00040000 /* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, * the user PIN value is the default value set by token * initialization or manufacturing, or the PIN has been * expired by the card. */ #define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 /* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an * incorrect SO login PIN has been entered at least once since * the last successful authentication. */ #define CKF_SO_PIN_COUNT_LOW 0x00100000 /* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true, * supplying an incorrect SO PIN will it to become locked. */ #define CKF_SO_PIN_FINAL_TRY 0x00200000 /* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO * PIN has been locked. SO login to the token is not possible. */ #define CKF_SO_PIN_LOCKED 0x00400000 /* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, * the SO PIN value is the default value set by token * initialization or manufacturing, or the PIN has been * expired by the card. */ #define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; /* CK_SESSION_HANDLE is a Cryptoki-assigned value that * identifies a session */ typedef CK_ULONG CK_SESSION_HANDLE; typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; /* CK_USER_TYPE enumerates the types of Cryptoki users */ /* CK_USER_TYPE has been changed from an enum to a CK_ULONG for * v2.0 */ typedef CK_ULONG CK_USER_TYPE; /* Security Officer */ #define CKU_SO 0 /* Normal user */ #define CKU_USER 1 /* CK_STATE enumerates the session states */ /* CK_STATE has been changed from an enum to a CK_ULONG for * v2.0 */ typedef CK_ULONG CK_STATE; #define CKS_RO_PUBLIC_SESSION 0 #define CKS_RO_USER_FUNCTIONS 1 #define CKS_RW_PUBLIC_SESSION 2 #define CKS_RW_USER_FUNCTIONS 3 #define CKS_RW_SO_FUNCTIONS 4 /* CK_SESSION_INFO provides information about a session */ typedef struct CK_SESSION_INFO { CK_SLOT_ID slotID; CK_STATE state; CK_FLAGS flags; /* see below */ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for * v2.0 */ CK_ULONG ulDeviceError; /* device-dependent error code */ } CK_SESSION_INFO; /* The flags are defined in the following table: * Bit Flag Mask Meaning */ #define CKF_RW_SESSION 0x00000002 /* session is r/w */ #define CKF_SERIAL_SESSION 0x00000004 /* no parallel */ typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; /* CK_OBJECT_HANDLE is a token-specific identifier for an * object */ typedef CK_ULONG CK_OBJECT_HANDLE; typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; /* CK_OBJECT_CLASS is a value that identifies the classes (or * types) of objects that Cryptoki recognizes. It is defined * as follows: */ /* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for * v2.0 */ typedef CK_ULONG CK_OBJECT_CLASS; /* The following classes of objects are defined: */ /* CKO_HW_FEATURE is new for v2.10 */ /* CKO_DOMAIN_PARAMETERS is new for v2.11 */ #define CKO_DATA 0x00000000 #define CKO_CERTIFICATE 0x00000001 #define CKO_PUBLIC_KEY 0x00000002 #define CKO_PRIVATE_KEY 0x00000003 #define CKO_SECRET_KEY 0x00000004 #define CKO_HW_FEATURE 0x00000005 #define CKO_DOMAIN_PARAMETERS 0x00000006 #define CKO_VENDOR_DEFINED 0x80000000 typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; /* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a * value that identifies the hardware feature type of an object * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ typedef CK_ULONG CK_HW_FEATURE_TYPE; /* The following hardware feature types are defined */ #define CKH_MONOTONIC_COUNTER 0x00000001 #define CKH_CLOCK 0x00000002 #define CKH_VENDOR_DEFINED 0x80000000 /* CK_KEY_TYPE is a value that identifies a key type */ /* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ typedef CK_ULONG CK_KEY_TYPE; /* the following key types are defined: */ #define CKK_RSA 0x00000000 #define CKK_DSA 0x00000001 #define CKK_DH 0x00000002 /* CKK_ECDSA and CKK_KEA are new for v2.0 */ /* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */ #define CKK_ECDSA 0x00000003 #define CKK_EC 0x00000003 #define CKK_X9_42_DH 0x00000004 #define CKK_KEA 0x00000005 #define CKK_GENERIC_SECRET 0x00000010 #define CKK_RC2 0x00000011 #define CKK_RC4 0x00000012 #define CKK_DES 0x00000013 #define CKK_DES2 0x00000014 #define CKK_DES3 0x00000015 /* all these key types are new for v2.0 */ #define CKK_CAST 0x00000016 #define CKK_CAST3 0x00000017 /* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */ #define CKK_CAST5 0x00000018 #define CKK_CAST128 0x00000018 #define CKK_RC5 0x00000019 #define CKK_IDEA 0x0000001A #define CKK_SKIPJACK 0x0000001B #define CKK_BATON 0x0000001C #define CKK_JUNIPER 0x0000001D #define CKK_CDMF 0x0000001E #define CKK_AES 0x0000001F #define CKK_VENDOR_DEFINED 0x80000000 /* CK_CERTIFICATE_TYPE is a value that identifies a certificate * type */ /* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG * for v2.0 */ typedef CK_ULONG CK_CERTIFICATE_TYPE; /* The following certificate types are defined: */ /* CKC_X_509_ATTR_CERT is new for v2.10 */ #define CKC_X_509 0x00000000 #define CKC_X_509_ATTR_CERT 0x00000001 #define CKC_VENDOR_DEFINED 0x80000000 /* CK_ATTRIBUTE_TYPE is a value that identifies an attribute * type */ /* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for * v2.0 */ typedef CK_ULONG CK_ATTRIBUTE_TYPE; /* The following attribute types are defined: */ #define CKA_CLASS 0x00000000 #define CKA_TOKEN 0x00000001 #define CKA_PRIVATE 0x00000002 #define CKA_LABEL 0x00000003 #define CKA_APPLICATION 0x00000010 #define CKA_VALUE 0x00000011 /* CKA_OBJECT_ID is new for v2.10 */ #define CKA_OBJECT_ID 0x00000012 #define CKA_CERTIFICATE_TYPE 0x00000080 #define CKA_ISSUER 0x00000081 #define CKA_SERIAL_NUMBER 0x00000082 /* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new * for v2.10 */ #define CKA_AC_ISSUER 0x00000083 #define CKA_OWNER 0x00000084 #define CKA_ATTR_TYPES 0x00000085 /* CKA_TRUSTED is new for v2.11 */ #define CKA_TRUSTED 0x00000086 #define CKA_KEY_TYPE 0x00000100 #define CKA_SUBJECT 0x00000101 #define CKA_ID 0x00000102 #define CKA_SENSITIVE 0x00000103 #define CKA_ENCRYPT 0x00000104 #define CKA_DECRYPT 0x00000105 #define CKA_WRAP 0x00000106 #define CKA_UNWRAP 0x00000107 #define CKA_SIGN 0x00000108 #define CKA_SIGN_RECOVER 0x00000109 #define CKA_VERIFY 0x0000010A #define CKA_VERIFY_RECOVER 0x0000010B #define CKA_DERIVE 0x0000010C #define CKA_START_DATE 0x00000110 #define CKA_END_DATE 0x00000111 #define CKA_MODULUS 0x00000120 #define CKA_MODULUS_BITS 0x00000121 #define CKA_PUBLIC_EXPONENT 0x00000122 #define CKA_PRIVATE_EXPONENT 0x00000123 #define CKA_PRIME_1 0x00000124 #define CKA_PRIME_2 0x00000125 #define CKA_EXPONENT_1 0x00000126 #define CKA_EXPONENT_2 0x00000127 #define CKA_COEFFICIENT 0x00000128 #define CKA_PRIME 0x00000130 #define CKA_SUBPRIME 0x00000131 #define CKA_BASE 0x00000132 /* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */ #define CKA_PRIME_BITS 0x00000133 #define CKA_SUB_PRIME_BITS 0x00000134 #define CKA_VALUE_BITS 0x00000160 #define CKA_VALUE_LEN 0x00000161 /* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS, * and CKA_EC_POINT are new for v2.0 */ #define CKA_EXTRACTABLE 0x00000162 #define CKA_LOCAL 0x00000163 #define CKA_NEVER_EXTRACTABLE 0x00000164 #define CKA_ALWAYS_SENSITIVE 0x00000165 /* CKA_KEY_GEN_MECHANISM is new for v2.11 */ #define CKA_KEY_GEN_MECHANISM 0x00000166 #define CKA_MODIFIABLE 0x00000170 /* CKA_ECDSA_PARAMS is deprecated in v2.11, * CKA_EC_PARAMS is preferred. */ #define CKA_ECDSA_PARAMS 0x00000180 #define CKA_EC_PARAMS 0x00000180 #define CKA_EC_POINT 0x00000181 /* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, * CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET * are new for v2.10 */ #define CKA_SECONDARY_AUTH 0x00000200 #define CKA_AUTH_PIN_FLAGS 0x00000201 #define CKA_HW_FEATURE_TYPE 0x00000300 #define CKA_RESET_ON_INIT 0x00000301 #define CKA_HAS_RESET 0x00000302 #define CKA_VENDOR_DEFINED 0x80000000 /* CK_ATTRIBUTE is a structure that includes the type, length * and value of an attribute */ typedef struct CK_ATTRIBUTE { CK_ATTRIBUTE_TYPE type; CK_VOID_PTR pValue; /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */ CK_ULONG ulValueLen; /* in bytes */ } CK_ATTRIBUTE; typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR; /* CK_DATE is a structure that defines a date */ typedef struct CK_DATE{ CK_CHAR year[4]; /* the year ("1900" - "9999") */ CK_CHAR month[2]; /* the month ("01" - "12") */ CK_CHAR day[2]; /* the day ("01" - "31") */ } CK_DATE; /* CK_MECHANISM_TYPE is a value that identifies a mechanism * type */ /* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for * v2.0 */ typedef CK_ULONG CK_MECHANISM_TYPE; /* the following mechanism types are defined: */ #define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 #define CKM_RSA_PKCS 0x00000001 #define CKM_RSA_9796 0x00000002 #define CKM_RSA_X_509 0x00000003 /* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS * are new for v2.0. They are mechanisms which hash and sign */ #define CKM_MD2_RSA_PKCS 0x00000004 #define CKM_MD5_RSA_PKCS 0x00000005 #define CKM_SHA1_RSA_PKCS 0x00000006 /* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and * CKM_RSA_PKCS_OAEP are new for v2.10 */ #define CKM_RIPEMD128_RSA_PKCS 0x00000007 #define CKM_RIPEMD160_RSA_PKCS 0x00000008 #define CKM_RSA_PKCS_OAEP 0x00000009 /* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31, * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */ #define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A #define CKM_RSA_X9_31 0x0000000B #define CKM_SHA1_RSA_X9_31 0x0000000C #define CKM_RSA_PKCS_PSS 0x0000000D #define CKM_SHA1_RSA_PKCS_PSS 0x0000000E #define CKM_DSA_KEY_PAIR_GEN 0x00000010 #define CKM_DSA 0x00000011 #define CKM_DSA_SHA1 0x00000012 #define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 #define CKM_DH_PKCS_DERIVE 0x00000021 /* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for * v2.11 */ #define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030 #define CKM_X9_42_DH_DERIVE 0x00000031 #define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032 #define CKM_X9_42_MQV_DERIVE 0x00000033 #define CKM_RC2_KEY_GEN 0x00000100 #define CKM_RC2_ECB 0x00000101 #define CKM_RC2_CBC 0x00000102 #define CKM_RC2_MAC 0x00000103 /* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */ #define CKM_RC2_MAC_GENERAL 0x00000104 #define CKM_RC2_CBC_PAD 0x00000105 #define CKM_RC4_KEY_GEN 0x00000110 #define CKM_RC4 0x00000111 #define CKM_DES_KEY_GEN 0x00000120 #define CKM_DES_ECB 0x00000121 #define CKM_DES_CBC 0x00000122 #define CKM_DES_MAC 0x00000123 /* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */ #define CKM_DES_MAC_GENERAL 0x00000124 #define CKM_DES_CBC_PAD 0x00000125 #define CKM_DES2_KEY_GEN 0x00000130 #define CKM_DES3_KEY_GEN 0x00000131 #define CKM_DES3_ECB 0x00000132 #define CKM_DES3_CBC 0x00000133 #define CKM_DES3_MAC 0x00000134 /* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN, * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC, * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */ #define CKM_DES3_MAC_GENERAL 0x00000135 #define CKM_DES3_CBC_PAD 0x00000136 #define CKM_CDMF_KEY_GEN 0x00000140 #define CKM_CDMF_ECB 0x00000141 #define CKM_CDMF_CBC 0x00000142 #define CKM_CDMF_MAC 0x00000143 #define CKM_CDMF_MAC_GENERAL 0x00000144 #define CKM_CDMF_CBC_PAD 0x00000145 #define CKM_MD2 0x00000200 /* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ #define CKM_MD2_HMAC 0x00000201 #define CKM_MD2_HMAC_GENERAL 0x00000202 #define CKM_MD5 0x00000210 /* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */ #define CKM_MD5_HMAC 0x00000211 #define CKM_MD5_HMAC_GENERAL 0x00000212 #define CKM_SHA_1 0x00000220 /* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */ #define CKM_SHA_1_HMAC 0x00000221 #define CKM_SHA_1_HMAC_GENERAL 0x00000222 /* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC, * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */ #define CKM_RIPEMD128 0x00000230 #define CKM_RIPEMD128_HMAC 0x00000231 #define CKM_RIPEMD128_HMAC_GENERAL 0x00000232 #define CKM_RIPEMD160 0x00000240 #define CKM_RIPEMD160_HMAC 0x00000241 #define CKM_RIPEMD160_HMAC_GENERAL 0x00000242 /* All of the following mechanisms are new for v2.0 */ /* Note that CAST128 and CAST5 are the same algorithm */ #define CKM_CAST_KEY_GEN 0x00000300 #define CKM_CAST_ECB 0x00000301 #define CKM_CAST_CBC 0x00000302 #define CKM_CAST_MAC 0x00000303 #define CKM_CAST_MAC_GENERAL 0x00000304 #define CKM_CAST_CBC_PAD 0x00000305 #define CKM_CAST3_KEY_GEN 0x00000310 #define CKM_CAST3_ECB 0x00000311 #define CKM_CAST3_CBC 0x00000312 #define CKM_CAST3_MAC 0x00000313 #define CKM_CAST3_MAC_GENERAL 0x00000314 #define CKM_CAST3_CBC_PAD 0x00000315 #define CKM_CAST5_KEY_GEN 0x00000320 #define CKM_CAST128_KEY_GEN 0x00000320 #define CKM_CAST5_ECB 0x00000321 #define CKM_CAST128_ECB 0x00000321 #define CKM_CAST5_CBC 0x00000322 #define CKM_CAST128_CBC 0x00000322 #define CKM_CAST5_MAC 0x00000323 #define CKM_CAST128_MAC 0x00000323 #define CKM_CAST5_MAC_GENERAL 0x00000324 #define CKM_CAST128_MAC_GENERAL 0x00000324 #define CKM_CAST5_CBC_PAD 0x00000325 #define CKM_CAST128_CBC_PAD 0x00000325 #define CKM_RC5_KEY_GEN 0x00000330 #define CKM_RC5_ECB 0x00000331 #define CKM_RC5_CBC 0x00000332 #define CKM_RC5_MAC 0x00000333 #define CKM_RC5_MAC_GENERAL 0x00000334 #define CKM_RC5_CBC_PAD 0x00000335 #define CKM_IDEA_KEY_GEN 0x00000340 #define CKM_IDEA_ECB 0x00000341 #define CKM_IDEA_CBC 0x00000342 #define CKM_IDEA_MAC 0x00000343 #define CKM_IDEA_MAC_GENERAL 0x00000344 #define CKM_IDEA_CBC_PAD 0x00000345 #define CKM_GENERIC_SECRET_KEY_GEN 0x00000350 #define CKM_CONCATENATE_BASE_AND_KEY 0x00000360 #define CKM_CONCATENATE_BASE_AND_DATA 0x00000362 #define CKM_CONCATENATE_DATA_AND_BASE 0x00000363 #define CKM_XOR_BASE_AND_DATA 0x00000364 #define CKM_EXTRACT_KEY_FROM_KEY 0x00000365 #define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 #define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 #define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 /* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN, * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */ #define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373 #define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374 #define CKM_TLS_MASTER_KEY_DERIVE 0x00000375 #define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376 #define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377 #define CKM_SSL3_MD5_MAC 0x00000380 #define CKM_SSL3_SHA1_MAC 0x00000381 #define CKM_MD5_KEY_DERIVATION 0x00000390 #define CKM_MD2_KEY_DERIVATION 0x00000391 #define CKM_SHA1_KEY_DERIVATION 0x00000392 #define CKM_PBE_MD2_DES_CBC 0x000003A0 #define CKM_PBE_MD5_DES_CBC 0x000003A1 #define CKM_PBE_MD5_CAST_CBC 0x000003A2 #define CKM_PBE_MD5_CAST3_CBC 0x000003A3 #define CKM_PBE_MD5_CAST5_CBC 0x000003A4 #define CKM_PBE_MD5_CAST128_CBC 0x000003A4 #define CKM_PBE_SHA1_CAST5_CBC 0x000003A5 #define CKM_PBE_SHA1_CAST128_CBC 0x000003A5 #define CKM_PBE_SHA1_RC4_128 0x000003A6 #define CKM_PBE_SHA1_RC4_40 0x000003A7 #define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8 #define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 #define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA #define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB /* CKM_PKCS5_PBKD2 is new for v2.10 */ #define CKM_PKCS5_PBKD2 0x000003B0 #define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 #define CKM_KEY_WRAP_LYNKS 0x00000400 #define CKM_KEY_WRAP_SET_OAEP 0x00000401 /* Fortezza mechanisms */ #define CKM_SKIPJACK_KEY_GEN 0x00001000 #define CKM_SKIPJACK_ECB64 0x00001001 #define CKM_SKIPJACK_CBC64 0x00001002 #define CKM_SKIPJACK_OFB64 0x00001003 #define CKM_SKIPJACK_CFB64 0x00001004 #define CKM_SKIPJACK_CFB32 0x00001005 #define CKM_SKIPJACK_CFB16 0x00001006 #define CKM_SKIPJACK_CFB8 0x00001007 #define CKM_SKIPJACK_WRAP 0x00001008 #define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009 #define CKM_SKIPJACK_RELAYX 0x0000100a #define CKM_KEA_KEY_PAIR_GEN 0x00001010 #define CKM_KEA_KEY_DERIVE 0x00001011 #define CKM_FORTEZZA_TIMESTAMP 0x00001020 #define CKM_BATON_KEY_GEN 0x00001030 #define CKM_BATON_ECB128 0x00001031 #define CKM_BATON_ECB96 0x00001032 #define CKM_BATON_CBC128 0x00001033 #define CKM_BATON_COUNTER 0x00001034 #define CKM_BATON_SHUFFLE 0x00001035 #define CKM_BATON_WRAP 0x00001036 /* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11, * CKM_EC_KEY_PAIR_GEN is preferred */ #define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 #define CKM_EC_KEY_PAIR_GEN 0x00001040 #define CKM_ECDSA 0x00001041 #define CKM_ECDSA_SHA1 0x00001042 /* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE * are new for v2.11 */ #define CKM_ECDH1_DERIVE 0x00001050 #define CKM_ECDH1_COFACTOR_DERIVE 0x00001051 #define CKM_ECMQV_DERIVE 0x00001052 #define CKM_JUNIPER_KEY_GEN 0x00001060 #define CKM_JUNIPER_ECB128 0x00001061 #define CKM_JUNIPER_CBC128 0x00001062 #define CKM_JUNIPER_COUNTER 0x00001063 #define CKM_JUNIPER_SHUFFLE 0x00001064 #define CKM_JUNIPER_WRAP 0x00001065 #define CKM_FASTHASH 0x00001070 /* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC, * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN, * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are * new for v2.11 */ #define CKM_AES_KEY_GEN 0x00001080 #define CKM_AES_ECB 0x00001081 #define CKM_AES_CBC 0x00001082 #define CKM_AES_MAC 0x00001083 #define CKM_AES_MAC_GENERAL 0x00001084 #define CKM_AES_CBC_PAD 0x00001085 #define CKM_DSA_PARAMETER_GEN 0x00002000 #define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 #define CKM_X9_42_DH_PARAMETER_GEN 0x00002002 #define CKM_VENDOR_DEFINED 0x80000000 typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; /* CK_MECHANISM is a structure that specifies a particular * mechanism */ typedef struct CK_MECHANISM { CK_MECHANISM_TYPE mechanism; CK_VOID_PTR pParameter; /* ulParameterLen was changed from CK_USHORT to CK_ULONG for * v2.0 */ CK_ULONG ulParameterLen; /* in bytes */ } CK_MECHANISM; typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; /* CK_MECHANISM_INFO provides information about a particular * mechanism */ typedef struct CK_MECHANISM_INFO { CK_ULONG ulMinKeySize; CK_ULONG ulMaxKeySize; CK_FLAGS flags; } CK_MECHANISM_INFO; /* The flags are defined as follows: * Bit Flag Mask Meaning */ #define CKF_HW 0x00000001 /* performed by HW */ /* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN, * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER, * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, * and CKF_DERIVE are new for v2.0. They specify whether or not * a mechanism can be used for a particular task */ #define CKF_ENCRYPT 0x00000100 #define CKF_DECRYPT 0x00000200 #define CKF_DIGEST 0x00000400 #define CKF_SIGN 0x00000800 #define CKF_SIGN_RECOVER 0x00001000 #define CKF_VERIFY 0x00002000 #define CKF_VERIFY_RECOVER 0x00004000 #define CKF_GENERATE 0x00008000 #define CKF_GENERATE_KEY_PAIR 0x00010000 #define CKF_WRAP 0x00020000 #define CKF_UNWRAP 0x00040000 #define CKF_DERIVE 0x00080000 /* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They * describe a token's EC capabilities not available in mechanism * information. */ #define CKF_EC_F_P 0x00100000 #define CKF_EC_F_2M 0x00200000 #define CKF_EC_ECPARAMETERS 0x00400000 #define CKF_EC_NAMEDCURVE 0x00800000 #define CKF_EC_UNCOMPRESS 0x01000000 #define CKF_EC_COMPRESS 0x02000000 #define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */ typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; /* CK_RV is a value that identifies the return value of a * Cryptoki function */ /* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */ typedef CK_ULONG CK_RV; #define CKR_OK 0x00000000 #define CKR_CANCEL 0x00000001 #define CKR_HOST_MEMORY 0x00000002 #define CKR_SLOT_ID_INVALID 0x00000003 /* CKR_FLAGS_INVALID was removed for v2.0 */ /* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */ #define CKR_GENERAL_ERROR 0x00000005 #define CKR_FUNCTION_FAILED 0x00000006 /* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS, * and CKR_CANT_LOCK are new for v2.01 */ #define CKR_ARGUMENTS_BAD 0x00000007 #define CKR_NO_EVENT 0x00000008 #define CKR_NEED_TO_CREATE_THREADS 0x00000009 #define CKR_CANT_LOCK 0x0000000A #define CKR_ATTRIBUTE_READ_ONLY 0x00000010 #define CKR_ATTRIBUTE_SENSITIVE 0x00000011 #define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012 #define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013 #define CKR_DATA_INVALID 0x00000020 #define CKR_DATA_LEN_RANGE 0x00000021 #define CKR_DEVICE_ERROR 0x00000030 #define CKR_DEVICE_MEMORY 0x00000031 #define CKR_DEVICE_REMOVED 0x00000032 #define CKR_ENCRYPTED_DATA_INVALID 0x00000040 #define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041 #define CKR_FUNCTION_CANCELED 0x00000050 #define CKR_FUNCTION_NOT_PARALLEL 0x00000051 /* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */ #define CKR_FUNCTION_NOT_SUPPORTED 0x00000054 #define CKR_KEY_HANDLE_INVALID 0x00000060 /* CKR_KEY_SENSITIVE was removed for v2.0 */ #define CKR_KEY_SIZE_RANGE 0x00000062 #define CKR_KEY_TYPE_INCONSISTENT 0x00000063 /* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED, * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED, * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for * v2.0 */ #define CKR_KEY_NOT_NEEDED 0x00000064 #define CKR_KEY_CHANGED 0x00000065 #define CKR_KEY_NEEDED 0x00000066 #define CKR_KEY_INDIGESTIBLE 0x00000067 #define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068 #define CKR_KEY_NOT_WRAPPABLE 0x00000069 #define CKR_KEY_UNEXTRACTABLE 0x0000006A #define CKR_MECHANISM_INVALID 0x00000070 #define CKR_MECHANISM_PARAM_INVALID 0x00000071 /* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID * were removed for v2.0 */ #define CKR_OBJECT_HANDLE_INVALID 0x00000082 #define CKR_OPERATION_ACTIVE 0x00000090 #define CKR_OPERATION_NOT_INITIALIZED 0x00000091 #define CKR_PIN_INCORRECT 0x000000A0 #define CKR_PIN_INVALID 0x000000A1 #define CKR_PIN_LEN_RANGE 0x000000A2 /* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */ #define CKR_PIN_EXPIRED 0x000000A3 #define CKR_PIN_LOCKED 0x000000A4 #define CKR_SESSION_CLOSED 0x000000B0 #define CKR_SESSION_COUNT 0x000000B1 #define CKR_SESSION_HANDLE_INVALID 0x000000B3 #define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4 #define CKR_SESSION_READ_ONLY 0x000000B5 #define CKR_SESSION_EXISTS 0x000000B6 /* CKR_SESSION_READ_ONLY_EXISTS and * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */ #define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7 #define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8 #define CKR_SIGNATURE_INVALID 0x000000C0 #define CKR_SIGNATURE_LEN_RANGE 0x000000C1 #define CKR_TEMPLATE_INCOMPLETE 0x000000D0 #define CKR_TEMPLATE_INCONSISTENT 0x000000D1 #define CKR_TOKEN_NOT_PRESENT 0x000000E0 #define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1 #define CKR_TOKEN_WRITE_PROTECTED 0x000000E2 #define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0 #define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1 #define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2 #define CKR_USER_ALREADY_LOGGED_IN 0x00000100 #define CKR_USER_NOT_LOGGED_IN 0x00000101 #define CKR_USER_PIN_NOT_INITIALIZED 0x00000102 #define CKR_USER_TYPE_INVALID 0x00000103 /* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES * are new to v2.01 */ #define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104 #define CKR_USER_TOO_MANY_TYPES 0x00000105 #define CKR_WRAPPED_KEY_INVALID 0x00000110 #define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112 #define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113 #define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114 #define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 #define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 /* These are new to v2.0 */ #define CKR_RANDOM_NO_RNG 0x00000121 /* These are new to v2.11 */ #define CKR_DOMAIN_PARAMS_INVALID 0x00000130 /* These are new to v2.0 */ #define CKR_BUFFER_TOO_SMALL 0x00000150 #define CKR_SAVED_STATE_INVALID 0x00000160 #define CKR_INFORMATION_SENSITIVE 0x00000170 #define CKR_STATE_UNSAVEABLE 0x00000180 /* These are new to v2.01 */ #define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190 #define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191 #define CKR_MUTEX_BAD 0x000001A0 #define CKR_MUTEX_NOT_LOCKED 0x000001A1 #define CKR_VENDOR_DEFINED 0x80000000 /* CK_NOTIFY is an application callback that processes events */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_NOTIFICATION event, CK_VOID_PTR pApplication /* passed to C_OpenSession */ ); /* CK_FUNCTION_LIST is a structure holding a Cryptoki spec * version and pointers of appropriate types to all the * Cryptoki functions */ /* CK_FUNCTION_LIST is new for v2.0 */ typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; /* CK_CREATEMUTEX is an application callback for creating a * mutex object */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ ); /* CK_DESTROYMUTEX is an application callback for destroying a * mutex object */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)( CK_VOID_PTR pMutex /* pointer to mutex */ ); /* CK_LOCKMUTEX is an application callback for locking a mutex */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( CK_VOID_PTR pMutex /* pointer to mutex */ ); /* CK_UNLOCKMUTEX is an application callback for unlocking a * mutex */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)( CK_VOID_PTR pMutex /* pointer to mutex */ ); /* CK_C_INITIALIZE_ARGS provides the optional arguments to * C_Initialize */ typedef struct CK_C_INITIALIZE_ARGS { CK_CREATEMUTEX CreateMutex; CK_DESTROYMUTEX DestroyMutex; CK_LOCKMUTEX LockMutex; CK_UNLOCKMUTEX UnlockMutex; CK_FLAGS flags; CK_VOID_PTR pReserved; } CK_C_INITIALIZE_ARGS; /* flags: bit flags that provide capabilities of the slot * Bit Flag Mask Meaning */ #define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001 #define CKF_OS_LOCKING_OK 0x00000002 typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; /* additional flags for parameters to functions */ /* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ #define CKF_DONT_BLOCK 1 /* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message * Generation Function (MGF) applied to a message block when * formatting a message block for the PKCS #1 OAEP encryption * scheme. */ typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR; /* The following MGFs are defined */ #define CKG_MGF1_SHA1 0x00000001 /* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source * of the encoding parameter when formatting a message block * for the PKCS #1 OAEP encryption scheme. */ typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; /* The following encoding parameter sources are defined */ #define CKZ_DATA_SPECIFIED 0x00000001 /* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10. * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the * CKM_RSA_PKCS_OAEP mechanism. */ typedef struct CK_RSA_PKCS_OAEP_PARAMS { CK_MECHANISM_TYPE hashAlg; CK_RSA_PKCS_MGF_TYPE mgf; CK_RSA_PKCS_OAEP_SOURCE_TYPE source; CK_VOID_PTR pSourceData; CK_ULONG ulSourceDataLen; } CK_RSA_PKCS_OAEP_PARAMS; typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; /* CK_RSA_PKCS_PSS_PARAMS is new for v2.11. * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the * CKM_RSA_PKCS_PSS mechanism(s). */ typedef struct CK_RSA_PKCS_PSS_PARAMS { CK_MECHANISM_TYPE hashAlg; CK_RSA_PKCS_MGF_TYPE mgf; CK_ULONG sLen; } CK_RSA_PKCS_PSS_PARAMS; /* CK_KEA_DERIVE_PARAMS provides the parameters to the * CKM_KEA_DERIVE mechanism */ /* CK_KEA_DERIVE_PARAMS is new for v2.0 */ typedef struct CK_KEA_DERIVE_PARAMS { CK_BBOOL isSender; CK_ULONG ulRandomLen; CK_BYTE_PTR pRandomA; CK_BYTE_PTR pRandomB; CK_ULONG ulPublicDataLen; CK_BYTE_PTR pPublicData; } CK_KEA_DERIVE_PARAMS; typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR; /* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just * holds the effective keysize */ typedef CK_ULONG CK_RC2_PARAMS; typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR; /* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC * mechanism */ typedef struct CK_RC2_CBC_PARAMS { /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for * v2.0 */ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ CK_BYTE iv[8]; /* IV for CBC mode */ } CK_RC2_CBC_PARAMS; typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; /* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the * CKM_RC2_MAC_GENERAL mechanism */ /* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */ typedef struct CK_RC2_MAC_GENERAL_PARAMS { CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ CK_ULONG ulMacLength; /* Length of MAC in bytes */ } CK_RC2_MAC_GENERAL_PARAMS; typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \ CK_RC2_MAC_GENERAL_PARAMS_PTR; /* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and * CKM_RC5_MAC mechanisms */ /* CK_RC5_PARAMS is new for v2.0 */ typedef struct CK_RC5_PARAMS { CK_ULONG ulWordsize; /* wordsize in bits */ CK_ULONG ulRounds; /* number of rounds */ } CK_RC5_PARAMS; typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; /* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC * mechanism */ /* CK_RC5_CBC_PARAMS is new for v2.0 */ typedef struct CK_RC5_CBC_PARAMS { CK_ULONG ulWordsize; /* wordsize in bits */ CK_ULONG ulRounds; /* number of rounds */ CK_BYTE_PTR pIv; /* pointer to IV */ CK_ULONG ulIvLen; /* length of IV in bytes */ } CK_RC5_CBC_PARAMS; typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; /* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the * CKM_RC5_MAC_GENERAL mechanism */ /* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */ typedef struct CK_RC5_MAC_GENERAL_PARAMS { CK_ULONG ulWordsize; /* wordsize in bits */ CK_ULONG ulRounds; /* number of rounds */ CK_ULONG ulMacLength; /* Length of MAC in bytes */ } CK_RC5_MAC_GENERAL_PARAMS; typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \ CK_RC5_MAC_GENERAL_PARAMS_PTR; /* CK_MAC_GENERAL_PARAMS provides the parameters to most block * ciphers' MAC_GENERAL mechanisms. Its value is the length of * the MAC */ /* CK_MAC_GENERAL_PARAMS is new for v2.0 */ typedef CK_ULONG CK_MAC_GENERAL_PARAMS; typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; /* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ /* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */ typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS { CK_ULONG ulPasswordLen; CK_BYTE_PTR pPassword; CK_ULONG ulPublicDataLen; CK_BYTE_PTR pPublicData; CK_ULONG ulPAndGLen; CK_ULONG ulQLen; CK_ULONG ulRandomLen; CK_BYTE_PTR pRandomA; CK_BYTE_PTR pPrimeP; CK_BYTE_PTR pBaseG; CK_BYTE_PTR pSubprimeQ; } CK_SKIPJACK_PRIVATE_WRAP_PARAMS; typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \ CK_SKIPJACK_PRIVATE_WRAP_PTR; /* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the * CKM_SKIPJACK_RELAYX mechanism */ /* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */ typedef struct CK_SKIPJACK_RELAYX_PARAMS { CK_ULONG ulOldWrappedXLen; CK_BYTE_PTR pOldWrappedX; CK_ULONG ulOldPasswordLen; CK_BYTE_PTR pOldPassword; CK_ULONG ulOldPublicDataLen; CK_BYTE_PTR pOldPublicData; CK_ULONG ulOldRandomLen; CK_BYTE_PTR pOldRandomA; CK_ULONG ulNewPasswordLen; CK_BYTE_PTR pNewPassword; CK_ULONG ulNewPublicDataLen; CK_BYTE_PTR pNewPublicData; CK_ULONG ulNewRandomLen; CK_BYTE_PTR pNewRandomA; } CK_SKIPJACK_RELAYX_PARAMS; typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ CK_SKIPJACK_RELAYX_PARAMS_PTR; typedef struct CK_PBE_PARAMS { CK_BYTE_PTR pInitVector; CK_UTF8CHAR_PTR pPassword; CK_ULONG ulPasswordLen; CK_BYTE_PTR pSalt; CK_ULONG ulSaltLen; CK_ULONG ulIteration; } CK_PBE_PARAMS; typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; /* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the * CKM_KEY_WRAP_SET_OAEP mechanism */ /* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */ typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS { CK_BYTE bBC; /* block contents byte */ CK_BYTE_PTR pX; /* extra data */ CK_ULONG ulXLen; /* length of extra data in bytes */ } CK_KEY_WRAP_SET_OAEP_PARAMS; typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR; typedef struct CK_SSL3_RANDOM_DATA { CK_BYTE_PTR pClientRandom; CK_ULONG ulClientRandomLen; CK_BYTE_PTR pServerRandom; CK_ULONG ulServerRandomLen; } CK_SSL3_RANDOM_DATA; typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS { CK_SSL3_RANDOM_DATA RandomInfo; CK_VERSION_PTR pVersion; } CK_SSL3_MASTER_KEY_DERIVE_PARAMS; typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; typedef struct CK_SSL3_KEY_MAT_OUT { CK_OBJECT_HANDLE hClientMacSecret; CK_OBJECT_HANDLE hServerMacSecret; CK_OBJECT_HANDLE hClientKey; CK_OBJECT_HANDLE hServerKey; CK_BYTE_PTR pIVClient; CK_BYTE_PTR pIVServer; } CK_SSL3_KEY_MAT_OUT; typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR; typedef struct CK_SSL3_KEY_MAT_PARAMS { CK_ULONG ulMacSizeInBits; CK_ULONG ulKeySizeInBits; CK_ULONG ulIVSizeInBits; CK_BBOOL bIsExport; CK_SSL3_RANDOM_DATA RandomInfo; CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; } CK_SSL3_KEY_MAT_PARAMS; typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; typedef struct CK_KEY_DERIVATION_STRING_DATA { CK_BYTE_PTR pData; CK_ULONG ulLen; } CK_KEY_DERIVATION_STRING_DATA; typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \ CK_KEY_DERIVATION_STRING_DATA_PTR; /* The CK_EXTRACT_PARAMS is used for the * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit * of the base key should be used as the first bit of the * derived key */ /* CK_EXTRACT_PARAMS is new for v2.0 */ typedef CK_ULONG CK_EXTRACT_PARAMS; typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; /* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10. * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to * indicate the Pseudo-Random Function (PRF) used to generate * key bits using PKCS #5 PBKDF2. */ typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; /* The following PRFs are defined in PKCS #5 v2.0. */ #define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001 /* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10. * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the * source of the salt value when deriving a key using PKCS #5 * PBKDF2. */ typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; /* The following salt value sources are defined in PKCS #5 v2.0. */ #define CKZ_SALT_SPECIFIED 0x00000001 /* CK_PKCS5_PBKD2_PARAMS is new for v2.10. * CK_PKCS5_PBKD2_PARAMS is a structure that provides the * parameters to the CKM_PKCS5_PBKD2 mechanism. */ typedef struct CK_PKCS5_PBKD2_PARAMS { CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; CK_VOID_PTR pSaltSourceData; CK_ULONG ulSaltSourceDataLen; CK_ULONG iterations; CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; CK_VOID_PTR pPrfData; CK_ULONG ulPrfDataLen; CK_UTF8CHAR_PTR pPassword; CK_ULONG_PTR ulPasswordLen; } CK_PKCS5_PBKD2_PARAMS; typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; #endif libdigidoc-3.10.5/libdigidoc/pkcs11/unix.h0000664000372000037200000000060613560273131017625 0ustar travistravis #ifndef UNIX_H #define UNIX_H #define CK_PTR * #define CK_DEFINE_FUNCTION(returnType, name) \ returnType name #define CK_DECLARE_FUNCTION(returnType, name) \ returnType name #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ returnType (* name) #define CK_CALLBACK_FUNCTION(returnType, name) \ returnType (* name) #ifndef NULL_PTR #define NULL_PTR 0 #endif #endif libdigidoc-3.10.5/libdigidoc/pkcs11/pkcs11.h0000664000372000037200000002064113560273131017745 0ustar travistravis/* pkcs11.h include file for PKCS #11. 2001 June 25 */ #ifndef _PKCS11_H_ #define _PKCS11_H_ 1 #ifdef __cplusplus extern "C" { #endif /* Before including this file (pkcs11.h) (or pkcs11t.h by * itself), 6 platform-specific macros must be defined. These * macros are described below, and typical definitions for them * are also given. Be advised that these definitions can depend * on both the platform and the compiler used (and possibly also * on whether a Cryptoki library is linked statically or * dynamically). * * In addition to defining these 6 macros, the packing convention * for Cryptoki structures should be set. The Cryptoki * convention on packing is that structures should be 1-byte * aligned. * * If you're using Microsoft Developer Studio 5.0 to produce * Win32 stuff, this might be done by using the following * preprocessor directive before including pkcs11.h or pkcs11t.h: * * #pragma pack(push, cryptoki, 1) * * and using the following preprocessor directive after including * pkcs11.h or pkcs11t.h: * * #pragma pack(pop, cryptoki) * * If you're using an earlier version of Microsoft Developer * Studio to produce Win16 stuff, this might be done by using * the following preprocessor directive before including * pkcs11.h or pkcs11t.h: * * #pragma pack(1) * * In a UNIX environment, you're on your own for this. You might * not need to do (or be able to do!) anything. * * * Now for the macros: * * * 1. CK_PTR: The indirection string for making a pointer to an * object. It can be used like this: * * typedef CK_BYTE CK_PTR CK_BYTE_PTR; * * If you're using Microsoft Developer Studio 5.0 to produce * Win32 stuff, it might be defined by: * * #define CK_PTR * * * If you're using an earlier version of Microsoft Developer * Studio to produce Win16 stuff, it might be defined by: * * #define CK_PTR far * * * In a typical UNIX environment, it might be defined by: * * #define CK_PTR * * * * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes * an exportable Cryptoki library function definition out of a * return type and a function name. It should be used in the * following fashion to define the exposed Cryptoki functions in * a Cryptoki library: * * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( * CK_VOID_PTR pReserved * ) * { * ... * } * * If you're using Microsoft Developer Studio 5.0 to define a * function in a Win32 Cryptoki .dll, it might be defined by: * * #define CK_DEFINE_FUNCTION(returnType, name) \ * returnType __declspec(dllexport) name * * If you're using an earlier version of Microsoft Developer * Studio to define a function in a Win16 Cryptoki .dll, it * might be defined by: * * #define CK_DEFINE_FUNCTION(returnType, name) \ * returnType __export _far _pascal name * * In a UNIX environment, it might be defined by: * * #define CK_DEFINE_FUNCTION(returnType, name) \ * returnType name * * * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes * an importable Cryptoki library function declaration out of a * return type and a function name. It should be used in the * following fashion: * * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)( * CK_VOID_PTR pReserved * ); * * If you're using Microsoft Developer Studio 5.0 to declare a * function in a Win32 Cryptoki .dll, it might be defined by: * * #define CK_DECLARE_FUNCTION(returnType, name) \ * returnType __declspec(dllimport) name * * If you're using an earlier version of Microsoft Developer * Studio to declare a function in a Win16 Cryptoki .dll, it * might be defined by: * * #define CK_DECLARE_FUNCTION(returnType, name) \ * returnType __export _far _pascal name * * In a UNIX environment, it might be defined by: * * #define CK_DECLARE_FUNCTION(returnType, name) \ * returnType name * * * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro * which makes a Cryptoki API function pointer declaration or * function pointer type declaration out of a return type and a * function name. It should be used in the following fashion: * * // Define funcPtr to be a pointer to a Cryptoki API function * // taking arguments args and returning CK_RV. * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args); * * or * * // Define funcPtrType to be the type of a pointer to a * // Cryptoki API function taking arguments args and returning * // CK_RV, and then define funcPtr to be a variable of type * // funcPtrType. * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args); * funcPtrType funcPtr; * * If you're using Microsoft Developer Studio 5.0 to access * functions in a Win32 Cryptoki .dll, in might be defined by: * * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ * returnType __declspec(dllimport) (* name) * * If you're using an earlier version of Microsoft Developer * Studio to access functions in a Win16 Cryptoki .dll, it might * be defined by: * * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ * returnType __export _far _pascal (* name) * * In a UNIX environment, it might be defined by: * * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ * returnType (* name) * * * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes * a function pointer type for an application callback out of * a return type for the callback and a name for the callback. * It should be used in the following fashion: * * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args); * * to declare a function pointer, myCallback, to a callback * which takes arguments args and returns a CK_RV. It can also * be used like this: * * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args); * myCallbackType myCallback; * * If you're using Microsoft Developer Studio 5.0 to do Win32 * Cryptoki development, it might be defined by: * * #define CK_CALLBACK_FUNCTION(returnType, name) \ * returnType (* name) * * If you're using an earlier version of Microsoft Developer * Studio to do Win16 development, it might be defined by: * * #define CK_CALLBACK_FUNCTION(returnType, name) \ * returnType _far _pascal (* name) * * In a UNIX environment, it might be defined by: * * #define CK_CALLBACK_FUNCTION(returnType, name) \ * returnType (* name) * * * 6. NULL_PTR: This macro is the value of a NULL pointer. * * In any ANSI/ISO C environment (and in many others as well), * this should best be defined by * * #ifndef NULL_PTR * #define NULL_PTR 0 * #endif */ #ifndef WIN32 #include "unix.h" #else #include "cryptoki.h" #endif /* All the various Cryptoki types and #define'd values are in the * file pkcs11t.h. */ #include "pkcs11t.h" #define __PASTE(x,y) x##y /* ============================================================== * Define the "extern" form of all the entry points. * ============================================================== */ #define CK_NEED_ARG_LIST 1 #define CK_PKCS11_FUNCTION_INFO(name) \ extern CK_DECLARE_FUNCTION(CK_RV, name) /* pkcs11f.h has all the information about the Cryptoki * function prototypes. */ #include "pkcs11f.h" #undef CK_NEED_ARG_LIST #undef CK_PKCS11_FUNCTION_INFO /* ============================================================== * Define the typedef form of all the entry points. That is, for * each Cryptoki function C_XXX, define a type CK_C_XXX which is * a pointer to that kind of function. * ============================================================== */ #define CK_NEED_ARG_LIST 1 #define CK_PKCS11_FUNCTION_INFO(name) \ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name)) /* pkcs11f.h has all the information about the Cryptoki * function prototypes. */ #include "pkcs11f.h" #undef CK_NEED_ARG_LIST #undef CK_PKCS11_FUNCTION_INFO /* ============================================================== * Define structed vector of entry points. A CK_FUNCTION_LIST * contains a CK_VERSION indicating a library's Cryptoki version * and then a whole slew of function pointers to the routines in * the library. This type was declared, but not defined, in * pkcs11t.h. * ============================================================== */ #define CK_PKCS11_FUNCTION_INFO(name) \ __PASTE(CK_,name) name; struct CK_FUNCTION_LIST { CK_VERSION version; /* Cryptoki version */ /* Pile all the function pointers into the CK_FUNCTION_LIST. */ /* pkcs11f.h has all the information about the Cryptoki * function prototypes. */ #include "pkcs11f.h" }; #undef CK_PKCS11_FUNCTION_INFO #undef __PASTE #ifdef __cplusplus } #endif #endif libdigidoc-3.10.5/libdigidoc/pkcs11/cryptoki.h0000664000372000037200000000264613560273131020514 0ustar travistravis/* cryptoki.h include file for PKCS #11. 2001 June 25 */ /* This is a sample file containing the top level include directives * for building Win32 Cryptoki libraries and applications. */ #ifndef ___CRYPTOKI_H_INC___ #define ___CRYPTOKI_H_INC___ #pragma pack(push, cryptoki, 1) /* Specifies that the function is a DLL entry point. */ #define CK_IMPORT_SPEC __declspec(dllimport) /* Define CRYPTOKI_EXPORTS during the build of cryptoki libraries. Do * not define it in applications. */ #ifdef CRYPTOKI_EXPORTS /* Specified that the function is an exported DLL entry point. */ #define CK_EXPORT_SPEC __declspec(dllexport) #else #define CK_EXPORT_SPEC CK_IMPORT_SPEC #endif /* Ensures the calling convention for Win32 builds */ #define CK_CALL_SPEC __cdecl #define CK_PTR * #define CK_DEFINE_FUNCTION(returnType, name) \ returnType CK_EXPORT_SPEC CK_CALL_SPEC name #define CK_DECLARE_FUNCTION(returnType, name) \ returnType CK_EXPORT_SPEC CK_CALL_SPEC name #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name) #define CK_CALLBACK_FUNCTION(returnType, name) \ returnType (CK_CALL_SPEC CK_PTR name) #ifndef NULL_PTR #define NULL_PTR 0 #endif #include "pkcs11.h" #pragma pack(pop, cryptoki) #endif /* ___CRYPTOKI_H_INC___ */ libdigidoc-3.10.5/libdigidoc/DigiDocLib.h0000664000372000037200000002162713560273131017477 0ustar travistravis#ifndef __DIGI_DOC_LIB_H__ #define __DIGI_DOC_LIB_H__ //================================================== // FILE: DigiDocLib.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for creating // and reading signed documents. // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details.ode // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 10.02.2004 Integrated // 02.01.2004 Veiko Sinivee // Added support for format 1.3 // 29.10.2003 Aare Amenberg // Added some function headers // (needed for compiling COM) // 1.0 09.04.2002 Veiko Sinivee // Supports XML format (Type: SK-XML-1.0) //================================================== #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include //==========< data structures >==================== // supported format and version combination typedef struct FormatAndVer_st { char* szFormat; char* szVersion; } FormatAndVer; //==========< admin functions >==================== // returns the library name EXP_OPTION const char* getLibName(); // returns the library version EXP_OPTION const char* getLibVersion(); // returns an array of supported formats terminated by NULL EXP_OPTION const char** getSupportedFormats(); // returns an array of supported formats and versions terminated by NULL EXP_OPTION FormatAndVer* getSupportedFormatsAndVersions(); // returns the GUI version EXP_OPTION const char* getGUIVersion(); // sets the GUI version EXP_OPTION void setGUIVersion(const char* szVer); // initializes error library EXP_OPTION void initDigiDocLib(); // cleanup of error library EXP_OPTION void finalizeDigiDocLib(); // trim leading and trailing whitespace EXP_OPTION char* trim(char* src); // Sets a string element of a struct to a new value EXP_OPTION int setString(char** dest, const char* value, int valLen); EXP_OPTION int checkFileExists(const char* szFileName); int ddocPullUrl(const char* url, DigiDocMemBuf* pSendData, DigiDocMemBuf* pRecvData, const char* proxyHost, const char* proxyPort); // Cheks a combination of format and version for validity int ddocCheckFormatAndVer(const char* format, const char* version); //-------------------------------------------------- // Converts timestamp (time_t) value to a struct // tm value. Caller must provide address of tm struct. // This function is used because loacltime() is not // thread-safe and win32 has no equvalent of localtime_r(). // pTime - time_t value address // pTmStruct - struct tm address // bLocal - 1=localtime_r, 0=gmtime_r // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocLocalTime(time_t* pTime, struct tm* pTmStruct, int bLocal); EXP_OPTION int getTempFileName(char* szFileName, int len); //==========< general crypto fucntions >============ // calculates input files digest. // supports only SHA1 EXP_OPTION int calculateFileDigest(const char* szFileName, int nDigestType, byte* pDigestBuf, int* nDigestLen, long* lFileLen); // calculate file size EXP_OPTION int calculateFileSize(const char* szFileName, long* lFileLen); // calculates files RSA+SHA1 signature EXP_OPTION int calculateFileSignature(const char* szFileName, int nDigestType, byte* pSigBuf, int* nSigLen, const char *keyfile, const char* passwd); // sign some arbitrary daya EXP_OPTION int signData(const byte* data, int dlen, byte* pSigBuf, int* nSigLen, int nDigestType, const char *keyfile, const char* passwd); // calculate digest over some arbitrary data EXP_OPTION int calculateDigest(const byte* data, int nDataLen, int nDigestType, byte* pDigestBuf, int* nDigestLen); //-------------------------------------------------- // Prepares a new signature for signing and calculates // the final hash value to sign. // pSigDoc - signed document object // ppSigInfo - pointer for address of newly allocated signature // manifest - manifest or role // city - signers address , city // state - signers address , state or province // zip - signers address , postal code // country - signers address , country name // id - id for new signature. Optional, use NULL for default // return returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocPrepareSignature(SignedDoc* pSigDoc, SignatureInfo** ppSigInfo, const char* manifest, const char* city, const char* state, const char* zip, const char* country, X509* pCert, const char* id); //-------------------------------------------------- // Returns the hash to be signed with or without ASN1 // prefix and with or without base64 encoding // pSigInfo - signature address // pBuf - buffer for hash value with or without prefix // pBufLen - pointer to buffer length // enc - return 0=unencoded, 1=base64, 2=hex // bWithAsn1Prefix - return with or without ASN1 prefix 1/0 // return returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocGetSignedHash(SignatureInfo* pSigInfo, char* pBuf, int* pBufLen, int enc, int bWithAsn1Prefix); //==========< XML generating functions >================= // thse functions generate certain XML form info, that // is used as input data for either signing or digesting // creates XML block (actually signed info) EXP_OPTION char* createXMLSignedInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo); // creates XML mime type block for signing EXP_OPTION int createMimeType(char* buf, const char* mime, const char* sigId, const char* docId); //==========< memory mgmt functions >================= // Get the filename part of full file name EXP_OPTION const char* getSimpleFileName(const char* szFileName); // Get the absolute filename with path EXP_OPTION int getFullFileName(const char* szFileName, char* szDest, int len); // Get the path part of full file name EXP_OPTION int getFileNamePath(const char* szFileName, char* szPath, int len); //------------------------ ?? // Sets the signatures certificate and calculates EXP_OPTION int setSignatureCertFile(SignatureInfo* pSigInfo, const char* certFile); // Sets the signatures certificate and calculates it's digest EXP_OPTION int setSignatureCert(SignatureInfo* pSigInfo, X509* cert); // Sets the signature value EXP_OPTION int setSignatureValue(SignatureInfo* pSigInfo, byte* szSignature, int sigLen); // Sets the signature value from a file that contains // the base64 encoded signature value EXP_OPTION int setSignatureValueFromFile(SignatureInfo* pSigInfo, char* szSigFile); //================< certficate info functions> ================================= // Decodes a signature value void decodeSignatureValue(const char* b64val, int b64len, char* value, int* vlen); // Returns the user signatures certificate data EXP_OPTION X509* getSignCertData(const SignatureInfo* pSignInfo); // Returns the notary signatures certificate data //EXP_OPTION X509* getNotCertData(const NotaryInfo* pNotInfo); //================< deprecated functions> ================================= // these functions are deprecated. Use the replacements in DigiDocCert.h // these functions will be removed in future releases! #ifdef WITH_DEPRECATED_FUNCTIONS // get signers id-code // USE: ddocCertGetSubjectPerCode(getSignCertData(pSignInfo), pMemBuf); EXP_OPTION int getSignerCode(const SignatureInfo* pSigInfo, char* buf); // get signers first name // USE: ddocCertGetSubjectFirstName(getSignCertData(pSignInfo), pMemBuf); EXP_OPTION int getSignerFirstName(const SignatureInfo* pSigInfo, char* buf); // get signers last name // USE: ddocCertGetSubjectLastName(getSignCertData(pSignInfo), pMemBuf); EXP_OPTION int getSignerLastName(const SignatureInfo* pSigInfo, char* buf); // get the whole signers CN in desired charset // USE: ddocCertGetSubjectCN(getSignCertData(pSignInfo), pMemBuf); EXP_OPTION int getSignerCN(const SignatureInfo* pSigInfo, char* buf, int bUTF8); #endif // WITH_DEPRECATED_FUNCTIONS //================================================================================== void CorrectCharacters(char *psText); #ifdef __cplusplus } #endif #endif // __DIGI_DOC_LIB_H__ libdigidoc-3.10.5/libdigidoc/DigiDocCsp.h0000664000372000037200000001241513560273131017511 0ustar travistravis#ifndef __DIGIDOCCSP_H__ #define __DIGIDOCCSP_H__ //================================================== // FILE: DigDocCsp.h // PROJECT: Digi Doc // DESCRIPTION: CSP Functions // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 1.0 09.05.2002 Veiko Sinivee //================================================== #ifdef __cplusplus extern "C" { #endif #define EST_EID_CSP "EstEID Card CSP" typedef struct CSProvider_st { char* CSPName; int rsa_full; // if FALSE RSA_SIG will be used int at_sig; //// if FALSE AT_KEYEXCHANGE will be used } CSProvider; // general structure for a list of certificates typedef struct CertItem_st { X509* pCert; struct CertItem_st* nextItem; } CertItem; typedef struct CertSearchStore_st { int searchType; char* storeName; // default is "My" long certSerial; int numberOfSubDNCriterias; char** subDNCriterias; int numberOfIssDNCriterias; char** issDNCriterias; void* publicKeyInfo; } CertSearchStore; typedef struct CertSearch_st { int searchType; char* x509FileName; char* keyFileName; char* pkcs12FileName; char * pswd; CertSearchStore* certSearchStore; } CertSearch; //===================================================================== // Hashes and signes data with EstId card, returns also cert // which can be used in order to verify signature // IN dataToBeSigned - source data buffer // IN dataLen - how many bytes will be read from source buffer // OUT cert - cert buffer( corresponding private key was used to sign.), migth be NULL if this parameter is not needed. // OUT certLen - cert length in buffer, migth be NULL if cert parameter is not needed. // OUT keyBlob - public key's buffer, migth be NULL if this parameter is not needed. // OUT keyBlobLen - public key's length in buffer, migth be NULL if keyBlob parameter is not needed. // OUT hash - hash buffer, migth be NULL if this parameter is not needed. // OUT hashLen - hash length in buffer, migth be NULL if hash parameter is not needed. // OUT sign - output data buffer for hashed and signed data // OUT sigLen - data length in output buffer //===================================================================== int GetSignParametersWithEstIdCSP(byte * dataToBeSigned,unsigned long dataLen, X509 **x509, int *needCert, byte *keyBlob, unsigned long *keyBlobLen, byte *hash, unsigned long *hashLen, byte *sign,unsigned long *sigLen); //EXP_OPTION int calculateSigInfoSignatureWithEstID(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, // int slot, const char* passwd); //Added parameter iByKeyContainer by A.Amenberg 06062003 EXP_OPTION int calculateSigInfoSignatureWithCSPEstID(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, int iByKeyContainer, const char* szPin); EXP_OPTION X509 * findIssuerCertificatefromMsStore(X509 *x509); EXP_OPTION CertSearchStore* CertSearchStore_new(); EXP_OPTION void CertSearchStore_free(CertSearchStore* certSearchStore); EXP_OPTION CertSearch* CertSearch_new(); EXP_OPTION void CertSearch_free(CertSearch* certSearch); EXP_OPTION void CertList_free(CertItem* pListStart); EXP_OPTION void CertSearch_setX509FileName(CertSearch* certSearch, const char* str); EXP_OPTION void CertSearch_setKeyFileName(CertSearch* certSearch, const char* str); EXP_OPTION void CertSearch_setPkcs12FileName(CertSearch* certSearch, const char* str); EXP_OPTION void CertSearch_setPasswd(CertSearch* certSearch, const char* str); // EXP_OPTION CSProvider * getCurrentCSProvider(BOOL tryToFindIfMissing); EXP_OPTION X509* findCertificate(const CertSearch * cS); EXP_OPTION int findAllCertificates(const CertSearchStore *sS, X509 ***certsArray, int *numberOfCerts); EXP_OPTION int Digi_readCertificateByPKCS12OnlyCertHandle(const char *pkcs12file, const char * passwd, X509 **x509); EXP_OPTION int Digi_getConfirmationWithCertSearch(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, char* pkcs12File, char* password, char* notaryURL, char* proxyHost, char* proxyPort); EXP_OPTION int Digi_setNotaryCertificate(NotaryInfo* pNotary, X509* notCert); EXP_OPTION int Digi_verifyNotaryInfoWithCertSearch(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo); // verifies this one signature EXP_OPTION int Digi_verifySignatureInfo(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, const char* szDataFile); // verifies the whole document (returns on first err) EXP_OPTION int Digi_verifySigDoc(const SignedDoc* pSigDoc, const char* szDataFile); EXP_OPTION int Digi_verifySigDocWithCertSearch(const SignedDoc* pSigDoc, const char* szDataFile); #ifdef __cplusplus } #endif #endiflibdigidoc-3.10.5/libdigidoc/DigiDocService.c0000664000372000037200000003535213560273131020364 0ustar travistravis//================================================== // FILE: DigiDocService.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for DigiDocService access // AUTHOR: Veiko Sinivee, Sunset Software O //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //================================================== // config data comes from there #include #include #include #include #include #include #include #include #include #include #include #include char* g_xmlHdr1 = "\n"; char* g_xmlEnd1 = ""; char* g_xmlHdr2 = "\n"; char* g_xmlEnd2 = ""; char* g_ddsUrl = "https://digidocservice.sk.ee/DigiDocService"; int ddocXmlElem(DigiDocMemBuf* pMbuf, const char* szElem, const char* szValue) { int err = ERR_OK; if(szValue) { err = ddocGen_startElem(pMbuf, szElem); if(!err) err = ddocMemAppendData(pMbuf, szValue, -1); if(!err) err = ddocGen_endElem(pMbuf, szElem); } return err; } int findXmlElemValue(DigiDocMemBuf* pMbMsg, const char* szTag, DigiDocMemBuf* pMbValue) { char *p1, *p2; char tag[50]; p1 = (char*)pMbMsg->pMem; if(p1) { snprintf(tag, sizeof(tag), "<%s", szTag); p1 = strstr(p1, tag); if(p1) { while(*p1 && *p1 != '>') p1++; if(*p1 && *p1 == '>') p1++; snprintf(tag, sizeof(tag), " (long)p1) { ddocMemAssignData(pMbValue, p1, (int)(p2 - p1)); return 0; } } } return -1; } //-------------------------------------------------- // Signs the document and gets return status back // pSigDoc - signed document object // szIdCode - personal id code // szPhoneNo - users phone number // szLang - language code // manifest - manifest or role // city - signers address , city // state - signers address , state or province // zip - signers address , postal code // country - signers address , country name // pSesscode - pointer to long int buffer for returning session code // szChallenge - buffer for returning challenge code (char 4) // nChalLen - length of challenge buffer // return error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddsSign(SignedDoc* pSigDoc, const char* szIdCode, const char* szPhoneNo, const char* szLang, const char* szServiceName, const char* manifest, const char* city, const char* state, const char* zip, const char* country, char* url, char* proxyHost, char* proxyPort, long* pSesscode, char* szChallenge, int nChalLen) { int err = ERR_OK, i, l1; char *p1 = 0; DataFile *pDf = 0; DigiDocMemBuf mbuf1, mbuf2, mbuf3; char buf1[40]; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; mbuf3.pMem = 0; mbuf3.nLen = 0; ddocDebug(3, "ddsSign", "Creating M-ID signature using: %s", szPhoneNo); RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(szIdCode); RETURN_IF_NULL_PARAM(country); RETURN_IF_NULL_PARAM(szPhoneNo); //RETURN_IF_NULL_PARAM(url); if(url == NULL) url = g_ddsUrl; RETURN_IF_NULL_PARAM(pSesscode); RETURN_IF_NULL_PARAM(szChallenge); ddocMemAssignData(&mbuf2, g_xmlHdr1, -1); // create xml request err = ddocXmlElem(&mbuf2, "IDCode", szIdCode); err = ddocXmlElem(&mbuf2, "SignersCountry", country); err = ddocXmlElem(&mbuf2, "PhoneNo", szPhoneNo); err = ddocXmlElem(&mbuf2, "Language", szLang); err = ddocXmlElem(&mbuf2, "ServiceName", szServiceName); err = ddocXmlElem(&mbuf2, "Role", manifest); err = ddocXmlElem(&mbuf2, "City", city); err = ddocXmlElem(&mbuf2, "StateOrProvince", state); err = ddocXmlElem(&mbuf2, "PostalCode", zip); err = ddocXmlElem(&mbuf2, "CountryName", country); err = ddocGen_startElem(&mbuf2, "DataFiles"); for(i = 0; i < getCountOfDataFiles(pSigDoc); i++) { pDf = getDataFile(pSigDoc, i); err = ddocGen_startElem(&mbuf2, "DataFileDigest"); err = ddocXmlElem(&mbuf2, "Id", pDf->szId); err = ddocXmlElem(&mbuf2, "DigestType", pDf->szDigestType); l1 = sizeof(buf1); memset(buf1, 0, l1); encode((const byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, (byte*)buf1, &l1); err = ddocXmlElem(&mbuf2, "DigestValue", buf1); err = ddocGen_endElem(&mbuf2, "DataFileDigest"); } err = ddocGen_endElem(&mbuf2, "DataFiles"); err = ddocXmlElem(&mbuf2, "Format", pSigDoc->szFormat); err = ddocXmlElem(&mbuf2, "Version", pSigDoc->szFormatVer); sprintf(buf1, "S%d", getNextSignatureId(pSigDoc)); err = ddocXmlElem(&mbuf2, "SignatureID", buf1); err = ddocXmlElem(&mbuf2, "MessagingMode", "asynchClientServer"); err = ddocXmlElem(&mbuf2, "AsyncConfiguration", "0"); ddocMemAppendData(&mbuf2, g_xmlEnd1, -1); // create http req ddocMemAssignData(&mbuf1, "POST ", -1); if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) { ddocMemAppendData(&mbuf1, url, -1); } else { p1 = strstr(url, "://"); if(p1) p1 += 3; if(p1) p1 = strchr(p1, '/'); if(p1) ddocMemAppendData(&mbuf1, p1, -1); else ddocMemAppendData(&mbuf1, "/", -1); } ddocMemAppendData(&mbuf1, " HTTP/1.0\r\n", -1); ddocMemAppendData(&mbuf1, "User-Agent: DigiDocLib\r\n", -1); ddocMemAppendData(&mbuf1, "Content-Type: text/xml; charset=utf-8\r\n", -1); snprintf(buf1, sizeof(buf1), "Content-Length: %d\r\n", (int)mbuf2.nLen); ddocMemAppendData(&mbuf1, buf1, -1); ddocMemAppendData(&mbuf1, "Connection: Close\r\n", -1); if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) // if we use proxy then send also Proxy-Connection ddocMemAppendData(&mbuf1, "Proxy-Connection: Close\r\n", -1); ddocMemAppendData(&mbuf1, "SOAPAction: \"\"\r\n", -1); ddocMemAppendData(&mbuf1, "\r\n", -1); ddocMemAppendData(&mbuf1, mbuf2.pMem, mbuf2.nLen); ddocDebug(4, "ddsSign", "Send to host: %s request len: %d", url, mbuf1.nLen); ddocDebug(4, "ddsSign", "Sending: \n---\n%s\n---\n", mbuf1.pMem); ddocMemBuf_free(&mbuf2); err = ddocPullUrl(url, &mbuf1, &mbuf2, proxyHost, proxyPort); ddocDebug(4, "ddsSign", "Recevied len: %d RC: %d", mbuf2.nLen, err); //ddocDebug(3, "ddsSign", "Received: \n---\n%s\n---\n", mbuf2.pMem); if(!err && ((l1 = ddocGetHttpResponseCode(&mbuf2)) == 200)) { err = ddocGetHttpPayload(&mbuf2, &mbuf3); ddocMemBuf_free(&mbuf2); ddocDebug(4, "ddsSign", "SOAP: \n---\n%s\n---\n", mbuf3.pMem); err = findXmlElemValue(&mbuf3, "Sesscode", &mbuf2); if(!err) (*pSesscode) = atol((char*)mbuf2.pMem); //ddocDebug(3, "ddsSign", "Sesscode: %ld", (*pSesscode)); ddocMemBuf_free(&mbuf2); err = findXmlElemValue(&mbuf3, "ChallengeID", &mbuf2); //ddocDebug(3, "ddsSign", "Challenge id %s", mbuf2.pMem); if(!err && mbuf2.pMem && mbuf2.nLen) { memset(szChallenge, 0, nChalLen); strncpy(szChallenge, mbuf2.pMem, mbuf2.nLen); } ddocDebug(3, "ddsSign", "Sesscode: %ld Challenge id %s RC: %d", (*pSesscode), szChallenge, err); ddocMemBuf_free(&mbuf2); } ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); RETURN_IF_NOT(err == ERR_OK, err); return err; } //------------------------------------------ // Gets DigiDocService session status and returns status code // If session is ready then signature will be returned // pSigDoc - signed document object to be modified // lSesscode - session code // url - dds service url // proxyHost - proxy hostname // proxyPort -proxy port // pStatus - buffer for returning status // pMBufSig - buffer for returning signature // returns DigiDocService session status code // deprecated use ddsGetStatus(pSigDoc, lSesscode, url, proxyHost, proxyPort, pStatus, szFileName) //------------------------------------------ DIGIDOC_DEPRECATED EXP_OPTION int ddsGetStatus(SignedDoc* pSigDoc, long lSesscode, char* url, char* proxyHost, char* proxyPort, int* pStatus) { return ddsGetStatusWithFile(pSigDoc, lSesscode, url, proxyHost, proxyPort, pStatus, NULL); } //------------------------------------------ // Gets DigiDocService session status and returns status code // If session is ready then signature will be returned // pSigDoc - signed document object to be modified // lSesscode - session code // url - dds service url // proxyHost - proxy hostname // proxyPort -proxy port // pStatus - buffer for returning status // szFileName - ddoc filename to add signature from dds (optional) // pMBufSig - buffer for returning signature // returns DigiDocService session status code //------------------------------------------ EXP_OPTION int ddsGetStatusWithFile(SignedDoc* pSigDoc, long lSesscode, char* url, char* proxyHost, char* proxyPort, int* pStatus, const char* szFileName) { int err = ERR_OK, l1; SignatureInfo *pSigInfo = 0; DigiDocMemBuf mbuf1, mbuf2, mbuf3; char buf1[40], *p1; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; mbuf3.pMem = 0; mbuf3.nLen = 0; ddocDebug(3, "ddsGetStatus", "Get Status for sess: %ld", lSesscode); RETURN_IF_NULL_PARAM(pSigDoc); //RETURN_IF_NULL_PARAM(url); if(url == NULL) url = g_ddsUrl; RETURN_IF_NULL_PARAM(pStatus); *pStatus = 0; ddocMemAssignData(&mbuf2, g_xmlHdr2, -1); // create xml request sprintf(buf1, "%ld", lSesscode); err = ddocXmlElem(&mbuf2, "Sesscode", buf1); err = ddocXmlElem(&mbuf2, "WaitSignature", "false"); ddocMemAppendData(&mbuf2, g_xmlEnd2, -1); // create http req ddocMemAssignData(&mbuf1, "POST ", -1); if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) { ddocMemAppendData(&mbuf1, url, -1); } else { p1 = strstr(url, "://"); if(p1) p1 += 3; if(p1) p1 = strchr(p1, '/'); if(p1) ddocMemAppendData(&mbuf1, p1, -1); else ddocMemAppendData(&mbuf1, "/", -1); } ddocMemAppendData(&mbuf1, " HTTP/1.0\r\n", -1); ddocMemAppendData(&mbuf1, "User-Agent: DigiDocLib\r\n", -1); ddocMemAppendData(&mbuf1, "Content-Type: text/xml; charset=utf-8\r\n", -1); snprintf(buf1, sizeof(buf1), "Content-Length: %d\r\n", (int)mbuf2.nLen); ddocMemAppendData(&mbuf1, buf1, -1); ddocMemAppendData(&mbuf1, "Connection: Close\r\n", -1); if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) // if we use proxy then send also Proxy-Connection ddocMemAppendData(&mbuf1, "Proxy-Connection: Close\r\n", -1); ddocMemAppendData(&mbuf1, "SOAPAction: \"\"\r\n", -1); ddocMemAppendData(&mbuf1, "\r\n", -1); ddocMemAppendData(&mbuf1, mbuf2.pMem, mbuf2.nLen); ddocDebug(4, "ddsGetStatus", "Send to host: %s request len: %d", url, mbuf1.nLen); ddocDebug(4, "ddsGetStatus", "Sending: \n---\n%s\n---\n", mbuf1.pMem); ddocMemBuf_free(&mbuf2); err = ddocPullUrl(url, &mbuf1, &mbuf2, proxyHost, proxyPort); ddocDebug(4, "ddsGetStatus", "Recevied len: %d RC: %d", mbuf2.nLen, err); //ddocDebug(3, "ddsSign", "Received: \n---\n%s\n---\n", mbuf2.pMem); if(!err && ((l1 = ddocGetHttpResponseCode(&mbuf2)) == 200)) { err = ddocGetHttpPayload(&mbuf2, &mbuf3); ddocMemBuf_free(&mbuf2); ddocDebug(4, "ddsGetStatus", "SOAP: \n---\n%s\n---\n", mbuf3.pMem); err = findXmlElemValue(&mbuf3, "Status", &mbuf2); if(!err && mbuf2.pMem) { if(!strcmp((char*)mbuf2.pMem, "OUTSTANDING_TRANSACTION")) (*pStatus) = STATUS_OUTSTANDING_TRANSACTION; if(!strcmp((char*)mbuf2.pMem, "SIGNATURE")) (*pStatus) = STATUS_SIGNATURE; if(!strcmp((char*)mbuf2.pMem, "ERROR")) (*pStatus) = STATUS_ERROR; } ddocDebug(3, "ddsGetStatus", "Sesscode: %ld Status: %d RC: %d", lSesscode, (*pStatus), err); ddocMemBuf_free(&mbuf2); if((*pStatus) == STATUS_SIGNATURE) { err = findXmlElemValue(&mbuf3, "Signature", &mbuf2); ddocDebug(4, "ddsGetStatus", "Sig-esacped: \n---\n%s\n---\n", mbuf2.pMem); p1 = escape2xmlsym((char*)mbuf2.pMem); ddocDebug(4, "ddsGetStatus", "Signature: \n---\n%s\n---\n", p1); err = ddocAddSignatureFromMemory(pSigDoc, szFileName, (const void*)p1, strlen(p1)); /*sprintf(buf1, "S%d", getNextSignatureId(pSigDoc)); SignatureInfo_new(&pSigInfo, pSigDoc, buf1); ddocMemAssignData(&(pSigInfo->mbufOrigContent), p1, -1);*/ free(p1); } } ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); RETURN_IF_NOT(err == ERR_OK, err); return err; } libdigidoc-3.10.5/libdigidoc/DigiDocEncSAXParser.c0000664000372000037200000012420613560273131021217 0ustar travistravis//================================================== // FILE: DigiDocEncSAXParser.c // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDocEnc XML SAX parsing // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 11.10.2004 Veiko Sinivee // Creation //================================================== #ifdef WIN32 #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* only for xmlNewInputFromFile() */ #if OPENSSL_VERSION_NUMBER < 0x10010000L static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new() { return (EVP_ENCODE_CTX*)OPENSSL_malloc(sizeof(EVP_ENCODE_CTX)); } static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) { OPENSSL_free(ctx); } #endif //===============< SAX handlers >============================== /* * Working area for XML parsing with SAX */ typedef struct DEncParse_st { DEncEncryptedData* pEncData; // document file to be filled with data int errcode; ElementEntry dencStack; // stack used for keeping the current parsing position DigiDocMemBuf mbufContent; // used for collecting element content int bCollectMode; // flag to switch collection of content on and off char errmsg[100]; } DEncParse; //-------------------------------------------------- // Cleans up the memory that might habe been allocated // during parsing process // pctx - SAX parser context //-------------------------------------------------- void dencSaxCleanup(DEncParse* pctx) { ddocMemBuf_free(&(pctx->mbufContent)); memset(pctx, 0, sizeof(DEncParse)); } //-------------------------------------------------- // Handles the start event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleStartEncryptedData(DEncParse* pctx, const xmlChar** atts) { int i, err = ERR_OK; char *id = NULL, *type = NULL, *mime = NULL, *xmlns = NULL; // check the atributes for(i = 0; atts && atts[i] && atts[i+1]; i++) { if(!strcmp((char*)atts[i], "Id")) id = (char*)atts[i+1]; if(!strcmp((char*)atts[i], "Type")) type = (char*)atts[i+1]; if(!strcmp((char*)atts[i], "MimeType")) mime = (char*)atts[i+1]; if(!strncmp((char*)atts[i], "xmlns", 5)) xmlns = (char*)atts[i+1]; } // create new EncryptedData object err = dencEncryptedData_new(&(pctx->pEncData), xmlns, NULL, id, type, mime); // delete automatically generated meta info to read the stuff from file err = dencMetaInfo_deleteVersionInfo(pctx->pEncData); return err; } //-------------------------------------------------- // Handles the start event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleStartEncryptionMethod(DEncParse* pctx, const xmlChar** atts) { int i, err = ERR_OK; char *alg = NULL; // check the atributes for(i = 0; atts && atts[i] && atts[i+1]; i++) { if(!strcmp((char*)atts[i], "Algorithm")) alg = (char*)atts[i+1]; } // check the EncryptionMethod position in xml doc if(ddocStackHasParentWithName(&(pctx->dencStack), (xmlChar*)"EncryptedKey", NULL)) { DEncEncryptedKey* pEncKey = dencEncryptedData_GetLastEncryptedKey(pctx->pEncData); if(pEncKey) err = dencEncryptedKey_SetEncryptionMethod(pEncKey, alg); } else if(ddocStackHasParentWithName(&(pctx->dencStack), (xmlChar*)"EncryptedData", NULL)) err = dencEncryptedData_SetEncryptionMethod(pctx->pEncData, alg); return err; } //-------------------------------------------------- // Handles the start event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleStartEncryptedKey(DEncParse* pctx, const xmlChar** atts) { int i; char *id = NULL, *recipient = NULL; DEncEncryptedKey* pEncKey = 0; // check the atributes for(i = 0; atts && atts[i] && atts[i+1]; i++) { if(!strcmp((char*)atts[i], "Id")) id = (char*)atts[i+1]; if(!strcmp((char*)atts[i], "Recipient")) recipient = (char*)atts[i+1]; } // create new EncryptedData object return dencEncryptedKey_new(pctx->pEncData, &pEncKey, NULL, NULL, id, recipient, NULL, NULL); } //-------------------------------------------------- // Handles the end event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleEndX509Certificate(DEncParse* pctx) { int err = ERR_OK; X509 *pCert = 0; DEncEncryptedKey* pEncKey = 0; err = ddocDecodeX509PEMData(&pCert, (const char*)pctx->mbufContent.pMem, (int)pctx->mbufContent.nLen); if(err) return err; pEncKey = dencEncryptedData_GetLastEncryptedKey(pctx->pEncData); if(pEncKey) err = dencEncryptedKey_SetCertificate(pEncKey, pCert); ddocDebug(4, "dencSaxHandleEndX509Certificate", "EncKey: %s, cert: %s rc: %d", (pEncKey ? "OK" : "NULL"), (pCert ? "OK" : "NULL"), err); // reset collect mode and cleanup pctx->bCollectMode = 0; ddocMemBuf_free(&(pctx->mbufContent)); return err; } //-------------------------------------------------- // Handles the end event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleEndKeyName(DEncParse* pctx) { int err = ERR_OK; DEncEncryptedKey* pEncKey = dencEncryptedData_GetLastEncryptedKey(pctx->pEncData); if(pEncKey) err = dencEncryptedKey_SetKeyName(pEncKey, (char*)pctx->mbufContent.pMem); ddocDebug(4, "dencSaxHandleEndKeyName", "EncKey: %s, KeyName: %s rc: %d", (pEncKey ? "OK" : "NULL"), (pctx->mbufContent.pMem ? pctx->mbufContent.pMem : "NULL"), err); // reset collect mode and cleanup pctx->bCollectMode = 0; ddocMemBuf_free(&(pctx->mbufContent)); return err; } //-------------------------------------------------- // Handles the end event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleEndCarriedKeyName(DEncParse* pctx) { int err = ERR_OK; DEncEncryptedKey* pEncKey = dencEncryptedData_GetLastEncryptedKey(pctx->pEncData); if(pEncKey) err = dencEncryptedKey_SetCarriedKeyName(pEncKey, (char*)pctx->mbufContent.pMem); ddocDebug(4, "dencSaxHandleEndKeyName", "EncKey: %s, CarriedKeyName: %s rc: %d", (pEncKey ? "OK" : "NULL"), (pctx->mbufContent.pMem ? pctx->mbufContent.pMem : "NULL"), err); // reset collect mode and cleanup pctx->bCollectMode = 0; ddocMemBuf_free(&(pctx->mbufContent)); return err; } //-------------------------------------------------- // Handles the end event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleEndCipherValue(DEncParse* pctx) { int err = ERR_OK, l = 0, i; char *p = 0; EVP_ENCODE_CTX *ectx; if(pctx->mbufContent.pMem && pctx->mbufContent.nLen) { l = pctx->mbufContent.nLen; // enough since it's shrinking p = (char*)malloc(l); RETURN_IF_BAD_ALLOC(p) //decode((const byte*)pctx->mbufContent.pMem, pctx->mbufContent.nLen, p, &l); ectx = EVP_ENCODE_CTX_new(); EVP_DecodeInit(ectx); EVP_DecodeUpdate(ectx, (unsigned char*)p, &l, (unsigned char*)pctx->mbufContent.pMem, pctx->mbufContent.nLen); ddocDebug(3, "dencSaxHandleEndCipherValue", "Initial decoding: %d -> %d bytes", pctx->mbufContent.nLen, l); i = pctx->mbufContent.nLen - l; EVP_DecodeFinal(ectx, (unsigned char*)p+l, &i); EVP_ENCODE_CTX_free(ectx); l += i; ddocDebug(3, "dencSaxHandleEndCipherValue", "Final decoding: %d bytes", i); ddocDebug(3, "dencSaxHandleEndCipherValue", "Decoding: %d bytes of base64 data, got: %d bytes", pctx->mbufContent.nLen, l); ddocMemBuf_free(&(pctx->mbufContent)); } if(p) { // check the EncryptionMethod position in xml doc if(ddocStackHasParentWithName(&(pctx->dencStack), (xmlChar*)"EncryptedKey", NULL)) { DEncEncryptedKey* pEncKey = dencEncryptedData_GetLastEncryptedKey(pctx->pEncData); if(pEncKey) { pEncKey->mbufTransportKey.pMem = p; pEncKey->mbufTransportKey.nLen = l; ddocDebug(4, "dencSaxHandleEndCipherValue", "Set encrypted tarnsport key: %d bytes", l); } else free(p); } else { if(ddocStackHasParentWithName(&(pctx->dencStack), (xmlChar*)"EncryptedData", NULL)) { pctx->pEncData->mbufEncryptedData.pMem = p; pctx->pEncData->mbufEncryptedData.nLen = l; ddocDebug(4, "dencSaxHandleEndCipherValue", "Set encrypted data: %d bytes", l); if(pctx->pEncData->szMimeType && (!strcmp(pctx->pEncData->szMimeType, DENC_ENCDATA_MIME_ZLIB))) pctx->pEncData->nDataStatus = DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED; else pctx->pEncData->nDataStatus = DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED; } else free(p); } } // reset collect mode and cleanup pctx->bCollectMode = 0; return err; } //-------------------------------------------------- // Handles the start event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleStartEncryptionProperties(DEncParse* pctx, const xmlChar** atts) { int i, err = ERR_OK; char *id = NULL; // check the atributes for(i = 0; atts && atts[i] && atts[i+1]; i++) { if(!strcmp((char*)atts[i], "Id")) id = (char*)atts[i+1]; } if(id) err = dencEncryptedData_SetEncryptionPropertiesId(pctx->pEncData, id); return err; } //-------------------------------------------------- // Handles the start event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleStartEncryptionProperty(DEncParse* pctx, const xmlChar** atts) { int i, err = ERR_OK; char *id = NULL, *target = NULL, *name = NULL; DEncEncryptionProperty* pEncProperty = 0; // check the atributes for(i = 0; atts && atts[i] && atts[i+1]; i++) { if(!strcmp((char*)atts[i], "Id")) id = (char*)atts[i+1]; if(!strcmp((char*)atts[i], "Target")) target = (char*)atts[i+1]; if(!strcmp((char*)atts[i], "Name")) name = (char*)atts[i+1]; } err = dencEncryptionProperty_new(pctx->pEncData, &pEncProperty, id, target, name, NULL); if(err) return err; pctx->bCollectMode = 1; ddocMemBuf_free(&(pctx->mbufContent)); return err; } //-------------------------------------------------- // Handles the end event // pctx - SAX parser context // atts - array of atribute names and values // returns error code or ERR_OK. //-------------------------------------------------- int dencSaxHandleEndEncryptionProperty(DEncParse* pctx) { int err = ERR_OK; DEncEncryptionProperty* pEncProperty = 0; if(pctx->mbufContent.pMem && pctx->mbufContent.nLen) { pEncProperty = dencEncryptedData_GetLastEncryptionProperty(pctx->pEncData); if(pEncProperty) err = dencEncryptionProperty_SetContent(pEncProperty, (char*)pctx->mbufContent.pMem); ddocMemBuf_free(&(pctx->mbufContent)); } pctx->bCollectMode = 0; return err; } //===============< SAX handlers >============================== //-------------------------------------------------- // dencStartElementHandler: // @ctxt: An XML parser context // @name: The element name // called when an opening tag has been processed. //-------------------------------------------------- static void dencStartElementHandler(void *ctx, const xmlChar *name, const xmlChar **atts) { DEncParse* pctx = (DEncParse*)ctx; ElementEntry* pCurrElem = 0; ddocDebug(5, "dencStartElementHandler", "<%s>, err: %d", (const char*)name, pctx->errcode); if(pctx->errcode) return; // if error skip all additional parsing pctx->errcode = ddocStackPushElementSAX(&(pctx->dencStack), name, atts, &pCurrElem); if(pctx->errcode) return; // check the element name if(pCurrElem) { if(!strcmp((const char*)pCurrElem->tag, "EncryptedData")) pctx->errcode = dencSaxHandleStartEncryptedData(pctx, atts); if(!strcmp((const char*)pCurrElem->tag, "EncryptionMethod")) pctx->errcode = dencSaxHandleStartEncryptionMethod(pctx, atts); if(!strcmp((const char*)pCurrElem->tag, "EncryptedKey")) pctx->errcode = dencSaxHandleStartEncryptedKey(pctx, atts); // start collecting certificate data if(!strcmp((const char*)pCurrElem->tag, "X509Certificate") || !strcmp((const char*)pCurrElem->tag, "KeyName") || !strcmp((const char*)pCurrElem->tag, "CipherValue") || !strcmp((const char*)pCurrElem->tag, "CarriedKeyName") ) { pctx->bCollectMode = 1; ddocMemBuf_free(&(pctx->mbufContent)); } if(!strcmp((const char*)pCurrElem->tag, "EncryptionProperties")) pctx->errcode = dencSaxHandleStartEncryptionProperties(pctx, atts); if(!strcmp((const char*)pCurrElem->tag, "EncryptionProperty")) pctx->errcode = dencSaxHandleStartEncryptionProperty(pctx, atts); } } //-------------------------------------------------- // dencEndElementHandler: // @ctxt: An XML parser context // @name: The element name // called when the end of an element has been detected. //-------------------------------------------------- static void dencEndElementHandler(void *ctx, const xmlChar *name) { DEncParse* pctx = (DEncParse*)ctx; ElementEntry* pCurrElem = 0; ddocDebug(5, "dencEndElementHandler", ", err: %d", (const char*)name, pctx->errcode); if(pctx->errcode) return; // if error skip all additional parsing // find last element pCurrElem = ddocStackFindEnd(&(pctx->dencStack)); // check the element name if(pCurrElem) { if(!strcmp((const char*)pCurrElem->tag, "X509Certificate")) pctx->errcode = dencSaxHandleEndX509Certificate(pctx); if(!strcmp((const char*)pCurrElem->tag, "KeyName")) pctx->errcode = dencSaxHandleEndKeyName(pctx); if(!strcmp((const char*)pCurrElem->tag, "CarriedKeyName")) pctx->errcode = dencSaxHandleEndCarriedKeyName(pctx); if(!strcmp((const char*)pCurrElem->tag, "CipherValue")) pctx->errcode = dencSaxHandleEndCipherValue(pctx); if(!strcmp((const char*)pCurrElem->tag, "EncryptionProperty")) pctx->errcode = dencSaxHandleEndEncryptionProperty(pctx); } // pop stack pctx->errcode = ddocStackPopElement(&(pctx->dencStack), 0, NULL); } //-------------------------------------------------- // dencCharactersHandler: // @ctxt: An XML parser context // @ch: a xmlChar string // @len: the number of xmlChar // receiving some chars from the parser. //-------------------------------------------------- static void dencCharactersHandler(void *ctx, const xmlChar *ch, int len) { DEncParse* pctx = (DEncParse*)ctx; ddocDebug(5, "dencCharactersHandler", "err: %d", pctx->errcode); if(pctx->errcode) return; // if error skip all additional parsing if(pctx->bCollectMode) { pctx->errcode = ddocMemAppendData(&(pctx->mbufContent), (char*)ch, len); } ddocDebug(5, "dencCharactersHandler: %s", "End"); } //-------------------------------------------------- // cdataBlockHandler: // @ctx: the user data (XML parser context) // @value: The pcdata content // @len: the block length // called when a pcdata block has been parsed //-------------------------------------------------- static void dencCdataBlockHandler(void * ctx, const xmlChar *value, int len) { ddocDebug(5, "dencCdataBlockHandler", "SAX.pcdata(%.20s, %d)", (char*)value, len); } //-------------------------------------------------- // dencWarningHandler: // @ctxt: An XML parser context // @msg: the message to display/transmit // @...: extra parameters for the message display // Display and format a warning messages, gives file, line, position and // extra parameters //-------------------------------------------------- static void dencWarningHandler(void * ctx, const char *msg, ...) { va_list args; va_start(args, msg); ddocDebug(2, "dencWarningHandler", msg, args); fprintf(stdout, "SAX.warning: "); vfprintf(stdout, msg, args); va_end(args); } //-------------------------------------------------- // dencErrorHandler: // @ctxt: An XML parser context // @msg: the message to display/transmit // @...: extra parameters for the message display // Display and format a error messages, gives file, line, position and // extra parameters. //-------------------------------------------------- static void dencErrorHandler(void *ctx, const char *msg, ...) { va_list args; DEncParse* pctx = (DEncParse*)ctx; va_start(args, msg); pctx->errcode = ERR_DIGIDOC_PARSE; ddocDebugVaArgs(1, "dencErrorHandler", msg, args); addError(pctx->errcode, __FILE__, __LINE__, "XML parsing error"); va_end(args); } //-------------------------------------------------- // dencFatalErrorHandler: // @ctxt: An XML parser context // @msg: the message to display/transmit // @...: extra parameters for the message display // Display and format a fatalError messages, gives file, line, position and // extra parameters. //-------------------------------------------------- static void dencFatalErrorHandler(void *ctx, const char *msg, ...) { va_list args; DEncParse* pctx = (DEncParse*)ctx; va_start(args, msg); pctx->errcode = ERR_DIGIDOC_PARSE; ddocDebugVaArgs(1, "dencFatalErrorHandler", msg, args); addError(pctx->errcode, __FILE__, __LINE__, "XML parsing error"); va_end(args); } xmlSAXHandler dencSAXHandlerStruct = { NULL, //internalSubsetHandler, NULL, //isStandaloneHandler, NULL, //hasInternalSubsetHandler, NULL, //hasExternalSubsetHandler, NULL, //resolveEntityHandler, NULL, //getEntityHandler, NULL, //entityDeclHandler, NULL, //notationDeclHandler, NULL, //attributeDeclHandler, NULL, //elementDeclHandler, NULL, //unparsedEntityDeclHandler, NULL, //setDocumentLocatorHandler, NULL, //startDocumentHandler, NULL, //endDocumentHandler, dencStartElementHandler, dencEndElementHandler, NULL, //referenceHandler, dencCharactersHandler, NULL, //ignorableWhitespaceHandler, NULL, //processingInstructionHandler, NULL, //commentHandler, dencWarningHandler, dencErrorHandler, dencFatalErrorHandler, NULL, //getParameterEntityHandler, dencCdataBlockHandler, NULL, //externalSubsetHandler, 1 }; xmlSAXHandlerPtr dencSAXHandler = &dencSAXHandlerStruct; //-------------------------------------------------- // Reads in encrypted XML document. // ppEncData - address for new encrypted data object [REQUIRED] // szFileName - input file name // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencSaxReadEncryptedData(DEncEncryptedData** ppEncData, const char* szFileName) { FILE *f; int ret; char chars[1025]; xmlParserCtxtPtr ctxt; DEncParse pctx; #ifdef WIN32 wchar_t *convFileName = 0; int i= 0; #endif RETURN_IF_NULL_PARAM(szFileName) RETURN_IF_NULL_PARAM(ppEncData) clearErrors(); *ppEncData = 0; // mark as not read yet memset(&pctx, 0, sizeof(pctx)); //ddocConvertFileName(chars, sizeof(chars), szFileName ); ddocDebug(3, "dencSaxReadEncryptedData", "Opening file: %s", szFileName); #ifdef WIN32 i = 0; ret = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "dencSaxReadEncryptedData", "file: %s, conv-file: %s len: %d, rc: %d", szFileName, convFileName, i, ret); if((f = _wfopen(convFileName, L"rb")) != NULL) { ddocDebug(3, "dencSaxReadEncryptedData", "Opened w-file: %s", convFileName); #else if((f = fopen(szFileName, "rb")) != NULL) { ddocDebug(3, "dencSaxReadEncryptedData", "Opened file: %s", szFileName); #endif ret = fread(chars, 1, 1024, f); if (ret > 0) { ddocDebug(3, "dencSaxReadEncryptedData", "Read first %d bytes", ret); ctxt = xmlCreatePushParserCtxt(dencSAXHandler, &pctx, chars, ret, szFileName); while ((ret = fread(chars, 1, 1024, f)) > 0) { ddocDebug(3, "dencSaxReadEncryptedData", "Parsing %d bytes", ret); xmlParseChunk(ctxt, chars, ret, 0); } xmlParseChunk(ctxt, chars, 0, 1); xmlFreeParserCtxt(ctxt); } fclose(f); } else { ddocDebug(1, "dencSaxReadEncryptedData", "Error reading file: %s", szFileName); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } // cleanup stack ret = pctx.errcode = ddocStackPopElement(&(pctx.dencStack), 1, NULL); ddocDebug(3, "dencSaxReadEncryptedData", "End parsing file: %s - RC: %d", szFileName, ret); if(ret == 0) *ppEncData = pctx.pEncData; // cleanup dencSaxCleanup(&pctx); return ret; } //-------------------------------------------------- // Reads in encrypted XML document. // ppEncData - address for new encrypted data object [REQUIRED] // pData - input data [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencSaxReadEncryptedDataFromMemory(DEncEncryptedData** ppEncData, DigiDocMemBuf* pData) { int ret; DEncParse pctx; RETURN_IF_NULL_PARAM(pData) RETURN_IF_NULL_PARAM(ppEncData) clearErrors(); *ppEncData = 0; // mark as not read yet memset(&pctx, 0, sizeof(pctx)); ddocDebug(3, "dencSaxReadEncryptedData", "Reading from mem %d bytes", pData->nLen); ret = xmlSAXUserParseMemory(dencSAXHandler, &pctx, (const char*)pData->pMem, pData->nLen); // cleanup stack ret = pctx.errcode = ddocStackPopElement(&(pctx.dencStack), 1, NULL); ddocDebug(3, "dencSaxReadEncryptedData", "End parsing mem: %d - RC: %d", pData->nLen, ret); if(ret == 0) *ppEncData = pctx.pEncData; // cleanup dencSaxCleanup(&pctx); return ret; } //===============< Large file decryption SAX handlers >============================== /* * Working area for XML parsing with SAX */ typedef struct DEncDecryptParse_st { int errcode; ElementEntry dencStack; // stack used for keeping the current parsing position FILE* hOutFile; DigiDocMemBuf mbufTransportKey; DigiDocMemBuf mbufTemp; X509* pCert; EVP_PKEY* pkey; char* szPin; int nSlot; long lB64Len, lBinLen, lDecLen; EVP_ENCODE_CTX *ectx; EVP_CIPHER_CTX *dctx; int nB64SkipMode; char errmsg[100]; char szCertSerial[100]; int nCipherInited; } DEncDecryptParse; //-------------------------------------------------- // Cleans up data that might have been allocated // during the parsing process // pctx: An XML parser context //-------------------------------------------------- void dencDecryptSaxCleanup(DEncDecryptParse* pctx) { ddocMemBuf_free(&(pctx->mbufTransportKey)); ddocMemBuf_free(&(pctx->mbufTemp)); if(pctx->pCert) X509_free(pctx->pCert); if(pctx->hOutFile) fclose(pctx->hOutFile); memset(pctx, 0, sizeof(DEncDecryptParse)); } //-------------------------------------------------- // dencDecryptStartElementHandler: // @ctxt: An XML parser context // @name: The element name // called when an opening tag has been processed. //-------------------------------------------------- static void dencDecryptStartElementHandler(void *ctx, const xmlChar *name, const xmlChar **atts) { DEncDecryptParse* pctx = (DEncDecryptParse*)ctx; ElementEntry* pCurrElem = 0; char *mime = NULL; int i; // check the atributes for(i = 0; atts && atts[i] && atts[i+1]; i++) { if(!strcmp((char*)atts[i], "MimeType")) { mime = (char*)atts[i+1]; } } ddocDebug(4, "dencDecryptStartElementHandler", "<%s>, err: %d", (const char*)name, pctx->errcode); if(pctx->errcode) return; // if error skip all additional parsing pctx->errcode = ddocStackPushElementSAX(&(pctx->dencStack), name, atts, &pCurrElem); // initialize decoding and decryption if(pCurrElem && !strcmp((const char*)pCurrElem->tag, "CipherValue") && !ddocStackHasParentWithName(&(pctx->dencStack), (xmlChar*)"EncryptedKey", NULL)) { if(pctx->nB64SkipMode == 0) { ddocDebug(4, "dencDecryptStartElementHandler", "Decode init"); pctx->ectx = EVP_ENCODE_CTX_new(); EVP_DecodeInit(pctx->ectx); EVP_CIPHER_CTX_init(pctx->dctx); pctx->lB64Len = pctx->lBinLen = pctx->lDecLen = 0; } pctx->nB64SkipMode++; // increment skip mode ddocDebug(4, "dencDecryptStartElementHandler", "Decode start, skip: %d", pctx->nB64SkipMode); } // check mime if(strstr((char*)name, "EncryptedData")) { } // if(strstr((char*)name, "X509Certificate")) { ddocDebug(4, "dencDecryptStartElementHandler", "Start collecting cert"); ddocMemBuf_free(&(pctx->mbufTemp)); } } //-------------------------------------------------- // dencDecryptEndElementHandler: // @ctxt: An XML parser context // @name: The element name // called when the end of an element has been detected. //-------------------------------------------------- static void dencDecryptEndElementHandler(void *ctx, const xmlChar *name) { DEncDecryptParse* pctx = (DEncDecryptParse*)ctx; char buf1[4096], buf2[4096]; int l1, l2, l3; DigiDocMemBuf mbuf1; mbuf1.pMem = NULL; mbuf1.nLen = 0; ddocDebug(4, "dencDecryptEndElementHandler", ", err: %d", (const char*)name, pctx->errcode); if(pctx->errcode) return; // if error skip all additional parsing // decode the certificate data if(strstr((char*)name, "X509Certificate")) { pctx->errcode = ddocDecodeX509PEMData(&(pctx->pCert), (const char*)pctx->mbufTemp.pMem, (int)pctx->mbufTemp.nLen); ddocDebug(4, "dencDecryptEndElementHandler", "Decoding pem: %d cert: %s, rc: %d", pctx->mbufTemp.nLen, (pctx->pCert ? "OK" : "NULL"), pctx->errcode); ddocMemBuf_free(&(pctx->mbufTemp)); //EVP_DecodeFinal(&(pctx->ectx),out,outl) pctx->nB64SkipMode = 0; } // check if it was the right key and decrypt transport key if(strstr((char*)name, "EncryptedKey")) { memset(buf1, 0, sizeof(buf1)); pctx->errcode = ReadCertSerialNumber(buf1, sizeof(buf1), pctx->pCert); ddocCertGetDN(pctx->pCert, &mbuf1, 0); ddocDebug(4, "dencDecryptEndElementHandler", "Looking for cert: %s, found: %s - %s, rc: %d", pctx->szCertSerial, buf1, (char*)mbuf1.pMem, pctx->errcode); ddocMemBuf_free(&mbuf1); if(!strcmp(pctx->szCertSerial, buf1)) { l1 = sizeof(buf1); memset(buf1, 0, l1); decode((const byte*)pctx->mbufTemp.pMem, pctx->mbufTemp.nLen, (byte*)buf1, &l1); ddocDebug(4, "dencDecryptEndElementHandler", "Decoded key-len: %d got: %d", pctx->mbufTemp.nLen, l1); // cleanup temp buffer ddocMemBuf_free(&(pctx->mbufTemp)); if(l1 < DENC_ENCRYPTED_KEY_LEN) { SET_LAST_ERROR(ERR_DENC_DECRYPT); pctx->errcode = ERR_DENC_DECRYPT; return; } // decrypt the transport key pctx->mbufTransportKey.nLen = l1; pctx->mbufTransportKey.pMem = (char*)malloc(l1); if(!pctx->mbufTransportKey.pMem) { SET_LAST_ERROR(ERR_BAD_ALLOC); pctx->errcode = ERR_BAD_ALLOC; return; } memset(pctx->mbufTransportKey.pMem, 0, l1); l3 = pctx->mbufTransportKey.nLen; if(pctx->pkey) { #if OPENSSL_VERSION_NUMBER > 0x10000000 l3 = EVP_PKEY_decrypt_old((unsigned char *)pctx->mbufTransportKey.pMem, (const unsigned char*)buf1, l1, pctx->pkey); #else l3 = EVP_PKEY_decrypt((unsigned char *)pctx->mbufTransportKey.pMem, (const unsigned char*)buf1, l1, pctx->pkey); #endif pctx->mbufTransportKey.nLen = l3; if(l3 != 16) pctx->errcode = ERR_DENC_DECRYPT; } else { pctx->errcode = decryptWithEstID(pctx->nSlot, pctx->szPin, (char *)buf1, l1, (char*)pctx->mbufTransportKey.pMem, &l3); pctx->mbufTransportKey.nLen = l3; } ddocDebug(4, "dencDecryptEndElementHandler", "Decrypted key-len: %d rc: %d", pctx->mbufTransportKey.nLen, pctx->errcode); if(pctx->mbufTransportKey.nLen != DENC_DECRYPTED_KEY_LEN) { SET_LAST_ERROR(ERR_DENC_DECRYPT); pctx->errcode = ERR_DENC_DECRYPT; return; } } } // last block of encrypted data if(strstr((char*)name, "CipherValue") && !ddocStackHasParentWithName(&(pctx->dencStack), (xmlChar*)"EncryptedKey", NULL)) { ddocDebug(4, "dencDecryptEndElementHandler", "Decode end, skip: %d", pctx->nB64SkipMode); if(pctx->nB64SkipMode > 0) pctx->nB64SkipMode--; if(pctx->nB64SkipMode == 0) { l1 = sizeof(buf1); memset(buf1, 0, l1); ddocDebug(4, "dencDecryptEndElementHandler", "Decoding: final into: %d", l1); EVP_DecodeFinal(pctx->ectx, (unsigned char*)buf1, &l1); EVP_ENCODE_CTX_free(pctx->ectx); pctx->lBinLen += l1; ddocDebug(4, "dencDecryptEndElementHandler", "Decoded: final got: %d, total %d -> %d", l1, pctx->lB64Len, pctx->lBinLen); // decrypt decoded data l2 = sizeof(buf2); memset(buf2, 0, l2); ddocDebug(3, "dencDecryptEndElementHandler", "Decrypting: final into: %d", l2); EVP_CipherFinal_ex(pctx->dctx, (unsigned char*)buf2, &l2); EVP_CIPHER_CTX_free(pctx->dctx); ddocDebug(4, "dencDecryptEndElementHandler", "Decrypted: final got: %d", l2); // write to file if(pctx->hOutFile) { if(l2) pctx->lDecLen += fwrite(buf2, 1, l2, pctx->hOutFile); fclose(pctx->hOutFile); pctx->hOutFile = 0; } ddocDebug(3, "dencDecryptEndElementHandler", "Total base64: %d decoded: %d decrypted: %d RC: %d", pctx->lB64Len, pctx->lBinLen, pctx->lDecLen, pctx->errcode); pctx->nB64SkipMode = 0; } } // pop stack pctx->errcode = ddocStackPopElement(&(pctx->dencStack), 0, NULL); } //-------------------------------------------------- // dencDecryptCharactersHandler: // @ctxt: An XML parser context // @ch: a xmlChar string // @len: the number of xmlChar // receiving some chars from the parser. //-------------------------------------------------- static void dencDecryptCharactersHandler(void *ctx, const xmlChar *ch, int len) { DEncDecryptParse* pctx = (DEncDecryptParse*)ctx; ElementEntry* pCurrElem = 0; char *buf1=0, *buf2=0, *p1=0; int l1, l2, i, l; ddocDebug(4, "dencDecryptCharactersHandler", "Parsing: %d chars err: %d, skip: %d", len, pctx->errcode, pctx->nB64SkipMode); if(pctx->errcode) return; // if error skip all additional parsing // find last element pCurrElem = ddocStackFindEnd(&(pctx->dencStack)); // if this is data belonging to tag and // the latter is not a child of , thus // it must be the main content, then decrypt it if(pCurrElem && !strcmp((const char*)pCurrElem->tag, "X509Certificate")) { // collect the certificate data pctx->errcode = ddocMemAppendData(&(pctx->mbufTemp), (char*)ch, len); } if(pCurrElem || pctx->nB64SkipMode > 0) { // handle encrypted data if((pCurrElem && !strcmp((const char*)pCurrElem->tag, "CipherValue")) || pctx->nB64SkipMode > 0) { // collect encrypted transport key data if(pCurrElem && ddocStackHasParentWithName(&(pctx->dencStack), (xmlChar*)"EncryptedKey", NULL)) { pctx->errcode = ddocMemAppendData(&(pctx->mbufTemp), (char*)ch, len); } // if this is the real encrypted content not a key then decrypt it else { // check if the transport key is ready for decryption if(pctx->mbufTransportKey.nLen != DENC_DECRYPTED_KEY_LEN) { ddocDebug(1, "dencDecryptCharactersHandler", "Transport key len: %d", pctx->mbufTransportKey.nLen); SET_LAST_ERROR(ERR_DENC_NO_KEY_FOUND); // not encrypted for this user! pctx->errcode = ERR_DENC_NO_KEY_FOUND; return; } // decode base64 encrypted data pctx->lB64Len += len; l1 = len * 2; buf1 = (char*)malloc(l1); if(!buf1) { SET_LAST_ERROR(ERR_BAD_ALLOC); return; } memset(buf1, 0, l1); ddocDebug(4, "dencDecryptCharactersHandler", "Decoding: %d into: %d, skip: %d", len, l1, pctx->nB64SkipMode); EVP_DecodeUpdate(pctx->ectx, (unsigned char*)buf1, &l1, (unsigned char*)ch, len); ddocDebug(4, "dencDecryptCharactersHandler", "Decoded: %d got: %d, skip: %d", len, l1, pctx->nB64SkipMode); // if this was the first block of decoded base64 data // then use the first 16 bytes as the IV value p1 = buf1; if(pctx->lBinLen == 0) { ddocDebug(4, "dencDecryptCharactersHandler", "Using 16 bytes for IV. Initing cipher"); p1 += 16; // don't decrypt the IV data l1 -= 16; pctx->dctx = EVP_CIPHER_CTX_new(); EVP_CipherInit_ex(pctx->dctx, EVP_aes_128_cbc(), NULL, (const unsigned char*)pctx->mbufTransportKey.pMem, (const unsigned char*)buf1, DECRYPT); } pctx->lBinLen += l1; ddocDebug(4, "dencDecryptCharactersHandler", "Decoded: %d got: %d, skip: %d", len, l1, pctx->nB64SkipMode); // decrypt decoded data l = l2 = l1 * 2; buf2 = (char*)malloc(l2); if(!buf2) { SET_LAST_ERROR(ERR_BAD_ALLOC); return; } memset(buf2, 0, l2); //if(pctx->nB64SkipMode == 4) // l1 += 16; // ??? ddocDebug(4, "dencDecryptCharactersHandler", "Decrypting: %d into: %d", l1, l2); EVP_CipherUpdate(pctx->dctx, (unsigned char*)buf2, &l, (const unsigned char*)p1, l1); ddocDebug(4, "dencDecryptCharactersHandler", "Decrypted: %d got: %d, skip: %d", l1, l, pctx->nB64SkipMode); if(buf1) free(buf1); // no padding until the final chunk if((pctx->nB64SkipMode == 0 || pctx->nB64SkipMode == 4)) { // on the last block check for a block with all 0x0F l1 = (int)(unsigned char)buf2[l-1]; if(l1 == 16) { ddocDebug(4, "dencDecryptCharactersHandler", "Check 0x0F padding 1: %d", l1); for(i = l - l1; i < l - 1; i++) { ddocDebug(4, "dencDecryptCharactersHandler", "Pad pos: %d = %d", i, buf2[i]); if(buf2[i] != 16) { l1 = 0; // set not matched flag break; } } if(l1) { ddocDebug(4, "dencDecryptCharactersHandler", "Decrypted len: %d reduce by: %d -> %d", l2, l1, (l-l1)); l -= l1; } } // remove padding l1 = (int)(unsigned char)buf2[l-1]; if(l1 > 0 && l1 <= 16) { ddocDebug(4, "dencDecryptCharactersHandler", "Check padding: %d", l1); for(i = l - l1; i < l - 1; i++) { ddocDebug(4, "dencDecryptCharactersHandler", "Pad pos: %d = %d", i, buf2[i]); if(buf2[i]) { l1 = 0; // set not matched flag break; } } if(l1) { ddocDebug(4, "dencDecryptCharactersHandler", "Decrypted len: %d reduce by: %d -> %d", l2, l1, (l-l1)); l -= l1; } } else ddocDebug(4, "dencDecryptCharactersHandler", "Impossible padding: %d", l1); if(pctx->nB64SkipMode == 4) pctx->nB64SkipMode = 1; // reset flag - look for padding } // write to file if(pctx->hOutFile && buf2) pctx->lDecLen += fwrite(buf2, 1, l, pctx->hOutFile); free(buf2); } } } ddocDebug(5, "dencDecryptCharactersHandler", "End"); } xmlSAXHandler dencDecryptSAXHandlerStruct = { NULL, //internalSubsetHandler, NULL, //isStandaloneHandler, NULL, //hasInternalSubsetHandler, NULL, //hasExternalSubsetHandler, NULL, //resolveEntityHandler, NULL, //getEntityHandler, NULL, //entityDeclHandler, NULL, //notationDeclHandler, NULL, //attributeDeclHandler, NULL, //elementDeclHandler, NULL, //unparsedEntityDeclHandler, NULL, //setDocumentLocatorHandler, NULL, //startDocumentHandler, NULL, //endDocumentHandler, dencDecryptStartElementHandler, dencDecryptEndElementHandler, NULL, //referenceHandler, dencDecryptCharactersHandler, NULL, //ignorableWhitespaceHandler, NULL, //processingInstructionHandler, NULL, //commentHandler, dencWarningHandler, dencErrorHandler, dencFatalErrorHandler, NULL, //getParameterEntityHandler, dencCdataBlockHandler, NULL, //externalSubsetHandler, 1 }; xmlSAXHandlerPtr dencDecryptSAXHandler = &dencDecryptSAXHandlerStruct; // string used to force parser to flush it's buffers static char g_szCipherValueFlush1[] = ""; static char g_szCipherValueFlush2[] = ""; //-------------------------------------------------- // Decrypts an encrypted XML document and stores the // cleartext data in another document. // szInputFileName - input file name [REQUIRED] // szOutputFileName - output file name [REQUIRED] // szPin - PIN1 of the id-card to decrypt the transport key [REQUIRED] // szPkcs12File - pkcs12 key container filename [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencSaxReadDecryptFile(const char* szInputFileName, const char* szOutputFileName, const char* szPin, const char* szPkcs12File) { FILE *f; int ret; char chars[1025], convInFileName[256], convOutFileName[256], *p; xmlParserCtxtPtr ctxt; DEncDecryptParse pctx; X509* pCert = 0; EVP_PKEY *pkey = NULL; DigiDocMemBuf mbuf1; mbuf1.pMem = NULL; mbuf1.nLen = 0; RETURN_IF_NULL_PARAM(szInputFileName) RETURN_IF_NULL_PARAM(szOutputFileName) RETURN_IF_NULL_PARAM(szPin) clearErrors(); ddocDebug(3, "dencSaxReadDecryptFile", "input-file: %s, output-file: %s", szInputFileName, szOutputFileName); memset(&pctx, 0, sizeof(pctx)); ddocConvertFileName(convInFileName, sizeof(convInFileName), szInputFileName); ddocConvertFileName(convOutFileName, sizeof(convOutFileName), szOutputFileName); //store decryption params pctx.nSlot = ConfigItem_lookup_int("DIGIDOC_AUTH_KEY_SLOT", 0); pctx.szPin = (char*)szPin; pctx.hOutFile = fopen(convOutFileName, "wb"); pctx.nB64SkipMode = 0; if(!pctx.hOutFile) { ddocDebug(1, "dencSaxReadDecryptFile", "Error writing to file: %s", szOutputFileName); SET_LAST_ERROR_RETURN(ERR_FILE_WRITE, ERR_FILE_WRITE) } // if using pkcs12 file for decryption if(szPkcs12File) { pctx.errcode = ReadCertificateByPKCS12(&pCert, szPkcs12File, szPin, &pkey); pctx.pkey = pkey; } else { pctx.errcode = findUsersCertificate(pctx.nSlot, &pCert); } if(pCert) { pctx.errcode = ReadCertSerialNumber(pctx.szCertSerial, sizeof(pctx.szCertSerial), pCert); ddocCertGetDN(pCert, &mbuf1, 0); ddocDebug(3, "dencSaxReadDecryptFile", "Decrypting using certificate: %s - %s", pctx.szCertSerial, (char*)mbuf1.pMem); ddocMemBuf_free(&mbuf1); } else { ddocDebug(1, "dencSaxReadDecryptFile", "Users cert for decryption could not be read from card!"); return pctx.errcode; } // parse and decrypt data in file if((f = fopen(convInFileName, "r")) != NULL && !pctx.errcode) { ret = fread(chars, 1, 1024, f); if (ret > 0) { ctxt = xmlCreatePushParserCtxt(dencDecryptSAXHandler, &pctx, chars, ret, convInFileName); do { memset(chars, 0, sizeof(chars)); ret = fread(chars, 1, 1024, f); if(ret == 0) ret = strlen(chars); ddocDebug(4, "dencSaxReadDecryptFile", "In: %d Parsed: %d, skip: %d", ret, ctxt->nbChars, pctx.nB64SkipMode); // this horrible chemistry is done to prevent // libxml2 to start colecting huge memory structures // Since we cannot disable it we'll just bypass parser // with a large amount of base64 data if(pctx.nB64SkipMode > 0) { p = strchr(chars, '<'); // if was found and no "<" (beginn of new element) // is found then send the "flush command" and enter bypass mode if(pctx.nB64SkipMode == 1 && !p) { pctx.nB64SkipMode += 2; ddocDebug(4, "dencSaxReadDecryptFile", "Starting bypass mode, skip: %d", pctx.nB64SkipMode); // force the parser to release element content // before entering into bypass mode xmlParseChunk(ctxt, g_szCipherValueFlush1, strlen(g_szCipherValueFlush1), 0); ddocDebug(4, "dencSaxReadDecryptFile", "Entering bypass mode, skip: %d", pctx.nB64SkipMode); } if(pctx.nB64SkipMode >= 2 && !p) { ddocDebug(4, "dencSaxReadDecryptFile", "Parsing in bypass mode, skip: %d", pctx.nB64SkipMode); dencDecryptCharactersHandler(&pctx, (const xmlChar *)chars, ret); } // if we reached the first block that contains a start of xml element // then stop bypass mode if(strchr(chars, '<')) { pctx.nB64SkipMode = 2; xmlParseChunk(ctxt, g_szCipherValueFlush2, strlen(g_szCipherValueFlush2), 0); ddocDebug(4, "dencSaxReadDecryptFile", "Ending bypass mode len: %d, skip: %d", ret, pctx.nB64SkipMode); } } // if bypass mode // if in normal mode or finished bypass mode if(pctx.nB64SkipMode == 0 || pctx.nB64SkipMode == 3) { if(pctx.nB64SkipMode == 3) pctx.nB64SkipMode = 4; // used as flag: last block - look for padding ddocDebug(4, "dencSaxReadDecryptFile", "parsing normal chunk"); xmlParseChunk(ctxt, chars, ret, 0); } //memset(chars, 0, sizeof(chars)); } while(ret == 1024); // do-while // last block of data ddocDebug(4, "dencSaxReadDecryptFile", "parsing final chunk: %d", strlen(chars)); if(!pctx.errcode) xmlParseChunk(ctxt, NULL, 0, 1); xmlFreeParserCtxt(ctxt); } // if(ret > 0) fclose(f); } else { ddocDebug(1, "dencSaxReadDecryptFile", "Error reading file: %s", szInputFileName); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } // cleanup stack ret = pctx.errcode = ddocStackPopElement(&(pctx.dencStack), 1, NULL); // cleanup dencDecryptSaxCleanup(&pctx); ddocDebug(1, "dencSaxReadDecryptFile", "End parsing file: %s - RC: %d", szInputFileName, ret); return ret; } libdigidoc-3.10.5/libdigidoc/DigiDocEncGen.c0000664000372000037200000004147013560273131020121 0ustar travistravis//================================================== // FILE: DigiDocEncGen.c // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDocEnc XML generation // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 11.10.2004 Veiko Sinivee // Creation //================================================== #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 #include #endif //-----------< XML generation functions >---------------------------- //-------------------------------------------------- // Generates XML for element // pEncProperty - encryption property object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptionProperty_toXML(DEncEncryptionProperty* pEncProperty, DigiDocMemBuf* pBuf) { int err = ERR_OK; char* p = 0, *p1 = 0; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncProperty) // start of element err = ddocGen_startElemBegin(pBuf, "denc:EncryptionProperty"); if(err) return err; // Id atribute p = (char*)dencEncryptionProperty_GetId(pEncProperty); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; // Target atribute p = (char*)dencEncryptionProperty_GetTarget(pEncProperty); if(p) err = ddocGen_addAtribute(pBuf, "Target", p); if(err) return err; // Name atribute p = (char*)dencEncryptionProperty_GetName(pEncProperty); if(p) err = ddocGen_addAtribute(pBuf, "Name", p); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // content p = (char*)dencEncryptionProperty_GetContent(pEncProperty); if(p) { escapeXMLSymbols(p, -1, &p1); err = ddocMemAppendData(pBuf, p1, -1); free(p1); } if(err) return err; err = ddocGen_endElem(pBuf, "denc:EncryptionProperty"); return err; } //-------------------------------------------------- // Generates XML for element // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptionProperties_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf) { int err = ERR_OK; char* p; int n, i; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncData) // count the prperties - do nothing if none exist n = dencEncryptedData_GetEncryptionPropertiesCount(pEncData); if(!n) return err; // start of element err = ddocGen_startElemBegin(pBuf, "denc:EncryptionProperties"); if(err) return err; // Id atribute p = (char*)dencEncryptedData_GetEncryptionPropertiesId(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // content for(i = 0; i < n; i++) { DEncEncryptionProperty* pEncProp = dencEncryptedData_GetEncryptionProperty(pEncData, i); if(pEncProp) err = dencGenEncryptionProperty_toXML(pEncProp, pBuf); if(err) return err; } // end of element err = ddocGen_endElem(pBuf, "denc:EncryptionProperties"); return err; } //-------------------------------------------------- // Generates XML for element // pEncKey - encrypted key object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptedKey_toXML(DEncEncryptedKey* pEncKey, DigiDocMemBuf* pBuf) { int err = ERR_OK, l1; char* p; X509* pCert; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncKey) // start of element err = ddocGen_startElemBegin(pBuf, "denc:EncryptedKey"); if(err) return err; // Id atribute p = (char*)dencEncryptedKey_GetId(pEncKey); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; // Recipient atribute p = (char*)dencEncryptedKey_GetRecipient(pEncKey); if(p) err = ddocGen_addAtribute(pBuf, "Recipient", p); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // p = (char*)dencEncryptedKey_GetEncryptionMethod(pEncKey); if(p) { err = ddocGen_startElemBegin(pBuf, "denc:EncryptionMethod"); if(err) return err; err = ddocGen_addAtribute(pBuf, "Algorithm", p); if(err) return err; err = ddocGen_startElemEnd(pBuf); if(err) return err; err = ddocGen_endElem(pBuf, "denc:EncryptionMethod"); if(err) return err; } // err = ddocGen_startElem(pBuf, "ds:KeyInfo"); if(err) return err; // p = (char*)dencEncryptedKey_GetKeyName(pEncKey); if(p) { err = ddocGen_startElem(pBuf, "ds:KeyName"); if(err) return err; err = ddocMemAppendData(pBuf, p, -1); if(err) return err; err = ddocGen_endElem(pBuf, "ds:KeyName"); if(err) return err; } // / pCert = dencEncryptedKey_GetCertificate(pEncKey); if(pCert) { err = ddocGen_startElem(pBuf, "ds:X509Data"); if(err) return err; err = ddocGen_startElem(pBuf, "ds:X509Certificate"); if(err) return err; p = 0; err = getCertPEM(pCert, 0, &p); if(err) { if(p) free(p); return err; } if(p) { err = ddocMemAppendData(pBuf, p, -1); free(p); p = 0; if(err) return err; } err = ddocGen_endElem(pBuf, "ds:X509Certificate"); if(err) return err; err = ddocGen_endElem(pBuf, "ds:X509Data"); if(err) return err; } // end of element err = ddocGen_endElem(pBuf, "ds:KeyInfo"); if(err) return err; // transport key if(pEncKey->mbufTransportKey.pMem && pEncKey->mbufTransportKey.nLen) { l1 = 2 * pEncKey->mbufTransportKey.nLen; p = (char*)malloc(l1); if(!p) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(p, 0, l1); encode((const byte*)pEncKey->mbufTransportKey.pMem, pEncKey->mbufTransportKey.nLen, (byte*)p, &l1); if(p && l1) { err = ddocGen_startElem(pBuf, "denc:CipherData"); if(err) return err; err = ddocGen_startElem(pBuf, "denc:CipherValue"); if(err) return err; err = ddocMemAppendData(pBuf, p, -1); free(p); p = 0; if(err) return err; err = ddocGen_endElem(pBuf, "denc:CipherValue"); if(err) return err; err = ddocGen_endElem(pBuf, "denc:CipherData"); if(err) return err; } } // p = (char*)dencEncryptedKey_GetCarriedKeyName(pEncKey); if(p) { err = ddocGen_startElem(pBuf, "denc:CarriedKeyName"); if(err) return err; err = ddocMemAppendData(pBuf, p, -1); if(err) return err; err = ddocGen_endElem(pBuf, "denc:CarriedKeyName"); if(err) return err; } // end of element err = ddocGen_endElem(pBuf, "denc:EncryptedKey"); return err; } //-------------------------------------------------- // Generates XML for element // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencGenEncryptedData_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf) { int err = ERR_OK, l1; char* p; int i, n; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncData) // xml header err = ddocMemAppendData(pBuf, "", -1); if(err) return err; // start of element err = ddocGen_startElemBegin(pBuf, "denc:EncryptedData"); if(err) return err; // xmlns:denc //p = dencEncryptedData_GetXmlNs(pEncData); //if(p) err = ddocGen_addAtribute(pBuf, "xmlns:denc", DENC_XMLNS_XMLENC); if(err) return err; // Id atribute p = (char*)dencEncryptedData_GetId(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; // Type atribute p = (char*)dencEncryptedData_GetType(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "Type", p); if(err) return err; // MimeType atribute p = (char*)dencEncryptedData_GetMimeType(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "MimeType", p); if(err) return err; // Encoding ??? // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // p = (char*)dencEncryptedData_GetEncryptionMethod(pEncData); if(p) { err = ddocGen_startElemBegin(pBuf, "denc:EncryptionMethod"); if(err) return err; err = ddocGen_addAtribute(pBuf, "Algorithm", p); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; err = ddocGen_endElem(pBuf, "denc:EncryptionMethod"); if(err) return err; } n = dencEncryptedData_GetEncryptedKeyCount(pEncData); if(n > 0) { // err = ddocGen_startElemBegin(pBuf, "ds:KeyInfo"); if(err) return err; // xmlns ??? err = ddocGen_addAtribute(pBuf, "xmlns:ds", DENC_XMLNS_XMLDSIG); if(err) return err; err = ddocGen_startElemEnd(pBuf); if(err) return err; // for(i = 0; i < n; i++) { DEncEncryptedKey* pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i); if(pEncKey) { err = dencGenEncryptedKey_toXML(pEncKey, pBuf); if(err) return err; } } // end of element err = ddocGen_endElem(pBuf, "ds:KeyInfo"); if(err) return err; } // encrypted data if(pEncData->mbufEncryptedData.pMem && pEncData->mbufEncryptedData.nLen) { l1 = 2 * pEncData->mbufEncryptedData.nLen; p = (char*)malloc(l1); if(!p) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(p, 0, l1); encode((const byte*)pEncData->mbufEncryptedData.pMem, pEncData->mbufEncryptedData.nLen, (byte*)p, &l1); ddocDebug(4, "dencGenEncryptedData_toXML", "Input data: %d base64: %d", pEncData->mbufEncryptedData.nLen, l1); if(p && l1) { err = ddocGen_startElem(pBuf, "denc:CipherData"); if(err) return err; err = ddocGen_startElem(pBuf, "denc:CipherValue"); if(err) return err; err = ddocMemAppendData(pBuf, p, -1); free(p); p = 0; if(err) return err; err = ddocGen_endElem(pBuf, "denc:CipherValue"); if(err) return err; err = ddocGen_endElem(pBuf, "denc:CipherData"); if(err) return err; } } // if(dencEncryptedData_GetEncryptionPropertiesCount(pEncData) > 0) err = dencGenEncryptionProperties_toXML(pEncData, pBuf); if(err) return err; // end of element err = ddocGen_endElem(pBuf, "denc:EncryptedData"); return err; } //-------------------------------------------------- // Writes encrypted data to a file // pEncData - encrypted data object [REQUIRED] // szFileName - name of the file to write the data [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencGenEncryptedData_writeToFile(DEncEncryptedData* pEncData, const char* szFileName) { int err = ERR_OK; DigiDocMemBuf mbufEncData; FILE* hFile; #ifdef WIN32 wchar_t *convFileName = 0; int i= 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "ddocGenEncryptedData_writeToFile", "file: %s, conv-file: %s len: %d", szFileName, convFileName, i); #else char convFileName[1024]; ddocConvertFileName( convFileName, sizeof(convFileName), szFileName ); #endif ddocDebug(3, "dencGenEncryptedData_writeToFile", "filename: %s", szFileName); RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(szFileName) // start of element mbufEncData.pMem = 0; mbufEncData.nLen = 0; err = dencGenEncryptedData_toXML(pEncData, &mbufEncData); #ifdef WIN32 if(!err && (hFile = _wfopen(convFileName, L"wb")) != NULL) { #else if(!err && (hFile = fopen(convFileName, "wb")) != NULL) { #endif fwrite(mbufEncData.pMem, mbufEncData.nLen, 1, hFile); fclose(hFile); } else { SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); ddocDebug(1, "dencGenEncryptedData_writeToFile", "Error writing encrypted document"); } // cleanup ddocMemBuf_free(&mbufEncData); return err; } //-------------------------------------------------- // Generates the header of XML for element // This contains everything upto the start of base64 encoded cipher data // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptedData_header_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf) { int err = ERR_OK; char* p; int i, n; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncData) // xml header err = ddocMemAppendData(pBuf, "", -1); if(err) return err; // start of element err = ddocGen_startElemBegin(pBuf, "denc:EncryptedData"); if(err) return err; // xmlns:denc //p = dencEncryptedData_GetXmlNs(pEncData); //if(p) err = ddocGen_addAtribute(pBuf, "xmlns:denc", DENC_XMLNS_XMLENC); if(err) return err; // Id atribute p = (char*)dencEncryptedData_GetId(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; // Type atribute p = (char*)dencEncryptedData_GetType(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "Type", p); if(err) return err; // MimeType atribute p = (char*)dencEncryptedData_GetMimeType(pEncData); if(p) err = ddocGen_addAtribute(pBuf, "MimeType", p); if(err) return err; // Encoding ??? // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // p = (char*)dencEncryptedData_GetEncryptionMethod(pEncData); if(p) { err = ddocGen_startElemBegin(pBuf, "denc:EncryptionMethod"); if(err) return err; err = ddocGen_addAtribute(pBuf, "Algorithm", p); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; err = ddocGen_endElem(pBuf, "denc:EncryptionMethod"); if(err) return err; } n = dencEncryptedData_GetEncryptedKeyCount(pEncData); if(n > 0) { // err = ddocGen_startElemBegin(pBuf, "ds:KeyInfo"); if(err) return err; // xmlns ??? err = ddocGen_addAtribute(pBuf, "xmlns:ds", DENC_XMLNS_XMLDSIG); if(err) return err; err = ddocGen_startElemEnd(pBuf); if(err) return err; // for(i = 0; i < n; i++) { DEncEncryptedKey* pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i); if(pEncKey) { err = dencGenEncryptedKey_toXML(pEncKey, pBuf); if(err) return err; } } // end of element err = ddocGen_endElem(pBuf, "ds:KeyInfo"); if(err) return err; } // encrypted data err = ddocGen_startElem(pBuf, "denc:CipherData"); if(err) return err; err = ddocGen_startElem(pBuf, "denc:CipherValue"); // here would come the base64 encoded cipher data return err; } //-------------------------------------------------- // Generates the trailer of XML for element // These are all the XML constructs following the // base64 encoded cipher data. // pEncData - encrypted data object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencGenEncryptedData_trailer_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pEncData) // here ends the base64 encoded cipher data err = ddocGen_endElem(pBuf, "denc:CipherValue"); if(err) return err; err = ddocGen_endElem(pBuf, "denc:CipherData"); if(err) return err; // if(dencEncryptedData_GetEncryptionPropertiesCount(pEncData) > 0) err = dencGenEncryptionProperties_toXML(pEncData, pBuf); if(err) return err; // end of element err = ddocGen_endElem(pBuf, "denc:EncryptedData"); return err; } libdigidoc-3.10.5/libdigidoc/DlgUnit.manifest0000664000372000037200000000121013560273131020455 0ustar travistravis TestDlg libdigidoc-3.10.5/libdigidoc/DigiDocObj.c0000664000372000037200000046566113560273131017510 0ustar travistravis//================================================== // FILE: DigiDocObj.c // PROJECT: Digi Doc // DESCRIPTION: DigiDoc helper routines for accessing dogidoc data // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 26.04.2006 Veiko Sinivee // Creation //================================================== #include "DigiDocObj.h" #include "DigiDocGen.h" #include "DigiDocError.h" #include "DigiDocConvert.h" #include "DigiDocDebug.h" #include "DigiDocCert.h" #include "DigiDocOCSP.h" #include "DigiDocConfig.h" #include "DigiDocError.h" #include #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x10010000L static EVP_MD_CTX *EVP_MD_CTX_new() { return (EVP_MD_CTX*)OPENSSL_malloc(sizeof(EVP_MD_CTX)); } static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { OPENSSL_free(ctx); } static int OCSP_resp_get0_id(const OCSP_BASICRESP *bs, const ASN1_OCTET_STRING **pid, const X509_NAME **pname) { *pid = NULL; *pname = NULL; if(!bs || !bs->tbsResponseData) return 0; const OCSP_RESPID *rid = bs->tbsResponseData->responderId; if (rid->type == V_OCSP_RESPID_NAME) *pname = rid->value.byName; else if (rid->type == V_OCSP_RESPID_KEY) *pid = rid->value.byKey; else return 0; return 1; } static const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP* bs) { return bs && bs->tbsResponseData ? bs->tbsResponseData->producedAt : NULL; } static const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single) { return single ? single->certId : NULL; } static const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs) { return bs ? bs->signature : NULL; } #endif //============================================================ // Sets a string element of a struct to a new value // dest - element pointer // value - new value // valLen - value length (use -1 for null terminated strings) //============================================================ EXP_OPTION int setString(char** dest, const char* value, int valLen) { RETURN_IF_NULL_PARAM(dest); RETURN_IF_NULL_PARAM(value); if(*dest) { free(*dest); *dest = NULL; } if(valLen == -1) { *dest = (char*)malloc(strlen(value)+1); RETURN_IF_BAD_ALLOC(*dest); strncpy(*dest, value, strlen(value)+1); } else { *dest = (char*)malloc(valLen); RETURN_IF_BAD_ALLOC(*dest); memcpy(*dest, value, valLen); } return ERR_OK; } //============================================================ // Allocates a new SignedDoc element and initializes it // format - format name // version - format version //============================================================ EXP_OPTION int SignedDoc_new(SignedDoc **pSignedDoc, const char* format, const char* version) { SignedDoc* pSigDoc = NULL; RETURN_IF_NULL_PARAM(format); RETURN_IF_NULL_PARAM(version); ddocDebug(3, "SignedDoc_new", "format: %s version: %s", (format ? format : "NULL"), (version ? version : "NULL")); pSigDoc = (SignedDoc*)malloc(sizeof(SignedDoc)); RETURN_IF_BAD_ALLOC(pSigDoc); memset(pSigDoc, 0, sizeof(SignedDoc)); if(!strcmp(format, DIGIDOC_XML_1_1_NAME) && !strcmp(version, DIGIDOC_XML_1_3_VER)) { setString(&(pSigDoc->szFormat), format, -1); setString(&(pSigDoc->szFormatVer), version, -1); setString(&(pSigDoc->szFileName), "", -1); } else { ddocDebug(3, "SignedDoc_new", "unsupported version"); SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_FORMAT); } *pSignedDoc = pSigDoc; return ERR_OK; } //============================================================ // Frees the memory of SignedDoc element // pSigDoc - element to free //============================================================ EXP_OPTION void SignedDoc_free(SignedDoc* pSigDoc) { int i; RETURN_VOID_IF_NULL(pSigDoc); for(i = 0; (pSigDoc->pDataFiles != NULL) && (i < pSigDoc->nDataFiles); i++) DataFile_free(pSigDoc->pDataFiles[i]); if(pSigDoc->pDataFiles) free(pSigDoc->pDataFiles); for(i = 0; (pSigDoc->pSignatures != NULL) && (i < pSigDoc->nSignatures); i++) SignatureInfo_free(pSigDoc->pSignatures[i]); if(pSigDoc->pSignatures) free(pSigDoc->pSignatures); if(pSigDoc->szFormat) free(pSigDoc->szFormat); if(pSigDoc->szFormatVer) free(pSigDoc->szFormatVer); if(pSigDoc->szFileName) free(pSigDoc->szFileName); if(pSigDoc->szProfile) free(pSigDoc->szProfile); if(pSigDoc) free(pSigDoc); } //============================================================ // Returns the number of data files // pSigDoc - signed doc pointer //============================================================ EXP_OPTION int getCountOfDataFiles(const SignedDoc* pSigDoc) { RETURN_OBJ_IF_NULL(pSigDoc, 0); return pSigDoc->nDataFiles; } //============================================================ // Returns the next free data file id // pSigDoc - signed doc pointer //============================================================ EXP_OPTION int getNextDataFileId(const SignedDoc* pSigDoc) { int id = 0, n, i; RETURN_OBJ_IF_NULL(pSigDoc, 0); for(i = 0; i < pSigDoc->nDataFiles; i++) { DataFile* pDataFile = pSigDoc->pDataFiles[i]; RETURN_OBJ_IF_NULL(pDataFile, 0); RETURN_OBJ_IF_NULL(pDataFile->szId, 0); SET_LAST_ERROR_RETURN_IF_NOT(strlen(pDataFile->szId) > 1, ERR_EMPTY_STRING, 0); n = atoi(pDataFile->szId+1); if(id <= n) id = n+1; } return id; } //============================================================ // Returns the desired DataFile object // pSigDoc - signed doc pointer // nIdx - DataFile index (starting with 0) //============================================================ EXP_OPTION DataFile* getDataFile(const SignedDoc* pSigDoc, int nIdx) { RETURN_OBJ_IF_NULL(pSigDoc, NULL); SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigDoc->nDataFiles, ERR_BAD_DATAFILE_INDEX, NULL); RETURN_OBJ_IF_NULL(pSigDoc->pDataFiles[nIdx], 0); return pSigDoc->pDataFiles[nIdx]; } //============================================================ // Returns the last DataFile object // pSigDoc - signed doc pointer //============================================================ EXP_OPTION DataFile* ddocGetLastDataFile(const SignedDoc* pSigDoc) { int nIdx; RETURN_OBJ_IF_NULL(pSigDoc, NULL); nIdx = pSigDoc->nDataFiles - 1; SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0, ERR_BAD_DATAFILE_INDEX, NULL); RETURN_OBJ_IF_NULL(pSigDoc->pDataFiles[nIdx], 0); return pSigDoc->pDataFiles[nIdx]; } //============================================================ // Returns the DataFile object with the given id // pSigDoc - signed doc pointer // id - DataFile id //============================================================ EXP_OPTION DataFile* getDataFileWithId(const SignedDoc* pSigDoc, const char* id) { DataFile* pDataFile = NULL; int i; //AA 12.11.2003 RETURN_OBJ_IF_NULL(id, NULL); RETURN_OBJ_IF_NULL(pSigDoc, NULL); ddocDebug(4, "getDataFileWithId", "id: \'%s\', files: %d", id, pSigDoc->nDataFiles); for(i = 0; i < pSigDoc->nDataFiles; i++) { RETURN_OBJ_IF_NULL(pSigDoc->pDataFiles[i], NULL); RETURN_OBJ_IF_NULL(pSigDoc->pDataFiles[i]->szId, NULL); if(!strcmp(pSigDoc->pDataFiles[i]->szId, id)) { pDataFile = pSigDoc->pDataFiles[i]; break; } } return pDataFile; } //============================================================ // Adds a new DataFile element to a SignedDoc element and initializes it // pSigDoc - signed document // id - data file id // filename - filename // contentType - EMBEDDED or EMBEDDED_BASE64 // mime - mime type // size - file size // digType - digestType // digest - file digest (SHA1) // digLen - digest length //============================================================ EXP_OPTION int DataFile_new(DataFile **newDataFile, SignedDoc* pSigDoc, const char* id, const char* filename, const char* contentType, const char* mime, long size, const byte* digest, int digLen, const char* digType, const char* szCharset) { char buf1[300]; int nId = 0, i, j, n; DataFile **pDataFiles; DataFile *pDataFile; FILE* hFile; RETURN_IF_NULL_PARAM(newDataFile); RETURN_IF_NULL_PARAM(pSigDoc); ddocDebug(3, "DataFile_new", "SigDoc ver: %s, file: %s, contentType: %s, mimeType: %s", (pSigDoc ? pSigDoc->szFormatVer : "NULL"), (filename ? filename : "NULL"), contentType, mime); //clearErrors(); if(!id) nId = getNextDataFileId(pSigDoc); if(pSigDoc->nDataFiles == 0) { SET_LAST_ERROR_RETURN_IF_NOT(!pSigDoc->pDataFiles, ERR_BAD_DATAFILE_COUNT, 0); pSigDoc->nDataFiles = 1; } else pSigDoc->nDataFiles++; pDataFiles = (DataFile**)malloc((pSigDoc->nDataFiles) * sizeof(void *)); RETURN_IF_BAD_ALLOC(pDataFiles); for(i = 0; i < pSigDoc->nDataFiles-1; i++) pDataFiles[i] = pSigDoc->pDataFiles[i]; pDataFile = (DataFile*)malloc(sizeof(DataFile)); RETURN_IF_BAD_ALLOC(pDataFile); memset(pDataFile, 0, sizeof(DataFile)); pDataFiles[pSigDoc->nDataFiles-1] = pDataFile; if(pSigDoc->pDataFiles) free(pSigDoc->pDataFiles); pSigDoc->pDataFiles = pDataFiles; if(id) { j = 0; n = strlen(id); if(n < 2 || id[0] != 'D') j = -1; if(j == 0 && n >= 2 && !isdigit(id[1]) && id[1] != 'O') j = -1; for(i = 2; j == 0 && i < n; i++) if(!isdigit(id[i])) j = -1; if(j == -1) { ddocDebug(1, "DataFile_new", "Invalid DataFile id: %s", id); SET_LAST_ERROR(ERR_BAD_PARAM); } setString(&(pDataFile->szId), id, -1); } else { snprintf(buf1, sizeof(buf1), "D%d", nId); setString(&(pDataFile->szId), buf1, -1); } if(szCharset) setString(&(pDataFile->szCharset), szCharset, -1); else setString(&(pDataFile->szCharset), CHARSET_ISO_8859_1, -1); if(filename) { // in versions 1.0, 1.1 and 1.2 we used wrong encoding for OEM windows charset setString(&(pDataFile->szFileName), filename, -1); if(!strcmp(contentType, CONTENT_EMBEDDED)) { if((hFile = fopen(pDataFile->szFileName, "rt")) != NULL) { fgets(buf1, sizeof(buf1), hFile); if(strstr(buf1, "szMimeType), mime, -1); if((!contentType || strcmp(contentType, CONTENT_EMBEDDED_BASE64)) && !ConfigItem_lookup_bool("EMBEDDED_XML_SUPPORT", 0)) { SET_LAST_ERROR(ERR_BAD_DATAFILE_CONTENT_TYPE); return ERR_BAD_DATAFILE_CONTENT_TYPE; } if(contentType) setString(&(pDataFile->szContentType), contentType, -1); pDataFile->nSize = size; if(digType && strlen(digType)) setString(&(pDataFile->szDigestType), digType, -1); if(digest && digLen) ddocMemAssignData(&(pDataFile->mbufDigest), (const char*)digest, digLen); *newDataFile = pDataFile; return ERR_OK; } //============================================================ // Removes this DataFile from signed doc and frees it's memory // pSigDoc - signed doc object // id - DataFile id to be removed //============================================================ EXP_OPTION int DataFile_delete(SignedDoc* pSigDoc, const char* id) { int err = ERR_OK, n, i, j; DataFile* pDataFile = NULL; DataFile** pDataFiles = NULL; RETURN_IF_NULL_PARAM(pSigDoc); ddocDebug(3, "DataFile_delete", "id: %s", id); if(pSigDoc->nSignatures > 0) SET_LAST_ERROR_RETURN_CODE(ERR_MODIFY_SIGNED_DOC); if((pDataFile = getDataFileWithId(pSigDoc, id)) != 0) { n = pSigDoc->nDataFiles - 1; if(n > 0) { pDataFiles = (DataFile**)malloc(n * sizeof(void*)); RETURN_IF_BAD_ALLOC(pDataFiles); for(i = j = 0; i < pSigDoc->nDataFiles; i++) { if(strcmp(pSigDoc->pDataFiles[i]->szId, id)) pDataFiles[j++] = pSigDoc->pDataFiles[i]; else{ DataFile_free(pSigDoc->pDataFiles[i]);} } free(pSigDoc->pDataFiles); pSigDoc->pDataFiles = pDataFiles; pSigDoc->nDataFiles = n; } else { for(i = 0; i < pSigDoc->nDataFiles; i++){ DataFile_free(pSigDoc->pDataFiles[i]);} free(pSigDoc->pDataFiles); pSigDoc->pDataFiles = NULL; pSigDoc->nDataFiles = 0; } } else err = ERR_BAD_DATAFILE_INDEX; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // Retrieve and convert cached DataFile data if possible // pSigDoc - signed document object // szDocId - datafile id // ppBuf - address of buffer pointer // pLen - address of lenght of bytes //============================================================ EXP_OPTION int ddocGetDataFileCachedData(SignedDoc* pSigDoc, const char* szDocId, void** ppBuf, long* pLen) { DataFile* pDf; DigiDocMemBuf mbuf1; int err1 = 0; mbuf1.pMem = 0; mbuf1.nLen = 0; //RETURN_IF_NULL_PARAM(pSigDoc); // if null then don't check for cached data (old logic) RETURN_IF_NULL_PARAM(szDocId); RETURN_IF_NULL_PARAM(ppBuf); RETURN_IF_NULL_PARAM(pLen); *ppBuf = 0; *pLen = 0; if(pSigDoc) { pDf = getDataFileWithId(pSigDoc, szDocId); if(pDf && pDf->mbufContent.pMem) { // gotcha! int len; // base64 content, allocate exact length and initialize if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64)) { err1 = ddocMemSetLength(&mbuf1, pDf->mbufContent.nLen); if(err1) { ddocMemBuf_free(&mbuf1); return err1; } *ppBuf = mbuf1.pMem; *pLen = mbuf1.nLen; err1 = ddocDecodeBase64(&(pDf->mbufContent), &mbuf1); if(err1) { ddocMemBuf_free(&mbuf1); return err1; } mbuf1.pMem = 0; mbuf1.nLen = 0; // release ownership } // simple text content. Make it zero terminated string else if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED)) { *ppBuf = malloc(pDf->mbufContent.nLen+1); RETURN_IF_BAD_ALLOC(*ppBuf); *pLen = pDf->mbufContent.nLen; memcpy(*ppBuf, pDf->mbufContent.pMem, pDf->mbufContent.nLen); ((char*)(*ppBuf))[*pLen] = 0; } } } return ERR_OK; } //============================================================ // Retrieve and convert DataFile Filename atribute and convert // to proper UTF-8 if necessary. // pSigDoc - signed document object // szDocId - datafile id // ppBuf - address of buffer pointer. Caller must free the buffer // pLen - address of lenght of bytes. Will be changed. //============================================================ EXP_OPTION int ddocGetDataFileFilename(SignedDoc* pSigDoc, const char* szDocId, void** ppBuf, int* pLen) { DataFile* pDf; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(szDocId); RETURN_IF_NULL_PARAM(ppBuf); RETURN_IF_NULL_PARAM(pLen); *ppBuf = 0; *pLen = 0; if(pSigDoc) { pDf = getDataFileWithId(pSigDoc, szDocId); if(pDf && pDf->szFileName) { // gotcha! *ppBuf = unescapeXmlsym((const char*)pDf->szFileName); *pLen = strlen((const char*)*ppBuf); // in version 1.2 and earlier we had bad UTF-8 for some chars // check and fix it for newer clients if((!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) { convWinToFName(pDf->szFileName, (char*)*ppBuf, *pLen+1); } } } return ERR_OK; } //-------------------------------------------------- // Checks if the size of this DataFile is less than // max size for memory cache and if so caches the data. // pDf - DataFile object // maxLen - max cacheable DataFile size // value - character values read from file // len - length of chars ??? // isBase64 - is allready in base64 form or not (1/0) //-------------------------------------------------- EXP_OPTION void ddocAppendDataFileData(DataFile* pDf, int maxLen, void* data, int len, int isBase64) { DigiDocMemBuf mbuf1, mbuf2; mbuf1.pMem = 0; mbuf1.nLen = 0; ddocDebug(5, "ddocAppendDataFileData", "append: %d, max: %d", len, maxLen); if(pDf && pDf->nSize < maxLen) { ddocDebug(6, "ddocAppendDataFileData", "DF: %s, size: %d, max: %d", pDf->szId, pDf->nSize, maxLen); // original content must be kept in the form it will exist in file if(!strcmp(pDf->szContentType, CONTENT_EMBEDDED_BASE64) && !isBase64) { mbuf2.pMem = data; mbuf2.nLen = len; ddocEncodeBase64(&mbuf2, &mbuf1); ddocMemAppendData(&(pDf->mbufContent), mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); } else ddocMemAppendData(&(pDf->mbufContent), data, len); } } //-------------------------------------------------- // Creates new DataFile and assigns contet from memory // ppDataFile address of pointer to return new DataFile object // pSigDoc - SignedDoc object // id - new DataFile id. Use NULL for default // filename - filename // contentType - content type // mime - mime type // pData - address of DataFile content to be assigned // size - length of data in bytes // return error code //-------------------------------------------------- EXP_OPTION int createDataFileInMemory(DataFile **ppDataFile, SignedDoc* pSigDoc, const char* id, const char* filename, const char* contentType, const char* mime, const char* pData, long size) { int err = ERR_OK; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; err = DataFile_new(ppDataFile, pSigDoc, id, filename, contentType, mime, size, NULL, 0, DIGEST_SHA1_NAME, NULL); if(!err && pData) { ddocAppendDataFileData(*ppDataFile, size+1, (void*)pData, size, 0); // calculate hash so it can be used in signing err = generateDataFileXML(pSigDoc, *ppDataFile, NULL, NULL, &mbuf1); ddocMemBuf_free(&mbuf1); } return err; } //============================================================ // cleanup DataFile memory // pDataFile - data file object to be cleaned up //============================================================ EXP_OPTION void DataFile_free(DataFile* pDataFile) { int i=0; RETURN_VOID_IF_NULL(pDataFile); if(pDataFile->szId) free(pDataFile->szId); if(pDataFile->szFileName) free(pDataFile->szFileName); if(pDataFile->szMimeType) free(pDataFile->szMimeType); if(pDataFile->szDigestType) free(pDataFile->szDigestType); ddocMemBuf_free(&(pDataFile->mbufDigest)); ddocMemBuf_free(&(pDataFile->mbufWrongDigest)); ddocMemBuf_free(&(pDataFile->mbufDetachedDigest)); if(pDataFile->szContentType) free(pDataFile->szContentType); for(i = 0; i < pDataFile->nAttributes; i++) { free(pDataFile->pAttNames[i]); free(pDataFile->pAttValues[i]); } if(pDataFile->szCharset) free(pDataFile->szCharset); if(pDataFile->pAttNames) free(pDataFile->pAttNames); if(pDataFile->pAttValues) free(pDataFile->pAttValues); ddocMemBuf_free(&(pDataFile->mbufContent)); free(pDataFile); } //-------------------------------------------------- // Accessor for Digest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocDataFile_GetDigestValue(DataFile* pDataFile) { RETURN_OBJ_IF_NULL(pDataFile, NULL) return &(pDataFile->mbufDigest); } //-------------------------------------------------- // Mutatoror for Digest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDataFile_SetDigestValue(DataFile* pDataFile, const char* value, long len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pDataFile) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignData(&(pDataFile->mbufDigest), value, len); return err; } //-------------------------------------------------- // Accessor for DetachedDigest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocDataFile_GetDetachedDigestValue(DataFile* pDataFile) { RETURN_OBJ_IF_NULL(pDataFile, NULL) return &(pDataFile->mbufDetachedDigest); } //-------------------------------------------------- // Mutatoror for DetachedDigest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDataFile_SetDetachedDigestValue(DataFile* pDataFile, const char* value, long len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pDataFile) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignData(&(pDataFile->mbufDetachedDigest), value, len); return err; } //-------------------------------------------------- // Accessor for WrongDigest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocDataFile_GetWrongDigestValue(DataFile* pDataFile) { RETURN_OBJ_IF_NULL(pDataFile, NULL) return &(pDataFile->mbufWrongDigest); } //-------------------------------------------------- // Mutatoror for WrongDigest atribute of DataFile object. // pDataFile - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDataFile_SetWrongDigestValue(DataFile* pDataFile, const char* value, long len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pDataFile) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignData(&(pDataFile->mbufWrongDigest), value, len); return err; } //============================================================ // Removes this NotaryInfo from signed doc and frees it's memory // pSigInfo - signature object // id - notary id to be removed //============================================================ EXP_OPTION int NotaryInfo_delete(SignatureInfo* pSigInfo) { RETURN_IF_NULL_PARAM(pSigInfo); if(pSigInfo->pNotary) { NotaryInfo_free(pSigInfo->pNotary); pSigInfo->pNotary = 0; } return ERR_OK; } //============================================================ // Returns number of DataFile attributes // pDataFile - data file //============================================================ EXP_OPTION int getCountOfDataFileAttributes(const DataFile* pDataFile) { RETURN_OBJ_IF_NULL(pDataFile, -1); return pDataFile->nAttributes; } //============================================================ // Adds an attribute to data file // pDataFile - data file // name - attribute name // value - attribute value //============================================================ // FIXME : Badly in need for a rewrite - memory leaks, when something fails. int addDataFileAttribute(DataFile* pDataFile, const char* name, const char* value) { char **pp; int i; RETURN_IF_NULL_PARAM(pDataFile); RETURN_IF_NULL_PARAM(name); RETURN_IF_NULL_PARAM(value); if(pDataFile->nAttributes == 0) { RETURN_IF_NOT(!pDataFile->pAttNames, ERR_BAD_ATTR_COUNT); RETURN_IF_NOT(!pDataFile->pAttValues, ERR_BAD_ATTR_COUNT); pDataFile->nAttributes = 1; } else pDataFile->nAttributes++; // set name pp = (char**)malloc((pDataFile->nAttributes) * sizeof(char *)); RETURN_IF_BAD_ALLOC(pp); for(i = 0; i < pDataFile->nAttributes-1; i++) pp[i] = pDataFile->pAttNames[i]; if(pDataFile->pAttNames) free(pDataFile->pAttNames); pDataFile->pAttNames = pp; pp[pDataFile->nAttributes-1] = NULL; setString(&(pp[pDataFile->nAttributes-1]), name, -1); // set value pp = (char**)malloc((pDataFile->nAttributes) * sizeof(char *)); RETURN_IF_BAD_ALLOC(pp); for(i = 0; i < pDataFile->nAttributes-1; i++) pp[i] = pDataFile->pAttValues[i]; if(pDataFile->pAttValues) free(pDataFile->pAttValues); pDataFile->pAttValues = pp; pp[pDataFile->nAttributes-1] = NULL; setString(&(pp[pDataFile->nAttributes-1]), value, -1); return ERR_OK; } //============================================================ // Gets an attribute of a data file // pDataFile - data file // name - buffer for attribute name pointer // value - buffer for attribute value pointer //============================================================ EXP_OPTION int getDataFileAttribute(DataFile* pDataFile, int idx, char** name, char** value) { RETURN_IF_NULL_PARAM(pDataFile); RETURN_IF_NOT(idx < pDataFile->nAttributes, ERR_BAD_ATTR_INDEX); RETURN_IF_NULL_PARAM(name); RETURN_IF_NULL_PARAM(value); *name = pDataFile->pAttNames[idx]; *value = pDataFile->pAttValues[idx]; return ERR_OK; } //============================================================ // Calculates the file size and digest // pSigDoc - signed document // id - data file id // filename - filename // digType - digestType (code) //============================================================ EXP_OPTION int calculateDataFileSizeAndDigest(SignedDoc* pSigDoc, const char* id, const char* filename, int digType) { int err = ERR_OK, len1 = 0; char buf1[DIGEST_LEN+2]; long len2 = 0; DataFile* pDataFile; RETURN_IF_NULL_PARAM(pSigDoc); ddocDebug(3, "calculateDataFileSizeAndDigest", "File: %s id: %s", filename, id); pDataFile = getDataFileWithId(pSigDoc, id); RETURN_IF_NOT(pDataFile, ERR_FILE_READ); if(digType == DIGEST_SHA1) { // in version 1.0 we use DigestType and DigestValue // attrributes of DataFile element and calculate the digest // over the original content if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) && !strcmp(pSigDoc->szFormatVer, SK_XML_1_VER)) { len1 = sizeof(buf1); err = calculateFileDigest(filename, digType, (byte*)buf1, &len1, &len2); RETURN_IF_NOT(err == ERR_OK, err); ddocDataFile_SetDigestValue(pDataFile, buf1, len1); pDataFile->nSize = len2; } // in version 1.1 we don't use those attributes // and we calculate the digest over the whole // DataFile element including the tags else { err = calculateFileSize(filename, &pDataFile->nSize); ddocDebug(4, "calculateDataFileSizeAndDigest", "File: %s size: %d", filename, pDataFile->nSize); err = generateDataFileXML(pSigDoc, pDataFile, filename, NULL, NULL); } } else SET_LAST_ERROR_RETURN_CODE(ERR_UNSUPPORTED_DIGEST); return err; } //=======================< DigestValue >===================================== //-------------------------------------------------- // "Constructor" of DigestValue object // ppDigestValue - address of buffer for newly allocated object [REQUIRED] // szDigestMethod - digest method [OPTIONAL] // szDigVal/lDigLen - digest value and length [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDigestValue_new(DigestValue** ppDigestValue, const char* szDigestMethod, void* szDigVal, long lDigLen) { int err = ERR_OK; // check input parameters ddocDebug(4, "ddocDigestValue_new", "DigestMethod: %s, dig-len: %ld", (szDigestMethod ? szDigestMethod : "NULL"), lDigLen); RETURN_IF_NULL_PARAM(ppDigestValue); *ppDigestValue = 0; // mark as not yet allocated // allocate memory for new DigestValue *ppDigestValue = (DigestValue*)malloc(sizeof(DigestValue)); if(!(*ppDigestValue)) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(*ppDigestValue, 0, sizeof(DigestValue)); // set optional fields if(szDigestMethod) { err = ddocMemAssignString((char**)&((*ppDigestValue)->szDigestMethod), szDigestMethod); if(err) return err; } else { // default is sha1 err = ddocMemAssignString((char**)&((*ppDigestValue)->szDigestMethod), DIGEST_METHOD_SHA1); } if(szDigVal && lDigLen) err = ddocMemAssignData(&((*ppDigestValue)->mbufDigestValue), szDigVal, lDigLen); return err; } //-------------------------------------------------- // "Destructor" of DigestValue object // pDigestValue - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDigestValue_free(DigestValue* pDigestValue) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pDigestValue) // cleanup this object if(pDigestValue->szDigestMethod) free(pDigestValue->szDigestMethod); ddocMemBuf_free(&(pDigestValue->mbufDigestValue)); free(pDigestValue); return err; } //-------------------------------------------------- // Accessor for DigestMethod atribute of DigestValue object. // pDigestValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocDigestValue_GetDigestMethod(DigestValue* pDigestValue) { RETURN_OBJ_IF_NULL(pDigestValue, NULL) return pDigestValue->szDigestMethod; } //-------------------------------------------------- // Mutatoror for DigestMethod atribute of DigestValue object. // pDigestValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDigestValue_SetDigestMethod(DigestValue* pDigestValue, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pDigestValue) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pDigestValue->szDigestMethod), value); return err; } //-------------------------------------------------- // Accessor for DigestValue atribute of DigestValue object. // pDigestValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocDigestValue_GetDigestValue(DigestValue* pDigestValue) { RETURN_OBJ_IF_NULL(pDigestValue, NULL) return &(pDigestValue->mbufDigestValue); } //-------------------------------------------------- // Mutatoror for DigestValue atribute of DigestValue object. // pDigestValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocDigestValue_SetDigestValue(DigestValue* pDigestValue, const char* value, long len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pDigestValue) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignData(&(pDigestValue->mbufDigestValue), value, len); return err; } //-------------------------------------------------- // Compares two DigestValue structure on equality // pDigest1 - address of first digest [REQUIRED] // pDigest2 - address of second digest [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCompareDigestValues(DigestValue* pDigest1, DigestValue* pDigest2) { RETURN_IF_NULL_PARAM(pDigest1) RETURN_IF_NULL_PARAM(pDigest2) return compareByteArrays((const byte*)pDigest1->mbufDigestValue.pMem, pDigest1->mbufDigestValue.nLen, (const byte*)pDigest2->mbufDigestValue.pMem, pDigest2->mbufDigestValue.nLen); } //-------------------------------------------------- // Generates XML for element // pSigDoc - signed doc object [REQUIRED] // pDigestValue - DigestValue object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocDigestValue_toXML(const DigestValue* pDigestValue, DigiDocMemBuf* pBuf) { int err = ERR_OK; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pDigestValue) mbuf1.pMem = 0; mbuf1.nLen = 0; // DigestMethod if(pDigestValue->szDigestMethod) { err = ddocGen_startElemBegin(pBuf, "DigestMethod"); if(err) return err; // Algorithm atribute err = ddocGen_addAtribute(pBuf, "Algorithm", pDigestValue->szDigestMethod); if(err) return err; //err = ddocGen_startElemEnd(pBuf); //err = ddocGen_endElem(pBuf, "DigestMethod"); // end of element start tag err = ddocMemAppendData(pBuf, "/>\n", -1); } if(pDigestValue->mbufDigestValue.pMem) { err = ddocGen_startElem(pBuf, "DigestValue"); } if(err) return err; // digest value ddocEncodeBase64(&(pDigestValue->mbufDigestValue), &mbuf1); //AM 17.11.08 to remove newline after base64 if(mbuf1.pMem && ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] == '\n') ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] = 0; err = ddocMemAppendData(pBuf, (char*)mbuf1.pMem, -1); ddocMemBuf_free(&mbuf1); if(err) return err; err = ddocGen_endElem(pBuf, "DigestValue"); err = ddocMemAppendData(pBuf, "\n", -1); return err; } //======================< SignatureValue >==================================== //-------------------------------------------------- // "Constructor" of SignatureValue object // ppSignatureValue - address of buffer for newly allocated object [REQUIRED] // szId - Id atribute value [OPTIONAL] // szType - signature type [OPTIONAL] // szDigVal/lDigLen - digest value and length [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_new(SignatureValue** ppSignatureValue, const char* szId, const char* szType, void* szSigVal, long lSigLen) { int err = ERR_OK; // check input parameters ddocDebug(4, "ddocSignatureValue_new", "id: %s, type: %s, dig-len: %ld", (szId ? szId : "NULL"), (szType ? szType : "NULL"), lSigLen); RETURN_IF_NULL_PARAM(ppSignatureValue); *ppSignatureValue = 0; // mark as not yet allocated // allocate memory for new DigestValue *ppSignatureValue = (SignatureValue*)malloc(sizeof(SignatureValue)); if(!(*ppSignatureValue)) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(*ppSignatureValue, 0, sizeof(SignatureValue)); // set optional fields if(szId) { err = ddocMemAssignString((char**)&((*ppSignatureValue)->szId), szId); if(err) return err; } if(szType) { err = ddocMemAssignString((char**)&((*ppSignatureValue)->szType), szType); if(err) return err; } if(szSigVal && lSigLen) err = ddocMemAssignData(&((*ppSignatureValue)->mbufSignatureValue), szSigVal, lSigLen); return err; } //-------------------------------------------------- // "Destructor" of SignatureValue object // pSignatureValue - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_free(SignatureValue* pSignatureValue) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pSignatureValue) // cleanup this object if(pSignatureValue->szId) free(pSignatureValue->szId); if(pSignatureValue->szType) free(pSignatureValue->szType); ddocMemBuf_free(&(pSignatureValue->mbufSignatureValue)); free(pSignatureValue); return err; } //-------------------------------------------------- // Accessor for Id atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocSignatureValue_GetId(const SignatureValue* pSignatureValue) { RETURN_OBJ_IF_NULL(pSignatureValue, NULL) return pSignatureValue->szId; } //-------------------------------------------------- // Mutatoror for Id atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_SetId(SignatureValue* pSignatureValue, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pSignatureValue) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pSignatureValue->szId), value); return err; } //-------------------------------------------------- // Accessor for Type atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocSignatureValue_GetType(const SignatureValue* pSignatureValue) { RETURN_OBJ_IF_NULL(pSignatureValue, NULL) return pSignatureValue->szType; } //-------------------------------------------------- // Mutatoror for Type atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_SetType(SignatureValue* pSignatureValue, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pSignatureValue) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pSignatureValue->szType), value); return err; } //-------------------------------------------------- // Accessor for SignatureValue atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocSignatureValue_GetSignatureValue(const SignatureValue* pSignatureValue) { RETURN_OBJ_IF_NULL(pSignatureValue, NULL) return &(((SignatureValue*)pSignatureValue)->mbufSignatureValue); } //-------------------------------------------------- // Mutatoror for SignatureValue atribute of SignatureValue object. // pSignatureValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSignatureValue_SetSignatureValue(SignatureValue* pSignatureValue, const char* value, long len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pSignatureValue) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignData(&(pSignatureValue->mbufSignatureValue), value, len); return err; } //-------------------------------------------------- // Generates XML for element // pSignatureValue - SignatureValue object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocSignatureValue_toXML(const SignatureValue* pSignatureValue, DigiDocMemBuf* pBuf) { int err = ERR_OK; char* p; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pBuf) //RETURN_IF_NULL_PARAM(pSignatureValue) mbuf1.pMem = 0; mbuf1.nLen = 0; // start of element err = ddocGen_startElemBegin(pBuf, "SignatureValue"); if(err) return err; // Id atribute if(pSignatureValue) { p = (char*)ddocSignatureValue_GetId(pSignatureValue); if(p) err = ddocGen_addAtribute(pBuf, "Id", p); if(err) return err; } // end of element start tag err = ddocGen_startElemEnd(pBuf); //err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // signature value if(pSignatureValue) { ddocEncodeBase64(ddocSignatureValue_GetSignatureValue(pSignatureValue), &mbuf1); //AM 17.11.08 to remove newline after base64 if(mbuf1.pMem && ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] == '\n') ((char*)mbuf1.pMem)[strlen((const char*)mbuf1.pMem)-1] = 0; err = ddocMemAppendData(pBuf, (char*)mbuf1.pMem, -1); ddocMemBuf_free(&mbuf1); } err = ddocGen_endElem(pBuf, "SignatureValue"); err = ddocMemAppendData(pBuf, "\n", -1); return err; } //======================< CertID >==================================== //-------------------------------------------------- // "Constructor" of CertID object // ppCertID - address of buffer for newly allocated object [REQUIRED] // szId - Id atribute value [OPTIONAL] // nType - certid internal type (signers or responders cert) [REQUIRED] // szIssuerSerial - issuer serial number [OPTIONAL] // szIssuerName - issuer DN [OPTIONAL] // szDigVal/lDigLen - digest value and length [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_new(CertID** ppCertID, int nType, const char* szId, const char* szIssuerSerial, const char* szIssuerName, void* szDigVal, long lDigLen) { int err = ERR_OK; // check input parameters ddocDebug(4, "ddocCertID_new", "id: %s, type: %d, issuer-serial: %s issuer-name: %s, dig-len: %ld", (szId ? szId : "NULL"), nType, (szIssuerSerial ? szIssuerSerial : "NULL"), (szIssuerName ? szIssuerName : "NULL"), lDigLen); RETURN_IF_NULL_PARAM(ppCertID); *ppCertID = 0; // mark as not yet allocated // allocate memory for new CertID *ppCertID = (CertID*)malloc(sizeof(CertID)); if(!(*ppCertID)) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(*ppCertID, 0, sizeof(CertID)); (*ppCertID)->nType = nType; // set optional fields if(szId) { err = ddocMemAssignString((char**)&((*ppCertID)->szId), szId); if(err) return err; } if(szIssuerSerial) { err = ddocMemAssignString((char**)&((*ppCertID)->szIssuerSerial), szIssuerSerial); if(err) return err; } if(szIssuerName) { err = ddocMemAssignString((char**)&((*ppCertID)->szIssuerName), szIssuerName); if(err) return err; } if(szDigVal && lDigLen) { if(!(*ppCertID)->pDigestValue) ddocDigestValue_new(&((*ppCertID)->pDigestValue), 0, szDigVal, lDigLen); else err = ddocDigestValue_SetDigestValue((*ppCertID)->pDigestValue, szDigVal, lDigLen); } return err; } EXP_OPTION int bdocCertID_new(CertID** ppCertID, int nType, const char* szId, const char* szIssuerSerial, const char* szIssuerName, void* szDigVal, long lDigLen) { int err = ERR_OK; // check input parameters ddocDebug(4, "ddocCertID_new", "id: %s, type: %d, issuer-serial: %s issuer-name: %s, dig-len: %ld", (szId ? szId : "NULL"), nType, (szIssuerSerial ? szIssuerSerial : "NULL"), (szIssuerName ? szIssuerName : "NULL"), lDigLen); RETURN_IF_NULL_PARAM(ppCertID); *ppCertID = 0; // mark as not yet allocated // allocate memory for new CertID *ppCertID = (CertID*)malloc(sizeof(CertID)); if(!(*ppCertID)) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(*ppCertID, 0, sizeof(CertID)); (*ppCertID)->nType = nType; // set optional fields if(szId) { err = ddocMemAssignString((char**)&((*ppCertID)->szId), szId); if(err) return err; } if(szIssuerSerial) { err = ddocMemAssignString((char**)&((*ppCertID)->szIssuerSerial), szIssuerSerial); if(err) return err; } if(szIssuerName) { err = ddocMemAssignString((char**)&((*ppCertID)->szIssuerName), szIssuerName); if(err) return err; } if(szDigVal && lDigLen) { if(!(*ppCertID)->pDigestValue){ ddocDigestValue_new(&((*ppCertID)->pDigestValue), 0, szDigVal, lDigLen); }else err = ddocDigestValue_SetDigestValue((*ppCertID)->pDigestValue, szDigVal, lDigLen); } return err; } //-------------------------------------------------- // "Destructor" of CertID object // pCertID - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_free(CertID* pCertID) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pCertID) // cleanup this object if(pCertID->szId) free(pCertID->szId); if(pCertID->szIssuerSerial) free(pCertID->szIssuerSerial); if(pCertID->szIssuerName) free(pCertID->szIssuerName); if(pCertID->pDigestValue) ddocDigestValue_free(pCertID->pDigestValue); if(pCertID->szDigestType) free(pCertID->szDigestType); free(pCertID); return err; } //-------------------------------------------------- // Accessor for IssuerSerial atribute of CertID object. // pCertID - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocCertID_GetIssuerSerial(const CertID* pCertID) { RETURN_OBJ_IF_NULL(pCertID, NULL) return pCertID->szIssuerSerial; } //-------------------------------------------------- // Mutatoror for IssuerSerial atribute of CertID object. // pCertID - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_SetIssuerSerial(CertID* pCertID, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pCertID) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pCertID->szIssuerSerial), value); return err; } //-------------------------------------------------- // Accessor for Id atribute of CertID object. // pCertID - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocCertID_GetId(const CertID* pCertID) { RETURN_OBJ_IF_NULL(pCertID, NULL) return pCertID->szId; } //-------------------------------------------------- // Mutatoror for Id atribute of CertID object. // pCertID - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_SetId(CertID* pCertID, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pCertID) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pCertID->szId), value); return err; } //-------------------------------------------------- // Accessor for IssuerName atribute of CertID object. // pCertID - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocCertID_GetIssuerName(const CertID* pCertID) { RETURN_OBJ_IF_NULL(pCertID, NULL) return pCertID->szIssuerName; } //-------------------------------------------------- // Mutatoror for IssuerName atribute of CertID object. // pCertID - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_SetIssuerName(CertID* pCertID, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pCertID) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pCertID->szIssuerName), value); return err; } //-------------------------------------------------- // Accessor for DigestValue atribute of CertID object. // pCertID - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION DigiDocMemBuf* ddocCertID_GetDigestValue(const CertID* pCertID) { RETURN_OBJ_IF_NULL(pCertID, NULL) return ddocDigestValue_GetDigestValue(pCertID->pDigestValue); } //-------------------------------------------------- // Mutatoror for DigestValue atribute of CertID object. // pCertID - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // len - length of value in bytes [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertID_SetDigestValue(CertID* pCertID, const char* value, long len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pCertID) RETURN_IF_NULL_PARAM(value) if(!pCertID->pDigestValue) err = ddocDigestValue_new(&(pCertID->pDigestValue), 0, (char*)value, len); else err = ddocDigestValue_SetDigestValue(pCertID->pDigestValue, value, len); return err; } //-------------------------------------------------- // Generates XML for element // pSigDoc - SignedDoc object [REQUIRED] // pCertID - CertID object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCertID_toXML(const SignedDoc* pSigDoc, const CertID* pCertID, DigiDocMemBuf* pBuf) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pCertID) RETURN_IF_NULL_PARAM(pSigDoc) // start of element err = ddocGen_startElemBegin(pBuf, "Cert"); if(err) return err; // only formats 1.0, 1.1 and 1.2 we use the Id atribute //AM 28.10.08 can also have 1.0 version if((!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) { // Id atribute if(pCertID->szId) err = ddocGen_addAtribute(pBuf, "Id", pCertID->szId); if(err) return err; } // end of element start tag err = ddocGen_startElemEnd(pBuf); // err = ddocGen_startElem(pBuf, "CertDigest"); if(err) return err; ddocDigestValue_toXML(pCertID->pDigestValue, pBuf); err = ddocGen_endElem(pBuf, "CertDigest"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); // szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME))|| !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) { err = ddocMemAppendData(pBuf, ddocCertID_GetIssuerSerial(pCertID), -1); } else { // in 1.3 and 1.4 we use all subelement of err = ddocGen_startElemBegin(pBuf, "X509IssuerName"); if(err) return err; err = ddocGen_addAtribute(pBuf, "xmlns", NAMESPACE_XML_DSIG); // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; err = ddocMemAppendData(pBuf, ddocCertID_GetIssuerName(pCertID), -1); if(err) return err; err = ddocGen_endElem(pBuf, "X509IssuerName"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); err = ddocGen_startElemBegin(pBuf, "X509SerialNumber"); if(err) return err; err = ddocGen_addAtribute(pBuf, "xmlns", NAMESPACE_XML_DSIG); // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; err = ddocMemAppendData(pBuf, ddocCertID_GetIssuerSerial(pCertID), -1); if(err) return err; err = ddocGen_endElem(pBuf, "X509SerialNumber"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); } err = ddocGen_endElem(pBuf, "IssuerSerial"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; err = ddocGen_endElem(pBuf, "Cert"); return err; } //-------------------------------------------------- // Generates XML for element // pSigDoc - SignedDoc object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCompleteCertificateRefs_toXML(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, DigiDocMemBuf* pBuf) { int err = ERR_OK, i, n; CertID* pCertID; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pSigDoc) RETURN_IF_NULL_PARAM(pSigInfo) RETURN_IF_NULL(pSigInfo->pCertIDs) // err = ddocGen_startElemBegin(pBuf, "CompleteCertificateRefs"); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; // (not used in 1.0, 1.1 and 1.2 if((strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) && strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) && strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) { err = ddocGen_startElem(pBuf, "CertRefs"); if(err) return err; } n = ddocCertIDList_GetCertIDsCount(pSigInfo->pCertIDs); for(i = 0; i < n; i++) { pCertID = ddocCertIDList_GetCertID(pSigInfo->pCertIDs, i); if(pCertID && pCertID->nType != CERTID_TYPE_SIGNERS_CERTID) ddocCertID_toXML(pSigDoc, pCertID, pBuf); } // (not used in 1.0, 1.1 and 1.2 //AM 29.10.08 if((strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) && strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) && strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)) { err = ddocGen_endElem(pBuf, "CertRefs"); } if(err) return err; err = ddocGen_endElem(pBuf, "CompleteCertificateRefs"); return err; } //-------------------------------------------------- // Generates XML for element // pSigDoc - SignedDoc object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCompleteRevocationRefs_toXML(const SignedDoc* pSigDoc, const SignatureInfo* pSigInfo, DigiDocMemBuf* pBuf) { int err = ERR_OK, l1, l2; //AM 28.04.04 increased buffer for sha256 char buf1[80], buf2[80], *p1, *p2; const DigiDocMemBuf *pMBuf = 0; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pSigDoc) RETURN_IF_NULL_PARAM(pSigInfo) RETURN_IF_NULL(pSigInfo->pNotary) // err = ddocGen_startElemBegin(pBuf, "CompleteRevocationRefs"); if(err) return err; // end of element start tag err = ddocGen_startElemEnd(pBuf); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_startElem(pBuf, "OCSPRefs"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_startElem(pBuf, "OCSPRef"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_startElemBegin(pBuf, "OCSPIdentifier"); if(err) return err; snprintf(buf1, sizeof(buf1), "#%s", pSigInfo->pNotary->szId); err = ddocGen_addAtribute(pBuf, "URI", buf1); err = ddocGen_startElemEnd(pBuf); if(err) return err; // err = ddocGen_startElem(pBuf, "ResponderID"); if(err) return err; if(pSigInfo->pNotary->nRespIdType == RESPID_NAME_TYPE) { p1 = (char*)ddocNotInfo_GetResponderId_Value(pSigInfo->pNotary); RETURN_IF_NULL(p1); err = ddocMemAppendData(pBuf, p1, -1); if(err) return err; } else if(pSigInfo->pNotary->nRespIdType == RESPID_KEY_TYPE) { pMBuf = ddocNotInfo_GetResponderId(pSigInfo->pNotary); RETURN_IF_NULL(pMBuf); l2 = pMBuf->nLen * 2 + 10; p2 = (char*)malloc(l2); RETURN_IF_NULL(p2); memset(p2, 0, l2); encode((const byte*)pMBuf->pMem, pMBuf->nLen, (byte*)p2, &l2); err = ddocMemAppendData(pBuf, p2, -1); if(err) return err; } else { SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_WRONG_RESPID); } err = ddocGen_endElem(pBuf, "ResponderID"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_startElem(pBuf, "ProducedAt"); if(err) return err; err = ddocMemAppendData(pBuf, pSigInfo->pNotary->timeProduced, -1); if(err) return err; err = ddocGen_endElem(pBuf, "ProducedAt"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_endElem(pBuf, "OCSPIdentifier"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_startElem(pBuf, "DigestAlgAndValue"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_startElemBegin(pBuf, "DigestMethod"); if(err) return err; err = ddocGen_addAtribute(pBuf, "Algorithm", DIGEST_METHOD_SHA1); err = ddocGen_startElemEnd(pBuf); if(err) return err; err = ddocGen_endElem(pBuf, "DigestMethod"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_startElem(pBuf, "DigestValue"); if(err) return err; l2 = sizeof(buf2); err = calculateNotaryInfoDigest(pSigDoc, pSigInfo->pNotary, (byte*)buf2, &l2); l1 = sizeof(buf1); encode((const byte*)buf2, l2, (byte*)buf1, &l1); err = ddocMemAppendData(pBuf, buf1, -1); err = ddocGen_endElem(pBuf, "DigestValue"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_endElem(pBuf, "DigestAlgAndValue"); if(err) return err; // err = ddocGen_endElem(pBuf, "OCSPRef"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_endElem(pBuf, "OCSPRefs"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); if(err) return err; // err = ddocGen_endElem(pBuf, "CompleteRevocationRefs"); if(err) return err; err = ddocMemAppendData(pBuf, "\n", -1); return err; } //==========< CertIDList >==================== //-------------------------------------------------- // "Constructor" of CertIDList object // ppCertIDList - address of buffer for newly allocated object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertIDList_new(CertIDList** ppCertIDList) { int err = ERR_OK; // check input parameters ddocDebug(3, "ddocCertIDList_new", "Create new certid list"); RETURN_IF_NULL_PARAM(ppCertIDList); *ppCertIDList = (CertIDList*)malloc(sizeof(CertIDList)); // allocate new object RETURN_IF_BAD_ALLOC(*ppCertIDList); memset(*ppCertIDList, 0, sizeof(CertIDList)); return err; } //-------------------------------------------------- // "Destructor" of CertIDList object // pCertIDList - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertIDList_free(CertIDList* pCertIDList) { int i, err = ERR_OK; RETURN_IF_NULL_PARAM(pCertIDList) // free timestamp-infos for(i = 0; i < pCertIDList->nCertIDs; i++) { if(pCertIDList->pCertIDs[i]) { err = ddocCertID_free(pCertIDList->pCertIDs[i]); if(err) return err; } } free(pCertIDList->pCertIDs); free(pCertIDList); return err; } //-------------------------------------------------- // Accessor for count of CertIDs subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCertIDList_addCertID(CertIDList* pCertIDList, CertID* pCertID) { CertID** pCertIDs = 0; RETURN_IF_NULL_PARAM(pCertIDList) RETURN_IF_NULL_PARAM(pCertID) pCertIDs = (CertID**)realloc(pCertIDList->pCertIDs, sizeof(CertID*) * (pCertIDList->nCertIDs + 1)); RETURN_IF_BAD_ALLOC(pCertIDs); pCertIDList->pCertIDs = pCertIDs; pCertIDList->pCertIDs[pCertIDList->nCertIDs] = pCertID; pCertIDList->nCertIDs++; ddocDebug(3, "ddocCertIDList_addCertID", "added certid: %s type: %d", pCertID->szId, pCertID->nType); return ERR_OK; } //-------------------------------------------------- // Accessor for count of CertIDs subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // returns count or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int ddocCertIDList_GetCertIDsCount(CertIDList* pCertIDList) { SET_LAST_ERROR_RETURN_IF_NOT(pCertIDList, ERR_NULL_POINTER, -1) return pCertIDList->nCertIDs; } //-------------------------------------------------- // Accessor for CertIDs subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // nIdx - index of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetCertID(CertIDList* pCertIDList, int nIdx) { RETURN_OBJ_IF_NULL(pCertIDList, NULL) SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pCertIDList->nCertIDs, ERR_BAD_CERTID_IDX, NULL); RETURN_OBJ_IF_NULL(pCertIDList->pCertIDs[nIdx], 0); return pCertIDList->pCertIDs[nIdx]; } //-------------------------------------------------- // Accessor for last CertIDs subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetLastCertID(CertIDList* pCertIDList) { RETURN_OBJ_IF_NULL(pCertIDList, NULL) SET_LAST_ERROR_RETURN_IF_NOT(pCertIDList->nCertIDs > 0, ERR_BAD_CERTID_IDX, NULL); RETURN_OBJ_IF_NULL(pCertIDList->pCertIDs[pCertIDList->nCertIDs-1], 0); return pCertIDList->pCertIDs[pCertIDList->nCertIDs-1]; } //-------------------------------------------------- // Deletes CertID subelement of CertIDList object. // pCertIDList - pointer to CertIDList object [REQUIRED] // nIdx - index of CertID object to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertIDList_DeleteCertID(CertIDList* pCertIDList, int nIdx) { int err = ERR_OK, i; RETURN_IF_NULL_PARAM(pCertIDList) SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pCertIDList->nCertIDs, ERR_BAD_CERTID_IDX, ERR_BAD_CERTID_IDX); RETURN_IF_NULL_PARAM(pCertIDList->pCertIDs[nIdx]); // delete the given object err = ddocCertID_free(pCertIDList->pCertIDs[nIdx]); if(err) return err; pCertIDList->pCertIDs[nIdx] = 0; // move other objects 1 step close to array start for(i = nIdx; i < pCertIDList->nCertIDs; i++) pCertIDList->pCertIDs[i] = pCertIDList->pCertIDs[i+1]; pCertIDList->pCertIDs[pCertIDList->nCertIDs - 1] = 0; pCertIDList->nCertIDs--; return err; } //-------------------------------------------------- // Finds a CertID object with required type // pCertIDList - pointer to CertIDList object [REQUIRED] // nType - type of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetCertIDOfType(CertIDList* pCertIDList, int nType) { int i; RETURN_OBJ_IF_NULL(pCertIDList, NULL) ddocDebug(4, "ddocCertIDList_GetCertIDOfType", "find type: %d", nType); for(i = 0; i < pCertIDList->nCertIDs; i++) { ddocDebug(4, "ddocCertIDList_GetCertIDOfType", "idx: %d type: %d", i, pCertIDList->pCertIDs[i]->nType); if(pCertIDList->pCertIDs[i]->nType == nType) return pCertIDList->pCertIDs[i]; } return NULL; } //-------------------------------------------------- // Finds a CertID object with serial nr // pCertIDList - pointer to CertIDList object [REQUIRED] // nType - type of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetCertIDOfSerial(CertIDList* pCertIDList, const char* szSerial) { int i; RETURN_OBJ_IF_NULL(pCertIDList, NULL) RETURN_OBJ_IF_NULL(szSerial, NULL) ddocDebug(4, "ddocCertIDList_GetCertIDOfSerial", "find serial: %s", szSerial); for(i = 0; i < pCertIDList->nCertIDs; i++) { //AM 19.09.08 if(pCertIDList->pCertIDs[i]->szIssuerSerial){ if(!strcmp(pCertIDList->pCertIDs[i]->szIssuerSerial, szSerial)) return pCertIDList->pCertIDs[i]; } } return NULL; } //-------------------------------------------------- // Finds a CertID object with required type or creates a new one // pCertIDList - pointer to CertIDList object [REQUIRED] // nType - type of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocCertIDList_GetOrCreateCertIDOfType(CertIDList* pCertIDList, int nType) { CertID* pCertID = ddocCertIDList_GetCertIDOfType(pCertIDList, nType); if(!pCertID) { ddocCertID_new(&pCertID, nType, 0, 0, 0, 0, 0); if(pCertID) ddocCertIDList_addCertID(pCertIDList, pCertID); } return pCertID; } //======================< CertValue >==================================== //-------------------------------------------------- // "Constructor" of CertValue object // ppCertValue - address of buffer for newly allocated object [REQUIRED] // szId - Id atribute value [OPTIONAL] // nType - certid internal type (signers or responders cert) [REQUIRED] // pCert - certificate itself [OPTIONAL]. Must fill in later. Do not X509_free() param! // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValue_new(CertValue** ppCertValue, int nType, const char* szId, X509* pCert) { int err = ERR_OK; // check input parameters ddocDebug(4, "ddocCertValue_new", "id: %s, type: %d, cert: %s", (szId ? szId : "NULL"), nType, (pCert ? "OK" : "NULL")); RETURN_IF_NULL_PARAM(ppCertValue); //RETURN_IF_NULL_PARAM(pCert); *ppCertValue = 0; // mark as not yet allocated // allocate memory for new CertValue *ppCertValue = (CertValue*)malloc(sizeof(CertValue)); if(!(*ppCertValue)) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(*ppCertValue, 0, sizeof(CertValue)); (*ppCertValue)->nType = nType; if(pCert) (*ppCertValue)->pCert = pCert; // set optional fields if(szId) { err = ddocMemAssignString((char**)&((*ppCertValue)->szId), szId); if(err) return err; } return err; } //-------------------------------------------------- // "Destructor" of CertValue object // pCertValue - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValue_free(CertValue* pCertValue) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pCertValue) // cleanup this object if(pCertValue->szId) free(pCertValue->szId); if(pCertValue->pCert) X509_free(pCertValue->pCert); free(pCertValue); return err; } //-------------------------------------------------- // Accessor for Id atribute of CertValue object. // pCertValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* ddocCertValue_GetId(CertValue* pCertValue) { RETURN_OBJ_IF_NULL(pCertValue, NULL) return pCertValue->szId; } //-------------------------------------------------- // Mutatoror for Id atribute of CertValue object. // pCertValue - address of object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValue_SetId(CertValue* pCertValue, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pCertValue) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pCertValue->szId), value); return err; } //-------------------------------------------------- // Accessor for Cert atribute of CertValue object. // pCertValue - address of object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION X509* ddocCertValue_GetCert(CertValue* pCertValue) { RETURN_OBJ_IF_NULL(pCertValue, NULL) return pCertValue->pCert; } //-------------------------------------------------- // Mutatoror for Cert atribute of CertValue object. // pCertValue - address of object [REQUIRED] // pCert - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValue_SetCert(CertValue* pCertValue, X509* pCert) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pCertValue) RETURN_IF_NULL_PARAM(pCert) if(pCertValue->pCert && pCertValue->pCert != pCert) // free old cert X509_free(pCertValue->pCert); else ddocDebug(3, "ddocCertValue_SetCert", "Not freeing old cert"); pCertValue->pCert = pCert; ddocDebug(3, "ddocCertValue_SetCert", "id: %s type: %d cert: %s", pCertValue->szId, pCertValue->nType, (pCert ? "OK" : "NULL")); return err; } //-------------------------------------------------- // Generates XML for element // pCertID - CertID object [REQUIRED] // pBuf - memory buffer for storing xml [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int ddocCertValue_toXML(const CertValue* pCertValue, DigiDocMemBuf* pBuf) { int err = ERR_OK; char *p1 = 0; RETURN_IF_NULL_PARAM(pBuf) RETURN_IF_NULL_PARAM(pCertValue) // start of element err = ddocGen_startElemBegin(pBuf, "EncapsulatedX509Certificate"); if(err) return err; if(pCertValue->szId) err = ddocGen_addAtribute(pBuf, "Id", pCertValue->szId); if(err) return err; err = ddocGen_startElemEnd(pBuf); if(err) return err; //err = ddocMemAppendData(pBuf, "\n", -1); if(pCertValue->pCert) { err = getCertPEM(pCertValue->pCert, 0, &p1); if(p1) { err = ddocMemAppendData(pBuf, p1, -1); free(p1); } } if(err) return err; err = ddocGen_endElem(pBuf, "EncapsulatedX509Certificate"); return err; } //==========< CertValueList >==================== //-------------------------------------------------- // "Constructor" of CertValueList object // ppCertValueList - address of buffer for newly allocated object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValueList_new(CertValueList** ppCertValueList) { int err = ERR_OK; // check input parameters ddocDebug(3, "ddocCertValueList_new", "Create new cerValue list"); RETURN_IF_NULL_PARAM(ppCertValueList); *ppCertValueList = (CertValueList*)malloc(sizeof(CertValueList)); // allocate new object RETURN_IF_BAD_ALLOC(*ppCertValueList); memset(*ppCertValueList, 0, sizeof(CertValueList)); return err; } //-------------------------------------------------- // "Destructor" of CertValueList object // pCertValueList - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValueList_free(CertValueList* pCertValueList) { int i, err = ERR_OK; RETURN_IF_NULL_PARAM(pCertValueList) // free timestamp-infos for(i = 0; i < pCertValueList->nCertValues; i++) { if(pCertValueList->pCertValues[i]) { err = ddocCertValue_free(pCertValueList->pCertValues[i]); if(err) return err; } } free(pCertValueList->pCertValues); free(pCertValueList); return err; } //-------------------------------------------------- // Adds a CertValue element to CertValueList object. // pCertValueList - pointer to CertValueList object [REQUIRED] // pCertValue - new object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValueList_addCertValue(CertValueList* pCertValueList, CertValue* pCertValue) { CertValue** pCertValues = 0; RETURN_IF_NULL_PARAM(pCertValueList) RETURN_IF_NULL_PARAM(pCertValue) pCertValues = (CertValue**)realloc(pCertValueList->pCertValues, sizeof(CertValue*) * (pCertValueList->nCertValues + 1)); RETURN_IF_BAD_ALLOC(pCertValues); pCertValueList->pCertValues = pCertValues; pCertValueList->pCertValues[pCertValueList->nCertValues] = pCertValue; pCertValueList->nCertValues++; ddocDebug(4, "ddocCertValueList_addCertValue", "added cert: %s type: %d", pCertValue->szId, pCertValue->nType); return ERR_OK; } //-------------------------------------------------- // Accessor for count of CertValues subelement of CertValueList object. // pCertValueList - pointer to CertValueList object [REQUIRED] // returns count or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int ddocCertValueList_GetCertValuesCount(CertValueList* pCertValueList) { SET_LAST_ERROR_RETURN_IF_NOT(pCertValueList, ERR_NULL_POINTER, -1) return pCertValueList->nCertValues; } //-------------------------------------------------- // Accessor for CertValues subelement of CertValueList object. // pCertValueList - pointer to CertValueList object [REQUIRED] // nIdx - index of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocCertValueList_GetCertValue(CertValueList* pCertValueList, int nIdx) { RETURN_OBJ_IF_NULL(pCertValueList, NULL) SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pCertValueList->nCertValues, ERR_BAD_CERTVALUE_IDX, NULL); RETURN_OBJ_IF_NULL(pCertValueList->pCertValues[nIdx], 0); return pCertValueList->pCertValues[nIdx]; } //-------------------------------------------------- // Deletes CertValue subelement of CertValueList object. // pCertValueList - pointer to CertValueList object [REQUIRED] // nIdx - index of CertValue object to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertValueList_DeleteCertValue(CertValueList* pCertValueList, int nIdx) { int err = ERR_OK, i; RETURN_IF_NULL_PARAM(pCertValueList) SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pCertValueList->nCertValues, ERR_BAD_CERTVALUE_IDX, ERR_BAD_CERTVALUE_IDX); RETURN_IF_NULL_PARAM(pCertValueList->pCertValues[nIdx]); // delete the given object err = ddocCertValue_free(pCertValueList->pCertValues[nIdx]); if(err) return err; pCertValueList->pCertValues[nIdx] = 0; // move other objects 1 step close to array start for(i = nIdx; i < pCertValueList->nCertValues; i++) pCertValueList->pCertValues[i] = pCertValueList->pCertValues[i+1]; pCertValueList->pCertValues[pCertValueList->nCertValues - 1] = 0; pCertValueList->nCertValues--; return err; } //-------------------------------------------------- // Finds a CertValue object with required type // pCertValueList - pointer to CertValueList object [REQUIRED] // nType - type of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocCertValueList_GetCertValueOfType(CertValueList* pCertValueList, int nType) { int i; RETURN_OBJ_IF_NULL(pCertValueList, NULL) ddocDebug(4, "ddocCertValueList_GetCertValueOfType", "find type: %d", nType); for(i = 0; i < pCertValueList->nCertValues; i++) { ddocDebug(4, "ddocCertValueList_GetCertValueOfType", "idx: %d", i); ddocDebug(4, "ddocCertValueList_GetCertValueOfType", "idx: %d type: %d", i, pCertValueList->pCertValues[i]->nType); if(pCertValueList->pCertValues[i]->nType == nType){ ddocDebug(4, "ddocCertValueList_GetCertValueOfType", "found"); return pCertValueList->pCertValues[i];} } return NULL; } //-------------------------------------------------- // Finds a CertValue object with required type or creates a new one // pCertValueList - pointer to CertValueList object [REQUIRED] // nType - type of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocCertValueList_GetOrCreateCertValueOfType(CertValueList* pCertValueList, int nType) { CertValue* pCertValue = ddocCertValueList_GetCertValueOfType(pCertValueList, nType); if(!pCertValue) { ddocCertValue_new(&pCertValue, nType, 0, 0); if(pCertValue) ddocCertValueList_addCertValue(pCertValueList, pCertValue); } return pCertValue; } //======================< SignatureInfo >==================================== //============================================================ // Returns the number of signatures // pSigDoc - signed doc pointer //============================================================ EXP_OPTION int getCountOfSignatures(const SignedDoc* pSigDoc) { RETURN_OBJ_IF_NULL(pSigDoc, -1); return pSigDoc->nSignatures; } //============================================================ // Returns the next free signature id // pSigDoc - signed doc pointer //============================================================ EXP_OPTION int getNextSignatureId(const SignedDoc* pSigDoc) { int id = 0, n, i; RETURN_OBJ_IF_NULL(pSigDoc, -1); for(i = 0; i < pSigDoc->nSignatures; i++) { SignatureInfo* pSignature = pSigDoc->pSignatures[i]; RETURN_OBJ_IF_NULL(pSignature, -1); RETURN_OBJ_IF_NULL(pSignature->szId, -1); SET_LAST_ERROR_RETURN_IF_NOT(strlen(pSignature->szId) > 1, ERR_EMPTY_STRING, -1); n = atoi(pSignature->szId+1); if(id <= n) id = n+1; } return id; } //============================================================ // Returns the signature object for the given Notary // pSigDoc - signed doc pointer //============================================================ EXP_OPTION SignatureInfo* ddocGetSignatureForNotary(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo) { int i; RETURN_OBJ_IF_NULL(pSigDoc, NULL); for(i = 0; i < pSigDoc->nSignatures; i++) { SignatureInfo* pSignature = pSigDoc->pSignatures[i]; RETURN_OBJ_IF_NULL(pSignature, NULL); if(pSignature->pNotary == pNotInfo) return pSignature; } return NULL; } //============================================================ // Returns the desired SignatureInfo object // pSigDoc - signed doc pointer // nIdx - SignatureInfo index (starting with 0) //============================================================ EXP_OPTION SignatureInfo* getSignature(const SignedDoc* pSigDoc, int nIdx) { RETURN_OBJ_IF_NULL(pSigDoc, NULL); SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigDoc->nSignatures, ERR_BAD_SIG_INDEX, NULL); RETURN_OBJ_IF_NULL(pSigDoc->pSignatures[nIdx], NULL); return pSigDoc->pSignatures[nIdx]; } //============================================================ // Returns the last SignatureInfo object // pSigDoc - signed doc pointer //============================================================ EXP_OPTION SignatureInfo* ddocGetLastSignature(const SignedDoc* pSigDoc) { int nIdx; RETURN_OBJ_IF_NULL(pSigDoc, NULL); nIdx = pSigDoc->nSignatures - 1; SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigDoc->nSignatures, ERR_BAD_SIG_INDEX, NULL); RETURN_OBJ_IF_NULL(pSigDoc->pSignatures && pSigDoc->pSignatures[nIdx], NULL); return pSigDoc->pSignatures[nIdx]; } //============================================================ // Returns the SignatureInfo object with the given id // pSigDoc - signed doc pointer // id - SignatureInfo id //============================================================ EXP_OPTION SignatureInfo* getSignatureWithId(const SignedDoc* pSigDoc, const char* id) { SignatureInfo* pSignature = NULL; int i; RETURN_OBJ_IF_NULL(pSigDoc, NULL); RETURN_OBJ_IF_NULL(id, NULL); for(i = 0; i < pSigDoc->nSignatures; i++) { RETURN_OBJ_IF_NULL(pSigDoc->pSignatures[i], NULL); RETURN_OBJ_IF_NULL(pSigDoc->pSignatures[i]->szId, NULL); if(!strcmp(pSigDoc->pSignatures[i]->szId, id)) { pSignature = pSigDoc->pSignatures[i]; break; } } return pSignature; } //============================================================ // Adds a new SignedInfo element to a SignedDoc element and initializes it // id - signature id (use NULL for default) // return the newly created structure //============================================================ // FIXME : memory leaks possible.. EXP_OPTION int SignatureInfo_new(SignatureInfo **newSignatureInfo, SignedDoc* pSigDoc, const char* id) { int i, nId = 0; SignatureInfo** pSignatures = NULL; SignatureInfo* pSigInfo = NULL; char buf[100]; RETURN_IF_NULL_PARAM(pSigDoc); //clearErrors(); if(hasSignatureWithWrongDataFileHash(pSigDoc)) { ddocDebug(1, "SignatureInfo_new", "Cannot add signature in ddoc with invalid DataFile hashes!"); return ERR_FILE_WRITE; } if(!id) nId = getNextSignatureId(pSigDoc); if(pSigDoc->nSignatures == 0) { RETURN_IF_NOT(!pSigDoc->pSignatures, ERR_BAD_SIG_COUNT); pSigDoc->nSignatures = 1; } else pSigDoc->nSignatures++; pSignatures = (SignatureInfo**)malloc((pSigDoc->nSignatures) * sizeof(void *)); RETURN_IF_BAD_ALLOC(pSignatures); for(i = 0; i < pSigDoc->nSignatures-1; i++) pSignatures[i] = pSigDoc->pSignatures[i]; pSigInfo = (SignatureInfo*)malloc(sizeof(SignatureInfo)); RETURN_IF_BAD_ALLOC(pSigInfo); memset(pSigInfo, 0, sizeof(SignatureInfo)); pSignatures[pSigDoc->nSignatures-1] = pSigInfo; if(pSigDoc->pSignatures) free(pSigDoc->pSignatures); pSigDoc->pSignatures = pSignatures; if(id) { setString(&(pSigInfo->szId), id, -1); } else { snprintf(buf, sizeof(buf), "S%d", nId); setString(&(pSigInfo->szId), buf, -1); } // create timestamp createTimestamp(pSigDoc, buf, sizeof(buf)); setString(&(pSigInfo->szTimeStamp), buf, -1); *newSignatureInfo = pSigInfo; return ERR_OK; } //============================================================ // Sets the signature production place info // pSigInfo - signature info object // city - city name // state - state or province name // zip - postal code // country - country name //============================================================ EXP_OPTION int setSignatureProductionPlace(SignatureInfo* pSigInfo, const char* city, const char* state, const char* zip, const char* country) { char* p = 0; RETURN_IF_NULL_PARAM(pSigInfo); if(city) { p = (char*)escape2xmlsym(city); if(p) { setString(&(pSigInfo->sigProdPlace.szCity), p, -1); free(p); } } if(state) { p = (char*)escape2xmlsym(state); if(p) { setString(&(pSigInfo->sigProdPlace.szStateOrProvince), p, -1); free(p); } } if(zip) { p = (char*)escape2xmlsym(zip); if(p) { setString(&(pSigInfo->sigProdPlace.szPostalCode), p, -1); free(p); } } if(country) { p = (char*)escape2xmlsym(country); if(p) { setString(&(pSigInfo->sigProdPlace.szCountryName), country, -1); free(p); } } return ERR_OK; } //============================================================ // Adds a signer role // pSigInfo - signature info object // nCertified - certified role? (1/0) // role - role data // rLen - role data length // encode - 1=encode it with Base64, 0=use as is //============================================================ // FIXME : memory leaks possible... EXP_OPTION int addSignerRole(SignatureInfo* pSigInfo, int nCertified, const char* role, int rLen, int enc) { int n, i; char **p = NULL, *b = NULL, *p1; RETURN_IF_NULL_PARAM(pSigInfo); //if(!enc && role && (strchr(role, '<') || strchr(role, '>'))) // SET_LAST_ERROR_RETURN(ERR_INVALID_CONTENT, ERR_INVALID_CONTENT); if(nCertified) { n = pSigInfo->signerRole.nCertifiedRoles + 1; p = (char**)malloc(n * sizeof(void*)); RETURN_IF_BAD_ALLOC(p); if(pSigInfo->signerRole.nCertifiedRoles) { RETURN_IF_NULL(pSigInfo->signerRole.pCertifiedRoles); for(i = 0; i < pSigInfo->signerRole.nCertifiedRoles; i++) p[i] = pSigInfo->signerRole.pCertifiedRoles[i]; free(pSigInfo->signerRole.pCertifiedRoles); } p[n-1] = 0; if(enc) { b = (char*)malloc(rLen * 2); RETURN_IF_BAD_ALLOC(b); i = sizeof(b); encode((const byte*)role, rLen, (byte*)b, &i); b[i] = 0; setString(&(p[n-1]), b, i); } else setString(&(p[n-1]), role, rLen); pSigInfo->signerRole.pCertifiedRoles = p; pSigInfo->signerRole.nCertifiedRoles = n; } else { n = pSigInfo->signerRole.nClaimedRoles + 1; p = (char**)malloc(n * sizeof(void*)); RETURN_IF_BAD_ALLOC(p); if(pSigInfo->signerRole.nClaimedRoles) { RETURN_IF_NULL(pSigInfo->signerRole.pClaimedRoles); for(i = 0; i < pSigInfo->signerRole.nClaimedRoles; i++) p[i] = pSigInfo->signerRole.pClaimedRoles[i]; free(pSigInfo->signerRole.pClaimedRoles); } p[n-1] = 0; if(enc) { b = (char*)malloc(rLen * 2); RETURN_IF_BAD_ALLOC(b); i = sizeof(b); encode((const byte*)role, rLen, (byte*)b, &i); b[i] = 0; setString(&(p[n-1]), b, i); } else { p1 = (char*)escape2xmlsym(role); if(p1) { setString(&(p[n-1]), p1, -1); free(p1); } } pSigInfo->signerRole.pClaimedRoles = p; pSigInfo->signerRole.nClaimedRoles = n; } return ERR_OK; } //============================================================ // Returns the number of signer roles // pSigInfo - signature info object // nCertified - certified role? (1/0) //============================================================ EXP_OPTION int getCountOfSignerRoles(SignatureInfo* pSigInfo, int nCertified) { RETURN_OBJ_IF_NULL(pSigInfo, -1); if(nCertified) return pSigInfo->signerRole.nCertifiedRoles; else return pSigInfo->signerRole.nClaimedRoles; } //============================================================ // Returns the desired signer role // pSigInfo - signature info object // nCertified - certified role? (1/0) //============================================================ EXP_OPTION const char* getSignerRole(SignatureInfo* pSigInfo, int nCertified, int nIdx) { RETURN_OBJ_IF_NULL(pSigInfo, 0); if(nCertified) { SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigInfo->signerRole.nCertifiedRoles, ERR_BAD_ROLE_INDEX, 0); RETURN_OBJ_IF_NULL(pSigInfo->signerRole.pCertifiedRoles[nIdx], 0); return pSigInfo->signerRole.pCertifiedRoles[nIdx]; } else { SET_LAST_ERROR_RETURN_IF_NOT(nIdx < pSigInfo->signerRole.nClaimedRoles, ERR_BAD_ROLE_INDEX, 0); RETURN_OBJ_IF_NULL(pSigInfo->signerRole.pClaimedRoles[nIdx], 0); return pSigInfo->signerRole.pClaimedRoles[nIdx]; } } //============================================================ // Removes this SignatureInfo from signed doc and frees it's memory // pSigDoc - signed doc object // id - signature id to be removed //============================================================ EXP_OPTION int SignatureInfo_delete(SignedDoc* pSigDoc, const char* id) { int n, i, j, err = ERR_OK; SignatureInfo* pSignature; SignatureInfo** pSignatures; RETURN_IF_NULL_PARAM(pSigDoc); ddocDebug(3, "SignatureInfo_delete", "id: %s", id); if(hasSignatureWithWrongDataFileHash(pSigDoc)) { ddocDebug(1, "SignatureInfo_delete", "Cannot delete signature in ddoc with invalid DataFile hashes!"); return ERR_FILE_WRITE; } if((pSignature = getSignatureWithId(pSigDoc, id)) != NULL) { n = pSigDoc->nSignatures - 1; if(n > 0) { pSignatures = (SignatureInfo**)malloc(n * sizeof(void*)); RETURN_IF_BAD_ALLOC(pSignatures); for(i = j = 0; i < pSigDoc->nSignatures; i++) { if(strcmp(pSigDoc->pSignatures[i]->szId, id)) { pSignatures[j++] = pSigDoc->pSignatures[i]; } else { SignatureInfo_free(pSigDoc->pSignatures[i]); } } free(pSigDoc->pSignatures); pSigDoc->pSignatures = pSignatures; pSigDoc->nSignatures = j; } else { for(i = 0; i < pSigDoc->nSignatures; i++){ SignatureInfo_free(pSigDoc->pSignatures[i]); free(pSigDoc->pSignatures); pSigDoc->pSignatures = NULL; pSigDoc->nSignatures = 0;} } } else err = ERR_BAD_SIG_INDEX; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // cleanup SignatureInfo memory // pSigInfo - object to be cleaned up //============================================================ EXP_OPTION void SignatureInfo_free(SignatureInfo* pSigInfo) { int i; RETURN_VOID_IF_NULL(pSigInfo); if(pSigInfo->szId) free(pSigInfo->szId); if(pSigInfo->szTimeStamp) free(pSigInfo->szTimeStamp); if(pSigInfo->pSigPropDigest) ddocDigestValue_free(pSigInfo->pSigPropDigest); if(pSigInfo->pSigPropRealDigest) ddocDigestValue_free(pSigInfo->pSigPropRealDigest); if(pSigInfo->pSigInfoRealDigest) ddocDigestValue_free(pSigInfo->pSigInfoRealDigest); if(pSigInfo->pSigValue) ddocSignatureValue_free(pSigInfo->pSigValue); for(i = 0; i < pSigInfo->nDocs; i++) { DocInfo_free(pSigInfo->pDocs[i]); } if(pSigInfo->pDocs) free(pSigInfo->pDocs); // signature production place if(pSigInfo->sigProdPlace.szCity) free(pSigInfo->sigProdPlace.szCity); if(pSigInfo->sigProdPlace.szStateOrProvince) free(pSigInfo->sigProdPlace.szStateOrProvince); if(pSigInfo->sigProdPlace.szPostalCode) free(pSigInfo->sigProdPlace.szPostalCode); if(pSigInfo->sigProdPlace.szCountryName) free(pSigInfo->sigProdPlace.szCountryName); // signer role for(i = 0; i < pSigInfo->signerRole.nClaimedRoles; i++) { if(pSigInfo->signerRole.pClaimedRoles[i]) free(pSigInfo->signerRole.pClaimedRoles[i]); } if(pSigInfo->signerRole.pClaimedRoles) free(pSigInfo->signerRole.pClaimedRoles); for(i = 0; i < pSigInfo->signerRole.nCertifiedRoles; i++) { if (pSigInfo->signerRole.pCertifiedRoles[i]) free(pSigInfo->signerRole.pCertifiedRoles[i]); } if(pSigInfo->signerRole.pCertifiedRoles) free(pSigInfo->signerRole.pCertifiedRoles); ddocMemBuf_free(&(pSigInfo->mbufOrigContent)); if(pSigInfo->pNotary) NotaryInfo_free(pSigInfo->pNotary); if(pSigInfo->pCertIDs) ddocCertIDList_free(pSigInfo->pCertIDs); if(pSigInfo->pCertValues) ddocCertValueList_free(pSigInfo->pCertValues); //AM 23.05.08 if(pSigInfo->szDigestType) free(pSigInfo->szDigestType); free(pSigInfo); } //============================================================ // Sets signatures signed properties digest // pSigInfo - signature info object // value - new binary digest value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSigPropDigest(SignatureInfo* pSigInfo, const char* value, long len) { RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(value); if(!pSigInfo->pSigPropDigest) ddocDigestValue_new(&(pSigInfo->pSigPropDigest), 0, 0, 0); return ddocDigestValue_SetDigestValue(pSigInfo->pSigPropDigest, value, len); } //============================================================ // Sets signatures signed properties real digest as read from file // pSigInfo - signature info object // value - new binary digest value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSigPropRealDigest(SignatureInfo* pSigInfo, const char* value, long len) { RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(value); if(!pSigInfo->pSigPropRealDigest) ddocDigestValue_new(&(pSigInfo->pSigPropRealDigest), 0, 0, 0); return ddocDigestValue_SetDigestValue(pSigInfo->pSigPropRealDigest, value, len); } //============================================================ // Sets signatures signed info real digest as read from file // pSigInfo - signature info object // value - new binary digest value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSigInfoRealDigest(SignatureInfo* pSigInfo, const char* value, long len) { RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(value); if(!pSigInfo->pSigInfoRealDigest) ddocDigestValue_new(&(pSigInfo->pSigInfoRealDigest), 0, 0, 0); return ddocDigestValue_SetDigestValue(pSigInfo->pSigInfoRealDigest, value, len); } //============================================================ // Returns signatures signed properties digest // pSigInfo - signature info object // return digest value as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSigPropDigest(SignatureInfo* pSigInfo) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); return ddocDigestValue_GetDigestValue(pSigInfo->pSigPropDigest); } //============================================================ // Returns signatures signed properties digest as read from file // pSigInfo - signature info object // return digest value as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSigPropRealDigest(SignatureInfo* pSigInfo) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); return ddocDigestValue_GetDigestValue(pSigInfo->pSigPropRealDigest); } //============================================================ // Returns signatures signed info digest as read from file // pSigInfo - signature info object // return digest value as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSigInfoRealDigest(SignatureInfo* pSigInfo) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); return ddocDigestValue_GetDigestValue(pSigInfo->pSigInfoRealDigest); } //============================================================ // Returns signatures signature-value // pSigInfo - signature info object // return signature-value as SignatureValue pointer or NULL //============================================================ EXP_OPTION SignatureValue* ddocSigInfo_GetSignatureValue(SignatureInfo* pSigInfo) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); return pSigInfo->pSigValue; } //============================================================ // Returns signatures signature-value // pSigInfo - signature info object // return signature-value as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSignatureValue_Value(SignatureInfo* pSigInfo) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); return ddocSignatureValue_GetSignatureValue(pSigInfo->pSigValue); } //============================================================ // Sets signatures signature-value // pSigInfo - signature info object // value - new binary signature value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSignatureValue(SignatureInfo* pSigInfo, const char* value, long len) { char buf1[30]; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(value); snprintf(buf1, sizeof(buf1), "%s-SIG", pSigInfo->szId); if(!pSigInfo->pSigValue) ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, 0, 0, 0); ddocSignatureValue_SetId(pSigInfo->pSigValue, buf1); return ddocSignatureValue_SetSignatureValue(pSigInfo->pSigValue, value, len); } //============================================================ // Returns signaers certs - issuer-serial // pSigInfo - signature info object // return required atribute value //============================================================ EXP_OPTION const char* ddocSigInfo_GetSignersCert_IssuerSerial(const SignatureInfo* pSigInfo) { CertID* pCertID = 0; RETURN_OBJ_IF_NULL(pSigInfo, NULL); pCertID = ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID); RETURN_OBJ_IF_NULL(pCertID, NULL); return ddocCertID_GetIssuerSerial(pCertID); } //============================================================ // Sets signers certs issuer serial // pSigInfo - signature info object // value - new value //============================================================ EXP_OPTION int ddocSigInfo_SetSignersCert_IssuerSerial(SignatureInfo* pSigInfo, const char* value) { CertID* pCertID = 0; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(value); pCertID = ddocCertIDList_GetOrCreateCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID); return ddocCertID_SetIssuerSerial(pCertID, value); } //============================================================ // Returns signaers certs - issuer-name // pSigInfo - signature info object // return required atribute value //============================================================ EXP_OPTION const char* ddocSigInfo_GetSignersCert_IssuerName(const SignatureInfo* pSigInfo) { CertID* pCertID = 0; RETURN_OBJ_IF_NULL(pSigInfo, NULL); pCertID = ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID); RETURN_OBJ_IF_NULL(pCertID, NULL); return ddocCertID_GetIssuerName(pCertID); } //============================================================ // Returns signaers certs - issuer-name // pSigInfo - signature info object // pMbuf - memory buffer to return hash // return required atribute value //============================================================ EXP_OPTION const char* ddocSigInfo_GetSignersCert_IssuerNameAndHash(const SignatureInfo* pSigInfo, DigiDocMemBuf *pMbuf) { CertID* pCertID = 0; X509* pCert = 0; /* DigiDocMemBuf mbuf1, mbuf2, mbuf3; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; mbuf3.pMem = 0; mbuf3.nLen = 0; */ RETURN_OBJ_IF_NULL(pSigInfo, NULL); RETURN_OBJ_IF_NULL(pMbuf, NULL); pCertID = ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID); RETURN_OBJ_IF_NULL(pCertID, NULL); pCert = ddocSigInfo_GetSignersCert(pSigInfo); RETURN_OBJ_IF_NULL(pCert, NULL); /*ddocCertGetSubjectCN(pCert, &mbuf1); readSubjectKeyIdentifier(pCert, &mbuf2); ddocEncodeBase64(&mbuf2, &mbuf3); ddocMemBuf_free(&mbuf2); readAuthorityKeyIdentifier(pCert, pMbuf); ddocEncodeBase64(pMbuf, &mbuf2); ddocDebug(3, "ddocSigInfo_GetSignersCert_IssuerNameAndHash", "CN: %s subj-hash: %s issuer-hash: %s", (char*)mbuf1.pMem, (char*)mbuf3.pMem, (char*)mbuf2.pMem); ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3);*/ readAuthorityKeyIdentifier(pCert, pMbuf); return ddocCertID_GetIssuerName(pCertID); } //============================================================ // Sets signers certs issuer name // pSigInfo - signature info object // value - new value //============================================================ EXP_OPTION int ddocSigInfo_SetSignersCert_IssuerName(SignatureInfo* pSigInfo, const char* value) { CertID* pCertID = 0; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(value); pCertID = ddocCertIDList_GetOrCreateCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID); return ddocCertID_SetIssuerName(pCertID, value); } //============================================================ // Returns signers certs digest as DigiDocMemBuf object // pSigInfo - signature info object // return signers certs digest as DigiDocMemBuf pointer or NULL //============================================================ EXP_OPTION DigiDocMemBuf* ddocSigInfo_GetSignersCert_DigestValue(const SignatureInfo* pSigInfo) { CertID* pCertID = 0; RETURN_OBJ_IF_NULL(pSigInfo, NULL); pCertID = ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID); RETURN_OBJ_IF_NULL(pCertID, NULL); return ddocCertID_GetDigestValue(pCertID); } //============================================================ // Sets signers certs digest // pSigInfo - signature info object // value - new binary signature value // len - length of the value //============================================================ EXP_OPTION int ddocSigInfo_SetSignersCert_DigestValue(SignatureInfo* pSigInfo, const char* value, long len) { CertID* pCertID = 0; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(value); pCertID = ddocCertIDList_GetOrCreateCertIDOfType(pSigInfo->pCertIDs, CERTID_TYPE_SIGNERS_CERTID); return ddocCertID_SetDigestValue(pCertID, value, len); } //-------------------------------------------------- // Finds a CertID object with required type // pSigInfo - signature info object [REQUIRED] // nType - type of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocSigInfo_GetCertIDOfType(const SignatureInfo* pSigInfo, int nType) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); if(pSigInfo->pCertIDs) return ddocCertIDList_GetCertIDOfType(pSigInfo->pCertIDs, nType); return NULL; } //-------------------------------------------------- // Finds last CertID object of this signature // pSigInfo - signature info object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocSigInfo_GetLastCertID(const SignatureInfo* pSigInfo) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); if(pSigInfo->pCertIDs) return ddocCertIDList_GetLastCertID(pSigInfo->pCertIDs); return NULL; } //-------------------------------------------------- // Finds a CertID object with required type or creates a new one // pSigInfo - signature info object [REQUIRED] // nType - type of CertID object [REQUIRED] // returns CertID pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertID* ddocSigInfo_GetOrCreateCertIDOfType(SignatureInfo* pSigInfo, int nType) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); if(!pSigInfo->pCertIDs) ddocCertIDList_new(&(pSigInfo->pCertIDs)); RETURN_OBJ_IF_NULL(pSigInfo->pCertIDs, NULL); return ddocCertIDList_GetOrCreateCertIDOfType(pSigInfo->pCertIDs, nType); } //-------------------------------------------------- // Finds a CertValue object with required type // pSigInfo - signature info object [REQUIRED] // nType - type of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocSigInfo_GetCertValueOfType(const SignatureInfo* pSigInfo, int nType) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); ddocDebug(9, "ddocSigInfo_GetCertValueOfType", "start"); if(pSigInfo->pCertValues) return ddocCertValueList_GetCertValueOfType(pSigInfo->pCertValues, nType); ddocDebug(9, "ddocSigInfo_GetCertValueOfType", "end"); return NULL; } //-------------------------------------------------- // Finds a CertValue object with required type or creates a new one // pSigInfo - signature info object [REQUIRED] // nType - type of CertValue object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocSigInfo_GetOrCreateCertValueOfType(SignatureInfo* pSigInfo, int nType) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); if(!pSigInfo->pCertValues) ddocCertValueList_new(&(pSigInfo->pCertValues)); RETURN_OBJ_IF_NULL(pSigInfo->pCertValues, NULL); return ddocCertValueList_GetOrCreateCertValueOfType(pSigInfo->pCertValues, nType); } //-------------------------------------------------- // Finds last CertValue // pSigInfo - signature info object [REQUIRED] // returns CertValue pointer or NULL for error //-------------------------------------------------- EXP_OPTION CertValue* ddocSigInfo_GetLastCertValue(const SignatureInfo* pSigInfo) { RETURN_OBJ_IF_NULL(pSigInfo, NULL); if(pSigInfo->pCertValues) return ddocCertValueList_GetCertValue(pSigInfo->pCertValues, ddocCertValueList_GetCertValuesCount(pSigInfo->pCertValues) - 1); return NULL; } //-------------------------------------------------- // Finds the signers certificate // pSigInfo - signature info object [REQUIRED] // returns certificate or NULL //-------------------------------------------------- EXP_OPTION X509* ddocSigInfo_GetSignersCert(const SignatureInfo* pSigInfo) { X509 *pCert = 0; CertValue *pCertValue = 0; RETURN_OBJ_IF_NULL(pSigInfo, NULL); if(pSigInfo->pCertValues) { pCertValue = ddocSigInfo_GetCertValueOfType(pSigInfo, CERTID_VALUE_SIGNERS_CERT); if(pCertValue) pCert = pCertValue->pCert; } return pCert; } //-------------------------------------------------- // Sets the signers certificate // pSigInfo - signature info object [REQUIRED] // pCert - certificate [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSigInfo_SetSignersCert(SignatureInfo* pSigInfo, X509* pCert) { int err = ERR_OK; CertValue *pCertValue = 0; char buf1[50]; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pCert); pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_SIGNERS_CERT); if(pCertValue) { snprintf(buf1, sizeof(buf1), "%s-SIGNER_CERT", pSigInfo->szId); err = ddocCertValue_SetId(pCertValue, buf1); if(!err && pCert) err = ddocCertValue_SetCert(pCertValue, pCert); } return err; } //-------------------------------------------------- // Finds the OCSP responders certificate // pSigInfo - signature info object [REQUIRED] // returns certificate or NULL //-------------------------------------------------- EXP_OPTION X509* ddocSigInfo_GetOCSPRespondersCert(const SignatureInfo* pSigInfo) { X509 *pCert = 0; CertValue *pCertValue = 0; RETURN_OBJ_IF_NULL(pSigInfo, NULL); if(pSigInfo->pCertValues) { ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "start"); pCertValue = ddocSigInfo_GetCertValueOfType(pSigInfo, CERTID_VALUE_RESPONDERS_CERT); ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "end"); if(pCertValue){ pCert = pCertValue->pCert; ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "test");} } ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "end2"); if(pCert) ddocDebug(5, "ddocSigInfo_GetOCSPRespondersCert", "pCert exists" ); return pCert; } //-------------------------------------------------- // Sets the OCSP Responders certificate // pSigInfo - signature info object [REQUIRED] // pCert - certificate [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSigInfo_SetOCSPRespondersCert(SignatureInfo* pSigInfo, X509* pCert) { int err = ERR_OK; CertValue *pCertValue = 0; char buf1[50]; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pCert); pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_RESPONDERS_CERT); if(pCertValue) { snprintf(buf1, sizeof(buf1), "%s-RESPONDER_CERT", pSigInfo->szId); err = ddocCertValue_SetId(pCertValue, buf1); if(!err) err = ddocCertValue_SetCert(pCertValue, pCert); } return err; } //============================================================ // Adds a certificate and it's certid to this signature // pSigInfo - signature info object [REQUIRED] // pCert - vertificate [REQUIRED] // nCertIdType - type of cert [REQUIRED] // return error code or ERR_OK //============================================================ EXP_OPTION int ddocSigInfo_addCert(SignatureInfo* pSigInfo, X509* pCert, int nCertIdType) { int err = ERR_OK, l1; char buf1[100], buf2[200], buf3[300], buf4[100]; CertID *pCertID = 0; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NOT(err == ERR_OK, err); l1 = sizeof(buf1); RETURN_IF_NOT(X509_digest(pCert, EVP_sha1(), (unsigned char*)buf1, (unsigned int*)&l1), ERR_X509_DIGEST); if(err) return err; err = ReadCertSerialNumber(buf2, sizeof(buf2), pCert); memset(buf3, 0, sizeof(buf3)); err = ddocCertGetIssuerDN(pCert, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); // now set all those atributes switch(nCertIdType) { case CERTID_TYPE_SIGNERS_CERTID: err = ddocSigInfo_SetSignersCert(pSigInfo, pCert); snprintf(buf4, sizeof(buf4), "%s-CERTINFO", pSigInfo->szId); ddocCertID_new(&pCertID, CERTID_TYPE_SIGNERS_CERTID, buf4, buf2, (char*)mbuf1.pMem, buf1, l1); break; case CERTID_TYPE_RESPONDERS_CERTID: err = ddocSigInfo_SetOCSPRespondersCert(pSigInfo, pCert); snprintf(buf4, sizeof(buf4), "%s-OCSP_CERTINFO", pSigInfo->szId); ddocCertID_new(&pCertID, CERTID_TYPE_RESPONDERS_CERTID, buf4, buf2, (char*)mbuf1.pMem, buf1, l1); break; } RETURN_IF_NOT(pCertID, ERR_BAD_ALLOC); if(!pSigInfo->pCertIDs) { err = ddocCertIDList_new(&(pSigInfo->pCertIDs)); //ddocCertID_free(pCertID); // not owner any more! SET_LAST_ERROR_IF_NOT(err == ERR_OK, err); } if(pCertID) { ddocCertIDList_addCertID(pSigInfo->pCertIDs, pCertID); ddocDebug(3, "ddocSigInfo_addCert", "Added signers cert-id: %s type: %d", pCertID->szId, pCertID->nType); } ddocMemBuf_free(&mbuf1); return err; } //======================< DocInfo functions >========================================= //============================================================ // Adds a new DocInfo element to a SignatureInfo element and initializes it // pSigInfo - signature info object // docId - document id (use NULL for default) // digType - digest type // digest - documents digest // digLen - digest length // mime - mime type // mimeDig - mime digest // mimeDigLen - mime digest length // return the newly created structure //============================================================ EXP_OPTION int addDocInfo(DocInfo **newDocInfo, SignatureInfo* pSigInfo, const char* docId, const char* digType, const byte* digest, int digLen, const byte* mimeDig, int mimeDigLen) { DocInfo** pDocInfos = NULL; DocInfo* pDocInfo = NULL; int i; RETURN_IF_NULL_PARAM(pSigInfo); if(pSigInfo->nDocs == 0) { RETURN_IF_NOT(!pSigInfo->pDocs, ERR_BAD_DOCINFO_COUNT); pSigInfo->nDocs = 1; } else pSigInfo->nDocs++; pDocInfos = (DocInfo**)malloc((pSigInfo->nDocs) * sizeof(void *)); RETURN_IF_BAD_ALLOC(pDocInfos); for(i = 0; i < pSigInfo->nDocs-1; i++) pDocInfos[i] = pSigInfo->pDocs[i]; pDocInfo = (DocInfo*)malloc(sizeof(DocInfo)); // MEMLEAK: ??? if (!pDocInfo) { free(pDocInfos); SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); } memset(pDocInfo, 0, sizeof(DocInfo)); pDocInfos[pSigInfo->nDocs-1] = pDocInfo; // PR. leak found if(pSigInfo->pDocs) free(pSigInfo->pDocs); pSigInfo->pDocs = pDocInfos; if(docId) setString(&(pDocInfo->szDocId), docId, -1); if(digType) setString(&(pDocInfo->szDigestType), digType, -1); if(digest) { setString((char**)&(pDocInfo->szDigest), (const char*)digest, digLen); pDocInfo->nDigestLen = digLen; } if(mimeDig && strlen((const char*)mimeDig)) { setString((char**)&(pDocInfo->szMimeDigest), (const char*)mimeDig, mimeDigLen); pDocInfo->nMimeDigestLen = mimeDigLen; } *newDocInfo = pDocInfo; return ERR_OK; } //============================================================ // cleanup DocInfo memory // pDocInfo - object to be cleaned up //============================================================ EXP_OPTION void DocInfo_free(DocInfo* pDocInfo) { RETURN_VOID_IF_NULL(pDocInfo); //assert(pDocInfo); if(pDocInfo->szDocId) free(pDocInfo->szDocId); if(pDocInfo->szDigestType) free(pDocInfo->szDigestType); if(pDocInfo->szDigest) free(pDocInfo->szDigest); if(pDocInfo->szMimeDigest) free(pDocInfo->szMimeDigest); // free the object itself free(pDocInfo); } //============================================================ // Returns number of DocInfos // pSigInfo - signature info pointer //============================================================ EXP_OPTION int getCountOfDocInfos(const SignatureInfo* pSigInfo) { RETURN_OBJ_IF_NULL(pSigInfo, -1); return pSigInfo->nDocs; } //============================================================ // Returns the desired DocInfo // pSigInfo - signature info pointer // idx - DocInfo index //============================================================ EXP_OPTION DocInfo* getDocInfo(const SignatureInfo* pSigInfo, int idx) { ddocDebug(3, "getDocInfo", "Idx: %d, Docs: %d", idx, pSigInfo->nDocs); RETURN_OBJ_IF_NULL(pSigInfo, NULL); SET_LAST_ERROR_RETURN_IF_NOT(idx < pSigInfo->nDocs, ERR_BAD_DOCINFO_INDEX, NULL); RETURN_OBJ_IF_NULL(pSigInfo->pDocs, NULL); RETURN_OBJ_IF_NULL(pSigInfo->pDocs[idx], NULL); return pSigInfo->pDocs[idx]; } //============================================================ // Returns the last DocInfo // pSigInfo - signature info pointer // idx - DocInfo index //============================================================ EXP_OPTION DocInfo* ddocGetLastDocInfo(const SignatureInfo* pSigInfo) { int idx; RETURN_OBJ_IF_NULL(pSigInfo, NULL); idx = pSigInfo->nDocs - 1; SET_LAST_ERROR_RETURN_IF_NOT(idx < pSigInfo->nDocs, ERR_BAD_DOCINFO_INDEX, NULL); RETURN_OBJ_IF_NULL(pSigInfo->pDocs, NULL); RETURN_OBJ_IF_NULL(pSigInfo->pDocs[idx], NULL); return pSigInfo->pDocs[idx]; } //============================================================ // Returns the DocInfo object with the given id // pSigInfo - signature info pointer // id - SignatureInfo id //============================================================ EXP_OPTION DocInfo* getDocInfoWithId(const SignatureInfo* pSigInfo, const char* id) { DocInfo* pDocInfo = NULL; int i; RETURN_OBJ_IF_NULL(pSigInfo, NULL); //RETURN_OBJ_IF_NULL(id, NULL); for(i = 0; i < pSigInfo->nDocs; i++) { RETURN_OBJ_IF_NULL(pSigInfo->pDocs[i], NULL); RETURN_OBJ_IF_NULL(pSigInfo->pDocs[i]->szDocId, NULL); if((id && !strcmp(pSigInfo->pDocs[i]->szDocId, id)) || !id) { pDocInfo = pSigInfo->pDocs[i]; break; } } return pDocInfo; } //============================================================ // Sets the DocInfo objects document digest and digest type // pDocInfo - document info pointer // digest - digest value // digLen - digest value length // digType - digest type //============================================================ EXP_OPTION void setDocInfoDigest(DocInfo* pDocInfo, const byte* digest, int digLen, const char* digType) { RETURN_VOID_IF_NULL(pDocInfo); if(digType) setString(&(pDocInfo->szDigestType), digType, -1); if(digest) { setString((char**)&(pDocInfo->szDigest), (const char*)digest, digLen); pDocInfo->nDigestLen = digLen; } } //============================================================ // Sets the DocInfo objects mime digest and mime type // pDocInfo - document info pointer // mimeDig - mime digest value // mimeDigLen - mime digest value length //============================================================ EXP_OPTION void setDocInfoMimeDigest(DocInfo* pDocInfo, const byte* mimeDig, int mimeDigLen) { RETURN_VOID_IF_NULL(pDocInfo); if(mimeDig) { setString((char**)&(pDocInfo->szMimeDigest), (const char*)mimeDig, mimeDigLen); pDocInfo->nMimeDigestLen = mimeDigLen; } } //============================================================ // Adds all DocInfo elements in this file to a SignatureInfo element // pSigInfo - signature info object // pSigDoc - signed document //============================================================ EXP_OPTION int addAllDocInfos(SignedDoc* pSigDoc, SignatureInfo* pSigInfo) { int i, c, l2; int len = 0; //Added by AA 28/10/2003 - not defined len value DataFile *pDf = NULL; DocInfo *pDocInfo = NULL; byte buf[DIGEST_LEN+2], buf2[50]; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pSigInfo); c = getCountOfDataFiles(pSigDoc); for(i = 0; i < c; i++ ) { pDf = getDataFile(pSigDoc, i); RETURN_IF_NULL(pDf); buf[0] = 0; // in version 1.0 we use mime digest if(!strcmp(pSigDoc->szFormatVer, SK_XML_1_VER) && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { len = sizeof(buf); calculateDigest((const byte*)pDf->szMimeType, strlen(pDf->szMimeType), DIGEST_SHA1, buf, &len); } // in 1.1 we don't use mime digest memset(buf2, 0, sizeof(buf2)); l2 = 0; encode((const byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, (byte*)buf2, &l2); ddocDebug(3, "addAllDocInfos", "DF: %s digest \'%s\'", pDf->szId, buf2); addDocInfo(&pDocInfo, pSigInfo, pDf->szId, pDf->szDigestType, (byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, buf, len); } return ERR_OK; } //============================================================ // Calculates and stores a signature for this SignatureInfo object // pSigInfo - signature info object // nSigType - signature type code // keyfile - RSA key file // passwd - key password // certfile - certificate file //============================================================ EXP_OPTION int calculateSigInfoSignature(const SignedDoc* pSigDoc, SignatureInfo* pSigInfo, int nSigType, const char* keyfile, const char* passwd, const char* certfile) { int err = ERR_OK; char buf2[SIGNATURE_LEN], *buf1 = NULL; int l2, l1; X509 *pCert = 0; RETURN_IF_NULL_PARAM(pSigInfo); clearErrors(); if(nSigType == SIGNATURE_RSA) { err = ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, SIGN_RSA_NAME, 0, 0); if(err) return err; err = ReadCertificate(&pCert, certfile); if(!err && pCert) err = ddocSigInfo_SetSignersCert(pSigInfo, pCert); RETURN_IF_NOT(err == ERR_OK, ERR_CERT_READ); // Signed properties digest buf1 = createXMLSignedProperties(pSigDoc, pSigInfo, 0); RETURN_IF_NULL(buf1); l1 = strlen(buf1); l2 = sizeof(buf2); calculateDigest((const byte*)buf1, l1, DIGEST_SHA1, (byte*)buf2, &l2); free(buf1); err = ddocSigInfo_SetSigPropDigest(pSigInfo, buf2, l2); // SignedInfo digest buf1 = createXMLSignedInfo(pSigDoc, pSigInfo); RETURN_IF_NULL(buf1); l2 = sizeof(buf2); err = signData((const byte*)buf1, strlen(buf1), (byte*)buf2, &l2, DIGEST_SHA1, keyfile, passwd); free(buf1); err = ddocSigInfo_SetSignatureValue(pSigInfo, buf2, l2); } else err = ERR_UNSUPPORTED_SIGNATURE; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // Calculates digest // pSigInfo - signature info object //============================================================ EXP_OPTION int calculateSignedPropertiesDigest(SignedDoc* pSigDoc, SignatureInfo* pSigInfo) { int err = ERR_OK, l1, l2; byte buf1[DIGEST_LEN256+2], *buf2 = 0, *buf3 = 0; RETURN_IF_NULL_PARAM(pSigInfo); /* P.R 0->1 */ buf2 = (byte*)createXMLSignedProperties(pSigDoc, pSigInfo, 1); RETURN_IF_NULL(buf2); buf3 = canonicalizeXML((char*)buf2, strlen((const char*)buf2)); //dumpInFile("sigprop-sig1.txt", buf2); l2 = (int)strlen((const char*)buf3); l1 = (int)sizeof(buf1); calculateDigest(buf3, l2, DIGEST_SHA1, buf1, &l1); free(buf2); free(buf3); err = ddocSigInfo_SetSigPropDigest(pSigInfo, (char*)buf1, l1); return err; } //============================================================ // Returns 1 if this signature has 1 reference that was verified // by wrong DataFile hash calculated not using xmlns atribute // pSigInfo - signature info pointer //============================================================ EXP_OPTION int verifiedByWrongDataFileHash(const SignatureInfo* pSigInfo) { int i; RETURN_IF_NULL_PARAM(pSigInfo); for(i = 0; i < pSigInfo->nDocs; i++) { RETURN_IF_NULL_PARAM(pSigInfo->pDocs[i]); if(pSigInfo->pDocs[i] && pSigInfo->pDocs[i]->szDigestType && !strcmp(pSigInfo->pDocs[i]->szDigestType, DIGEST_SHA1_WRONG)) return 1; } return 0; } //============================================================ // Returns 1 if one signature has 1 reference that was verified // by wrong DataFile hash calculated not using xmlns atribute // pSigDoc - signed doc container pointer //============================================================ EXP_OPTION int hasSignatureWithWrongDataFileHash(const SignedDoc* pSigDoc) { int i, d, j; SignatureInfo *pSigInfo = 0; RETURN_IF_NULL_PARAM(pSigDoc); d = getCountOfSignatures(pSigDoc); for(i = 0; i < d; i++) { pSigInfo = getSignature(pSigDoc, i); j = verifiedByWrongDataFileHash(pSigInfo); if(j) return j; } return 0; } //============================================================ // Calculates digest // pSigInfo - signature info object // digBuf - buffer for digest value // digLen - address of buffer length. Must be initialized // with buf max len, will be changed to actual length //============================================================ EXP_OPTION int calculateSignedInfoDigest(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, byte* digBuf, int* digLen) { int err = ERR_OK, l2; byte *buf2 = NULL; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(digBuf); buf2 = (byte*)createXMLSignedInfo(pSigDoc, pSigInfo); RETURN_IF_NULL(buf2); l2 = strlen((const char*)buf2); calculateDigest(buf2, l2, DIGEST_SHA1, digBuf, digLen); free(buf2); return err; } //============================================================ // Sets the signature value from a file that contains // the base64 encoded signature value // pSigInfo - signature info object // szSigFile - filename //============================================================ EXP_OPTION int setSignatureValueFromFile(SignatureInfo* pSigInfo, char* szSigFile) { int err = ERR_OK, i, j, slen; FILE* hFile = 0; byte buf[FILE_BUFSIZE], sbuf[300], buf1[30]; DigiDocMemBuf mbuf1; char *p1; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(szSigFile); mbuf1.pMem = 0; mbuf1.nLen = 0; ddocDebug(3, "setSignatureValueFromFile", "reading: %s", szSigFile); if((hFile = fopen(szSigFile, "rb")) != NULL) { slen = 0; memset(sbuf, 0, sizeof(sbuf)); // collect all hex chars to sbuf while((i = fread(buf, sizeof(char), FILE_BUFSIZE, hFile)) > 0) { ddocDebug(3, "setSignatureValueFromFile", "read: %d", i); for(j = 0; j < i; j++) { if(isxdigit(buf[j])) { if(isdigit(buf[j])) { sbuf[slen++] = buf[j]; } else { sbuf[slen++] = toupper(buf[j]); } // else } // if } // for } ddocDebug(3, "setSignatureValueFromFile", "input: %d - \'%s\'", slen, sbuf); // decode hex memset(buf, 0, sizeof(buf)); j = 0; hex2bin((const char*)sbuf, (byte*)buf, &j); ddocDebug(3, "setSignatureValueFromFile", "decoded: %d", j); // encode in base64 again as we need it this way for signature value memset(sbuf, 0, sizeof(sbuf)); slen = 0; encode((const byte*)buf, j, (byte*)sbuf, &slen); ddocDebug(3, "setSignatureValueFromFile", "encoded: %d - \'%s\'", slen, sbuf); if(j == SIGNATURE_LEN) { snprintf((char*)buf1, sizeof(buf1), "#%s-SIG", pSigInfo->szId); ddocSignatureValue_new(&(pSigInfo->pSigValue), (char*)buf1, SIGN_RSA_NAME, (char*)buf, j); //ddocMemBuf_free(&(pSigInfo->mbufOrigContent)); if(pSigInfo->mbufOrigContent.pMem) { p1 = strstr((char*)pSigInfo->mbufOrigContent.pMem, "'); if(p1) p1++; if(p1) *p1 = 0; if(p1) { ddocMemAssignData(&mbuf1, (char*)pSigInfo->mbufOrigContent.pMem, -1); ddocMemAppendData(&mbuf1, (char*)sbuf, -1); p1++; //ddocDebug(3, "setSignatureValueFromFile", "add: %s", p1); ddocMemAppendData(&mbuf1, p1, -1); } ddocMemAssignData(&(pSigInfo->mbufOrigContent), (const char*)mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); } } else err = ERR_SIGNATURE; fclose(hFile); } else err = ERR_FILE_READ; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //============================================================ // Sets the signature value // pSigInfo - signature info object // szSignature - signature value // sigLen - signature length //============================================================ EXP_OPTION int setSignatureValue(SignatureInfo* pSigInfo, byte* szSignature, int sigLen) { RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(szSignature); //clearErrors(); // VS: not quite sure if there's not a second constant to use instead of removing the check //RETURN_IF_NOT(sigLen == SIGNATURE_LEN, ERR_SIGNATURE); ddocSignatureValue_new(&(pSigInfo->pSigValue), 0, SIGN_RSA_NAME, szSignature, sigLen); ddocMemBuf_free(&(pSigInfo->mbufOrigContent)); return ERR_OK; } //=====================< NotaryInfo >====================================== //============================================================ // Returns the number of notary infos // pSigDoc - signed doc pointer //============================================================ EXP_OPTION int getCountOfNotaryInfos(const SignedDoc* pSigDoc) { int n = 0, i = 0; SignatureInfo* pSigInfo = 0; RETURN_OBJ_IF_NULL(pSigDoc, -1); for(i = 0; i < getCountOfSignatures(pSigDoc); i++) { pSigInfo = getSignature(pSigDoc, i); if(pSigInfo->pNotary) n++; } return n; } //============================================================ // Returns the next free notary id // pSigDoc - signed doc pointer //============================================================ EXP_OPTION int getNextNotaryId(const SignedDoc* pSigDoc) { int id = 0, n, i; SignatureInfo* pSigInfo = 0; RETURN_OBJ_IF_NULL(pSigDoc, -1); for(i = 0; i < getCountOfSignatures(pSigDoc); i++) { pSigInfo = getSignature(pSigDoc, i); if(pSigInfo->pNotary && pSigInfo->pNotary->szId) { n = atoi(pSigInfo->pNotary->szId+1); if(id <= n) id = n+1; } } return id; } //============================================================ // Returns the desired NotaryInfo object // pSigDoc - signed doc pointer // nIdx - NotaryInfo index (starting with 0) //============================================================ EXP_OPTION NotaryInfo* getNotaryInfo(const SignedDoc* pSigDoc, int nIdx) { SignatureInfo* pSigInfo = 0; NotaryInfo* pNotInfo = 0; int n = 0, i = 0; RETURN_OBJ_IF_NULL(pSigDoc, NULL); for(i = 0; i < getCountOfSignatures(pSigDoc); i++) { pSigInfo = getSignature(pSigDoc, i); if(pSigInfo->pNotary) { n++; if(n == nIdx) { pNotInfo = pSigInfo->pNotary; break; } } } return pNotInfo; } //============================================================ // Returns the last NotaryInfo object // pSigDoc - signed doc pointer // nIdx - NotaryInfo index (starting with 0) //============================================================ EXP_OPTION NotaryInfo* ddocGetLastNotaryInfo(const SignedDoc* pSigDoc) { SignatureInfo* pSigInfo; RETURN_OBJ_IF_NULL(pSigDoc, NULL); pSigInfo = ddocGetLastSignature(pSigDoc); RETURN_OBJ_IF_NULL(pSigInfo, NULL); return pSigInfo->pNotary; } //============================================================ // Returns the NotaryInfo object with the given id // pSigDoc - signed doc pointer // id - NotaryInfo id //============================================================ EXP_OPTION NotaryInfo* getNotaryWithId(const SignedDoc* pSigDoc, const char* id) { SignatureInfo* pSigInfo = 0; int i = 0; RETURN_OBJ_IF_NULL(pSigDoc, NULL); for(i = 0; i < getCountOfSignatures(pSigDoc); i++) { pSigInfo = getSignature(pSigDoc, i); if(pSigInfo->pNotary && pSigInfo->pNotary->szId && !strcmp(pSigInfo->pNotary->szId, id)) { return pSigInfo->pNotary; } } return NULL; } //============================================================ // Returns the NotaryInfo object that corresponds to the given signature // pSigDoc - signed doc pointer // id - NotaryInfo id //============================================================ NotaryInfo* getNotaryWithSigId(const SignedDoc* pSigDoc, const char* sigId) { SignatureInfo* pSigInfo = NULL; RETURN_OBJ_IF_NULL(pSigDoc, NULL); RETURN_OBJ_IF_NULL(sigId, NULL); pSigInfo = getSignatureWithId(pSigDoc, sigId); RETURN_OBJ_IF_NULL(pSigInfo, NULL); return pSigInfo->pNotary; } //============================================================ // Returns the NotaryInfo object that corresponds to the given signature // ore creates a new one // pSigDoc - signed doc pointer // id - SignatureInfo id //============================================================ NotaryInfo* getOrCreateNotaryWithSigId(SignedDoc* pSigDoc, const char* sigId) { NotaryInfo* pNotary = 0; SignatureInfo* pSigInfo = 0; RETURN_OBJ_IF_NULL(pSigDoc, NULL); RETURN_OBJ_IF_NULL(sigId, NULL); pNotary = getNotaryWithSigId(pSigDoc, sigId); if(!pNotary) { pSigInfo = getSignatureWithId(pSigDoc, sigId); RETURN_OBJ_IF_NULL(pSigInfo, NULL); NotaryInfo_new(&pNotary, pSigDoc, pSigInfo); } return pNotary; } //============================================================ // Adds a new Notary element to a SignedDoc element and // initializes it partly // pSigInfo - signature object to be verified by this notary // return the newly created structure //============================================================ EXP_OPTION int NotaryInfo_new(NotaryInfo **newNotaryInfo, SignedDoc* pSigDoc, SignatureInfo* pSigInfo) { int n; char buf[10]; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pSigInfo); // get next notary id if (pSigInfo) { strncpy(buf, pSigInfo->szId, sizeof(buf)); buf[0] = 'N'; // make sure we reset the szOrigContent on this signature // otherwise the new confirmation will not be written to file! ddocMemBuf_free(&(pSigInfo->mbufOrigContent)); } else { n = getNextNotaryId(pSigDoc); RETURN_IF_NOT(n >= 0, ERR_BAD_NOTARY_ID); snprintf(buf, sizeof(buf), "N%d", n); } // memory management pSigInfo->pNotary = (NotaryInfo*)malloc(sizeof(NotaryInfo)); // MEMLEAK: ??? if (!pSigInfo->pNotary) RETURN_IF_BAD_ALLOC(pSigInfo->pNotary); memset(pSigInfo->pNotary, 0, sizeof(NotaryInfo)); // set id setString(&(pSigInfo->pNotary->szId), buf, -1); // version setString(&(pSigInfo->pNotary->szNotType), SK_NOT_VERSION, -1); *newNotaryInfo = pSigInfo->pNotary; return ERR_OK; } //============================================================ // cleanup NotaryInfo memory // pNotary - object to be cleaned up //============================================================ EXP_OPTION void NotaryInfo_free(NotaryInfo* pNotary) { RETURN_VOID_IF_NULL(pNotary); //assert(pNotary); if(pNotary->szId) free(pNotary->szId); if(pNotary->szNotType) free(pNotary->szNotType); if(pNotary->timeProduced) free(pNotary->timeProduced); if(pNotary->szProducedAt) free(pNotary->szProducedAt); ddocMemBuf_free(&(pNotary->mbufRespId)); if(pNotary->szDigestType) free(pNotary->szDigestType); if(pNotary->szSigType) free(pNotary->szSigType); ddocMemBuf_free(&(pNotary->mbufOcspDigest)); ddocMemBuf_free(&(pNotary->mbufOcspResponse)); // free the object itself free(pNotary); } //============================================================ // Returns OCSP responders id as in XML document // pNotary - Notary info // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ EXP_OPTION const DigiDocMemBuf* ddocNotInfo_GetResponderId(const NotaryInfo* pNotary) { RETURN_OBJ_IF_NULL(pNotary, NULL); return &(pNotary->mbufRespId); } //============================================================ // Returns OCSP responders id value as string // pNotary - Notary info // return responder id value or NULL //============================================================ EXP_OPTION const char* ddocNotInfo_GetResponderId_Value(const NotaryInfo* pNotary) { RETURN_OBJ_IF_NULL(pNotary, NULL); return (const char*)pNotary->mbufRespId.pMem; } //============================================================ // Sets OCSP responders id as in XML document // pNotary - Notary info // data - new responder id value // len - length of value // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ int ddocNotInfo_SetResponderId(NotaryInfo* pNotary, const char* data, long len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(data); err = ddocMemAssignData(&(pNotary->mbufRespId), data, len); return err; } //============================================================ // Returns OCSP response as memory buffer // pNotary - Notary info // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ const DigiDocMemBuf* ddocNotInfo_GetOCSPResponse(const NotaryInfo* pNotary) { RETURN_OBJ_IF_NULL(pNotary, NULL); return &(pNotary->mbufOcspResponse); } //============================================================ // Retrieves OCSP responses responder id type and value // pResp - OCSP response // pType - buffer for type // pMbufRespId - responder id // returns error code or ERR_OK //============================================================ int ddocGetOcspRespIdTypeAndValue(OCSP_RESPONSE* pResp, int *pType, DigiDocMemBuf* pMbufRespId) { int err = ERR_OK; OCSP_BASICRESP *br = NULL; const X509_NAME *name = NULL; const ASN1_OCTET_STRING *id = NULL; RETURN_IF_NULL_PARAM(pResp); RETURN_IF_NULL_PARAM(pType); RETURN_IF_NULL_PARAM(pMbufRespId); if((br = OCSP_response_get1_basic(pResp)) == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_BASIC_RESP); if(!err && br) { OCSP_resp_get0_id(br, &id, &name); if(name) { *pType = RESPID_NAME_TYPE; ddocMemSetLength(pMbufRespId, 300); //X509_NAME_oneline(br->tbsResponseData->responderId->value.byName, (char*)pMbufRespId->pMem, pMbufRespId->nLen); //AM 26.09.08 err = ddocCertGetDNFromName((X509_NAME*)name, pMbufRespId); //RETURN_IF_NOT(err == ERR_OK, err); } else if(id) { *pType = RESPID_KEY_TYPE; err = ddocMemAssignData(pMbufRespId, (const char*)id->data, id->length); } else { SET_LAST_ERROR(ERR_OCSP_WRONG_RESPID); } } if(br) OCSP_BASICRESP_free(br); return err; } //============================================================ // Sets OCSP respondese value as in XML document. Must pass in // binary DER data! // pNotary - Notary info // data - new responder id value // len - length of value // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ int ddocNotInfo_SetOCSPResponse(NotaryInfo* pNotary, const char* data, long len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(data); err = ddocMemAssignData(&(pNotary->mbufOcspResponse), data, len); return err; } //============================================================ // Returns OCSP response value // pNotary - Notary info // return OCSP_RESPONSE pointer or NULL for error. Caller must // use OCSP_RESPONSE_free() to release it. //============================================================ OCSP_RESPONSE* ddocNotInfo_GetOCSPResponse_Value(const NotaryInfo* pNotary) { OCSP_RESPONSE* pResp = NULL; RETURN_OBJ_IF_NULL(pNotary, NULL); RETURN_OBJ_IF_NULL(pNotary->mbufOcspResponse.pMem, NULL); ddocOcspReadOcspResp(&pResp, (DigiDocMemBuf*)&(pNotary->mbufOcspResponse)); return pResp; } //============================================================ // Sets OCSP respondese value. Must pass in real OCSP_RESPONSE // pNotary - Notary info // data - new responder id value // len - length of value // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ int ddocNotInfo_SetOCSPResponse_Value(NotaryInfo* pNotary, OCSP_RESPONSE* pResp) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pResp); err = ddocOcspWriteOcspResp(pResp, (DigiDocMemBuf*)&(pNotary->mbufOcspResponse)); return err; } //============================================================ // Helper function to get OCSP response parts // pNotary - notary object // ppResp - adr for OCSP_RESPONSE - must free! // ppBasResp - adr for OCSP_BASICRESP - don't free // ppSingle - optional adr for OCSP_SINGLERESP - don't free //============================================================ int ddocNotInfo_GetBasicResp(const NotaryInfo* pNotary, OCSP_RESPONSE **ppResp, OCSP_BASICRESP **ppBasResp, OCSP_SINGLERESP **ppSingle) { int err = ERR_OK; // check input RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(ppResp); RETURN_IF_NULL_PARAM(ppBasResp); // single response retrieval is optional - don't check it *ppResp = ddocNotInfo_GetOCSPResponse_Value(pNotary); if(*ppResp && ppBasResp) { *ppBasResp = OCSP_response_get1_basic(*ppResp); if(*ppBasResp) { if(ppSingle) *ppSingle = OCSP_resp_get0(*ppBasResp, 0); } else return ERR_OCSP_NO_BASIC_RESP; } return err; } //============================================================ // Returns OCSP responders id type as string // pNotary - Notary info // return responder id type or NULL. DO NOT free() it! //============================================================ EXP_OPTION const char* ddocNotInfo_GetResponderId_Type(const NotaryInfo* pNotary) { int err = ERR_OK; OCSP_RESPONSE *pResp = 0; OCSP_BASICRESP *br = NULL; const ASN1_OCTET_STRING *id = NULL; const X509_NAME *name = NULL; char *p1 = RESPID_NAME_VALUE; // default value is name - usefull in format 1.0 where we had no good OCSP response RETURN_OBJ_IF_NULL(pNotary, NULL); err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, NULL); if(!err && br) { OCSP_resp_get0_id(br, &id, &name); if(name) p1 = RESPID_NAME_VALUE; else if(id) p1 = RESPID_KEY_VALUE; else SET_LAST_ERROR(ERR_OCSP_WRONG_RESPID); } if(pResp) OCSP_RESPONSE_free(pResp); // PR. leak found if(br) OCSP_BASICRESP_free(br); return p1; } //============================================================ // Returns OCSP responses thisUpdate atribute as string // pNotary - Notary info // pMBuf - buffer for thisUpdate value // return error code OR ERR_OK. //============================================================ EXP_OPTION int ddocNotInfo_GetThisUpdate(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf) { int err = ERR_OK; OCSP_RESPONSE *pResp = 0; OCSP_BASICRESP *br = NULL; OCSP_SINGLERESP *single = NULL; ASN1_GENERALIZEDTIME *thisUpdate = NULL; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pMBuf); err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single); if(!err && br && single) { err = ddocMemSetLength(pMBuf, 50); OCSP_single_get0_status(single, NULL, NULL, &thisUpdate, NULL); ddocDebug(3, "ddocNotInfo_GetThisUpdate", "This update: %s", thisUpdate); if(!err && thisUpdate) err = asn1time2str(NULL, thisUpdate, (char*)pMBuf->pMem, pMBuf->nLen); } if(pResp) OCSP_RESPONSE_free(pResp); // PR. leak found if(br) OCSP_BASICRESP_free(br); return err; } //============================================================ // Returns OCSP responses thisUpdate atribute as time_t // pNotary - Notary info // pTime - address of time_t variable // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetThisUpdate_timet(const NotaryInfo* pNotary, time_t* pTime) { int err = ERR_OK; OCSP_RESPONSE *pResp = 0; OCSP_BASICRESP *br = NULL; OCSP_SINGLERESP *single = NULL; ASN1_GENERALIZEDTIME *thisUpdate = NULL; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pTime); err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single); if(!err && br && single) { OCSP_single_get0_status(single, NULL, NULL, &thisUpdate, NULL); if(!err && thisUpdate) err = asn1time2time_t_local(thisUpdate, pTime); } if(pResp) OCSP_RESPONSE_free(pResp); // PR. leak found if(br) OCSP_BASICRESP_free(br); return err; } //============================================================ // Returns OCSP responses producedAt atribute as time_t // pNotary - Notary info // pTime - address of time_t variable // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetProducedAt_timet(const NotaryInfo* pNotary, time_t* pTime) { int err = ERR_OK; OCSP_RESPONSE *pResp = 0; OCSP_BASICRESP *br = NULL; const ASN1_GENERALIZEDTIME *producedAt = NULL; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pTime); err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, NULL); if(br) producedAt = OCSP_resp_get0_produced_at(br); if(!err && br && producedAt) { err = asn1time2time_t_local((ASN1_GENERALIZEDTIME*)producedAt, pTime); } //AM 22.06.08 lets free br too if(br) OCSP_BASICRESP_free(br); if(pResp) OCSP_RESPONSE_free(pResp); return err; } //============================================================ // Returns OCSP responses producedAt from xml as time_t // pNotary - Notary info // pTime - address of time_t variable // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetProducedAtXml_timet(const NotaryInfo* pNotary, time_t* pTime) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pTime); if(!err && pNotary->szProducedAt) { err = str2time_t(pNotary->szProducedAt, pTime); } return err; } //============================================================ // Returns OCSP responses nextUpdate atribute as string // pNotary - Notary info // pMBuf - buffer for nextUpdate value // return error code OR ERR_OK. //============================================================ EXP_OPTION int ddocNotInfo_GetNextUpdate(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf) { int err = ERR_OK; OCSP_RESPONSE *pResp = 0; OCSP_BASICRESP *br = NULL; OCSP_SINGLERESP *single = NULL; ASN1_GENERALIZEDTIME *nextUpdate = NULL; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pMBuf); err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single); if(!err && br && single) { err = ddocMemSetLength(pMBuf, 50); OCSP_single_get0_status(single, NULL, NULL, NULL, &nextUpdate); if(!err && nextUpdate) err = asn1time2str(NULL, nextUpdate, (char*)pMBuf->pMem, pMBuf->nLen); } if(pResp) OCSP_RESPONSE_free(pResp); // PR. leak found if(br) OCSP_BASICRESP_free(br); return err; } //============================================================ // Returns OCSP responses IssuerNameHash atribute // pNotary - Notary info // pMBuf - buffer for IssuerNameHash value // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetIssuerNameHash(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf) { int err = ERR_OK; OCSP_RESPONSE *pResp = 0; OCSP_BASICRESP *br = NULL; OCSP_SINGLERESP *single = NULL; ASN1_OCTET_STRING *issuerNameHash = NULL; const OCSP_CERTID *cid = NULL; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pMBuf); err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single); if(!err && br) { cid = OCSP_SINGLERESP_get0_id(OCSP_resp_get0(br, 0)); OCSP_id_get0_info(&issuerNameHash, NULL, NULL, NULL, (OCSP_CERTID*)cid); err = ddocMemAssignData(pMBuf, (const char*)issuerNameHash->data, issuerNameHash->length); } if(pResp) OCSP_RESPONSE_free(pResp); // PR. leak found if(br) OCSP_BASICRESP_free(br); return err; } //============================================================ // Returns OCSP responses IssuerKeyHash atribute // pNotary - Notary info // pMBuf - buffer for IssuerKeyHash value // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetIssuerKeyHash(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf) { int err = ERR_OK; OCSP_RESPONSE *pResp = 0; OCSP_BASICRESP *br = NULL; OCSP_SINGLERESP *single = NULL; ASN1_OCTET_STRING *issuerKeyHash = NULL; const OCSP_CERTID *cid = NULL; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pMBuf); err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single); if(!err && br) { cid = OCSP_SINGLERESP_get0_id(OCSP_resp_get0(br, 0)); OCSP_id_get0_info(NULL, NULL, &issuerKeyHash, NULL, (OCSP_CERTID*)cid); err = ddocMemAssignData(pMBuf, (const char*)issuerKeyHash->data, issuerKeyHash->length); } if(pResp) OCSP_RESPONSE_free(pResp); // PR. leak found if(br) OCSP_BASICRESP_free(br); return err; } //============================================================ // Returns OCSP responses real digest from response data // pNotary - Notary info // pMBuf - buffer for digest value // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetOcspRealDigest(const SignedDoc* pSigDoc, const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf) { int err = ERR_OK, nIdx = 0, l1 = 0, l2 = 0, nCheckOcspLen = 0; OCSP_RESPONSE *pResp = 0; OCSP_BASICRESP *br = NULL; OCSP_SINGLERESP *single = NULL; X509_EXTENSION *ext = NULL; ASN1_OCTET_STRING *value = NULL; byte* p = 0, buf2[DIGEST_LEN256 * 2 + 2]; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pMBuf); err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, &single); nCheckOcspLen = ConfigItem_lookup_bool("CHECK_OCSP_NONCE", 0); if(!err && br) { nIdx = OCSP_BASICRESP_get_ext_by_NID(br, NID_id_pkix_OCSP_Nonce, -1); if(nIdx >= 0) { ext = OCSP_BASICRESP_get_ext(br, nIdx); if(ext != NULL) { value = X509_EXTENSION_get_data(ext); int l1 = ASN1_STRING_length(value); p = ASN1_STRING_data(value); if(l1 > 20 && p[0] == V_ASN1_OCTET_STRING && p[1] == l1-2) err = ddocMemAssignData(pMBuf, (const char*)p+2, l1-2); else err = ddocMemAssignData(pMBuf, (const char*)p, l1); // debug l2 = sizeof(buf2); memset(buf2, 0, l2); if(l1 <= DIGEST_LEN256) { bin2hex((const byte*)p, l1, (byte*)buf2, &l2); ddocDebug(3, "ddocNotInfo_GetOcspRealDigest", "Not: %s nonce: %s len: %d err: %d", pNotary->szId, buf2, l1, err); } if(l1 != 22 && nCheckOcspLen && pSigDoc && strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { ddocDebug(1, "ddocNotInfo_GetOcspRealDigest", "Not: %s invalid nonce: %s len: %d err: %d", pNotary->szId, buf2, l1, err); err = ERR_OCSP_NONCE_INVALID; } } } else err = ERR_OCSP_NO_NONCE; } if(pResp) OCSP_RESPONSE_free(pResp); if(br) OCSP_BASICRESP_free(br); return err; } //============================================================ // Returns OCSP responses signature value // pNotary - Notary info // pMBuf - buffer for signature value // return error code OR ERR_OK. //============================================================ int ddocNotInfo_GetOcspSignatureValue(const NotaryInfo* pNotary, DigiDocMemBuf* pMBuf) { int err = ERR_OK; OCSP_RESPONSE *pResp = 0; OCSP_BASICRESP *br = NULL; const ASN1_OCTET_STRING *signature = NULL; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pMBuf); err = ddocNotInfo_GetBasicResp(pNotary, &pResp, &br, NULL); if(!err && br) { signature = OCSP_resp_get0_signature(br); err = ddocMemAssignData(pMBuf, (const char*)signature->data, signature->length); } if(pResp) OCSP_RESPONSE_free(pResp); // PR. leak found if(br) OCSP_BASICRESP_free(br); return err; } //============================================================ // Returns OCSP response digest as in XML document // pNotary - Notary info // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ EXP_OPTION const DigiDocMemBuf* ddocNotInfo_GetOcspDigest(const NotaryInfo* pNotary) { RETURN_OBJ_IF_NULL(pNotary, NULL); return &(pNotary->mbufOcspDigest); } //============================================================ // Sets OCSP response digest id as in XML document // pNotary - Notary info // data - new digest value // len - length of value // return DigiDocMemBuf buffer pointer or NULL for error //============================================================ int ddocNotInfo_SetOcspDigest(NotaryInfo* pNotary, const char* data, long len) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(data); err = ddocMemAssignData(&(pNotary->mbufOcspDigest), data, len); return err; } //============================================================ // Adds a certificate to Notary and initializes Notary // pNotary - Notary info // cert - responders certificate // return error code //============================================================ int addNotaryInfoCert(SignedDoc *pSigDoc, NotaryInfo *pNotary, X509 *cert) { int err = ERR_OK, n; char buf[300]; CertID* pCertID = 0; SignatureInfo* pSigInfo = 0; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; ddocDebug(3, "addNotaryInfoCert", "adding cert: %s to notary: %s", (cert ? "OK" : "NULL"), pNotary->szId); RETURN_IF_NULL_PARAM(pNotary); pSigInfo = ddocGetSignatureForNotary(pSigDoc, pNotary); RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(cert); RETURN_IF_NOT(err == ERR_OK, err); if(!ddocSigInfo_GetOCSPRespondersCert(pSigInfo)) err = ddocSigInfo_SetOCSPRespondersCert(pSigInfo, cert); buf[0] = 0; err = ReadCertSerialNumber(buf, sizeof(buf), cert); if(strlen(buf)){ pCertID = ddocCertIDList_GetCertIDOfSerial(pSigInfo->pCertIDs, buf); } if(!pCertID) pCertID = ddocSigInfo_GetOrCreateCertIDOfType(pSigInfo, CERTID_TYPE_RESPONDERS_CERTID); else //AM quick fix for smartlink bdoc if(pCertID->nType==0)pCertID->nType = CERTID_TYPE_RESPONDERS_CERTID; RETURN_IF_NULL(pCertID); ddocCertID_SetIssuerSerial(pCertID, buf); n = sizeof(buf); memset(buf, 0, sizeof(buf)); n = 40; RETURN_IF_NOT(X509_digest(cert, EVP_sha1(), (unsigned char*)buf, (unsigned int*)&n), ERR_X509_DIGEST); if(!pCertID->pDigestValue) ddocCertID_SetDigestValue(pCertID, (const char*)buf, n); ddocCertGetSubjectDN(cert, &mbuf1); ddocCertID_SetIssuerName(pCertID, (char*)mbuf1.pMem); ddocMemBuf_free(&mbuf1); snprintf(buf, sizeof(buf), "%s-RESPONDER_CERTINFO", pSigInfo->szId); ddocCertID_SetId(pCertID, buf); ddocDebug(4, "addNotaryInfoCert", "cert: %s to notary: %s", (cert ? "OK" : "NULL"), pNotary->szId, err); return err; } //============================================================ // Removes Notary cert value and id after unsucessful verification attempt // pSigInfo - signature info [REQUIRED] // return error code //============================================================ int removeNotaryInfoCert(SignatureInfo* pSigInfo) { CertID* pCertID; CertValue* pCertVal; int i; RETURN_IF_NULL_PARAM(pSigInfo); // remove cert values of type responder for(i = 0; i < ddocCertValueList_GetCertValuesCount(pSigInfo->pCertValues); i++) { pCertVal = ddocCertValueList_GetCertValue(pSigInfo->pCertValues, i); if(pCertVal && pCertVal->nType == CERTID_VALUE_RESPONDERS_CERT) ddocCertValueList_DeleteCertValue(pSigInfo->pCertValues, i); } // remove cert ids of type responder for(i = 0; i < ddocCertIDList_GetCertIDsCount(pSigInfo->pCertIDs); i++) { pCertID = ddocCertIDList_GetCertID(pSigInfo->pCertIDs, i); if(pCertID && pCertID->nType == CERTID_TYPE_RESPONDERS_CERTID) ddocCertIDList_DeleteCertID(pSigInfo->pCertIDs, i); } return ERR_OK; } //============================================================ // Adds a new Notary SignedInfo element to a SignedDoc // element and initializes it // newNotaryInfo - newly created structure // pSigDoc - signed doc data // pSigInfo - signature object to be verified by this notary // ocspRespFile - OCSP response file name // notaryCertFile - Notary cert file name // returns error code or ERR_OK if no error. //============================================================ // FIXME : What to do if initializeNotaryInfoWithOCSP fails? EXP_OPTION int NotaryInfo_new_file(NotaryInfo **newNotaryInfo, SignedDoc *pSigDoc, const SignatureInfo *pSigInfo, const char *ocspRespFile, const char *notaryCertFile) { OCSP_RESPONSE* resp; X509* notCert; NotaryInfo* pNotInf = NULL; int err = ERR_OK; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(ocspRespFile); RETURN_IF_NULL_PARAM(notaryCertFile); err = ReadOCSPResponse(&resp, ocspRespFile); RETURN_IF_NOT(err == ERR_OK, ERR_FILE_READ); err = ReadCertificate(¬Cert, notaryCertFile); RETURN_IF_NOT(err == ERR_OK, ERR_CERT_READ); err = NotaryInfo_new(&pNotInf, pSigDoc, (SignatureInfo*)pSigInfo); RETURN_IF_NOT(err == ERR_OK, err); *newNotaryInfo = pNotInf; err = initializeNotaryInfoWithOCSP(pSigDoc, pNotInf, resp, notCert, 1); RETURN_IF_NOT(err == ERR_OK, err); return ERR_OK; } // forward deklaratsioon int notary2ocspBasResp(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo, X509* notCert, OCSP_BASICRESP** pBasResp); int calculateOcspBasicResponseDigest(OCSP_BASICRESP* pBsResp, byte* digBuf, int* digLen); //============================================================ // Calculates the digest of NotaryInfo // pSigDoc - signed document pointer // pNotInfo - notary signature info // digBuf - signature buffer // digLen - signature buffer length // returns error code //============================================================ EXP_OPTION int calculateNotaryInfoDigest(const SignedDoc* pSigDoc, const NotaryInfo* pNotInfo, byte* digBuf, int* digLen) { SignatureInfo* pSigInfo; int err = ERR_OK; const DigiDocMemBuf *pMBuf = 0; pMBuf = ddocNotInfo_GetOCSPResponse(pNotInfo); RETURN_IF_NULL(pMBuf); pSigInfo = ddocGetSignatureForNotary(pSigDoc, pNotInfo); RETURN_IF_NULL_PARAM(pSigInfo); if(!strcmp(pNotInfo->szDigestType,DIGEST_SHA256_NAME)) err = calculateDigest((const byte*)pMBuf->pMem, pMBuf->nLen, DIGEST_SHA256, digBuf, digLen); else err = calculateDigest((const byte*)pMBuf->pMem, pMBuf->nLen, DIGEST_SHA1, digBuf, digLen); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //AM 12.03.08 //-------------------------------------------------- // Sets the CA Responders certificate // pSigInfo - signature info object [REQUIRED] // pCert - certificate [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocSigInfo_SetCACert(SignatureInfo* pSigInfo, X509* pCert) { int err = ERR_OK; CertValue *pCertValue = 0; char buf1[50]; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pCert); pCertValue = ddocSigInfo_GetOrCreateCertValueOfType(pSigInfo, CERTID_VALUE_CA_CERT); if(pCertValue) { snprintf(buf1, sizeof(buf1), "%s-CA_CERT", pSigInfo->szId); err = ddocCertValue_SetId(pCertValue, buf1); if(!err) err = ddocCertValue_SetCert(pCertValue, pCert); } return err; } //============================================================ // Calculates and stores a signature for this SignatureInfo object // Uses PKCS#12 file to sign the info // pSigInfo - signature info object // nSigType - signature type code // szPkcs12File - PKCS#12 file // passwd - key password //============================================================ EXP_OPTION int calculateSignatureWithPkcs12(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const char* szPkcs12File, const char* passwd) { int err = ERR_OK; int sigLen; char sigDig[100]; char signature[256]; char* buf1; int l2; EVP_PKEY *pkey = 0; X509* x509 = 0; EVP_MD_CTX *ctx; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pSigInfo); RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(szPkcs12File); ddocDebug(3, "calculateSignatureWithPkcs12", "Keystore: %s passwd-len: %d", szPkcs12File, (passwd ? strlen(passwd) : 0)); // read pkcs12 file err = ReadCertificateByPKCS12(&x509, szPkcs12File, passwd, &pkey); RETURN_IF_NOT(err == ERR_OK, err); // try key-usage check if(ConfigItem_lookup_int("KEY_USAGE_CHECK", 1) && x509) { if(!ddocCertCheckKeyUsage(x509, KUIDX_NON_REPUDIATION)) { X509_free(x509); EVP_PKEY_free(pkey); SET_LAST_ERROR(ERR_SIGNERS_CERT_NON_REPU); return ERR_SIGNERS_CERT_NON_REPU; } } // set signers cert setSignatureCert(pSigInfo, x509); // create signing timestamp createTimestamp(pSigDoc, (char*)sigDig, sizeof(sigDig)); setString((char**)&(pSigInfo->szTimeStamp), (const char*)sigDig, -1); // Signed properties digest buf1 = createXMLSignedProperties(pSigDoc, pSigInfo, 0); mbuf1.pMem = canonicalizeXML((char*)buf1, strlen(buf1)); mbuf1.nLen = strlen((const char*)mbuf1.pMem); ddocDebugWriteFile(4, "sigprop-signed.txt", &mbuf1); l2 = sizeof(sigDig); err = calculateDigest((const byte*)mbuf1.pMem, mbuf1.nLen, DIGEST_SHA1, sigDig, &l2); free(buf1); ddocMemBuf_free(&mbuf1); if (err != ERR_OK) { SET_LAST_ERROR(err); return err; } ddocSigInfo_SetSigPropDigest(pSigInfo, (const char*)sigDig, l2); ddocSigInfo_SetSigPropRealDigest(pSigInfo, (const char*)sigDig, l2); // create signed info buf1 = createXMLSignedInfo(pSigDoc, pSigInfo); if (!buf1) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err ; } mbuf1.pMem = buf1; //canonicalizeXML((char*)buf1, strlen(buf1)); mbuf1.nLen = strlen((const char*)mbuf1.pMem); //ddocDebugWriteFile(4, "siginf-signed.txt", &mbuf1); // get digest l2 = sizeof(sigDig); err = calculateDigest((const byte*)buf1, strlen(buf1), DIGEST_SHA1, (byte*)sigDig, &l2); // debug sigLen = sizeof(signature); bin2hex((const byte*)sigDig, l2, (char*)signature, &sigLen); sigLen = sizeof(signature); encode((const byte*)sigDig, l2, (char*)signature, &sigLen); ddocDebug(3, "calculateSignatureWithPkcs12", "Sig-inf hash b64: %s", signature); if (err != ERR_OK) { err = ERR_NULL_POINTER; SET_LAST_ERROR(err); return err; } ddocSigInfo_SetSigInfoRealDigest(pSigInfo, (const char*)sigDig, l2); // sign data sigLen = sizeof(signature); memset(signature, 0, sizeof(signature)); // sign data ctx = EVP_MD_CTX_new(); EVP_SignInit(ctx, EVP_sha1()); EVP_SignUpdate(ctx, buf1, (unsigned long)strlen(buf1)); err = EVP_SignFinal(ctx, signature, &sigLen, pkey); EVP_MD_CTX_free(ctx); free(buf1); if(err == ERR_LIB_NONE) err = ERR_OK; // set signature value ddocSigInfo_SetSignatureValue(pSigInfo, (const char*)signature, (int)sigLen); ddocDebug(3, "calculateSignatureWithPkcs12", "Sig-len: %ld", sigLen); //X509_free(x509); EVP_PKEY_free(pkey); return err; } libdigidoc-3.10.5/libdigidoc/DigiDocDefs.h0000664000372000037200000001250413560273131017644 0ustar travistravis#ifndef __DIGIDOC_DEFS_H__ #define __DIGIDOC_DEFS_H__ //================================================== // FILE: DigiDocDefs.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc global definitions. // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details.ode // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 15.06.2005 Veiko Sinivee //================================================== #ifdef WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #define WIN32_CSP #ifdef _MSC_VER #pragma warning( disable: 4100 4706 4204 4221 ) #endif #ifdef digidoc_EXPORTS #define EXP_OPTION __declspec(dllexport) #else #define EXP_OPTION __declspec(dllimport) #endif #define DIGIDOC_DEPRECATED __declspec(deprecated) #else #if __GNUC__ >= 4 #define EXP_OPTION __attribute__ ((visibility("default"))) #define DIGIDOC_DEPRECATED __attribute__ ((__deprecated__)) #else #define EXP_OPTION #define DIGIDOC_DEPRECATED #endif #endif #ifdef WIN32 //for _msize function #define FILESEPARATOR "\\" #include #include #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif #else #define FILESEPARATOR "/" #define DIGI_DOC_LIB #include #define _mkdir mkdir #define _rmdir rmdir #define _unlink unlink #define _tzset tzset #define _getcwd getcwd #if defined(__FreeBSD__) #define _timezone tzone extern long int tzone; /* default for Estonia, but see initDigiDocLib() */ #define _daylight daylight extern int daylight; /* default, but see initDigiDocLib() */ #else #define _timezone timezone #define _daylight daylight #endif #endif #define WITH_BASE64_HASHING_HACK 1 // VS: disabled ecdsa support for FC13 building //#define WITH_ECDSA 1 //#define WITH_DEPRECATED_FUNCTIONS // old timestamp struct #define WITH_TIMETSTAMP_STRUCT #ifndef byte typedef unsigned char byte; #endif #define WITH_SHA256 //==========< Digest types >======================= #ifdef WITH_SHA256 #define SIGNATURE_LEN 144 #else #define SIGNATURE_LEN 128 #endif #define DIGEST_LEN 20 #define DIGEST_SHA1 0 #define DIGEST_SHA256 1 #define DIGEST_LEN256 32 #define CERT_DATA_LEN 4096 #define X509_NAME_LEN 256 #define SIGNATURE_RSA 0 #define CONTENT_EMBEDDED "EMBEDDED" #define CONTENT_EMBEDDED_BASE64 "EMBEDDED_BASE64" #define X509_NAME_BUF_LEN 500 //==========< Format types >======================= #define SK_PKCS7_1 "SK-PKCS#7-1.0" #define SK_XML_1_NAME "SK-XML" #define DIGIDOC_XML_1_1_NAME "DIGIDOC-XML" #define SK_XML_1_VER "1.0" #define DIGIDOC_XML_1_1_VER "1.1" #define DIGIDOC_XML_1_2_VER "1.2" #define DIGIDOC_XML_1_3_VER "1.3" #define SK_NOT_VERSION "OCSP-1.0" #define DIGEST_SHA1_NAME "sha1" #define DIGEST_SHA1_WRONG "sha1wrong" #define DIGEST_SHA256_NAME "sha256" #define SIGN_RSA_NAME "RSA" #ifdef WITH_ECDSA #define SIGN_ECDSA_NAME "ECDSA" #endif #define OCSP_NONCE_NAME "OCSP Nonce" #define RESPID_NAME_VALUE "NAME" #define RESPID_KEY_VALUE "KEY HASH" #define OCSP_SIG_TYPE "sha1WithRSAEncryption" #define RESPID_NAME_TYPE 1 #define RESPID_KEY_TYPE 2 #define DIGEST_METHOD_SHA1 "http://www.w3.org/2000/09/xmldsig#sha1" #define DIGEST_METHOD_SHA256 "http://www.w3.org/2001/04/xmlenc#sha256" #define NAMESPACE_XML_DSIG "http://www.w3.org/2000/09/xmldsig#" #define NAMESPACE_XADES_111 "http://uri.etsi.org/01903/v1.1.1#" #define NAMESPACE_XADES_132 "http://uri.etsi.org/01903/v1.3.2#" #define NAMESPACE_XADES "http://uri.etsi.org/01903#" //==========< Format types >======================= #define CHARSET_ISO_8859_1 "ISO-8859-1" #define CHARSET_UTF_8 "UTF-8" //==========< language codes >======================= #define DDOC_LANG_ENGLISH 0 #define DDOC_LANG_ESTONIAN 1 #define DDOC_NUM_LANGUAGES 2 #define SUPPORTED_VERSION_COUNT 4 //==========< file formats >======================= #define FILE_FORMAT_ASN1 0 #define FILE_FORMAT_PEM 1 //#define FILE_FORMAT_ //============< OCSP paramaters >================== #define OCSP_REQUEST_SIGN_NO 1 #define OCSP_REQUEST_SIGN_CSP 2 #define OCSP_REQUEST_SIGN_X509 3 #define OCSP_REQUEST_SIGN_PKCS11_WIN 4 #define OCSP_REQUEST_SIGN_PKCS12 5 //================== Cert search constants ========= #define CERT_SEARCH_BY_STORE 1 #define CERT_SEARCH_BY_X509 2 #define CERT_SEARCH_BY_PKCS12 3 // thes can be XOR'ed, then all criterias are used #define CERT_STORE_SEARCH_BY_SERIAL 0x01 #define CERT_STORE_SEARCH_BY_SUBJECT_DN 0x02 #define CERT_STORE_SEARCH_BY_ISSUER_DN 0x04 #define CERT_STORE_SEARCH_BY_KEY_INFO 0x08 #define FILE_BUFSIZE 1024*16 #endif // __DIGIDOC_DEFS_H__ libdigidoc-3.10.5/libdigidoc/cdigidoc.c0000664000372000037200000025634613560273131017316 0ustar travistravis//================================================== // FILE: digidoc.c // PROJECT: Digi Doc // DESCRIPTION: Utility program to demonstrate the // functionality of DigiDocLib // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 12.01.2004 Veiko Sinivee // Creation //================================================== #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 #define snprintf _snprintf #include #endif #include #include #include #include #include #include //==========< global constants >==================== // programm arguments char* p_szInFile = 0; char* p_szInEncFile = 0; char* p_szInDecFile = 0; char* p_szOutFile = 0; char* p_szConfigFile = 0; int p_parseMode = 1, g_nLibErrors = 0; int g_cgiMode = 1; // 1=output in CGI mode, 0=normal e.g. human readable mode char* g_szOutputSeparator = 0; char *errorClass[] = {"NO_ERRORS", "TECHNICAL", "USER", "LIBRARY"}; char* g_szProgNameVer = "cdigidoc/"DIGIDOC_VERSION; //==========< forward defs >======================== void printErrorsAndWarnings(SignedDoc* pSigDoc); int isWarning(SignedDoc* pSigDoc, int nErrCd); //==========< helper functions for argument handling >==================== //-------------------------------------------------- // Handles one argument //-------------------------------------------------- int checkArguments(int argc, char** argv, int* pCounter, char** dest) { int nLen = 0; if(argc > (*pCounter)+1 && argv[(*pCounter)+1][0] != '-') { nLen = strlen(argv[(*pCounter)+1]) * 2; ddocConvertInput((const char*)argv[(*pCounter)+1], dest); (*pCounter)++; } return nLen; } //-------------------------------------------------- // checks the existence of one command line argument //-------------------------------------------------- int hasCmdLineArg(int argc, char** argv, const char* argName) { int i; for(i = 1; i < argc; i++) { if(argv[i] != NULL && argv[i][0] == '-' && !strcmp(argv[i], argName)) { return i; } } return 0; } //-------------------------------------------------- // Returns the value of one command line argument //-------------------------------------------------- int checkCmdLineArg(int argc, char** argv, const char* argName, char** dest) { int i; *dest = 0; // mark as not found for(i = 1; i < argc; i++) { if(argv[i] != NULL && argv[i][0] == '-' && !strcmp(argv[i], argName)) { if((i + 1 < argc) && (argv[i+1][0] != '-')) { ddocConvertInput((const char*)argv[i+1], dest); return 0; } else return ERR_BAD_PARAM; } } return 0; // not found but no error } //-------------------------------------------------- // prints usage statement //-------------------------------------------------- void printUsage() { fprintf(stderr, "USAGE: cdigidoc [-in ] [-out ] [-config ]\n"); fprintf(stderr, "COMMANDS:\n"); fprintf(stderr, "\t[-new] \n"); fprintf(stderr, "\t-check-cert <-cerificate-file-name (PEM format)>\n"); fprintf(stderr, "\t-add [] []\n"); fprintf(stderr, "\t-verify \n"); fprintf(stderr, "\t-sign [[[] [ ]] [slot(0)] [ocsp(1)] [PKCS11/CNG/PKCS12] [pkcs12-file-name]]\n"); fprintf(stderr, "\t-extract [] []\n"); fprintf(stderr, "\t-encrypt \n"); fprintf(stderr, "\t-encrypt-sk \n"); fprintf(stderr, "\t-encrecv [] [] []\n"); fprintf(stderr, "\t-decrypt [pkcs12-file] [slot(0)]\n"); fprintf(stderr, "\t-decrypt-sk [pkcs12-file] [slot(0)]\n"); fprintf(stderr, "\t-denc-list \n"); fprintf(stderr, "\t-encrypt-file []\n"); fprintf(stderr, "\t-decrypt-file [pkcs12-file]\n"); fprintf(stderr, "\t-calc-sign [] [ ]\n"); fprintf(stderr, "\t-add-sign-value \n"); fprintf(stderr, "\t-del-sign \n"); fprintf(stderr, "\t-get-confirmation \n"); fprintf(stderr, "\t-mid-sign [[(EE)] [(EST)] [(Testing)] [] [ ]]\n"); fprintf(stderr, "\t-mid-test [ (Testimine)]\n"); fprintf(stderr, "\t-in-mem \n"); fprintf(stderr, "\t-add-mem []\n"); fprintf(stderr, "\t-out-mem \n"); fprintf(stderr, "\t-extract-mem \n"); fprintf(stderr, "OPTIONS:\n"); fprintf(stderr, "\t-cgimode [ print usage if(!err && (hasCmdLineArg(argc, argv, "-?") || hasCmdLineArg(argc, argv, "-help"))) printUsage(); // -in if(!err) if((err = checkCmdLineArg(argc, argv, "-in", &p_szInFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid input file name"); // -in-mem if(!err && hasCmdLineArg(argc, argv, "-in-mem")) { if((err = checkCmdLineArg(argc, argv, "-in-mem", &p_szInFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid input file name"); p_parseMode = 3; } // -SAX -> use Sax parser (default) if(!err) if(hasCmdLineArg(argc, argv, "-SAX")) p_parseMode = 1; // -SAX -> use Sax parser (default) if(!err) if(hasCmdLineArg(argc, argv, "-XRDR")) p_parseMode = 2; // -libraryerrors if(!err) if(hasCmdLineArg(argc, argv, "-libraryerrors")) g_nLibErrors = 1; // -out if(!err) if((err = checkCmdLineArg(argc, argv, "-out", &p_szOutFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid output file name"); if(!err && hasCmdLineArg(argc, argv, "-out-mem")) { if((err = checkCmdLineArg(argc, argv, "-out-mem", &p_szOutFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid output file name"); p_parseMode = 3; } // -encrypt if(!err && hasCmdLineArg(argc, argv, "-encrypt")) if((err = checkCmdLineArg(argc, argv, "-encrypt", &p_szInEncFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid encrypt input file name"); // -encrypt-sk if(!err && hasCmdLineArg(argc, argv, "-encrypt-sk")) if((err = checkCmdLineArg(argc, argv, "-encrypt-sk", &p_szInEncFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid encrypt input file name"); // -config if(!err) if((err = checkCmdLineArg(argc, argv, "-config", &p_szConfigFile)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid configuration file name"); // -CGI -> use CGI output mode if(!err) if(hasCmdLineArg(argc, argv, "-cgimode")) { g_cgiMode = 1; if((err = checkCmdLineArg(argc, argv, "-cgimode", &g_szOutputSeparator)) != ERR_OK) addError(err, __FILE__, __LINE__, "Missing or invalid cgi output separator"); if(!g_szOutputSeparator || !g_szOutputSeparator[0] || err) { g_szOutputSeparator = strdup("|"); err = ERR_OK; } } if(hasCmdLineArg(argc, argv, "-consolemode")) { g_cgiMode = 0; } return err; } //-------------------------------------------------- // reads various statusflags from config file //-------------------------------------------------- void readConfigParams() { int n = 0; const char* s = 0; // check if we are in CGI mode n = ConfigItem_lookup_bool("DIGIDOC_CGI_MODE", 0); if(!g_cgiMode && n) g_cgiMode = n; s = ConfigItem_lookup("DIGIDOC_CGI_SEPARATOR"); if(!g_szOutputSeparator && s) g_szOutputSeparator = (char*)strdup(s); if(!g_szOutputSeparator || !g_szOutputSeparator[0]) { if(g_szOutputSeparator) free(g_szOutputSeparator); g_szOutputSeparator = strdup("|"); } } //==========< command handlers >==================== //-------------------------------------------------- // Creates a new signed doc //-------------------------------------------------- int cmdNew(SignedDoc** ppSigDoc, const char* pFormat, const char* pVersion) { int err = ERR_OK; const char* format = pFormat, *version = pVersion; if(!p_szOutFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No output file specified"); return err; } if(!format) format = "DIGIDOC-XML"; if(!version) version = "1.3"; if(format && version) { err = SignedDoc_new(ppSigDoc, format, version); RETURN_IF_NOT(err == ERR_OK, err); } else { err = ERR_UNSUPPORTED_FORMAT; addError(err, __FILE__, __LINE__, "Error finding new document format or version"); } return err; } //-------------------------------------------------- // Adds a DataFile to signed doc //-------------------------------------------------- int cmdAddDataFile(SignedDoc** ppSigDoc, const char* file, const char* mime, const char* content, const char* charset) { int err = ERR_OK, l1; DataFile *pDataFile; char *p = 0, buf1[300]; // if there was no new command then implicitly create a new document if(!(*ppSigDoc)) { err = cmdNew(ppSigDoc, NULL, NULL); RETURN_IF_NOT(err == ERR_OK, err); } // convert to UTF-8 err = ddocConvertInput(file, &p); l1 = sizeof(buf1); getFullFileName(p, buf1, l1); freeLibMem(p); // add a file err = DataFile_new(&pDataFile, *ppSigDoc, NULL, buf1, content, mime, 0, NULL, 0, NULL, charset); if(!err) err = calculateDataFileSizeAndDigest(*ppSigDoc, pDataFile->szId, buf1, DIGEST_SHA1); RETURN_IF_NOT(err == ERR_OK, err); return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- int runAddCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-new")) { char* format = NULL; char* version = NULL; // optional content and charset checkArguments(argc, argv, &i, &format); checkArguments(argc, argv, &i, &version); //printf("format: %s version: %s\n", format, version); err = cmdNew(ppSigDoc, format, version); freeLibMem(format); freeLibMem(version); RETURN_IF_NOT(err == ERR_OK, err); } // add a DataFile if(!strcmp(argv[i], "-add")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* file = argv[i+1]; char* mime = argv[i+2]; char* content = NULL; char* charset = NULL; i += 2; // optional content and charset checkArguments(argc, argv, &i, &content); checkArguments(argc, argv, &i, &charset); err = cmdAddDataFile(ppSigDoc, (const char*)file, (const char*)mime, (const char*)(content ? content : CONTENT_EMBEDDED_BASE64), (const char*)(charset ? charset : CHARSET_UTF_8)); freeLibMem(content); freeLibMem(charset); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing and arguments of -add command"); } } } } return err; } //-------------------------------------------------- // Adds a DataFile to signed doc //-------------------------------------------------- int cmdAddDataFileFromMem(SignedDoc** ppSigDoc, const char* file, const char* mime, const char* content) { int err = ERR_OK; DataFile *pDf = NULL; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; // if there was no new command then implicitly create a new document if(!(*ppSigDoc)) { err = cmdNew(ppSigDoc, NULL, NULL); RETURN_IF_NOT(err == ERR_OK, err); } err = ddocReadFile(file, &mbuf1); if(!err) err = createDataFileInMemory(&pDf, *ppSigDoc, NULL, file, content, mime, mbuf1.pMem, mbuf1.nLen); ddocMemBuf_free(&mbuf1); return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- int runAddMemCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a DataFile if(!strcmp(argv[i], "-add-mem")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* file = argv[i+1]; char* mime = argv[i+2]; char* content = NULL; i += 2; // optional content and charset checkArguments(argc, argv, &i, &content); err = cmdAddDataFileFromMem(ppSigDoc, (const char*)file, (const char*)mime, (const char*)(content ? content : CONTENT_EMBEDDED_BASE64)); freeLibMem(content); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing and arguments of -add-mem command"); } } } } return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- /*int runAddSignValue(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-addsignvalue")) { char* infile = NULL; char* sigid = NULL; char* sigvalf = NULL; checkArguments(argc, argv, &i, &infile); checkArguments(argc, argv, &i, &sigid); checkArguments(argc, argv, &i, &sigvalf); err = cmdReadDigiDoc(ppSigDoc, 0, 1); } // add a DataFile if(!strcmp(argv[i], "-addsignvalue")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* file = argv[i+1]; char* mime = argv[i+2]; char* content = CONTENT_EMBEDDED_BASE64; char* charset = CHARSET_UTF_8; i += 2; // optional content and charset checkArguments(argc, argv, &i, &content); checkArguments(argc, argv, &i, &charset); err = cmdAddDataFile(ppSigDoc, (const char*)file, (const char*)mime, (const char*)content, (const char*)charset); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing and or arguments of -addsignvalue command"); } } } return err; }*/ //-------------------------------------------------- // Add ecryption recipients //-------------------------------------------------- int runRecipientCmds(int argc, char** argv, DEncEncryptedData** ppEncData) { int err = ERR_OK, i, rb = 0; DEncEncryptedKey* pEncKey = 0; X509* pCert = 0; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a recipients key if(!strcmp(argv[i], "-encrecv")) { if(argc > i+1 && argv[i+1][0] != '-') { char* certfile = argv[i+1]; char* recipient = NULL; char* keyname = NULL; char* carriedkeyname = NULL; char* id = NULL; i++; if(!(*ppEncData)) err = dencEncryptedData_new(ppEncData, DENC_XMLNS_XMLENC, DENC_ENC_METHOD_AES128, 0, 0, 0); if(!err) { err = dencMetaInfo_SetLibVersion(*ppEncData); if(!err) { err = dencMetaInfo_SetFormatVersion(*ppEncData); if(!err) { // optional arguments checkArguments(argc, argv, &i, &recipient); checkArguments(argc, argv, &i, &keyname); checkArguments(argc, argv, &i, &carriedkeyname); err = ReadCertificate(&pCert, certfile); if(!err) { if(!recipient) { ddocCertGetSubjectCN(pCert, &mbuf1); recipient = (char*)mbuf1.pMem; rb = 1; } err = dencEncryptedKey_new(*ppEncData, &pEncKey, pCert, DENC_ENC_METHOD_RSA1_5, id, recipient, keyname, carriedkeyname); if(rb) recipient = NULL; // was not malloc separately from mbuf1 } } } } ddocMemBuf_free(&mbuf1); freeLibMem(recipient); freeLibMem(keyname); freeLibMem(carriedkeyname); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -encrecv command"); } } } } return err; } unsigned char* findFileExt(unsigned char* szFileName) { int i = 0; if(szFileName && strlen(szFileName) > 0) { for(i = strlen(szFileName)-1; (i > 0) && (szFileName[i] != '.'); i--); if(szFileName[i] == '.') return szFileName + i + 1; } return 0; } int checkOldFormatVer(SignedDoc* pSigDoc) { if(!pSigDoc || !pSigDoc->szFormat || !pSigDoc->szFormatVer) { addError(ERR_BAD_PARAM, __FILE__, __LINE__, "Format or version not specified"); return ERR_BAD_PARAM; } if(!strcmp(pSigDoc->szFormat, SK_XML_1_NAME) || (!strcmp(pSigDoc->szFormat, DIGIDOC_XML_1_1_NAME) && (!strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_1_VER) || !strcmp(pSigDoc->szFormatVer, DIGIDOC_XML_1_2_VER)))) { SET_LAST_ERROR(ERR_OLD_VERSION); return ERR_OLD_VERSION; } return ERR_OK; } //-------------------------------------------------- // reads in a signed doc //-------------------------------------------------- int cmdReadDigiDoc(SignedDoc** ppSigDoc, DEncEncryptedData** ppEncData, int nMode) { int err = ERR_OK, e; int nMaxDfLen; unsigned char* pExt = 0; if(!p_szInFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No input file specified"); return err; } nMaxDfLen = ConfigItem_lookup_int("DATAFILE_MAX_CACHE", 0); pExt = findFileExt(p_szInFile); //printf("Read file: %s - ext: %s", p_szInFile, pExt); if(pExt && strcmp(pExt, "cdoc") == 0) { err = dencSaxReadEncryptedData(ppEncData, p_szInFile); } else if(pExt && strcmp(pExt, "ddoc") == 0) { switch(nMode) { case 2: // new XMLReader interface //err = ddocXRdrReadSignedDocFromFile(p_szInFile, CHARSET_ISO_8859_1, ppSigDoc, nMaxDfLen); break; case 1: default: err = ddocSaxReadSignedDocFromFile(ppSigDoc, p_szInFile, 0, nMaxDfLen); } } else { err = ERR_FILE_READ; } e = checkOldFormatVer(*ppSigDoc); if(!err && e) err = e; printErrorsAndWarnings(*ppSigDoc); return err; } //-------------------------------------------------- // reads in a signed doc //-------------------------------------------------- int cmdReadDigiDocFromMem(SignedDoc** ppSigDoc, DEncEncryptedData** ppEncData) { int err = ERR_OK, e; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; if(!p_szInFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No input file specified"); return err; } //nMaxDfLen = ConfigItem_lookup_int("DATAFILE_MAX_CACHE", 0); if(strstr(p_szInFile, ".cdoc")) { err = ddocReadFile(p_szInFile, &mbuf1); if(!err) err = dencSaxReadEncryptedDataFromMemory(ppEncData, &mbuf1); } else { err = ddocReadFile(p_szInFile, &mbuf1); if(!err) err = ddocSaxReadSignedDocFromMemory(ppSigDoc, mbuf1.pMem, mbuf1.nLen, mbuf1.nLen + 1); } ddocMemBuf_free(&mbuf1); e = checkOldFormatVer(*ppSigDoc); printErrorsAndWarnings(*ppSigDoc); if(!err && e) err = e; return err; } //-------------------------------------------------- // writes a digidoc in file //-------------------------------------------------- int cmdWrite(SignedDoc* pSigDoc, DEncEncryptedData* pEncData) { int err = ERR_OK; FILE* hFile; #ifdef WIN32 wchar_t *convFileName = 0; int l1 = 0; #endif if(!p_szOutFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No output file specified"); return err; } if(pSigDoc) err = createSignedDoc(pSigDoc, p_szInFile, p_szOutFile); if(pEncData) { if(pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED || pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED) { err = dencGenEncryptedData_writeToFile(pEncData, p_szOutFile); } else { #ifdef WIN32 err = utf82unicode((const char*)p_szOutFile, (char**)&convFileName, &l1); ddocDebug(3, "cmdWrite", "Writing file: %s, conv-file: %s len: %d", p_szOutFile, convFileName, l1); if((hFile = _wfopen(convFileName, L"wb")) != NULL) { #else if((hFile = fopen(p_szOutFile, "wb")) != NULL) { #endif fwrite((pEncData)->mbufEncryptedData.pMem, 1, (pEncData)->mbufEncryptedData.nLen, hFile); fclose(hFile); } else err = ERR_FILE_WRITE; } } if (err) addError(err, __FILE__, __LINE__, "Error writing file\n"); return err; } //-------------------------------------------------- // writes a digidoc in file //-------------------------------------------------- int cmdWriteMem(SignedDoc* pSigDoc, DEncEncryptedData* pEncData) { int err = ERR_OK; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; if(!p_szOutFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No output file specified"); return err; } if(pSigDoc) { err = createSignedDocInMemory(pSigDoc, NULL, &mbuf1); if(!err) err = ddocWriteFile(p_szOutFile, &mbuf1); } if(pEncData) { if(pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED || pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED) { err = dencGenEncryptedData_toXML(pEncData, &mbuf1); if(!err) err = ddocWriteFile(p_szOutFile, &mbuf1); } else { err = ddocWriteFile(p_szOutFile, &(pEncData->mbufEncryptedData)); } } ddocMemBuf_free(&mbuf1); if (err) addError(err, __FILE__, __LINE__, "Error writing file\n"); return err; } //----------------------------------------- // prints certificate info //----------------------------------------- void printCertificateInfo(SignedDoc* pSigDoc, X509* pCert) { int err, p; char buf1[500]; PolicyIdentifier* pPolicies; DigiDocMemBuf mbuf; int nPols; mbuf.pMem = 0; mbuf.nLen = 0; // serial number err = ReadCertSerialNumber(buf1, sizeof(buf1), pCert); if(g_cgiMode) fprintf(stdout, "\nX509Certificate%s%s", g_szOutputSeparator, buf1); else fprintf(stdout, "\nX509Certificate nr: %s", buf1); // issuer err = ddocCertGetIssuerDN(pCert, &mbuf); if(g_cgiMode) fprintf(stdout, "%s%s", g_szOutputSeparator, (char*)mbuf.pMem); else fprintf(stdout, "\n\tIssuer: %s", (char*)mbuf.pMem); ddocMemBuf_free(&mbuf); // subject err = ddocCertGetSubjectDN(pCert, &mbuf); if(g_cgiMode) fprintf(stdout, "%s%s", g_szOutputSeparator, (char*)mbuf.pMem); else fprintf(stdout, "\n\tSubject: %s", (char*)mbuf.pMem); ddocMemBuf_free(&mbuf); // ValidFrom memset(buf1, 0, sizeof(buf1)); err = getCertNotBefore(pSigDoc, pCert, buf1, sizeof(buf1)); if(g_cgiMode) fprintf(stdout, "%s%s", g_szOutputSeparator, buf1); else fprintf(stdout, "\n\tNotBefore: %s", buf1); // ValidTo memset(buf1, 0, sizeof(buf1)); err = getCertNotAfter(pSigDoc, pCert, buf1, sizeof(buf1)); if(g_cgiMode) fprintf(stdout, "%s%s", g_szOutputSeparator, buf1); else fprintf(stdout, "\n\tNotAfter: %s", buf1); // policy URL err = readCertPolicies(pCert, &pPolicies, &nPols); if(nPols) { for(p = 0; p < nPols; p++) { if(g_cgiMode) fprintf(stdout, "\nSignaturePolicy%s%s%s%s%s%s", g_szOutputSeparator, pPolicies[p].szOID, g_szOutputSeparator, pPolicies[p].szCPS, g_szOutputSeparator, pPolicies[p].szUserNotice); else fprintf(stdout, "\n\tnSignaturePolicy oid: %s cps: %s desc: %s", pPolicies[p].szOID, pPolicies[p].szCPS, pPolicies[p].szUserNotice); } // for p < nPols } PolicyIdentifiers_free(pPolicies, nPols); } char* TEST_OIDS_PREFS[] = { "1.3.6.1.4.1.10015.3.7", "1.3.6.1.4.1.10015.7", // tempel test "1.3.6.1.4.1.10015.3.3", "1.3.6.1.4.1.10015.3.11", // mid test "1.3.6.1.4.1.10015.3.2", // digi-id test "1.3.6.1.4.1.10015.3.1" // est-eid test }; int checkTestCert(X509* pCert) { int err = ERR_OK, i, p; PolicyIdentifier* pPolicies = NULL; DigiDocMemBuf mbuf; int nPols = 0; mbuf.pMem = 0; mbuf.nLen = 0; ddocCertGetSubjectCN(pCert, &mbuf); /*if(mbuf.pMem && strstr(mbuf.pMem, "TEST")) { printf("\n Test CN: %s", (char*)(mbuf.pMem)); err = ERR_TEST_SIGNATURE; }*/ err = readCertPolicies(pCert, &pPolicies, &nPols); if(!err && nPols && !err) { for(p = 0; p < nPols; p++) { //printf("\nOID: %s", pPolicies[p].szOID); for(i = 0; i < 6 && !err; i++) { if(i == 1 && // tempel - test strstr(pPolicies[p].szOID, TEST_OIDS_PREFS[1]) && strstr(mbuf.pMem, "TEST")) { //printf("\nTempel-Test OID: %s", TEST_OIDS_PREFS[i]); err = ERR_TEST_SIGNATURE; } else if(i != 1) { if(strstr(pPolicies[p].szOID, TEST_OIDS_PREFS[i])) { //printf("\nTest OID: %s", TEST_OIDS_PREFS[i]); err = ERR_TEST_SIGNATURE; } } } } } ddocMemBuf_free(&mbuf); PolicyIdentifiers_free(pPolicies, nPols); if(err == ERR_TEST_SIGNATURE) SET_LAST_ERROR(ERR_TEST_SIGNATURE); return err; } int isError(SignedDoc* pSigDoc, int nErrCd) { return (nErrCd != ERR_OK && !isWarning(pSigDoc, nErrCd)); } int isWarning(SignedDoc* pSigDoc, int nErrCd) { if(pSigDoc && pSigDoc->szFormat && !strcmp(pSigDoc->szFormat, SK_XML_1_NAME)) { // currently no warnings for ddoc 1.0 return (nErrCd == ERR_OLD_VERSION) || (nErrCd == ERR_TEST_SIGNATURE); } else { return ((nErrCd == ERR_ISSUER_XMLNS) || (nErrCd == ERR_OLD_VERSION) || (nErrCd == ERR_TEST_SIGNATURE) || (nErrCd == ERR_DF_WRONG_DIG) ); } } int isLibraryError(int nErrCd) { return (nErrCd != ERR_OK && nErrCd != ERR_OLD_VERSION && nErrCd != ERR_TEST_SIGNATURE && nErrCd != ERR_UNSUPPORTED_FORMAT); } int hasWarnings(SignedDoc* pSigDoc) { int n; ErrorInfo* pErr; for(n = getLastErrorsIdx(); n >= 0; n--) { pErr = getErrorsInfo(n); if(isWarning(pSigDoc, pErr->code)) return pErr->code; } return ERR_OK; } int hasErrors(SignedDoc* pSigDoc) { int n; ErrorInfo* pErr; for(n = getLastErrorsIdx(); n >= 0; n--) { pErr = getErrorsInfo(n); if(isError(pSigDoc, pErr->code)) return pErr->code; } return ERR_OK; } void printErrorsAndWarnings(SignedDoc* pSigDoc) { int n, m = getLastErrorsIdx(); ErrorInfo* pErr; char* pErrStr; // list all errors if(g_cgiMode) { /*for(n = 0; n < m; n++) { pErr = getErrorsInfo(n); pErrStr = getErrorString(pErr->code); printf("\nErr: %d cd: %d msg: %s", n, pErr->code, pErrStr); }*/ for(n = m; n >= 0; n--) { pErr = getErrorsInfo(n); pErrStr = getErrorString(pErr->code); if(isError(pSigDoc, pErr->code)) fprintf(stdout, "\nERROR%s%d%s%s%s%s%s%d%s%s%s%s", g_szOutputSeparator, pErr->code, g_szOutputSeparator, pErrStr, g_szOutputSeparator, pErr->fileName, g_szOutputSeparator, pErr->line, g_szOutputSeparator, pErr->assertion, g_szOutputSeparator, errorClass[getErrorClass(pErr->code)]); } for(n = m; n >= 0; n--) { pErr = getErrorsInfo(n); pErrStr = getErrorString(pErr->code); if(isWarning(pSigDoc, pErr->code)) fprintf(stdout, "\nWARNING%s%d%s%s%s%s%s%d%s%s%s%s", g_szOutputSeparator, pErr->code, g_szOutputSeparator, pErrStr, g_szOutputSeparator, pErr->fileName, g_szOutputSeparator, pErr->line, g_szOutputSeparator, pErr->assertion, g_szOutputSeparator, errorClass[getErrorClass(pErr->code)]); } if(g_nLibErrors) { for(n = m; n >= 0; n--) { pErr = getErrorsInfo(n); if(isLibraryError(pErr->code)) { pErrStr = getErrorString(pErr->code); fprintf(stdout, "\nLIBRARY-ERROR%s%d%s%s%s%s%s%d%s%s%s%s", g_szOutputSeparator, pErr->code, g_szOutputSeparator, pErrStr, g_szOutputSeparator, pErr->fileName, g_szOutputSeparator, pErr->line, g_szOutputSeparator, pErr->assertion, g_szOutputSeparator, errorClass[getErrorClass(pErr->code)]); } } } } else { for(n = m; n >= 0; n--) { pErr = getErrorsInfo(n); pErrStr = getErrorString(pErr->code); if(isError(pSigDoc, pErr->code)) fprintf(stdout, "\nERROR: %d - %s - %s", pErr->code, pErrStr, pErr->assertion); if(isWarning(pSigDoc, pErr->code)) fprintf(stdout, "\nWARNING: %d - %s - %s", pErr->code, pErrStr, pErr->assertion); } } } //-------------------------------------------------- // Verifys sigantures and notaries //-------------------------------------------------- int cmdVerify(SignedDoc* pSigDoc) { int err = ERR_OK, s, d, l, m, l1, e, e2, n1, e3; SignatureInfo* pSigInfo = 0; NotaryInfo* pNot; DataFile *pDf = 0; DigiDocMemBuf mbuf; X509* pRcert = 0; const DigiDocMemBuf* pMBuf = 0; char buf1[100], *p1 = 0; mbuf.pMem = 0; mbuf.nLen = 0; if(!pSigDoc) { SET_LAST_ERROR(ERR_UNSUPPORTED_FORMAT); return ERR_UNSUPPORTED_FORMAT; } // print signed doc format and version if(g_cgiMode) { fprintf(stdout, "\nSignedDoc%s%s%s%s", g_szOutputSeparator, pSigDoc->szFormat, g_szOutputSeparator, pSigDoc->szFormatVer); } else { fprintf(stdout, "\nSignedDoc format: %s version: %s\n", pSigDoc->szFormat, pSigDoc->szFormatVer); } // display DataFile-s d = getCountOfDataFiles(pSigDoc); for(l = 0; l < d; l++) { pDf = getDataFile(pSigDoc, l); ddocGetDataFileFilename(pSigDoc, pDf->szId, (void**)&p1, &n1); if(g_cgiMode) fprintf(stdout, "\n\nDataFile%s%s%s%s%s%ld%s%s%s%s", g_szOutputSeparator, pDf->szId, g_szOutputSeparator, p1, g_szOutputSeparator, pDf->nSize, g_szOutputSeparator, pDf->szMimeType, g_szOutputSeparator, pDf->szContentType); else fprintf(stdout, "\n\nDataFile: %s, file: %s, size: %ld, mime-type: %s content-type: %s", pDf->szId, p1, pDf->nSize, pDf->szMimeType, pDf->szContentType); if(p1) freeLibMem(p1); } // verify signatures d = getCountOfSignatures(pSigDoc); for(s = 0; s < d; s++) { pSigInfo = getSignature(pSigDoc, s); e = ddocCertGetSubjectCN(ddocSigInfo_GetSignersCert(pSigInfo), &mbuf); clearErrors(); e = verifySignatureAndNotary(pSigDoc, pSigInfo, p_szInFile); if(!e) e = hasErrors(pSigDoc); if(!err && e) err = e; e2 = checkTestCert(ddocSigInfo_GetSignersCert(pSigInfo)); if(!err && e2) err = e2; if(!e && e2) e = e2; if(g_cgiMode) { fprintf(stdout, "\n\nSignature%s%s%s%s%s%d%s%s", g_szOutputSeparator, pSigInfo->szId, g_szOutputSeparator, (const char*)mbuf.pMem, g_szOutputSeparator, e, g_szOutputSeparator, (e ? getErrorString(e) : "")); } else { fprintf(stdout, "\n\nSignature: %s - %s - %s", pSigInfo->szId, (const char*)mbuf.pMem, ((!e) ? "OK" : "ERROR")); } ddocMemBuf_free(&mbuf); // print signers roles / manifests m = getCountOfSignerRoles(pSigInfo, 0); for(l = 0; l < m; l++) { if(g_cgiMode) fprintf(stdout, "\nClaimedRole%s%s", g_szOutputSeparator, getSignerRole(pSigInfo, 0, l)); else fprintf(stdout, "\n\tClaimedRole: %s", getSignerRole(pSigInfo, 0, l)); } if(pSigInfo->sigProdPlace.szCity || pSigInfo->sigProdPlace.szStateOrProvince || pSigInfo->sigProdPlace.szPostalCode || pSigInfo->sigProdPlace.szCountryName) { if(g_cgiMode) { fprintf(stdout, "\nSignatureProductionPlace%s%s%s%s%s%s%s%s", g_szOutputSeparator, (pSigInfo->sigProdPlace.szCountryName ? pSigInfo->sigProdPlace.szCountryName : ""), g_szOutputSeparator, (pSigInfo->sigProdPlace.szStateOrProvince ? pSigInfo->sigProdPlace.szStateOrProvince : ""), g_szOutputSeparator, (pSigInfo->sigProdPlace.szCity ? pSigInfo->sigProdPlace.szCity : ""), g_szOutputSeparator, (pSigInfo->sigProdPlace.szPostalCode ? pSigInfo->sigProdPlace.szPostalCode : "")); } else { fprintf(stdout, "\n\tnSignatureProductionPlace - Country: %s, State: %s, City: %s, Postal code: %s", (pSigInfo->sigProdPlace.szCountryName ? pSigInfo->sigProdPlace.szCountryName : ""), (pSigInfo->sigProdPlace.szStateOrProvince ? pSigInfo->sigProdPlace.szStateOrProvince : ""), (pSigInfo->sigProdPlace.szCity ? pSigInfo->sigProdPlace.szCity : ""), (pSigInfo->sigProdPlace.szPostalCode ? pSigInfo->sigProdPlace.szPostalCode : "")); } } // signers certificate if(ddocSigInfo_GetSignersCert(pSigInfo)) printCertificateInfo(pSigDoc, ddocSigInfo_GetSignersCert(pSigInfo)); // confirmation if(pSigDoc && pSigInfo) { pNot = getNotaryWithSigId(pSigDoc, pSigInfo->szId); if(pNot) { pMBuf = ddocNotInfo_GetResponderId(pNot); buf1[0] = 0; l1 = sizeof(buf1); if(pNot->nRespIdType == RESPID_NAME_TYPE) { strncpy(buf1, (const char*)pMBuf->pMem, l1); } if(pNot->nRespIdType == RESPID_KEY_TYPE) { encode((const byte*)pMBuf->pMem, pMBuf->nLen, (byte*)buf1, &l1); } } if(pNot && pMBuf) { if(g_cgiMode) fprintf(stdout, "\nRevocationValues%s%s%s%s", g_szOutputSeparator, buf1, g_szOutputSeparator, pNot->timeProduced); else fprintf(stdout, "\n\tRevocationValues responder: %s produced-at: %s", buf1, pNot->timeProduced); // certificate pRcert = ddocSigInfo_GetOCSPRespondersCert(pSigInfo); e3 = checkTestCert(pRcert); if(!e2 && e3) { // live allkirjastaja sert aga test ocsp fprintf(stdout, "\n\tSigner from LIVE CA-chain but OCSP from TEST CA-chain!"); err = e3; SET_LAST_ERROR(e3); } printCertificateInfo(pSigDoc, pRcert); } } printErrorsAndWarnings(pSigDoc); } return err; } //-------------------------------------------------- // Signs the document and gets configrmation //-------------------------------------------------- int cmdSign(SignedDoc* pSigDoc, const char* pin, const char* manifest, const char* city, const char* state, const char* zip, const char* country, int nSlot, int nOcsp, int nSigner, const char* szPkcs12File) { int err = ERR_OK; SignatureInfo* pSigInfo = NULL; ddocDebug(3, "cmdSign", "Creating new digital signature"); err = signDocumentWithSlotAndSigner(pSigDoc, &pSigInfo, pin, manifest, city, state, zip, country, nSlot, nOcsp, nSigner, szPkcs12File); ddocDebug(3, "cmdSign", "End creating new digital signature"); RETURN_IF_NOT(err == ERR_OK, err); return ERR_OK; } //#ifdef WITH_DEPRECATED_FUNCTIONS //-------------------------------------------------- // Runs some test. This is used simply to test // new features of the library and the functionality // may change. //-------------------------------------------------- void cmdTest2(const char* infile) { X509* pCert = 0; //char buf1[X509_NAME_LEN + 10]; int err = ERR_OK, nPols = 0; PolicyIdentifier *pPolicies = 0; ddocDebug(3, "cmdTest2", "Reading cert: %s", infile); err = ReadCertificate(&pCert, infile); if(!err && pCert) { err = readCertPolicies(pCert, &pPolicies, &nPols); printf("Read pols rc: %d pols: %d\n", err, nPols); /* l1 = sizeof(buf1); memset(buf1, 0, sizeof(buf1)); err = getCertSubjectName(pCert, buf1, &l1); if(g_cgiMode) fprintf(stdout, "\nDN%s%s%s%d", g_szOutputSeparator, buf1, g_szOutputSeparator, l1); else fprintf(stdout, "\nDN: %s len: %d", buf1, l1); */ } if(pCert) X509_free(pCert); if(pPolicies) PolicyIdentifiers_free(pPolicies, nPols); } //#endif //-------------------------------------------------- // Encrypts a file //-------------------------------------------------- int cmdEncrypt(DEncEncryptedData** ppEncData, const char* szFileName) { FILE* hFile; SignedDoc *pSigDoc = 0; DEncEncryptionProperty* pEncProperty = 0; int len, err = ERR_OK, i = 0; long lFileLen; char buf[2048], *p = 0; #ifdef WIN32 wchar_t *convFileName = 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); #endif ddocDebug(3, "cmdEncrypt", "Encrypting %s rc: %d", szFileName, err); err = dencEncryptedData_new(ppEncData, DENC_XMLNS_XMLENC, DENC_ENC_METHOD_AES128, 0, 0, 0); if(!err) { err = dencMetaInfo_SetLibVersion(*ppEncData); if(!err) { err = dencMetaInfo_SetFormatVersion(*ppEncData); if(!err) { err = ddocConvertInput(szFileName, &p); if(!err) { err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_FILENAME, getSimpleFileName(p)); if(strstr(p, ".bdoc") || strstr(p, ".asice")) err = dencEncryptedData_SetMimeType(*ppEncData, "application/vnd.etsi.asic-e+zip"); err = calculateFileSize(szFileName, &lFileLen); sprintf(buf, "%ld", lFileLen); err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_ORIG_SIZE, buf); freeLibMem(p); if(!err) { ddocDebug(3, "cmdEncrypt", "Opening %s rc: %d", szFileName, err); #ifdef WIN32 if((hFile = _wfopen(convFileName, L"rb")) != NULL) { #else if((hFile = fopen(szFileName, "rb")) != NULL) { #endif do { memset(buf,0,sizeof(buf)); len = fread(buf, 1, sizeof(buf), hFile); if(len) err = dencEncryptedData_AppendData(*ppEncData, buf, len); } while(len && !err); fclose(hFile); } // if fopen/wfopen ddocDebug(3, "cmdEncrypt", "Enc data-len: %d rc: %d", (*ppEncData)->mbufEncryptedData.nLen, err); if(!err) err = dencEncryptedData_encryptData(*ppEncData, DENC_COMPRESS_NEVER); } // err - endProp_new } // err - conver filename } // err - serFormatVer } // err - setLibVer } // err - dencEncData_new return err; } //-------------------------------------------------- // Encrypts a file and uses SK specific method of // putting the file first in a ddoc container and then into // cdoc //-------------------------------------------------- int cmdEncryptSk(DEncEncryptedData** ppEncData, const char* szFileName) { SignedDoc *pSigDoc = 0; DEncEncryptionProperty* pEncProperty = 0; DataFile *pDf = 0; int err = ERR_OK; long lSize; char buf[256], *p = 0; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; err = dencEncryptedData_new(ppEncData, DENC_XMLNS_XMLENC, DENC_ENC_METHOD_AES128, 0, 0, 0); if(!err) { err = dencMetaInfo_SetLibVersion(*ppEncData); if(!err) { err = dencMetaInfo_SetFormatVersion(*ppEncData); if(!err) { err = ddocConvertInput(szFileName, &p); if(!err) { err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_FILENAME, getSimpleFileName(p)); if(!err) { err = SignedDoc_new(&pSigDoc, "DIGIDOC-XML", "1.3"); if(!err) { calculateFileSize(szFileName, &lSize); err = DataFile_new(&pDf, pSigDoc, NULL, szFileName, "EMBEDDED_BASE64", "application/file", lSize, NULL, 0, NULL, NULL); sprintf(buf, "%ld", lSize); err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_ORIG_SIZE, buf); if(!err) { err = dencOrigContent_registerDigiDoc(*ppEncData, pSigDoc); if(!err) { sprintf(buf, "%s.ddoc", szFileName); err = createSignedDoc(pSigDoc, NULL, buf); if(!err) { err = ddocReadFile(buf, &mbuf1); if(!err) { err = dencEncryptedData_AppendData(*ppEncData, mbuf1.pMem, mbuf1.nLen); //ddocDebug(3, "EncTest", "Enc data: \"%s\"", mbuf1.pMem); remove(buf); ddocMemBuf_free(&mbuf1); if(!err) err = dencEncryptedData_encryptData(*ppEncData, DENC_COMPRESS_NEVER); } // err - ddocReadFile } // err - createSignedDoc } // err - origContent_register } // err - sigDoc_new } // err - sigDoc_new SignedDoc_free(pSigDoc); } // err - encProp_new freeLibMem(p); } // err - convert filename } // err - setFormatVer } // err - setLibVer } // err - endData_new return err; } //-------------------------------------------------- // Runs various tests. Just for trying out new features //-------------------------------------------------- int runTestCmds(int argc, char** argv) { int err = ERR_OK, i; char* infile = NULL; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - if(!strcmp(argv[i], "-test")) { // add a recipients key } //#ifdef WITH_DEPRECATED_FUNCTIONS if(!strcmp(argv[i], "-test2")) { ddocConvertInput((const char*)argv[i+1], &infile); cmdTest2(argv[i+1]); } //#endif } } return err; } //-------------------------------------------------- // Encrypts whole files //-------------------------------------------------- int runEncryptFileCmds(int argc, char** argv, DEncEncryptedData* pEncData) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a recipients key if(!strcmp(argv[i], "-encrypt-file")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* infile = NULL; char* outfile = NULL; char* mime = NULL; ddocConvertInput((const char*)argv[i+1], &infile); ddocConvertInput((const char*)argv[i+2], &outfile); ddocConvertInput((const char*)argv[i+3], &mime); i += 3; // optional arguments checkArguments(argc, argv, &i, &mime); // encrypt the file err = dencEncryptFile(pEncData, infile, outfile, mime); if(infile) freeLibMem(infile); if(outfile) freeLibMem(outfile); if(mime) freeLibMem(mime); if(err) return err; } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing or argument of -encrypt-file command"); } } } } return err; } //-------------------------------------------------- // Decrypts whole files //-------------------------------------------------- int runDecryptFileCmds(int argc, char** argv) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // decrypt a file if(!strcmp(argv[i], "-decrypt-file")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-' && argv[i+3][0] != '-') { char* infile = NULL; char* outfile = NULL; char* pin = NULL; char* pkcs12file = NULL; ddocConvertInput((const char*)argv[i+1], &infile); ddocConvertInput((const char*)argv[i+2], &outfile); ddocConvertInput((const char*)argv[i+3], &pin); i += 3; // optional arguments checkArguments(argc, argv, &i, &pkcs12file); // decrypt the file err = dencSaxReadDecryptFile(infile, outfile, pin, pkcs12file); if(infile) freeLibMem(infile); if(outfile) freeLibMem(outfile); if(pin) freeLibMem(pin); if(pkcs12file) freeLibMem(pkcs12file); if(err) return err; } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing , or argument of -decrypt-file command"); } } } } return err; } //-------------------------------------------------- // Generates and encrypts a block of data with specific // length //-------------------------------------------------- int cmdEncryptTestSet(DEncEncryptedData** ppEncData, int nSize, char* dir, int nDdoc, int nDel) { DEncEncryptionProperty* pEncProperty = 0; int err = ERR_OK, i, nCompress, l2; char *p = 0, fname1[256], fname2[256], c, *p2; SignedDoc* pSigDoc = 0; DataFile *pDf = 0; FILE* hFile; DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; nCompress = ConfigItem_lookup_int("DENC_COMPRESS_MODE", DENC_COMPRESS_ALLWAYS); ddocDebug(3, "EncTest", "Test: %d", nSize); err = dencEncryptedData_new(ppEncData, DENC_XMLNS_XMLENC, DENC_ENC_METHOD_AES128, 0, 0, 0); if(err) return err; err = dencMetaInfo_SetLibVersion(*ppEncData); if(err) return err; err = dencMetaInfo_SetFormatVersion(*ppEncData); if(err) return err; sprintf(fname1, "%stest-%d.dat", dir, nSize); err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_FILENAME, fname1); if(err) return err; p = (char*)malloc(nSize+1); if(!p) return ERR_BAD_ALLOC; memset(p, 0, nSize+1); for(i = 0, c = 'A'; i < nSize; i++, c++) { p[i] = c; if(c >= 'z') c = 'A'; } // append x.923 padding if last block is full if(nSize % 16 == 0) { ddocDebug(3, "EncTest", "Full size: %d. Change last 8 bytes to X.923 padding", nSize); p[nSize-1] = 8; for(i = nSize -2; i > nSize - 9; i--) p[i] = 0; } l2 = nSize * 2 + 1; p2 = (char*)malloc(l2); if(!p2) return ERR_BAD_ALLOC; memset(p2, 0, l2); bin2hex((const byte*)p, nSize, (byte*)p2, &l2); ddocDebug(3, "EncTest", "Fil data hex: \"%s\" len: %d", p2, l2); if((hFile = fopen(fname1, "w")) != NULL) { fwrite(p, nSize, 1, hFile); fclose(hFile); } free(p); p = 0; fname2[0] = 0; if(nDdoc) { err = dencEncryptionProperty_new(*ppEncData, &pEncProperty, 0, 0, ENCPROP_ORIG_MIME, DENC_ENCDATA_TYPE_DDOC); err = SignedDoc_new(&pSigDoc, "DIGIDOC-XML", "1.3"); if(!err) { err = DataFile_new(&pDf, pSigDoc, NULL, fname1, "EMBEDDED_BASE64", "text/txt", nSize, NULL, 0, NULL, NULL); if(!err) { err = dencOrigContent_registerDigiDoc(*ppEncData, pSigDoc); if(!err) { sprintf(fname2, "%stest-%d.ddoc", dir, nSize); err = createSignedDoc(pSigDoc, NULL, fname2); if(!err) { err = ddocReadFile(fname2, &mbuf1); if(!err) err = dencEncryptedData_AppendData(*ppEncData, mbuf1.pMem, mbuf1.nLen); } } } } //ddocDebug(3, "EncTest", "Enc data: \"%s\"", mbuf1.pMem); if(nDel && fname2[0]) remove(fname2); ddocMemBuf_free(&mbuf1); } else { err = dencEncryptedData_AppendData(*ppEncData, p, nSize); } if(nDel && fname1[0]) remove(fname1); if(!err) err = dencEncryptedData_encryptData(*ppEncData, nCompress); if(pSigDoc) SignedDoc_free(pSigDoc); return err; } //-------------------------------------------------- // Encrypts generated test files //-------------------------------------------------- int runEncryptTestSetCmds(int argc, char** argv) { int err = ERR_OK, i, j; DEncEncryptedData* pEncData = 0; DEncEncryptedKey* pEncKey = 0; X509* pCert = 0; char fname[128]; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a recipients key if(!strcmp(argv[i], "-encrypt-test-set")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* certfile = argv[i+1]; char* recipient = argv[i+2]; char* outdir = argv[i+3]; int nStart = atoi(argv[i+4]); int nEnd = atoi(argv[i+5]); int nDdoc = atoi(argv[i+6]); int nDel = atoi(argv[i+7]); for(j = nStart; j < nEnd; j++) { err = ReadCertificate(&pCert, certfile); if(err) return err; pEncData = 0; err = cmdEncryptTestSet(&pEncData, j, outdir, nDdoc, nDel); if(err) return err; err = dencEncryptedKey_new(pEncData, &pEncKey, pCert, DENC_ENC_METHOD_RSA1_5, NULL, recipient, NULL, NULL); sprintf(fname, "%stest-%d.cdoc", outdir, j); err = dencGenEncryptedData_writeToFile(pEncData, fname); dencEncryptedData_free(pEncData); pEncKey = 0; pEncData = 0; } } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Invalid parameters for -encrypt-test-set command"); } } } } return err; } //-------------------------------------------------- // Lists EncryptedData objects //-------------------------------------------------- int cmdListEncryptedData(DEncEncryptedData* pEncData) { int err = ERR_OK, k; char buf1[50], buf2[50]; if(g_cgiMode) { fprintf(stdout, "\nEncryptedData%s%s%s%s%s%s%s%s", g_szOutputSeparator, (pEncData->szId ? pEncData->szId : ""), g_szOutputSeparator, (pEncData->szType ? pEncData->szType : ""), g_szOutputSeparator, (pEncData->szMimeType ? pEncData->szMimeType : ""), g_szOutputSeparator, (pEncData->szEncryptionMethod ? pEncData->szEncryptionMethod : "")); err = dencMetaInfo_GetLibVersion(pEncData, buf1, sizeof(buf1), buf2, sizeof(buf2)); fprintf(stdout, "\nLIBRARY%s%s%s%s", g_szOutputSeparator, buf1, g_szOutputSeparator, buf2); err = dencMetaInfo_GetFormatVersion(pEncData, buf1, sizeof(buf1), buf2, sizeof(buf2)); fprintf(stdout, "\nFORMAT%s%s%s%s", g_szOutputSeparator, buf1, g_szOutputSeparator, buf2); } else { fprintf(stdout, "\nEncryptedData - Id=%s Type=%s MimeType=%s EncryptionMethod=%s", (pEncData->szId ? pEncData->szId : ""), (pEncData->szType ? pEncData->szType : ""), (pEncData->szMimeType ? pEncData->szMimeType : ""), (pEncData->szEncryptionMethod ? pEncData->szEncryptionMethod : "")); err = dencMetaInfo_GetLibVersion(pEncData, buf1, sizeof(buf1), buf2, sizeof(buf2)); fprintf(stdout, "\n\tLIBRARY: %s VERSION: %s", buf1, buf2); err = dencMetaInfo_GetFormatVersion(pEncData, buf1, sizeof(buf1), buf2, sizeof(buf2)); fprintf(stdout, "\n\tFORMAT: %s VERSION: %s", buf1, buf2); } for(k = 0; k < pEncData->nEncryptedKeys; k++) { DEncEncryptedKey *pEncKey = pEncData->arrEncryptedKeys[k]; if(g_cgiMode) fprintf(stdout, "\nEncryptedKey%s%s%s%s%s%s%s%s%s%s%s%s", g_szOutputSeparator, (pEncKey->szId ? pEncKey->szId : ""), g_szOutputSeparator, (pEncKey->szRecipient ? pEncKey->szRecipient : ""), g_szOutputSeparator, (pEncKey->szKeyName ? pEncKey->szKeyName : ""), g_szOutputSeparator, (pEncKey->szCarriedKeyName ? pEncKey->szCarriedKeyName : ""), g_szOutputSeparator, (pEncKey->szEncryptionMethod ? pEncKey->szEncryptionMethod : ""), g_szOutputSeparator, (pEncKey->pCert ? "OK" : "NULL")); else fprintf(stdout, "\nEncryptedKey: Id=%s Recipient=%s KeyName=%s CarriedKeyName=%s EncryptionMethod=%s Cert: %s", (pEncKey->szId ? pEncKey->szId : ""), (pEncKey->szRecipient ? pEncKey->szRecipient : ""), (pEncKey->szKeyName ? pEncKey->szKeyName : ""), (pEncKey->szCarriedKeyName ? pEncKey->szCarriedKeyName : ""), (pEncKey->szEncryptionMethod ? pEncKey->szEncryptionMethod : ""), (pEncKey->pCert ? "OK" : "NULL")); } if(pEncData->encProperties.nEncryptionProperties > 0) { if(g_cgiMode) fprintf(stdout, "\nEncryptionProperties%s%s", g_szOutputSeparator, (pEncData->encProperties.szId ? pEncData->encProperties.szId : "")); else fprintf(stdout, "\nEncryptionProperties: %s", (pEncData->encProperties.szId ? pEncData->encProperties.szId : "")); for(k = 0; k < pEncData->encProperties.nEncryptionProperties; k++) { DEncEncryptionProperty *pEncProp = pEncData->encProperties.arrEncryptionProperties[k]; if(g_cgiMode) fprintf(stdout, "\nEncryptionProperty%s%s%s%s%s%s%s%s\n", g_szOutputSeparator, (pEncProp->szId ? pEncProp->szId : ""), g_szOutputSeparator, (pEncProp->szTarget ? pEncProp->szTarget : ""), g_szOutputSeparator, (pEncProp->szName ? pEncProp->szName : ""), g_szOutputSeparator, (pEncProp->szContent ? pEncProp->szContent : "")); else fprintf(stdout, "\nEncryptionProperty Id=%s Target=%s Name=%s Content=%s\n", (pEncProp->szId ? pEncProp->szId : ""), (pEncProp->szTarget ? pEncProp->szTarget : ""), (pEncProp->szName ? pEncProp->szName : ""), (pEncProp->szContent ? pEncProp->szContent : "")); } } return err; } //-------------------------------------------------- // Add ecryption recipients //-------------------------------------------------- int runDEncListCmds(int argc, char** argv) { int err = ERR_OK, i; DEncEncryptedData* pEncData = 0; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a recipients key if(!strcmp(argv[i], "-denc-list")) { if(argc > i+1 && argv[i+1][0] != '-') { char* file = argv[i+1]; err = dencSaxReadEncryptedData(&pEncData, file); if(!err) err = cmdListEncryptedData(pEncData); if(pEncData && !err) dencEncryptedData_free(pEncData); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -denc-list command"); } } } } return err; } //-------------------------------------------------- // decryption file //-------------------------------------------------- int runDecryptCmds(int argc, char** argv, DEncEncryptedData** ppEncData) { int err = ERR_OK, i, bDecSk = 0, nSlot = 0, nKey = 0; DEncEncryptedKey* pEncKey = 0; FILE *hFile = 0; SignedDoc *pSigDoc = 0; DataFile *pDf = 0; char fname1[256], *pkcs12file = 0, *infile = 0, *pin = 0, key[300]; EVP_PKEY *pkey; #ifdef WIN32 wchar_t *convFileName = 0; int l1 = 0; #endif for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // decrypt file if(!strcmp(argv[i], "-decrypt") || !strcmp(argv[i], "-decrypt-hex") || !strcmp(argv[i], "-decrypt-sk")) { if(!strcmp(argv[i], "-decrypt-sk")) bDecSk = 1; if(argc > i+3 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { ddocConvertInput(argv[i+1], &infile); ddocConvertInput(argv[i+2], &pin); nKey = 0; memset(key, 0, sizeof(key)); if(!strcmp(argv[i], "-decrypt-hex")) { nKey = sizeof(key); hex2bin(pin, (byte*)key, &nKey); } i += 2; if(argc > i+1 && argv[i+1][0] != '-') { ddocConvertInput(argv[i+1], &pkcs12file); i++; } if(argc > i+2 && argv[i+2][0] != '-') { nSlot = atoi(argv[i+2]); i++; } ddocDebug(3, "runDecryptCmds", "Decrypt file: %s pin: %s pkcs12: %s slot: %d", infile, pin, pkcs12file, nSlot); err = dencSaxReadEncryptedData(ppEncData, infile); if(err) return err; // if using hex key if(nKey > 0) { ddocDebug(3, "runDecryptCmds", "Decrypt with key: %s len: %d", pin, nKey); err = dencEncryptedData_decrypt_withKey(*ppEncData, key, nKey); } // if using pkcs12 else if(pkcs12file != NULL && strlen(pkcs12file) > 0) { ddocDebug(3, "runDecryptCmds", "Opening pkcs12 file: %s", pkcs12file); err = dencEncryptedData_findEncryptedKeyByPKCS12(*ppEncData, &pEncKey, &pkey, pkcs12file, pin); } else { ddocDebug(3, "runDecryptCmds", "Connecting to pkcs11, slot: %d", nSlot); err = dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot(*ppEncData, &pEncKey, nSlot); } if(!nKey) { if(pEncKey) { if(pkcs12file != NULL && strlen(pkcs12file) > 0) err = dencEncryptedData_decryptWithKey(*ppEncData, pEncKey, pkey); else err = dencEncryptedData_decryptUsingSlot(*ppEncData, pEncKey, pin, nSlot); if(err) return err; } else { err = ERR_DENC_DECRYPT; addError(err, __FILE__, __LINE__, "No transport key found for your smartcard"); } } // read in ddoc if necessary if(bDecSk && p_szOutFile) { sprintf(fname1, "%s.ddoc", p_szOutFile); ddocDebug(3, "runDecryptCmds", "writing ddoc to: %s", fname1); #ifdef WIN32 err = utf82unicode((const char*)fname1, (char**)&convFileName, &l1); ddocDebug(3, "ddocReadFile", "file: %s, conv-file: %s len: %d", fname1, convFileName, i); if((hFile = _wfopen(convFileName, L"wb")) != NULL) { #else if((hFile = fopen(fname1, "wb")) != NULL) { #endif fwrite((*ppEncData)->mbufEncryptedData.pMem, (*ppEncData)->mbufEncryptedData.nLen, 1, hFile); fclose(hFile); ddocDebug(3, "runDecryptCmds", "Reading ddoc: %s", fname1); err = ddocSaxReadSignedDocFromFile(&pSigDoc, fname1, 0, 0); if(!err && getCountOfDataFiles(pSigDoc) > 0) { pDf = getDataFile(pSigDoc, 0); ddocDebug(3, "runDecryptCmds", "writing DF: %s to: %s", pDf->szId, p_szOutFile); err = ddocExtractDataFile(pSigDoc, fname1, p_szOutFile, pDf->szId, "UTF-8"); dencEncryptedData_free(*ppEncData); *ppEncData = NULL; p_szOutFile = NULL; } SignedDoc_free(pSigDoc); if(fname1[0] && !remove(fname1)) ddocDebug(3, "runDecryptCmds", "error deleting file: %", fname1); } } // p_szOutFile } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing or argument of -decrypt command"); } } } } return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- int runExtractCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // add a DataFile if(!strcmp(argv[i], "-extract")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* id = NULL; char* file = NULL; char* charset = CHARSET_UTF_8; checkArguments(argc, argv, &i, &id); checkArguments(argc, argv, &i, &file); // optional charset & filenamecharset //checkArguments(argc, argv, &i, &charset); err = ddocExtractDataFile(*ppSigDoc, (const char*)p_szInFile, (const char*)file, (const char*)id, (const char*)charset); // report success if(g_cgiMode) fprintf(stdout, "\nDataFile%s%s%s%s%s%d", g_szOutputSeparator, id, g_szOutputSeparator, file, g_szOutputSeparator, err); else fprintf(stdout, "\nDataFile id: %s path: %s rc: %d", id, file, err); if(id) freeLibMem(id); if(file) freeLibMem(file); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -extract command"); } } } } return err; } //-------------------------------------------------- // Create digidoc and adds datafiles //-------------------------------------------------- int runExtractMemCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i; char* pBuf = 0; long nLen = 0; FILE* hFile = 0; for(i = 1; (err == ERR_OK) && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // extract DataFile if(!strcmp(argv[i], "-extract-mem")) { if(argc > i+2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { char* id = NULL; char* file = NULL; checkArguments(argc, argv, &i, &id); checkArguments(argc, argv, &i, &file); err = ddocGetDataFileCachedData(*ppSigDoc, id, (void**)&pBuf, &nLen); printf("\nExtract DF: %s, err: %d data: %ld", id, err, nLen); if(file && (hFile = fopen(file, "wb")) != NULL && pBuf && nLen) fwrite(pBuf, nLen, 1, hFile); if(id) freeLibMem(id); if(file) freeLibMem(file); if(hFile) fclose(hFile); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -extract command"); } } } } if(pBuf) freeLibMem(pBuf); if(hFile) fclose(hFile); return err; } //-------------------------------------------------- // Verfys sigantures and notaries //-------------------------------------------------- int runVerifyCmds(int argc, char** argv, SignedDoc* pSigDoc, DEncEncryptedData* pEncData) { int err = ERR_OK, i; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-verify")) { if(pSigDoc) { err = cmdVerify(pSigDoc); } if(pEncData) err = dencValidate(pEncData); } } } return err; } //-------------------------------------------------- // Handles signature commands //-------------------------------------------------- int runSignCmds(int argc, char** argv, SignedDoc** ppSigDoc) { int err = ERR_OK, i, nManif, nSlot = 0, nOcsp = 1, nSigner = 1; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-sign")) { char* pin = NULL; char* manifest = NULL; char* city = NULL; char* state = NULL; char* zip = NULL; char* country = NULL; char* sSlot = NULL; char* sOcsp = NULL; char* sSigner = NULL; char* szPkcs12File = NULL; checkArguments(argc, argv, &i, &pin); // if pin is NULL check for autosign pin if(!pin) pin = (char*)ConfigItem_lookup("AUTOSIGN_PIN"); if(!pin) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -sign command"); return err; } // check config file nManif = ConfigItem_lookup_int("MANIFEST_MODE", 0); if(nManif == 2) { manifest = (char*)ConfigItem_lookup("DIGIDOC_ROLE_MANIFEST"); country = (char*)ConfigItem_lookup("DIGIDOC_ADR_COUNTRY"); state = (char*)ConfigItem_lookup("DIGIDOC_ADR_STATE"); city = (char*)ConfigItem_lookup("DIGIDOC_ADR_CITY"); zip = (char*)ConfigItem_lookup("DIGIDOC_ADR_ZIP"); } // optional mainfest argument checkArguments(argc, argv, &i, &manifest); // optional address checkArguments(argc, argv, &i, &city); checkArguments(argc, argv, &i, &state); checkArguments(argc, argv, &i, &zip); checkArguments(argc, argv, &i, &country); checkArguments(argc, argv, &i, &sSlot); checkArguments(argc, argv, &i, &sOcsp); checkArguments(argc, argv, &i, &sSigner); if(sSlot) nSlot = atoi(sSlot); if(sOcsp) nOcsp = atoi(sOcsp); if(sSigner) { if(!strcmp(sSigner, "PKCS11")) nSigner = 1; if(!strcmp(sSigner, "PKCS12")) nSigner = 3; #ifdef WIN32 if(!strcmp(sSigner, "CNG")) nSigner = 2; #endif } checkArguments(argc, argv, &i, &szPkcs12File); err = cmdSign(*ppSigDoc, (const char*)pin, (const char*)manifest, (const char*)city, (const char*)state, (const char*)zip, (const char*)country, nSlot, nOcsp, nSigner, szPkcs12File); if(manifest) freeLibMem(manifest); if(city) freeLibMem(city); if(state) freeLibMem(state); if(zip) freeLibMem(zip); if(country) freeLibMem(country); if(sSlot) freeLibMem(sSlot); if(sOcsp) freeLibMem(sOcsp); if(sSigner) freeLibMem(sSigner); if(szPkcs12File) freeLibMem(szPkcs12File); } } } return err; } //-------------------------------------------------- // Handles commands related to checking certificates //-------------------------------------------------- int runCheckCertCmds(int argc, char** argv) { int err = ERR_OK, i; char* szCertFile = 0; X509* pCert = 0; DigiDocMemBuf mbuf; mbuf.pMem = 0; mbuf.nLen = 0; for(i = 1; !err && (i < argc); i++) { if(!strcmp(argv[i], "-check-cert") && argv[i+1][0] != '-') { szCertFile = argv[i+1]; i++; if(szCertFile) { err = ReadCertificate(&pCert, szCertFile); if(!err && pCert) { err = ddocVerifyCertByOCSP(pCert, NULL); err = ddocCertGetSubjectCN(pCert, &mbuf); printf("Verifying cert: %s --> RC :%d\n", (const char*)mbuf.pMem, err); ddocMemBuf_free(&mbuf); } if(pCert) { X509_free(pCert); pCert = 0; } } } } return err; } //-------------------------------------------------- // Handles commands related to adding signature value // from a file containging base64 encoded RSA-SHA1 signature value //-------------------------------------------------- int runAddSignValueCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i; char *szSignFile = 0, *szSignId = 0; SignatureInfo* pSignInfo = 0; for(i = 1; !err && (i < argc); i++) { if(!strcmp(argv[i], "-add-sign-value") && i < argc - 2 && argv[i+1][0] != '-' && argv[i+2][0] != '-') { checkArguments(argc, argv, &i, &szSignFile); checkArguments(argc, argv, &i, &szSignId); if(!pSigDoc) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No digidoc document read in yet!"); return err; } if(szSignFile && szSignId) { pSignInfo = getSignatureWithId(pSigDoc, szSignId); if(pSignInfo) { // read the file err = setSignatureValueFromFile(pSignInfo, szSignFile); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Wrong signature id"); } // report on success if(g_cgiMode) fprintf(stdout, "\nAddSignValue%s%s%s%s%s%d", g_szOutputSeparator, szSignId, g_szOutputSeparator, szSignFile, g_szOutputSeparator, err); else fprintf(stdout, "\nAddSignValue id: %s path: %s rc: %d", szSignId, szSignFile, err); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing or argument of -add-sign-value command"); } } } if(szSignFile) freeLibMem(szSignFile); if(szSignId) freeLibMem(szSignId); return err; } //-------------------------------------------------- // Handles commands related to deleting signatures //-------------------------------------------------- int runDelSignCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i; char *szSignId = 0; SignatureInfo* pSignInfo = 0; for(i = 1; !err && (i < argc); i++) { if(!strcmp(argv[i], "-del-sign") && i < argc - 1 && argv[i+1][0] != '-') { checkArguments(argc, argv, &i, &szSignId); if(!pSigDoc) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No digidoc document read in yet!"); return err; } if(szSignId) { pSignInfo = getSignatureWithId(pSigDoc, szSignId); if(pSignInfo) { err = SignatureInfo_delete(pSigDoc, szSignId); // report on success if(g_cgiMode) fprintf(stdout, "\nDelSign%s%s%s%d", g_szOutputSeparator, szSignId, g_szOutputSeparator, err); else fprintf(stdout, "\nDelSign id: %s rc: %d", szSignId, err); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "wrong signature id!"); } } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -del-sign command"); } } } if(szSignId) freeLibMem(szSignId); return err; } //-------------------------------------------------- // Handles commands related to notarizing signatures //-------------------------------------------------- int runGetConfirmationCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i; char *szSignId = 0; SignatureInfo* pSignInfo = 0; for(i = 1; !err && (i < argc); i++) { if(!strcmp(argv[i], "-get-confirmation") && i < argc - 1 && argv[i+1][0] != '-') { checkArguments(argc, argv, &i, &szSignId); if(!pSigDoc) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "No digidoc document read in yet!"); return err; } if(szSignId) { pSignInfo = getSignatureWithId(pSigDoc, szSignId); if(pSignInfo) { err = notarizeSignature(pSigDoc, pSignInfo); // report on success if(g_cgiMode) fprintf(stdout, "\nNotarizeSignature%s%s%s%d", g_szOutputSeparator, szSignId, g_szOutputSeparator, err); else fprintf(stdout, "\nNotarizeSignature id: %s rc: %d", szSignId, err); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "wrong signature id!"); } if(szSignId) freeLibMem(szSignId); } else { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -get-confirmation command"); } } } return err; } //-------------------------------------------------- // Signs the document and gets configrmation //-------------------------------------------------- int cmdCalcSign(SignedDoc* pSigDoc, const char* manifest, const char* city, const char* state, const char* zip, const char* country, const char* certFile) { int err = ERR_OK, l1; SignatureInfo* pSigInfo = NULL; X509* pCert = NULL; char buf1[50]; ddocDebug(3, "cmdCalcSign", "Creating new digital signature"); RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(certFile); // read certificate // this certificate will nto be released since new signature takes ownership! err = ReadCertificate(&pCert, certFile); RETURN_IF_NOT(err == ERR_OK, err); // prepare signature err = ddocPrepareSignature(pSigDoc, &pSigInfo, manifest, city, state, zip, country, pCert, NULL); // base64 encode final hash l1 = sizeof(buf1); err = ddocGetSignedHash(pSigInfo, buf1, &l1, 2, 0); RETURN_IF_NOT(err == ERR_OK, err); // report on success if(g_cgiMode) fprintf(stdout, "\nSignatureHash%s%s%s%s%s%d", g_szOutputSeparator, pSigInfo->szId, g_szOutputSeparator, buf1, g_szOutputSeparator, err); else fprintf(stdout, "\nSignatureHash id: %s hash: %s rc: %d", pSigInfo->szId, buf1, err); RETURN_IF_NOT(err == ERR_OK, err); return ERR_OK; } //-------------------------------------------------- // Handles signature commands //-------------------------------------------------- int runCalcSignCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i, nManif; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-calc-sign")) { char* certFile = NULL; char* manifest = NULL; char* city = NULL; char* state = NULL; char* zip = NULL; char* country = NULL; checkArguments(argc, argv, &i, &certFile); // check config file nManif = ConfigItem_lookup_int("MANIFEST_MODE", 0); if(nManif == 2) { manifest = (char*)ConfigItem_lookup("DIGIDOC_ROLE_MANIFEST"); country = (char*)ConfigItem_lookup("DIGIDOC_ADR_COUNTRY"); state = (char*)ConfigItem_lookup("DIGIDOC_ADR_STATE"); city = (char*)ConfigItem_lookup("DIGIDOC_ADR_CITY"); zip = (char*)ConfigItem_lookup("DIGIDOC_ADR_ZIP"); } // optional mainfest argument checkArguments(argc, argv, &i, &manifest); // optional address checkArguments(argc, argv, &i, &city); checkArguments(argc, argv, &i, &state); checkArguments(argc, argv, &i, &zip); checkArguments(argc, argv, &i, &country); if(!certFile) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -calc-sign command"); } else err = cmdCalcSign(pSigDoc, (const char*)manifest, (const char*)city, (const char*)state, (const char*)zip, (const char*)country, (const char*)certFile); if(manifest) freeLibMem(manifest); if(city) freeLibMem(city); if(state) freeLibMem(state); if(zip) freeLibMem(zip); if(country) freeLibMem(country); if(certFile) freeLibMem(certFile); } } } return err; } //-------------------------------------------------- // Signs the document and gets configrmation //-------------------------------------------------- int cmdMidSign(SignedDoc* pSigDoc, const char* szPhoneNo, const char* szIdCode, const char* szLang, const char* szService, const char* manifest, const char* city, const char* state, const char* zip, const char* country) { int err = ERR_OK, nPollFreq = 0, l1, nStatus = 0; char* szUrl = 0, *szProxyHost = 0, *szProxyPort = 0; long lSesscode = 0; char buf1[10]; DigiDocMemBuf mbuf1; #ifdef WIN32 time_t tNew, tOld; #endif mbuf1.pMem = 0; mbuf1.nLen = 0; nPollFreq = ConfigItem_lookup_int("DDS_POLLFREQ", 0); szUrl = (char*)ConfigItem_lookup("DDS_URL"); szProxyHost = (char*)ConfigItem_lookup("DDS_PROXY_HOST"); szProxyPort = (char*)ConfigItem_lookup("DDS_PROXY_PORT"); ddocDebug(3, "cmdMidSign", "Creating MID signature using: %s poll freq: %d", szPhoneNo, nPollFreq); // send signature req l1 = sizeof(buf1); ddsSign(pSigDoc, szIdCode, szPhoneNo, szLang, szService, manifest, city, state, zip, country, szUrl, szProxyHost, szProxyPort, &lSesscode, buf1, l1); // report on success if(g_cgiMode) fprintf(stdout, "\nMIDSinatureReq%s%ld%s%d", g_szOutputSeparator, lSesscode, g_szOutputSeparator, err); else fprintf(stdout, "\nMIDSignatureReq session: %ld rc: %d", lSesscode, err); // if we should keep on polling if(!err && nPollFreq) { // now check status do { #ifdef WIN32 time(&tOld); do { time(&tNew); } while(tNew - tOld < nPollFreq); #else ddocDebug(3, "cmdMidSign", "Sleep: %d", nPollFreq); sleep(nPollFreq); #endif err = ddsGetStatusWithFile(pSigDoc, lSesscode, szUrl, szProxyHost, szProxyPort, &nStatus, p_szInFile); ddocDebug(3, "cmdMidSign", "Txn: %ld status: %d err: %d", lSesscode, nStatus, err); } while(!err && nStatus == 1); } if(g_cgiMode) fprintf(stdout, "\nMID session %s%ld%s%d", g_szOutputSeparator, lSesscode, g_szOutputSeparator, nStatus); else fprintf(stdout, "\nMID session %ld complete status: %d", lSesscode, nStatus); RETURN_IF_NOT(err == ERR_OK, err); return ERR_OK; } //-------------------------------------------------- // Handles MID signature commands //-------------------------------------------------- int runMidSignCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i, nManif = 0; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-mid-sign")) { char* phoneNo = NULL; char* idcode = NULL; char* service = NULL; char* lang = NULL; char* manifest = NULL; char* city = NULL; char* state = NULL; char* zip = NULL; char* country = NULL; checkArguments(argc, argv, &i, &phoneNo); // check config file nManif = ConfigItem_lookup_int("MANIFEST_MODE", 0); if(nManif == 2) { manifest = (char*)ConfigItem_lookup("DIGIDOC_ROLE_MANIFEST"); country = (char*)ConfigItem_lookup("DIGIDOC_ADR_COUNTRY"); state = (char*)ConfigItem_lookup("DIGIDOC_ADR_STATE"); city = (char*)ConfigItem_lookup("DIGIDOC_ADR_CITY"); zip = (char*)ConfigItem_lookup("DIGIDOC_ADR_ZIP"); } // optional mainfest argument checkArguments(argc, argv, &i, &idcode); checkArguments(argc, argv, &i, &country); checkArguments(argc, argv, &i, &lang); checkArguments(argc, argv, &i, &service); checkArguments(argc, argv, &i, &manifest); checkArguments(argc, argv, &i, &city); checkArguments(argc, argv, &i, &state); checkArguments(argc, argv, &i, &zip); if(!phoneNo) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing argument of -mid-sign command"); } else cmdMidSign(pSigDoc, (const char*)phoneNo, (const char*)idcode, (const char*)(lang ? lang : "EST"), (const char*)(service ? service : "Testimine"), (const char*)manifest, (const char*)city, (const char*)state, (const char*)zip, (const char*)(country ? country : "EE")); if(manifest) freeLibMem(manifest); if(city) freeLibMem(city); if(state) freeLibMem(state); if(zip) freeLibMem(zip); if(country) freeLibMem(country); if(phoneNo) freeLibMem(phoneNo); } } } return err; } //-------------------------------------------------- // Handles MID signature commands //-------------------------------------------------- int runMidTestCmds(int argc, char** argv, SignedDoc* pSigDoc) { int err = ERR_OK, i, e1; SignedDoc *pSdoc = NULL; DataFile *pDf = NULL; long lSize1, lSize2, lSize3; for(i = 1; !err && (i < argc); i++) { if(argv[i][0] == '-') { // all commands and options must start with - // create new digidoc if(!strcmp(argv[i], "-mid-test")) { char* infile = NULL; char* inmime = NULL; char* outddoc = NULL; char* phoneNo = NULL; char* idcode = NULL; char* service = NULL; checkArguments(argc, argv, &i, &infile); checkArguments(argc, argv, &i, &inmime); checkArguments(argc, argv, &i, &outddoc); checkArguments(argc, argv, &i, &phoneNo); checkArguments(argc, argv, &i, &idcode); checkArguments(argc, argv, &i, &service); if(!phoneNo || !idcode || !infile || !inmime || !outddoc) { err = ERR_BAD_PARAM; addError(err, __FILE__, __LINE__, "Missing or argument of -mid-test command"); } else { p_szInFile = outddoc; printf("Creating ddoc: %s of file: %s mime: %s\n", outddoc, infile, inmime); err = SignedDoc_new(&pSdoc, "DIGIDOC-XML", "1.3"); printf("Creating ddoc: %s rc: %d\n", outddoc, err); RETURN_IF_NOT(err == ERR_OK, err); err = calculateFileSize(infile, &lSize1); err = DataFile_new(&pDf, pSdoc, NULL, infile, "EMBEDDED_BASE64", inmime, 0, NULL, 0, NULL, NULL); err = createSignedDoc(pSdoc, NULL, outddoc); if(pDf->nSize == 0 && lSize1 > 0) pDf->nSize = lSize1; err = calculateFileSize(outddoc, &lSize2); printf("Add data-file: %s rc: %d d-size: %ld ddoc-size: %ld\n", infile, err, lSize1, lSize2); err = ddocExtractDataFile(pSdoc, outddoc, "D0.dat", "D0", "UTF-8"); err = calculateFileSize("D0.dat", &lSize3); printf("Extract before signing rc: %d size: %ld\n", err, lSize3); printf("MID signing phone: %s id-code: %s\n", phoneNo, idcode); err = cmdMidSign(pSdoc, (const char*)phoneNo, (const char*)idcode, "EST", (service ? service : "Testimine"), NULL, NULL, NULL, NULL, "EE"); err = calculateFileSize(outddoc, &lSize2); printf("MID signed phone: %s id-code: %s ddoc-size: %ld rc: %d\n", phoneNo, idcode, lSize2, err); err = cmdVerify(pSdoc); printf("\nVerify after signing rc: %d\n", err); lSize3 = 0; err = ddocExtractDataFile(pSdoc, outddoc, "D0.dat", "D0", "UTF-8"); err = calculateFileSize("D0.dat", &lSize3); printf("Extract after signing rc: %d size: %ld\n", err, lSize3); } SignedDoc_free(pSdoc); if(infile) freeLibMem(infile); if(inmime) freeLibMem(inmime); if(outddoc) freeLibMem(outddoc); if(phoneNo) freeLibMem(phoneNo); if(idcode) freeLibMem(idcode); if(service) freeLibMem(service); } } } return err; } //-------------------------------------------------- // Program main function //-------------------------------------------------- int main(int argc, char** argv) { int err = ERR_OK, e = 0; SignedDoc* pSigDoc = 0; DEncEncryptedData* pEncData = 0; time_t t1, t2; #ifdef WIN32 char buf1[250]; #endif if(argc <= 1) { printUsage(); exit(0); } // init DigiDoc library initDigiDocLib(); #ifdef WIN32 // find out program home if invoked with a long command line memset(buf1, 0, sizeof(buf1)); getFileNamePath(argv[0], buf1, sizeof(buf1)); if(strlen(buf1)) { strncat(buf1, "digidoc.ini", sizeof(buf1)); err = initConfigStore(buf1); } else err = initConfigStore(NULL); #else // read in config file err = initConfigStore(NULL); #endif // clear all errors that were encountered by not finding config files err = checkProgArguments(argc, argv); time(&t1); // register program name and version setGUIVersion(g_szProgNameVer); ddocDebugTruncateLog(); // use command line argument if required if(p_szConfigFile) err = readConfigFile(p_szConfigFile, ITEM_TYPE_PRIVATE); // read flags from config file readConfigParams(); // display programm name and version if(g_cgiMode) { if(ConfigItem_lookup_bool("DIGIDOC_CGI_PRINT_HEADER", 1)) fprintf(stdout, "%s%s%s", getLibName(), g_szOutputSeparator, getLibVersion()); } else { fprintf(stdout, "%s - %s", getLibName(), getLibVersion()); } // execute the commands now // check certificate status throught OCSP if(!err) err = runCheckCertCmds(argc, argv); // read input file if necessary if(p_szInFile && !err) { if(p_parseMode != 3) err = cmdReadDigiDoc(&pSigDoc, &pEncData, p_parseMode); else err = cmdReadDigiDocFromMem(&pSigDoc, &pEncData); // if read error was warning then continue if(pSigDoc && isWarning(pSigDoc, err)) err = ERR_OK; if(err && pSigDoc) printErrorsAndWarnings(pSigDoc); } // various tests if(!err) err = runTestCmds(argc, argv); if(p_szInEncFile && !err) { if(hasCmdLineArg(argc, argv, "-encrypt-sk")) err = cmdEncryptSk(&pEncData, p_szInEncFile); else err = cmdEncrypt(&pEncData, p_szInEncFile); } // list encrypted files if(!err) err = runDEncListCmds(argc, argv); // add data files if(!err) err = runAddCmds(argc, argv, &pSigDoc); // add data files from mem if(!err) err = runAddMemCmds(argc, argv, &pSigDoc); // add recipients if(!err) err = runRecipientCmds(argc, argv, &pEncData); // encrypt whole files if(!err) err = runEncryptFileCmds(argc, argv, pEncData); // decrypt whole files if(!err) err = runDecryptFileCmds(argc, argv); // run signature commands if(!err) err = runSignCmds(argc, argv, &pSigDoc); // calculate signature hash commands if(!err) err = runCalcSignCmds(argc, argv, pSigDoc); if(!err) err = runMidSignCmds(argc, argv, pSigDoc); if(!err) err = runMidTestCmds(argc, argv, pSigDoc); // verify signatures if(!err) { e = runVerifyCmds(argc, argv, pSigDoc, pEncData); if(!err && e) err = e; } // extract datafiles if(!err) err = runExtractCmds(argc, argv, &pSigDoc); if(!err) err = runExtractMemCmds(argc, argv, &pSigDoc); // decrypt files if(!err) err = runDecryptCmds(argc, argv, &pEncData); // add signature value from a file if(!err) err = runAddSignValueCmds(argc, argv, pSigDoc); // delete signatures if(!err) err = runDelSignCmds(argc, argv, pSigDoc); // notarize signatures if(!err) err = runGetConfirmationCmds(argc, argv, pSigDoc); if(!err) err = runEncryptTestSetCmds(argc, argv); // write output file if(p_szOutFile && !err) if(p_parseMode != 3) err = cmdWrite(pSigDoc, pEncData); else err = cmdWriteMem(pSigDoc, pEncData); time(&t2); printErrorsAndWarnings(pSigDoc); if(pSigDoc && !isError(pSigDoc, err)) { // find correct error from list e = hasErrors(pSigDoc); if((!err || !isError(pSigDoc,err)) && e) err = e; } // display programm error code and elapsed time if(g_cgiMode) { if(ConfigItem_lookup_bool("DIGIDOC_CGI_PRINT_TRAILER", 1)) fprintf(stdout, "\n%s%s%d%s%ld", getLibName(), g_szOutputSeparator, (isError(pSigDoc,err) ? err : 0), g_szOutputSeparator, (long)(t2-t1)); } else { fprintf(stdout, "\n%s - time: %ld sec result: %s", getLibName(), (long)(t2-t1), (isError(pSigDoc,err) ? "failure" : "success")); } fprintf(stdout, "\n"); // cleanup if(pSigDoc) SignedDoc_free(pSigDoc); if(pEncData) dencEncryptedData_free(pEncData); if(g_szOutputSeparator) free(g_szOutputSeparator); // cleanup #ifndef WIN32 // TODO: somehow this free gives invalid heap error on win32 cleanupConfigStore(NULL); #endif finalizeDigiDocLib(); return err; } libdigidoc-3.10.5/libdigidoc/DigiCrypt.c0000664000372000037200000007207513560273131017442 0ustar travistravis//==========< HISTORY >============================= // 29.10.2003 Changes by AA // ReadCertFromCard adapted // from Tarmo's example // 09.10.2003 Changes by AA // 02.09.2003 Changes from Tarmo Milva //Changed functions: //DigiCrypt_GetDataFromCert //DigiCrypt_GetFirstAllowedCSPName //DigiCrypt_GetDefaultKeyContainerName //DigiCrypt_SelectFromAllKeysCerts // #include "DigiCrypt.h" #include "DigiDocDefs.h" #include "DigiDocConfig.h" #include #include #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) #define dSTRING_ITEM_LEN 255 #define dNAME_ITEM_LEN 1024 #define dCSPTYPE_NOTDEFINED -1 static char *psData_CSP_Path = "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\"; static char *psData_Extra_CSP_Name = "Advanced Setec SetCSP"; static char *psData_Ignore_CSP_Name ="XXXEstEID"; static char *psData_Est_CSP_Name = "EstEID"; //Global data static HCRYPTPROV oG_hProvider = 0; static char oG_sCSPName[dSTRING_ITEM_LEN+1]; static char oG_sKeyContainerName[dNAME_ITEM_LEN+1]; static BOOL oG_fDialogUserCancel; extern int RunDialogUnit(char *psList[], int iWinWidth, int iWinHeight); PCCERT_CONTEXT DigiCrypt_ReadCertFromCard(void); static BOOL DigiCrypt_AddCertToStore(PCCERT_CONTEXT pCert); static BOOL OpenProvider(HCRYPTPROV *phProv, char *psProvider, DWORD dwFlags); static HCERTSTORE DigiCrypt_OpenStore(void); static char *DigiCrypt_GetFirstAllowedCSPNameNew(void); static char *DigiCrypt_GetFirstAllowedCSPName(void); static void DigiCrypt_ReleaseFirstAllowedCSP(void); static BOOL DigiCrypt_GetCSPFromCert(PCCERT_CONTEXT pCertContext, char *psResult, int iMaxResLen); static BOOL DigiCrypt_GetContainerFromCert(PCCERT_CONTEXT pCertContext, char *psResult, int iMaxResLen); static BOOL DigiCrypt_CertIsSig(PCCERT_CONTEXT pCertContext); static char *DigiCrypt_GetDefaultKeyContainerName(char *psCSPName); static char *DigiCrypt_GetDefaultKeyContainerNameSimple(char *psCSPName); static char *DigiCrypt_GetDefaultCSPName(void); static BOOL DigiCrypt_GetDataFromCert(PCCERT_CONTEXT pCertContext); static PCCERT_CONTEXT DigiCrypt_SelectFromAllCerts(void); static PCCERT_CONTEXT DigiCrypt_SelectFromAllKeysCerts(HCRYPTPROV hProvider); static void DigiCrypt_SelectCertsFromKeyContainer(HCRYPTPROV hProv, char *psContainerName); static void DigiCrypt_ChangeContainerName(char *psContainerName); static void RunDlg_Clear(void); static BOOL RunDlg_AddItem(PCCERT_CONTEXT pCertContext, BOOL fTimeCheck); static PCCERT_CONTEXT RunDlg_RunDlg(void); static BOOL RunDlg_FillItem(PCCERT_CONTEXT pCertContext, char *psRes, int len); static void IntLogToFile(char *psMsg, int iMsgLen); static BOOL IsLogEnabled(void); PCCERT_CONTEXT DigiCrypt_FindContext(BOOL fByKeyContainer, DWORD *dwResult) { PCCERT_CONTEXT hCert = NULL; char *psCSPName; char *psDefaultKeyContainerName; oG_fDialogUserCancel = FALSE; *dwResult = dDigiCrypt_Okey; memset(oG_sCSPName, 0, sizeof(oG_sCSPName)); memset(oG_sKeyContainerName, 0, sizeof(oG_sKeyContainerName)); if (fByKeyContainer == TRUE) { hCert = DigiCrypt_ReadCertFromCard(); //TEST //Test_ReadCertDataC(hCert); //ENDTEST if (hCert == NULL) { psCSPName = DigiCrypt_GetFirstAllowedCSPNameNew(); if (psCSPName == NULL) *dwResult = dDigiCrypt_Error_NotFoundCSP; else { psDefaultKeyContainerName = DigiCrypt_GetDefaultKeyContainerName(oG_sCSPName); if (psDefaultKeyContainerName == NULL) *dwResult = dDigiCrypt_Error_NoDefaultKey; else hCert = DigiCrypt_SelectFromAllKeysCerts(oG_hProvider); } } } else { hCert = DigiCrypt_SelectFromAllCerts(); if (hCert != NULL) DigiCrypt_GetDataFromCert(hCert); } if (hCert == NULL) { if (oG_fDialogUserCancel == TRUE) *dwResult = dDigiCrypt_Error_UserCancel; else { if (*dwResult == dDigiCrypt_Okey) *dwResult = dDIgiCrypt_Error_NotFoundCert; } } return(hCert); } PCCERT_CONTEXT DigiCrypt_ReadCertFromCard(void) { HCRYPTPROV hCryptProv; BYTE *pbData = NULL; HCRYPTKEY hKey; DWORD cbData = 0; DWORD dwKeyType=0, dwKeySpec = AT_SIGNATURE; DWORD dwErrCode=0; DWORD cspType=0; DWORD cspFlag=CRYPT_SILENT; char *psCspName = NULL; char *psKeyContainer; BOOL fRes = FALSE; PCCERT_CONTEXT pCertContext = NULL; CRYPT_KEY_PROV_INFO KeyProvInfo; LPWSTR wszContainerName=NULL; LPWSTR wszProvName=NULL; DWORD cchContainerName; DWORD cchCSPName; HCRYPTPROV hProv; DigiCrypt_ReleaseFirstAllowedCSP(); psCspName=DigiCrypt_GetFirstAllowedCSPNameNew(); //very dummy thing.. i check from csp creators why i should do so... if(!lstrcmp(psCspName,"EstEID Card CSP")) fRes = CryptAcquireContext(&hProv,"XXX",psCspName,2, CRYPT_SILENT); // end dummy// if (psCspName == NULL || strstr(psCspName,psData_Est_CSP_Name) == NULL) return(pCertContext); cspType=DigiCrypt_FindContext_GetCSPType(psCspName); psKeyContainer=DigiCrypt_GetDefaultKeyContainerName(psCspName); fRes = CryptAcquireContext(&hCryptProv,psKeyContainer,psCspName,cspType, CRYPT_SILENT); if (fRes == FALSE) return(pCertContext); // VS: use alsu auth keys if KEY_USAGE_CHECK=false dwKeySpec = ConfigItem_lookup_int("KEY_USAGE_CHECK", 1) ? AT_SIGNATURE : 0; fRes=CryptGetUserKey(hCryptProv, dwKeySpec, &hKey); if (fRes == TRUE) { fRes=CryptGetKeyParam(hKey, KP_CERTIFICATE, NULL, &cbData, 0); if (fRes == TRUE) { pbData = malloc(cbData); if (pbData == NULL) fRes = FALSE; } if (fRes == TRUE) fRes=CryptGetKeyParam(hKey, KP_CERTIFICATE, pbData, &cbData, 0); if (fRes == TRUE) { pCertContext = CertCreateCertificateContext(MY_ENCODING_TYPE,pbData,cbData); if (pCertContext != NULL) { wszContainerName=NULL; wszProvName=NULL; cchContainerName = (lstrlen(psKeyContainer) + 1) * sizeof(WCHAR); cchCSPName = (lstrlen(psCspName) + 1) * sizeof(WCHAR); wszContainerName = (LPWSTR) malloc(cchContainerName); wszProvName = (LPWSTR) malloc(cchCSPName); mbstowcs(wszContainerName, psKeyContainer,cchContainerName); mbstowcs(wszProvName, psCspName, cchCSPName); ZeroMemory((PVOID)&KeyProvInfo, sizeof(CRYPT_KEY_PROV_INFO)); KeyProvInfo.pwszContainerName = (LPWSTR) wszContainerName; KeyProvInfo.pwszProvName = (LPWSTR) wszProvName; KeyProvInfo.dwProvType = PROV_RSA_SIG; KeyProvInfo.dwFlags = 0; KeyProvInfo.dwKeySpec = dwKeyType; fRes = CertSetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID, 0, (const void *) &KeyProvInfo); if (wszContainerName != NULL) free(wszContainerName); if (wszProvName != NULL) free(wszProvName); } } } //if (pCertContext != NULL) // DigiCrypt_AddCertToStore(pCertContext); if (fRes == FALSE && pCertContext != NULL) { CertFreeCertificateContext(pCertContext); pCertContext = NULL; } if (pbData != NULL) free(pbData); if (hCryptProv != 0) CryptReleaseContext(hCryptProv, 0); return(pCertContext); } static BOOL DigiCrypt_AddCertToStore(PCCERT_CONTEXT pCert) { BOOL fRes = FALSE; HCERTSTORE hSystemStore = NULL; // The system store handle. if (pCert != NULL) { if (hSystemStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A, 0, // Encoding type not needed with this PROV. 0, // Accept the default HCRYPTPROV. CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_SYSTEM_STORE_CURRENT_USER,"MY")) { if (CertAddCertificateContextToStore(hSystemStore, pCert, CERT_STORE_ADD_REPLACE_EXISTING,NULL)) fRes = TRUE; } } if (hSystemStore != NULL) CertCloseStore(hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG); return(fRes); } char *DigiCrypt_FindContext_GetKeyName() { if (lstrlen(oG_sKeyContainerName) > 0) return(oG_sKeyContainerName); else return(NULL); } char *DigiCrypt_FindContext_GetCSPName() { if (lstrlen(oG_sCSPName) > 0) return(oG_sCSPName); else return(NULL); } DWORD DigiCrypt_FindContext_GetCSPType(char *psCSPName) { DWORD dwRes = PROV_RSA_SIG; DWORD dwType = REG_DWORD; DWORD dwLen = dSTRING_ITEM_LEN; DWORD *pdwVal; HKEY hKey; LONG lRes; char sKeyNameBuf[dSTRING_ITEM_LEN+1]; char sValue[dSTRING_ITEM_LEN+1]; strncpy(sKeyNameBuf, psData_CSP_Path, sizeof(sKeyNameBuf)); strncat(sKeyNameBuf, psCSPName, sizeof(sKeyNameBuf) - strlen(sKeyNameBuf)); lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE,sKeyNameBuf, 0, KEY_READ, &hKey); if (lRes == ERROR_SUCCESS) { lRes = RegQueryValueEx(hKey, "Type", 0, &dwType, (LPBYTE)sValue, &dwLen); if (lRes == ERROR_SUCCESS) { pdwVal = (DWORD *)sValue; dwRes = (*pdwVal); } RegCloseKey(hKey); } return(dwRes); } static BOOL OpenProvider(HCRYPTPROV *phProv, char *psProvider, DWORD dwFlags) { BOOL fRes; DWORD dwType = DigiCrypt_FindContext_GetCSPType(psProvider); fRes = CryptAcquireContext(phProv,NULL,psProvider, dwType, dwFlags); return(fRes); } static HCERTSTORE DigiCrypt_OpenStore(void) { HCERTSTORE hStore; hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,(HCRYPTPROV)NULL,CERT_SYSTEM_STORE_CURRENT_USER,L"MY"); return(hStore); } static BOOL DigiCrypt_GetCSPFromCert(PCCERT_CONTEXT pCertContext, char *psResult, int iMaxResLen) { BOOL fRes = FALSE; CRYPT_KEY_PROV_INFO *poKeyInfo; DWORD pcbData; DWORD dwLen; if (pCertContext == NULL || psResult == 0) return(fRes); fRes = CertGetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID,NULL,&pcbData); if (fRes == TRUE) { poKeyInfo = malloc(pcbData); if (poKeyInfo != NULL) { fRes = CertGetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID,poKeyInfo,&pcbData); if (fRes == TRUE) { if (poKeyInfo->pwszProvName != NULL) { dwLen = WideCharToMultiByte(CP_ACP,0,poKeyInfo->pwszProvName,-1,psResult,iMaxResLen,NULL,NULL); } else fRes = FALSE; } free(poKeyInfo); } } return(fRes); } static BOOL DigiCrypt_GetContainerFromCert(PCCERT_CONTEXT pCertContext, char *psResult, int iMaxResLen) { BOOL fRes = FALSE; CRYPT_KEY_PROV_INFO *poKeyInfo; DWORD pcbData; DWORD dwLen; if (pCertContext == NULL || psResult == 0) return(fRes); fRes = CertGetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID,NULL,&pcbData); if (fRes == TRUE) { poKeyInfo = malloc(pcbData); if (poKeyInfo != NULL) { fRes = CertGetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID,poKeyInfo,&pcbData); if (fRes == TRUE) { if (poKeyInfo->pwszContainerName != NULL) { dwLen = WideCharToMultiByte(CP_ACP,0,poKeyInfo->pwszContainerName,-1,psResult,iMaxResLen,NULL,NULL); } else fRes = FALSE; } free(poKeyInfo); } } return(fRes); } static BOOL DigiCrypt_CertIsSig(PCCERT_CONTEXT pCertContext) { BOOL fRes = FALSE; CRYPT_KEY_PROV_INFO *poKeyInfo; DWORD pcbData; if (pCertContext == NULL) return(fRes); fRes = CertGetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID,NULL,&pcbData); if (fRes == TRUE) { poKeyInfo = malloc(pcbData); if (poKeyInfo != NULL) { fRes = CertGetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID,poKeyInfo,&pcbData); if (fRes == TRUE) { if (poKeyInfo->dwProvType == PROV_RSA_SIG) fRes = TRUE; } free(poKeyInfo); } } return(fRes); } static BOOL DigiCrypt_GetDataFromCert(PCCERT_CONTEXT pCertContext) { BOOL fRes = FALSE; char sContainer[dNAME_ITEM_LEN+1]; //DWORD dwLen; if (pCertContext == NULL) return(fRes); fRes = DigiCrypt_GetCSPFromCert(pCertContext, oG_sCSPName,dSTRING_ITEM_LEN); if (fRes == TRUE) { // DigiCrypt_GetDefaultKeyContainerNameSimple(oG_sCSPName); //this is not usable. Tarmo changed that! Instead we should use the following: if (DigiCrypt_GetContainerFromCert(pCertContext, sContainer, dNAME_ITEM_LEN) == TRUE) { strncpy(oG_sKeyContainerName, sContainer, sizeof(oG_sKeyContainerName)); } } return(fRes); } static char *DigiCrypt_GetFirstAllowedCSPNameNew(void) { char *psRes = NULL; HKEY hKey = NULL; LONG lRet=0; DWORD dwIndex = 0; BOOL fRes; char sProvName[dSTRING_ITEM_LEN+1]; char sKeyNameBuf[dSTRING_ITEM_LEN+1]; HCRYPTPROV hProvide = 0; DWORD dwBufLen; FILETIME oTime; //char buff[200]; BYTE pbData[dNAME_ITEM_LEN+1]; DWORD cbData=dNAME_ITEM_LEN+1; // DWORD dwProvType; strncpy(sKeyNameBuf, psData_CSP_Path, sizeof(sKeyNameBuf)); lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,sKeyNameBuf,0, KEY_READ, &hKey); while (lRet == ERROR_SUCCESS) { dwBufLen = dSTRING_ITEM_LEN; lRet = RegEnumKeyEx(hKey,dwIndex,sProvName,&dwBufLen,NULL,NULL,0,&oTime); if (lRet == ERROR_SUCCESS) { if (lstrcmp(sProvName,psData_Ignore_CSP_Name) != 0) { dwProvType = DigiCrypt_FindContext_GetCSPType(sProvName); LOG("CSP %s",sProvName); //printf("%s :",sProvName); if ((lstrcmp(sProvName,psData_Extra_CSP_Name) != 0) && (lstrcmp(sProvName,"Belgium Identity Card CSP")!=0)) { //fRes = OpenProvider(&hProvide, sProvName, CRYPT_SILENT); fRes = CryptAcquireContext(&hProvide,NULL,sProvName,dwProvType, CRYPT_SILENT); fRes=CryptGetProvParam(hProvide, PP_ENUMCONTAINERS, pbData, &cbData,CRYPT_FIRST); // printf("X\n"); } else { //fRes = OpenProvider(&hProvide, sProvName, CRYPT_VERIFYCONTEXT); //fRes = CryptAcquireContext(&hProvide,"SetCARDKeyContainer",sProvName,dwProvType, CRYPT_SILENT); fRes = CryptAcquireContext(&hProvide,NULL,sProvName,dwProvType, CRYPT_VERIFYCONTEXT); if (fRes == TRUE) { //the extra csp might give wrong answer. We should ask from provider, why. //The following is the work-around -- try to lookup key container from the card. //if the result is negative this is a not the csp what is needed. fRes=CryptGetProvParam(hProvide, PP_ENUMCONTAINERS, pbData, &cbData,CRYPT_FIRST); if (fRes == TRUE) fRes=CryptAcquireContext(&hProvide,(char*)pbData,sProvName,dwProvType, CRYPT_SILENT); } } //printf("fRes: %x\n",GetLastError()); if (fRes == TRUE) { // && dwProvType == 2) // printf("OK %d %s\n",cbData, pbData); //set global values LOG("CSP %s accepted",sProvName); //is it hardware token? cbData=dNAME_ITEM_LEN+1; if (CryptGetProvParam(hProvide, PP_IMPTYPE, pbData, &cbData, 0)) { //printf("implementat: %d\n",pbData[0]); if((pbData[0] & 1)) // hardware token { strncpy(oG_sCSPName, sProvName, sizeof(oG_sCSPName)); //CryptReleaseContext(hProvide, 0); psRes = oG_sCSPName; break; } } } } } //hProvide = 0; CryptReleaseContext(hProvide, 0); dwIndex++; } if (hKey != NULL) RegCloseKey(hKey); return(psRes); } static char *DigiCrypt_GetFirstAllowedCSPName(void) { char *psRes = NULL; HKEY hKey = NULL; LONG lRet=0; DWORD dwIndex = 0; BOOL fRes; char sProvName[dSTRING_ITEM_LEN+1]; char sKeyNameBuf[dSTRING_ITEM_LEN+1]; HCRYPTPROV hProvide = 0; DWORD dwBufLen; FILETIME oTime; //char buff[200]; BYTE pbData[dNAME_ITEM_LEN+1]; DWORD cbData=dNAME_ITEM_LEN+1; DWORD dwProvType; strncpy(sKeyNameBuf, psData_CSP_Path, sizeof(sKeyNameBuf)); lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,sKeyNameBuf,0, KEY_READ, &hKey); while (lRet == ERROR_SUCCESS) { dwBufLen = dSTRING_ITEM_LEN; lRet = RegEnumKeyEx(hKey,dwIndex,sProvName,&dwBufLen,NULL,NULL,0,&oTime); if (lRet == ERROR_SUCCESS) { if (lstrcmp(sProvName,psData_Ignore_CSP_Name) != 0) { dwProvType = DigiCrypt_FindContext_GetCSPType(sProvName); LOG("CSP %s",sProvName); if (lstrcmp(sProvName,psData_Extra_CSP_Name) != 0) fRes = OpenProvider(&hProvide, sProvName, CRYPT_SILENT); else { fRes = OpenProvider(&hProvide, sProvName, CRYPT_VERIFYCONTEXT); //fRes = CryptAcquireContext(&hProvide,"SetCARDKeyContainer",sProvName,dwProvType, CRYPT_SILENT); fRes = CryptAcquireContext(&hProvide,NULL,sProvName,dwProvType, CRYPT_VERIFYCONTEXT); if(fRes) { //the extra csp might give wrong answer. We should ask from provider, why. //The following is the work-around -- try to lookup key container from the card. //if the result is negative this is a not the csp what is needed. fRes=CryptGetProvParam(hProvide, PP_ENUMCONTAINERS, pbData, &cbData,CRYPT_FIRST); } } if (fRes == TRUE) { // && dwProvType == 2) //set global values LOG("CSP %s accepted",sProvName); strncpy(oG_sCSPName, sProvName, sizeof(oG_sCSPName)); CryptReleaseContext(hProvide, 0); psRes = oG_sCSPName; break; } } } //hProvide = 0; CryptReleaseContext(hProvide, 0); dwIndex++; } if (hKey != NULL) RegCloseKey(hKey); return(psRes); } static void DigiCrypt_ReleaseFirstAllowedCSP(void) { //clear global values if (oG_hProvider != 0) CryptReleaseContext(oG_hProvider, 0); oG_hProvider = 0; oG_sCSPName[0] = 0; } static char *DigiCrypt_GetDefaultKeyContainerName(char *psCSPName) { char *psRes = NULL; HCRYPTPROV hProvider; BOOL fRes; DWORD dwFlags = CRYPT_VERIFYCONTEXT; BYTE pbData[dNAME_ITEM_LEN+1]; DWORD cbData = dNAME_ITEM_LEN; DWORD dwError; DWORD dwProvType; ZeroMemory(pbData,cbData); ZeroMemory(oG_sKeyContainerName,1000); dwProvType = DigiCrypt_FindContext_GetCSPType(psCSPName); //LOG("GetDefaultKeyContainerName CSP=%s",psCSPName); if (lstrcmp(psCSPName,psData_Extra_CSP_Name) != 0) fRes = CryptAcquireContext(&hProvider,NULL,psCSPName,dwProvType, CRYPT_SILENT); else fRes = CryptAcquireContext(&hProvider,NULL,psCSPName,dwProvType, CRYPT_VERIFYCONTEXT); if (fRes == FALSE && dwFlags == CRYPT_SILENT) { //by description must be CRYPT_VERIFYCONTEXT fRes = CryptAcquireContext(&hProvider,NULL,psCSPName,dwProvType, CRYPT_VERIFYCONTEXT); } if (fRes == TRUE) { cbData = dNAME_ITEM_LEN; fRes = CryptGetProvParam(hProvider, PP_CONTAINER, pbData, &cbData, 0); /*if (fRes == FALSE) dwError = GetLastError();*/ } //Some cards should not have default key container //let try to find key containers on the card. if (fRes == FALSE) { fRes=CryptGetProvParam(hProvider, PP_ENUMCONTAINERS, pbData, &cbData,CRYPT_FIRST); if (fRes == FALSE) dwError = GetLastError(); } if (fRes == TRUE) { //oG_hProvider = hProvider; strncpy(oG_sKeyContainerName, (char *) pbData, sizeof(oG_sKeyContainerName)); //psRes = oG_sKeyContainerName; DigiCrypt_ChangeContainerName(oG_sKeyContainerName); } else { } if (psRes != NULL) LOG("GetDefaultKeyContainerName CSP=%s",psCSPName); else LOG("GetDefaultKeyContainerName Not found"); if (hProvider != 0) CryptReleaseContext(hProvider, 0); return(oG_sKeyContainerName); } static char *DigiCrypt_GetDefaultKeyContainerNameSimple(char *psCSPName) { char *psRes = NULL; HCRYPTPROV hProvider=0; BOOL fRes; DWORD dwFlags = 0; BYTE pbData[dNAME_ITEM_LEN+1]; DWORD cbData = dNAME_ITEM_LEN; DWORD dwError; fRes = OpenProvider(&hProvider, psCSPName, dwFlags); //fRes = CryptAcquireContext(&hProvider,NULL,psCSPName,PROV_RSA_SIG, dwFlags); if (fRes == TRUE) { fRes = CryptGetProvParam(hProvider, PP_CONTAINER, pbData, &cbData, 0); if (fRes == FALSE) dwError = GetLastError(); } if (fRes == TRUE) { strncpy(oG_sKeyContainerName, pbData, sizeof(oG_sKeyContainerName)); psRes = oG_sKeyContainerName; DigiCrypt_ChangeContainerName(oG_sKeyContainerName); } if (hProvider != 0) CryptReleaseContext(hProvider, 0); return(psRes); } static PCCERT_CONTEXT DigiCrypt_SelectFromAllCerts(void) { PCCERT_CONTEXT pCertContext = NULL; HCERTSTORE hStore; hStore = DigiCrypt_OpenStore(); if (hStore != NULL) { while (TRUE) { pCertContext = CertEnumCertificatesInStore(hStore,pCertContext); if (pCertContext == NULL) break; else { //TEST //Test_ReadCertDataC(pCertContext); //END TEST RunDlg_AddItem(pCertContext,TRUE); } } pCertContext = RunDlg_RunDlg(); } return(pCertContext); } static void DigiCrypt_SelectCertsFromKeyContainer(HCRYPTPROV hProv, char *psContainerName) { PCCERT_CONTEXT pCertContext = NULL; HCERTSTORE hStore; BOOL fRelease = FALSE; char sContainer[dNAME_ITEM_LEN+1]; if (memcmp(psContainerName,"AUT",3) == 0) { LOG("Find1 Ignore AUT cert"); return; } hStore = DigiCrypt_OpenStore(); if (hStore != NULL) { while (TRUE) { pCertContext = CertEnumCertificatesInStore(hStore,pCertContext); if (pCertContext == NULL) break; else { if (DigiCrypt_GetContainerFromCert(pCertContext, sContainer, dNAME_ITEM_LEN) == TRUE) { LOG("Find1 Container %s %s",sContainer,psContainerName); if (lstrcmp(sContainer+3,psContainerName+3) == 0) { LOG("Find1 Container %s accepted",sContainer); RunDlg_AddItem(pCertContext,TRUE); } } } } } else LOG("Find1 Can't open store"); if (fRelease == TRUE) CryptReleaseContext(hProv, 0); } static PCCERT_CONTEXT DigiCrypt_SelectFromAllKeysCerts(HCRYPTPROV hProvider) { PCCERT_CONTEXT pCertContext = NULL; HCRYPTPROV hProv; BYTE pbData[dNAME_ITEM_LEN+1]; DWORD cbData = dNAME_ITEM_LEN; DWORD dwFlag; BOOL fRes; BOOL fRelease = FALSE; CRYPT_KEY_PROV_INFO* poKeyInfo = NULL; char sContainer[dNAME_ITEM_LEN+1]; hProv = hProvider; if (hProv == 0) { fRes = OpenProvider(&hProv, oG_sCSPName, CRYPT_VERIFYCONTEXT); //fRes = CryptAcquireContext(&hProv,NULL,oG_sCSPName,PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (fRes == FALSE) { LOG("Find1 - Can't open provider"); return(pCertContext); } fRelease = TRUE; } dwFlag = CRYPT_FIRST; fRes = TRUE; while (fRes == TRUE) { cbData = dNAME_ITEM_LEN; cbData = 0; fRes = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, NULL, &cbData, dwFlag); if (fRes == TRUE) fRes = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, pbData, &cbData, dwFlag); dwFlag = 0; if (fRes == FALSE) { if (GetLastError() == ERROR_NO_MORE_ITEMS) { LOG("Find1 End"); fRes = TRUE; break; } } else { LOG("Find1 select certs from %s",pbData); DigiCrypt_SelectCertsFromKeyContainer(hProv, pbData); } } pCertContext = RunDlg_RunDlg(); //we have selected the cert, but do we know corresponding key? //let change values of globals when these are different if(DigiCrypt_GetContainerFromCert(pCertContext, sContainer, dNAME_ITEM_LEN) == TRUE) { strncpy(oG_sKeyContainerName, sContainer, sizeof(oG_sKeyContainerName)); } if(fRelease == TRUE) CryptReleaseContext(hProv, 0); return(pCertContext); } static BOOL DigiCrypt_IsValidCert(PCCERT_CONTEXT pCertContext, BOOL fTimeCheck) { BOOL fIsValid = FALSE; BOOL fRes = FALSE; BOOL fKuCheck = TRUE; BYTE bKeyUsageBits = CERT_NON_REPUDIATION_KEY_USAGE; DWORD dwKeyUsageBytes = 1; // VS use auth certs if key_usage_check = 0 fKuCheck = (BOOL)ConfigItem_lookup_int("KEY_USAGE_CHECK", 1); bKeyUsageBits = fKuCheck ? CERT_NON_REPUDIATION_KEY_USAGE : 0; //LOG("KEY_USAGE_CHECK: %d ku: %d", fKuCheck, bKeyUsageBits); //Old version //FILETIME oCurrentTime; if (pCertContext != NULL && pCertContext->pCertInfo != NULL) { //not needed (info from Tarmo Milva) //if (DigiCrypt_CertIsSig(pCertContext) == TRUE) fRes = CertGetIntendedKeyUsage(X509_ASN_ENCODING,pCertContext->pCertInfo,&bKeyUsageBits,dwKeyUsageBytes); //else // fRes = FALSE; if (fRes == TRUE) { //LOG("KU non-repu: %d", (bKeyUsageBits & CERT_NON_REPUDIATION_KEY_USAGE)); if(!fKuCheck || (bKeyUsageBits & CERT_NON_REPUDIATION_KEY_USAGE)) fIsValid = TRUE; if(bKeyUsageBits & CERT_KEY_CERT_SIGN_KEY_USAGE) // don't display CA certs fIsValid = FALSE; } if (fIsValid == TRUE && fTimeCheck == TRUE) { //Old version //GetSystemTimeAsFileTime(&oCurrentTime); //if (CompareFileTime(&oCurrentTime, &pCertContext->pCertInfo->NotBefore) < 0 || // CompareFileTime(&oCurrentTime, &pCertContext->pCertInfo->NotAfter) > 0 ) // fIsValid = FALSE; //New version //NULL, if current datetime if (CertVerifyTimeValidity(NULL,pCertContext->pCertInfo) != 0) fIsValid = FALSE; } } return(fIsValid); } static void DigiCrypt_ChangeContainerName(char *psContainerName) { if (memcmp(psContainerName,"AUT",3) == 0) memmove(psContainerName,"SIG",3); } //dialog functions #define DLGMAXIEMS 512 static char *psListItems[DLGMAXIEMS]; static PCCERT_CONTEXT psListItemsCert[DLGMAXIEMS]; static int iListItems=0; static void RunDlg_Clear(void) { int iI; for (iI=0; iI < DLGMAXIEMS;++iI) { psListItems[iI] = NULL; psListItemsCert[iI] = NULL; } iListItems=0; } static BOOL RunDlg_AddItem(PCCERT_CONTEXT pCertContext, BOOL fTimeCheck) { BOOL fRes = TRUE; BOOL fAddToList = TRUE; char *psData; int iI, len; if (iListItems == (DLGMAXIEMS-1)) return(FALSE); if (iListItems == 0) { for (iI=0; iI < DLGMAXIEMS;++iI) { psListItems[iI] = NULL; psListItemsCert[iI] = NULL; } } if (pCertContext != NULL) { fAddToList = DigiCrypt_IsValidCert(pCertContext,fTimeCheck); if (fAddToList == TRUE) { len = dSTRING_ITEM_LEN*4; psListItems[iListItems] = (char *)LocalAlloc(LMEM_ZEROINIT,(len)); psListItemsCert[iListItems] = CertDuplicateCertificateContext(pCertContext); //Make data buffer for list psData = psListItems[iListItems]; RunDlg_FillItem(pCertContext, psData, len); ++iListItems; } } return(fRes); } static PCCERT_CONTEXT RunDlg_RunDlg(void) { PCCERT_CONTEXT hCert = NULL; int iRes = -1; int iI; oG_fDialogUserCancel = FALSE; if (iListItems > 1) { LOG("StartDialog"); iRes = RunDialogUnit(psListItems, 450,300); if (iRes < 0) oG_fDialogUserCancel = TRUE; LOG("EndDialog"); } else { if (iListItems == 1) iRes = 0; } for (iI=0; iI < iListItems;++iI) { LocalFree(psListItems[iI]); if (iRes != iI) CertFreeCertificateContext(psListItemsCert[iI]); else hCert = psListItemsCert[iI]; } iListItems = 0; return(hCert); } static BOOL RunDlg_FillItem(PCCERT_CONTEXT pCertContext, char *psRes, int len) { char sTemp[dSTRING_ITEM_LEN+1]; SYSTEMTIME oT; PCERT_INFO pCertInfo; BOOL fRes = TRUE; *psRes = 0; if (pCertContext == NULL || pCertContext->pCertInfo == NULL || psRes == NULL) return(FALSE); pCertInfo = pCertContext->pCertInfo; CertGetNameString(pCertContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,CERT_NAME_ISSUER_FLAG,NULL,sTemp,dSTRING_ITEM_LEN); if (lstrlen(sTemp) > 0) { strncat(psRes, sTemp, len - strlen(psRes)); strncat(psRes, " \t", len - strlen(psRes)); } CertGetNameString(pCertContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,0,NULL,sTemp,dSTRING_ITEM_LEN); //CorrectCharacters(sTemp); if (lstrlen(sTemp) > 0) { strncat(psRes, sTemp, len - strlen(psRes)); strncat(psRes, " \t", len - strlen(psRes)); } if (FileTimeToSystemTime(&pCertInfo->NotBefore,&oT) == TRUE) { snprintf(sTemp, sizeof(sTemp), "%02d/%02d/%02d \t",oT.wYear,oT.wMonth,oT.wDay); strncat(psRes, sTemp, len - strlen(psRes)); } else fRes = FALSE; if (FileTimeToSystemTime(&pCertInfo->NotAfter,&oT) == TRUE) { snprintf(sTemp, sizeof(sTemp), "02d/%02d/%02d \t",oT.wYear,oT.wMonth,oT.wDay); strncat(psRes,sTemp, len - strlen(psRes)); } else fRes = FALSE; if (DigiCrypt_GetCSPFromCert(pCertContext, sTemp, dSTRING_ITEM_LEN) == TRUE) strncat(psRes,sTemp, len - strlen(psRes)); return(fRes); } static char sLogLine[4096]; static char sLogFile[256]; static int iLogCheck = -1; static BOOL IsLogEnabled(void) { BOOL fRes = FALSE; DWORD dwRes; char cVal; HANDLE hSearch; WIN32_FIND_DATA oF; if(iLogCheck == -1) { iLogCheck = 0; dwRes = GetModuleFileName(NULL, sLogFile, 255); //strcpy(sLogFile, "z:\\digicrypt.log"); dwRes=1;iLogCheck = 1; //MessageBox(NULL,sLogFile,"LogFile=",MB_OK|MB_SYSTEMMODAL|MB_ICONERROR); while (dwRes > 1) { cVal = sLogFile[dwRes-1]; if (cVal == '.') { strncat(sLogFile, "log", sizeof(sLogFile) - strlen(sLogFile)); hSearch = FindFirstFile(sLogFile,&oF); if (hSearch != INVALID_HANDLE_VALUE) { iLogCheck = 1; FindClose(hSearch); } break; } --dwRes; } } fRes = (BOOL)iLogCheck; return(fRes); } void LOG(char *psMsgFmt, ...) { int iLen; char buff[200]; va_list ArgList; va_start(ArgList, psMsgFmt); iLen = wvsprintf((LPTSTR)sLogLine, (LPTSTR)psMsgFmt, ArgList); snprintf(buff, sizeof(buff), (LPTSTR)psMsgFmt,ArgList); //MessageBox(NULL,(LPTSTR)sLogLine,"Teade",0); va_end(ArgList); if (IsLogEnabled() == TRUE) IntLogToFile(sLogLine,iLen); } static void IntLogToFile(char *psMsg, int iMsgLen) { char sLogFormat1[]="%02d%02d%02d %02d:%02d.%02d "; char sTimeBuf[64]; HANDLE hFile; DWORD dwLen; SYSTEMTIME oTime; if (psMsg == NULL || iMsgLen == 0) return; GetLocalTime(&oTime); wsprintf((LPTSTR)sTimeBuf,(LPTSTR)sLogFormat1, oTime.wYear-2000, oTime.wMonth, oTime.wDay, oTime.wHour, oTime.wMinute, oTime.wSecond); hFile = CreateFile((LPCTSTR)sLogFile, GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { if (psMsg != NULL) { SetFilePointer(hFile,0,NULL,FILE_END); WriteFile(hFile,sTimeBuf, strlen(sTimeBuf), &dwLen, NULL); if (iMsgLen < 0) iMsgLen = strlen(psMsg); if (iMsgLen > 0) WriteFile(hFile,psMsg, iMsgLen, &dwLen, NULL); WriteFile(hFile,"\r\n", 2, &dwLen, NULL); } CloseHandle(hFile); } } libdigidoc-3.10.5/libdigidoc/rc.rct0000664000372000037200000000075013560273131016505 0ustar travistravis $HWB0%| Template $HWB.0%IDOK1VS_VERSION_INFO1IDCANCEL2IDABORT3IDRETRY4IDIGNORE5IDYES6IDNO7IDCLOSE8IDHELP9_APS_NEXT_RESOURCE_VALUE101_APS_NEXT_SYMED_VALUE101_APS_NEXT_CONTROL_VALUE1000_APS_NEXT_COMMAND_VALUE40001H$HWBDHWB0%xHWB.0%libdigidoc-3.10.5/libdigidoc/DigiDocOCSP.c0000664000372000037200000015750313560273131017533 0ustar travistravis//================================================== // FILE: DigiDocOCSP.c // PROJECT: Digi Doc // DESCRIPTION: DigiDoc OCSP handling routines // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 26.04.2006 Veiko Sinivee // Creation //================================================== #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef FRAMEWORK #ifdef __APPLE__ #include #endif static int password_callback(char *buf, int bufsiz, int verify, void *cb_data) { static const char password[] = "pass"; int res = strlen(password); if (res > bufsiz) res = bufsiz; memcpy(buf, password, res); return res; } #endif #if OPENSSL_VERSION_NUMBER < 0x10010000L static int OCSP_resp_get0_id(const OCSP_BASICRESP *bs, const ASN1_OCTET_STRING **pid, const X509_NAME **pname) { *pid = NULL; *pname = NULL; const OCSP_RESPID *rid = bs->tbsResponseData->responderId; if (rid->type == V_OCSP_RESPID_NAME) *pname = rid->value.byName; else if (rid->type == V_OCSP_RESPID_KEY) *pid = rid->value.byKey; else return 0; return 1; } static const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP* bs) { return bs->tbsResponseData->producedAt; } static const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single) { return single->certId; } static const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs) { return bs->signature; } static const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x) { return x->cert_info->extensions; } static const ASN1_TIME *X509_get0_notBefore(const X509 *x) { return x->cert_info->validity->notBefore; } static const ASN1_TIME *X509_get0_notAfter(const X509 *x) { return x->cert_info->validity->notAfter; } #else # define BIO_R_BAD_HOSTNAME_LOOKUP 102 # define OCSP_R_NO_CONTENT 106 # define OCSP_F_OCSP_SENDREQ_BIO 112 # define OCSP_R_SERVER_READ_ERROR 113 # define OCSP_R_SERVER_WRITE_ERROR 116 #endif //================< OCSP functions> ================================= static int ddocOcspProxyAuthInfo(char *authinfo, const char *user, const char *pass) { BIO *b64 = 0, *hash = 0; char *data = 0; RETURN_IF_NULL_PARAM(authinfo); authinfo[0] = 0; if(!user && !pass) return ERR_OK; b64 = BIO_new(BIO_f_base64()); RETURN_IF_NOT(b64, ERR_NULL_POINTER); BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); hash = BIO_push(b64, BIO_new(BIO_s_mem())); RETURN_IF_NOT(hash, ERR_NULL_POINTER); BIO_printf(hash, "%s:%s", user, pass); (void)BIO_flush(hash); BIO_get_mem_data(hash, &data); sprintf(authinfo, "Proxy-Authorization: Basic %s\r\n", data); BIO_free_all(hash); return ERR_OK; } //============================================================ // Decodes binary (DER) OCSP_RESPONSE data and returns a OCSP_RESPONSE object // ppResp - pointer to a buffer to receive newly allocated OCSP_RESPONSE pointer // data - (DER) OCSP_RESPONSE data // len - length of data in bytes //============================================================ EXP_OPTION int ddocDecodeOCSPResponseData(OCSP_RESPONSE **ppResp, const byte* data, int len) { BIO* b1 = 0; // check input params RETURN_IF_NULL_PARAM(data); RETURN_IF_NULL_PARAM(ppResp); // mark as not read yet *ppResp = 0; // create BIO b1 = BIO_new_mem_buf((void*)data, len); RETURN_IF_NOT(b1, ERR_NULL_POINTER); // decode OCSP *ppResp = d2i_OCSP_RESPONSE_bio(b1, NULL); BIO_free(b1); ddocDebug(3, "ddocDecodeOCSPResponseData", "Decoding %d bytes DER data - OCSP_RESPONSE %s", len, (*ppResp ? "OK" : "ERROR")); RETURN_IF_NOT(*ppResp, ERR_OCSP_UNKNOWN_TYPE); return ERR_OK; } //============================================================ // Decodes base64 (PEM) OCSP_RESPONSE data and returns a OCSP_RESPONSE object // ppResp - pointer to a buffer to receive newly allocated OCSP_RESPONSE pointer // data - (PEM) OCSP_RESPONSE data // len - length of data in bytes //============================================================ EXP_OPTION int ddocDecodeOCSPResponsePEMData(OCSP_RESPONSE **ppResp, const byte* data, int len) { byte* p1 = 0; int l1 = 0, err = ERR_OK; // check input params RETURN_IF_NULL_PARAM(data); RETURN_IF_NULL_PARAM(ppResp); // mark as not read yet *ppResp = 0; // allocate memory for decoding l1 = len; // should be enough as it shrinks p1 = (byte*)malloc(l1); RETURN_IF_BAD_ALLOC(p1); memset(p1, 0, l1); // decode base64 data decode((const byte*)data, len, p1, &l1); // decode OCSP err = ddocDecodeOCSPResponseData(ppResp, p1, l1); // cleanup if(p1) free(p1); ddocDebug(3, "ddocDecodeOCSPResponsePEMData", "Decoding %d bytes PEM data - OSCP_RESPONSE %s", len, (*ppResp ? "OK" : "ERROR")); return err; } //============================================================ // Reads in an OCSP Response file in DER format // szFileName - OCSP response file name //============================================================ int ReadOCSPResponse(OCSP_RESPONSE **newOCSP_RESPONSE, const char* szFileName) { BIO *bin = NULL; OCSP_RESPONSE *resp = NULL; int err = ERR_OK; ddocDebug(4, "ReadOCSPResponse", "File: %s", szFileName); RETURN_IF_NULL_PARAM(newOCSP_RESPONSE); RETURN_IF_NULL_PARAM(szFileName); if((bin = BIO_new_file(szFileName, "rb")) != NULL) { ddocDebug(4, "ReadOCSPResponse", "File opened"); resp = d2i_OCSP_RESPONSE_bio(bin, NULL); BIO_free(bin); if (resp == NULL) { err = ERR_OCSP_WRONG_VERSION; } } else { ddocDebug(4, "ReadOCSPResponse", "Cannot read file:%s", szFileName); err =ERR_FILE_READ; } if (err != ERR_OK) SET_LAST_ERROR(err); *newOCSP_RESPONSE = resp; return err; } //============================================================ // Writes an OCSP Response to a file in DER format // szFileName - OCSP response file name // resp - OCSP response object //============================================================ int WriteOCSPResponse(const char* szFileName, const OCSP_RESPONSE* resp) { BIO* bout = 0; RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(resp); if((bout = BIO_new_file(szFileName, "wb")) != NULL) { #if OPENSSL_VERSION_NUMBER > 0x00908000 ASN1_i2d_bio((int (*)(void*, unsigned char**))i2d_OCSP_RESPONSE, bout, (unsigned char*)resp); #else ASN1_i2d_bio((int (*)())i2d_OCSP_RESPONSE, bout, (unsigned char*)resp); #endif //i2d_OCSP_RESPONSE_bio((unsigned char*)bout, resp); BIO_free(bout); } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); return ERR_OK; } //============================================================ // Reads in an OCSP Request file in DER format // szFileName - OCSP Request file name //============================================================ int ReadOCSPRequest(OCSP_REQUEST **newOCSP_REQUEST, const char* szFileName) { BIO *bin = NULL; OCSP_REQUEST *req = NULL; int err = ERR_OK; RETURN_IF_NULL_PARAM(*newOCSP_REQUEST); RETURN_IF_NULL_PARAM(szFileName); if((bin = BIO_new_file(szFileName, "rb")) != NULL) { req = d2i_OCSP_REQUEST_bio(bin, NULL); BIO_free(bin); if (req == NULL) { err = ERR_OCSP_WRONG_VERSION; } } else err =ERR_FILE_READ; if (err != ERR_OK) SET_LAST_ERROR(err); *newOCSP_REQUEST = req; return err; } //============================================================ // Writes an OCSP Request to a file in DER format // szFileName - OCSP Request file name // resp - OCSP Request object //============================================================ int WriteOCSPRequest(const char* szFileName, const OCSP_REQUEST* req) { BIO* bout = 0; if((bout = BIO_new_file(szFileName, "wb")) != NULL) { #if OPENSSL_VERSION_NUMBER > 0x00908000 ASN1_i2d_bio((int (*)(void*, unsigned char**))i2d_OCSP_RESPONSE, bout, (unsigned char*)req); #else ASN1_i2d_bio((int (*)())i2d_OCSP_RESPONSE, bout, (unsigned char*)req); #endif //i2d_OCSP_REQUEST_bio(bout, req); BIO_free(bout); } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); return ERR_OK; } //============================================================ // Checks OCSP certificate status and handles errors // status - status code // return error code //============================================================ int handleOCSPCertStatus(int status) { int err = ERR_OK; switch(status) { case V_OCSP_CERTSTATUS_GOOD: // cert is ok, do nothing break; case V_OCSP_CERTSTATUS_REVOKED: // cert has been revoked err = ERR_OCSP_CERT_REVOKED; break; case V_OCSP_CERTSTATUS_UNKNOWN: // cert status unknown err = ERR_OCSP_CERT_UNKNOWN; break; default: // should never happen? err = ERR_OCSP_RESP_STATUS; } return err; } //============================================================ // Calculates NotaryInfo digest if possible // pSigDoc - digidoc main object pointer // pNotary - NotaryInfo object to be initialized // return error code //============================================================ int calcNotaryDigest(SignedDoc* pSigDoc, NotaryInfo* pNotary) { int err = ERR_OK, l1; //AM 24.04.08 increased buffer size for sha256 char buf1[DIGEST_LEN256+2]; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pSigDoc); l1 = sizeof(buf1); err = calculateNotaryInfoDigest(pSigDoc, pNotary, (byte*)buf1, &l1); //err = calculateOcspBasicResponseDigest(br, buf1, &l1); if(!err) { err = ddocNotInfo_SetOcspDigest(pNotary, buf1, l1); } return err; } //============================================================ // Initializes NotaryInfo object with data from OCSP object // pSigDoc - digidoc main object pointer // pNotary - NotaryInfo object to be initialized // resp - OCSP response object // notCert - Notary cert object // return error code //============================================================ int initializeNotaryInfoWithOCSP(SignedDoc *pSigDoc, NotaryInfo *pNotary, OCSP_RESPONSE *resp, X509 *notCert, int initDigest) { int n, err = ERR_OK, status = 0; char buf[500]; OCSP_RESPBYTES *rb = NULL; OCSP_BASICRESP *br = NULL; OCSP_SINGLERESP *single = NULL; const OCSP_CERTID *cid = NULL; X509_EXTENSION *nonce; const ASN1_GENERALIZEDTIME *producedAt = NULL; //AM 26.09.08 DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; const ASN1_OCTET_STRING *id = NULL; const X509_NAME *name = NULL; ASN1_OBJECT *hashAlgorithm = NULL; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(resp); ddocDebug(3, "initializeNotaryInfoWithOCSP", "OCSP status: %d", OCSP_response_status(resp)); // save the response in memory err = ddocNotInfo_SetOCSPResponse_Value(pNotary, resp); // check the OCSP Response validity switch(OCSP_response_status(resp)) { case OCSP_RESPONSE_STATUS_SUCCESSFUL: // OK break; case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_MALFORMED); case OCSP_RESPONSE_STATUS_INTERNALERROR: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_INTERNALERR); case OCSP_RESPONSE_STATUS_TRYLATER: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_TRYLATER); case OCSP_RESPONSE_STATUS_SIGREQUIRED: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_SIGREQUIRED); case OCSP_RESPONSE_STATUS_UNAUTHORIZED: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_UNAUTHORIZED); default: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_UNSUCCESSFUL); } if((br = OCSP_response_get1_basic(resp)) == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_BASIC_RESP); ddocDebug(4, "initializeNotaryInfoWithOCSP", "test2"); n = OCSP_resp_count(br); if(n != 1) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_ONE_RESPONSE); single = OCSP_resp_get0(br, 0); RETURN_IF_NULL(single); cid = OCSP_SINGLERESP_get0_id(single); RETURN_IF_NULL(cid); status = OCSP_single_get0_status(single, NULL, NULL, NULL, NULL); ddocDebug(4, "initializeNotaryInfoWithOCSP", "CertStatus-type: %d", status); //printf("TYPE: %d\n", single->certStatus->type); if(status != 0) { ddocDebug(4, "initializeNotaryInfoWithOCSP", "errcode: %d", handleOCSPCertStatus(status)); SET_LAST_ERROR_RETURN_CODE(handleOCSPCertStatus(status)); } //Removed 31.10.2003 //if(single->singleExtensions) // SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_SINGLE_EXT); if((OCSP_BASICRESP_get_ext_count(br) != 1) || ((nonce = OCSP_BASICRESP_get_ext(br, 0)) == NULL)) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_NONCE); i2t_ASN1_OBJECT(buf,sizeof(buf), X509_EXTENSION_get_object(nonce)); if(strcmp(buf, OCSP_NONCE_NAME)) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_NONCE); OCSP_resp_get0_id(br, &id, &name); if(name) { pNotary->nRespIdType = RESPID_NAME_TYPE; } else if(id) { pNotary->nRespIdType = RESPID_KEY_TYPE; } else { SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_WRONG_RESPID); } // producedAt producedAt = OCSP_resp_get0_produced_at(br); err = asn1time2str(pSigDoc, (ASN1_GENERALIZEDTIME*)producedAt, buf, sizeof(buf)); setString(&(pNotary->timeProduced), buf, -1); n = sizeof(buf); if(name){ //X509_NAME_oneline(rid->value.byName,buf,n); err = ddocCertGetDNFromName((X509_NAME*)name, &mbuf1); err = ddocNotInfo_SetResponderId(pNotary, (char*)mbuf1.pMem, -1); ddocMemBuf_free(&mbuf1); } if(id) { err = ddocNotInfo_SetResponderId(pNotary, (const char*)id->data, id->length); } OCSP_id_get0_info(NULL, &hashAlgorithm, NULL, NULL, (OCSP_CERTID*)cid); // digest type i2t_ASN1_OBJECT(buf,sizeof(buf),hashAlgorithm); //AM 24.11.09 why its needed? added if. 08.12.09 used for gen if(!pNotary->szDigestType){ setString(&(pNotary->szDigestType), buf, -1); } #if OPENSSL_VERSION_NUMBER < 0x10010000L // signature algorithm i2t_ASN1_OBJECT(buf,sizeof(buf),br->signatureAlgorithm->algorithm); setString(&(pNotary->szSigType), buf, -1); #endif // notary cert if(notCert && !err) err = addNotaryInfoCert(pSigDoc, pNotary, notCert); // get the digest from original OCSP data if(initDigest && notCert) { err = calcNotaryDigest(pSigDoc, pNotary); } if(br != NULL) OCSP_BASICRESP_free(br); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } int initializeNotaryInfoWithOCSP2(SignedDoc *pSigDoc, NotaryInfo *pNotary, OCSP_RESPONSE *resp, X509 *notCert, int initDigest) { int n, err = ERR_OK, status = 0; char buf[500]; OCSP_RESPBYTES *rb = NULL; OCSP_BASICRESP *br = NULL; // OCSP_CERTSTATUS *cst = NULL; OCSP_SINGLERESP *single = NULL; const OCSP_CERTID *cid = NULL; X509_EXTENSION *nonce; const ASN1_GENERALIZEDTIME *producedAt = NULL; //AM 26.09.08 DigiDocMemBuf mbuf1; mbuf1.pMem = 0; mbuf1.nLen = 0; const ASN1_OCTET_STRING *id = NULL; const X509_NAME *name = NULL; ASN1_OBJECT *hashAlgorithm = NULL; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(resp); // check the OCSP Response validity switch(OCSP_response_status(resp)) { case OCSP_RESPONSE_STATUS_SUCCESSFUL: // OK break; case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_MALFORMED); case OCSP_RESPONSE_STATUS_INTERNALERROR: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_INTERNALERR); case OCSP_RESPONSE_STATUS_TRYLATER: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_TRYLATER); case OCSP_RESPONSE_STATUS_SIGREQUIRED: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_SIGREQUIRED); case OCSP_RESPONSE_STATUS_UNAUTHORIZED: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_UNAUTHORIZED); default: SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_UNSUCCESSFUL); } if((br = OCSP_response_get1_basic(resp)) == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_BASIC_RESP); n = OCSP_resp_count(br); if(n != 1) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_ONE_RESPONSE); single = OCSP_resp_get0(br, 0); RETURN_IF_NULL(single); cid = OCSP_SINGLERESP_get0_id(single); RETURN_IF_NULL(cid); status = OCSP_single_get0_status(single, NULL, NULL, NULL, NULL); ddocDebug(4, "initializeNotaryInfoWithOCSP", "CertStatus-type: %d", status); //printf("TYPE: %d\n", single->certStatus->type); //Am test /*if(single->certStatus->type != 0) { ddocDebug(4, "initializeNotaryInfoWithOCSP", "errcode: %d", handleOCSPCertStatus(single->certStatus->type)); SET_LAST_ERROR_RETURN_CODE(handleOCSPCertStatus(single->certStatus->type)); }*/ //Removed 31.10.2003 //if(single->singleExtensions) // SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_SINGLE_EXT); if((OCSP_BASICRESP_get_ext_count(br) != 1) || ((nonce = OCSP_BASICRESP_get_ext(br, 0)) == NULL)) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_NONCE); i2t_ASN1_OBJECT(buf,sizeof(buf),X509_EXTENSION_get_object(nonce)); if(strcmp(buf, OCSP_NONCE_NAME)) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_NONCE); OCSP_resp_get0_id(br, &id, &name); if(name) { pNotary->nRespIdType = RESPID_NAME_TYPE; } else if(id) { pNotary->nRespIdType = RESPID_KEY_TYPE; } else { SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_WRONG_RESPID); } // producedAt producedAt = OCSP_resp_get0_produced_at(br); err = asn1time2str(pSigDoc, (ASN1_GENERALIZEDTIME*)producedAt, buf, sizeof(buf)); setString(&(pNotary->timeProduced), buf, -1); n = sizeof(buf); if(name){ err = ddocCertGetDNFromName((X509_NAME*)name, &mbuf1); RETURN_IF_NOT(err == ERR_OK, err); err = ddocNotInfo_SetResponderId(pNotary, (char*)mbuf1.pMem, -1); ddocMemBuf_free(&mbuf1); } if(id) { err = ddocNotInfo_SetResponderId(pNotary, (const char*)id->data, id->length); } OCSP_id_get0_info(NULL, &hashAlgorithm, NULL, NULL, (OCSP_CERTID*)cid); // digest type i2t_ASN1_OBJECT(buf,sizeof(buf),hashAlgorithm); setString(&(pNotary->szDigestType), buf, -1); #if OPENSSL_VERSION_NUMBER < 0x10010000L // signature algorithm i2t_ASN1_OBJECT(buf,sizeof(buf),br->signatureAlgorithm->algorithm); setString(&(pNotary->szSigType), buf, -1); #endif // notary cert if(notCert && !err) err = addNotaryInfoCert(pSigDoc, pNotary, notCert); // save the response in memory err = ddocNotInfo_SetOCSPResponse_Value(pNotary, resp); // get the digest from original OCSP data if(initDigest && notCert) { err = calcNotaryDigest(pSigDoc, pNotary); } if(br != NULL) OCSP_BASICRESP_free(br); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Helper function to read OCSP_RESPONSE from binary input data // ppResp - address of newly allocated OCSP_RESPONSE object // pMBufInData - input data // returns error code or ERR_OK //-------------------------------------------------- int ddocOcspReadOcspResp(OCSP_RESPONSE** ppResp, DigiDocMemBuf* pMBufInData) { int err = ERR_OK; unsigned char* p1; RETURN_IF_NULL_PARAM(ppResp); RETURN_IF_NULL_PARAM(pMBufInData); RETURN_IF_NULL_PARAM(pMBufInData->pMem); *ppResp = 0; ddocDebug(4, "ddocOcspReadOcspResp", "converting: %d bytes to OCSP_RESPONSE", pMBufInData->nLen); p1 = (unsigned char*)pMBufInData->pMem; d2i_OCSP_RESPONSE(ppResp, (const unsigned char**)&p1, pMBufInData->nLen); ddocDebug(4, "ddocOcspReadOcspResp", "OCSP_RESPONSE: %s", (*ppResp ? "OK" : "ERR")); if(!(*ppResp)) err = ERR_OCSP_UNSUCCESSFUL; return err; } //-------------------------------------------------- // Helper function to write OCSP_RESPONSE to binary output data // pResp - address of OCSP_RESPONSE object // pMBufOutData - output data // returns error code or ERR_OK //-------------------------------------------------- int ddocOcspWriteOcspResp(OCSP_RESPONSE* pResp, DigiDocMemBuf* pMBufOutData) { int err = ERR_OK, l1; unsigned char* p1; RETURN_IF_NULL_PARAM(pResp); RETURN_IF_NULL_PARAM(pMBufOutData); pMBufOutData->pMem = NULL; pMBufOutData->nLen = 0; // find out how big a buffer we need l1 = i2d_OCSP_RESPONSE(pResp, NULL); ddocDebug(4, "ddocOcspReadOcspResp", "converting: %d bytes from OCSP_RESPONSE", l1); // alloc mem err = ddocMemSetLength(pMBufOutData, l1 + 50); p1 = (unsigned char*)pMBufOutData->pMem; l1 = i2d_OCSP_RESPONSE(pResp, &p1); pMBufOutData->nLen = l1; ddocDebug(4, "ddocOcspReadOcspResp", "Converted data: %d", l1); return err; } //============================================================ // Converts OCSP_RESPONSE to PEM form with or without the headers // pResp - OCSP_RESPONSE // bHeaders - 1= with headers, 0=no headers // buf - output buffer newly allocated // returns error code //============================================================ EXP_OPTION int getOcspPEM(OCSP_RESPONSE* pResp, int bHeaders, char** buf) { int l1, l2; char *p1, *p2; RETURN_IF_NULL_PARAM(buf); RETURN_IF_NULL_PARAM(pResp); l1 = i2d_OCSP_RESPONSE(pResp, NULL); p1 = (char*)malloc(l1+10); RETURN_IF_BAD_ALLOC(p1); p2 = p1; i2d_OCSP_RESPONSE(pResp, (unsigned char**)&p2); l2 = l1 * 2 + 200; *buf = (char*)malloc(l2); if(*buf == NULL) { free(p1); RETURN_IF_BAD_ALLOC(*buf); } memset(*buf, 0, l2); if(bHeaders) strncpy(*buf, "-----BEGIN OCSP RESPONSE-----\n", l2); encode((const byte*)p1, l1, (byte*)strchr(*buf, 0), &l2); if(bHeaders) strncat(*buf, "\n-----END OCSP RESPONSE-----", l2 - strlen(*buf)); free(p1); return ERR_OK; } //============================================================ // Converts OCSP_REQUEST to DER form // pResp - OCSP_REQUEST // pMBuf - output buffer for OCSP req // returns error code //============================================================ EXP_OPTION int ddocWriteOcspDER(OCSP_REQUEST* pReq, DigiDocMemBuf* pMBuf) { int l1; char *p1, *p2; RETURN_IF_NULL_PARAM(pMBuf); RETURN_IF_NULL_PARAM(pReq); l1 = i2d_OCSP_REQUEST(pReq, NULL); p1 = (char*)malloc(l1+10); RETURN_IF_BAD_ALLOC(p1); p2 = p1; i2d_OCSP_REQUEST(pReq, (unsigned char**)&p2); ddocMemAppendData(pMBuf, p1, l1); free(p1); return ERR_OK; } //-------------------------------------------------- // Helper function to return OCSP_RESPONSE in base64 form // Memory buffer will be resized as necessary. // Caller must release output buffer. // pNotary - Notary object // bHeaders - 1= with headers, 0=no headers // pMBufOutData - output data // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocGetOcspBase64(NotaryInfo *pNotary, int bHeaders, DigiDocMemBuf* pMBufOutData) { const DigiDocMemBuf *pMBuf = 0; DigiDocMemBuf mbuf1; RETURN_IF_NULL_PARAM(pNotary); RETURN_IF_NULL_PARAM(pMBufOutData); pMBufOutData->pMem = 0; pMBufOutData->nLen = 0; mbuf1.pMem = 0; mbuf1.nLen = 0; pMBuf = ddocNotInfo_GetOCSPResponse(pNotary); RETURN_IF_NULL(pMBuf); if(bHeaders) { ddocMemAppendData(pMBufOutData, "-----BEGIN OCSP RESPONSE-----\n", -1); ddocEncodeBase64(pMBuf, &mbuf1); ddocMemAppendData(pMBufOutData, (const char*)mbuf1.pMem, mbuf1.nLen); ddocMemAppendData(pMBufOutData, "\n-----END OCSP RESPONSE-----", -1); ddocMemBuf_free(&mbuf1); } else ddocEncodeBase64(pMBuf, pMBufOutData); return ERR_OK; } //-------------------------------------------------- // teeb 00:0a:df stiilis hexprinditud stringist tagasi tavalise //-------------------------------------------------- // Tanel - ver 1.66 unsigned char *decodeHex(unsigned char *str) { unsigned int i, j, k, len; unsigned char *ret; static unsigned char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; len = (int)(strlen((const char*)str) / 3) + 2; if((ret=(unsigned char*)malloc(len)) == NULL) return NULL; memset(ret, 0, len); for(i=0, j=0; idata; #if OPENSSL_VERSION_NUMBER > 0x00908000 // crashes here! st = ASN1_item_d2i(NULL, (const unsigned char**)&p, data->length, ASN1_ITEM_ptr(met->it)); #else st = ASN1_item_d2i(NULL, &p, ex->value->length, ASN1_ITEM_ptr(met->it)); #endif vals = met->i2v(met, st, NULL); /* P.R */ ASN1_item_free((ASN1_VALUE *)st, ASN1_ITEM_ptr(met->it)); /* P.R */ for(i=0; iname, val->value); if(val->name && (strcmp(val->name, "keyid") == 0)) ret = decodeHex((unsigned char*)val->value); } /* P.R */ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); /* P.R */ return ret; } //-------------------------------------------------- // otsib X.509 seest Authority Key Identifieri välja //-------------------------------------------------- unsigned char *get_authority_key_from_cert(X509 *x) { unsigned char *ret = 0; AUTHORITY_KEYID *val = (AUTHORITY_KEYID*)X509_get_ext_d2i( x, NID_authority_key_identifier, NULL, NULL ); if(!val) { ddocDebug(4, "get_authority_key_from_cert", "Extension not found"); return(NULL); } //ret = ASN1_STRING_data(val->keyid); // workaround encode/decode bugs ret = decodeHex((unsigned char*)hex_to_string(ASN1_STRING_data(val->keyid), ASN1_STRING_length(val->keyid))); AUTHORITY_KEYID_free(val); return ret; } //-------------------------------------------------- // creates OCSP_CERTID without using the issuer cert // cert - certificate for which we need certid // returns OCSP_CERTID pointer //-------------------------------------------------- // Tanel - ver 1.66 OCSP_CERTID* createOCSPCertid(X509 *cert, X509* pCACert) { OCSP_CERTID *pId = NULL; X509_NAME *iname; ASN1_INTEGER *sno; DigiDocMemBuf mbuf1, mbuf2; AUTHORITY_KEYID *val = NULL; mbuf1.pMem = mbuf2.pMem = NULL; mbuf1.nLen = mbuf2.nLen = 0; if(cert != NULL) { ddocCertGetSubjectDN(cert, &mbuf1); // standard variant would be //pId = OCSP_cert_to_id(EVP_sha1(), cert, issuer); if(pCACert) { ddocCertGetSubjectDN(pCACert, &mbuf2); ddocDebug(3, "createOCSPCertid", "Create ocsp id for cert: %s by CA: %s", (char*)mbuf1.pMem, (char*)mbuf2.pMem); pId = OCSP_cert_to_id(EVP_sha1(), cert, pCACert); } else { // CA unknown ddocDebug(3, "createOCSPCertid", "Create ocsp id for cert: %s unknown CA", (char*)mbuf1.pMem); // issuer name hashi arvutamine val = (AUTHORITY_KEYID*)X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL ); if(!val) { ddocDebug(4, "get_authority_key_from_cert", "Extension not found"); return(NULL); } sno = X509_get_serialNumber(cert); iname = X509_get_issuer_name(cert); pId = OCSP_cert_id_new(EVP_sha1(), iname, val->keyid, sno); } } ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocDebug(3, "createOCSPCertid", "Created ocsp id %s issuer-key-hash", (pId ? "OK" : "ERR")); return pId; } //-------------------------------------------------- // Creates an OCSP_REQUEST object // pSigDoc - address of signed document. If not NULL then // used to check if older openssl 0.9.6 style request must // be constructed. // req - buffer for storing the pointer of new object // cert - client certificate to verify // nonce - nonce value (e.g. client signature value RSA-128 bytes) // nlen - nonce value length // pkey - public key used to signe th request (not used yet) //-------------------------------------------------- // VS - ver 1.66 int createOCSPRequest(SignedDoc* pSigDoc, OCSP_REQUEST **req, X509 *cert, X509* pCACert, byte* nonce, int nlen) { int err = ERR_OK, l2; OCSP_CERTID *id = 0; byte buf2[DIGEST_LEN256 * 2 + 2]; RETURN_IF_NULL_PARAM(req); RETURN_IF_NULL_PARAM(cert); RETURN_IF_NULL_PARAM(nonce); //RETURN_IF_NULL_PARAM(pCACert); if((*req = OCSP_REQUEST_new()) != 0) { if((id = createOCSPCertid(cert, pCACert)) != 0) { if(OCSP_request_add0_id(*req, id)) { if((err = OCSP_request_add1_nonce(*req, nonce, nlen)) != 0) err = ERR_OK; // debug l2 = sizeof(buf2); memset(buf2, 0, l2); if(nlen <= DIGEST_LEN256) { bin2hex((const char*)nonce, nlen, (byte*)buf2, &l2); ddocDebug(3, "createOCSPRequest", "Sending nonce: %s len: %d err: %d", buf2, nlen, err); } } } } return err; } /* Quick and dirty HTTP OCSP request handler. * Could make this a bit cleverer by adding * support for non blocking BIOs and a few * other refinements. * Qick and dirty adaption of openssl -s * OCSP_sendreq_bio() to add UserAgent HTTP header */ OCSP_RESPONSE *OCSP_sendreq_bio_withParams(BIO *b, char *path, OCSP_REQUEST *req, unsigned long ip_addr ) { BIO *mem = NULL; char tmpbuf[1024], adrhdr[100]; OCSP_RESPONSE *resp = NULL; char *p, *q, *r; int len, retcode; static char req_txt[] = "POST %s HTTP/1.0\r\n\ Content-Type: application/ocsp-request\r\n\ User-Agent: LIB %s/%s APP %s\r\n%s\ Content-Length: %d\r\n\r\n"; adrhdr[0] = 0; if(ip_addr > 0) snprintf(adrhdr, sizeof(adrhdr), "From: %d.%d.%d.%d\r\n", (int)(ip_addr>>24)&0xFF, (int)(ip_addr>>16)&0xFF, (int)(ip_addr>>8)&0xFF, (int)(ip_addr&0xFF)); len = i2d_OCSP_REQUEST(req, NULL); if(BIO_printf(b, req_txt, path, getLibName(), getLibVersion(), getGUIVersion(), (ip_addr > 0 ? adrhdr : ""), len) < 0) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_WRITE_ERROR); goto err; } #if OPENSSL_VERSION_NUMBER > 0x00908000 retcode = ASN1_i2d_bio((int (*)(void*, unsigned char**))i2d_OCSP_REQUEST, b, (unsigned char*)req); #else retcode = ASN1_i2d_bio((int (*)())i2d_OCSP_REQUEST, b, (unsigned char*)req); #endif if(retcode <= 0) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_WRITE_ERROR); goto err; } mem = BIO_new(BIO_s_mem()); if(!mem) goto err; /* Copy response to a memory BIO: socket bios can't do gets! */ do { len = BIO_read(b, tmpbuf, sizeof tmpbuf); if(len < 0) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_READ_ERROR); goto err; } BIO_write(mem, tmpbuf, len); } while(len > 0); if(BIO_gets(mem, tmpbuf, 512) <= 0) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); goto err; } /* Parse the HTTP response. This will look like this: * "HTTP/1.0 200 OK". We need to obtain the numeric code and * (optional) informational message. */ /* Skip to first white space (passed protocol info) */ for(p = tmpbuf; *p && !isspace((unsigned char)*p); p++) continue; if(!*p) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); goto err; } /* Skip past white space to start of response code */ while(*p && isspace((unsigned char)*p)) p++; if(!*p) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); goto err; } /* Find end of response code: first whitespace after start of code */ for(q = p; *q && !isspace((unsigned char)*q); q++) continue; if(!*q) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); goto err; } /* Set end of response code and start of message */ *q++ = 0; /* Attempt to parse numeric code */ retcode = strtoul(p, &r, 10); if(*r) goto err; /* Skip over any leading white space in message */ while(*q && isspace((unsigned char)*q)) q++; if(*q) { /* Finally zap any trailing white space in message (include CRLF) */ /* We know q has a non white space character so this is OK */ for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) *r = 0; } if(retcode != 200) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_ERROR); if(!*q) { ERR_add_error_data(2, "Code=", p); } else { ERR_add_error_data(4, "Code=", p, ",Reason=", q); } goto err; } /* Find blank line marking beginning of content */ while(BIO_gets(mem, tmpbuf, 512) > 0) { for(p = tmpbuf; *p && isspace((unsigned char)*p); p++) continue; if(!*p) break; } if(*p) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_NO_CONTENT); goto err; } resp = d2i_OCSP_RESPONSE_bio(mem, NULL); if(!resp) { OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,ERR_R_NESTED_ASN1_ERROR); goto err; } err: BIO_free(mem); return resp; } //-------------------------------------------------- // sends an OCSP_REQUES object to remore server and // retrieves the OCSP_RESPONSE object // resp - buffer to store the new responses pointer // req - request objects pointer // url - OCSP responder URL // ip_addr - senders ip address if known or 0 //-------------------------------------------------- int sendOCSPRequest(OCSP_RESPONSE** resp, OCSP_REQUEST *req, char* url, char* proxyHost, char* proxyPort, unsigned long ip_addr) { BIO* cbio = 0, *sbio = 0; SSL_CTX *ctx = NULL; char *host = NULL, *port = NULL, *path = "/"; int err = ERR_OK, use_ssl = -1; int connResult = 0; long e = 0; RETURN_IF_NULL_PARAM(resp); RETURN_IF_NULL_PARAM(req); RETURN_IF_NULL_PARAM(url); //there is an HTTP proxy - connect to that instead of the target host ddocDebug(3, "sendOCSPRequest", "Send OCSP to: %s over: %s:%s", url, (proxyHost ? proxyHost : ""), (proxyPort ? proxyPort : "")); if (proxyHost != 0 && *proxyHost != '\0') { host = proxyHost; if(proxyPort != 0 && *proxyPort != '\0') port = proxyPort; path = url; } else { if((err = OCSP_parse_url(url, &host, &port, &path, &use_ssl)) == 0) { //printf("BIO_parse_url failed\n"); ddocDebug(1, "sendOCSPRequest", "BIO_parse_url failed: %d - %s", err, url); return ERR_WRONG_URL_OR_PROXY; } } if((cbio = BIO_new_connect(host)) != 0) { if(port != NULL) BIO_set_conn_port(cbio, port); if (use_ssl == 1) { ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); sbio = BIO_new_ssl(ctx, 1); cbio = BIO_push(sbio, cbio); } if ((connResult = BIO_do_connect(cbio)) > 0) { e = checkErrors(); //printf("BIO_do_connect returned %d\n", connResult); *resp = OCSP_sendreq_bio_withParams(cbio, path, req, ip_addr); //printf("OCSP_sendreq_bio answered %lX\n", *resp); e = checkErrors(); if(ERR_GET_REASON(e) == BIO_R_BAD_HOSTNAME_LOOKUP || ERR_GET_REASON(e) == OCSP_R_SERVER_WRITE_ERROR) err = ERR_CONNECTION_FAILURE; //if(ERR_GET_REASON(e) == BIO_R_BAD_HOSTNAME_LOOKUP) // err = ERR_CONNECTION_FAILURE; else err = (*resp == 0) ? ERR_OCSP_WRONG_URL : ERR_OK; //if (*resp == 0) // printErrors(); } else { ddocDebug(1, "sendOCSPRequest", "BIO-Connection error: %d - %ld", err, e); //printf("BIO_do_connect failed, rc = %d, shouldRetry = %d\n", connResult, BIO_should_retry(cbio)); //printErrors(); //if no connection if (host != NULL) err = ERR_WRONG_URL_OR_PROXY; else err = ERR_CONNECTION_FAILURE; } BIO_free_all(cbio); if (use_ssl != -1) { OPENSSL_free(host); OPENSSL_free(port); OPENSSL_free(path); SSL_CTX_free(ctx); } } else { err = ERR_CONNECTION_FAILURE; ddocDebug(1, "sendOCSPRequest", "Connection error: %d", err); } return(err); } //-------------------------------------------------- // sends an OCSP_REQUES object to remore server and // retrieves the OCSP_RESPONSE object // resp - buffer to store the new responses pointer // req - request objects pointer // url - OCSP responder URL // ip_addr - senders ip address if known or 0 //-------------------------------------------------- int sendOCSPRequest2(OCSP_RESPONSE** resp, OCSP_REQUEST *req, char* url, char* proxyHost, char* proxyPort, char *proxyUser, char *proxyPass, unsigned long ip_addr) { int err = ERR_OK, l1 = 0; DigiDocMemBuf mbuf1, mbuf2, mbuf3; char buf1[30], buf2[200], buf3[100], *p1; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; mbuf3.pMem = 0; mbuf3.nLen = 0; ddocMemAssignData(&mbuf1, "POST ", -1); if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) { ddocMemAppendData(&mbuf1, url, -1); } else { p1 = strstr(url, "://"); if(p1) p1 += 3; if(p1) p1 = strchr(p1, '/'); if(p1) ddocMemAppendData(&mbuf1, p1, -1); else ddocMemAppendData(&mbuf1, "/", -1); } ddocMemAppendData(&mbuf1, " HTTP/1.0\r\n", -1); buf1[0] = buf2[0] = 0; if(ip_addr > 0) snprintf(buf1, sizeof(buf1), "From: %d.%d.%d.%d\r\n", (int)(ip_addr>>24)&0xFF, (int)(ip_addr>>16)&0xFF, (int)(ip_addr>>8)&0xFF, (int)ip_addr&0xFF); snprintf(buf2, sizeof(buf2), "User-Agent: LIB %s/%s APP %s\r\n%s", getLibName(), getLibVersion(), getGUIVersion(), (ip_addr > 0 ? buf1 : "")); ddocMemAppendData(&mbuf1, "Content-Type: application/ocsp-request\r\n", -1); ddocMemAppendData(&mbuf1, buf2, -1); //ddocMemAppendData(&mbuf1, "Host: www.sk.ee\r\n", -1); //ddocMemAppendData(&mbuf1, "Accept: */*\r\n", -1); // convert OCSP req err = ddocWriteOcspDER(req, &mbuf3); if(!err) { snprintf(buf1, sizeof(buf1), "Content-Length: %d\r\n", (int)mbuf3.nLen); ddocMemAppendData(&mbuf1, buf1, -1); ddocMemAppendData(&mbuf1, "Connection: Close\r\n", -1); if(proxyUser || proxyPass) { err = ddocOcspProxyAuthInfo(buf3, proxyUser, proxyPass); ddocMemAppendData(&mbuf1, buf3, -1); } if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) // if we use proxy then send also Proxy-Connection ddocMemAppendData(&mbuf1, "Proxy-Connection: Close\r\n", -1); ddocMemAppendData(&mbuf1, "\r\n", -1); ddocMemAppendData(&mbuf1, mbuf3.pMem, mbuf3.nLen); ddocMemBuf_free(&mbuf3); ddocDebug(3, "sendOCSPRequest2", "Send to host: %s request len: %d", url, mbuf1.nLen); err = ddocPullUrl(url, &mbuf1, &mbuf2, proxyHost, proxyPort); ddocDebug(3, "sendOCSPRequest2", "Recevied len: %d RC: %d", mbuf2.nLen, err); if(!err && ((l1 = ddocGetHttpResponseCode(&mbuf2)) == 200)) { ddocDebug(4, "sendOCSPRequest2", "HTTP response\n-----\n%s\n-----\n", mbuf2.pMem); err = ddocGetHttpPayload(&mbuf2, &mbuf3); if(!err) err = ddocOcspReadOcspResp(resp, &mbuf3); } else { ddocDebug(1, "sendOCSPRequest2", "Ocsp request failed with http code: %d rc: %d", l1, err); err = ERR_OCSP_UNSUCCESSFUL; ddocDebug(1, "sendOCSPRequest2", "HTTP error message\n-----\n%s\n-----\n", mbuf2.pMem); } } // cleanup ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); return err; } //-------------------------------------------------- // Creates and writes an OCSP_REQUEST object // to disk // pSigDoc - signedDoc address // signerCertFile - cert file to verify // issuertCertFile - this certs direct CA cert // nonce - nonce (signature value) // nlen - nonce length // szOutputFile - output filename //-------------------------------------------------- EXP_OPTION int writeOCSPRequest(SignedDoc* pSigDoc, const char* signerCertFile, const char* issuertCertFile, byte* nonce, int nlen, const char* szOutputFile) { OCSP_REQUEST *req = 0; X509 *cert = 0, *issuer = 0; int err = ERR_OK, l1; //EVP_PKEY* pkey; byte buf1[DIGEST_LEN+2]; RETURN_IF_NULL_PARAM(signerCertFile); RETURN_IF_NULL_PARAM(issuertCertFile); RETURN_IF_NULL_PARAM(nonce); RETURN_IF_NULL_PARAM(szOutputFile); if((err = ReadCertificate(&cert, signerCertFile)) == ERR_OK) { //pkey = ReadPublicKey(signerCertFile); if((err = ReadCertificate(&issuer, issuertCertFile)) == ERR_OK) { l1 = sizeof(buf1); calculateDigest(nonce, nlen, DIGEST_SHA1, buf1, &l1); err = createOCSPRequest(pSigDoc, &req, cert, issuer, buf1, l1); //WriteOCSPRequest(szOutputFile, req); X509_free(issuer); //AM 22.04.08 if(req) OCSP_REQUEST_free(req); } X509_free(cert); } return err; } //-------------------------------------------------- // Signs an OCSP_REQUEST using PKCS#12 conteiner // req - OCSP_REQUEST // filename - PKCS#12 conteiner file // passwd - key decryption passwd //-------------------------------------------------- EXP_OPTION int signOCSPRequestPKCS12(OCSP_REQUEST *req, const char* filename, const char* passwd) { EVP_PKEY *pkey; int err = ERR_OK; STACK_OF(X509)* certs = NULL; X509* x509=0; #ifdef FRAMEWORK SecIdentityRef identity = 0; err = SecIdentityCopyPreference(CFSTR("ocsp.sk.ee"), 0, 0, &identity); if(identity) { SecCertificateRef certref = 0; SecKeyRef keyref = 0; err = SecIdentityCopyCertificate(identity, &certref); err = SecIdentityCopyPrivateKey(identity, &keyref); CFRelease(identity); RETURN_IF_NULL(certref); RETURN_IF_NULL(keyref); CFDataRef certdata = SecCertificateCopyData(certref); CFRelease(certref); RETURN_IF_NULL(certdata); const unsigned char *p = CFDataGetBytePtr(certdata); x509 = d2i_X509(0, &p, CFDataGetLength(certdata)); CFRelease(certdata); RETURN_IF_NULL(x509); CFDataRef keydata = 0; SecKeyImportExportParameters params; memset( ¶ms, 0, sizeof(params) ); params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; params.passphrase = CFSTR("pass"); err = SecKeychainItemExport(keyref, kSecFormatWrappedPKCS8, 0, ¶ms, &keydata); CFRelease(keyref); RETURN_IF_NULL(keydata); BIO *bio = BIO_new_mem_buf((void*)CFDataGetBytePtr(keydata), CFDataGetLength(keydata)); pkey = d2i_PKCS8PrivateKey_bio(bio, 0, &password_callback, 0); CFRelease(keydata); BIO_free(bio); RETURN_IF_NULL(pkey); } else { #endif RETURN_IF_NULL_PARAM(filename); if(strlen(filename) == 0) return ERR_OK; err = ReadCertificateByPKCS12(&x509, filename, passwd, &pkey); RETURN_IF_NOT(err == ERR_OK, err); #ifdef FRAMEWORK } #endif #if 0 // miscalulates on mac time zone // VS: ver 1.66 time(&tNow); err = isCertValid(x509, tNow); #else if( X509_cmp_current_time(X509_get0_notBefore(x509)) >= 0 && X509_cmp_current_time(X509_get0_notAfter(x509)) <= 0) err = ERR_CERT_INVALID; #endif if (err != ERR_OK) X509_free(x509); RETURN_IF_NOT(err == ERR_OK, ERR_PKCS12_EXPIRED); certs = sk_X509_new_null(); RETURN_IF_NULL(certs); //sk_X509_push(certs, x509); if (! OCSP_request_sign(req,x509,pkey,EVP_sha1(),certs,0)) { EVP_PKEY_free(pkey); err = ERR_OCSP_SIGN; SET_LAST_ERROR(err); } X509_free(x509); EVP_PKEY_free(pkey); //AM 22.04.08 sk_X509_free(certs); return err; } //-------------------------------------------------- // Signs an OCSP_REQUEST using X509 cert and separate keyfile // req - OCSP_REQUEST // certFile - signers certificate file // keyfile - signer's key file // passwd - key decryption passwd //-------------------------------------------------- EXP_OPTION int signOCSPRequest(OCSP_REQUEST *req,const char* certFile,const char* keyfile,const char* passwd){ EVP_PKEY *pkey; int err = ERR_OK; STACK_OF(X509)* certs = NULL; X509* x509 = NULL; certs = sk_X509_new_null(); RETURN_IF_NULL_PARAM(certs); if((err = ReadCertificate(&x509, certFile)) != ERR_OK) { SET_LAST_ERROR_RETURN_CODE(ERR_PKCS_CERT_LOC); } sk_X509_push(certs, x509); if((err = ReadPrivateKey(&pkey, keyfile, passwd, FILE_FORMAT_PEM)) == ERR_OK) { //ASN1_item_sign(ASN1_ITEM_rptr(OCSP_REQINFO),req->optionalSignature->signatureAlgorithm,NULL,req->optionalSignature->signature,req->tbsRequest,pkey,setSignAlgorithm(EVP_sha1())); //OCSP_request_sign_internal(req, x509,pkey, NULL); if(! OCSP_request_sign(req,x509,pkey,EVP_sha1(),certs,0)){ EVP_PKEY_free(pkey); SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_SIGN); } //printf("OCSP_request_sign()=%d \n",r); EVP_PKEY_free(pkey); }else{ SET_LAST_ERROR_RETURN_CODE(ERR_PRIVKEY_READ); } return err; } //-------------------------------------------------- // Creates and sends an OCSP_REQUEST object // to the notary server, receives the response // and uses it to create a confirmation object. // pSigDoc - signed doc info // pSigInfo - signature info // caCerts - responder CA certs chain // notaryCert - notarys cert search // pkcs12FileName - // pkcs12Password - // notaryURL - notarys URL // proxyHost - proxy host if needed // proxyPort - proxy port if needed //-------------------------------------------------- EXP_OPTION int getConfirmation(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const X509** caCerts, const X509* pNotCert, char* pkcs12FileName, char* pkcs12Password, char* notaryURL, char* proxyHost, char* proxyPort) { // default way to invoke it is without callers ip. return getConfirmationWithIp(pSigDoc, pSigInfo, caCerts, pNotCert, pkcs12FileName, pkcs12Password, notaryURL, proxyHost, proxyPort, 0); } //-------------------------------------------------- // Creates and sends an OCSP_REQUEST object // to the notary server, receives the response // and uses it to create a confirmation object. // pSigDoc - signed doc info // pSigInfo - signature info // caCerts - responder CA certs chain // notaryCert - notarys cert search // pkcs12FileName - // pkcs12Password - // notaryURL - notarys URL // proxyHost - proxy host if needed // proxyPort - proxy port if needed // ip - callers ip address if known //-------------------------------------------------- EXP_OPTION int getConfirmationWithIp(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const X509** caCerts, const X509* pNotCert, char* pkcs12FileName, char* pkcs12Password, char* notaryURL, char* proxyHost, char* proxyPort, unsigned long ip) { return getConfirmationWithIpEx(pSigDoc, pSigInfo, caCerts, pNotCert, pkcs12FileName, pkcs12Password, notaryURL, proxyHost, proxyPort, 0, 0, ip); } //-------------------------------------------------- // Creates and sends an OCSP_REQUEST object // to the notary server, receives the response // and uses it to create a confirmation object. // pSigDoc - signed doc info // pSigInfo - signature info // caCerts - responder CA certs chain // notaryCert - notarys cert search // pkcs12FileName - // pkcs12Password - // notaryURL - notarys URL // proxyHost - proxy host if needed // proxyPort - proxy port if needed // proxyUser - proxy user if needed // proxyPass - proxy pass if needed // ip - callers ip address if known //-------------------------------------------------- EXP_OPTION int getConfirmationWithIpEx(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const X509** caCerts, const X509* pNotCert, char* pkcs12FileName, char* pkcs12Password, char* notaryURL, char* proxyHost, char* proxyPort, char* proxyUser, char* proxyPass, unsigned long ip) { OCSP_REQUEST *req = 0; OCSP_RESPONSE *resp = 0; X509 *cert = 0, *pCA = 0; int err = ERR_OK, l1, i; byte buf1[DIGEST_LEN256+2]; NotaryInfo* pNotInf = NULL; DigiDocMemBuf* pMBuf; RETURN_IF_NULL_PARAM(pSigDoc); RETURN_IF_NULL_PARAM(pSigInfo); cert = ddocSigInfo_GetSignersCert(pSigInfo); RETURN_IF_NULL(cert); RETURN_IF_NULL_PARAM(notaryURL); clearErrors(); l1 = sizeof(buf1); pMBuf = ddocSigInfo_GetSignatureValue_Value(pSigInfo); RETURN_IF_NOT(pMBuf, err); #ifdef WIN32 RAND_screen(); RAND_bytes((unsigned char*)buf1, DIGEST_LEN); #else if((l1 = RAND_load_file("/dev/urandom", 1024)) > 0) { RAND_bytes((unsigned char*)buf1, DIGEST_LEN); l1 = DIGEST_LEN; } #endif err = calculateDigest(pMBuf->pMem, pMBuf->nLen, DIGEST_SHA1, buf1, &l1); RETURN_IF_NOT(err == ERR_OK, err); // find lowest CA cert for(i = 0; (caCerts != NULL) && (caCerts[i] != NULL); i++) pCA = (X509*)caCerts[i]; err = createOCSPRequest(pSigDoc, &req, cert, pCA, buf1, l1); // if both are NULL then this means don't sign OCSP requests if(!err && ConfigItem_lookup_bool("SIGN_OCSP", 1) /*pkcs12FileName && pkcs12Password*/) { ddocDebug(3, "getConfirmationWithIp", "Sign OCSP request with: %s", pkcs12FileName); err=signOCSPRequestPKCS12(req, pkcs12FileName, pkcs12Password); ddocDebug(3, "getConfirmationWithIp", "Signing ocsp rc: %d", err); } if(!err) { ddocDebug(3, "getConfirmationWithIp", "Send OCSP to: %s over: %s:%s", notaryURL, (proxyHost ? proxyHost : ""), (proxyPort ? proxyPort : "")); err = sendOCSPRequest2(&resp, req, notaryURL, proxyHost, proxyPort, proxyUser, proxyPass, ip); } if(!err) err = NotaryInfo_new(&pNotInf, pSigDoc, pSigInfo); //AM initializeNotaryInfoWithOCSP2? if(!err) err = initializeNotaryInfoWithOCSP(pSigDoc, pNotInf, resp, NULL, 1); if(!err && caCerts && pNotCert) { err = finalizeAndVerifyNotary(pSigDoc, pSigInfo, pNotInf, caCerts, pNotCert); } // VS - if finalizing notary fails then remove it - #8602 if(err) { if(pNotInf) ddocDebug(3, "getConfirmationWithIp", "Delete notary: %s because of error: %d", pNotInf->szId, err); NotaryInfo_delete(pSigInfo); } if(resp) OCSP_RESPONSE_free(resp); if(req) OCSP_REQUEST_free(req); return err; } //-------------------------------------------------- // Adds responder certificate to notary, searches it's // CA chain and then verifies notary // pSigDoc - signed doc info // pSigInfo - signature info // caCertSearches - responder CA certs chain // notaryCert - notarys cert search // returns error code //-------------------------------------------------- int EXP_OPTION finalizeAndVerifyNotary2(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, NotaryInfo* pNotInf, const X509** caCerts, const X509* pNotCert, const X509* pSigCa) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pNotCert); RETURN_IF_NULL_PARAM(caCerts); ddocDebug(3, "finalizeAndVerifyNotary2", "Notary: %s cert: %s", pNotInf->szId, (pNotCert ? "OK" : "NULL")); err = addNotaryInfoCert(pSigDoc, pNotInf, (X509*)pNotCert); RETURN_IF_NOT(err == ERR_OK, err); err = calcNotaryDigest(pSigDoc, pNotInf); RETURN_IF_NOT(err == ERR_OK, err); err = verifyNotaryInfoCERT2(pSigDoc, pSigInfo, pNotInf, caCerts, NULL, pNotCert, pSigCa); RETURN_IF_NOT(err == ERR_OK, err); ddocDebug(3, "finalizeAndVerifyNotary2", "rc: %d cert: %s cert2: %s", err, (pNotCert ? "OK" : "NULL"), (ddocSigInfo_GetOCSPRespondersCert(pSigInfo) ? "OK" : "NULL")); return ERR_OK; } //-------------------------------------------------- // Adds responder certificate to notary, searches it's // CA chain and then verifies notary // pSigDoc - signed doc info // pSigInfo - signature info // caCertSearches - responder CA certs chain // notaryCert - notarys cert search // returns error code //-------------------------------------------------- int EXP_OPTION finalizeAndVerifyNotary(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, NotaryInfo* pNotInf, const X509** caCerts, const X509* pNotCert) { return finalizeAndVerifyNotary2(pSigDoc, pSigInfo, pNotInf, caCerts, pNotCert, NULL); } //-------------------------------------------------- // Verfies OCSP_RESPONSE signature // pResp - signed OCSP response // caCerts - CA certificate pointer array terminated with NULL // CApath - path to (directory) all certs // notCertFile - Notary (e.g. OCSP responder) cert file //-------------------------------------------------- int verifyOCSPResponse(OCSP_RESPONSE* pResp, const X509** caCerts, const char *CApath, const X509* notCert) { X509_STORE *store; OCSP_BASICRESP* bs = NULL; STACK_OF(X509)* ver_certs = NULL; int err = ERR_OK; RETURN_IF_NULL_PARAM(pResp); RETURN_IF_NOT(caCerts != NULL, ERR_OCSP_RESP_NOT_TRUSTED); RETURN_IF_NOT(notCert != NULL, ERR_OCSP_CERT_NOTFOUND); RETURN_IF_NOT((bs = OCSP_response_get1_basic(pResp)) != NULL, ERR_OCSP_NO_BASIC_RESP); // now create an OCSP object and check its validity if((setup_verifyCERT(&store, CApath, caCerts)) == ERR_OK) { // new basic response // create OCSP basic response ver_certs = sk_X509_new_null(); if(ver_certs) { sk_X509_push(ver_certs, notCert); err = OCSP_basic_verify(bs, ver_certs, store, OCSP_TRUSTOTHER); if(err == ERR_LIB_NONE) { err = ERR_OK; } else { //checkErrors(); SET_LAST_ERROR(ERR_OCSP_WRONG_RESPID); err = ERR_OCSP_WRONG_RESPID; } // cleanup sk_X509_free(ver_certs); } X509_STORE_free(store); } if(bs) OCSP_BASICRESP_free(bs); return err; } int checkNonceAndCertbyOCSP(OCSP_RESPONSE* resp, X509* cert, byte* nonce1, int nonceLen) { int err = ERR_OK, n, status = 0; char buf[100]; OCSP_BASICRESP *br = NULL; OCSP_SINGLERESP *single = NULL; const OCSP_CERTID *cid = NULL; X509_EXTENSION *nonce; X509_NAME *iname; unsigned char *ikey; ASN1_INTEGER *serialNumber = NULL; ASN1_OCTET_STRING *issuerNameHash = NULL, *issuerKeyHash = NULL, *nonceValue = NULL; RETURN_IF_NULL_PARAM(resp); RETURN_IF_NULL_PARAM(cert); if((br = OCSP_response_get1_basic(resp)) == NULL) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_BASIC_RESP); n = OCSP_resp_count(br); RETURN_IF_NOT(n == 1, ERR_OCSP_ONE_RESPONSE); single = OCSP_resp_get0(br, 0); RETURN_IF_NOT(single, ERR_OCSP_ONE_RESPONSE); cid = OCSP_SINGLERESP_get0_id(single); RETURN_IF_NULL(cid); status = OCSP_single_get0_status(single, NULL, NULL, NULL, NULL); err = handleOCSPCertStatus(status); if(err) SET_LAST_ERROR_RETURN_CODE(err); if((OCSP_BASICRESP_get_ext_count(br) != 1) || ((nonce = OCSP_BASICRESP_get_ext(br, 0)) == NULL)) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_NONCE); i2t_ASN1_OBJECT(buf, sizeof(buf), X509_EXTENSION_get_object(nonce)); if(strcmp(buf, OCSP_NONCE_NAME)) SET_LAST_ERROR_RETURN_CODE(ERR_OCSP_NO_NONCE); // check serial number OCSP_id_get0_info(&issuerNameHash, NULL, &issuerKeyHash, &serialNumber, (OCSP_CERTID*)cid); if(ASN1_INTEGER_cmp(X509_get_serialNumber(cert), serialNumber) != 0) SET_LAST_ERROR_RETURN_CODE(ERR_WRONG_CERT); // check issuer name hash iname = X509_get_issuer_name(cert); n = sizeof(buf); X509_NAME_digest(iname, EVP_sha1(), (byte*)buf, (unsigned int*)&n); err = compareByteArrays((byte*)buf, (unsigned int)n, issuerNameHash->data, issuerNameHash->length); RETURN_IF_NOT(err == ERR_OK, err); // check issuer key hash if((ikey = get_authority_key(X509_get0_extensions(cert))) != NULL) { err = compareByteArrays(ikey, strlen((const char*)ikey), issuerKeyHash->data, issuerKeyHash->length); // cleanup ikey free(ikey); } // verify nonce value nonceValue = X509_EXTENSION_get_data(nonce); if(nonceValue->length == DIGEST_LEN) err = compareByteArrays(nonceValue->data, nonceValue->length, nonce1, nonceLen); else err = compareByteArrays(nonceValue->data + 2, nonceValue->length - 2, nonce1, nonceLen); ddocDebug(3, "checkNonceAndCertbyOCSP", "nonce1-len: %d nonce2-len: %d err: %d", nonceValue->length, nonceLen, err); if (err != ERR_OK) SET_LAST_ERROR(err); if(br) OCSP_BASICRESP_free(br); return err; } libdigidoc-3.10.5/libdigidoc/DigiDocEnc.h0000664000372000037200000012740113560273131017473 0ustar travistravis#ifndef __DIGIDOC_ENC_H__ #define __DIGIDOC_ENC_H__ //================================================== // FILE: DigiDocEnc.h // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDocEnc structures // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 15.09.2004 Veiko Sinivee // Creation //================================================== #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct DEncEncryptionProperty_st { char* szId; // Id atribute value if present char* szTarget; // Target atribute value if present char* szName; // "name" atribute value if present - used in our implementation char* szContent; // element content if used // TODO - other atributes ? } DEncEncryptionProperty; typedef struct DEncEncryptionProperties_st { char* szId; // Id atribute value if present DEncEncryptionProperty** arrEncryptionProperties; // array of EncryptionProperty pointers int nEncryptionProperties; // number of EncryptionProperty objects } DEncEncryptionProperties; typedef struct DEncEncrytedKey_st { char* szId; // Id atribute value if present char* szRecipient; // Recipient atribute value if present char* szEncryptionMethod; // EncryptionMethod element value char* szKeyName; // KeyName element value if used char* szCarriedKeyName; // CarriedKeyName element value if used X509* pCert; // receivers certificate - required in our implementation! DigiDocMemBuf mbufTransportKey; // encrypted transport key } DEncEncryptedKey; typedef struct DEncEncrytedData_st { char* szId; // Id atribute value if present char* szType; // Type atribute value if present char* szMimeType; // MimeType atribute value if present char* szEncryptionMethod; // EncryptionMethod element value char* szXmlNs; // XML namespace DEncEncryptedKey ** arrEncryptedKeys; int nEncryptedKeys; DigiDocMemBuf mbufEncryptedData; DEncEncryptionProperties encProperties; // private transient fields DigiDocMemBuf mbufTransportKey; // unencrypted transport key char initVector[16]; // flags int nDataStatus; int nKeyStatus; } DEncEncryptedData; typedef struct DEncRecvInfo_st { char* szId; // Id of recipient char* szRecipient; // Recipient atribute value if present char* szKeyName; // KeyName element value if used char* szCarriedKeyName; // CarriedKeyName element value if used X509* pCert; // receivers certificate - required in our implementation! } DEncRecvInfo; typedef struct DEncRecvInfoList_st { int nItems; DEncRecvInfo** pItems; } DEncRecvInfoList; #define DENC_DATA_STATUS_UNINITIALIZED 0 #define DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED 1 #define DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED 2 #define DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED 3 #define DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED 4 #define DENC_KEY_STATUS_UNINITIALIZED 0 #define DENC_KEY_STATUS_INITIALIZED 1 #define DENC_KEY_STATUS_DISCARDED 2 #define ENCPROP_FILENAME "Filename" #define ENCPROP_ORIG_SIZE "OriginalSize" #define ENCPROP_ORIG_MIME "OriginalMimeType" #define ENCPROP_ORIG_CONTENT "orig_file" #define ENCPROP_LIB_VERSION "LibraryVersion" #define ENCPROP_DOC_FORMAT "DocumentFormat" #define DENC_FORMAT_ENCDOC_XML "ENCDOC-XML" #define DENC_VERSION_1_0 "1.0" #define DENC_VERSION_1_1 "1.1" #define DENC_COMPRESS_ALLWAYS 0 #define DENC_COMPRESS_NEVER 1 #define DENC_COMPRESS_BEST_EFFORT 2 #define DENC_ENCRYPTED_KEY_LEN 128 #define DENC_DECRYPTED_KEY_LEN 16 #define ENCRYPT 1 #define DECRYPT 0 #define DENC_ENCDATA_TYPE_DDOC "http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd" #define DENC_ENCDATA_MIME_XML "text/xml" #define DENC_ENCDATA_MIME_ZLIB "http://www.isi.edu/in-noes/iana/assignments/media-types/application/zip" #define DENC_ENC_METHOD_AES128 "http://www.w3.org/2001/04/xmlenc#aes128-cbc" #define DENC_ENC_METHOD_RSA1_5 "http://www.w3.org/2001/04/xmlenc#rsa-1_5" #define DENC_ENC_METHOD_RSA1_5_BUGGY "http://www.w3.org/2001/04/xmlenc#rsa-1-5" #define DENC_XMLNS_XMLENC "http://www.w3.org/2001/04/xmlenc#" #define DENC_XMLNS_XMLENC_ELEMENT "http://www.w3.org/2001/04/xmlenc#Element" #define DENC_XMLNS_XMLENC_CONTENT "http://www.w3.org/2001/04/xmlenc#Content" #define DENC_XMLNS_XMLENC_ENCPROP "http://www.w3.org/2001/04/xmlenc#EncryptionProperties" #define DENC_XMLNS_XMLDSIG "http://www.w3.org/2000/09/xmldsig#" //======================< DEncEncryptedData >============================== //-------------------------------------------------- // "Constructor" of DEncEncryptedData object // pEncData - address of buffer for newly allocated object [REQUIRED] // szXmlNs - XML namespace uri [REQUIRED] // szEncMethod - encyrption method algorithm uri [REQUIRED] // szId - elements Id attribute [OPTIONAL] // szType - elements type atribute [OPTIONAL] // szMimeType - elements mime-type attribute [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_new(DEncEncryptedData** ppEncData, const char* szXmlNs, const char* szEncMethod, const char* szId, const char* szType, const char* szMimeType); //-------------------------------------------------- // "Destructor" of DEncEncryptedData object // pEncData - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_free(DEncEncryptedData* pEncData); //-------------------------------------------------- // Checks if this cdoc has embedded ddoc // pEncData - address of object to be deleted [REQUIRED] // returns 1 if true //-------------------------------------------------- EXP_OPTION int dencEncryptedData_IsDdoc(DEncEncryptedData* pEncData); //======================< DEncEncryptedData - accessors >=================== //-------------------------------------------------- // Accessor for Id atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetId(DEncEncryptedData* pEncData); //-------------------------------------------------- // Accessor for Type atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetType(DEncEncryptedData* pEncData); //-------------------------------------------------- // Accessor for MimeType atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetMimeType(DEncEncryptedData* pEncData); //-------------------------------------------------- // Accessor for xmlns atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetXmlNs(DEncEncryptedData* pEncData); //-------------------------------------------------- // Accessor for EncryptionMethod subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetEncryptionMethod(DEncEncryptedData* pEncData); //-------------------------------------------------- // Accessor for Id atribute of EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetEncryptionPropertiesId(DEncEncryptedData* pEncData); //-------------------------------------------------- // Accessor for count of EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns count or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int dencEncryptedData_GetEncryptionPropertiesCount(DEncEncryptedData* pEncData); //-------------------------------------------------- // Accessor for EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nIdx - index of EncryptionProperty object [REQUIRED] // returns EncryptionProperty pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptionProperty* dencEncryptedData_GetEncryptionProperty(DEncEncryptedData* pEncData, int nIdx); //-------------------------------------------------- // Retrieves the last EncryptionProperty subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns EncryptionProperty pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptionProperty* dencEncryptedData_GetLastEncryptionProperty(DEncEncryptedData* pEncData); //-------------------------------------------------- // Finds EncryptionProperty by Name atribute // pEncData - pointer to DEncEncryptedData object [REQUIRED] // name - name of searched property // returns EncryptionProperty pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptionProperty* dencEncryptedData_FindEncryptionPropertyByName(DEncEncryptedData* pEncData, const char* name); //-------------------------------------------------- // Accessor for count of EncryptedKey subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns count or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int dencEncryptedData_GetEncryptedKeyCount(DEncEncryptedData* pEncData); //-------------------------------------------------- // Accessor for EncryptedKey subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nIdx - index of EncryptedKey object [REQUIRED] // returns EncryptedKey pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptedKey* dencEncryptedData_GetEncryptedKey(DEncEncryptedData* pEncData, int nIdx); //-------------------------------------------------- // Searches an EncryptedKey by recipients name // pEncData - pointer to DEncEncryptedData object [REQUIRED] // recipient - recipient name used to search the key [REQUIRED] // returns EncryptedKey pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptedKey* dencEncryptedData_FindEncryptedKeyByRecipient(DEncEncryptedData* pEncData, const char* recipient); //-------------------------------------------------- // Searches an EncryptedKey by certs CN field // pEncData - pointer to DEncEncryptedData object [REQUIRED] // cn - cert CN used to search the key [REQUIRED] // returns EncryptedKey pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptedKey* dencEncryptedData_FindEncryptedKeyByCN(DEncEncryptedData* pEncData, const char* cn); //-------------------------------------------------- // Accessor for EncryptedKey subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns EncryptedKey pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptedKey* dencEncryptedData_GetLastEncryptedKey(DEncEncryptedData* pEncData); //-------------------------------------------------- // Accessor for encrypted data. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // ppBuf - address for encrypted data pointer [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_GetEncryptedData(DEncEncryptedData* pEncData, DigiDocMemBuf** ppBuf); //-------------------------------------------------- // Accessor for encrypted data status flag. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns status or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int dencEncryptedData_GetEncryptedDataStatus(DEncEncryptedData* pEncData); //======================< DEncEncryptedData - mutators >=================== //-------------------------------------------------- // Mutatoror for Id atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetId(DEncEncryptedData* pEncData, const char* value); //-------------------------------------------------- // Mutatoror for Type atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetType(DEncEncryptedData* pEncData, const char* value); //-------------------------------------------------- // Mutatoror for MimeType atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetMimeType(DEncEncryptedData* pEncData, const char* value); //-------------------------------------------------- // Mutatoror for xmlns atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetXmlNs(DEncEncryptedData* pEncData, const char* value); //-------------------------------------------------- // Mutatoror for EncryptionMethod subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetEncryptionMethod(DEncEncryptedData* pEncData, const char* value); //-------------------------------------------------- // Adds unencrypted data to encrypted data element // waiting to be encrypted in next steps // pEncData - pointer to DEncEncryptedData object [REQUIRED] // data - new unencrypted data [REQUIRED] // len - length of data. Use -1 for null terminated strings [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_AppendData(DEncEncryptedData* pEncData, const char* data, int len); //-------------------------------------------------- // Mutatoror for Id atribute of EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetEncryptionPropertiesId(DEncEncryptedData* pEncData, const char* value); //-------------------------------------------------- // Deletes EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nIdx - index of EncryptionProperty object to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_DeleteEncryptionProperty(DEncEncryptedData* pEncData, int nIdx); //-------------------------------------------------- // Deletes EncryptedKey subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nIdx - index of EncryptedKey object to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_DeleteEncryptedKey(DEncEncryptedData* pEncData, int nIdx); //======================< DEncEncryptionProperty >=================== //-------------------------------------------------- // "Constructor" for EncryptionProperty // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncProperty - address of buffer for new property object [REQUIRED] // szId - Id atribute of EncryptionProperty [OPTIONAL] // szTarget - Target atribute of EncryptionProperty [OPTIONAL] // szName - name atribute of EncryptionProperty [OPTIONAL] // szContent - content of EncryptionProperty [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_new(DEncEncryptedData* pEncData, DEncEncryptionProperty** pEncProperty, const char* szId, const char* szTarget, const char* szName, const char* szContent); //-------------------------------------------------- // "Destructor" for EncryptionProperty // pEncProperty - address of buffer for new property object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_free(DEncEncryptionProperty* pEncProperty); //======================< DEncEncryptionProperty - accessors >=================== //-------------------------------------------------- // Accessor for Id atribute of EncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptionProperty_GetId(DEncEncryptionProperty* pEncProp); //-------------------------------------------------- // Accessor for Target atribute of EncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptionProperty_GetTarget(DEncEncryptionProperty* pEncProp); //-------------------------------------------------- // Accessor for Name atribute of EncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptionProperty_GetName(DEncEncryptionProperty* pEncProp); //-------------------------------------------------- // Accessor for content of EncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptionProperty_GetContent(DEncEncryptionProperty* pEncProp); //======================< DEncEncryptionProperty - mutators >=================== //-------------------------------------------------- // Mutatoror for Id atribute of DEncEncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_SetId(DEncEncryptionProperty* pEncProp, const char* value); //-------------------------------------------------- // Mutatoror for Target atribute of DEncEncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_SetTarget(DEncEncryptionProperty* pEncProp, const char* value); //-------------------------------------------------- // Mutatoror for Name atribute of DEncEncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_SetName(DEncEncryptionProperty* pEncProp, const char* value); //-------------------------------------------------- // Mutatoror for content of DEncEncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_SetContent(DEncEncryptionProperty* pEncProp, const char* value); //======================< DEncEncryptedKey >=================== //-------------------------------------------------- // "Constructor" for EncryptedKey // Encrypts the transport key for a receiver // and stores encrypted key in memory // Call this function repeatedly for all receivers, // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncKey - address of buffer for new encrypted key object [REQUIRED] // pCert - recevers certificate [REQUIRED] // szEncMethod - encryption method [REQUIRED] // szId - Id atribute of EncryptedKey [OPTIONAL] // szRecipient - Recipient atribute of EncryptedKey [OPTIONAL] // szKeyName - KeyName subelement of EncryptedKey [OPTIONAL] // szCarriedKeyName - CarriedKeyName subelement of EncryptedKey [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_new(DEncEncryptedData* pEncData, DEncEncryptedKey** pEncKey, X509* pCert, const char* szEncMethod, const char* szId, const char* szRecipient, const char* szKeyName, const char* szCarriedKeyName); //-------------------------------------------------- // "Destructor" for EncryptedKey // pEncKey - address of buffer for new encrypted key object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_free(DEncEncryptedKey* pEncKey); //======================< DEncEncryptedKey - acessors >=================== //-------------------------------------------------- // Accessor for Id atribute of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetId(DEncEncryptedKey* pEncKey); //-------------------------------------------------- // Accessor for Recipient atribute of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetRecipient(DEncEncryptedKey* pEncKey); //-------------------------------------------------- // Accessor for EncryptionMethod subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetEncryptionMethod(DEncEncryptedKey* pEncKey); //-------------------------------------------------- // Accessor for KeyName subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetKeyName(DEncEncryptedKey* pEncKey); //-------------------------------------------------- // Accessor for CarriedKeyName subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetCarriedKeyName(DEncEncryptedKey* pEncKey); //-------------------------------------------------- // Accessor for certificate of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION X509* dencEncryptedKey_GetCertificate(DEncEncryptedKey* pEncKey); //======================< DEncEncryptedKey - mutators >=================== //-------------------------------------------------- // Mutatoror for Id atribute of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetId(DEncEncryptedKey* pEncKey, const char* value); //-------------------------------------------------- // Mutatoror for Recipient atribute of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetRecipient(DEncEncryptedKey* pEncKey, const char* value); //-------------------------------------------------- // Mutatoror for EncryptionMethod subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetEncryptionMethod(DEncEncryptedKey* pEncKey, const char* value); //-------------------------------------------------- // Mutatoror for KeyName subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetKeyName(DEncEncryptedKey* pEncKey, const char* value); //-------------------------------------------------- // Mutatoror for CarriedKeyName subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetCarriedKeyName(DEncEncryptedKey* pEncKey, const char* value); //-------------------------------------------------- // Mutatoror for certificate of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetCertificate(DEncEncryptedKey* pEncKey, X509* value); //==========< general crypto functions >============ //-------------------------------------------------- // Locates the correct EncryptedKey object by reading // users certificate from smartcard and searching the // right EncryptedKey object // pEncData - pointer to DEncEncryptedData object [REQUIRED] // ppEncKey - address of a buffer for EncryptedKey pointer [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_findEncryptedKeyByPKCS11(DEncEncryptedData* pEncData, DEncEncryptedKey** ppEncKey); //-------------------------------------------------- // Locates the correct EncryptedKey object by reading // users certificate from smartcard and searching the // right EncryptedKey object // pEncData - pointer to DEncEncryptedData object [REQUIRED] // ppEncKey - address of a buffer for EncryptedKey pointer [REQUIRED] // nSlot - slot nr // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot(DEncEncryptedData* pEncData, DEncEncryptedKey** ppEncKey, int nSlot); //-------------------------------------------------- // Locates the correct EncryptedKey object by reading // users certificate and private key from pkcs12 file and searching the // right EncryptedKey object // pEncData - pointer to DEncEncryptedData object [REQUIRED] // ppEncKey - address of a buffer for EncryptedKey pointer [REQUIRED] // ppKey - address of private key pointer. Caller must free [REQUIRED] // szPkcs12File - pkcs12 file name [REQUIRED] // szPasswd - pkcs12 file password [REQUIRED]. Might be empty? // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_findEncryptedKeyByPKCS12(DEncEncryptedData* pEncData, DEncEncryptedKey** ppEncKey, EVP_PKEY** ppKey, const char* szPkcs12File, const char* szPasswd); //-------------------------------------------------- // Encrypts data with the generated key // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nCompressOption - flag: DENC_COMPRESS_ALLWAYS, // DENC_COMPRESS_NEVER or DENC_COMPRESS_BEST_EFFORT // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_encryptData(DEncEncryptedData* pEncData, int nCompressOption); //-------------------------------------------------- // Decrypts data transport key with ID card and // then decrypts the data with the transport key. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // tKey - decrypted transport key [REQUIRED] // keyLen - length of trasnport key [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decrypt_withKey(DEncEncryptedData* pEncData, const char* tKey, int keyLen); //-------------------------------------------------- // Decrypts data with the generated key // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decryptData(DEncEncryptedData* pEncData); //-------------------------------------------------- // Decrypts data transport key with ID card and // then decrypts the data with the transport key. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncKey - transport key to decrypt [REQUIRED] // pin - pin code for smart card [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decrypt(DEncEncryptedData* pEncData, DEncEncryptedKey* pEncKey, const char* pin); //-------------------------------------------------- // Decrypts data transport key with ID card and // then decrypts the data with the transport key. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncKey - transport key to decrypt [REQUIRED] // pin - pin code for smart card [REQUIRED] // nSlot - slot nr // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decryptUsingSlot(DEncEncryptedData* pEncData, DEncEncryptedKey* pEncKey, const char* pin, int nSlot); //-------------------------------------------------- // Decrypts data transport key with ID card and // then decrypts the data with the transport key. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncKey - transport key to decrypt [REQUIRED] // pKey - private key for decrypting [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decryptWithKey(DEncEncryptedData* pEncData, DEncEncryptedKey* pEncKey, EVP_PKEY* pKey); //-------------------------------------------------- // Compresses data with ZLIB. Cannot compress encrypted data!!! // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nCompressOption - flag: DENC_COMPRESS_ALLWAYS, // DENC_COMPRESS_NEVER or DENC_COMPRESS_BEST_EFFORT // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_compressData(DEncEncryptedData* pEncData, int nCompressOption); //-------------------------------------------------- // Decompresses data with ZLIB. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nCompressOption - flag: DENC_COMPRESS_ALLWAYS, // DENC_COMPRESS_NEVER or DENC_COMPRESS_BEST_EFFORT // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decompressData(DEncEncryptedData* pEncData); //====================< RecipientInfo functions >========================== //-------------------------------------------------- // "Constructor" of DEncRecvInfo object // ppRecvInfo - address of buffer for newly allocated object [REQUIRED] // szId - recipients id [REQUIRED] // szRecipient - recipient atribute [OPTIONAL] // szKeyName - KeyName element [OPTIONAL] // szCarriedKeyName - CarriedKeyName element [OPTIONAL] // pCert - certificate [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_new(DEncRecvInfo** ppRecvInfo, const char* szId, const char* szRecipient, const char* szKeyName, const char* szCarriedKeyName, const X509* pCert); //-------------------------------------------------- // "Destructor" of DEncRecvInfo object // pRecvInfo - address of buffer for newly allocated object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_free(DEncRecvInfo* pRecvInfo); //-------------------------------------------------- // Stores DEncRecvInfo object to configuration store // pRecvInfo - address of buffer for newly allocated object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_store(DEncRecvInfo* pRecvInfo); //-------------------------------------------------- // Stores DEncRecvInfo object to configuration store // pConfStore - store to search in [OPTIONAL]. Use NULL for default // pRecvInfo - address of buffer for newly allocated object [REQUIRED] // szId - id of the object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_findById(ConfigurationStore *pConfStore, DEncRecvInfo** ppRecvInfo, const char* szId); //-------------------------------------------------- // Deletes DEncRecvInfo object from configuration store // pRecvInfo - address of RecvInfo [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_delete(DEncRecvInfo* pRecvInfo); //-------------------------------------------------- // Returns all DEncRecvInfo objects // pRecvInfoList - address of the list receiving the items [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_findAll(DEncRecvInfoList* pRecvInfoList); //====================< RecipientInfoList functions >========================== //-------------------------------------------------- // Adds a DEncRecvInfo object to the list // pRecvInfoList - address of the list receiving the item [REQUIRED] // pRecvInfo - new object to be added // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfoList_add(DEncRecvInfoList* pRecvInfoList, DEncRecvInfo *pRecvInfo); //-------------------------------------------------- // Frees the contents of a DEncRecvInfoList object // pRecvInfoList - address of the list [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfoList_free(DEncRecvInfoList* pRecvInfoList); //-------------------------------------------------- // Removes the given DEncRecvInfo object from the list // pRecvInfoList - address of the list [REQUIRED] // szId - id of the obect to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfoList_delete(DEncRecvInfoList* pRecvInfoList, const char* szId); //====================< big file functions >========================== //-------------------------------------------------- // Encrypts a file and writes it to output file // The caller must have initialized the transport keys // but not the data. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // szInputFileName - input data name [REQUIRED] // szOutputFileName - output file name [REQUIRED] // szMimeType - input data mime type [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptFile(DEncEncryptedData* pEncData, const char* szInputFileName, const char* szOutputFileName, const char* szMimeType); //====================< original content functions >=================== //-------------------------------------------------- // Returns the count of "orig_file" properties // pEncData - EncryptedData object [REQUIRED] // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencOrigContent_count(DEncEncryptedData* pEncData); //-------------------------------------------------- // Creates a new property of type "orig_file" // pEncData - EncryptedData object [REQUIRED] // szOrigContentId - Id atribute for new Property object [OPTIONAL] // szName - original file name [REQUIRED] // szSize - size as string or irginal file [REQUIRED] // szMime - mime type or original file [REQUIRED] // szDfId - Id atribute of original file [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencOrigContent_add(DEncEncryptedData* pEncData, const char* szOrigContentId, const char* szName, const char* szSize, const char* szMime, const char* szDfId); //-------------------------------------------------- // Returns the info from "orig_file" properties // pEncData - EncryptedData object [REQUIRED] // szOrigContentId - Id atribute for new Property object [OPTIONAL] // szName - buffer for original file name [REQUIRED] // nNameLen - buffer length of szName [REQUIRED] // szSize - buffer for size as string or irginal file [REQUIRED] // nSizeLen - buffer length of szSize [REQUIRED] // szMime - buffer for mime type or original file [REQUIRED] // nMimeLen - buffer length of szMime [REQUIRED] // szDfId - buffer for Id atribute of original file [REQUIRED] // nDfIdLen - buffer length of szDfId [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencOrigContent_findByIndex(DEncEncryptedData* pEncData, int origContIdx, char* szName, int nNameLen, char* szSize, int nSizeLen, char* szMime, int nMimeLen, char* szDfId, int nDfIdLen); //-------------------------------------------------- // Checks if there is a digidoc document in this // encrypted document. // pEncData - EncryptedData object [REQUIRED] // returns 1 if digidoc document is inside //-------------------------------------------------- EXP_OPTION int dencOrigContent_isDigiDocInside(DEncEncryptedData* pEncData); //-------------------------------------------------- // Registers digidoc document as encrypted datatype // and stores it's data file info. // pEncData - EncryptedData object [REQUIRED] // pSigDoc - SignedDoc object [REQUIRED] // returns 1 if digidoc document is inside //-------------------------------------------------- EXP_OPTION int dencOrigContent_registerDigiDoc(DEncEncryptedData* pEncData, SignedDoc* pSigDoc); //====================< other meta-info functions >=================== //-------------------------------------------------- // Sets the library name and version property // pEncData - EncryptedData object [REQUIRED] // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencMetaInfo_SetLibVersion(DEncEncryptedData* pEncData); //-------------------------------------------------- // Sets the format name and version property // pEncData - EncryptedData object [REQUIRED] // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencMetaInfo_SetFormatVersion(DEncEncryptedData* pEncData); //-------------------------------------------------- // Returns the library name and version meta-info of this document // pEncData - EncryptedData object [REQUIRED] // szLibrary - buffer for library name // nLibLen - length of library name buffer // szVersion - buffer for version info // nVerLen - length of version info buffer // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencMetaInfo_GetLibVersion(DEncEncryptedData* pEncData, char* szLibrary, int nLibLen, char* szVersion, int nVerLen); //-------------------------------------------------- // Returns the format name and version meta-info of this document // pEncData - EncryptedData object [REQUIRED] // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencMetaInfo_GetFormatVersion(DEncEncryptedData* pEncData, char* szFormat, int nFormatLen, char* szVersion, int nVerLen); //-------------------------------------------------- // Deletes the meta-info properties // pEncData - EncryptedData object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencMetaInfo_deleteVersionInfo(DEncEncryptedData* pEncData); //-------------------------------------------------- // Validates cdoc structure // pEncData - EncryptedData object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencValidate(DEncEncryptedData* pEncData); #ifdef __cplusplus } #endif #endif // __DIGIDOC_ENC_H__ libdigidoc-3.10.5/libdigidoc/DigiDocOCSP.h0000664000372000037200000001467513560273131017542 0ustar travistravis#ifndef __DIGIDOC_OCSP_H__ #define __DIGIDOC_OCSP_H__ //================================================== // FILE: DigiDocOCSP.h // PROJECT: Digi Doc // DESCRIPTION: DigiDoc OCSP handling routines // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 26.04.2006 Veiko Sinivee // Creation //================================================== #include #include #include #include //==========< XML generation routines >======================== #ifdef __cplusplus extern "C" { #endif //-------------------------------------------------- // sends an OCSP_REQUES object to remore server and // retrieves the OCSP_RESPONSE object // resp - buffer to store the new responses pointer // req - request objects pointer // url - OCSP responder URL // ip_addr - senders ip address if known or 0 //-------------------------------------------------- int sendOCSPRequest(OCSP_RESPONSE** resp, OCSP_REQUEST *req, char* url, char* proxyHost, char* proxyPort, unsigned long ip_addr); // Decodes binary (DER) OCSP_RESPONSE data and returns a OCSP_RESPONSE object EXP_OPTION int ddocDecodeOCSPResponseData(OCSP_RESPONSE **ppResp, const byte* data, int len); // Decodes base64 (PEM) OCSP_RESPONSE data and returns a OCSP_RESPONSE object EXP_OPTION int ddocDecodeOCSPResponsePEMData(OCSP_RESPONSE **ppResp, const byte* data, int len); EXP_OPTION int writeOCSPRequest(SignedDoc* pSigDoc, const char* signerCertFile, const char* issuertCertFile, byte* nonce, int nlen, const char* szOutputFile); // Creates and sends an OCSP_REQUEST object // to the notary server, receives the response // and uses it to create a confirmation object. EXP_OPTION int getConfirmation(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const X509** caCerts, const X509* pNotCert, char* pkcs12FileName, char* pkcs12Password, char* notaryURL, char* proxyHost, char* proxyPort); // another way to get OCSP confirmation by sending also callers ip address EXP_OPTION int getConfirmationWithIp(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const X509** caCerts, const X509* pNotCert, char* pkcs12FileName, char* pkcs12Password, char* notaryURL, char* proxyHost, char* proxyPort, unsigned long ip); // another way to get OCSP confirmation by sending also callers ip address EXP_OPTION int getConfirmationWithIpEx(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, const X509** caCerts, const X509* pNotCert, char* pkcs12FileName, char* pkcs12Password, char* notaryURL, char* proxyHost, char* proxyPort, char* proxyUser, char* proxyPass, unsigned long ip); // use this if you passed NULL-s to getConfirmation() param notaryCert EXP_OPTION int finalizeAndVerifyNotary(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, NotaryInfo* pNotInf, const X509** caCerts, const X509* pNotCert); //-------------------------------------------------- // Adds responder certificate to notary, searches it's // CA chain and then verifies notary // pSigDoc - signed doc info // pSigInfo - signature info // caCertSearches - responder CA certs chain // notaryCert - notarys cert search // returns error code //-------------------------------------------------- int EXP_OPTION finalizeAndVerifyNotary2(SignedDoc* pSigDoc, SignatureInfo* pSigInfo, NotaryInfo* pNotInf, const X509** caCerts, const X509* pNotCert, const X509* pSigCa); int ReadOCSPResponse(OCSP_RESPONSE **newOCSP_RESPONSE, const char* szFileName); int initializeNotaryInfoWithOCSP(SignedDoc *pSigDoc, NotaryInfo *pNotary, OCSP_RESPONSE *resp, X509 *notCert, int initDigest); int initializeNotaryInfoWithOCSP2(SignedDoc *pSigDoc, NotaryInfo *pNotary, OCSP_RESPONSE *resp, X509 *notCert, int initDigest); //-------------------------------------------------- // Verfies OCSP_RESPONSE signature // pResp - signed OCSP response // caCerts - CA certificate pointer array terminated with NULL // CApath - path to (directory) all certs // notCertFile - Notary (e.g. OCSP responder) cert file //-------------------------------------------------- int verifyOCSPResponse(OCSP_RESPONSE* pResp, const X509** caCerts, const char *CApath, const X509* notCert); //-------------------------------------------------- // Helper function to read OCSP_RESPONSE from binary input data // ppResp - address of newly allocated OCSP_RESPONSE object // pMBufInData - input data // returns error code or ERR_OK //-------------------------------------------------- int ddocOcspReadOcspResp(OCSP_RESPONSE** ppResp, DigiDocMemBuf* pMBufInData); //-------------------------------------------------- // Helper function to write OCSP_RESPONSE to binary output data // pResp - address of OCSP_RESPONSE object // pMBufOutData - output data // returns error code or ERR_OK //-------------------------------------------------- int ddocOcspWriteOcspResp(OCSP_RESPONSE* pResp, DigiDocMemBuf* pMBufOutData); // get OCSP in PEM form EXP_OPTION int getOcspPEM(OCSP_RESPONSE* pResp, int bHeaders, char** buf); //-------------------------------------------------- // Helper function to return OCSP_RESPONSE in base64 form. // Memory buffer will be resized as necessary. // Caller must release output buffer. // pNotary - Notary object // bHeaders - 1= with headers, 0=no headers // pMBufOutData - output data // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocGetOcspBase64(NotaryInfo *pNotary, int bHeaders, DigiDocMemBuf* pMBufOutData); #ifdef __cplusplus } #endif #endif // __DIGIDOC_OCSP_H__ libdigidoc-3.10.5/libdigidoc/DigiDocCert.c0000664000372000037200000016627313560273131017670 0ustar travistravis//================================================== // FILE: DigiDocCert.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for certificate handling // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 09.09.2004 Veiko Sinivee // Creation //================================================== #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //==========< forward declarations >==================== extern int createOCSPRequest(SignedDoc* pSigDoc, OCSP_REQUEST **req, X509 *cert, X509 *pCA, byte* nonce, int nlen); extern int signOCSPRequestPKCS12(OCSP_REQUEST *req, const char* filename, const char* passwd); extern int verifyOCSPResponse(OCSP_RESPONSE* pResp, const X509** caCerts, const char *CApath, const X509* notCert); extern int hasUmlauts(const char* str); extern int checkNonceAndCertbyOCSP(OCSP_RESPONSE* resp, X509* cert, byte* nonce1, int nonceLen); //==========< utility functions >==================== //-------------------------------------------------- // Reads a certificate file // certfile - name of the certificate file //-------------------------------------------------- EXP_OPTION int ReadCertificate(X509 **x509, const char *szCertfile) { BIO *in; RETURN_IF_NULL_PARAM(szCertfile); if((in = BIO_new_file(szCertfile, "rb")) != NULL) { *x509 = PEM_read_bio_X509(in, NULL, NULL, 0); BIO_free(in); if(!*x509) SET_LAST_ERROR_RETURN_CODE(ERR_NULL_CERT_POINTER); } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); return ERR_OK; } //-------------------------------------------------- // Reads a certificate file // certfile - name of the certificate file //-------------------------------------------------- EXP_OPTION int ReadCertificateNoErr(X509 **x509, const char *szCertfile) { BIO *in; RETURN_IF_NULL_PARAM(szCertfile); if((in = BIO_new_file(szCertfile, "rb")) != NULL) { *x509 = PEM_read_bio_X509(in, NULL, NULL, 0); BIO_free(in); if(!*x509) return ERR_NULL_CERT_POINTER; } else return ERR_FILE_READ; return ERR_OK; } //-------------------------------------------------- // Reads a certificate from pkcs12 conteiner //-------------------------------------------------- EXP_OPTION int ReadCertificateByPKCS12(X509 **x509, const char *pkcs12file, const char *passwd, EVP_PKEY **pkey) { BIO *bio; PKCS12 *p12; //memset(debugBuf,0,sizeof(debugBuf)); RETURN_IF_NULL_PARAM(pkcs12file); bio=BIO_new_file(pkcs12file, "rb"); RETURN_IF_NULL(bio); p12 = d2i_PKCS12_bio(bio, NULL); BIO_free(bio); RETURN_IF_NOT(p12, ERR_OCSP_PKCS12_CONTAINER); PKCS12_parse(p12, passwd, pkey, x509, NULL); // Hack: clear PKCS12_parse error "ERROR: 185073780 - error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch ERR_get_error(); PKCS12_free(p12); RETURN_IF_NOT(*x509, ERR_OCSP_PKCS12_CONTAINER); return ERR_OK; } //-------------------------------------------------- // Reads certificates serial number // szSerial - buffer for serial number // nMaxLen - maximum serial number buffer length // certfile - name of the certificate file //-------------------------------------------------- EXP_OPTION int GetCertSerialNumber(char *szSerial, int nMaxLen, const char *szCertfile) { BIO *in; X509 *x509; RETURN_IF_NULL_PARAM(szSerial); RETURN_IF_NULL_PARAM(szCertfile); if((in = BIO_new_file(szCertfile, "rb")) != NULL) { x509 = PEM_read_bio_X509(in, NULL, NULL, 0); BIO_free(in); RETURN_IF_NOT(x509, ERR_NULL_CERT_POINTER); ReadCertSerialNumber(szSerial, nMaxLen, x509); X509_free(x509); } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); return ERR_OK; } //-------------------------------------------------- // Reads certificates serial number // x509 - certificate object //-------------------------------------------------- int ReadCertSerialNumber(char* szSerial, int nMaxLen, X509 *x509) { ASN1_INTEGER *bs = NULL; BIGNUM* bn; char* str; int err = ERR_OK; RETURN_IF_NOT(x509, ERR_NULL_CERT_POINTER); RETURN_IF_NOT(szSerial, ERR_NULL_POINTER); bs = X509_get_serialNumber(x509); RETURN_IF_NOT(bs, ERR_NULL_SER_NUM_POINTER); bn = ASN1_INTEGER_to_BN(bs, NULL); RETURN_IF_NOT(bn, ERR_NULL_SER_NUM_POINTER); str = BN_bn2dec(bn); RETURN_IF_NOT(str, ERR_NULL_SER_NUM_POINTER); memset(szSerial, 0, nMaxLen); strncpy(szSerial, str, nMaxLen -1); if(strlen(str) > (unsigned int)nMaxLen) { err = ERR_BUF_LEN; SET_LAST_ERROR(ERR_BUF_LEN); } //AM 28.05.08 bn should be freed too if(bn) BN_free(bn); OPENSSL_free(str); checkErrors(); return err; } //-------------------------------------------------- // Reads a public key file // certfile - name of the certificate file //-------------------------------------------------- int ReadPublicKey(EVP_PKEY **PublicKey, const char *szCertfile) { EVP_PKEY *pkey = NULL; X509 *x509 = NULL; int err = ERR_OK; RETURN_IF_NULL_PARAM(szCertfile); RETURN_IF_NULL_PARAM(PublicKey); // SVEN - ver 1.92 - crashbug fixed if((err = ReadCertificate(&x509, szCertfile)) == ERR_OK) { pkey = X509_extract_key(x509); X509_free(x509); RETURN_IF_NOT(pkey, ERR_NULL_KEY_POINTER); *PublicKey = pkey; return ERR_OK; } else SET_LAST_ERROR_RETURN_CODE(err); } //-------------------------------------------------- // Reads a public key file // certfile - name of the certificate file //-------------------------------------------------- int GetPublicKey(EVP_PKEY **pubKey, const X509* x509) { EVP_PKEY *pkey = NULL; RETURN_IF_NULL_PARAM(x509); // SET_LAST_ERROR_RETURN_IF_NOT(x509, ERR_NULL_CERT_POINTER, pkey); // pkey = X509_extract_key((X509*)x509); pkey = X509_get_pubkey((X509*)x509); RETURN_IF_NOT(pkey, ERR_NULL_KEY_POINTER); *pubKey = pkey; return ERR_OK; } //-------------------------------------------------- // Callback routine for passing key password //-------------------------------------------------- int pemkey_callback(char *buf, int size, int rwflag, void *userdata) { RETURN_OBJ_IF_NULL(buf, 0); RETURN_OBJ_IF_NULL(userdata, 0); memset(buf, 0, size); strncpy(buf, (char*)userdata, size); return strlen(buf); } //-------------------------------------------------- // Reads a private key file // keyfile - name of the private key file // passwd - key password (problems with encrypted passwwords!) // format - file format (PEM or DER) //-------------------------------------------------- EXP_OPTION int ReadPrivateKey(EVP_PKEY **privKey, const char *keyfile, const char* passwd, int format) { BIO *in; EVP_PKEY *pkey = NULL; RETURN_IF_NULL_PARAM(keyfile); RETURN_IF_NULL_PARAM(passwd); if((in = BIO_new_file(keyfile, "rb")) != NULL) { switch(format) { case FILE_FORMAT_ASN1: pkey = d2i_PrivateKey_bio(in,NULL); break; case FILE_FORMAT_PEM: PEM_read_bio_PrivateKey(in, &pkey, pemkey_callback, (void*)passwd); break; } BIO_free(in); RETURN_IF_NOT(pkey, ERR_NULL_KEY_POINTER); *privKey = pkey; } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); return ERR_OK; } //-------------------------------------------------- // Writes a private key file // keyfile - name of the private key file // passwd - key password (problems with encrypted passwwords!) // format - file format (PEM or DER) //-------------------------------------------------- EXP_OPTION int WritePrivateKey(EVP_PKEY *privKey, const char *keyfile, const char* passwd, int format) { BIO *out = NULL; EVP_PKEY *pkey = privKey; RETURN_IF_NULL_PARAM(privKey); RETURN_IF_NULL_PARAM(keyfile); if((out = BIO_new_file(keyfile, "wb")) != NULL) { switch(format) { case FILE_FORMAT_ASN1: i2d_PUBKEY_bio(out, pkey); break; case FILE_FORMAT_PEM: PEM_write_bio_PrivateKey(out, pkey, (passwd ? EVP_des_ede3_cbc() : NULL), (unsigned char*)passwd, strlen(passwd), pemkey_callback, (void*)passwd) ; break; } BIO_free(out); } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); return ERR_OK; } //-------------------------------------------------- // Writes a private key and cert to a PEM file // privKey - private key // pCert - certificate // keyfile - name of the private key file // passwd - key password (problems with encrypted passwwords!) //-------------------------------------------------- EXP_OPTION int ddocWriteKeyAndCertPem(EVP_PKEY *privKey, X509* pCert, const char *keyfile, const char* passwd) { BIO *out = NULL; RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(privKey); RETURN_IF_NULL_PARAM(keyfile); if((out = BIO_new_file(keyfile, "wb")) != NULL) { PEM_write_bio_X509(out, pCert); PEM_write_bio_PrivateKey(out, privKey, (passwd ? EVP_des_ede3_cbc() : NULL), (unsigned char*)passwd, (passwd ? strlen(passwd) : 0), pemkey_callback, (void*)passwd); BIO_free(out); } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); return ERR_OK; } //-------------------------------------------------- // Reads an RSA private key file // keyfile - name of the private key file // passwd - key password (problems with encrypted passwwords!) // format - file format (PEM or DER) //-------------------------------------------------- int ReadRSAPrivateKey(RSA **privKey, const char *keyfile, const char* passwd, int format) { BIO *in = 0; RSA *pkey = 0; RETURN_IF_NULL_PARAM(keyfile); RETURN_IF_NULL_PARAM(passwd); if((in = BIO_new_file(keyfile, "rb")) != 0) { switch(format) { case FILE_FORMAT_ASN1: pkey = d2i_RSAPrivateKey_bio(in,NULL); break; case FILE_FORMAT_PEM: PEM_read_bio_RSAPrivateKey(in, &pkey, pemkey_callback, (void*)passwd); break; } BIO_free(in); RETURN_IF_NOT(pkey, ERR_NULL_KEY_POINTER); *privKey = pkey; } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); return ERR_OK; } //-------------------------------------------------- // Verifys a certificate by sending an OCSP_REQUEST object // to the notary server and checking the response. // Uses servers timestamps hash code as nonce value. // pCert - certificate to test // caCerts - responder CA certs chain // notaryCert - notarys cert search // proxyHost - proxy servers name // proxyPort - proxy servers port // notaryURL - notarys URL // ppResp - address to return OCSP response. Use NULL if // you don't want OCSP response to be returned // return 0 for OK, or error code //-------------------------------------------------- EXP_OPTION int verifyCertificateByOCSP(X509* pCert, const X509** caCerts, const X509* notaryCert, char* notaryURL, char* proxyHost, char* proxyPort, const char* pkcs12file, const char* pkcs12paswd, OCSP_RESPONSE **ppResp) { return verifyCertificateByOCSPWithIp(pCert, caCerts, notaryCert, notaryURL, proxyHost, proxyPort, pkcs12file, pkcs12paswd, ppResp, 0); } //-------------------------------------------------- // Verifys a certificate by sending an OCSP_REQUEST object // to the notary server and checking the response. // Uses servers timestamps hash code as nonce value. // pCert - certificate to test // caCerts - responder CA certs chain // notaryCert - notarys cert search // proxyHost - proxy servers name // proxyPort - proxy servers port // notaryURL - notarys URL // ppResp - address to return OCSP response. Use NULL if // you don't want OCSP response to be returned // return 0 for OK, or error code //-------------------------------------------------- EXP_OPTION int verifyCertificateByOCSPWithIp(X509* pCert, const X509** caCerts, const X509* notaryCert, char* notaryURL, char* proxyHost, char* proxyPort, const char* pkcs12file, const char* pkcs12paswd, OCSP_RESPONSE **ppResp, unsigned long ip) { OCSP_REQUEST *req = 0; OCSP_RESPONSE *resp = 0; int err = ERR_OK, l1, i; byte nonce1[DIGEST_LEN+2]; time_t tNow; X509* pCA = NULL; RETURN_IF_NULL(pCert); //RETURN_IF_NULL(notaryCert); //RETURN_IF_NULL(caCerts); RETURN_IF_NULL(notaryURL); // mark as not found yet if(ppResp) *ppResp = 0; time(&tNow); l1 = sizeof(nonce1); calculateDigest((const byte*)&tNow, sizeof(tNow), DIGEST_SHA1, nonce1, &l1); // find lowest CA for(i = 0; (caCerts != NULL) && (caCerts[i] != NULL); i++) pCA = (X509*)caCerts[i]; err = createOCSPRequest(NULL, &req, pCert, pCA, nonce1, l1); if(err == ERR_OK && pkcs12file) err = signOCSPRequestPKCS12(req, pkcs12file, pkcs12paswd); if(err == ERR_OK) { //WriteOCSPRequest("test1.req", req); err = sendOCSPRequest(&resp, req, notaryURL, proxyHost, proxyPort, ip); //WriteOCSPResponse("test1.resp", resp); //printf("sendOCSPRequest returned %d\n", err); if(err == ERR_OK) { if(caCerts && notaryCert) { ddocDebug(1, "verifyCertificateByOCSPWithIp", "Verify OCSP resp with known CA certs"); // check the response signature err = verifyOCSPResponse(resp, (const X509**)caCerts, NULL, notaryCert); } if(err == ERR_OK) err = checkNonceAndCertbyOCSP(resp, pCert, nonce1, l1); //WriteOCSPResponse("test1.resp", resp); } } // free OCSP request, if allocated; if (req) OCSP_REQUEST_free(req); // return OCSP response if required if(ppResp) *ppResp = resp; else OCSP_RESPONSE_free(resp); return err; } //============================================================ // Decodes binary (DER) cert data and returns a cert object // certData - binary (DER) cert data // certLen - cert data length //============================================================ EXP_OPTION int ddocDecodeX509Data(X509 **ppX509, const byte* certData, int certLen) { BIO* b1 = NULL; // check input params RETURN_IF_NULL_PARAM(certData); RETURN_IF_NULL_PARAM(ppX509); // mark as not read yet *ppX509 = 0; // create memory BIO on it b1 = BIO_new_mem_buf((void*)certData, certLen); RETURN_IF_NOT(b1, ERR_CERT_INVALID); *ppX509 = d2i_X509_bio(b1, NULL); ddocDebug(4, "ddocDecodeX509Data", "Decoding %d bytes DER data - cert %s", certLen, (*ppX509 ? "OK" : "ERROR")); // cleanup BIO_free(b1); RETURN_IF_NOT(*ppX509, ERR_CERT_INVALID); return ERR_OK; } //============================================================ // Decodes base64 (PEM) cert data and returns a cert object // certData - base64 (PEM) cert data // certLen - cert data length //============================================================ EXP_OPTION int ddocDecodeX509PEMData(X509 **ppX509, const char* certData, int certLen) { byte* p1 = 0; int l1 = 0, err = ERR_OK; // check input params RETURN_IF_NULL_PARAM(certData); RETURN_IF_NULL_PARAM(ppX509); // mark as not read yet *ppX509 = 0; // allocate memory for decoding l1 = certLen; // should be enough as it shrinks p1 = (byte*)malloc(l1); RETURN_IF_BAD_ALLOC(p1); memset(p1, 0, l1); // decode base64 data decode((const byte*)certData, certLen, p1, &l1); // decode cert err = ddocDecodeX509Data(ppX509, p1, l1); ddocDebug(4, "ddocDecodeX509PEMData", "Decoding %d bytes PEM data - cert %s", certLen, (*ppX509 ? "OK" : "ERROR")); // cleanup if(p1) free(p1); return err; } //============================================================ // Checks if the cert is valid (between begin and end date) // cert - certificate object // tDate - date to check the cert //============================================================ EXP_OPTION int isCertValid(X509* cert, time_t tDate) { int err = ERR_OK; ASN1_TIME *tm = 0; time_t tStart, tEnd; RETURN_IF_NULL_PARAM(cert); tm = X509_get_notBefore(cert); RETURN_IF_NULL(tm); asn1time2time_t_local(tm, &tStart); tm = X509_get_notAfter(cert); RETURN_IF_NULL(tm); asn1time2time_t_local(tm, &tEnd); if(tDate < tStart || tDate > tEnd) { err = ERR_CERT_INVALID; SET_LAST_ERROR(err); } return err; } //============================================================ // Retrieves the certificates first validity time as tim_t in GMT zone // pCert - certificate object // returns certificates first validity time as tim_t in GMT zone //============================================================ EXP_OPTION time_t getCertNotBeforeTimeT(X509* pCert) { time_t t1 = 0; ASN1_TIME *tm = 0; if(pCert) { tm = X509_get_notBefore(pCert); if(tm) asn1time2time_t_local(tm, &t1); } return t1; } //============================================================ // Retrieves the certificates last validity time as tim_t in GMT zone // pCert - certificate object // returns certificates last validity time as tim_t in GMT zone //============================================================ EXP_OPTION time_t getCertNotAfterTimeT(X509* pCert) { time_t t1 = 0; ASN1_TIME *tm = 0; if(pCert) { tm = X509_get_notAfter(pCert); if(tm) asn1time2time_t_local(tm, &t1); } return t1; } //============================================================ // Checks if the cert has been signed by this CA-cert // cert - certificate object // cafile - CA cert file //============================================================ EXP_OPTION int isCertSignedBy(X509* cert, const char* cafile) { int err = ERR_OK; EVP_PKEY* pubkey = NULL; // SVEN - ver 1.92 - crashbug fixed (void)ReadPublicKey(&pubkey, cafile); RETURN_IF_NOT(pubkey, ERR_PUBKEY_READ); err = X509_verify(cert, pubkey); if(err == ERR_LIB_NONE) err = ERR_OK; else { err = ERR_CERT_ISSUER; SET_LAST_ERROR(err); } // checkErrors(); //332:error:0D0890A1:lib(13):func(137):reason(161):.\crypto\asn1\a_verify.c:141: EVP_PKEY_free(pubkey); return err; } //============================================================ // Writes cert to file without the usual PEM headers // bout - output file // cert - certificate object // returns error code //============================================================ int writeCertToXMLFile(BIO* bout, X509* cert) { int l1, l2; char *p1, *p2; RETURN_IF_NULL_PARAM(bout); RETURN_IF_NULL_PARAM(cert); l1 = i2d_X509(cert, NULL); p1 = (char*)malloc(l1+10); RETURN_IF_BAD_ALLOC(p1); p2 = p1; i2d_X509(cert, (unsigned char**)&p2); l2 = l1 * 2; p2 = (char*)malloc(l2); if (p2 == NULL) { free(p1); RETURN_IF_BAD_ALLOC(p2); } encode((const byte*)p1, l1, (byte*)p2, &l2); BIO_puts(bout, p2); free(p2); free(p1); return ERR_OK; } //============================================================ // Converts the certificate to PEM form with or without headers // cert - certificate object // bHeaders - 1= with headers, 0=no headers // buf - output buffer newly allocated // returns error code //============================================================ EXP_OPTION int getCertPEM(X509* cert, int bHeaders, char** buf) { int l1, l2; char *p1, *p2; RETURN_IF_NULL_PARAM(buf); RETURN_IF_NULL_PARAM(cert); l1 = i2d_X509(cert, NULL); p1 = (char*)malloc(l1+10); RETURN_IF_BAD_ALLOC(p1); p2 = p1; i2d_X509(cert, (unsigned char**)&p2); l2 = l1 * 2 + 200; *buf = (char*)malloc(l2); if(*buf == NULL) { free(p1); RETURN_IF_BAD_ALLOC(*buf); } memset(*buf, 0, l2); if(bHeaders) strncpy(*buf, "-----BEGIN CERTIFICATE-----\n", l2); encode((const byte*)p1, l1, (byte*)strchr(*buf, 0), &l2); l2 = l1 * 2 + 200 - strlen(*buf); if(bHeaders) strncat(*buf, "\n-----END CERTIFICATE-----", l2); free(p1); return ERR_OK; } //-------------------------------------------------- // Returns the certificates validity first date // cert - certificate data // timestamp - timestamp buffer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int getCertNotBefore(const SignedDoc* pSigDoc, X509* cert, char* timestamp, int len) { int err = ERR_OK; ASN1_TIME *tm = 0; RETURN_IF_NULL_PARAM(cert); RETURN_IF_NULL_PARAM(timestamp); tm = X509_get_notBefore(cert); RETURN_IF_NULL(tm); err = asn1time2strYear(pSigDoc, tm, timestamp, 1900, len); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Returns the certificates validity last date // cert - certificate data // timestamp - timestamp buffer // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int getCertNotAfter(const SignedDoc* pSigDoc, X509* cert, char* timestamp, int len) { int err = ERR_OK; ASN1_TIME *tm = 0; RETURN_IF_NULL_PARAM(cert); RETURN_IF_NULL_PARAM(timestamp); tm = X509_get_notAfter(cert); RETURN_IF_NULL(tm); err = asn1time2strYear(pSigDoc, tm, timestamp, 1900, len); if (err != ERR_OK) SET_LAST_ERROR(err); return err; } //-------------------------------------------------- // Saves the certificate in a file // cert - certificate data // szFileName - destination filename // nFormat - cert format // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int saveCert(X509* cert, const char* szFileName, int nFormat) { // int err = ERR_OK; BIO* b; RETURN_IF_NULL_PARAM(cert); RETURN_IF_NULL_PARAM(szFileName); if((b = BIO_new_file(szFileName, "w")) != NULL) { if(nFormat == FILE_FORMAT_PEM) PEM_write_bio_X509(b, cert); if(nFormat == FILE_FORMAT_ASN1) i2d_X509_bio(b, cert); BIO_free(b); } else SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); return ERR_OK; } // new functions for Win client EXP_OPTION void* decodeCert(const char* pemData) { BIO* b1; X509* x509; int l1; RETURN_OBJ_IF_NULL(pemData, NULL); l1 = strlen(pemData); b1 = BIO_new_mem_buf((void*)pemData, l1); RETURN_OBJ_IF_NULL(b1, 0); x509 = PEM_read_bio_X509(b1, NULL, NULL, 0); if(!x509) SET_LAST_ERROR(ERR_CERT_READ); // checkErrors(); BIO_free(b1); return x509; } //=========================================================== // Encodes certificate from X509 to binary //=========================================================== EXP_OPTION void encodeCert(const X509* x509, char * encodedCert, int* encodedCertLen) { if(x509==NULL){ *encodedCertLen = 0; return; } if(encodedCert==NULL){ *encodedCertLen = 0; return; } *encodedCertLen = i2d_X509((X509*)x509, NULL); i2d_X509((X509*)x509, (unsigned char**)&encodedCert); } //============================================================ // Checks if the cert has been signed by this CA-cert // cert - certificate object // cafile - CA cert file //============================================================ EXP_OPTION int isCertSignedByCERT(const X509* cert, const X509* caCert) { int err = ERR_OK; EVP_PKEY* pubkey; DigiDocMemBuf mbuf1, mbuf2, mbuf3; mbuf1.pMem = 0; mbuf1.nLen = 0; mbuf2.pMem = 0; mbuf2.nLen = 0; mbuf3.pMem = 0; mbuf3.nLen = 0; RETURN_IF_NULL_PARAM(cert); RETURN_IF_NULL_PARAM(caCert); err = ddocCertGetSubjectCN((X509*)caCert, &mbuf1); err = ddocCertGetSubjectCN((X509*)cert, &mbuf2); err = ddocCertGetIssuerCN((X509*)cert, &mbuf3); ddocDebug(3, "isCertSignedByCERT", "Issuer: %s, Subject: %s, Subjects-issuer: %s", (const char*)mbuf1.pMem, (const char*)mbuf2.pMem, (const char*)mbuf3.pMem); ddocMemBuf_free(&mbuf1); ddocMemBuf_free(&mbuf2); ddocMemBuf_free(&mbuf3); err = GetPublicKey(&pubkey, caCert); if(err == ERR_OK) { err = X509_verify((X509*)cert, pubkey); ddocDebug(3, "isCertSignedByCERT", "verify: %d", err); if(err == ERR_LIB_NONE) err = ERR_OK; else err = ERR_CERT_ISSUER; if(err != ERR_OK) { ddocDebug(3, "isCertSignedByCERT", "Cert not issued by ca verify: %d", err); checkErrors(); } EVP_PKEY_free(pubkey); } else err = ERR_PUBKEY_READ; if (err != ERR_OK) SET_LAST_ERROR(err); return err; } /*int utc2latin1(const char* data, int len, char* dest) { int i, j; for(i = j = 0; i < len; i++) { if(data[i]) { dest[j] = data[i]; j++; } } dest[j] = 0; return j; }*/ //-------------------------------------------------------- // Checks if the desired key-usage bit is set on a given cert // pCert - certificate // nBit - flag index // return 1 if bit is set //-------------------------------------------------------- EXP_OPTION int ddocCertCheckKeyUsage(X509 *pCert, int nBit) { int crit = -1, extIdx = -1; ASN1_BIT_STRING *keyUsage; if(pCert && nBit >= 0 && nBit < 8) { keyUsage = (ASN1_BIT_STRING *)X509_get_ext_d2i(pCert, NID_key_usage, &crit, &extIdx); if(keyUsage) { ddocDebug(3, "ddocCertCheckKeyUsage", "Bit: %d set: %d", nBit, ASN1_BIT_STRING_get_bit(keyUsage, nBit)); return ASN1_BIT_STRING_get_bit(keyUsage, nBit); } } return 0; } //-------------------------------------------------------- // Finds and copies a substring from source string that is // prefixed by szLabel and terminated by szTerminator // szSrc - source string // szLabel - prefix of searched string // szTerminator - terminator string // szDest - found string. Caller must free this mem. //-------------------------------------------------------- int ddocCertCopySubstring(const char* szSrc, const char* szLabel, const char* szTerminator, char** szDest) { ptrdiff_t l; char *p1, *p2; RETURN_IF_NULL_PARAM(szSrc); RETURN_IF_NULL_PARAM(szLabel); RETURN_IF_NULL_PARAM(szTerminator); RETURN_IF_NULL_PARAM(szDest); *szDest = 0; // mark as empty p1 = strstr(szSrc, szLabel); if(p1) { p1 += strlen(szLabel); p2 = strstr(p1, szTerminator); if(!p2) p2 = strchr(p1, 0); if(p2 && p2 > p1) { l = p2 - p1 + 1; *szDest = (char*)malloc(l); if(*szDest) { memset(*szDest, 0, l); strncpy(*szDest, p1, p2 - p1); } } } return ERR_OK; } EXP_OPTION int readCertPoliciesFromOU(X509* pX509, PolicyIdentifier** pPolicies, int* nPols) { DigiDocMemBuf mbuf1; int err = ERR_OK; char *pUri, *pDesc, *pOid; PolicyIdentifier *pTmp; RETURN_IF_NULL_PARAM(pX509); RETURN_IF_NULL_PARAM(pPolicies); RETURN_IF_NULL_PARAM(nPols); mbuf1.nLen = 0; mbuf1.pMem = 0; pUri = pDesc = pOid = 0; err = ddocCertGetSubjectOrganizationUnit(pX509, &mbuf1); if(!err && mbuf1.pMem) { err = ddocCertCopySubstring((const char*)mbuf1.pMem, "SP Desc:", "\n", &pDesc); if(!err) { err = ddocCertCopySubstring((const char*)mbuf1.pMem, "SP URI:", "\n", &pUri); if(!err) { err = ddocCertCopySubstring((const char*)mbuf1.pMem, "SP OID:", "\n", &pOid); if(!err && (pDesc || pUri || pOid)) { pTmp = (PolicyIdentifier*)realloc(*pPolicies, sizeof(PolicyIdentifier) * ((*nPols) + 1)); if(pTmp) { *pPolicies = pTmp; pTmp = (*pPolicies) + (*nPols); *nPols = (*nPols) + 1; pTmp->szOID = (pOid ? strdup((const char*)pOid) : 0); pTmp->szUserNotice = (pDesc ? strdup((const char*)pDesc) : 0); pTmp->szCPS = (pUri ? strdup((const char*)pUri) : 0); } } free(pOid); } free(pUri); } free(pDesc); } ddocMemBuf_free(&mbuf1); return err; } //-------------------------------------------------- // Reads certificates PolicyIdentifiers and returns // them in a newly allocated structure. Caller must // free this, regardless of function return status. // pX509 - certificate // pPolicies - returned PolicyIdentifiers array // nPols - number of returned policies //-------------------------------------------------- EXP_OPTION int readCertPolicies(X509* pX509, PolicyIdentifier** pPolicies, int* nPols) { char buf[512], *p; int err = 0, i, k, j, pos, l; PolicyIdentifier *pPol, *pTmp; RETURN_IF_NULL_PARAM(pX509); RETURN_IF_NULL_PARAM(pPolicies); RETURN_IF_NULL_PARAM(nPols); *pPolicies = NULL; *nPols = 0; // try read from certificates OU first if(!err) err = readCertPoliciesFromOU(pX509, pPolicies, nPols); // read from usual place pos = X509_get_ext_by_NID(pX509, NID_certificate_policies, -1); if(pos >= 0) { POLICYINFO *pol; STACK_OF(POLICYINFO)* pPols; STACK_OF(POLICYQUALINFO)* pQuals; POLICYQUALINFO* pQual; X509_EXTENSION* pExt = X509_get_ext(pX509, pos); // X509V3_EXT_METHOD *method = X509V3_EXT_get(pExt); //pPols = (STACK*)X509V3_EXT_d2i(pExt); pPols = X509V3_EXT_d2i(pExt); for(i = 0; i < sk_POLICYINFO_num(pPols); i++) { pol = sk_POLICYINFO_value(pPols, i); if(*pPolicies && *nPols) { pTmp = (PolicyIdentifier*)realloc(*pPolicies, sizeof(PolicyIdentifier) * ((*nPols) + 1)); if (pTmp != NULL) { *pPolicies = pTmp; *nPols = (*nPols) + 1; pPol = (*pPolicies) + ((*nPols) - 1); } else SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); } else { pTmp = (PolicyIdentifier*)malloc(sizeof(PolicyIdentifier)); if (pTmp != NULL) { *pPolicies = pTmp; pPol = *pPolicies; *nPols = 1; } else SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); } pPol->szCPS = pPol->szOID = pPol->szUserNotice = NULL; // check i2t_ASN1_OBJECT(buf, sizeof(buf), pol->policyid); pPol->szOID = strdup(buf); pQuals = pol->qualifiers; for(k = 0; k < sk_POLICYQUALINFO_num(pQuals); k++) { pQual = sk_POLICYQUALINFO_value(pQuals, k); switch(OBJ_obj2nid(pQual->pqualid)) { case NID_id_qt_cps: pPol->szCPS = strdup((const char*)pQual->d.cpsuri->data); // if strdup fails, szCPS will be NULL break; case NID_id_qt_unotice: ddocDebug(4, "readCertPolicies", "Exptext: %d - \'%s\'", pQual->d.usernotice->exptext->length, pQual->d.usernotice->exptext->data); if(pQual->d.usernotice->exptext) { if(pQual->d.usernotice->exptext->type == V_ASN1_UTF8STRING) { pPol->szUserNotice = strdup((const char*)pQual->d.usernotice->exptext->data); } else { p = 0; l = ASN1_STRING_to_UTF8((unsigned char**)&p, pQual->d.usernotice->exptext); pPol->szUserNotice = strdup(p); OPENSSL_free(p); } /*if(pQual->d.usernotice->exptext->data[0]) { pPol->szUserNotice = strdup((const char*)pQual->d.usernotice->exptext->data); } else { utc2latin1((const char*)pQual->d.usernotice->exptext->data, pQual->d.usernotice->exptext->length, buf); pPol->szUserNotice = strdup(buf); // if strdup fails, szUserNotice will be NULL }*/ } if(pQual->d.usernotice->noticeref) { NOTICEREF *ref = pQual->d.usernotice->noticeref; p = 0; l = 0; // calculate the memory required l += strlen((const char*)ref->organization->data) + 1; for(j = 0; j < sk_ASN1_INTEGER_num(ref->noticenos); j++) { ASN1_INTEGER *num; char *tmp; num = sk_ASN1_INTEGER_value(ref->noticenos, j); tmp = i2s_ASN1_INTEGER(NULL, num); l += strlen(tmp) + 2; OPENSSL_free(tmp); } // now alloc mem and copy data l += 10; // alloc with a little extra p = (char*)malloc(l); if(p) { memset(p, 0, l); strncpy(p, (const char*)ref->organization->data, l); strncat(p, " ", l - strlen(p)); for(j = 0; j < sk_ASN1_INTEGER_num(ref->noticenos); j++) { ASN1_INTEGER *num; char *tmp; num = sk_ASN1_INTEGER_value(ref->noticenos, j); if (j) strncat(p, ", ", l - strlen(p)); tmp = i2s_ASN1_INTEGER(NULL, num); strncat(buf, tmp, sizeof(buf) - strlen(buf)); OPENSSL_free(tmp); } pPol->szUserNotice = p; } } break; default: break; } } } sk_POLICYINFO_pop_free(pPols, POLICYINFO_free); } ddocDebug(4, "readCertPolicies", "End"); return err; } //-------------------------------------------------- // Frees policy identifiers array // pPolicies - PolicyIdentifiers array // nPols - number of policies //-------------------------------------------------- EXP_OPTION void PolicyIdentifiers_free(PolicyIdentifier* pPolicies, int nPols) { int i; for(i = 0; i < nPols; i++) { free(pPolicies[i].szOID); free(pPolicies[i].szCPS); free(pPolicies[i].szUserNotice); //free(pPolicies[i]); } free(pPolicies); } //-------------------------------------------------- // Reads certificates extension value // pCert - certificate // pMemBuf - memory buffer to return data // nExt - extension code //-------------------------------------------------- EXP_OPTION int readCertExtData(X509* pCert, DigiDocMemBuf* pMemBuf, int nExt, int nOff) { int err = ERR_OK, pos; X509_EXTENSION* pExt; /* char buf1[300]; int l1;*/ RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; pos = X509_get_ext_by_NID(pCert, nExt, -1); if(pos >= 0) { pExt = X509_get_ext(pCert, pos); ASN1_OCTET_STRING *value = X509_EXTENSION_get_data(pExt); if(pExt && value && value->data) { /* memset(buf1, 0, sizeof(buf1)); l1 = sizeof(buf1); bin2hex(pExt->value->data, pExt->value->length, buf1, &l1); ddocDebug(3, "readCertExtData", "Ext: %d len: %d data: %s", nExt, pExt->value->length, buf1);*/ if(value->length > 20 && nOff) //ddocMemAssignData(pMemBuf, ((char*)pExt->value->data) + (pExt->value->length - 20), 20); ddocMemAssignData(pMemBuf, ((char*)value->data) + nOff, 20); else ddocMemAssignData(pMemBuf, ((char*)value->data), value->length); } } return err; } //-------------------------------------------------- // Reads certificates authority key identifier // pCert - certificate // pMemBuf - memory buffer to return data //-------------------------------------------------- EXP_OPTION int readAuthorityKeyIdentifier(X509* pCert, DigiDocMemBuf* pMemBuf) { int err = ERR_OK; int crit = 0, l1; char *p = 0; AUTHORITY_KEYID *pAkid = X509_get_ext_d2i(pCert, NID_authority_key_identifier, &crit, NULL); if(pAkid) { l1 = i2d_ASN1_OCTET_STRING(pAkid->keyid, (unsigned char **)&p); if(l1 > 20) ddocMemAssignData(pMemBuf, p + (l1 - 20), 20); else ddocMemAssignData(pMemBuf, (char*)p, l1); OPENSSL_free(p); AUTHORITY_KEYID_free(pAkid); } return err; //return readCertExtData(pCert, pMemBuf, NID_authority_key_identifier, 5); } //-------------------------------------------------- // Reads certificates subject key identifier // pCert - certificate // pMemBuf - memory buffer to return data //-------------------------------------------------- EXP_OPTION int readSubjectKeyIdentifier(X509* pCert, DigiDocMemBuf* pMemBuf) { return readCertExtData(pCert, pMemBuf, NID_subject_key_identifier, 2); } //-------------------------------------------------- // Checks if this is a company CPS policy // pPolicy - PolicyIdentifier to be checked //-------------------------------------------------- EXP_OPTION int isCompanyCPSPolicy(PolicyIdentifier* pPolicy) { //return (strstr(pPolicy->szCPS, "1.3.6.4.1.10015.7") != NULL); if(pPolicy && pPolicy->szCPS) return (strstr(pPolicy->szCPS, "1.3.6.1.4.1.10015.5") != NULL); else return 0; } //-------------------------------------------------- // Returns the certificates sha1 hash. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetDigest(X509* pCert, DigiDocMemBuf* pMemBuf) { int err = ERR_OK; unsigned int l1; RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; l1 = 30; err = ddocMemSetLength(pMemBuf, l1); X509_digest(pCert, EVP_sha1(), (unsigned char*)pMemBuf->pMem, &l1); pMemBuf->nLen = l1; return err; } //-------------------------------------------------- // Returns the certificates public key sha1 hash. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetPubkeyDigest(X509* pCert, DigiDocMemBuf* pMemBuf) { int err = ERR_OK; unsigned int l1; RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; l1 = 30; err = ddocMemSetLength(pMemBuf, l1); X509_pubkey_digest(pCert, EVP_sha1(), (unsigned char*)pMemBuf->pMem, &l1); pMemBuf->nLen = l1; return err; } //-------------------------------------------------- // Returns the certificates subject name sha1 hash. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetSubjectNameDigest(X509* pCert, DigiDocMemBuf* pMemBuf) { int err = ERR_OK; unsigned int l1; X509_NAME *iname; RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; l1 = 30; err = ddocMemSetLength(pMemBuf, l1); iname = X509_get_subject_name(pCert); X509_NAME_digest(iname, EVP_sha1(), (unsigned char*)pMemBuf->pMem, &l1); pMemBuf->nLen = l1; return err; } //-------------------------------------------------- // Returns the certificates issuer name sha1 hash. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetIssuerNameDigest(X509* pCert, DigiDocMemBuf* pMemBuf) { int err = ERR_OK; unsigned int l1; X509_NAME *iname; RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; l1 = 30; err = ddocMemSetLength(pMemBuf, l1); iname = X509_get_issuer_name(pCert); X509_NAME_digest(iname, EVP_sha1(), (unsigned char*)pMemBuf->pMem, &l1); pMemBuf->nLen = l1; return err; } //-------------------------------------------------- // Returns the certificates DN. Internal function. // Do not call directly, subject to change // pCert - certificate data // pMemBuf - memory buffer object for storing DN // bIssuer - 1=issuer, 0=subject // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetDN(X509* pCert, DigiDocMemBuf* pMemBuf, int bIssuer) { int err = ERR_OK; X509_NAME *pName = 0; X509_NAME_ENTRY *pNe = 0; ASN1_STRING *data = 0; int i, n, l, t, b = 0; const char *s; unsigned char* p; RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pMemBuf); // initialize if(pMemBuf->pMem) err = ddocMemBuf_free(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; // iterate over name entries if(bIssuer) pName = X509_get_issuer_name(pCert); else pName = X509_get_subject_name(pCert); RETURN_IF_NULL(pName) for(i = 0; (err == ERR_OK) && (i < X509_NAME_entry_count(pName)); i++) { pNe = X509_NAME_get_entry(pName, i); n = OBJ_obj2nid(X509_NAME_ENTRY_get_object(pNe)); s = OBJ_nid2sn(n); data = X509_NAME_ENTRY_get_data(pNe); t = data->type; // mostly we find here: // V_ASN1_PRINTABLESTRING, V_ASN1_TELETEXSTRING or V_ASN1_BMPSTRING // that we convert to UTF, but V_ASN1_UTF8STRING allready is in UTF8 // handle only the enry types we know if(n != NID_undef && s != NULL) { // convert to UTF8 only p = 0; if(t == V_ASN1_UTF8STRING) { p = data->data; l = data->length; } else l = ASN1_STRING_to_UTF8(&p, data); ddocDebug(5, "ddocCertGetDN", "NameEntry nid: %d type: %d len: %d item: %s value: \'%s\'", n, t, l, s, (p ? (const char*)p : "NULL")); // append separator if necessary if(b) err = ddocMemAppendData(pMemBuf, ",", -1); // RFC2253 must use , else b = 1; // print the entry err = ddocMemAppendData(pMemBuf, s, -1); err = ddocMemAppendData(pMemBuf, "=", -1); err = ddocMemAppendData(pMemBuf, (const char*)p, l); // cleanup if(p && t != V_ASN1_UTF8STRING) OPENSSL_free(p); } ddocDebug(5, "ddocCertGetDN", "Subject: \'%s\' len: %d", (const char*)pMemBuf->pMem, pMemBuf->nLen); } // for return err; } //-------------------------------------------------- // Returns the certificates issuer name. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetIssuerDN(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDN(pCert, pMemBuf, 1); } //-------------------------------------------------- // Returns the certificates subject name. // pCert - certificate data // pMemBuf - memory buffer object for storing DN // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectDN(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDN(pCert, pMemBuf, 0); } //-------------------------------------------------- // Returns the certificates DN. // Do not call directly, subject to change // pCert - certificate data // pMemBuf - memory buffer object for storing DN // bIssuer - 1=issuer, 0=subject // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetDNFromName(X509_NAME* pName, DigiDocMemBuf* pMemBuf) { int err = ERR_OK; X509_NAME_ENTRY *pNe = 0; ASN1_STRING *data = 0; int i, n, l, t, b = 0; const char *s; unsigned char* p; RETURN_IF_NULL_PARAM(pMemBuf); // initialize if(pMemBuf->pMem) err = ddocMemBuf_free(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; for(i = 0; (err == ERR_OK) && (i < X509_NAME_entry_count(pName)); i++) { pNe = X509_NAME_get_entry(pName, i); n = OBJ_obj2nid(X509_NAME_ENTRY_get_object(pNe)); s = OBJ_nid2sn(n); data = X509_NAME_ENTRY_get_data(pNe); t = data->type; // mostly we find here: // V_ASN1_PRINTABLESTRING, V_ASN1_TELETEXSTRING or V_ASN1_BMPSTRING // that we convert to UTF, but V_ASN1_UTF8STRING allready is in UTF8 // handle only the enry types we know if(n != NID_undef && s != NULL) { // convert to UTF8 only p = 0; if(t == V_ASN1_UTF8STRING) { p = data->data; l = data->length; } else l = ASN1_STRING_to_UTF8(&p, data); ddocDebug(5, "ddocCertGetDN", "NameEntry nid: %d type: %d len: %d item: %s value: \'%s\'", n, t, l, s, (p ? (const char*)p : "NULL")); // append separator if necessary if(b) err = ddocMemAppendData(pMemBuf, "/", -1); else b = 1; // print the entry err = ddocMemAppendData(pMemBuf, s, -1); err = ddocMemAppendData(pMemBuf, "=", -1); err = ddocMemAppendData(pMemBuf, (const char*)p, l); // cleanup if(p && t != V_ASN1_UTF8STRING) OPENSSL_free(p); } ddocDebug(5, "ddocCertGetDN", "Subject: \'%s\' len: %d", (const char*)pMemBuf->pMem, pMemBuf->nLen); } // for return err; } //-------------------------------------------------- // Returns the certificates subject name and returns // the desired item from it. // pCert - certificate data // pMemBuf - memory buffer object for storing result // nNid - cert name part NID // bIssuer - 1=from issuer DN, 0=from subject DN // returns error code or ERR_OK //-------------------------------------------------- int ddocCertGetDNPart(X509* pCert, DigiDocMemBuf* pMemBuf, int nNid, int bIssuer) { int err = ERR_OK; X509_NAME *pName = 0; X509_NAME_ENTRY *pNe = 0; ASN1_STRING *data; int i, n, l, t, m, j; const char *s; unsigned char* p = 0; RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pMemBuf); // initialize if(pMemBuf->pMem) err = ddocMemBuf_free(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; // iterate over name entries if(bIssuer) pName = X509_get_issuer_name(pCert); else pName = X509_get_subject_name(pCert); for(i = 0; (err == ERR_OK) && (i < X509_NAME_entry_count(pName)); i++) { pNe = X509_NAME_get_entry(pName, i); n = OBJ_obj2nid(X509_NAME_ENTRY_get_object(pNe)); s = OBJ_nid2sn(n); data = X509_NAME_ENTRY_get_data(pNe); t = data->type; // mostly we find here: // V_ASN1_PRINTABLESTRING, V_ASN1_TELETEXSTRING or V_ASN1_BMPSTRING // that we convert to UTF, but V_ASN1_UTF8STRING allready is in UTF8 // handle only the enry types we know if(n == nNid && s != NULL) { // convert to UTF8 only if(t == V_ASN1_UTF8STRING) { p = data->data; l = data->length; } else l = ASN1_STRING_to_UTF8(&p, data); // test for 0x0 m = (p ? strlen(p) : 0); if(m < l && p) { for(j = 0; j < l; j++) if(p[j] == 0) p[j] = ' '; } ddocDebug(5, "ddocCertGetDNPart", "NameEntry type: %d len: %d item: %s value: \'%s\'", t, l, s, (p ? (const char*)p : "NULL")); if(pMemBuf->pMem && strlen(pMemBuf->pMem)) ddocMemAppendData(pMemBuf, "\n", -1); err = ddocMemAppendData(pMemBuf, (const char*)p, l); // cleanup if(p && t != V_ASN1_UTF8STRING) OPENSSL_free(p); // continue search } } // for return err; } //-------------------------------------------------- // Returns the certificates subject CN // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectCN(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDNPart(pCert, pMemBuf, NID_commonName, 0); } //-------------------------------------------------- // Returns the certificates issuer CN // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetIssuerCN(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDNPart(pCert, pMemBuf, NID_commonName, 1); } //-------------------------------------------------- // Returns the certificates subject first name // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectFirstName(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDNPart(pCert, pMemBuf, NID_firstName, 0); } //-------------------------------------------------- // Returns the certificates subject last name // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectLastName(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDNPart(pCert, pMemBuf, NID_lastName, 0); } //-------------------------------------------------- // Returns the certificates subject personal code // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectPerCode(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDNPart(pCert, pMemBuf, NID_perCode, 0); } //-------------------------------------------------- // Returns the certificates subject country code // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectCountryName(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDNPart(pCert, pMemBuf, NID_countryName, 0); } //-------------------------------------------------- // Returns the certificates subject organization // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectOrganization(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDNPart(pCert, pMemBuf, NID_organization, 0); } //-------------------------------------------------- // Returns the certificates subject organization unit // pCert - certificate data // pMemBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int ddocCertGetSubjectOrganizationUnit(X509* pCert, DigiDocMemBuf* pMemBuf) { return ddocCertGetDNPart(pCert, pMemBuf, NID_organizationUnit, 0); } //-------------------------------------------------- // Returns the desired item from string rep of DN // sDn - certificate DN // sId - searched DN part // pMBuf - memory buffer object for storing result // returns error code or ERR_OK //-------------------------------------------------- int ddocGetDNPartFromString(const char* sDn, const char* sId, DigiDocMemBuf* pMBuf) { int err = ERR_OK, j, l; char *p0 = 0, *p1 = 0; char buf1[30]; RETURN_IF_NULL_PARAM(sDn); RETURN_IF_NULL_PARAM(sId); RETURN_IF_NULL_PARAM(pMBuf); // initialize if(pMBuf->pMem) err = ddocMemBuf_free(pMBuf); pMBuf->pMem = 0; pMBuf->nLen = 0; memset(buf1, 0, sizeof(buf1)); snprintf(buf1, sizeof(buf1)-1, "%s=", sId); p0 = strstr(sDn, buf1); if(p0) { p0 += strlen(buf1); p1 = strchr(p0, ','); if(p1) { while(p1 && *(p1-1) == '\\') p1 = strchr(p1, ','); if(p1 && *p1 == ',') p1--; } else { p1 = strchr(p0, '/'); if(p1) { while(p1 && *(p1-1) == '\\') p1 = strchr(p1, '/'); if(p1 && *p1 == '/') p1--; } else p1 = (char*)sDn + strlen(sDn); } // if(p0 && p1 && (int)(p1 - p0) > 0) { l = (int)(p1 - p0) + 1; ddocMemAppendData(pMBuf, (const char*)p0, l); ((char*)pMBuf->pMem)[l] = 0; } } return err; } //AM 06.03.08 //-------------------------------------------------- // Returns the certificates DN. Internal function. // Do not call directly, subject to change // pCert - certificate data // pMemBuf - memory buffer object for storing DN // bIssuer - 1=issuer, 0=subject // returns error code or ERR_OK //-------------------------------------------------- int bdocCertGetDN(X509* pCert, DigiDocMemBuf* pMemBuf, int bIssuer) { int err = ERR_OK; X509_NAME *pName = 0; X509_NAME_ENTRY *pNe = 0; ASN1_STRING *data = NULL; int i, n, l, t, b = 0; const char *s; unsigned char* p; RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(pMemBuf); // initialize if(pMemBuf->pMem) err = ddocMemBuf_free(pMemBuf); pMemBuf->pMem = 0; pMemBuf->nLen = 0; // iterate over name entries if(bIssuer) pName = X509_get_issuer_name(pCert); else pName = X509_get_subject_name(pCert); for(i = 0; (err == ERR_OK) && (i < X509_NAME_entry_count(pName)); i++) { pNe = X509_NAME_get_entry(pName, i); data = X509_NAME_ENTRY_get_data(pNe); n = OBJ_obj2nid(X509_NAME_ENTRY_get_object(pNe)); s = OBJ_nid2sn(n); t = data->type; // mostly we find here: // V_ASN1_PRINTABLESTRING, V_ASN1_TELETEXSTRING or V_ASN1_BMPSTRING // that we convert to UTF, but V_ASN1_UTF8STRING allready is in UTF8 // handle only the enry types we know if(n != NID_undef && s != NULL) { // convert to UTF8 only p = 0; if(t == V_ASN1_UTF8STRING) { p = data->data; l = data->length; } else l = ASN1_STRING_to_UTF8(&p, data); ddocDebug(5, "ddocCertGetDN", "NameEntry nid: %d type: %d len: %d item: %s value: \'%s\'", n, t, l, s, (p ? (const char*)p : "NULL")); // append separator if necessary if(b) err = ddocMemAppendData(pMemBuf, ",", -1); else b = 1; // print the entry err = ddocMemAppendData(pMemBuf, s, -1); err = ddocMemAppendData(pMemBuf, "=", -1); err = ddocMemAppendData(pMemBuf, (const char*)p, l); // cleanup if(p && t != V_ASN1_UTF8STRING) OPENSSL_free(p); } ddocDebug(5, "ddocCertGetDN", "Subject: \'%s\' len: %d", (const char*)pMemBuf->pMem, pMemBuf->nLen); } // for return err; } //================< deprecated functions> ================================= #ifdef WITH_DEPRECATED_FUNCTIONS //============================================================ // Decodes base64 (PEM) cert data and returns a cert object // certData - base64 (PEM) cert data // certLen - cert data length //============================================================ // FIXME : Ugly as hell... #pragma message ("Function decodeCertificateData may be removed from future releases. Please use function ddocDecodeX509PEMData() instead.") EXP_OPTION int decodeCertificateData(X509 **newX509, const byte* certData, int certLen) { int l1, l2; char *buf1; BIO* b1 = NULL; X509* x509 = NULL; RETURN_IF_NULL_PARAM(certData); l2 = certLen * 2; buf1 = (char*)malloc(l2); RETURN_IF_BAD_ALLOC(buf1); memset(buf1, 0, l2); strncpy(buf1, "-----BEGIN CERTIFICATE-----\r\n", l2); l1 = l2 - strlen(buf1); encode(certData, certLen, (byte*)strchr(buf1,0), &l1); l1 = l2 - strlen(buf1); strncat(buf1, "\n-----END CERTIFICATE-----", l1); l1 = strlen(buf1); b1 = BIO_new_mem_buf(buf1, l1); if (!b1) { free(buf1); SET_LAST_ERROR_RETURN_CODE(ERR_NULL_POINTER); } x509 = PEM_read_bio_X509(b1, NULL, NULL, 0); BIO_free(b1); free(buf1); RETURN_IF_NOT(x509, ERR_CERT_INVALID); *newX509 = x509; return ERR_OK; } //-------------------------------------------------- // Returns the certificates issuer name // cert - certificate data // buf - usser name buffer // buflen - pointer to buffer length (will be modified) // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int getCertIssuerName(X509* cert, char* buf, int* buflen) { int l1; char buf1[X509_NAME_BUF_LEN]; RETURN_IF_NULL_PARAM(cert); RETURN_IF_NULL_PARAM(buf); RETURN_IF_NULL_PARAM(buflen); if(*buflen >= X509_NAME_LEN) { l1 = sizeof(buf1); memset(buf1,0,l1); memset(buf, 0, *buflen); X509_NAME_oneline(X509_get_issuer_name(cert), buf1, l1); unicode2ascii(buf1, buf); ddocDebug(5, "getCertIssuerName", "Issuer: \'%s\' -> \'%s\'", buf1, buf); *buflen = strlen(buf); } else SET_LAST_ERROR_RETURN_CODE(ERR_BUF_LEN); return ERR_OK; } //-------------------------------------------------- // Returns the certificates subject name. This finction // is also used in the COM library // cert - certificate data // buf - user name buffer // buflen - pointer to buffer length (will be modified) // returns error code or ERR_OK //-------------------------------------------------- #pragma message ("Function getCertSubjectName may be removed from future releases. Please use function ddocCertGetSubjectDN() instead.") EXP_OPTION int getCertSubjectName(X509* cert, char* buf, int* buflen) { int err = ERR_OK; DigiDocMemBuf mbuf; mbuf.pMem = 0; mbuf.nLen = 0; err = ddocCertGetSubjectDN(cert, &mbuf); if(err == ERR_OK) { if(*buflen >= X509_NAME_LEN) { #ifdef WIN32 utf82oem((const char*)mbuf.pMem, buf, buflen); #else utf82ascii((const char*)mbuf.pMem, buf, buflen); #endif *buflen = strlen(buf); } else SET_LAST_ERROR(ERR_BUF_LEN); ddocMemBuf_free(&mbuf); } return err; } //-------------------------------------------------- // Returns the certificates subjects DN // cert - certificate data // buf - usser name buffer // buflen - pointer to buffer length (will be modified) // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int getCertSubjectDN(X509* cert, char* buf, int* buflen, int bUTF8) { int l1; char buf1[X509_NAME_BUF_LEN]; RETURN_IF_NULL_PARAM(cert); RETURN_IF_NULL_PARAM(buf); RETURN_IF_NULL_PARAM(buflen); if(*buflen >= X509_NAME_LEN) { l1 = sizeof(buf1); memset(buf1, 0, l1); memset(buf, 0, *buflen); X509_NAME_oneline(X509_get_subject_name(cert), buf1, l1); if (bUTF8) { unicode2ascii(buf1, buf); *buflen = strlen(buf); } else { ascii2utf8(buf1, buf, buflen); } } else SET_LAST_ERROR_RETURN_CODE(ERR_BUF_LEN); return ERR_OK; } //-------------------------------------------------- // Returns the certificates subjects name's CN part // cert - certificate data // buf - usser name buffer // buflen - pointer to buffer length (will be modified) // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int getCertSubjectCN(X509* cert, char* buf, int* buflen, int bUTF8) { int l1, err = ERR_OK; char buf1[X509_NAME_BUF_LEN], *p , *p2, buf2[X509_NAME_BUF_LEN]; RETURN_IF_NULL_PARAM(cert); RETURN_IF_NULL_PARAM(buf); RETURN_IF_NULL_PARAM(buflen); if(*buflen >= X509_NAME_LEN) { l1 = sizeof(buf1); memset(buf1,0,l1); memset(buf, 0, *buflen); err = getCertSubjectName(cert, buf1, &l1); if(bUTF8 && hasUmlauts(buf1)) { //printf("Converting umlauts toi UTF8\n"); l1 = sizeof(buf2); ascii2utf8(buf1, buf2, &l1); strncpy(buf1, buf2, sizeof(buf1)); ddocDebug(4, "getCertSubjectCN", "Subject: \'%s\'", buf1); } /*if (!bUTF8) { l1 = sizeof(buf2); utf82ascii(buf1, buf2, &l1); //strcpy(buf1, buf2); }*/ //printf("SUBJECT: %s\n", buf1); p = strstr(buf1, "CN="); if(p) { p += 3; p2 = strchr(p, '/'); if(!p2) p2 = p + strlen(p); if(p2) { strncpy(buf, p, p2-p); buf[p2-p] = 0; } } *buflen = strlen(buf); } else SET_LAST_ERROR_RETURN_CODE(ERR_BUF_LEN); return ERR_OK; } //-------------------------------------------------- // Returns the certificates issuer name's CN part // cert - certificate data // buf - usser name buffer // buflen - pointer to buffer length (will be modified) // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int getCertIssuerCN(X509* cert, char* buf, int* buflen, int bUTF8) { int l1; char buf1[X509_NAME_BUF_LEN], *p , *p2, buf2[X509_NAME_BUF_LEN]; RETURN_IF_NULL_PARAM(cert); RETURN_IF_NULL_PARAM(buf); RETURN_IF_NULL_PARAM(buflen); if(*buflen >= X509_NAME_LEN) { l1 = sizeof(buf1); memset(buf1,0,l1); memset(buf, 0, *buflen); X509_NAME_oneline(X509_get_issuer_name(cert), buf1, l1); if (bUTF8) { unicode2ascii(buf1, buf2); } else { l1 = sizeof(buf2); ascii2utf8(buf1, buf2, &l1); } //printf("SUBJECT: %s\n", buf2); p = strstr(buf2, "CN="); if(p) { p += 3; p2 = strchr(p, '/'); if(!p2) p2 = p + strlen(p); if(p2) { strncpy(buf, p, p2-p); buf[p2-p] = 0; } } *buflen = strlen(buf); } else SET_LAST_ERROR_RETURN_CODE(ERR_BUF_LEN); return ERR_OK; } // get cert owners id-code EXP_OPTION int getCertOwnerCode(const X509* pCert, char* buf, int len) { int err, l1; char buf1[500], *p; RETURN_IF_NULL_PARAM(pCert); RETURN_IF_NULL_PARAM(buf); l1 = sizeof(buf1); err = getCertSubjectName((void*)pCert, buf1, &l1); if (err != ERR_OK) SET_LAST_ERROR_RETURN_CODE(err); err = ERR_CERT_READ; p = strstr(buf1, "CN="); if (p) { p = strchr(p, ','); if(p) { p = strchr(p+1, ','); if(p) { strncpy(buf, p+1, 1en); buf[1en] = 0; err = ERR_OK; } } else { // no comma -> no id-code ! buf[0] = 0; // is this really an error ? err = ERR_WRONG_CERT; } } if (err != ERR_OK) SET_LAST_ERROR(err); return err; } #endif // WITH_DEPRECATED_FUNCTIONS libdigidoc-3.10.5/libdigidoc/DigiDocGlobals.h0000664000372000037200000000404213560273131020344 0ustar travistravis#ifndef __DIGIDOC_PROFILE_H__ #define __DIGIDOC_PROFILE_H__ //================================================== // FILE: DigiDocGlobals.h // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDoc TSA profiles // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 01.06.2006 Arvo Sulakatko // Creation // 08.06.2006 Veiko Sinivee // Changed implementation and assignment of profile values //================================================== #include #ifdef __cplusplus extern "C" { #endif // TSAProfile typedef struct tag_TSAProfile *LPTSAProfile; // TSAProfile typedef struct tag_TSAProfile { char g_szTsaPolicy[255]; char g_szTsaUrl[255]; int g_nTsaMaxTsInterval; int g_bAddSignatureTimeStamp; int g_bAddSigAndRefsTimeStamp; char m_szDebugFilePath[0xFF]; int m_nDebugLevel; } TSAProfile, *LPTSAProfile; //-------------------------------------------------- // Initializes TSA profile block // returns pointer to global TSA profile //-------------------------------------------------- EXP_OPTION TSAProfile* TSAProfile_init(); // default TSAProfile (to be extended) //extern LPTSAProfile g_current_TSAProfile; EXP_OPTION void TSAProfile_free(); #ifdef __cplusplus } #endif #endif // __DIGIDOC_PROFILE_H__ libdigidoc-3.10.5/libdigidoc/DigiDocDebug.h0000664000372000037200000000522113560273131020007 0ustar travistravis#ifndef __DIGIDOC_DEBUG_H__ #define __DIGIDOC_DEBUG_H__ //================================================== // FILE: DigiDocDebug.h // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for debug output // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 10.08.2004 Veiko Sinivee // Creation //================================================== #include #include #include #ifdef __cplusplus extern "C" { #endif //----------------------------------------- // Formats debug output // level - debug level to output this message on // func - name of the function // format - message format and arguments //----------------------------------------- EXP_OPTION void ddocDebug(int level, const char* func, const char* format, ...); //----------------------------------------- // Formats debug output // level - debug level to output this message on // func - name of the function // msg - message format and arguments // args - va_list struct //----------------------------------------- EXP_OPTION void ddocDebugVaArgs(int level, const char* func, const char* msg, va_list args); //----------------------------------------- // Deletes the log file if it exists. //----------------------------------------- EXP_OPTION void ddocDebugTruncateLog(); //----------------------------------------- // Reads the contents of the log file // pMemBuf - buffer for log data //----------------------------------------- EXP_OPTION int ddocDebugReadLog(DigiDocMemBuf *pMemBuf); //----------------------------------------- // Writes debug data in a file // level - debug level to write on // szFileName - target file name // pMemBuf - buffer for log data //----------------------------------------- EXP_OPTION int ddocDebugWriteFile(int level, const char* szFileName, DigiDocMemBuf *pMemBuf); #ifdef __cplusplus } #endif #endif // __DIGIDOC_DEBUG_H__ libdigidoc-3.10.5/libdigidoc/DigiDocEnc.c0000664000372000037200000031625213560273131017472 0ustar travistravis//================================================== // FILE: DigiDocEnc.c // PROJECT: Digi Doc Encryption // DESCRIPTION: DigiDocEnc structure admin functions // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 15.09.2004 Veiko Sinivee // Creation //================================================== // config data comes from there #ifndef WIN32 #if HAVE_CONFIG_H #include #endif #endif // no win32 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 #define snprintf _snprintf #endif #if OPENSSL_VERSION_NUMBER < 0x10010000L static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new() { return (EVP_ENCODE_CTX*)OPENSSL_malloc(sizeof(EVP_ENCODE_CTX)); } static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) { OPENSSL_free(ctx); } #endif //======================< DEncEncryptedData >============================== //-------------------------------------------------- // Validates the parameter. We // currently support only AES-128-CBC. // szEncMethod - value to be checked // returns error code or ERR_OK //-------------------------------------------------- int dencEncDataValidateEncMethod(const char* szEncMethod) { if(szEncMethod && strcmp(szEncMethod, DENC_ENC_METHOD_AES128)) SET_LAST_ERROR_RETURN(ERR_DENC_ENC_METHOD, ERR_DENC_ENC_METHOD) else return ERR_OK; } //-------------------------------------------------- // Validates the XML namespace parameter. We // currently support only // szEncMethod - value to be checked // returns error code or ERR_OK //-------------------------------------------------- int dencValidateEncXmlNs(const char* szXmlNs) { if(szXmlNs && strcmp(szXmlNs, DENC_XMLNS_XMLENC)) SET_LAST_ERROR_RETURN(ERR_DENC_ENC_XMLNS, ERR_DENC_ENC_XMLNS) else return ERR_OK; } //-------------------------------------------------- // "Constructor" of DEncEncryptedData object // pEncData - address of buffer for newly allocated object [REQUIRED] // szXmlNs - XML namespace uri // szEncMethod - encyrption method algorithm uri // szId - elements Id attribute [OPTIONAL] // szType - elements type atribute [OPTIONAL] // szMimeType - elements mime-type attribute [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_new(DEncEncryptedData** pEncData, const char* szXmlNs, const char* szEncMethod, const char* szId, const char* szType, const char* szMimeType) { int err = ERR_OK; // check input parameters ddocDebug(3, "dencEncryptedData_new", "EncMethod: %s, Id: %s, type: %s, mime: %s", szEncMethod, szId, szType, szMimeType); RETURN_IF_NULL_PARAM(pEncData); err = dencEncDataValidateEncMethod(szEncMethod); if(err) return err; err = dencValidateEncXmlNs(szXmlNs); if(err) return err; *pEncData = (DEncEncryptedData*)malloc(sizeof(DEncEncryptedData)); // allocate new object RETURN_IF_BAD_ALLOC(*pEncData); memset(*pEncData, 0, sizeof(DEncEncryptedData)); // set required fields if(szXmlNs) { err = ddocMemAssignString((char**)&((*pEncData)->szXmlNs), szXmlNs); if(err) return err; } if(szEncMethod) { err = ddocMemAssignString((char**)&((*pEncData)->szEncryptionMethod), szEncMethod); if(err) return err; } // set optional fields if(szId) { err = ddocMemAssignString((char**)&((*pEncData)->szId), szId); if(err) return err; } if(szType) { err = ddocMemAssignString((char**)&((*pEncData)->szType), szType); if(err) return err; } if(szMimeType) { err = ddocMemAssignString((char**)&((*pEncData)->szMimeType), szMimeType); if(err) return err; } // set meta info carrying lib & document format versions dencMetaInfo_SetLibVersion(*pEncData); dencMetaInfo_SetFormatVersion(*pEncData); return err; } //-------------------------------------------------- // "Destructor" of DEncEncryptedData object // pEncData - address of object to be deleted [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_free(DEncEncryptedData* pEncData) { int i, err = ERR_OK; RETURN_IF_NULL_PARAM(pEncData) // cleanup this object if(pEncData->szId) free(pEncData->szId); if(pEncData->szType) free(pEncData->szType); if(pEncData->szMimeType) free(pEncData->szMimeType); if(pEncData->szEncryptionMethod) free(pEncData->szEncryptionMethod); if(pEncData->szXmlNs) free(pEncData->szXmlNs); // cleanup child objects ddocMemBuf_free(&(pEncData->mbufEncryptedData)); if(pEncData->encProperties.szId) free(pEncData->encProperties.szId); for(i = 0; i < pEncData->encProperties.nEncryptionProperties; i++) { if(pEncData->encProperties.arrEncryptionProperties[i]) { err = dencEncryptionProperty_free(pEncData->encProperties.arrEncryptionProperties[i]); if(err) return err; } } if(pEncData->encProperties.arrEncryptionProperties) free(pEncData->encProperties.arrEncryptionProperties); ddocMemBuf_free(&(pEncData->mbufTransportKey)); for(i = 0; i < pEncData->nEncryptedKeys; i++) { if(pEncData->arrEncryptedKeys[i]) { err = dencEncryptedKey_free(pEncData->arrEncryptedKeys[i]); if(err) return err; } } free(pEncData->arrEncryptedKeys); free(pEncData); return err; } //======================< DEncEncryptedData - accessors >=================== //-------------------------------------------------- // Accessor for Id atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetId(DEncEncryptedData* pEncData) { RETURN_OBJ_IF_NULL(pEncData, NULL) return pEncData->szId; } //-------------------------------------------------- // Accessor for Type atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetType(DEncEncryptedData* pEncData) { RETURN_OBJ_IF_NULL(pEncData, NULL) return pEncData->szType; } //-------------------------------------------------- // Accessor for MimeType atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetMimeType(DEncEncryptedData* pEncData) { RETURN_OBJ_IF_NULL(pEncData, NULL) return pEncData->szMimeType; } //-------------------------------------------------- // Accessor for xmlns atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetXmlNs(DEncEncryptedData* pEncData) { RETURN_OBJ_IF_NULL(pEncData, NULL) return pEncData->szXmlNs; } //-------------------------------------------------- // Accessor for EncryptionMethod subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetEncryptionMethod(DEncEncryptedData* pEncData) { RETURN_OBJ_IF_NULL(pEncData, NULL) return pEncData->szEncryptionMethod; } //-------------------------------------------------- // Accessor for Id atribute of EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedData_GetEncryptionPropertiesId(DEncEncryptedData* pEncData) { RETURN_OBJ_IF_NULL(pEncData, NULL) return pEncData->encProperties.szId; } //-------------------------------------------------- // Accessor for count of EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns count or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int dencEncryptedData_GetEncryptionPropertiesCount(DEncEncryptedData* pEncData) { SET_LAST_ERROR_RETURN_IF_NOT(pEncData, ERR_NULL_POINTER, -1) return pEncData->encProperties.nEncryptionProperties; } //-------------------------------------------------- // Accessor for EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nIdx - index of EncryptionProperty object [REQUIRED] // returns EncryptionProperty pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptionProperty* dencEncryptedData_GetEncryptionProperty(DEncEncryptedData* pEncData, int nIdx) { RETURN_OBJ_IF_NULL(pEncData, NULL) SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->encProperties.nEncryptionProperties, ERR_DENC_BAD_PROP_IDX, NULL); RETURN_OBJ_IF_NULL(pEncData->encProperties.arrEncryptionProperties[nIdx], 0); return pEncData->encProperties.arrEncryptionProperties[nIdx]; } //-------------------------------------------------- // Finds EncryptionProperty by Name atribute // pEncData - pointer to DEncEncryptedData object [REQUIRED] // name - name of searched property // returns EncryptionProperty pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptionProperty* dencEncryptedData_FindEncryptionPropertyByName(DEncEncryptedData* pEncData, const char* name) { DEncEncryptionProperty* pEncProp = 0; int i; RETURN_OBJ_IF_NULL(pEncData, NULL) RETURN_OBJ_IF_NULL(name, NULL) for(i = 0; i < pEncData->encProperties.nEncryptionProperties; i++) { if(pEncData->encProperties.arrEncryptionProperties[i] && pEncData->encProperties.arrEncryptionProperties[i]->szName && !strcmp(pEncData->encProperties.arrEncryptionProperties[i]->szName, name)) { pEncProp = pEncData->encProperties.arrEncryptionProperties[i]; break; } } return pEncProp; } //-------------------------------------------------- // Retrieves the last EncryptionProperty subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns EncryptionProperty pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptionProperty* dencEncryptedData_GetLastEncryptionProperty(DEncEncryptedData* pEncData) { int nIdx; RETURN_OBJ_IF_NULL(pEncData, NULL) nIdx = pEncData->encProperties.nEncryptionProperties -1; SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->encProperties.nEncryptionProperties, ERR_DENC_BAD_PROP_IDX, NULL); RETURN_OBJ_IF_NULL(pEncData->encProperties.arrEncryptionProperties[nIdx], 0); return pEncData->encProperties.arrEncryptionProperties[nIdx]; } //-------------------------------------------------- // Accessor for count of EncryptedKey subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns count or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int dencEncryptedData_GetEncryptedKeyCount(DEncEncryptedData* pEncData) { SET_LAST_ERROR_RETURN_IF_NOT(pEncData, ERR_NULL_POINTER, -1) return pEncData->nEncryptedKeys; } //-------------------------------------------------- // Accessor for EncryptedKey subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nIdx - index of EncryptedKey object [REQUIRED] // returns EncryptedKey pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptedKey* dencEncryptedData_GetEncryptedKey(DEncEncryptedData* pEncData, int nIdx) { RETURN_OBJ_IF_NULL(pEncData, NULL) SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->nEncryptedKeys, ERR_DENC_BAD_KEY_IDX, NULL); RETURN_OBJ_IF_NULL(pEncData->arrEncryptedKeys[nIdx], 0); return pEncData->arrEncryptedKeys[nIdx]; } //-------------------------------------------------- // Searches an EncryptedKey by recipients name // pEncData - pointer to DEncEncryptedData object [REQUIRED] // recipient - recipient name used to search the key [REQUIRED] // returns EncryptedKey pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptedKey* dencEncryptedData_FindEncryptedKeyByRecipient(DEncEncryptedData* pEncData, const char* recipient) { int i; DEncEncryptedKey *pKey; RETURN_OBJ_IF_NULL(pEncData, NULL) RETURN_OBJ_IF_NULL(recipient, NULL) for(i = 0; i < pEncData->nEncryptedKeys; i++) { pKey = pEncData->arrEncryptedKeys[i]; if(pKey && pKey->szRecipient && !strcmp(pKey->szRecipient, recipient)) return pKey; } return NULL; } //-------------------------------------------------- // Searches an EncryptedKey by certs CN field // pEncData - pointer to DEncEncryptedData object [REQUIRED] // cn - cert CN used to search the key [REQUIRED] // returns EncryptedKey pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptedKey* dencEncryptedData_FindEncryptedKeyByCN(DEncEncryptedData* pEncData, const char* cn) { int i, err = ERR_OK; DEncEncryptedKey *pKey; DigiDocMemBuf mbuf; mbuf.pMem = 0; mbuf.nLen = 0; RETURN_OBJ_IF_NULL(pEncData, NULL) RETURN_OBJ_IF_NULL(cn, NULL) for(i = 0; i < pEncData->nEncryptedKeys; i++) { pKey = pEncData->arrEncryptedKeys[i]; if(pKey && pKey->pCert) { err = ddocCertGetSubjectCN(pKey->pCert, &mbuf); if(!strcmp((const char*)mbuf.pMem, cn)) { ddocMemBuf_free(&mbuf); return pKey; } } } ddocMemBuf_free(&mbuf); return NULL; } //-------------------------------------------------- // Accessor for EncryptedKey subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns EncryptedKey pointer or NULL for error //-------------------------------------------------- EXP_OPTION DEncEncryptedKey* dencEncryptedData_GetLastEncryptedKey(DEncEncryptedData* pEncData) { int nIdx; RETURN_OBJ_IF_NULL(pEncData, NULL) nIdx = pEncData->nEncryptedKeys-1; SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->nEncryptedKeys, ERR_DENC_BAD_KEY_IDX, NULL); RETURN_OBJ_IF_NULL(pEncData->arrEncryptedKeys[nIdx], 0); return pEncData->arrEncryptedKeys[nIdx]; } //-------------------------------------------------- // Accessor for encrypted data. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // ppBuf - address for encrypted data pointer [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_GetEncryptedData(DEncEncryptedData* pEncData, DigiDocMemBuf** ppBuf) { RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(ppBuf) *ppBuf = &(pEncData->mbufEncryptedData); return ERR_OK; } //-------------------------------------------------- // Accessor for encrypted data status flag. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns status or -1 for error. Then use error API to check errors //-------------------------------------------------- EXP_OPTION int dencEncryptedData_GetEncryptedDataStatus(DEncEncryptedData* pEncData) { SET_LAST_ERROR_RETURN_IF_NOT(pEncData, ERR_NULL_POINTER, -1) return pEncData->nDataStatus; } //======================< DEncEncryptedData - mutators >=================== //-------------------------------------------------- // Mutatoror for Id atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetId(DEncEncryptedData* pEncData, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncData->szId), value); return err; } //-------------------------------------------------- // Mutatoror for Type atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetType(DEncEncryptedData* pEncData, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncData->szType), value); return err; } //-------------------------------------------------- // Mutatoror for MimeType atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetMimeType(DEncEncryptedData* pEncData, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncData->szMimeType), value); return err; } //-------------------------------------------------- // Mutatoror for xmlns atribute of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetXmlNs(DEncEncryptedData* pEncData, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(value) err = dencValidateEncXmlNs(value); if(err) return err; err = ddocMemAssignString((char**)&(pEncData->szXmlNs), value); return err; } //-------------------------------------------------- // Mutatoror for EncryptionMethod subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetEncryptionMethod(DEncEncryptedData* pEncData, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(value) // replace the buggy URI with correct one to enable // decrypting files with buggy URI but write only // correct URI in new files if(!strcmp(value, DENC_ENC_METHOD_RSA1_5_BUGGY)) value = DENC_ENC_METHOD_RSA1_5; err = dencEncDataValidateEncMethod(value); if(err) return err; err = ddocMemAssignString((char**)&(pEncData->szEncryptionMethod), value); return err; } //-------------------------------------------------- // Adds unencrypted data to encrypted data element // waiting to be encrypted in next steps // pEncData - pointer to DEncEncryptedData object [REQUIRED] // data - new unencrypted data [REQUIRED] // len - length of data. Use -1 for null terminated strings [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_AppendData(DEncEncryptedData* pEncData, const char* data, int len) { ddocDebug(3, "dencEncryptedData_AppendData", "data: %s, len: %d", (data ? "OK" : "NULL"), len); RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(data) SET_LAST_ERROR_RETURN_IF_NOT(pEncData->nDataStatus == DENC_DATA_STATUS_UNINITIALIZED || pEncData->nDataStatus == DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED, ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS) if(pEncData->nDataStatus == DENC_DATA_STATUS_UNINITIALIZED) pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED; return ddocMemAppendData(&(pEncData->mbufEncryptedData), data, len); } //-------------------------------------------------- // Mutatoror for Id atribute of EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetEncryptionPropertiesId(DEncEncryptedData* pEncData, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncData->encProperties.szId), value); return err; } //-------------------------------------------------- // Deletes EncryptionProperties subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nIdx - index of EncryptionProperty object to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_DeleteEncryptionProperty(DEncEncryptedData* pEncData, int nIdx) { int err = ERR_OK, i; RETURN_IF_NULL_PARAM(pEncData) SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->encProperties.nEncryptionProperties, ERR_DENC_BAD_PROP_IDX, ERR_DENC_BAD_PROP_IDX); RETURN_IF_NULL_PARAM(pEncData->encProperties.arrEncryptionProperties[nIdx]); // delete the given object err = dencEncryptionProperty_free(pEncData->encProperties.arrEncryptionProperties[nIdx]); if(err) return err; pEncData->encProperties.arrEncryptionProperties[nIdx] = 0; // move other objects 1 step close to array start for(i = nIdx; i < pEncData->encProperties.nEncryptionProperties-1; i++) pEncData->encProperties.arrEncryptionProperties[i] = pEncData->encProperties.arrEncryptionProperties[i+1]; pEncData->encProperties.arrEncryptionProperties[pEncData->encProperties.nEncryptionProperties - 1] = 0; pEncData->encProperties.nEncryptionProperties--; return err; } //-------------------------------------------------- // Deletes EncryptedKey subelement of DEncEncryptedData object. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nIdx - index of EncryptedKey object to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_DeleteEncryptedKey(DEncEncryptedData* pEncData, int nIdx) { int err = ERR_OK, i; RETURN_IF_NULL_PARAM(pEncData) SET_LAST_ERROR_RETURN_IF_NOT(nIdx >= 0 && nIdx < pEncData->nEncryptedKeys, ERR_DENC_BAD_KEY_IDX, ERR_DENC_BAD_KEY_IDX); RETURN_IF_NULL_PARAM(pEncData->arrEncryptedKeys[nIdx]); // delete the given object err = dencEncryptedKey_free(pEncData->arrEncryptedKeys[nIdx]); if(err) return err; pEncData->arrEncryptedKeys[nIdx] = 0; // move other objects 1 step closer to array start for(i = nIdx; i < pEncData->nEncryptedKeys-1; i++) pEncData->arrEncryptedKeys[i] = pEncData->arrEncryptedKeys[i+1]; pEncData->arrEncryptedKeys[pEncData->nEncryptedKeys - 1] = 0; pEncData->nEncryptedKeys--; return err; } //-------------------------------------------------- // Mutatoror for Id atribute of DEncEncryptedData object. // Sets the default value - "ED0" // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetId_default(DEncEncryptedData* pEncData) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncData) err = ddocMemAssignString((char**)&(pEncData->szId), "ED0"); return err; } //-------------------------------------------------- // Mutatoror for Type atribute of DEncEncryptedData object. // Sets the default value - "http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd" // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_SetType_default(DEncEncryptedData* pEncData) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncData) err = ddocMemAssignString((char**)&(pEncData->szType), DENC_ENCDATA_TYPE_DDOC); return err; } //======================< DEncEncryptionProperty >=================== //-------------------------------------------------- // "Constructor" for EncryptionProperty // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncProperty - address of buffer for new property object [REQUIRED] // szId - Id atribute of EncryptionProperty [OPTIONAL] // szTarget - Target atribute of EncryptionProperty [OPTIONAL] // szName - name atribute of EncryptionProperty [OPTIONAL] // szContent - content of EncryptionProperty [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_new(DEncEncryptedData* pEncData, DEncEncryptionProperty** ppEncProperty, const char* szId, const char* szTarget, const char* szName, const char* szContent) { int err = ERR_OK, nProps; DEncEncryptionProperty **pProps, *pProp; // check parameters RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(ppEncProperty) *ppEncProperty = 0; // mark as not yet allocated // allocate memory for pointer array nProps = pEncData->encProperties.nEncryptionProperties + 1; pProps = (DEncEncryptionProperty **)realloc(pEncData->encProperties.arrEncryptionProperties, sizeof(DEncEncryptionProperty *) * nProps); if(!pProps) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) pEncData->encProperties.arrEncryptionProperties = pProps; pProps[pEncData->encProperties.nEncryptionProperties] = 0; // allocate memory for new property pProp = (DEncEncryptionProperty*)malloc(sizeof(DEncEncryptionProperty)); if(!pProp) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memset(pProp, 0, sizeof(DEncEncryptionProperty)); pProps[pEncData->encProperties.nEncryptionProperties] = pProp; *ppEncProperty = pProp; pEncData->encProperties.nEncryptionProperties = nProps; // set data if(szId) { err = ddocMemAssignString((char**)&(pProp->szId), szId); if(err) return err; } if(szTarget) { err = ddocMemAssignString((char**)&(pProp->szTarget), szTarget); if(err) return err; } if(szName) { err = ddocMemAssignString((char**)&(pProp->szName), szName); if(err) return err; } if(szContent) { err = ddocMemAssignString((char**)&(pProp->szContent), szContent); if(err) return err; } return err; } //-------------------------------------------------- // "Destructor" for EncryptionProperty // pEncProperty - address of buffer for new property object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_free(DEncEncryptionProperty* pEncProperty) { RETURN_IF_NULL_PARAM(pEncProperty) if(pEncProperty->szId) free(pEncProperty->szId); if(pEncProperty->szTarget) free(pEncProperty->szTarget); if(pEncProperty->szName) free(pEncProperty->szName); if(pEncProperty->szContent) free(pEncProperty->szContent); free(pEncProperty); return ERR_OK; } //======================< DEncEncryptionProperty - accessors >=================== //-------------------------------------------------- // Accessor for Id atribute of EncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptionProperty_GetId(DEncEncryptionProperty* pEncProp) { RETURN_OBJ_IF_NULL(pEncProp, NULL) return pEncProp->szId; } //-------------------------------------------------- // Accessor for Target atribute of EncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptionProperty_GetTarget(DEncEncryptionProperty* pEncProp) { RETURN_OBJ_IF_NULL(pEncProp, NULL) return pEncProp->szTarget; } //-------------------------------------------------- // Accessor for Name atribute of EncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptionProperty_GetName(DEncEncryptionProperty* pEncProp) { RETURN_OBJ_IF_NULL(pEncProp, NULL) return pEncProp->szName; } //-------------------------------------------------- // Accessor for content of EncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptionProperty_GetContent(DEncEncryptionProperty* pEncProp) { RETURN_OBJ_IF_NULL(pEncProp, NULL) return pEncProp->szContent; } //======================< DEncEncryptionProperty - mutators >=================== //-------------------------------------------------- // Mutatoror for Id atribute of DEncEncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_SetId(DEncEncryptionProperty* pEncProp, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncProp) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncProp->szId), value); return err; } //-------------------------------------------------- // Mutatoror for Target atribute of DEncEncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_SetTarget(DEncEncryptionProperty* pEncProp, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncProp) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncProp->szTarget), value); return err; } //-------------------------------------------------- // Mutatoror for Name atribute of DEncEncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_SetName(DEncEncryptionProperty* pEncProp, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncProp) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncProp->szName), value); return err; } //-------------------------------------------------- // Mutatoror for content of DEncEncryptionProperty object. // pEncProp - pointer to DEncEncryptionProperty object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptionProperty_SetContent(DEncEncryptionProperty* pEncProp, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncProp) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncProp->szContent), value); return err; } //======================< DEncEncryptedKey >=================== //-------------------------------------------------- // Initializes transport key and init vector. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- int dencEncryptedData_initTransportKey(DEncEncryptedData* pEncData) { int err = ERR_OK, l1; char salt[8], indata[128], key[16]; RETURN_IF_NULL_PARAM(pEncData) // init random generator #ifdef WIN32 RAND_screen(); RAND_bytes((unsigned char*)salt, sizeof(salt)); RAND_bytes((unsigned char*)indata, sizeof(indata)); RAND_bytes((unsigned char*)pEncData->initVector, sizeof(pEncData->initVector)); #else if((l1 = RAND_load_file("/dev/urandom", 1024)) > 0) { ddocDebug(4, "dencEncryptedData_initTransportKey", "rand load: %d", l1); RAND_bytes((unsigned char*)salt, sizeof(salt)); RAND_bytes((unsigned char*)indata, sizeof(indata)); RAND_bytes((unsigned char*)pEncData->initVector, sizeof(pEncData->initVector)); } #endif // intialize IV memset(key, 0, sizeof(key)); l1 = EVP_BytesToKey(EVP_aes_128_cbc(), EVP_md5(), (const unsigned char*)salt, (const unsigned char*)indata, sizeof(indata), 1, (unsigned char*)key, NULL); ddocDebug(3, "dencEncryptedData_initTransportKey", "BytesToKey: %d", l1); err = ddocMemAssignData(&(pEncData->mbufTransportKey), key, sizeof(key)); if(err) return err; ddocDebug(3, "dencEncryptedData_initTransportKey", "RC: %d key: %d", l1, pEncData->mbufTransportKey.nLen); pEncData->nKeyStatus = DENC_KEY_STATUS_INITIALIZED; return err; } //-------------------------------------------------- // Validates the parameter. We // currently support only RSA-1.5 // szEncMethod - value to be checked // returns error code or ERR_OK //-------------------------------------------------- int dencEncKeyValidateEncMethod(const char* szEncMethod) { if(szEncMethod && strcmp(szEncMethod, DENC_ENC_METHOD_RSA1_5)) SET_LAST_ERROR_RETURN(ERR_DENC_ENC_METHOD, ERR_DENC_ENC_METHOD) else return ERR_OK; } //-------------------------------------------------- // Encrypts data with RSA public key (receivers key?) // pCert - receivers certificate // data - input data // dLen - input data length // result - encrypted data // resLen - output buffer length / used bytes //-------------------------------------------------- int dencEncryptWithCert(X509* pCert, const char* data, int dLen, char* result, int* resLen) { int err = ERR_OK; EVP_PKEY* pkey; RSA *rsa; // check parameters RETURN_IF_NULL_PARAM(pCert) RETURN_IF_NULL_PARAM(data) RETURN_IF_NULL_PARAM(result) RETURN_IF_NULL_PARAM(resLen) // get certificates public key err = GetPublicKey(&pkey, pCert); if(err) return err; // encrypt data memset((char*)result, 0, *resLen); rsa = EVP_PKEY_get1_RSA(pkey); *resLen = RSA_public_encrypt(dLen, (const unsigned char*)data, (unsigned char*)result, rsa, RSA_PKCS1_PADDING); RSA_free(rsa); // cleanup EVP_PKEY_free(pkey); // should I ??? return err; } //-------------------------------------------------- // "Constructor" for EncryptedKey // Encrypts the transport key for a receiver // and stores encrypted key in memory // Call this function repeatedly for all receivers, // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncKey - address of buffer for new encrypted key object [REQUIRED] // pCert - recevers certificate [REQUIRED] // szEncMethod - encryption method [REQUIRED] // szId - Id atribute of EncryptedKey [OPTIONAL] // szRecipient - Recipient atribute of EncryptedKey [OPTIONAL] // szKeyName - KeyName subelement of EncryptedKey [OPTIONAL] // szCarriedKeyName - CarriedKeyName subelement of EncryptedKey [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_new(DEncEncryptedData* pEncData, DEncEncryptedKey** pEncKey, X509* pCert, const char* szEncMethod, const char* szId, const char* szRecipient, const char* szKeyName, const char* szCarriedKeyName) { int err = ERR_OK, nKeys, l1; DEncEncryptedKey **pKeys, *pKey; //AM 14.10.08 from 130 to 300 char tkey[300]; ddocDebug(3, "dencEncryptedKey_new", "cert: %s, method: %s, id: %s, recipient: %s, keyname: %s carriedkeyname: %s", (pCert ? "OK" : "NULL"), szEncMethod, szId, szRecipient, szKeyName, szCarriedKeyName); // check parameters RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(pEncKey) err = dencEncKeyValidateEncMethod(szEncMethod); if(err) return err; *pEncKey = 0; // increase the buffer for EncryptedKey pointers nKeys = pEncData->nEncryptedKeys + 1; pKeys = (DEncEncryptedKey **)realloc(pEncData->arrEncryptedKeys, sizeof(DEncEncryptedKey *) * nKeys); if(!pKeys) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) pEncData->arrEncryptedKeys = pKeys; pEncData->arrEncryptedKeys[pEncData->nEncryptedKeys] = 0; pKey = (DEncEncryptedKey*)malloc(sizeof(DEncEncryptedKey)); if(!pKey) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) pEncData->arrEncryptedKeys[pEncData->nEncryptedKeys] = pKey; pEncData->nEncryptedKeys = nKeys; *pEncKey = pKey; memset(pKey, 0, sizeof(DEncEncryptedKey)); // set required parameters if(szEncMethod) { err = ddocMemAssignString((char**)&(pKey->szEncryptionMethod), szEncMethod); if(err) return err; } if(pCert) { if(!ddocCertCheckKeyUsage(pCert, KUIDX_KEY_ENCIPHERMENT)) { ddocDebug(1, "dencEncryptedKey_new", "ENC: cert has no key-encipherment key usage"); SET_LAST_ERROR(ERR_CERT_INVALID); return ERR_CERT_INVALID; } else ddocDebug(3, "dencEncryptedKey_new", "ENC: cert has key-encipherment key usage"); pKey->pCert = pCert; } // set optional parameters if(szId) { err = ddocMemAssignString((char**)&(pKey->szId), szId); if(err) return err; } if(szRecipient) { err = ddocMemAssignString((char**)&(pKey->szRecipient), szRecipient); if(err) return err; } if(szKeyName) { err = ddocMemAssignString((char**)&(pKey->szKeyName), szKeyName); if(err) return err; } if(szCarriedKeyName) { err = ddocMemAssignString((char**)&(pKey->szCarriedKeyName), szCarriedKeyName); if(err) return err; } if(pCert) { // encrypt the key if(pEncData->nKeyStatus == DENC_KEY_STATUS_UNINITIALIZED) { err = dencEncryptedData_initTransportKey(pEncData); if(err) return err; } l1 = sizeof(tkey); err = dencEncryptWithCert(pCert, (const char*)pEncData->mbufTransportKey.pMem, pEncData->mbufTransportKey.nLen, tkey, &l1); if(err) return err; //if(pKey)dencEncryptedKey_/free(&pKey); //pKey = (DEncEncryptedKey*)malloc(sizeof(DEncEncryptedKey)); //memset(pKey, 0, sizeof(DEncEncryptedKey)); err = ddocMemAssignData(&(pKey->mbufTransportKey), tkey, l1); } return err; } //-------------------------------------------------- // "Destructor" for EncryptedKey // pEncKey - address of buffer for new encrypted key object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_free(DEncEncryptedKey* pEncKey) { RETURN_IF_NULL_PARAM(pEncKey) if(pEncKey->szId) free(pEncKey->szId); if(pEncKey->szRecipient) free(pEncKey->szRecipient); if(pEncKey->szEncryptionMethod) free(pEncKey->szEncryptionMethod); if(pEncKey->szKeyName) free(pEncKey->szKeyName); if(pEncKey->szCarriedKeyName) free(pEncKey->szCarriedKeyName); if(pEncKey->pCert) X509_free(pEncKey->pCert); ddocMemBuf_free(&(pEncKey->mbufTransportKey)); free(pEncKey); return ERR_OK; } //======================< DEncEncryptedKey - acessors >=================== //-------------------------------------------------- // Accessor for Id atribute of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetId(DEncEncryptedKey* pEncKey) { RETURN_OBJ_IF_NULL(pEncKey, NULL) return pEncKey->szId; } //-------------------------------------------------- // Accessor for Recipient atribute of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetRecipient(DEncEncryptedKey* pEncKey) { RETURN_OBJ_IF_NULL(pEncKey, NULL) return pEncKey->szRecipient; } //-------------------------------------------------- // Accessor for EncryptionMethod subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetEncryptionMethod(DEncEncryptedKey* pEncKey) { RETURN_OBJ_IF_NULL(pEncKey, NULL) return pEncKey->szEncryptionMethod; } //-------------------------------------------------- // Accessor for KeyName subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetKeyName(DEncEncryptedKey* pEncKey) { RETURN_OBJ_IF_NULL(pEncKey, NULL) return pEncKey->szKeyName; } //-------------------------------------------------- // Accessor for CarriedKeyName subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION const char* dencEncryptedKey_GetCarriedKeyName(DEncEncryptedKey* pEncKey) { RETURN_OBJ_IF_NULL(pEncKey, NULL) return pEncKey->szCarriedKeyName; } //-------------------------------------------------- // Accessor for certificate of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // returns value of atribute or NULL. //-------------------------------------------------- EXP_OPTION X509* dencEncryptedKey_GetCertificate(DEncEncryptedKey* pEncKey) { RETURN_OBJ_IF_NULL(pEncKey, NULL) return pEncKey->pCert; } //======================< DEncEncryptedKey - mutators >=================== //-------------------------------------------------- // Mutatoror for Id atribute of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetId(DEncEncryptedKey* pEncKey, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncKey) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncKey->szId), value); return err; } //-------------------------------------------------- // Mutatoror for Recipient atribute of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetRecipient(DEncEncryptedKey* pEncKey, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncKey) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncKey->szRecipient), value); return err; } //-------------------------------------------------- // Mutatoror for EncryptionMethod subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetEncryptionMethod(DEncEncryptedKey* pEncKey, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncKey) RETURN_IF_NULL_PARAM(value) err = dencEncKeyValidateEncMethod(value); if(err) return err; err = ddocMemAssignString((char**)&(pEncKey->szEncryptionMethod), value); return err; } //-------------------------------------------------- // Mutatoror for KeyName subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetKeyName(DEncEncryptedKey* pEncKey, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncKey) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncKey->szKeyName), value); return err; } //-------------------------------------------------- // Mutatoror for CarriedKeyName subelement of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetCarriedKeyName(DEncEncryptedKey* pEncKey, const char* value) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pEncKey) RETURN_IF_NULL_PARAM(value) err = ddocMemAssignString((char**)&(pEncKey->szCarriedKeyName), value); return err; } //-------------------------------------------------- // Mutatoror for certificate of DEncEncryptedKey object. // pEncKey - pointer to DEncEncryptedKey object [REQUIRED] // value - new value for atribute [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedKey_SetCertificate(DEncEncryptedKey* pEncKey, X509* value) { RETURN_IF_NULL_PARAM(pEncKey) RETURN_IF_NULL_PARAM(value) pEncKey->pCert = value; return ERR_OK; } //==========< general crypto fucntions >============ //-------------------------------------------------- // Locates the correct EncryptedKey object by reading // users certificate from smartcard and searching the // right EncryptedKey object // pEncData - pointer to DEncEncryptedData object [REQUIRED] // ppEncKey - address of a buffer for EncryptedKey pointer [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_findEncryptedKeyByPKCS11(DEncEncryptedData* pEncData, DEncEncryptedKey** ppEncKey) { return dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot(pEncData, ppEncKey, 0); } //-------------------------------------------------- // Locates the correct EncryptedKey object by reading // users certificate from smartcard and searching the // right EncryptedKey object // pEncData - pointer to DEncEncryptedData object [REQUIRED] // ppEncKey - address of a buffer for EncryptedKey pointer [REQUIRED] // nSlot - slot nr // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot(DEncEncryptedData* pEncData, DEncEncryptedKey** ppEncKey, int nSlot) { int err = ERR_OK, i, n; X509 *pCert = 0; DEncEncryptedKey *pEncKey = 0; char buf1[100], buf2[100]; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(ppEncKey) *ppEncKey = 0; // mark as not found yet err = findUsersCertificate(nSlot, &pCert); if(err) return err; memset(buf1, 0, sizeof(buf1)); err = ReadCertSerialNumber(buf1, sizeof(buf1), pCert); if(err) return err; ddocDebug(3, "dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot", "Users cert: %s", buf1); n = dencEncryptedData_GetEncryptedKeyCount(pEncData); for(i = 0; i < n; i++) { pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i); memset(buf2, 0, sizeof(buf2)); err = ReadCertSerialNumber(buf2, sizeof(buf2), pEncKey->pCert); ddocDebug(3, "dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot", "Key: %d cert: %s", i, buf2); if(!err && !strcmp(buf1, buf2)) { *ppEncKey = pEncKey; ddocDebug(3, "dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot", "Using key: %d cert: %s", i, buf2); break; } } if(pCert) X509_free(pCert); if(!*ppEncKey) { ddocDebug(3, "dencEncryptedData_findEncryptedKeyByPKCS11UsingSlot", "No matching key found!"); SET_LAST_ERROR_RETURN(ERR_DENC_NO_KEY_FOUND, ERR_DENC_NO_KEY_FOUND) } return err; } //-------------------------------------------------- // Locates the correct EncryptedKey object by reading // users certificate and private key from pkcs12 file and searching the // right EncryptedKey object // pEncData - pointer to DEncEncryptedData object [REQUIRED] // ppEncKey - address of a buffer for EncryptedKey pointer [REQUIRED] // ppKey - address of private key pointer. Caller must free [REQUIRED] // szPkcs12File - pkcs12 file name [REQUIRED] // szPasswd - pkcs12 file password [REQUIRED]. Might be empty? // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_findEncryptedKeyByPKCS12(DEncEncryptedData* pEncData, DEncEncryptedKey** ppEncKey, EVP_PKEY** ppKey, const char* szPkcs12File, const char* szPasswd) { int err = ERR_OK, i, n; X509 *pCert = 0; DEncEncryptedKey *pEncKey = 0; char buf1[100], buf2[100]; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(ppEncKey) RETURN_IF_NULL_PARAM(ppKey) *ppEncKey = 0; // mark as not found yet *ppKey = 0; err = ReadCertificateByPKCS12(&pCert, szPkcs12File, szPasswd, ppKey); if(err) return err; memset(buf1, 0, sizeof(buf1)); err = ReadCertSerialNumber(buf1, sizeof(buf1), pCert); if(err) return err; n = dencEncryptedData_GetEncryptedKeyCount(pEncData); for(i = 0; i < n; i++) { pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i); memset(buf2, 0, sizeof(buf2)); err = ReadCertSerialNumber(buf2, sizeof(buf2), pEncKey->pCert); if(!err && !strcmp(buf1, buf2)) { *ppEncKey = pEncKey; break; } } if(pCert) X509_free(pCert); if(!*ppEncKey) SET_LAST_ERROR_RETURN(ERR_DENC_NO_KEY_FOUND, ERR_DENC_NO_KEY_FOUND) return err; } //-------------------------------------------------- // AES encrypt/decrypt operations // pInData - input data // pOutData - output buffer // pKey - AES key // operation - ENCRYPT/DECRYPT // iv - init vector for the cipher //-------------------------------------------------- int encryptDecrypt(DigiDocMemBuf *pInData, DigiDocMemBuf *pOutData, DigiDocMemBuf *pKey, int operation, const char* iv) { EVP_CIPHER_CTX *ectx; int err = ERR_OK, len, i, nInLen, nOutLen; char padBuf[16], *pInMem; int lOrigLen, lEncLen; ddocDebug(3, "encryptDecrypt", "Input: %d, output: %d, key: %d, operation: %s", (pInData ? pInData->nLen : 0), (pOutData ? pOutData->nLen : 0), (pKey ? pKey->nLen : 0), (operation ? "ENCRYPT" : "DECRYPT")); RETURN_IF_NULL_PARAM(pInData) RETURN_IF_NULL_PARAM(pOutData) RETURN_IF_NULL_PARAM(pKey) nInLen = pInData->nLen; pInMem = (char*)pInData->pMem; // use the first 16 bytes as IV // and remove this data from data to be decrypted if(operation == DECRYPT) { memcpy((char*)iv, (const char*)pInData->pMem, 16); for(i = 0; i < 16; i++) ddocDebug(3, "encryptDecrypt", "IV pos: %d = %d", i, iv[i]); nInLen -= 16; pInMem += 16; ddocDebug(3, "encryptDecrypt", "DECRYPT using iv input left: %d", nInLen); } lOrigLen = lEncLen = 0; len = nInLen % 16; if(operation == ENCRYPT) { len = 16 - (nInLen % 16); ddocDebug(3, "encryptDecrypt", "Input len: %d adding padding: %d\n", nInLen, len); memset(padBuf, 0, sizeof(padBuf)); for(i = 0; i < len; i++) padBuf[i] = 0; padBuf[len-1] = (unsigned char)len; // number of padded chars } if(pOutData->pMem) free(pOutData->pMem); pOutData->nLen = nInLen * 2 + len * 2; if(operation == ENCRYPT) pOutData->nLen += 16; nOutLen = pOutData->nLen; pOutData->pMem = (char*)malloc(pOutData->nLen); memset(pOutData->pMem, 0, pOutData->nLen); if(!pOutData->pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) ddocDebug(3, "encryptDecrypt", "Allocated: %d", pOutData->nLen); // copy init vector to begin of output data if(operation == ENCRYPT) memcpy(pOutData->pMem, iv, 16); ectx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ectx); EVP_CipherInit_ex(ectx, EVP_aes_128_cbc(), NULL, (const unsigned char*)pKey->pMem, (const unsigned char*)iv, operation); //EVP_CIPHER_CTX_set_padding(&ectx, 1); //checkErrors(); lOrigLen += nInLen; i = nOutLen; // set initial position for encryted data if(operation == ENCRYPT) pOutData->nLen = 16; else pOutData->nLen = 0; EVP_CipherUpdate(ectx, (unsigned char*)pOutData->pMem + pOutData->nLen, &i, (const unsigned char*)pInMem, nInLen); lEncLen += i; pOutData->nLen += i; ddocDebug(3, "encryptDecrypt", "Initial update: %d into: %d -> %d", nInLen, nOutLen, i); //TODO: in 1.1 don't check len if(len && operation == ENCRYPT) { EVP_CipherUpdate(ectx, (unsigned char*)pOutData->pMem + pOutData->nLen, &i, (const unsigned char*)padBuf, len); ddocDebug(3, "encryptDecrypt", "Padding update: %d -> %d", len, i); pOutData->nLen += i; lOrigLen += len; nOutLen -= i; lEncLen += i; } i = nOutLen; EVP_CipherFinal_ex(ectx, (unsigned char*)pOutData->pMem + pOutData->nLen, &i); ddocDebug(3, "encryptDecrypt", "Final update: %d into: %d", i, nOutLen); pOutData->nLen += i; lEncLen += i; ddocDebug(3, "encryptDecrypt", "Total input: %d encrypted: %d", lOrigLen, lEncLen); EVP_CIPHER_CTX_free(ectx); if(operation == DECRYPT) { // check ANSI X.923 padding len = (int)(unsigned char)((char*)pOutData->pMem)[pOutData->nLen-1]; if(len > 0 && len <= 16) { ddocDebug(3, "encryptDecrypt", "X.923 check padding: %d", len); // check if all previous are 0-s for(i = pOutData->nLen - len; i < pOutData->nLen - 1; i++) { ddocDebug(3, "encryptDecrypt", "Byte at: %d = %d", i, ((char*)pOutData->pMem)[i]); if(((char*)pOutData->pMem)[i]) len = 0; // set not matched flag } if(len >= 1) { ddocDebug(3, "encryptDecrypt", "X.923 decrypted len: %d reduce by: %d", pOutData->nLen, len); pOutData->nLen -= len; } else ddocDebug(3, "encryptDecrypt", "X.923 decrypted len remains: %d", pOutData->nLen); } else ddocDebug(3, "encryptDecrypt", "Impossible padding: %d", len); } return err; } //-------------------------------------------------- // Encrypts data with the generated key // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nCompressOption - flag: DENC_COMPRESS_ALLWAYS, // DENC_COMPRESS_NEVER or DENC_COMPRESS_BEST_EFFORT // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_encryptData(DEncEncryptedData* pEncData, int nCompressOption) { int err = ERR_OK; DigiDocMemBuf outData; RETURN_IF_NULL_PARAM(pEncData) // check compression if(nCompressOption == DENC_COMPRESS_ALLWAYS || nCompressOption == DENC_COMPRESS_BEST_EFFORT) { err = dencEncryptedData_compressData(pEncData, nCompressOption); if(err) return err; } // check data status if(pEncData->nDataStatus != DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED && pEncData->nDataStatus != DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED) SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS) // init transport key if necessary if(pEncData->nKeyStatus == DENC_KEY_STATUS_UNINITIALIZED) { err = dencEncryptedData_initTransportKey(pEncData); if(err) return err; } outData.pMem = 0; outData.nLen = 0; err = encryptDecrypt(&(pEncData->mbufEncryptedData), &outData, &(pEncData->mbufTransportKey), ENCRYPT, pEncData->initVector); if(!err) { free(pEncData->mbufEncryptedData.pMem); pEncData->mbufEncryptedData.pMem = outData.pMem; pEncData->mbufEncryptedData.nLen = outData.nLen; // check if we have original length in if(pEncData->nDataStatus == DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED) pEncData->nDataStatus = DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED; else pEncData->nDataStatus = DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED; } return err; } //-------------------------------------------------- // Decrypts data with the generated key // pEncData - pointer to DEncEncryptedData object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decryptData(DEncEncryptedData* pEncData) { int err = ERR_OK; DigiDocMemBuf outData; RETURN_IF_NULL_PARAM(pEncData) // check data status if(pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED && pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED) SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS) // check transport key if(pEncData->nKeyStatus == DENC_KEY_STATUS_UNINITIALIZED) SET_LAST_ERROR_RETURN(ERR_DENC_KEY_STATUS, ERR_DENC_KEY_STATUS) outData.pMem = 0; outData.nLen = 0; err = encryptDecrypt(&(pEncData->mbufEncryptedData), &outData, &(pEncData->mbufTransportKey), DECRYPT, pEncData->initVector); if(!err) { free(pEncData->mbufEncryptedData.pMem); pEncData->mbufEncryptedData.pMem = outData.pMem; pEncData->mbufEncryptedData.nLen = outData.nLen; if(pEncData->nDataStatus == DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED) pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED; else pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED; } // decompress if necessary if(!err && pEncData->nDataStatus == DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED) err = dencEncryptedData_decompressData(pEncData); return err; } //-------------------------------------------------- // Decrypts data transport key with ID card and // then decrypts the data with the transport key. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncKey - transport key to decrypt [REQUIRED] // pin - pin code for smart card [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decrypt(DEncEncryptedData* pEncData, DEncEncryptedKey* pEncKey, const char* pin) { int nSlot = nSlot = ConfigItem_lookup_int("DIGIDOC_AUTH_KEY_SLOT", 0); return dencEncryptedData_decryptUsingSlot(pEncData, pEncKey, pin, nSlot); } //-------------------------------------------------- // Decrypts data transport key with ID card and // then decrypts the data with the transport key. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncKey - transport key to decrypt [REQUIRED] // pin - pin code for smart card [REQUIRED] // nSlot - slot nr // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decryptUsingSlot(DEncEncryptedData* pEncData, DEncEncryptedKey* pEncKey, const char* pin, int nSlot) { int err = ERR_OK, len; DEncEncryptionProperty* pEncProp; long l; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(pEncKey) RETURN_IF_NULL_PARAM(pin) // check data status if(pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED && pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED) SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS) pEncData->nKeyStatus = DENC_KEY_STATUS_UNINITIALIZED; // it will shrink during decrypt so this is enough pEncData->mbufTransportKey.nLen = pEncKey->mbufTransportKey.nLen; pEncData->mbufTransportKey.pMem = (char*)malloc(pEncData->mbufTransportKey.nLen); if(!pEncData->mbufTransportKey.pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) ddocDebug(3, "dencEncryptedData_decrypt", "Decrypt enckey: %d into: %d", pEncKey->mbufTransportKey.nLen, pEncData->mbufTransportKey.nLen); len = pEncData->mbufTransportKey.nLen; err = decryptWithEstID(nSlot, pin, (const char*)pEncKey->mbufTransportKey.pMem, pEncKey->mbufTransportKey.nLen, (char*)pEncData->mbufTransportKey.pMem, &len); pEncData->mbufTransportKey.nLen = len; if(err) return err; pEncData->nKeyStatus = DENC_KEY_STATUS_INITIALIZED; err = dencEncryptedData_decryptData(pEncData); /*pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_SIZE); if(pEncProp && pEncProp->szContent) { l = atol(pEncProp->szContent); if(l > 0 && l < pEncData->mbufEncryptedData.nLen) { ddocDebug(4, "dencEncryptedData_decrypt", "Truncating decrypted data: %d to: %d", pEncData->mbufEncryptedData.nLen, l); pEncData->mbufEncryptedData.nLen = l; } }*/ return err; } //-------------------------------------------------- // Decrypts data transport key with ID card and // then decrypts the data with the transport key. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // pEncKey - transport key to decrypt [REQUIRED] // pKey - private key for decrypting [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decryptWithKey(DEncEncryptedData* pEncData, DEncEncryptedKey* pEncKey, EVP_PKEY* pKey) { int err = ERR_OK, len; DEncEncryptionProperty* pEncProp; long l; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(pEncKey) RETURN_IF_NULL_PARAM(pKey) // check data status if(pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED && pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED) SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS) pEncData->nKeyStatus = DENC_KEY_STATUS_UNINITIALIZED; // it will shrink during decrypt so this is enough pEncData->mbufTransportKey.nLen = pEncKey->mbufTransportKey.nLen; pEncData->mbufTransportKey.pMem = (char*)malloc(pEncData->mbufTransportKey.nLen); if(!pEncData->mbufTransportKey.pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) ddocDebug(3, "dencEncryptedData_decryptWithKey", "Decrypt enckey: %d into: %d", pEncKey->mbufTransportKey.nLen, pEncData->mbufTransportKey.nLen); #if OPENSSL_VERSION_NUMBER > 0x10000000 len = EVP_PKEY_decrypt_old((unsigned char *)pEncData->mbufTransportKey.pMem, (const unsigned char*)pEncKey->mbufTransportKey.pMem, pEncKey->mbufTransportKey.nLen, pKey); #else len = EVP_PKEY_decrypt((unsigned char *)pEncData->mbufTransportKey.pMem, (const unsigned char*)pEncKey->mbufTransportKey.pMem, pEncKey->mbufTransportKey.nLen, pKey); #endif ddocDebug(3, "dencEncryptedData_decryptWithKey", "Decrypt rv: %d len: %l", err, len); pEncData->mbufTransportKey.nLen = len; if(len != 16) return ERR_DENC_DECRYPT; else err = ERR_OK; pEncData->nKeyStatus = DENC_KEY_STATUS_INITIALIZED; err = dencEncryptedData_decryptData(pEncData); pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_SIZE); if(pEncProp && pEncProp->szContent) { l = atol(pEncProp->szContent); if(l > 0 && l < pEncData->mbufEncryptedData.nLen) { ddocDebug(4, "dencEncryptedData_decrypt", "Truncating decrypted data: %d to: %d", pEncData->mbufEncryptedData.nLen, l); pEncData->mbufEncryptedData.nLen = l; } } return err; } //-------------------------------------------------- // Decrypts data transport key with ID card and // then decrypts the data with the transport key. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // tKey - decrypted transport key [REQUIRED] // keyLen - length of trasnport key [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decrypt_withKey(DEncEncryptedData* pEncData, const char* tKey, int keyLen) { int err = ERR_OK; DEncEncryptionProperty* pEncProp; long l; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(tKey) // check data status if(pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED && pEncData->nDataStatus != DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED) SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS) pEncData->mbufTransportKey.nLen = keyLen; pEncData->mbufTransportKey.pMem = (char*)malloc(pEncData->mbufTransportKey.nLen); if(!pEncData->mbufTransportKey.pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) memcpy(pEncData->mbufTransportKey.pMem, tKey, keyLen); ddocDebug(4, "dencEncryptedData_decrypt_withKey", "Decrypt enckey: %d into: %d", keyLen, pEncData->mbufTransportKey.nLen); pEncData->nKeyStatus = DENC_KEY_STATUS_INITIALIZED; err = dencEncryptedData_decryptData(pEncData); pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_SIZE); if(pEncProp && pEncProp->szContent) { l = atol(pEncProp->szContent); if(l > 0 && l < pEncData->mbufEncryptedData.nLen) { ddocDebug(4, "dencEncryptedData_decrypt_withKey", "Truncating decrypted data: %d to: %d", pEncData->mbufEncryptedData.nLen, l); pEncData->mbufEncryptedData.nLen = l; } } return err; } //-------------------------------------------------- // Compresses data with ZLIB. Cannot compress encrypted data!!! // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nCompressOption - flag: DENC_COMPRESS_ALLWAYS, // DENC_COMPRESS_NEVER or DENC_COMPRESS_BEST_EFFORT // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_compressData(DEncEncryptedData* pEncData, int nCompressOption) { int err = ERR_OK; DigiDocMemBuf outData; char buf[20]; DEncEncryptionProperty* pEncProperty; RETURN_IF_NULL_PARAM(pEncData) // check compress option RETURN_IF_NOT(nCompressOption == DENC_COMPRESS_ALLWAYS || nCompressOption == DENC_COMPRESS_BEST_EFFORT, ERR_COMPRESS) // check data status - cannot compress encrypted data!!! if(pEncData->nDataStatus != DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED) SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS) //AM 30.04.08 2048 instead of 1024 outData.nLen = pEncData->mbufEncryptedData.nLen + 2048; // it should get smaller outData.pMem = malloc(outData.nLen); if(!outData.pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) err = compress OF(( (Bytef *)outData.pMem, (uLongf *)&outData.nLen, (const Bytef *)pEncData->mbufEncryptedData.pMem, (uLong)pEncData->mbufEncryptedData.nLen)); ddocDebug(3, "dencEncryptedData_compressData", "Orig len: %d, compressed: %d, RC: %d", pEncData->mbufEncryptedData.nLen, outData.nLen, err); if(err != Z_OK) { free(outData.pMem); SET_LAST_ERROR_RETURN(ERR_COMPRESS, ERR_COMPRESS) } if(!err && ((nCompressOption == DENC_COMPRESS_ALLWAYS) || (nCompressOption == DENC_COMPRESS_BEST_EFFORT && outData.nLen < pEncData->mbufEncryptedData.nLen))) { snprintf(buf, sizeof(buf), "%d", (int)(pEncData->mbufEncryptedData.nLen)); err = dencEncryptionProperty_new(pEncData, &pEncProperty, NULL, NULL, ENCPROP_ORIG_SIZE, buf); free(pEncData->mbufEncryptedData.pMem); pEncData->mbufEncryptedData.pMem = outData.pMem; pEncData->mbufEncryptedData.nLen = outData.nLen; pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED; // store original mime type if(pEncData->szMimeType) { pEncProperty = 0; err = dencEncryptionProperty_new(pEncData, &pEncProperty, NULL, NULL, ENCPROP_ORIG_MIME, pEncData->szMimeType); free(pEncData->szMimeType); } pEncData->szMimeType = (char*)strdup(DENC_ENCDATA_MIME_ZLIB); } else free(outData.pMem); return err; } //-------------------------------------------------- // Decompresses data with ZLIB. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // nCompressOption - flag: DENC_COMPRESS_ALLWAYS, // DENC_COMPRESS_NEVER or DENC_COMPRESS_BEST_EFFORT // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptedData_decompressData(DEncEncryptedData* pEncData) { int err = ERR_OK; long origLen; DigiDocMemBuf outData; DEncEncryptionProperty* pEncProp; RETURN_IF_NULL_PARAM(pEncData) // check data status - cannot decompress encrypted data!!! if(pEncData->nDataStatus != DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED) SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS) // find original data size pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_SIZE); if(pEncProp && pEncProp->szContent) { origLen = atol(pEncProp->szContent); outData.nLen = (int)origLen; } else SET_LAST_ERROR_RETURN(ERR_DECOMPRESS, ERR_DECOMPRESS) outData.pMem = malloc(outData.nLen); if(!outData.pMem) SET_LAST_ERROR_RETURN(ERR_BAD_ALLOC, ERR_BAD_ALLOC) err = uncompress OF(( (Bytef *)outData.pMem, (uLongf *)&outData.nLen, (const Bytef *)pEncData->mbufEncryptedData.pMem, (uLong)pEncData->mbufEncryptedData.nLen)); ddocDebug(3, "dencEncryptedData_decompressData", "Compressed len: %d, orig-len: %ld, uncompressed: %d, RC: %d", pEncData->mbufEncryptedData.nLen, origLen, outData.nLen, err); if(err != Z_OK) { free(outData.pMem); SET_LAST_ERROR_RETURN(ERR_DECOMPRESS, ERR_DECOMPRESS) } if(!err) { free(pEncData->mbufEncryptedData.pMem); pEncData->mbufEncryptedData.pMem = outData.pMem; pEncData->mbufEncryptedData.nLen = outData.nLen; pEncData->nDataStatus = DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED; if(pEncData->szMimeType) free(pEncData->szMimeType); // restor original mime type ? pEncData->szMimeType = 0; // find original mime type pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_ORIG_MIME); if(pEncProp && pEncProp->szContent) pEncData->szMimeType = (char*)strdup(pEncProp->szContent); } else free(outData.pMem); return err; } //-------------------------------------------------- // Encrypts a file and writes it to output file // The caller must have initialized the transport keys // but not the data. // pEncData - pointer to DEncEncryptedData object [REQUIRED] // szInputFileName - input data name [REQUIRED] // szOutputFileName - output file name [REQUIRED] // szMimeType - input data mime type [OPTIONAL] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencEncryptFile(DEncEncryptedData* pEncData, const char* szInputFileName, const char* szOutputFileName, const char* szMimeType) { int err = ERR_OK, l1, l2, l3, i, nBlock; long lOrigLen, lEncSize, lWritten; EVP_CIPHER_CTX *ectx; EVP_ENCODE_CTX *bctx; char convInFileName[250], convOutFileName[250]; char buf1[4096], buf2[5120], buf3[6144], buf4[70], *p2; DigiDocMemBuf mbuf; FILE *hInFile, *hOutFile; DEncEncryptionProperty* pEncProperty; RETURN_IF_NULL_PARAM(pEncData) RETURN_IF_NULL_PARAM(szInputFileName) RETURN_IF_NULL_PARAM(szOutputFileName) ddocDebug(3, "dencEncryptFile", "In-file: %s, out-file: %s, key: %d", szInputFileName, szOutputFileName, pEncData->mbufTransportKey.nLen); // check data status - must be uninitialized since we will read it from file if(pEncData->nDataStatus != DENC_DATA_STATUS_UNINITIALIZED) SET_LAST_ERROR_RETURN(ERR_DENC_DATA_STATUS, ERR_DENC_DATA_STATUS) // check key status - must have been initialized already! if(pEncData->nKeyStatus == DENC_KEY_STATUS_UNINITIALIZED) SET_LAST_ERROR_RETURN(ERR_DENC_KEY_STATUS, ERR_DENC_KEY_STATUS) // convert filenames ddocConvertFileName( convInFileName, sizeof(convInFileName), szInputFileName ); ddocConvertFileName( convOutFileName, sizeof(convOutFileName), szOutputFileName ); if(strstr(szInputFileName, ".bdoc") || strstr(szInputFileName, ".asice")) err = dencEncryptedData_SetMimeType(pEncData, "application/vnd.etsi.asic-e+zip"); // TODO: compress the data // read and encrypt data memset(buf4, 0, sizeof(buf4)); nBlock = 0; if((hInFile = fopen(convInFileName, "rb")) != NULL) { if((hOutFile = fopen(convOutFileName, "wb")) != NULL) { // write header mbuf.pMem = 0; mbuf.nLen = 0; err = dencGenEncryptedData_header_toXML(pEncData, &mbuf); fwrite(mbuf.pMem, 1, mbuf.nLen, hOutFile); ddocMemBuf_free(&mbuf); // init encryption ectx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ectx); // init encoding bctx = EVP_ENCODE_CTX_new(); EVP_EncodeInit(bctx); EVP_CipherInit_ex(ectx, EVP_aes_128_cbc(), NULL, (const unsigned char*)pEncData->mbufTransportKey.pMem, (const unsigned char*)pEncData->initVector, ENCRYPT); //EVP_CIPHER_CTX_set_padding(&ectx, 1); lOrigLen = 0; lEncSize = 0; lWritten = 0; // read file & encrypt & write to output do { memset(buf1, 0, sizeof(buf1)); l1 = fread(buf1, 1, sizeof(buf1), hInFile); if(l1 > 0) { lOrigLen += l1; // padding for final block if(l1 != sizeof(buf1)) { l2 = 16 - (l1 % 16); ddocDebug(3, "dencEncryptFile", "Original %d padding: %d, new block: %d", l1, l2, l1+l2); for(i = 0; i < l2; i++) buf1[l1 + i] = 0; buf1[l1 + l2 - 1] = (unsigned char)l2; l1 += l2; } memset(buf2, 0, sizeof(buf2)); l2 = sizeof(buf2); p2 = buf2; // first block of encrypted data will contain // not encrypted IV vector in the first 16 bytes if(nBlock == 0) { memcpy(buf2, pEncData->initVector, 16); p2 += 16; l2 -= 16; } EVP_CipherUpdate(ectx, (unsigned char*)p2, &l2, (const unsigned char*)buf1, l1); ddocDebug(3, "dencEncryptFile", "Input: %d, block: %d, buf: %d encrypted: %d", l1, nBlock, sizeof(buf2), l2); lEncSize += l2; // if it's the final block if(l1 != sizeof(buf1)) { l3 = sizeof(buf2) - l2; p2 = buf2 + l2; if(nBlock == 0) { p2 += 16; l3 -= 16; } EVP_CipherFinal_ex(ectx, (unsigned char*)p2, &l3); ddocDebug(3, "dencEncryptFile", "Buf: %d Final encrypted: %d", sizeof(buf2) - l2, l3); l2 += l3; lEncSize += l3; } // base64 encode l3 = sizeof(buf3); memset(buf3, 0, l3); // encode also the IV vector at the beginning of first block if(nBlock == 0) l2 += 16; EVP_EncodeUpdate(bctx, (unsigned char*)buf3, &l3, (byte*)buf2, l2); lWritten += l3; fwrite(buf3, 1, l3, hOutFile); ddocDebug(3, "dencEncryptFile", "In: %d, encrypted: %d, base64: %d", l1, l2, l3); } nBlock++; } while(!err && l1 > 0); EVP_CIPHER_CTX_free(ectx); // write the last portion of line data l3 = sizeof(buf3); memset(buf3, 0, l3); EVP_EncodeFinal(bctx, (unsigned char*)buf3, &l3); EVP_ENCODE_CTX_free(bctx); lWritten += l3; fwrite(buf3, 1, l3, hOutFile); ddocDebug(4, "dencEncryptFile", "Total input: %d, blocks: %d, encrypted: %d written: %d", lOrigLen, nBlock, lEncSize, lWritten); // setup encryption properties snprintf(buf1, sizeof(buf1), "%ld", lOrigLen); pEncProperty = 0; err = dencEncryptionProperty_new(pEncData, &pEncProperty, NULL, NULL, ENCPROP_ORIG_SIZE, buf1); pEncProperty = 0; err = dencEncryptionProperty_new(pEncData, &pEncProperty, NULL, NULL, ENCPROP_FILENAME, szInputFileName); // write trailer mbuf.pMem = 0; mbuf.nLen = 0; err = dencGenEncryptedData_trailer_toXML(pEncData, &mbuf); fwrite(mbuf.pMem, 1, mbuf.nLen, hOutFile); ddocMemBuf_free(&mbuf); fclose(hOutFile); } else { SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); ddocDebug(1, "dencEncryptFile", "Error writing encrypted document: %s", convOutFileName); } fclose(hInFile); } else { SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); ddocDebug(1, "dencEncryptFile", "Error reading input from file: %s", convInFileName); } return err; } //====================< RecipientInfo functions >========================== //-------------------------------------------------- // "Constructor" of DEncRecvInfo object // ppRecvInfo - address of buffer for newly allocated object [REQUIRED] // szId - recipients id [REQUIRED] // szRecipient - recipient atribute [OPTIONAL] // szKeyName - KeyName element [OPTIONAL] // szCarriedKeyName - CarriedKeyName element [OPTIONAL] // pCert - certificate [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_new(DEncRecvInfo** ppRecvInfo, const char* szId, const char* szRecipient, const char* szKeyName, const char* szCarriedKeyName, const X509* pCert) { int err = ERR_OK; // check input parameters ddocDebug(3, "dencRecvInfo_new", "RecvInfo id: %s, recipient: %s, keyname: %s, ckeyname: %s cert: %s", szId, szRecipient, szKeyName, szCarriedKeyName, (pCert ? "OK" : "NULL")); RETURN_IF_NULL_PARAM(ppRecvInfo); RETURN_IF_NULL_PARAM(szId); RETURN_IF_NULL_PARAM(pCert); *ppRecvInfo = (DEncRecvInfo*)malloc(sizeof(DEncRecvInfo)); // allocate new object RETURN_IF_BAD_ALLOC(*ppRecvInfo); memset(*ppRecvInfo, 0, sizeof(DEncRecvInfo)); // set required fields if(szId) { err = ddocMemAssignString((char**)&((*ppRecvInfo)->szId), szId); if(err) return err; } (*ppRecvInfo)->pCert = (X509*)pCert; // set optional fields if(szRecipient) { err = ddocMemAssignString((char**)&((*ppRecvInfo)->szRecipient), szRecipient); if(err) return err; } if(szKeyName) { err = ddocMemAssignString((char**)&((*ppRecvInfo)->szKeyName), szKeyName); if(err) return err; } if(szCarriedKeyName) { err = ddocMemAssignString((char**)&((*ppRecvInfo)->szCarriedKeyName), szCarriedKeyName); if(err) return err; } return err; } //-------------------------------------------------- // "Destructor" of DEncRecvInfo object // pRecvInfo - address of buffer for newly allocated object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_free(DEncRecvInfo* pRecvInfo) { int err = ERR_OK; RETURN_IF_NULL_PARAM(pRecvInfo); if(pRecvInfo->szId) free(pRecvInfo->szId); if(pRecvInfo->szRecipient) free(pRecvInfo->szRecipient); if(pRecvInfo->szKeyName) free(pRecvInfo->szKeyName); if(pRecvInfo->szCarriedKeyName) free(pRecvInfo->szCarriedKeyName); if(pRecvInfo->pCert) X509_free(pRecvInfo->pCert); return err; } //-------------------------------------------------- // Replaces newlines with blanks // data - data with newlines // returns data without newlines //-------------------------------------------------- char* removeNewlines(char* data) { int i, n, j; n = strlen(data); for(i = j = 0; i < n; i++) { if(data[i] != '\n' && data[i] != '\r') { data[j] = data[i]; j++; } } if(j < i) data[j] = 0; return data; } //-------------------------------------------------- // Stores DEncRecvInfo object to configuration store // pRecvInfo - address of RecvInfo object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_store(DEncRecvInfo* pRecvInfo) { int err = ERR_OK; char key[100], *p; RETURN_IF_NULL_PARAM(pRecvInfo); RETURN_IF_NULL_PARAM(pRecvInfo->szId); RETURN_IF_NULL_PARAM(pRecvInfo->pCert); if(!err) { snprintf(key, sizeof(key), "RECV_%s_RECIPIENT", pRecvInfo->szId); if(pRecvInfo->szRecipient) err = createOrReplacePrivateConfigItem(NULL, key, removeNewlines(pRecvInfo->szRecipient)); else err = ConfigItem_delete(key); } if(!err) { snprintf(key, sizeof(key), "RECV_%s_KEY_NAME", pRecvInfo->szId); if(pRecvInfo->szKeyName) err = createOrReplacePrivateConfigItem(NULL, key, removeNewlines(pRecvInfo->szKeyName)); else err = ConfigItem_delete(key); } if(!err) { snprintf(key, sizeof(key), "RECV_%s_CARRIED_KEY_NAME", pRecvInfo->szId); if(pRecvInfo->szCarriedKeyName) err = createOrReplacePrivateConfigItem(NULL, key, removeNewlines(pRecvInfo->szCarriedKeyName)); else err = ConfigItem_delete(key); } if(!err && pRecvInfo->pCert) { snprintf(key, sizeof(key), "RECV_%s_CERT", pRecvInfo->szId); err = getCertPEM(pRecvInfo->pCert, 0, &p); if(!err && p) { err = createOrReplacePrivateConfigItem(NULL, key, removeNewlines(p)); free(p); } } return err; } //-------------------------------------------------- // Deletes DEncRecvInfo object from configuration store // pRecvInfo - address of RecvInfo [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_delete(DEncRecvInfo* pRecvInfo) { int err = ERR_OK; char key[100]; RETURN_IF_NULL_PARAM(pRecvInfo); RETURN_IF_NULL_PARAM(pRecvInfo->szId); snprintf(key, sizeof(key), "RECV_%s_RECIPIENT", pRecvInfo->szId); err = ConfigItem_delete(key); snprintf(key, sizeof(key), "RECV_%s_KEY_NAME", pRecvInfo->szId); err = ConfigItem_delete(key); snprintf(key, sizeof(key), "RECV_%s_CARRIED_KEY_NAME", pRecvInfo->szId); err = ConfigItem_delete(key); snprintf(key, sizeof(key), "RECV_%s_CERT", pRecvInfo->szId); err = ConfigItem_delete(key); return err; } //-------------------------------------------------- // Finds the DEncRecvInfo object with the given id // pConfStore - store to search in [OPTIONAL]. Use NULL for default // ppRecvInfo - address of buffer for newly allocated object [REQUIRED] // szId - id of the object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_findById(ConfigurationStore *pConfStore, DEncRecvInfo** ppRecvInfo, const char* szId) { int err = ERR_OK; char key[100], *p; X509* pCert = NULL; RETURN_IF_NULL_PARAM(ppRecvInfo); *ppRecvInfo = 0; // mark as not found // check for existence first snprintf(key, sizeof(key), "RECV_%s_CERT", szId); if(pConfStore) p = (char*)ConfigItem_lookup_fromStore(pConfStore, key); else p = (char*)ConfigItem_lookup(key); if(!p) return err; err = ddocDecodeX509PEMData(&pCert, (const char*)p, strlen((const char*)p)); if(!pCert) return err; err = dencRecvInfo_new(ppRecvInfo, szId, NULL, NULL, NULL, pCert); // now set the optional items if possible snprintf(key, sizeof(key), "RECV_%s_RECIPIENT", szId); if(pConfStore) p = (char*)ConfigItem_lookup_fromStore(pConfStore, key); else p = (char*)ConfigItem_lookup(key); if(p) (*ppRecvInfo)->szRecipient = (char*)strdup(p); snprintf(key, sizeof(key), "RECV_%s_KEY_NAME", szId); if(pConfStore) p = (char*)ConfigItem_lookup_fromStore(pConfStore, key); else p = (char*)ConfigItem_lookup(key); if(p) (*ppRecvInfo)->szKeyName = (char*)strdup(p); snprintf(key, sizeof(key), "RECV_%s_CARRIED_KEY_NAME", szId); if(pConfStore) p = (char*)ConfigItem_lookup_fromStore(pConfStore, key); else p = (char*)ConfigItem_lookup(key); if(p) (*ppRecvInfo)->szCarriedKeyName = (char*)strdup(p); return err; } //-------------------------------------------------- // Returns all DEncRecvInfo objects // pRecvInfoList - address of the list receiving the items [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfo_findAll(DEncRecvInfoList* pRecvInfoList) { int err = ERR_OK, i, j, k; char id[50]; ConfigurationStore confStore; DEncRecvInfo* pRecvInfo; RETURN_IF_NULL_PARAM(pRecvInfoList); pRecvInfoList->nItems = 0; pRecvInfoList->pItems = NULL; confStore.nItems = 0; confStore.pItems = NULL; // search the id's err = ConfigItem_findByPrefix(&confStore, "RECV"); ddocDebug(4, "dencRecvInfo_findAll", "RECV items: %d", confStore.nItems); for(i = 0; confStore.pItems && i < confStore.nItems; i++) { j = (confStore.pItems[i] && confStore.pItems[i]->szKey) ? strlen(confStore.pItems[i]->szKey) : 0; if(j && !strcmp(confStore.pItems[i]->szKey + j - 4, "CERT")) { j -= 6; for(k = j; k > 0 && confStore.pItems[i]->szKey[k] != '_'; k--); memset(id, 0, sizeof(id)); strncpy(id, confStore.pItems[i]->szKey + k + 1, j - k); ddocDebug(4, "dencRecvInfo_findAll", "Read obj with id: %s", id); err = dencRecvInfo_findById(&confStore, &pRecvInfo, id); if(!err && pRecvInfo) err = dencRecvInfoList_add(pRecvInfoList, pRecvInfo); } } // cleanup cleanupConfigStore(&confStore); return err; } //====================< RecipientInfoList functions >========================== //-------------------------------------------------- // Adds a DEncRecvInfo object to the list // pRecvInfoList - address of the list receiving the item [REQUIRED] // pRecvInfo - new object to be added // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfoList_add(DEncRecvInfoList* pRecvInfoList, DEncRecvInfo *pRecvInfo) { int err = ERR_OK; DEncRecvInfo** pItems; RETURN_IF_NULL_PARAM(pRecvInfoList); RETURN_IF_NULL_PARAM(pRecvInfo); pItems = (DEncRecvInfo**)realloc(pRecvInfoList->pItems, (pRecvInfoList->nItems + 1) * sizeof(DEncRecvInfo *)); RETURN_IF_BAD_ALLOC(pItems); pRecvInfoList->pItems = pItems; pRecvInfoList->pItems[pRecvInfoList->nItems] = pRecvInfo; pRecvInfoList->nItems++; return err; } //-------------------------------------------------- // Frees the contents of a DEncRecvInfoList object // pRecvInfoList - address of the list [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfoList_free(DEncRecvInfoList* pRecvInfoList) { int err = ERR_OK, i; RETURN_IF_NULL_PARAM(pRecvInfoList); for(i = 0; i < pRecvInfoList->nItems; i++) { if(pRecvInfoList->pItems[i]) dencRecvInfo_free(pRecvInfoList->pItems[i]); } free(pRecvInfoList->pItems); pRecvInfoList->pItems = 0; pRecvInfoList->nItems = 0; return err; } //-------------------------------------------------- // Removes the given DEncRecvInfo object from the list // pRecvInfoList - address of the list [REQUIRED] // szId - id of the obect to be removed [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencRecvInfoList_delete(DEncRecvInfoList* pRecvInfoList, const char* szId) { int err = ERR_OK, i, j; ddocDebug(4, "dencRecvInfoList_delete", "Deleting id: %s orig-len: %d", szId, pRecvInfoList->nItems); RETURN_IF_NULL_PARAM(pRecvInfoList); RETURN_IF_NULL_PARAM(szId); for(i = j = 0; i < pRecvInfoList->nItems; i++) { if(pRecvInfoList->pItems[j] && pRecvInfoList->pItems[j]->szId && !strcmp(pRecvInfoList->pItems[j]->szId, szId)) { free(pRecvInfoList->pItems[j]); ddocDebug(4, "dencRecvInfoList_delete", "Dleting item on pos: %d", j); } else { pRecvInfoList->pItems[j] = pRecvInfoList->pItems[i]; j++; } } pRecvInfoList->nItems = j; ddocDebug(4, "dencRecvInfoList_delete", "remaining-len: %d", pRecvInfoList->nItems); return err; } //====================< original content functions >=================== //-------------------------------------------------- // Returns the count of "orig_file" properties // pEncData - EncryptedData object [REQUIRED] // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencOrigContent_count(DEncEncryptedData* pEncData) { int nCount = 0, i, n; DEncEncryptionProperty* pEncProp = 0; char* pName; SET_LAST_ERROR_RETURN_IF_NOT(pEncData, ERR_NULL_POINTER, -1) n = dencEncryptedData_GetEncryptionPropertiesCount(pEncData); for(i = 0; i < n; i++) { pEncProp = (DEncEncryptionProperty*)dencEncryptedData_GetEncryptionProperty(pEncData, i); if(pEncProp) { pName = (char*)dencEncryptionProperty_GetName(pEncProp); if(pName && !strcmp(pName, ENCPROP_ORIG_CONTENT)) nCount++; } } return nCount; } //-------------------------------------------------- // Creates a new property of type "orig_file" // pEncData - EncryptedData object [REQUIRED] // szOrigContentId - Id atribute for new Property object [OPTIONAL] // szName - original file name [REQUIRED] // szSize - size as string or irginal file [REQUIRED] // szMime - mime type or original file [REQUIRED] // szDfId - Id atribute of original file [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencOrigContent_add(DEncEncryptedData* pEncData, const char* szOrigContentId, const char* szName, const char* szSize, const char* szMime, const char* szDfId) { int err = ERR_OK, l1 = 0; char* p1 = 0; DEncEncryptionProperty* pEncProp = 0; RETURN_IF_NULL_PARAM(pEncData); RETURN_IF_NULL_PARAM(szName); RETURN_IF_NULL_PARAM(szSize); RETURN_IF_NULL_PARAM(szMime); RETURN_IF_NULL_PARAM(szDfId); l1 = strlen(szName) + strlen(szSize) + strlen(szMime) + strlen(szDfId) + 10; p1 = (char*)malloc(l1); RETURN_IF_BAD_ALLOC(p1); memset(p1, 0, l1); snprintf(p1, l1, "%s|%s|%s|%s", szName, szSize, szMime, szDfId); err = dencEncryptionProperty_new(pEncData, &pEncProp, szOrigContentId, NULL, ENCPROP_ORIG_CONTENT, p1); if(p1) free(p1); return err; } //-------------------------------------------------- // Returns the info from "orig_file" properties // pEncData - EncryptedData object [REQUIRED] // szOrigContentId - Id atribute for new Property object [OPTIONAL] // szName - buffer for original file name [REQUIRED] // nNameLen - buffer length of szName [REQUIRED] // szSize - buffer for size as string or irginal file [REQUIRED] // nSizeLen - buffer length of szSize [REQUIRED] // szMime - buffer for mime type or original file [REQUIRED] // nMimeLen - buffer length of szMime [REQUIRED] // szDfId - buffer for Id atribute of original file [REQUIRED] // nDfIdLen - buffer length of szDfId [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencOrigContent_findByIndex(DEncEncryptedData* pEncData, int origContIdx, char* szName, int nNameLen, char* szSize, int nSizeLen, char* szMime, int nMimeLen, char* szDfId, int nDfIdLen) { int nCount = -1, i, n, j, k, l, m; DEncEncryptionProperty* pEncProp = 0; char *p1; RETURN_IF_NULL_PARAM(pEncData); RETURN_IF_NULL_PARAM(szName); RETURN_IF_NULL_PARAM(szSize); RETURN_IF_NULL_PARAM(szMime); RETURN_IF_NULL_PARAM(szDfId); memset(szName, 0, nNameLen); memset(szSize, 0, nSizeLen); memset(szMime, 0, nMimeLen); memset(szDfId, 0, nDfIdLen); n = dencEncryptedData_GetEncryptionPropertiesCount(pEncData); for(i = 0; i < n; i++) { pEncProp = (DEncEncryptionProperty*)dencEncryptedData_GetEncryptionProperty(pEncData, i); if(pEncProp) { p1 = (char*)dencEncryptionProperty_GetName(pEncProp); if(p1 && !strcmp(p1, ENCPROP_ORIG_CONTENT)) nCount++; ddocDebug(4, "dencOrigContent_findByIndex", "Prop: %d, name: %s count: %d", i, p1, nCount); if(nCount == origContIdx && p1 && !strcmp(p1, ENCPROP_ORIG_CONTENT)) { p1 = (char*)dencEncryptionProperty_GetContent(pEncProp); ddocDebug(4, "dencOrigContent_findByIndex", "Prop: %d, count: %d, content: %s", i, nCount, p1); if(p1) { k = strlen(p1); for(j = l = m = 0; j < k; j++) { if(p1[j] == '|') { l = 0; m++; } else { switch(m) { case 0: if(l < nNameLen) szName[l] = p1[j]; l++; break; case 1: if(l < nSizeLen) szSize[l] = p1[j]; l++; break; case 2: if(l < nMimeLen) szMime[l] = p1[j]; l++; break; case 3: if(l < nDfIdLen) szDfId[l] = p1[j]; l++; break; } } } ddocDebug(4, "dencOrigContent_findByIndex", "Prop: %d, name: %s size: %s, mime: %s, id: %s", i, szName, szSize, szMime, szDfId); } } } } if(!szName[0] && !szSize[0]) { // if not property name="orig_files" was not found then use Filename and OriginalSize for(i = 0; i < n; i++) { pEncProp = (DEncEncryptionProperty*)dencEncryptedData_GetEncryptionProperty(pEncData, i); if(pEncProp) { p1 = (char*)dencEncryptionProperty_GetName(pEncProp); if(p1 && !strcmp(p1, ENCPROP_FILENAME)) { p1 = (char*)dencEncryptionProperty_GetContent(pEncProp); if(p1) strncpy(szName, p1, nNameLen); } if(p1 && !strcmp(p1, ENCPROP_ORIG_SIZE)) { p1 = (char*)dencEncryptionProperty_GetContent(pEncProp); if(p1) strncpy(szSize, p1, nSizeLen); } } } } return ERR_OK; } //-------------------------------------------------- // Checks if there is a digidoc document in this // encrypted document. // pEncData - EncryptedData object [REQUIRED] // returns 1 if digidoc document is inside //-------------------------------------------------- EXP_OPTION int dencOrigContent_isDigiDocInside(DEncEncryptedData* pEncData) { int i, n; DEncEncryptionProperty* pEncProp = 0; char *p1, *p2; RETURN_IF_NULL_PARAM(pEncData); if(pEncData->szMimeType && !strcmp(pEncData->szMimeType, DENC_ENCDATA_TYPE_DDOC)) { ddocDebug(3, "dencOrigContent_isDigiDocInside", "mime: %s", pEncData->szMimeType); return 1; } n = dencEncryptedData_GetEncryptionPropertiesCount(pEncData); ddocDebug(3, "dencOrigContent_isDigiDocInside", "Props: %d", n); for(i = 0; i < n; i++) { pEncProp = (DEncEncryptionProperty*)dencEncryptedData_GetEncryptionProperty(pEncData, i); if(pEncProp) { p1 = (char*)dencEncryptionProperty_GetName(pEncProp); ddocDebug(3, "dencOrigContent_isDigiDocInside", "Prop: %d name: %s", i, p1); if(p1 && !strcmp(p1, ENCPROP_ORIG_MIME)) { p2 = (char*)dencEncryptionProperty_GetContent(pEncProp); ddocDebug(3, "dencOrigContent_isDigiDocInside", "Prop: %d mime: %s", i, p2); if(p2 && !strcmp(p2, DENC_ENCDATA_TYPE_DDOC)) { ddocDebug(3, "dencOrigContent_isDigiDocInside", "Name: %s mime: %s", p1, p2); return 1; } } } } return 0; } //-------------------------------------------------- // Registers digidoc document as encrypted datatype // and stores it's data file info. // pEncData - EncryptedData object [REQUIRED] // pSigDoc - SignedDoc object [REQUIRED] // returns 1 if digidoc document is inside //-------------------------------------------------- EXP_OPTION int dencOrigContent_registerDigiDoc(DEncEncryptedData* pEncData, SignedDoc* pSigDoc) { int err = ERR_OK, i, n; DEncEncryptionProperty* pEncProp = 0; DataFile* pDf; char buf[500], *sVer; RETURN_IF_NULL_PARAM(pEncData); RETURN_IF_NULL_PARAM(pSigDoc); // set the mime type sVer = (char*)ConfigItem_lookup_str("DENC_VERSION", DENC_VERSION_1_0); err = dencEncryptedData_SetMimeType(pEncData, DENC_ENCDATA_TYPE_DDOC); n = getCountOfDataFiles(pSigDoc); for(i = 0; i < n; i++) { pDf = getDataFile(pSigDoc, i); if(pDf) { pEncProp = 0; snprintf(buf, sizeof(buf), "%s|%ld|%s|%s", getSimpleFileName(pDf->szFileName), pDf->nSize, pDf->szMimeType, pDf->szId); err = dencEncryptionProperty_new(pEncData, &pEncProp, NULL, NULL, ENCPROP_ORIG_CONTENT, buf); } } return err; } //====================< other meta-info functions >=================== //-------------------------------------------------- // Sets the library name and version property // pEncData - EncryptedData object [REQUIRED] // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencMetaInfo_SetLibVersion(DEncEncryptedData* pEncData) { int err = ERR_OK; DEncEncryptionProperty* pEncProp = 0; char buf[500]; RETURN_IF_NULL_PARAM(pEncData); // set the library name and version snprintf(buf, sizeof(buf), "%s|%s", getLibName(), getLibVersion()); pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_LIB_VERSION); if(pEncProp) { // property exists, set the content err = dencEncryptionProperty_SetContent(pEncProp, (const char*)buf); } else { // create a new property err = dencEncryptionProperty_new(pEncData, &pEncProp, NULL, NULL, ENCPROP_LIB_VERSION, buf); } return err; } //-------------------------------------------------- // Sets the format name and version property // pEncData - EncryptedData object [REQUIRED] // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencMetaInfo_SetFormatVersion(DEncEncryptedData* pEncData) { int err = ERR_OK; DEncEncryptionProperty* pEncProp = 0; char buf[500]; RETURN_IF_NULL_PARAM(pEncData); // set the library name and version snprintf(buf, sizeof(buf), "%s|%s", DENC_FORMAT_ENCDOC_XML, ConfigItem_lookup_str("DENC_VERSION", DENC_VERSION_1_0)); pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_DOC_FORMAT); if(pEncProp) { // property exists, set the content err = dencEncryptionProperty_SetContent(pEncProp, (const char*)buf); } else { // create a new property err = dencEncryptionProperty_new(pEncData, &pEncProp, NULL, NULL, ENCPROP_DOC_FORMAT, buf); } return err; } //-------------------------------------------------- // Returns the library name and version meta-info of this document // pEncData - EncryptedData object [REQUIRED] // szLibrary - buffer for library name // nLibLen - length of library name buffer // szVersion - buffer for version info // nVerLen - length of version info buffer // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencMetaInfo_GetLibVersion(DEncEncryptedData* pEncData, char* szLibrary, int nLibLen, char* szVersion, int nVerLen) { int err = ERR_OK, i, j, n; DEncEncryptionProperty* pEncProp = 0; char *p1; RETURN_IF_NULL_PARAM(pEncData); RETURN_IF_NULL_PARAM(szLibrary); RETURN_IF_NULL_PARAM(szVersion); // mark as not found memset(szLibrary, 0, nLibLen); memset(szVersion, 0, nVerLen); pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_LIB_VERSION); if(pEncProp) { // property exists, set the content p1 = (char*)dencEncryptionProperty_GetContent(pEncProp); if(p1) { for(i = j = n = 0; p1[i]; i++) { if(p1[i] == '|' && j < nLibLen - 1) { szLibrary[j] = 0; j = 0; n++; continue; } else { if(!n) { if(j < nLibLen - 1) szLibrary[j++] = p1[i]; } else { if(j < nVerLen - 1) szVersion[j++] = p1[i]; } } } } } return err; } //-------------------------------------------------- // Returns the format name and version meta-info of this document // pEncData - EncryptedData object [REQUIRED] // returns count or -1 for error. //-------------------------------------------------- EXP_OPTION int dencMetaInfo_GetFormatVersion(DEncEncryptedData* pEncData, char* szFormat, int nFormat, char* szVersion, int nVersion) { int err = ERR_OK, i, j, n; DEncEncryptionProperty* pEncProp = 0; char *p1; RETURN_IF_NULL_PARAM(pEncData); RETURN_IF_NULL_PARAM(szFormat); RETURN_IF_NULL_PARAM(szVersion); // mark as not found memset(szFormat, 0, nFormat); memset(szVersion, 0, nVersion); pEncProp = dencEncryptedData_FindEncryptionPropertyByName(pEncData, ENCPROP_DOC_FORMAT); if(pEncProp) { // property exists, set the content p1 = (char*)dencEncryptionProperty_GetContent(pEncProp); if(p1) { for(i = j = n = 0; p1[i]; i++) { if(p1[i] == '|' && j < nFormat - 1) { szFormat[j] = 0; j = 0; n++; continue; } else { if(!n) { if(j < nFormat - 1) szFormat[j++] = p1[i]; } else { if(j < nVersion - 1) szVersion[j++] = p1[i]; } } } } } return err; } //-------------------------------------------------- // Deletes the meta-info properties // pEncData - EncryptedData object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencMetaInfo_deleteVersionInfo(DEncEncryptedData* pEncData) { int err = ERR_OK, i, j; RETURN_IF_NULL_PARAM(pEncData); // delete doc-format property j = -1; for(i = 0; i < pEncData->encProperties.nEncryptionProperties; i++) { if(pEncData->encProperties.arrEncryptionProperties[i] && pEncData->encProperties.arrEncryptionProperties[i]->szName && !strcmp(pEncData->encProperties.arrEncryptionProperties[i]->szName, ENCPROP_DOC_FORMAT)) { j = i; break; } } if(j >= 0) err = dencEncryptedData_DeleteEncryptionProperty(pEncData, j); // delete lib-version property j = -1; for(i = 0; i < pEncData->encProperties.nEncryptionProperties; i++) { if(pEncData->encProperties.arrEncryptionProperties[i] && pEncData->encProperties.arrEncryptionProperties[i]->szName && !strcmp(pEncData->encProperties.arrEncryptionProperties[i]->szName, ENCPROP_LIB_VERSION)) { j = i; break; } } if(j >= 0) err = dencEncryptedData_DeleteEncryptionProperty(pEncData, j); return err; } //-------------------------------------------------- // Validates cdoc structure // pEncData - EncryptedData object [REQUIRED] // returns error code or ERR_OK //-------------------------------------------------- EXP_OPTION int dencValidate(DEncEncryptedData* pEncData) { int err = ERR_OK, i; char* p1 = 0; char errbuf[300]; X509* pCert = 0; if(!pEncData) { printf("\nERROR: 164 Invalid format. No found!"); SET_LAST_ERROR_RETURN_CODE(ERR_VALIDATE); } // xmlns p1 = (char*)dencEncryptedData_GetXmlNs(pEncData); if(!p1 || strcmp(p1, DENC_XMLNS_XMLENC)) { printf("\nERROR: 164 Invalid xmlns attribute: %s. xmlns attribute is required atribute and only valid value is: %s\n", (p1 ? p1 : ""), DENC_XMLNS_XMLENC); err = ERR_VALIDATE; } // p1 = (char*)dencEncryptedData_GetEncryptionMethod(pEncData); if(!p1 || strcmp(p1, DENC_ENC_METHOD_AES128)) { printf("\nERROR: 164 Invalid EncryptedData encryption method: %s. Encryption method is required atribute and only valid value is: %s\n", (p1 ? p1 : ""), DENC_ENC_METHOD_AES128); err = ERR_VALIDATE; } // encrypted data itself if(!pEncData->mbufEncryptedData.pMem || !pEncData->mbufEncryptedData.nLen) { printf("\nERROR: 164 empty cdoc! This element has no encrypted data!\n"); err = ERR_VALIDATE; } // encryption properties for(i = 0; i < dencEncryptedData_GetEncryptionPropertiesCount(pEncData); i++) { DEncEncryptionProperty* pEncProp = dencEncryptedData_GetEncryptionProperty(pEncData, i); if(pEncProp) { p1 = (char*)dencEncryptionProperty_GetName(pEncProp); if(!p1 || !strlen(p1)) { printf("\nERROR: 164 Invalid encryption property: %d. Encryption property name attribute is required and may not be empty!\n", i); err = ERR_VALIDATE; } p1 = (char*)dencEncryptionProperty_GetContent(pEncProp); if(!p1 || !strlen(p1)) { printf("\nERROR: 164 Invalid encryption property: %d. Encryption property content may not be empty!\n", i); err = ERR_VALIDATE; } } } if(!dencEncryptedData_GetEncryptedKeyCount(pEncData)) { printf("\nERROR: 164 Invalid cdoc. This cdoc has no EncryptedKey elements!\n"); err = ERR_VALIDATE; } // encrypted keys for(i = 0; i < dencEncryptedData_GetEncryptedKeyCount(pEncData); i++) { DEncEncryptedKey* pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i); // encryption method p1 = (char*)dencEncryptedKey_GetEncryptionMethod(pEncKey); if(!p1 || strcmp(p1, DENC_ENC_METHOD_RSA1_5)) { printf("\nERROR: 164 Invalid EncryptedKey encryption method: %s. Encryption method is required atribute and only valid value is: %s\n", (p1 ? p1 : ""), DENC_ENC_METHOD_RSA1_5); err = ERR_VALIDATE; } // recipients cert pCert = dencEncryptedKey_GetCertificate(pEncKey); if(!pCert) { printf("\nERROR: 164 Invalid encrypted key: %d. Recipients certificate is required!\n", i); err = ERR_VALIDATE; } else { if(!ddocCertCheckKeyUsage(pCert, KUIDX_DATA_ENCIPHERMENT)) { printf("\nERROR: 164 RecipientsCertificate is not suitable for encryption - keyEncipherment flag not set!\n"); err = ERR_VALIDATE; } } } // xmlns if(err) SET_LAST_ERROR(err); return err; } libdigidoc-3.10.5/libdigidoc/DigiDocDfExtract.c0000664000372000037200000003025213560273131020642 0ustar travistravis//================================================== // FILE: DigiDocDfExtract.c // PROJECT: Digi Doc // DESCRIPTION: Digi Doc functions for extracting contents // AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia //================================================== // Copyright (C) AS Sertifitseerimiskeskus // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // GNU Lesser General Public Licence is available at // http://www.gnu.org/copyleft/lesser.html //==========< HISTORY >============================= // 03.03.2008 Veiko Sinivee // Creation //================================================== #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 #define snprintf _snprintf #include #endif #if OPENSSL_VERSION_NUMBER < 0x10010000L static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new() { return (EVP_ENCODE_CTX*)OPENSSL_malloc(sizeof(EVP_ENCODE_CTX)); } static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) { OPENSSL_free(ctx); } #endif #define ST_START 0 #define ST_XML 1 #define ST_TAG_NM 2 #define ST_TAG_WS 3 #define ST_ATTR_NM 4 #define ST_ATTR_WS 5 #define ST_ATTR_CON 6 #define ST_CON 7 #define ST_DF_START 8 #define ST_DF_CON 9 #define ST_DF_TAG 10 #define ST_DF_END 11 #define ST_DF_END_END 12 //-------------------------------------------------- // Reads in signed XML document and extracts the desired data file // pSigDoc - signed document object if exists. Can be NULL // szFileName - digidoc filename // szDataFileName - name of the file where to store embedded data. // szDocId - DataFile Id atribute value // szCharset - convert DataFile content to charset //-------------------------------------------------- EXP_OPTION int ddocExtractDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDataFileName, const char* szDocId, const char* szCharset) { FILE *fIn = 0, *fOut = 0; int err = ERR_OK, i, nRead, lt, la, lc, j, ld, lb, l, eState = 0, fs = 0; long len, lExtr = 0, lSize = 0; char chars[1050], tag[100], attr[100], con[1030], dec[70], b64line[70]; unsigned char b64 = 0, nNc = 0, bFound = 0; void *pBuf; EVP_ENCODE_CTX *ectx; #ifdef WIN32 wchar_t *convFileName = 0, *convDataFileName = 0; i= 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "ddocExtractDataFile", "file: %s, conv-file: %s len: %d", szFileName, convFileName, i); i= 0; err = utf82unicode((const char*)szDataFileName, (char**)&convDataFileName, &i); ddocDebug(3, "ddocExtractDataFile", "dfile: %s, conv-dfile: %s len: %d", szDataFileName, convDataFileName, i); #endif RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(szDataFileName); RETURN_IF_NULL_PARAM(szDocId); RETURN_IF_NULL_PARAM(szCharset); clearErrors(); ddocDebug(3, "ddocExtractDataFile", "SigDoc: %s, docid: %s, digidoc: %s, file: %s, charset: %s", (pSigDoc ? "OK" : "NULL"), szDocId, szFileName, szDataFileName, szCharset); if(szCharset && !strcmp(szCharset, "NO-CHANGE")) nNc = 1; // try reading from memory if already cached? nRead = ddocGetDataFileCachedData(pSigDoc, szDocId, &pBuf, &len); if(pBuf) { // gotcha ddocDebug(3, "ddocSaxExtractDataFile", "Using cached data: %d bytes", len); #ifdef WIN32 if((fOut = _wfopen(convDataFileName, L"wb")) != NULL) { #else if((fOut = fopen(szDataFileName, "wb")) != NULL) { #endif fwrite(pBuf, 1, len, fOut); fclose(fOut); } else { free(pBuf); ddocDebug(1, "ddocSaxExtractDataFile", "Error writing file: %s", szDataFileName); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); } free(pBuf); return nRead; } // open ddoc file #ifdef WIN32 if((fIn = _wfopen(convFileName, L"rb")) != NULL) { #else if((fIn = fopen(szFileName, "rb")) != NULL) { #endif ddocDebug(3, "ddocExtractDataFile", "Opened ddoc-file: %s", szFileName); do { nRead = fread(chars, 1, 1024, fIn); chars[nRead] = 0; ddocDebug(6, "ddocExtractDataFile", "Parsing %d bytes: \n%s\n", nRead, chars); // handle read data for(i = 0; i < nRead; i++) { switch(eState) { case ST_START: // search ' %d", sizeof(tag)); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } } else if(chars[i] == '>') { // tag ended - content eState = ST_CON; } else { // expecting atributes eState = ST_TAG_WS; } break; case ST_TAG_WS: if(chars[i] == '>') { if(bFound) { eState = ST_DF_CON; if(b64) { ectx = EVP_ENCODE_CTX_new(); EVP_DecodeInit(ectx); } } else eState = ST_CON; // tag endded - content lc = 0; con[lc] = 0; } else if(isalnum(chars[i])) { eState = ST_ATTR_NM; // attr name started la = 0; attr[la] = chars[i]; attr[++la] = 0; } break; case ST_ATTR_NM: if(isalnum(chars[i])) { if(la < (int)sizeof(attr)-1) { attr[la] = chars[i]; attr[++la] = 0; } else ddocDebug(1, "ddocExtractDataFile", "Truncating attr name: %s", attr); break; //19.11.08 added support for ' } else if(chars[i] == '\"'/*|| chars[i] == '\''*/) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; fs = 2; } else if(chars[i] == '\'' && fs==0) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; fs = 1; } else { eState = ST_ATTR_WS; } break; case ST_ATTR_WS: //19.11.08 added support for ' if(chars[i] == '\"'/*|| chars[i] == '\''*/) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; } else if(chars[i] == '\'' && fs==1) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; } else { eState = ST_TAG_WS; } break; case ST_ATTR_CON: //19.11.08 added support for ' if(chars[i] != '\"' /*&& chars[i] != '\''*/) { if(lc < (int)sizeof(con)-1) { con[lc] = chars[i]; con[++lc] = 0; } else ddocDebug(1, "ddocExtractDataFile", "Truncating attr content: %s", attr); } else if(chars[i] == '\'' && fs==1) { if(lc < (int)sizeof(con)-1) { con[lc] = chars[i]; con[++lc] = 0; } else ddocDebug(1, "ddocExtractDataFile", "Truncating attr content: %s", attr); } else { eState = ST_TAG_WS; // attribute value complete if(!strcmp(tag, "DataFile")) { // ddocDebug(3, "ddocSaxExtractDataFile", "DataFile start, attr: %s", attr); if(!strcmp(attr, "ContentType")) { b64 = (!strcmp(con, "EMBEDDED_BASE64")) ? 1 : 0; lb = 0; b64line[0] = 0; } if(!strcmp(attr, "Size") && bFound) { lSize = atol(con); } if(!strcmp(attr, "Id")) { ddocDebug(3, "ddocSaxExtractDataFile", "Found Id: %s searching id: %s", con, szDocId); if(!strcmp(con, szDocId)) { bFound = 1; #ifdef WIN32 fOut = _wfopen(convDataFileName, L"wb"); ddocDebug(3, "ddocSaxExtractDataFile", "Opening file: %s handle: %s", convDataFileName, (fOut ? "OK" : "NULL")); #else fOut = fopen(szDataFileName, "wb"); ddocDebug(3, "ddocSaxExtractDataFile", "Opening file: %s handle: %s", szDataFileName, (fOut ? "OK" : "NULL")); #endif if(!fOut) { SET_LAST_ERROR(ERR_FILE_WRITE); err = ERR_FILE_WRITE; return err; } } } } } break; case ST_CON: if(chars[i] == '<') { eState = ST_TAG_NM; lt = 0; tag[lt] = 0; } else { //con[lc] = chars[i]; //con[++lc] = 0; } break; case ST_DF_START: // find tag end if(chars[i] == '>') { eState = ST_DF_CON; lc = 0; con[lc] = 0; if(b64) { ectx = EVP_ENCODE_CTX_new(); EVP_DecodeInit(ectx); } } break; case ST_DF_CON: if(chars[i] == '<') { eState = ST_DF_TAG; lt = 0; tag[lt] = 0; } else { if(lc < (int)sizeof(con) - 1) { if(b64 && !nNc) { for(l = 0; l < lc; ) { while(lb < 64 && l < lc && l < sizeof(con)) { if(con[l] != '\n' && con[l] != '\r') b64line[lb++] = con[l]; l++; } if(lb == 64) { b64line[lb++] = '\n'; b64line[lb] = 0; ld = sizeof(dec); dec[0] = 0; EVP_DecodeUpdate(ectx, (unsigned char*)dec, &ld, (unsigned char*)b64line, lb); lExtr += ld; if(ld > 0) fwrite(dec, 1, ld, fOut); lb = 0; } } } else if(nNc || !b64) { lExtr += lc; fwrite(con, 1, lc, fOut); } lc = 0; } if(lc < sizeof(con)-1) { con[lc] = chars[i]; con[++lc] = 0; } } break; case ST_DF_TAG: if(/*isalnum(chars[i]) || chars[i] == ':' || chars[i] == '/' ||*/ chars[i] != '>') { if(lt < sizeof(tag)-1) { tag[lt] = chars[i]; tag[++lt] = 0; } else { ddocDebug(1, "ddocSaxExtractDataFile", "Invalid xml tag-len > %d", sizeof(tag)); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } } else { // DF intenal tag name ready if(!strcmp(tag, "/DataFile")) { // end of DF eState = ST_DF_END; } else { // wrong tag - this is content if(lc < sizeof(con)-1) { con[lc] = '<'; for(j = 0; j < lt; j++) con[++lc] = tag[j]; con[++lc] = '>'; con[++lc] = 0; } eState = ST_DF_CON; } } if(eState != ST_DF_END) break; case ST_DF_END: if(b64 && !nNc) { if(lc > 0) { for(l = 0; l < lc; ) { while(lb < 64 && l < lc) { if(con[l] != '\n' && con[l] != '\r') b64line[lb++] = con[l]; l++; } b64line[lb++] = '\n'; b64line[lb] = 0; ld = sizeof(dec); dec[0] = 0; EVP_DecodeUpdate(ectx, (unsigned char*)dec, &ld, (unsigned char*)b64line, lb); lExtr += ld; if(ld > 0) fwrite(dec, 1, ld, fOut); lb = 0; } } ld = 0; dec[ld] = 0; EVP_DecodeFinal(ectx, (unsigned char*)dec, &ld); EVP_ENCODE_CTX_free(ectx); lExtr += ld; if(ld) fwrite(dec, 1, ld, fOut); } else if(nNc || !b64) { if(lc) { lExtr += lc; fwrite(con, 1, lc, fOut); lc = 0; } } i = sizeof(chars); //AM 24.09.08 RIK eState = ST_DF_END_END; break; } } //AM 24.09.08 RIK ST_DF_END to ST_DF_END_END_END } while(nRead > 0 && !err && eState < ST_DF_END_END); } else { ddocDebug(1, "ddocExtractDataFile", "Error reading file: %s", szFileName); SET_LAST_ERROR(ERR_FILE_READ); } if(fIn) fclose(fIn); if(fOut) fclose(fOut); if(!nNc && lSize != lExtr) { ddocDebug(1, "ddocExtractDataFile", "Warning! Extracted: %ld bytes but expected: %ld bytes", lExtr, lSize); //SET_LAST_ERROR(ERR_FILE_READ); //err = ERR_FILE_READ; } if(!bFound) { ddocDebug(1, "ddocExtractDataFile", "DF: %s not found", szDocId); SET_LAST_ERROR(ERR_FILE_WRITE); err = ERR_FILE_WRITE; } ddocDebug(3, "ddocExtractDataFile", "Extracted DF: %s to %s size: %ld expected: %ld", szDocId, szDataFileName, lExtr, lSize); #ifdef WIN32 free(convFileName); free(convDataFileName); #endif return err; } libdigidoc-3.10.5/.travis.yml0000664000372000037200000000421113560273131015403 0ustar travistravislanguage: c++ matrix: include: - os: linux env: TARGET=ubuntu:16.04 - os: linux env: TARGET=ubuntu:18.04 - os: linux env: TARGET=i386/ubuntu:16.04 - os: osx env: TARGET=osx sudo: required sudo: false dist: trusty osx_image: xcode9.3 services: - docker cache: ccache env: global: - BUILD_NUMBER=${TRAVIS_BUILD_NUMBER} before_install: if [ "${TRAVIS_OS_NAME}" = "osx" ]; then brew update; brew install openssl; fi script: case ${TARGET} in *osx*) mkdir build && cd build && cmake -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl ..; make all pkgbuild; cd ..; ;; *) docker run -e BUILD_NUMBER=${BUILD_NUMBER} -e COVERITY_SCAN_TOKEN=${COVERITY_SCAN_TOKEN} -e TRAVIS_BRANCH=${TRAVIS_BRANCH} -e TARGET=${TARGET} -v ${HOME}:${HOME} -t "${TARGET}" /bin/bash -c "cd $(pwd);"' apt-get update -qq; apt-get install -y dh-make devscripts cdbs cmake libxml2-dev libssl-dev doxygen git curl wget ruby; export VERSION=$(grep project CMakeLists.txt | egrep -o "([0-9]{1,}\.)+[0-9]{1,}").${BUILD_NUMBER}; export DEBFULLNAME="Travis"; export DEBEMAIL="travis-ci@travis"; dh_make --createorig --addmissing --defaultless -y -p libdigidoc_${VERSION}; dch --distribution $(lsb_release -cs) -v ${VERSION} "Release ${VERSION}."; dpkg-buildpackage -rfakeroot -us -uc; if [ "${TARGET}" = "ubuntu:16.04" ]; then export COVERITY_SCAN_PROJECT_NAME="open-eid/libdigidoc"; export COVERITY_SCAN_NOTIFICATION_EMAIL="raul@metsma.ee"; export COVERITY_SCAN_BRANCH_PATTERN=coverity_scan; export COVERITY_SCAN_BUILD_COMMAND_PREPEND="cmake ."; export COVERITY_SCAN_BUILD_COMMAND=make; wget -O - https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh | bash; fi; git clean -dxf'; esac before_deploy: - export VERSION=${TRAVIS_TAG:1} - cd .. - mv libdigidoc libdigidoc-${VERSION} - tar czf libdigidoc-${VERSION}.tar.gz --exclude-vcs libdigidoc-${VERSION} deploy: provider: releases api_key: ${GITHUB_ACCESS_TOKEN} file: libdigidoc-${VERSION}.tar.gz skip_cleanup: true on: tags: true condition: "$TRAVIS_OS_NAME = linux" libdigidoc-3.10.5/libdigidoc.wxs0000664000372000037200000001442713560273131016140 0ustar travistravis 1 "1"]]> 1 NOT Installed Installed AND PATCH 1 1 NOT WIXUI_DONTVALIDATEPATH "1"]]> WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1" 1 1 NOT Installed Installed AND NOT PATCH Installed AND PATCH 1 1 1 1 libdigidoc-3.10.5/CMakeLists.txt0000664000372000037200000000316113560273131016035 0ustar travistraviscmake_minimum_required(VERSION 3.0) project(libdigidoc VERSION 3.10.5) set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules" ) set( BUILD_TOOLS YES CACHE BOOL "Build digidoc-tool" ) set( BUILD_TYPE SHARED CACHE STRING "Build library as SHARED/STATIC" ) set( SIGNCERT "" CACHE STRING "Common name of certificate to used sign binaries, empty skip signing" ) set( INSTCERT "" CACHE STRING "Common name of certificate to used sign packages, empty skip signing" ) if( APPLE ) set( FRAMEWORK YES CACHE BOOL "Build library as Mac OS X Framework" ) endif() include( VersionInfo ) include( GNUInstallDirs ) if( WIN32 ) set( DIGIDOC_CONF_NAME "digidoc.ini" ) else() set( DIGIDOC_CONF_NAME "digidoc.conf" ) endif() find_package( Doxygen ) find_package( LibXml2 REQUIRED ) find_package( OpenSSL REQUIRED ) find_package( PKCS11 ) find_package( ZLIB REQUIRED ) find_package( Iconv ) if( DOXYGEN_FOUND ) configure_file( ${CMAKE_SOURCE_DIR}/etc/Doxyfile.in Doxyfile @ONLY ) add_custom_target( docs ALL ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM ) install( DIRECTORY ${CMAKE_BINARY_DIR}/doc/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/libdigidoc ) install( DIRECTORY doc/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/libdigidoc ) endif() configure_file( config.h.cmake config.h ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${LIBXML2_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ) if( ICONV_FOUND ) include_directories( ${ICONV_INCLUDE_DIR} ) endif() add_subdirectory( libdigidoc ) libdigidoc-3.10.5/AUTHORS0000664000372000037200000000025513560273131014346 0ustar travistravisVeiko Sinivee The main project leader and author of DigiDoc library. Martin Paljak Integrator, fixer, packaging maintainer. libdigidoc-3.10.5/debian/0000775000372000037200000000000013560273530014521 5ustar travistravislibdigidoc-3.10.5/debian/libdigidoc2.install0000664000372000037200000000002413560273131020255 0ustar travistravisusr/lib/*/lib*.so.* libdigidoc-3.10.5/debian/control0000664000372000037200000000357713560273131016135 0ustar travistravisSource: libdigidoc Section: libs Priority: extra Maintainer: RIA Build-Depends: cdbs, cmake, libssl-dev, libxml2-dev Standards-Version: 3.9.8 Homepage: https://github.com/open-eid/libdigidoc Package: libdigidoc-common Architecture: all Section: misc Multi-Arch: foreign Depends: ${misc:Depends} Breaks: libdigidoc2 (<< ${binary:Version}) Replaces: libdigidoc2 (<< ${binary:Version}) Description: DigiDoc digital signature library common files This package contains common files for using applications with the DigiDoc digital signature library. Package: libdigidoc2 Replaces: libdigidoc Breaks: libdigidoc Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} Depends: libdigidoc-common (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Recommends: opensc Description: DigiDoc digital signature library DigiDoc is an XML file format for documents with digital signatures in use by the Estonian ID card infrastructure. This library allows for creation and reading of DigiDoc files. Package: libdigidoc-tools Architecture: any Section: misc Depends: libdigidoc2 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Description: DigiDoc digital signature library tools This package contains tools for manipulating signatures command line with the DigiDoc digital signature library. Package: libdigidoc-dev Architecture: any Section: libdevel Depends: libdigidoc2 (= ${binary:Version}), libssl-dev, libxml2-dev, ${misc:Depends} Description: DigiDoc digital signature development files This package contains files necessary for developing applications with the DigiDoc digital signature library. Package: libdigidoc-doc Architecture: all Section: doc Depends: ${misc:Depends} Description: DigiDoc digital signature library documentation This package contains documentation for developing applications with the DigiDoc digital signature library. libdigidoc-3.10.5/debian/rules0000755000372000037200000000063513560273131015600 0ustar travistravis#!/usr/bin/make -f include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/cmake.mk DEB_CMAKE_EXTRA_FLAGS = \ -DCMAKE_INSTALL_SYSCONFDIR="/etc" \ -DCMAKE_INSTALL_LIBDIR="lib/$(DEB_HOST_MULTIARCH)" DEB_DH_INSTALL_ARGS=--exclude=TEST binary-install/libdigidoc-dev:: # Run dh_install without the default DEB_DH_INSTALL_ARGS to install the TEST*.crt certificates dh_install -plibdigidoc-dev libdigidoc-3.10.5/debian/libdigidoc-dev.install0000664000372000037200000000011513560273131020750 0ustar travistravisusr/include usr/lib/*/lib*.so usr/lib/*/pkgconfig usr/share/libdigidoc/TEST* libdigidoc-3.10.5/debian/source/0000775000372000037200000000000013560273131016016 5ustar travistravislibdigidoc-3.10.5/debian/source/format0000664000372000037200000000001413560273131017224 0ustar travistravis3.0 (quilt) libdigidoc-3.10.5/debian/changelog0000664000372000037200000000037413560273473016405 0ustar travistravislibdigidoc (3.10.5.78) xenial; urgency=medium * Release 3.10.5.78. -- Travis Tue, 05 Nov 2019 13:20:59 +0000 libdigidoc (3.10.0) stable; urgency=low * Initial release -- RIA Tue, 15 Nov 2014 15:42:56 +0300 libdigidoc-3.10.5/debian/libdigidoc-tools.install0000664000372000037200000000002613560273131021333 0ustar travistravisusr/bin usr/share/man libdigidoc-3.10.5/debian/libdigidoc-common.install0000664000372000037200000000005713560273131021467 0ustar travistravisdebian/tmp/etc debian/tmp/usr/share/libdigidoc libdigidoc-3.10.5/debian/libdigidoc-doc.install0000664000372000037200000000001613560273131020737 0ustar travistravisusr/share/doc libdigidoc-3.10.5/debian/copyright0000664000372000037200000000132213560273131016447 0ustar travistravisCopyright 2012 Estonian Information System's Authority This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License with your system, in /usr/share/common-licenses/LGPL-2.1 If not, see . libdigidoc-3.10.5/debian/compat0000664000372000037200000000000313560273131015715 0ustar travistravis10 libdigidoc-3.10.5/CONTRIBUTING.md0000664000372000037200000000020313560273131015520 0ustar travistravisPlease read the [common contributing guidelines](https://github.com/open-eid/org/blob/master/CONTRIBUTING.md) before you continue! libdigidoc-3.10.5/config.h.cmake0000664000372000037200000000045113560273131015771 0ustar travistravis/* default config file for libdigidoc */ #define SYSCONFDIR "@CMAKE_INSTALL_FULL_SYSCONFDIR@" /* Version number of package */ #define VERSION "@VERSION@" #define DIGIDOC_VERSION "@VERSION@" #define VERSION_COMMA @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@BUILD_VER@

s33z=.c5Nh8)U4xC !mo"k!䅩:!oZ{bj>fj66w =W)UЛ|u!UWZfȤ5 Pis[_T+eLfH3T(۷gdj0U6d76&TՖT+U KC/<1fۖsv4ՆF4jU[[Pϕ0Y_YyCgc&{2l>o DKcĢϰ}˄SŗbS2[kg< fZwZ(PΪ䳅zץoT[an'Ֆ Foƭԉ݂[d l.5+vdDjuB?(#E"tեQ!#ce]plL;4-[>OT`FEha9R)iЍjoo·3P+&Z1վ1USjݎrT^HKChJq+nj~?yR(Ym5T}7gjXYhymފu3[ s>|[}յCX'֮qec9=%m>-7TOƘwCMmX5 %um=PV{j0WdDO1[jUojLv lҦMKj 䚋%-6Y]7N\.q0q2f̾a/b݀9GT-ss:YSP]4`Jm(߯z#`Z(!cTSUFCTԨPۈFMl~2uu:xi:8BloeֵwWq(Uגō,^VGd`M>55xZTN&,Dm,&wi)f)Ghsq%u:;?RﶅQf4h ~PEՇE7Ultx1h'C֌Qp P66 aq1s ]ɨiwFZ;'d{qY]ɆTVjnm5Zz[o Q]sΞ( ^8KuR)Z)HZUR )NbI"r)IDR,b /ũR"<)J1GR̒Y&)fJ(E3.EӤ*)ꤨbJQ#Eb'Ec#h)FI1RRTHQ.ERH1\R bC, )(b("_<)KORJGRHᗢ=Ȗ"KL)2!Ot)ҤJ"U)pK$E.))C8)bKa"Fh)RX0Ka"J )RJHK"wJ!Q)~Q^Vok)K)KJw)>c)>C)>oRUxOwxGxK7xCHg)^5)^)$R$ŋR R<'ųR<#R<%œRrC:`Aa8EDa4 l*|=ԟj n 9D~QO,(((#lԃG}SiԙzRd"7QQbVrmA a P>>0zo_a{.6ozuk?kW=X3=^~<`{ֺ OA?i=uq\c9h({xt!Ae,=>lvڀ|gynjvZ]66soϭ[&VoZu ڂ*J `3p9p].1\l4dztBs 9Jg=/\%XWX k5ªU`,}Lpt## +`EePSc5bx&`..{` rθ (S{;8j1F6qL8ajoeTgjJH!ĂSֶq~Q]הքتs7mb%)cB)յ)ucB BtBxVR矾e߿|:ӗ-? YyiQf,CZ.OmLN9Y88 X UJ t`p,K"`! s,hf@0Ӏ& PT*`0Tc1h`0T@P ÁP C ( @. ~L t  H7$. b;`bh X3`#`S4k(p8 ||| |5%p ; 1!7{;[_?^^^^}@; va `;pp'pp;  \\\ \l6 @+p8885_q9?sq9?sq9?_ p8|>p8|>p8|>p8|>sq9>ws}q9S=11 u\~aO`el>Mr{d롶l)?:-`eӳ8:w뢻X.G.N=nu~q틎;mXfRZ5/O~0_ c_nqIkPŦlg ofs<̩l>[(lf|ZKrNg1HN-Q-l>3Jfk"e5JVӁLYlUI&zv;v>.T+.>_.z K]]dW\\ˮ;zjnęeWrDqd=Z6ahEVp1`5fˈiV[[kd~vEQ\ eI+q @(w:֮KVuYk՜P'[]xbUԍjXݭjv+ {q$ev㺫"Vw.Xf{}]RwGc{}l?Nȃ<#H=Tm=EPOgسrϫ'{^V<^}p?R:_Ǧ㣃WZ /0+blz?> {:ʌ \ü@VcݗTWߤG{ }G9[{;۾~^+ivhh 2)GkT[Ô!-4"ϕ?׬Oӥ&8z&{HzjƐ>)ŠWtFC10S)FclJ3n8.?tGJlVP65Z=ՕkpڨI1q69f7biGs&>Nh%yXV`,]/GDf{W{f)L$2liU8+{23-fY4|^)>216 آz{BҞg;ߞW!3g)iJK0:'|JmOF\vяNQLq䔌na51++)Z*KT5Jvkhc̛ƴ+Y!{2qx#V<\8qǥ{ 7-ձ3g|sSx^ʳ;&N>X:q@⸌V=xpmi&_6ta,Y}jFƚ &.ܱ㏾=v0yDYcWZ.xd6YdUU!VY;x.Kc<'W{֗i+!Kӷv_ G˵;#T\`#U#-֢F}+_:)nN㗌y`A%S+ULze容oi4;:.)֑U~ëW=pL=7Pqb8qrɉs`qp /NKIMR$ENLRdm(%]nm::%r-^'^xxm_mB;>joնEk8rDɷ|esFdNlGa3b q:.2Ȩ"kZSXj[v%yD("9=r˓ )R5Y jҪ:`tx\cMj=l7v48=AC3wt 'JPXd^,2/̋En:sJmxd4>'5:i ic"d1jߐ*2*<-훐kr%Âeg3g~dB-8}&1@NUfW5կޓ] JW^ 'IOn;ECso2cN;յ<ObBZQӑ)gì.o!=۷+I18sddPr̾WKRʶ^樸/:i?ѥ7,:KK!.C,]򲾈YȚFWjyF2+}dVIGN>2+8&v|̮7ʢ^8_3zo;?vuyzk_FY-u:;?859VpֹJX iOaNhf mIdܿtHgXvruw|͍Ԅ']ސ^:{z ${t ]A 6nXQTR1nћھݹ8|:lJqQ= N8 jGb -g>veŋ~ap&/p>Rsesh]+vCQ4ˢ(&45Ǡ봅Gh屫dLL.GUVoF~u ⿫ +lPV'eEȸ ,ai_? .u ӏ6\s}sfK4HE'9N`fOI@Q>&ݹI6:=bdȺiwvůdxAvl& K𦌭 +i/'~Ma[˼ZY4;f+4;fiJsu4OuzE8ơ-c:kۛZx:&FZǠ&qůr,jj/,U= Mh_bz$${[=V/UІyxS9KQN~~CњNOC59ϝ_:R$UAd>% ˂kQ)Y>?4"{Q6CCF+4$А/>A21}$")Jf)4/&{"ͶUل&)6&^DZL1-VZҪ-aQ2L^_ TDc;>(,1'+NWv?nXYO8ep.TR3'N%F\&D^1f=A)}] @y>+ec`'EbvduK(K .Jq)qMNMKæ]NKKMpx#>mqY)fsJAzzQٜT~>! $<M<"l$(D}% eIr2, b'lj|FG3^|#] .5.\> 5ǝ68Z-eұ29Y-8#JL 2ĬlP®azSOӱn&+SM0Np4RTC ΙWCZxšZNSCf!ɓ`|b%#B'mp"3wT԰;n3Q dkaicgjwvWq)M(ti0Ge>S}+_-<0Qs:a3Pѻb1Q|+"O/*ցW{:a֜WlLY|E/kݺv-[׏YҽuauWW5޼d@k.oQ2VoV64iƜe*n<_qkӒ-;a׫`Kt9I` ނ>YG\X>eʋe/!~O("(PьKN"m[/c>gb&xCD̞C֚gyjl S؟7d~=7[w\eEtdI7_@wAiã7-~MKMU5&~x[C6V'~g:Z_>{234sL)43f&Q65$<.{`2qRDKv&b`7?w::ɎO03ՙNYIj0Y6Zlo^4e]XNc7ёJv+3gbQlgd ՐvlNfl$S$2 .c[G2&#Btن.KJVH8f{D[y?PE~Hf $O&Z-g dlculVRG5#X_u= ( <+xuYO%xU@όS,ف 3!3 ,#؝ olns]26\ayiW‚ { F&_%'b]ed4cedbj7zHiRlLwu܂4-vA\f,lX^ٳꍋIzmJS N[LfFb+[l;C<(;QbR<+z4Df 0k\_FeQ葉ͦ?IHgQ:ֱ_Uu+L[I(ƪ7$#MW(d8 W)fmmLխCGn쓧*u7!mף!Hj!{e|d~<9 ;t=%8߇P/s'!Ե<" ΀O~ ~4d5jGC }>G9w՟OBg)<)"+C?wNCB/~>AG|h.BvQp70vh-[x6nm8cy0:38kA<93BoO\jd9ZN$!o!sN ,nsQG5\gі zH&~IƁm3x Q6Ews ME<2Q^Q)2LeD'Qo7Coyey>>'9I^$/spe~FG,kୡ]P~ă >z h̍r>#UOpF$B}98h>du[$Ks1zUinCT/Gꖉ"&p$l-$_Wt46g8n~knJC[ FKzWsE5!*HdHqPs!&Io&m!qJp2 $T'krVݪU*gխYuҨrV݆pUΪ[V嬺U9nUΪ[V嬺U9?HRNJIk zj b$$egk#a=d;↸χww!2CmE^΋~7^E { Wu)[CZcF.-^ʠVj):Y mu7sY[Zx[r V(dDL!/q5絪ev-oV!嶇Kז}/8}>T(֮A.m< 1|jw_!Z9~^.aMfSYU5Z#ӵ2֨{4C]D+T hmċY [s'xyZb{X}Vo,WJRM}y]Y-;#:fףٵ?YqiCNe4]< /?%ݜy]_Vz {p~LbݼRg_p{ w%oj%{v8 ! o>^^prnbe2'vk_~2Xs eW~ͲԲ|raY#siYöHMsKLQQƵ 9k|B\uQ`-Qۢy"5.GTwL?qU{[0?k/RK{i/fD G:s]ȃJyiY3084T owpXiSl)}C._W2o_@;x._`@ )V}{ݽ`O t )H#@9!%)A9T {뇛e Qp/C /`HF}}Aw@ v(}k[ V+ FܻWhR{a4^܎}m W؃<8bM*~.&}=}@D7A8hRY\hЃoZhA4|7T6ܙS|`p{0-)ٽ{wq8_1{^=%~'Kw0DGrbъ{A_m|c[bt ؽs{T^{:&+ :7,Vu@y4S@8xrfPP0۩Kvf&8^e}" kp@ߠ7R`Hx42f84}} t)(u{a!HdDB9ۓXH 1BĎ5 z1NB~V^v;K/6_jzN'K֥Az }xzIEI"ؑ`o&VrXSQ;uC4|ɣ3n![ yitiO&:A۰{j:]vOл3k/'h/fcx=>`?_y_7,0 ̅\ Ky-0of0[y`20s*09x4 s0g"`n<0??W60OnA ̋y0ky0$0̯o]` V/B :o6f(I 7s0?k&0Nh;us:0s#0m<m|'0o`)0̧]`P|G .Yps0slRe`.:v WNn{`~_!uS 9y%0o` ̷5`~'`7c@?/s0Wr`>`( [y;0;{K2Tr`z`a`=00׀-`IB\-N`~`? _ogl|q8rsIz*O=pY1: T؏ 1:Ĝ=$J%ݨvILǎ}=<#5"dRԋW:6ܜp`<+80GX5T?X$FGG$tv!02>1W̲1Aӓގj7Ԡ;tqʨ#FZm)O~aAO  |`Ft i&Pg0QK"N"{:sMi1_$G1׈81jV5ͬKUL%ѣIF*5cPХWSJүA/" fgYP\6eJK13'.1-J6| a%GH˲ebFhDŽ&G,D%KbyMM,1!OASz擧3! =itb&*[&ps' Y~b8.m!QO5#@MR9lǏ(u9Q:.xQF5^; Ѹc Ff FMf5jyJ"-oR6duԨ(s3cp@0J}K)32k(? h"Fsٓ?ȉ 1QȨ@}NGMq\\CP;f$ʔ'fI hvC1aU C1 .#5LI3I64tnfiZ.LM։X*Udj27h&@LFb" /؏^lfh2jts[YĜ"&dD܍Lͣ!.B2SjjlD Ϥ.#2S6̭m*fF/$%bGZN7i݉%Q:tl"fKF MQxFjƤYYplMS4v9ynN1lHH<{8w|*nn$LTl Tb6sU98`?2ni+g1R5SXW ifƅX=kfB1>6vxZ-MT=5q0)7\ݚjs+ <)W ϥ6`d&ղڳ6st X`1D@β7=7Jd aH$}fE)X6bQhhMlxctĉϝ8v؉si?A&!ib49Dut4jfi5",6jqJ=zW^qs?8ybkN&PD,r(qRFc Í'N<*QU1uxW]cӴ\}jVC}GGTvYXMډ7"ǍVqUV!k!QlS(=1"!Rdz>Or*\[85j98bcAYsjMlyQ($CZ6&Ğ/t}S'JUQzEYOLP!/9vqҰs- ww6OL=>$}iC ݰ~$Hb:T}a"q<\ 0MIe$$N|or0Or} ?y_5Oq&ﰣ_y2Ŝ/|;w7r~nο'rB8D.AX7fO߅ ЃZȞcNryyG"JZk!b3(;mSQy`ooZ۲gCYӳ'WYo tel`ӹ3e#?8,˅e,_X;g7Y mMCUBG?`15F/AF(T j >㎻5:EdĦ9lλ"Jۙ7U$7$I*K+(MPEEeTD TAA}2:A,e`)m 񶴥6{Q}9χ{r~Imo>_:3g;v9@;dji}ڦcgͶ7[AƓ-uyd-l_u[Vx5ݽ?&GƴW336Vk=VhW:>upMKӍ?eD>]Gvο}n"_<6{7ZPzj=eբW^ ed ^ۿ[؀g/@60}ك6& *܃6h!f;>a''Ca5泚a5_\ɴ3馫94]5zqqc:d̰1v3[fb+=6v`ܢq_?*UY3w}#ZE8>lk4*gWd˪a. rzә N5iIKtvKnk?Ђ ;d_͞J쒅y' K6.r/jhТM[vQG.m[?0E|c3;磜-9Ǘ%kK/^!7wj'gף_VQGr_?ݚ*̽1gϸ_ΓLͪs~Y;rnFu-<ݚQC[OypY#Uuu7[J-8U3yqo'-VM*QGN-&¸ǝ'VVЛqU=2*:OuNP ϨQgϬʽ̦*:d4:j:^ummMydjYvr9uhk;5eWی+ws4qzZԂ~^ZV4~qӫ3WRc,檙\7X9u_ɕsݍ@H q{R㦙hٔ)MC/~39cV@'W¦^s\`;O0\15eqUүK?sU:+\ffg__ag{c5s-Ԋ;lvjf?Vܣ~w9yyt5l]Z9>㩥ƮlO؍1=P cQGF3wG͝VchЧI]֎7>&9Mײ 0^1v4}fx{#5Ϯ5kբ[>sߕlY+݌],+sQh.afЌVh>mZsvj66kT両 sj7aM#om /__;zf\TL؍o)/jӔ(oD,b>Rovg.<.qWk`*2,weheW̔~*k\ۊk\bjrΜ9ߙҗ_f<ȍȑbJrP\DD?%*z*%Χ];m6Y?c4"[#ƈ0XtC`#6\Y/|XٰP"W, CGQx 'Sq <n`,1rL&-#I VTn#RqL\^mA!R>AtoRiv@mp7Sy\5rcαn}r~y2jhcG;?CA q=vᅩ0 fBȅeFx W9XPP ;` DB iZt4syb>: Y kd[7JAFm*6la|K|LO)7Ewɛo)*AV$"BQŭf}l3OΊD3ESyD^e|+I#Ғ^.җ^KOzV=]LOƷ(:3-}F]y.#JgtJzXVۊ^{Ы^5څ/o1'ʉ•0'$FeY#R!X#(</b]{;(RP*R!u2,2A Aup HZX̪XL!,(q#R}"(J! Ʉ0GP @-Qb,Mp 50B:n8pV n S^8xdB?12X+9>x ^xMx!?iXhAwJ&Lքɚ0Y&kdM 5a&Lքɚ0YI'uq1aq-kaqJǩ0q# TOz@UUUQTGQèbè6glpd'k+{XXmL}DM}- =ɬI뤇u:aNzX'=It9ke.Bl!s9[Μ՘sVcjY49aFl9b,i9yZ<-SnpX:ڑu#h{NkavzX;=Nka.FbXӘs̹B\5a}yX<̕k s%! B/$r_#5ֿ4ֿ4?B9a yX<#eZױ?{J>y81 ''k JHL5 su)Wb>%l*xu>Ž[w r-žG7se+ r2r;9?9_!(g?).1'7E2o0fl ҷ21ϻ)_̪}#4V%vVbTÌ k?Xg˯-{NƚѬ`S[h6s5Z`dY{F֞gdY{F֞gdY{l͝35w0LTLTLTLTLTƝrg7Լ͝nts;N7w͝w [E05{ K`7n)RػwKinwZ}J4LEbYa='%p)0.a ?`WPa\ W0k:a qp=dxx ^WUx ^7Mx ކZxރG'|nmǯde3| y l2d!vNyȲ v÷ i6Y` `; dȶfdEB;H Ya_ k CXz'͑ݦȐ;/.+.< tn2.@.8;?C+8NGVYTpBsH!Z9יq;INvA{ tn<!`k#Zn纩\w`:\, +y-R<_uɊ PshFj~!9cA XPǂ:Աpu,cA[48ZCh 2 ߿:Ag]\dE>ewzAo}A0`0 +`( 0j p08a\L&pLdܓf 8Rȅe a9<+axa-gYx`?o o  hYzxއ`Pk-Z?`#_"1Nl!1l;*2Q%P`87LlT<FųQlT<FųQlT<FųQl!|oYe> _f`pv÷}լ veBVٟ}%Wxװ&Y^9lgvlJ?FrpxS `viV<;ymo@|^kŲs(Ůݵݵg;YG4ЉAtUs%tȀ=tEB7v\CwqVצ+Np9A3{Nh)7B 8ZB+HsHq!΃q:q:= :C *gO>Їd%a ?`Ϲܗ%7E68ogwqUϻN>:@cXK!彙f^q5ex*Sc[1jsl±+fegjގ!;?4fzr_cE s3coUfQkv)϶8W%zY/qac-wX'.ؗ2YHx#(<$Y.e%< </*xVx ^WUx ^7Mx ޖqwO #խLg|8pƇ3>g|8pƇ3>g|8pƇ%(P%(P%(P%(P3>q5*xQQۭDIɟ><ڢBTh ?%vڎWQ#52Q#52Q#52QË^5E /jxQË^5E /jxQË^5E /jxQË^5ELDLDLDLD p D&gx>"\ 2(}Цm! 8(bEq1"Q8Gs'9ՋqGNfNպjRõX]@, ArxVEmtQ]FEmtQ]FEmtQ]EuE]tQ]EuE]lRE3*{0#ӻqv/s7܍0w#s75Ʈ1vk]cc5Ʈ1vk]cc5Ʈ1vk]cc5Ʈ1vk]cc؍5Y~;QS5ˈL#+8߀q8n2urB}))D'3-8te(D Q2@ e(D Q2@ e(D Q2@ e(D Q2@ e@\F$~ن7۬>̀:,'vɟ̴3~2C$/?»mx 6FT~D'*?QOT~D'*?QOT~D'*?QOT~D'*?QOT~ds"oZF(\Ļxw.jCLm8"]ijxv.a'yȺxRV[_0~ΫRIt ݚMF,2d]!և 2v"fqdz+u%ZWZ,UbTEKj9C=ntOs||2emvf[93 3-Ed(Xs` ˗^2Vz: ןk!k!k?U!jȾ!jO+ zsKP%p阘hUW'RhQo%ϟ3 VE(F5Qtk]5]5]5]5]5]5]5]5]5]5]5]5]ɩ*r"ȩ*r"=Qt{ݣE(G=Qt{ݣE(G=Qt{ݣE(G]F`>,lXdLHs֯qn&/֭r( M$ *қO}9ʓDKfSsn{~7ffײКG[ymwȰu7t y"T=Ne"N_Y\**?\&uep{Sr 8Δa,&sC~ר}y^OwCHu6Zr$&w큽Px*y}ֲ: >0 ORӧ2ԇe}h ޒbLRR|Jj1VjGՃZŨzUQ5uԬC:C:CşPQCE 5BR,Fb,Eb,A,E,E*B*,AR,E*BbԫB*POC*PLC1 4P PPPPP8T)JURJi(U':Y֏G($ZTѺ_Mͳݓȳ-"|Jqd{Hi-=JGqU%;)}U-92L.Q&;LYL%װU;cw8L5XAGKCKCDǾ{˘/;9p^Ν[Мd!w~%s!;rޯ̜|6pGioYG;Ȭo`wU"CA q8HfdE9Yq8JV%#dDHdBLH q 5D cgo~y맰M6>􌸳Nu_Gu5<US'lUgsGSK>&e{#eo1ɼJeNUoûpg-J4D#=TD伪Gzk@2=)Zީōv t?*sw{ ._h.eUn=3*Q% K^%*䠴D(%V2*QQ%WꍨވZ9(_b9Ds9ǝq'=+XNrN[R vp`:j\U"EX / EF֑8ݟsss2O0O0O0Oax} pUKF{={=qw qk P_j/ԖZjK-2zYCVR+j-)22`ogqY8Vk7UEBrDγ~/B_>l-XycȖ5A%8V9Z'z%%J|dN>?B$`/dg?Ʈ̮[ˎǎ-cWffa`gc'mfǼ9Ž`.a?p=Bx|JV7sm$aG#s'fUm쵍쵍!NqbaFmoJ7xgl?1O<97 6 62FFyy^D'6262X6l{YEfcV?ױ?ױ?בxEx ^yDOmWar ~\/R|_+ŷV*ůJ"?>u ZG&sk Q܃(r;>Evn' oj VĪėDb,{H]eacF%qhC4!#W#uDQ6'D "k5%EM"g1OaSX0E"f)^Q/HED3bX(f2bD0O'ZD)@t 2ND S>Q)@T 4G QhdrXcDB"K!t:Ft)&ADB"C!PJeRT&QPJeRBV;?ŎbgY v{=n v{^*f Bvy!5ԱM:v]gʎJeGdkX׵k:n e&tkQ.g-|</OSTb>^^xy*܀6aMxsڄʰU^݀쓎}ұO:)Ûlұ&Mss:s<$c.0Z,ʙYYfA1 f.0 F.0 Fu]`DAFdDAFs\`4AFd4®e=S>=S9=vIo5IoVKoIo-cZ-s-=s9=c^K^NIv}XNPL O0\CIJDܓD\>҉Z4PmX;)qڮѱy?6Ѵa,|yXBM//gyG2Y. c}yl~yNZw x! tYd6O`ر;cG.~Np1a G'wf/帒f sD{w1cL/8Ռ>ȸW5fՌ9>G[IWIUM?R_DY?vHO;Rgcau]0ؑ(ӗ1V#FE/=(9_w燝1:qKV- JA`bwOcXk%[_mX [\WXq%;dGhǮ0c1s,fŬj, ar"G[dw1DX8%4C 0*Fl k`FYrV.X+`,\@OUX`[u UDKd?JRjj(g8=8a'"S֑)Ȕu# Y΢x!2]LWGCדBhzt&'Ցnuztw=Vl!E#ԑ]D4 w[l[םWȉ*d-Hr 3 u%G Sx)c͵ޞ36 X"tWYZ\hǙ=f_kA+?y 3qf1 1fVjDwz;}kI{9}C9=ůbۓضgIM節NmO{9=j](̼Vb+W,ԒZ Ub 쿮UaJ 4X ԑm#i 'ȸ@Q7AMuDQ3AJ&( "&h> XO譁޾oD/~*c>çaew~}vX#+%lxok uOW$&zE)}*aVJT *amT )"%Xk`Q5JF (%X+`P":1"Xc5s3sP0TeUb.E(KsKsAIGaE̡90_H2$?q>O8/jef4n>~TE[ v\a\0#^-~x r]J3`&<eޜ7ixsUyobx ކw]Xxn5| XP+ *8˵q :tv`#s-9Nxxx  O'd17̖S)| ~>EI/ WUx ^ er6+:͊Êih+Ɗ d ª)jU xVj>` | kHu66fVHe:PT8ZpLVϩH'de"mnGqZKYZpkY"VAR ]+i)H\;ͱn khJ0Y0a\Wh?B!PE==Xn-sĘ)J_/ė)FڣimS<8_8b |NďdG2#DH"~L&~LKـ/y\{A B7`Lcffxga>,Ű8~ R\B9v;w9i4oZPMoh+sA:Ag5F1(zB/ } 5<\}|N)2Q}otξ7&,E|mxޅ%Raa>5/@ ̅ym}G`>c>c>c>c>c>c>c>c>c>h\!Z|/wj')eD##ՙD3ux_h" @P@@P@@P@ז%B P!@%B P!@%B P!DDD{iI00g`*Lg99:::::h@4M &M DShMuN4Չ:T'DShw ɻBn!y[H-;`##"Z_k-Eȿ"Z_k-444QA-{JCXP gKkkkkk곈곈곈곈&DӛhzMoM47&DӛhzMoM47&DӛhzMoM47&DӛhzMoM47&DӛhzMoM47ߊ8e$d"?O&d"?O&d"?O&d"?O&d"?O&d"?O&%vSK즖M-Z"Z"Z"Z"Z"]VJB'd1,fCG9%FF8l `'YM"d[ll&S/Ԟ]WNPgQdYNNRdwL^I. A3rY d9,g A3rJ:C(J:C(J:C(J:Z*-W*,`9> d2guW:uW:uW:YT'dQ,EuNɢ:YT'dQ,3-tδЙ:BgZL i3-tδЙ:rʰ"A=4%h&`Ogg'di&IgR&IJP%d)iQ)ddnfLd2ApG8P@Mdz"@EPQߠPY<]h{Z*#2H@Qm:(APy<T*a"a"a"a8!z`:$IIY%GI=;;91S2֒ԉ8GqQ~jtjtj»Q ~ޛNMN]`QXuE]PJYK]`QXiiGd(,o"Sާ x ,jB(¢5[-TN=aQOX QA+,,NmaQ[XEmaQ[X(i(i(i(iSNKG5-E5-E5E5E-B-MC-E-B-&IoR&IoR&IoR&IoR&.?ˏ.?ˏ.?ˏ.?ˏQ/F5'8OS\0 &32B(4|YOh&wGzfq(84sn+ӣ ]_0Z@ٍ2ςdQ-0P|@(>g 3P|@(>g 3P|@(>g 3P|@(>g*>gxSެÕyw q2A<%Fă(y6ZަkrV*BjD8\G謅*EM9$6lqXf[ z~oJ$/[jlB/K[HX/Nj|_z\Vz_HODv\2-rSyXN BˇɝiZv$Bh}7ytOvѦ/#{߭'OԧG'STX\֒cEK[dkgtzTӲ5sdi7o0#?:9Sk5* qRV) !/DA4bD+" M'E/K2^W5xĆ;d)U( BD>V@[vt C 7~+p@ ̅y0O/gX$ |uܢ^ 0RnW_UG*a J{&bVǎ^!R]hң5E*eẔ]GJ+*R犎tq".CƻbނvẀ<ِ̂ s 51O zFa |[!>m]vNa}A8![nqr!N ("(wx4=nӆc[`Bxn,,TΙc>30l %N{k>9 ȃ2^T98jNy[@KhvN{L[|Xa| 8-QdQ j9{̏zIx\_r2?ZȢ_NEOȀ>i Ӂu~:]ބ B*,`9>0G}5|GFnF|0#^-d7R`.̃Ex ^?+*&,E B*,ۍ+r{ |rp+CZ$r s B P?ElQ?[ElQ?[ElQ?[ElQ?[ElQ?[ElQ?[ElQ?[ElQ?[ElQ?[ElQ?[ϖ-\_Qf SYԬaTTu<wjlfŖk'D7e ujp˩SÅpv~ P?,j&ɢf,j&i9ur$˩!SCXaj: LqhZ8-пBZ_ k-пBZ_ k-^ WU JiBoZpt,iLEc)sД9Fpo2bh8;a/]$O bwLȇw3 "[qv.eJ(څ[)m`iq-섈g\o}-3b?rgК܄&欈D%Ύ~%<(|`@ Q67.t~t.]I0f0 fC2́ D<|<5{<5{<5z<5z<5yd\{hl{hd^Jea_kch5V917VKo%fRm^[*nQ v Xѕ'ϵtѝbO?J8>q:)aq?y"4 qe4--ZT8QFECrtӳd -Y`.ON[&j&j&j&j&j&j&j&%oN:o˕5|LanQ'9FW<,<}o?Go6捵1kxc4o;<&(J1x;EGfȓM<X"x]Q&KM=ah9P{h=qS}e<3Gb%p3Ϥ!d˕No~Ǟʹ#])ۈ;c`,Ka pVsEfc5#k` ln`dw'mG(3 hxn8xON7|gkd|52FUb&`H0R`Hǖx%1ˍGXy$1,KOwôr1s ѐќAM(C\HӵJ$V"J sp s"D13g_7jߨZ VqͭE_ 2H+֫+q])#WR\[#EMĆq[Qֻ|i9ywy._#V^RcF\óZRKFhO\JUj # k  &zP0+(|\MM̠K o-"yoPx#<-yLv,b <݋ xvk ?^]tEK3+lVT!=chgQzQES]岇"rg[*@ i[);bݿ[/VyxY`u '{;wE Wvc|:L4e|ʽnɽޜ^_#\qЙ9aM W,g߉:ӓ\\>\=ss ']mrWWCѕe9TƧT;{@OMs?WyKcg:2N"oPu^o|cǘ;N̥3߅.n͵>~̏Y6xoWC"XՅ9wM7t~I^MGfpA2b#qض' 3XWEh;5ӜyDuU v/׈7xjw>Gxە\ oў_Xu| 18Qrb$H$}Ӆ6\&ݡ5EBD DD!.w$HD}hԅ6&EBD DD!E,rE:pQ^EZ0AX/VnNГ^M>K~xM4AٿsHEƢt{*~V8kNeIyL U)(B{Z!C#N+7N:W<3J~_nq>ٿnWʧTW !P@q_ 0Zf{xSψb/goZ䉷DjQ)"[\%rapQܫ< ʕ1#R2AT+ₒ{IYNY\WN(ԁ`Ze:D\ު+7VաP&.fu:\:R_M}P$cձʝxur:A}R[NTQ'O+g}C+DuDITSetu2CMW(/GQUggvg;$@] QO(6aATD4| > T*{wO̞v,xgsV*^rV:7 1Mxg3_l˜o7;;yk~?;8'xG#ޕwewݙp)| G,§LO,b?5zn&Yۘr;/~w^wXwG^ <)%yo)[fKu:md+Mfbk=Ma0mqB8v@$vB$LQsQVaQW颾-E+~h#zz9Mb~xU(NcCb;IbXLG4,fxsBX,!bX_+*[p[#%IߔRȊ#/D6K T6+u:N oFAwny&Aٙ]dw~\>+{L _t]Ow(G(GQn-ǸrLZu+"|֕yLj_ѽٯWwou ~#{o_7wv[[[~{a1q}ws{3~tCܞ0O')ݗC!w` !;4BP;!T"Tʝ**>};6}?|O}t?w?N ?~$dIppwFk;3b]wvrwGxex{ |8枈 DDy/GEfy#Dxo*RUUuBݬգ":N"^=:DEuEUW(E5H ƋzjzWWSGffshfj^\~RE+]ܦ%ZVj%کxRQDWu" #`7wx!HAJ"iAIJP* bt#!=ؠO 01%x-xM F׃q`Bgqqܸq◸qG|baw"uIk2 NozSٵVMkbgr7W}yM^gp|C-34B( 3m|]>f~S\*C %zuD GoqlPJzY"J۫s<݁ݞwz4qНv3=Rr>Рo~srS>`1snf׊d?^xWj]oܹoӛ1vdq2j.Ϟ'~-qX VBM?iz1~?_/ΧvM ̈O9o4at6ו(o_i,n4[a~ۢ۸_v5 y԰ZGU=/6qC1:УnAj%dxkyOi|D?(_3 -t?@vL>dCR =Knf?-ݟR7QK3Bbf2Ga执-Sbu{|Vljk(t!OZZ=w?rl~(JאaBdOQO'|{tX1Mտ߳4iygޅN`3iղ kZDi)m8tiKâ7u2<=ixz=:ӰǗP7[G&^d[Vcls4eGec@c`K4k-FidZMD/~gEb9*4ttD^+ƦUnƦƦMƦ-ƦƦƦ;kn#P9 Ή76`l: ':IƦsΩns99vn{~qtKe~yQ"bqXm:O:tub/c9]Mt<43\%gzWQ.ck8 ,5*ck83.ck83s1cG8ǍX\(.d\Ѹ,w(3{ 8Vc4f,H$|$A` }V3ϡUaUah\)B aвE`Ki9 Z1:W2h7F|^:H>0s4tjQTV/+[VR[PqZk )V_Z}M4ӔA)Z#PQD?>8q mT6W6ENt%+ ܍n w"Nwr(=qh9VZOڟn?j:RJ("/+aܢ4H 8("=>A)Aۀ_ 07A\\|v޷8-8X``q)S-YTNOi!G;9sQEP%#%C%,&&ml8hq0g)"`wK>0SޚV$t}vOL8XY8A|`1 [KW̬b|6M1z/+q.0ݸE7a-E-!1z7Vi0εV̢[آ[Э-)y nWދl o.CN$O8_>-F. g"]KF o[ rJ$_ĠoQOPo>b_E=nQϕx ʱHhx78-eAnq@:}/Z`[AY [+nQ/Ţ^E4zJ{Q`_1})bw -)Q w?M3gw wH) )dqED^#f'Ym$j%Z|IȒ d9!u)'0  x)h")Hőd H"AAq1ؑ鐗aGY`#bGŎ";1L@@DX]fKQsd<7戝2Ys;վ7= _G}k2tzP,-ظ M,9Iɱ\;~8'#ʵET\` (HG+="-ioqfP~6zU~1KO̸˽Hf5^˲7R3c@L^8b\1{,ܥls]:!BodRVb}gcKȑt0z?sWfý켽*=g $&,o9fA+d3}Nh^gvԧѻ'@̏cgs;dn8@9@Lc 'gqNgL6g1ytк0JҬLeIeڕQ&nmя3""r}=Mf7QO!5H\Tl϶]NwnzWu{/a6<[ani7іcF/ufE*#nV*;QpƜ}vg=stkjC'.|b 9wqLF;BNKU:g-L?0Oӝs˙Wp><)|qǬ3kT#$ձNoLhGY;]bn48w?FUϱU?3 Wg@QFC8:)}eΨ1LڴYyl=,awQosZ=Y sv:l,,K%tq;'yVG.Ռ?'m w>;/zmП[u_Qiݙ-ݐqӕy=~6CowV,{Fe Qz]z-e gp3fzI>mĐү_+l#}g$A?x#NG{FK\g杲ñݿ;;8n)zR+:Y{Svm7:(|i3dkr"tE[GC-X'2O5},^ϴvsx3-ߡ}_  ;Tm'|wXdiV8ByZUIc9{5`=僳v'Xӻb]k(GU[Nf~m!CBA$2\o%l2 v6)ABPYW 1^ړy=fbtFmb;ޘwO= nB$3}htqn[؛ {>-aFIkbkUlgΪ6שW78=Y3-Ɋb[tղ~bαW:r⠝)?&Zh6 ؃߇#,n3o-3NDߤnd{g: `*>`x&sp|ǔF=kc׋rS:[t}w~Nk rwW_W'~4 );0hNGt f5XMzNG bx*ւqZ:i9ĆJ6MM6ֱil:meOi;͢lvl.e?y~l[@"s:x"3H[sd=yHaη^"֫\*`%ZrI5I;b]9'x}sҌ7;ݝ6^ߜ7^i%xE^o9x˽5Γߛ{soNwy{s^{G7en|9c7gL4>ޜǛ3xsfoίxYl1xwc<ݍIݍb_7h$׍4~Xy׍UsVxtcn[Y#э555ƣxtcni~3%{֏ˏXo?Of)~*{OY_5Xq 0@_ 6~w 5~ث~)n׌56]ckll&N-}mw56eS6bk}}hO56П>Eb_V+ eیW6vxec|ra㕍3^q㕍;P)l<)T.T'ZZtn./jˆ.C.BBWBC-x5VͼnPG^?\&\72xSݍ_e[xkOomFn'L㭍??m|Uw?mO+67l-j%67is?mnU5QMv?mnm`?mnmjW?mO{ޠ֨nkeͽxYs/k]˚{>hX>'ƳLnxwĜ@8X|@S"aR0w{ρ">*aP2NH]H=9W3 ]ӢvM5-jj;o0||K мEs4.0]XLO,'XLO~-_`1$0m*aP:Ke|9,ʗs`}),֧F<_+߀,_+Zlѿ?<4FiT3A%ĕy|@|R x yC\m#_<cnļk}}J~+;0Ogl10$5w45pǸ㨸;/S܏) 3teR3P#32 /zE"T.T ĽB*-Q[L[Jf听V@[I["[o E̜Dsx͔i+96o;Z$o -Sw;@Aw9FwQ;G'$K Ox`BSq8<uI(,lHE4QEIKRd/,ߞ?=Bc`QE!^~/0*: JWQma u$oo*ô ӢaZi!BM{=heuQ ú־6{+Dty 9jOuCT#V8!̿P  %BJFP2 ơb␧RN(-FJJ ]2TqT$vHۡ'v!C n1bp;vQp;zJDU7oDMHnMɆAbx"H! <s8H]jX ]`X 1"UJ6uQmT*nWSiuʫ-Sw;ԽHS퐿jP#\>sէj$3LHw"R}E稯F}Kw;^}V~R@򫚏:Q"by?puZzVHRXԶVJ+S)p^T2T-^T:x)x  eOC>M dç>|14%>MX>ift7g2fÏ,?[Jˌ[fhՖ̸e)fY=Y={<dz{dz{<dz{{<*뿧ߓd\cii\kG'=:iN8a_rnpN;t7w#FއE #F>`!.q9qհ, Բ, ,qy6/*C0Tz*b= X~]d< 1nxyU6M*򖑟cy%#pl>BkQ:[VbFլWsz v+e=U`l7ۃrTeǐ6JLS)w8C==!mޏ*@_Zױ߼/ ayyyEsƫ!kSmX_@ aT@M@u~1{ZYKFk h?GSe)񗰌wC09.l><)dJ>@sk 4ZX{$ ,x` H eXƟ!6rDYNτKS-kofL=2TΛY^.-/O8^Q\X.hx # =Q ofYxsK˳WZnrD˭ܺ-N:ղT1@ |I6is˘ab1׵-FG\OWndr ˕7;KX||4MB3c1Ƙ"L0Ƙ` !ii_ZD2X(D(je4* p3ZFDaFG aXY Fv~}u8UW/+.*.^4K.,%_}+ac0?4W.,I̒0K~ 4d%%Yr!f/c\Yk%^K/a+͏Ù+C"̏1?bC*͌K03~2'Ms2̉_y&9Rqfocf*`6?/ 5̀+b%VۅĢ." EcX"VUĢXtL}L=:%va7"VURX V*bXE,*b{UۅUb."UĢ."X4VۅUĢ"UĢ."X4VۅU갊X4V?,a~X4V?,aX?laX?la_ao`=X?MVauX?,Ec7~X-V?,뇥`h0{H1(+OAdِȾH\37}y}~ T;o^T̾Ǿc ; |vs쯁hy^GSή03<pvT@U<)ASjNc;AᔀMPTykp@=X23P8EmD=Szy3;@>V 2havy ^vzyKCDPtH#*&im%X#0bMX3-LkZtXqEkF+;ܑA|G.Ҁvp^A5̋a^PyFٮ4BNu3X^mt@**ӣJ9'/>yAP$OyUy2GMR^99lPNB?U&/)W#&)P$/&%6$ Ir^9K^'UZ 9Vz9ʻ{C+f(+Ц^` zX/iGwځbLH!:Ocm4&&MÚYXS0k۹ i}{vZe0 >3yg ls`Z;3vfVZq0 +f`̝ƝF *@P=<(>P_ϡz uW=oCA륝v6\ ʅX0+faB9aWuOBԍ5@"fCAA(8,<"`0 LfsDGB܄] ` )1dunx}TNj cK`)Y˼yp wX,G70|$@ H$c}8huj1m]GZl EP|s= l?^A }lspm\| pp p0 #{֛#[ַm D#Iԏi2ٟz-ti")`wЮRwPzk2_*#455Buϔ:AJ G;Ҁwd院{yg;=Ef=a_mB䒭Ŏt|_h깣nGx],G;jc:':;:g1!z "'JԳL=6\:;z\XE1|80Rq 8,pJy=^oKVLjt\/x%Q% !IAR $eގEx#!T R1R2ppBJkC^M+5`C-6eP9Nr"=^s&iU0$巄)mR Ra!sTH۞aU9ڕ%y/rV{\ |\|\ E!uxkxli๮!j_¼V9EI~Jd^&ސ-ܓnH L{(*p_l$ p㰝u 8k8k8ӽzCOؐDcn}]E]C{U&4(Wb{Ob%X튧l a; Ε ϕָ I{6\ŽCc;RhsIAISt/SuƔ$ ]J`F=3JGULqcUŇ\فKlʖN[A |r]~K++~FuՔ'5^s齆pL{zoLE$6T-9i{g TS2iԸWuy}uk x5ᚒF9&p4JW4UJUM51Nr-I;ziZd/reխv4Z65Ks\v7n4Z5i[Cȇ籽hg>||x<a^k(UYZĚ#'!I+tgR095|2mk2̓8j3ȷ>3t/ό:ɦ>4ט7-rXN3{4ZK:tē1ZS3qK?M1ۖw,g<%9UY.ƀkMp˖g^`<\}ide̓ժ{ՍVeSD$uzjm<0l&X-iUL 8wZg)U%OEk hZTUO]k0e1y4OZ2=k3`M97U'B~7KzZE)V#7AoA$JiAAJ[zPlQITC:C|[z\jޚSSzzVϋyo(d`(&q𙎊g=uqn%Dq ϕu'WvE}z׹Lrw03\}w>9݅IBrnw xri-uB<նNYqknGzֻDϝq10fM[ >Lײ6N\YVՈrmU=Mޓ8VnMQe[STyt)MeZs{{Z佪-Lь;Vxǵjzu][g݇mJdxoj5V`5yhMVwIkZ] -2kpYk=+ڐ0! dq6h>aR{TɭzVC+p>n3ހgsT%dRKu:uއlȺ3ce{kXK.ڒS Ҵlaej2`u[Tݰr_~8l me\ےlC s[&jqr#YזaYj˶Yn˳5ҌǷشϗO\Iȇ}A|m6o F>Vf3K m6ÐwjL&e)Ӭw>mͶpئKmF`X8k}ľFa; (d6 dsRm[vrIU-} s[m7ɰM=s\D Mh-lwhD--{V.؉ae/vF϶]'7vړqaO6fO'3)mSJzM{?+h|enSmwܶ%{o2mrzE){y_9b舽g썞8®]'-vt(=%؝D]]߽meK@'5~|3Rr|Y86%| By=;~1i=3rSe(1_5]qߤk_kt AOMm8K:>|?v({ü՘C=ȃ'ODGszXDxuAJ X^?;h_ Yxu/5;yu,dW/N9Y5g\YG yGz8<+p_Ӎ8r={u=E(￱'i "M8J!vC!ujOnQQهȕxt+B0yt6iA/s뜶*k( pn:Iux#ng(;-cP*w`(;=jdQ wx([u$qφCb#)n{4Ǎw_qSʰ:PwOK#P wu!T 疺@-u×WBjt? \[ 72Jw\'C>ٝri?@,\at*ρw>o<. s]:ƗCFc.wINܽ/t2GMz61*ԕEܚ_rQ+n(97tJnvjt\9^Er<>$EaiwCx}"t9t*=yNhpeBu_ p6ej+0WNk2}#^E~@$r%APDꀒ< tu @2=VҶq{؄4e1Ϻu~ν.]=w{ay ,@ ryXPTk=AE$Iӂ'ɐfP3/U=ye!@Rz ! FfTJzovx 4> CXqؗOq 8קS@>1H\ǥ@~J [_{aM/u\ +7jdX_ SD^sPoDD}c1P8 =zc=Ь796Zd#sD[z[<,36{;}PgR_35pD3x3;pI3ystgq~,p!SÝK5+1qf_ zQV?٩tNc`JtnNBuIrZh~+w ,w ,I~L~Cy!aw^b;!s,0$u)i &l͐y3lL3t f;9`s5Xh|,1;IܰߩV`AL6: 6;ӤÙl096AY8˃ᘳ*(N:kNz 9 N Nup | QU'79qø <唂 7a׳΃Du(xay*xѰ< 88N}s EIѮtGߞNg:9l{iW^ 8s0.,w¿^\ mu>N7tɂ+j![Zkobk꒮8Oz+1]ו+k{ve ]۝]ukzۃ])*z{{|+{sêh׾޽ǻzh[J W8KţO /u4l{Q DWA3]ό>䙉~d5wzMa>{'2oB1kD<`> rCCh<&!SxnS,쒥Ȟ$egY{'L+_')bF4$-t\zܛ$=.Ʃzމ ݈G&n9n܄ ~Gvn@v}DC"Z-D'A2@'!OWd%Q2;ɇ.qa7N,}oyidL*΄9T11z{Q1Mng:^ɿŸaȿߗ7?b" 3 w{#iwsyE2忑9)ߘз{09 "Z(W<Ϭ*^P1S|AQ|@`>T7e [&YE*t Q+$gT˾P⌬~9!WW\UŤbRfQL)feⶬ[1+c|*Ve!ŚbCCbvމIy\'byp+1l4sXv/1ߎR|'xΘƜC_ը'bkԘFb)f6 VbTQ̿[kl{!cD*{9+Iڸ|8KxM:o͊|xW[B/ZoռywQ8 q?_GQ:?Oa?/we(v'$ )B:f=4 Y06W+7TR'hcMF .+C0gpXNנ߬k KIEN$C> KayKJaA*kvuw_FOaI%{Db%6҅ZzIy|%'r^|g|_eT5|=f^y3ݼ~њv߈k 7aمVV|Zy"ZhIhh)hO?VVV,Zy&ZshYhϣ@&`A[m=m=mhhC[ m`2R?gbee]G| rW{0xW5W5W3<Ԧk7њkњ zf$_e~4l#ζ>) n/P UMOX`)8p̬8c,,ܣ}JK+ޢ0Xj?:Xoi04rklQs-j^&q8qh|7-"aq)tф,+7-o {?H\7Y_m-#c|]Mύ\OZNMSt8c9k489yE(-#ne7}q8n0NY/nZf)ZI mܧ˂qrXP~elv1><(C(Dp}SN)q bav;.pbʟ︌sL1sA(AXQ.VpUb'P+q OQlz?x5ӉMwYy5 ljS)8I~t5 O5;(€xx t 5ۧy;*~  %kZӏ8 }Yk0ZIw<K܈xq8yӷośrݲj|мոݏly_6ѢռumYۏ }Ixa`>~~:&`{7q\ݴg9X}_ k "Z~znBd=Ij=Ca='d[/ Y/Sߎ .Xng:&Yy )z-M;霈zmal]eh]FD%\C q2?ğu`~΁ێؔ1[;[v=ښ"S6c=&d<3{qb9[&.@ /kz}AM8.x~g35c1 \H4nMW-[1Hl+8 a c}q-sWYaʖ뛶|ᶭwl%’\XU Z0%>O[/2)lj|.6_Dۂy3)7E_>Ǟ-y0sSڟ͔fM6'=nSM2ۂ9 mM%Oq#~|m9f<׏~x?5UEֵ0=-|On?n>4m39/{]Uu~"#ҔG 414"JcH 4c%&9 h)\1r)ŘE )Āϫ4R̟)\wobHvqhۓ{O/}cŞrZ‹E=ADro\w&ktlZBf[ᦹR\kܮ=f[un?|73M(l˴f۟%uoۇ]A=`[{n*wf;$VyB}x#s9j4~#ӯu{hf ½xwcq[QuL3hO/\}ϼ}gq.)q?p)XK (xSLm[ze; /߳!ʯ,lQ<2ar: ωSHBt.\s12 r$-9kO|>ߊdȑѰM .~ >2 !2 )˹`@$ -(HdD y# 2# 9#Kpf`bdYȪWA^ 焂6SH,T,/X9{@\*R[&R"{plFN 6F #9 Eh *"W*r6GZ8u= є+߂cH~XphV{NNkڃ#Nf #Q͓pVtq-i9 F]:iWY&ɒŶĶB4JW@of F1H3ҍ cd4D©F,d(FQh7Ke*cQjl4ʍmF~Qk̲ Tg6`7+ ŧ:z}ɾ`pHX_! i8}||38Q|/ ^-&[9v{P͍ T=h܃~_=hO) ^,* }}q5܆&6!܆~q0nCmh nCmh*nC64\4X2 q:BT }wĝ܉ŝp'mK?K?)wON4 wq';܉q'K۲ȲHzwp'܉NmT鿕얦NDgK՟HKӋKj}A/ӷS!}8`&O=\8n7̸s4FPpt+bESC|g~Et!.'Fz";J'(8w|Ћ-߇1"GAz"_a,i&c\oiHcD K)(h*nZ(aaN1o-!%nDܨ6㑪>Mm_BXxGe\/f{ݢ˼U$iW5zw:}#sbE/λ`a,Ţޥޥz{߻ڻl`]ekᭌe>j_ޚطǩl Ib 6{OQs 6zC ^C,X8(C2{Kwuĉҁ赺Mo-uz點AO F֮4]Q20-J8GnoYϼuSOb$깢z>I<#Ekc@k cEx[O#BmDfc,1ɞ0&q|ӈަBB諰đrT<G4/ӍF(#-3mbj_bcJ>Xzy%&=⤘t7ۍ][^QM-_aE/=4bG pgdg-zM1Wxt &5/%47bIQ>?dQ|!<_}#|el%f훌ї|ӽ>IY&Y9y"_wo9xVfQo vn3|_oAKe,ULjjW;NڧJD czT(bKsDL+|$/˾z'i?ݟ9ɳsT#-ßϣ룹лB>O7 \S<2*\Q\{^cgpZdwG{HzNR2ds3Cset:*^H_ yƤ&]S/5D7]d "IV'hGGԿJ.Ӑv4ˑ3hߡlAr_&M<4n9/GnۜY&1i t58QQYfXajuhCT֎GtiGǿCwF+޹/I.w@L-lrPy.Ԫ|$JwqwՖm_LooG N$z4c;n#((yrdmm,_y$G,NڎVMkoSkNibs؜[fb~Bv1,;tQX^_ XLT"NjUb p7MI,?;hMslu2@69_MۥtP^t۽`':[ζ3qJszj85%6N%bmtmsnS \~ls_v@'ڬmVjjCN|~-L]۬w99|Һts$'ANZ>SNs,18\g s"<#%"oq~nW:Jcn}|s\-5kP9(A>n}wn|y'O͕mrd|$S'Cs xo{ CLŊ+xce퍜f1U,}2\j3q=M {.j doI16̟|ܛMsQ2m"_]pܺa'wSV/침oVQm(jt@_Z h_F8j>ptU1j}c"ۡ&6{ІŐ?~a֚88:dR6=ES +WN[ ކyu@r?1;GK5茀p!Ցȁ6o>ɨ=&Ô+~XkUcZ $Y i)Ki^MK,'\ە TzpZ_a$>$(֑-v߀{93-B-x;w Q`OJ+ [X o:+hU`4p-kK0p&5^l^4qb`?$- -Ђ8g!9kJ* !bcD$4c"#Mȇ9JDH!INd˄">aypY ^o gl ꞁ7QD^5t'M4jbdG~{%7U$teL(F($1G"lM!| O_+OiD>dMKgOdb`/xc+t0>4́X`_h=ƣo {CC.U=.i+etDo jҶs]u+ZoC"[9sdY9Uyija+Of_@{|+ ~F.)W3dQB/2G9@ >_>|_9 )Gf|>ţL3xfN.%7b$Iy|oD > mB/#W\LL@;*n2}l-$|J{Wa*-cѶ#hGxd˓>EGcw:ǧ:ulMy6UFJ'-Ԛ\B gA߀ǡ!xd.{wQ5yXC;'ÎU[FݻhMkF*Cȓv bɚH$.va9 ;>aHFAVfn ='gnbg}Tp]y )g;{ O$l~k׀e-*as- Ϊ S> Rx!ޟ(#]5h y& ~vks6}uv>"ndfA?:LX,6[>yihv>a7Bq" Qmb9ށ<BLd6Q\pY8b@oAS)\BBȽX,ɚ(I!fk=VX[q>UWX,-EN}?NcA~P`׷7aL bwnA3svϴ  8$ 1u_ {~obosػaW5r,8@>c:z0 Jao!.!,Mk!?hR!UY@|. C1nGx`w&DnJ0C/bxӱނ5I}jUom*Ti,x 5p~yüna6S|qtN*._ ܜ(%aoO1KXb p6>oN63v+t~ɑA=`_E;{*1-ümy; yY;qrL782e-bMuG8aFO@п/UZ1|6W aa{_}#j/^O4-Dx15X dNf^C؟#~ޱL iF n4 ?OʯЗ%fڇ$hB3—" : ٕng#}8E-ӕߋО?!+~Ğ룁3YޒW>U'w|rW~aZ,Ў1FK(o$\SJㄲsm%N:+TEo$=>hS{y!lYo KԁdJ#nA]?p y;8=D@r=k ~@H5='be'hлJBel>w'́9=mBOW3lٚ gcNqNpݗz ubšW+neՇ gI>e:_!Vm AUb,+Rͨ26_*lG7Z,|L_>a@ssNVz[x ;fkqnޙh-8>~(gb\ցQ(Q؆xW1x+!u kC1S!|1ZdF$@Q O NUHVBWm&$< fGx7XS'&m(d $AT;| 7lK* KEx& zmygWBGxob,K(OJ׀ZxwO%_ay^iC/4U3-+G,KLoqkhZq%$W yQ|"0x_L~o\Oq#[,bVi-|Hr'F+":Q ת1֛g?mODl*:t_=ͳTo? 1ʷCO&$^1"-"?Yy:P21Țnx$B)XPqPD5#)q=Wj<&o@`9 'Ja9bFWЩ.WL`[\0y!q"E6&kG.C<`4oJ* oQ1^Ig}@7 -\l_-Èf̈)Eur_oAl`e +}Ҍl|fȧyo-GDuk?Xi Z:,i Kh9<< d p4o"wE_:o$6gQF!4C ~c"^9&2bb֝Yay) ok;Qw"?7ߐfWkS2;9q(F?='n,R7sDș.<Z_QOᬊy\.q %U _yI+G#rE$iJg-fqaV܄2J.,ɨ5 8p&+g)Xyy!.,F%iJG-ɢ$FF [ŰpX\ ܮ}N*\> HzhN-,3/a$}揰6 vPk¿7@Yãl@66jm$ul I2 M#RMkKh[G-57eYfe/o ooM[J~#nKK%E2tPV{>s>CI. 0 AI"IA0 H D2H sNdəq𺿽O}o],]j>agoAfgp_.*C=H/Ag{&Ji3MT4Yagwy@s*tf/f/yVX 7(4ԀWx63^4~T Ћ!YRIRpՒŘ9yQsy9%ZcL^ek쌱 3_n*\``1ZF:z 0;Sf>j{ S%t Kxu` Ya|:4_XZXxݠ  킟d[)fG YXy@aP]k `tmZ^A=| \͠}X:HF_O. `!HƂƼ#6M0*8A[k* 4d9^5KTo m$8c2hl mͽB/h$p[5<eNp¶ ? y>1] y ~f6VxD=3/1kˋiC|n+؀{EcU`p;d^e(cօV zX;·`A21|2ۋۉ9؃ݠ!ɇ5Ȍz^$c8S0wRPx +`V_vHIy`_7!+"aĮ@x^cÈ}rn\;8 Q!{ Y߆13嫅@"H ˜7[SJK {M"zADe#h /D9`]3:y bJ15V^7(.0h'#p AHFk-A7EpF9ADZ`8E`=p{dWDvg`O2u3A>f$Ӷ 8x1/# z9 gBrA/= >Yp0fGTT=@7_1-`qv>^0nXYZϠ/f3onL~K@BoŽyVЉuEUDk0y:4":| /Ek 32KG^ 6/½X >dppu8ڼu, }KWI%@ =(vHI+e_7+0bW 'a>{ky1o'{J`qoc?ېG_+9p^V-)Hp~'ތVC&x+h l6aYuN ,>.AcX}Gǚ n >vHȄV[ -/VSDhD̋1@Ğ܃Z6b5J(V A3H'12"{tk>CҜx֜68I滱"|n8 |̷- A{A n m7=I?G¼6ģ[gNQj$!Q8Y ӗ-Z'p\x9![pj :V,3} "~$4@8!)o8,5U3g#q!SƦsz{Lȼ ͪn֪W> ɾˣu#z]' s)~Qd@`KѠ)4.e@Akt;C= ͎y6S>БPo(㠧ZkT".8'AA{Aρ4@@ 3 X8a<薠`kzZ;AO7K:U@T@g@JvyM9 ]| Y#Q D%1І~F*b>Z+טB5?2% lƆ64~M|ykZV=w:.47?+tSa}va.gz2<w?# )g3êX3|[ȋWLp ]fEBqi!L1f(Ŝv @R^31bN;3`-F5-$K@ ƀ axc֏9m$o!쯍 g ^$7֯NKXwTS*ݬKM_~h*r ~q/{w [NCؾH62́cy +{k d&K`Rq79kaO{OH(©5"*{u60ay"xo?S+Tu6@2ɥ(CP:DJ=b5 /jeg'֯ll9VD//̓qJ|Z#ZZ_ӯ"By@xh$;+f7yi%r*ފ,њ &AsUW%``-_d~:6L+#*Nnb5 񜄵0Cm_Ųcf=3}ƫb97: JDD!GMg" vG !lH/_,? z1Sa5fI^ nŚyZF_X b. <蛃rjj: FhB pROY46OARBK.vJ,w!7'5M mţ0r~4ֳroʠ{J6GJ>H7NWnWn )ͯFAy _^'SX -ےx6>l^9|G0b[`.JduYIDkȏ;D`^Od`A?=,ytaЯCA  8á844]t)}y-#LU 6-0hmy L@k嗠5GB[8 a)//SAoW=X λ5ɫ'=NJ`. zACMDd:y йa7ъJ>%1! a$ZӽE-שE\+TEEj*e"R*FUZ5:ӻ>ԕzP_>L|S2H:stnO7>:g(Uuz8L jCoԋSf5իA})l\4 Z7CԹXzӛ$5~4R'NiDP.*H=KU=E"rS4zKQYHըե&B]^4QgAH߂PNXzSMGM%zԞP1eڪdVU`s`[``<_19%Zh#6ϴjչL0hq`$0'(|NYՁ Zwjll m۽E+k p$p"p&p!p)pV<<ީKEu]C`AԵU';fԍ|"`3*]:7mݻvo G'gkd/nnѡK[$2&0أsnQB=zĔ< ll ld0888^cTbR*&]S =z |L2(90T=zv!\qړ,"*Uy:DWyv_~8΢; wtK?B9PLg? 9Vk=>?4>71,ߡyЕ*3e,Oyk^]St%}tOa xCKi ,XV5dYƳ9l) ,[<'|2_W8EHD"%!&z^̊:i[~4͏d>~~zƏggJs_ |4MܧOg.^ޏ۟cOz>4~w_4qu~Ͱ`=Zțc.U|>zܿ^HH_k׆[Qd|R/iVd4iߟzߗ(D4e/S6}Zik*Qiϴb-lR#S#(T[jZ6hN`7mvg}Lz^=릉. ^g4|H{DX,3W#i*m3Ȣ AmU[[mF3HsW 1532 m_iL[a-mz&B):m][E <[~'yٗK^%E[{kh{`o-в-IrOo3OnGHLګ­Ni S _Hg5Pߦc?fO=1kJCX'֙oX`o8`#h4>1CcƱG7Axh"wK<=Myfgi2^<ףi<5EtC{m`ć򡴙i B[~$+b)ETU)U54&8kVv+Vncavv;kw;v+c{^v/V>ʅ^`BCRHmN_[;{2eVT!ʢ"UUE)*QQ1RCV zrr=* K=9V&Eͧ^P/P~L5jEUՆ vVT'*.ꦺQQ/*^S1[⪟G1j@%`5Jj(RpU#H*FQTF}>85ʪ jSOT}J5Eij=fTQR9*j.UV|>WjZDU R_Qu^PKRWSM\-ZjZA/j5F{ ΝΝ[ڦg}Cgjζ/=:6Tt}EYUuPga]3fXR ~#nQ3uGݡꞺGo>νWbk زY3L۰6Ĭe2@2``E5ѧs࿣G_4yb'cQ1~dyxn5TP-j@녎~Aci2ͦ q:GW~'`nDo=""gD\#ŵW{~Eǵg\#ǵW }1מ1^5^ˍ5.C\{F5>#\{E^Zn q3b,pїng04'<231'g&d3S|L=2 #3}=2gG{dG>=b#_Y{K#{DLG# I|{#Y{;#|,c3+|Ϭ=j3k|=#}l=V#|l=N#_##R#[I=^#|{G9{cG9I3?9{3g9{}\=r.xd?O0|;W(^$.:$Dkц,^t.SPĉ8"^? }E_rE?1bB ¥åqM!+mZV>N׽SMήWBDQs6%:, `B7nleZ٬hwZ?唏Ym,i+d9k-e"-seF>z֪HU٪LJbX /&Yl[6];.{~ Mi4fL3g4Qgta:BG1'$D4:㜧 3]Kts I6%}z@C%Q2Pceސ_Fuޘ7My3ޜ-xKފmx[ގxG;.+3Q~'I?O3,? g~_~_E7o~?W$SxNABX!EPDxY4ME3h!:`1D| qS1U|%ߊbA{>/8,8.N'qJgYAu:bYǭI'u:cY Euٺb]Y׭MuۺcݵY }JYIVba;,eUYMV/%_K+|Y6Wk|]6MdSL6o7e R|KveUvo=e%{wd|O(r@p9B~(Gʏ(9Z˱r/'ȉ9I~*')r&r%gH._%KZ~#Kw{_r\)Wr\+r(7r*r)wr+~y@ayDqyB?S<#s %yY^W5y]ސ7-y[ޑwCLdL)25HA&yr\ ? = P;>wC}C  }us9@g3 s;#G(g3ƙLq:Ӝ g3˙|q:sgY|||||,us:glqv8;gp:Qsٹ\q9;=' YKE:&7OFt{Nb,$3EԭK[Q2 q*ggxn#HVg%ge#cM M<47g m=%qtK_G?M`zgqbP=HL9M1gήz 牬S?=rsBN':7LOhTFhdh=}Y4nUc-dEK6DS^vekIx:N5uy]CB(ZZF2t;t[S}߮3?[7;kfZ建YMڨfue:HHSOVžm5T.۪_t}U>̳a;'_Gu13GWua;?^7H7Fn7͍v9'ܜn.7s܂n![?*B⿭*Tnu9Qwa>1sz2,7U9oʪRu~6չ,~) QR^^5gm)֎R@-֙Je}&iԜ}RKޝ{ P> xS>lӅ+2 %h,|QTUJP«lk/]YVeYh'.#0<{"0:0 LLbSx`q`)>U l ccOӬ~6Hfm`,#+Y[,,lkL ,,Ƕ؎``%3X%X VVg55ٞ``m70ؐ |llb bCmBPP;ųkNau]:8i¥?(iz& I H=dL(DA HV xUP 1a朳Ŝtw~|ϳCꞙ>uN=51TdGlZrť?k޳ܐ\30NB J4o큭[PU6@s.pL!!^U6PMкO hCmDiڔ6i ڒiږhmGoJ|·|U>C OP^AQP'$||4_ A!Ef *dG BBϙV_f E< :Bn IQPTQ )JFt2&BiBX +#Hc}OVǴ `F CrUFxzx$@&x<c 2dzld9 Fp?~dHOSȞ79D8/u@f̅j ңd 6їLcCA4X$g(0L$bf3sYDjfRe0Ws;}!D)Ș "C1q_A2@[r  ȭ!W uL6u"[t9Ѭ .+H@B.#$D#9wH%^ KJRc60@6Ct4 :c1 S˼xMm2_)+!D"Z@\z *}̄ר5++-#&Ad. s> b+Rky;}ؘ&"GE!#&V>Rd™pBf>)A5l?GmCfrLȼb>XQ9h u(bV :ZBlؾ"=x.!x>@dCt@BLo[dOB0!!!!!yC"C CbCC,!%CT I R'8Ip]@Bu섞Ga(`U8va7`8xN] +ZWux3ށC>}s?o'9JBRZ>eLY@:a š~]݈;9=;;# q؛aQy{GkR"r;݆lHKZ*RnH="Ƚ"%"l(R%)0!@ <[VPG@h >:ʠP#@7GcԱ8ܕ_=|C{@}N=Pi5DPoz4=PL"yD"E ݀:!sUoAh>*@:8v ]B7! czx1;xSwzǁk#r^O@Ax#&"qQx31X8/AG}^m#2 rȐ/vD6l4nOd'\H췔XXXXnrbRbr+V˭!R#=Nz\&q-mHk!=Kz#"+X' A,n4hii%c/+毐ae@(!(/|LB޸}qN`BhFRT OZ~aF%L!)bfv?s9b3G1KVҬ+ϊ:S|f0 L`Oxxx8W@PHXM]C\!)%-#+!)-+WkOO/ů%DAHDQJ$+Fb+$2^ q8I%.W]!($,"*txVeYUVʪ:5H! ANNBN~fID2e2"(!UrTnv.A6U&<@|lfn7ٷ"OȶqW"HEbw A$vBbw(ݽI#} %H=DI:DɠNW,YbbHo"қ UI?~4&[͝ADPQ4e~4y}?w*S'KDLBJ)%T#T' $"lC vD:g/Vgl'~bSAg%Rj+iA# ēiēEMY,~f6BiP:e.AGӱtH@wtӉ?b(hEOB{pD" HJd0aa W#F^ŵ}@0SŬ> F*+QJ&Mq&_~ pL8n RL8& wpL8& `Aΐ"L& `D0a"0L&L& `D0a"0L&L& `D0a"0L&L& `D0a"0L&L& `D0a"0L&L& `D0a"0L&L& `D0a"0L&L& `D0a"0L&L& `D0a"0L&L& `D0a"_r ^%`1X*^VQĜm (mqQrlg B ΪIr;(@4?y#g`B5 BiIVڰc"*_ Tegsƒ\`m%SY\jK{r-gi8Q4rRwLʩ")'jDB2ewKcc9]~#UONKn0 Z^MLIJJ1k*egg'Fl:rv-\V91X*,37mLLIM3ey;Xs.Nݼ]d9&tQHlZFbt,۵aSـR1Fe>YZU=8cV}>3ToyݔS:ՑE.#v[Mt#onꢙ|?=ToǠSC5?ϟ7lC 6̚si'sVo R"R-Ȭ1+ϫyk!Ѳl=BszХz,q oo,lj[Ѡ۵EUo 8IjF{0:gԗ[n:Xąoh+E>E^<Slmӆ$}MtrmD~mJZr-fH^ioʉ``Ҵ<ž/6GMsoQF bΑ9)zH)Dafƚgg'\Xi,ޘxTIUsiEV&%ή0z篌i<:^WR_i5̻1;#P鮾dD_XwWS^Q>&\nU;̺w3oO?tugGvb=$Kn}]b+]~SmeL{ذD-F-lۺ"{ܺL]X3pgHg s '~3׵^trf\V^UBM8EF'q.[IwS^C WOlAѝ_ ^7ո?&v?[KyI]Ռ{Y`VG-|"~+.DX&Kc]C۽;-0ej龜dvt U;ya\SL1>p8W5ޗƾؖҥ\ъq@݀w˛7&lM# $(5ekFC/ki~S.2kβ Bpr2*1.1:*=֠Lfb0W{;3M;~?6Gb 208#dXG+ɧNz2a;n铵=m}k4T؇o_&)ݓ闚#K;KF8fDW*yx͍=%,^Y6"/ӊd 5yƹhp͉7ڈ榛We؆R?^޲ SiuglYEvsNM 6]W^։{fԌYKQ9'U~ s߿NaW=) gKsHƒP8SShNMԱ&۲,{uX%K^5צMjPϠ4O;,cefA{g{LHnxr. zp>WgQi:CAV(֝Pnb. gQ(];N4XܹnZvj|ֳU↓eˌN \4ɰ:۞;KVOٵc̭=>t|e{ē֟āN[;*Ai3Z͋up2hlyU^W|]|FZ{1 Z&k}r%TH%nΌVta)np)nGKTfc]\䓪BWc:/Z5ޚW>WVFo93<^I4cyo4eY}).pvY<^V4gշeus5bٙoǼM>}C-Yv^_]woD]|buikB$Y*6փ>c5j،GbxposnP,xYaZd]Cނ5ƾטl\1U>2ۼS= }Οq|'6-g2T! W)oq]9e~ u9s =ǓQ;ٴ\{i;Zjޞ?sK+X{O Tj/uE 4f잧+}`^rI{K^׵< '7 9¹m*,[1l^U!{`mcnZjU9s߄sK>MpᄏoDCxYĩǭZX}Q.˷nJ5S݀ES2lm#]CnE6TGQ[>ߌϴ m0E#+z4[7pk.kQfr~ˣ^طt}}KmbϠ_Jݡ<)t*d2~I3{j;P' o\gƾyuFuijo },{[έ~3翖*xqG/Q _[+`ɯCŮև'#;i,eЩJ^ۮ7Ca&>$ţq*#s&vl_c/>Nk2jj޹W-}T7uک%)sy}5Zc(7w=~RVz?{:~wN5R5NT]^?Ү2 'sq5]Uh+lgx]otnRO#Xq{n{LTgol/Q[KW[R5LamtغDѡ.6o*hHsKG[%^ov}E/0Rxw?_%{8ʅgd~u}-d[cq/l! aJ c/|$rQ!5@&i=C 'mK,c֯d26^M:,*q1>"qE̐?JD( %I8 P(D)2M&`MLIOJI4!1cT.4ǗmvSj-WF< !.n2à'^uC#dK7jWg"[J·]v s0[X /!?lĶ;P#R~,UmlwߪxqfieerΤ9*[|d͉ѻsc NpVaAc/S,qWmԔ 3ot;3zPb6>}—rRȩ XnLnϧgSf\6eFrlJv?~~EOZە _ -Sje9˜]]"#?ے<_Wb~kWO/mܻlvl[sˇy;;]m3K._ﵾ&51uiL:]5JY:3#jʲw$>|O _$gz]eRuⓣo 4ڝ[D~Aj1,@}DF3ma+>u֜;%?>JczX[PC~QX0΋2'8Szd-Ͱ'JoL~/߼8/2Eʿcw΍1B` endstream endobj 647 0 obj <> stream x]j0 ~ CqK{cClJfXd8d/t0 }i'7'8-B'uyv2QiuN84UנE{r!{ayqBJP x5.ؾus|068ȆFTu%@*($Oߨ~_xX{,yJCT>?!oP endstream endobj 648 0 obj <> stream x{ \TUsaM°o3 ( *%0(03Ro- .[ˬLU+-+L{f00 r9Y<9 .3ǫqq; 獞 -XЄT^R9gp C%ڒOhaqXapmfba啖9!o2 N{INCv/ \RJ1q6@i&‡Pn֛l~n8vY3λ2ikY viׇσR<1LvNYGZ_H9v Cұfܭ4r@ U]0@*>DGIJ׉1n{Pʸ;b1aTˆ 38\.Ie䍅JEGh&i f/C_i'*߭_M0=RBrk{理"{KX"fYwNg_z*A25D9 vpgDpAtW&u!;x z'x7 7\91!BrC0#r!@b("*A a#!Q ш1 U8xH@LHD$HBLd2HHA(@ b*`8 A3 a`8p?gHt012 Y0q$/(88"fC688r!& NaL ya TĩPX4t0^3ZցJRR(C,r[(f!B<a6bT VBL&9A5b5E3-`AZ,BbA0q.(·oq4 6xCðq1,A\K24,FFX+a%*x&&r"(F\ !>xZĵ5<O"> SOW4 <Ќt3ql俄 q<__͈a Vĭ"/!2 X؆ #n;`'9W_]v#`xuqG~88x@|?7!x -xކw߁w.{p0pE< #??cS>cH##/pDB ?ēp F4A<mi "Q8"-|{x~@.!?K3?Q~A/p2\UkpW :{﹁ xڑA'QXq( vXwNn>'J߳I仱gvwd#^ r{ ݵO>gßzL}>&7jع-lpsD$wa[lzLw1{I^)yv\f1z ;83rՇq)K U }o3}׻^R`-zfw_rz r왭Cls/ O.lꙭ w•޸MpC=ݻxuMwb";HO)gvwxuMw%-{fwگ~0T}LIAhS}Cl% LpI=k}5s/h4gvne14 w^3 뽟>ǔ;H;83z'"{IyI=G&~t5/ypy=k{?1}K*)Hms𨾷(虭{? }{bM8&⏷#C!/oW=nrswtB4 /~DB/Tr.{:x4Æ 2h@D*!>.6&:*2"Rr֣JLTLe!gHEЌ3fBB[YIeY[ޘU83zy|tD4aOdΨ_eSf *X,mu⤂̀8+)auU J2R*3r%@V:(K3 Pr3>s|bKYN66.͓ XX}`[&|dQHǡ4+yEr%U6,S4:(G(g7Z!>df7 gqe6_'4op~KZn6Ƕ '箄VhuνY"hatjRDRЧ@.a*$Z#b:d5* |UPrW#@yBwΑ+@ qr+ְZcbfh~@|\m+4)8|`"V[8X xy1c]88`hTVH(9Y5Y(YYry#y^VYĭ?WGV`+b<;O=iZXdmv~=>](€\X{!!E d)G@lMm,$2d 7j?,[ { Q<>&NS( ʎYi;-iu/Yp AL# xd+'㟆xly!Uqp^ xL /(gɗ0I0ˠq,!xغ?O>xNLj\@Mt0vf8! dVxBӅ72Q'Qy~.3a+Z}BYW G<[_o;R/A{њsX x5:9u>Lv,7*a,h:Xy2ƙYOHsƏ o Aj;fzDYd B1$,DVՄۊ7+8Y8Chkѐd2Iʈ%VE#@&2e0Mia3m/`65[7wُ/0NJ"F*LtItY!Vܾ#c:|^ALLQ oՠU&zhx}'xUh1Jޡ +8-%"!$$QxMq%BC?x _he3+Sns Gg%8(6Nge- IYv=`1jу&+wDCčxY;{g%IIU*:`;-#YJ^"X901 D*5 $3TVGH)ϰ X8""yDRypS&hō67:a3}3_H\ lbLj ZǘTnD3/V&`+6gP<+i?pn2p|)ڵ`aŅLl"l}_OnLFd~ ~E>LUCGg8p7gOypm*eY! T=Hǂ\"ֱ, ɢS|csƷ(W4NT'& D| |a. RV`wѿjE=fW*iÉ{jjCF ?09 RO2Ԟ}(@2BN3 餌1n8o&'$h4עf͸HaFE g+ɉA.:AưN"G<O\B $ He1:LXvhDi?sf^N('׷; S\nx=qxZZZ &^CK|qO.OjC<${C{fsI=["do;:̺ ۩_!ZQZbU WE2 YR UrʠPe+]>|TVbh||=}||Ho$с*/$ۋQEF8NO$s W~#!;qCCF,}Y "-M@TaR'vsM,QM !n>^! ?BBH2T*񺭔a';S¼sua'*ۯ7ޟfk-7Nhf-l}+H4 M؟ pN `CÔ$D$#$c*:ɩHw%/D%q{qWE^ )EEŶM0|/*ܨ|Ri\DDFf NFF(C%^>lSdD%'fXF%fY#ý慩43gz.7}/~{<ӥBٙ ȩ?,T-w]3>!rYm튣'/Y 5HܵkUQtĕӊ3= ^Di 0l40Q-u6%jJ9EU81F.6M @F&.(Rr N<"I!=00ZHl"͢E0&^/ '7pjԒ` A(xd{/^yCۧkW4"n`bC/~~9)xP͵5Qe̢zpÂ׾F/>^}g s}!d7dA ?'C"6MAG#bǜ8cǞX{I=O&U yn.&O=uLo]g@SoyNr̰Ӣ.uNW WOL3rLFz 9܄ܸ1Y9yY\ܬY9rgy*k\ rkhv`qYǥS/ SFg+7ʻŧJWQSMg%.5Uqqn ќXh{_U{TV/FRmqE<6AX̪6c]UQU(*ai<k, Wf)WnOGRȩ*q6FJuTcJ-[ީ ʰ1QMtN6r:Z*6Br0^%Gs*6:w֦S3r T :.vmWd= >첄^(d2w]"EZay«^ cL뢢+Q тuT3!gݴIU!D`!0F❁@O@0sF",! (Yx|p9 mcZ[zk2Xk]) #h=:KLt)A):ڣm, =ɵ tVU`T[tr]Ė p*a+[nPRQ.z:zҫ}K^rkf Ug Uvt` I#osUtRݼj[Ìv}UjkOΕO9jS/cgRg&:ڣӹ;:St7ﶻw?uE$JeF"bm-(xO,].]V̇,}ڄ^ iI9 M"qY$u5M|lrRy]w!Nqܘ*]Bb:&(:eyfAh "L!MGr_⒚K;r~:yuvƒ~_~8yCe Vg]tau/0_k+;77~W^잙T6]۸ywS=RtAon篇䒽3JL`\(Ds'?U[ΞyqE̛C}`fږ%VxCojmm"? sa}{? ;qhu3ZL2Cї־kο?|e!ۗðP/\_"Èμ,:)O0+hz‹dj >t,NQlߜXmoZehN-XE` W%!D>z8c'HmV׿+x#_'cox7,z^qNHX[bkL0%.iyʒϯ& xsdܗwiy{jOv>o-ӳv~2$7 %8yus>K}]z<̌?NGuJ8BUxЈބ e^䶉Q|C5,8Ժ^xz["|xM=g77怘h?:zw~j N͘_:`16d g^^:c4no:6EwnBa3K~38Rt]sNڜIUj"#_JO\7oYxXk,ڬyr[G_L;gd3;%zʹ׽FʏO=Zܭі#.m}pOX0Cdl<^_N$GddSǨ#i2ZxN?o:.dJi} d鋜\M~k{ۗ]>篏?\v{%G42?kģ["WyqtS?񗀉a ?VV^sNuǿxAsӯ,s[7>1om˵GP0:K;cuktv/qxuI2ymxsyhܜԾygyɕG>Wkܰ+qˏop BZ6_{|Ֆ}Ϙwi^R7q ͶAXaWuNjzL+sn3l /TIh*L ХHY( " HSDP#EM+^:"J]{g?g?9s23ya VpH4|+y=m5Y$&z\O  h&dr7Or'^cJs퀩hVI2))pՋ&1/4f }[ I u.kptVdߜ>蜔"إxJV{Ew oB^p(ċd~&8)% !ĹcTpV4a46͏EW+N6,Z J8meRYTc#bZs-o(Oivu҉f.$TBQ($&ੈB%a7X,ιP>Kl0bNg<=g-Y7e7bb;k⃦FM{좑i$UCk3u%|;kRw(szp-kq_+ؤw' 53MqG"k-08_TKpbJgt܋#ڦǤԝȯv uR}MK5Ck}aP2} n\l5>2}<@w)N5FPeQcܬꐍB#o%ל0żxVY:9}QEeXl$ֳ{L"X<$! 7 8/tnQrK|ַm67.w):ʶd :O uu]m}K`ώy1yʒ)VV "R5hSg|!! c-*to눏 Z f-r5Bnmd;}=cIE%[t*2w0iÓ!ɢfXEcF{ɫ^D<ܥ:fYBZgp&x=\̚B@5* |d̆U{3zަyoޛ.]~ gUj'(vjk ?S@ɡin MFaZKYIJB&cvhݫ"rm!ۏދn}XcD&?//x}T_sF윜d#!A)]N_G^Qxrod-Ky"H_CZhgpkK@FiV\k[Mc2v'f==?oS_Rτ}MИz<J\d>{'Gߎupד!L ZSن$"oR6 f޸704gؓy핟/vT J RsbAitt0̷;?/wWQms2 @jˮBNTPԶ(]}﯋>?7Hdn[3!:{2Afd+>ZFf> ]ӬI_06H^ 9:M+WUX|>%`ȢSdrD]R_œ@=݁X <2\ zLt٢b@WXF ;պ>VhgV].5O֭?5Ei`A=t'Oixh/3Wn,3n;beUcXcL:IQD 4v:aZPd;mzfmg+_Z@lD(:o%v|_JWk]{x q  pL`kɮ;Y2XI( j]58BҐ TY5'&4Wc~d!/j:1@$Yg2St3GI% YSNli{,t;/>nqETgd'p"6xn2SB_AO endstream endobj 649 0 obj [ 0[ 600] 120[ 460] ] endobj 650 0 obj [ 278 0 0 556 0 0 0 0 333 333 0 0 0 333 278 278 556 556 556 556 0 556 556 556 556 556 333 0 584 0 584 0 0 722 0 722 722 667 611 778 0 278 0 722 611 833 722 778 667 0 722 667 611 0 667 944 667 0 0 333 278 333 0 0 0 556 611 556 611 556 333 611 611 278 278 556 278 889 611 611 611 0 389 556 333 611 556 778 556 556] endobj 651 0 obj [ 250] endobj 652 0 obj <> stream xRn0+|L6H)%ġHX$mZk3c{ܖijzQHVIC4"V'5 R5=20.6 ^Ӫ]|Q/@<u4e)m0' 4Kt-$cv4ٕPrVQogm<;lB;מX("vbcGi?MtUd4=-wX Z{)-"lŨ[fչgGWfxH8GDxW)=0Ll^ j 7>8_#ۻ^%L0 .Q׽v*}! endstream endobj 653 0 obj <> stream x `Esdf2Ifene 9; VȂz++ "L+z o$#.{WUO?=3 ZkOUf5Fq[7^P `e 16nރeVZ&T [^xԚMV@!wf٭mRY,8콬R #=e~œY\dȕ߳`V{ rY n.@ݾsd27H߇Λ=wߋO_ QNoxV &^|Ƽ%g{o^yyٯ|A W>_<{E}5׽g^/^"ni):d5MYؤ_ןyc,\.q,srέ8jKot/tS ؉TAJ9<ֹ8j0Tk c\\5mpuBLk8`Kqy&Χct;t #O\_l_ sA_60|V #Ba{ ~O8p8p8p8p>p8{0~BTEBUUTwS2&ɸ*G 5ZUSr %`Dysmkp8N??O>9?DBEW(|ij̨Zjcj[pC\DMi"$_QL}AM/|LS TA@ C5 B0H2 iYLOtsȆ Be'A>d@j!<"G-!P C`R(B-br0dP:p(E2 #J#aᨵL GAF! P:jQB8aG`Fdh@cPXP` ]O6]i_vC7؁ ga'sQ2}ҟ#/£/1} Q *qOo&}$[۰ iwa {=7x}gQsn8{Q?`/~/~cx xS4f9/u)@ D~o~wPuOP6=lzA̦_0L\y̲3lz̦ѦS-A~m`Tj[6uSj?13111釘M?l!f{Ma6f{Ma6̦d6 M?lf0~̦`6#6tfOg6 fd6}KM_ll6Rf/e62f/6Ml.fw1]̦b6}N 360釙MM~:ܦo/0/0̦e6}11Ȧa6}{Mlf M`l6(fN$QfN *b41`'*0&<(p?u8>~UqO,tjdAt ~AQUDU4bk`8`p8ޞX&$I~93D1dTj25^j }Ƹp8 nf}Zed q`d0f F3㵰@}?+-&Ә0pVsߏp8~=)}~fX,F +h3 FAbJߏp~=q8 rGτSgFY|?GW6gl4Xh87|,r83 i{fWqۇb vl5V XZf,db&4`>`9}[tQ-%wxnf6îa]A;^bXEͲSͲl3 8IeyAk4p84p9fMp0AkZ-Vj*EI jѨ8@g p ߗ@eyqۧ8!! '&1tn]QlJ"-f6uq <DiV &hq8 nxܪݥyJעivM3hU/-f4{}h0p8~w zSf܆Bg4}.7xdHMMPٝ 0YZ<cxF1L;v?|;ps8$?7L_%aHͰڭ  @Z $e0H@n$OR5)d2h1ǚ~gYap8N@ 3f93&<qRp 3 %geb]Pad_r-9di1ϖKq=p/p8΀Q2$:?W*Mq8AdfAvݟQtӆkIMSS%s$8m^.p8\:?3}6Csi0'ȄLR2y CfY`0%ԂA5Z@R`I) 6mp8 Hu\.7DW P/  `HkP^zYyx-]v {)-8ȕ>hA {p8N?{2J6m>88AAE;({XIF>^KvvFv;;p |쌒q=`p8{/gh0%%}Ó88A)TVˆJOvi~MCx-|3YK%g{+8@hz=`p8OοόZJP1@R `aP?2)XVÚ''$'Iw 3ؒap8$mitImB!P2 'U5֏h0nRVVTV\VX8 %RT4`>`K9Sw?B웓cy $؈ bH0P0F@-L0 Za%`4uoɄ\(W `Lٰ|;;ibws_~Dxf"?fMdOMf ]s+E6Y_P8ByEںQn3v '5”Ӛ:G]pq s"#&G- Q{˂gRUY3Ets`GmWvkpZKenxMQqv3mÑD=~ʝM^j4ֶ:mbkCT,+׵aWҽ-MݨyZrz0j /l;HR[& u&%Ev 66)Vͳk;m._$;vM^nݛ6{_b=:0/Xvjߝ(| hpN{ )2 a6`\< 6Q9] ><Mݗk `?ɉfgqV>gy˻p>ЄŚ+ pB^0hbSo<;!RZG׸5o NnwԐkڅQ/V]n8)Xҷo&]__D"[#qF<34YR:)l$V 8Y E^m6B?P-f"ď鞥MKBmmcաik Zfwjm-G[y?Zwe3nBRUafbGi޴CC3frS@ꖑiiG--K41h 8;[X& it iKC:&> lµacgyq[إSѻ,΢U#؂#8q7t^Co]&]Dcxwi.bo}W _UTOK5a=Cvp^r3&b뺒EGuc[Ǻ.bxUpD)9tYL0=@[g-L V1l,?t8!@hx) H.b$!k9R:$\e_dpeJ F C{lj+IUg#mq:AQ'&L |6WnD\/_|s=@w[\ew D+s+g Ugp1`MhްqAʨV=P+k ~(cEh%k.zE Jm`h5oT7#}^9j{ڞ&`3X &$`CB/C}E E*&P(. Q 44$ G@inbB!G&FrU}R4!N815*SsrS7Ѥڼﲫt_vUs3$.V9;jiwxsax0mvD646E74Gh@Oin^ѴGA6Es1W;5 xhX>|3U4T^d$қ/͗0N /lyA*˗wTښp,޺,K YBO R],,%|'Лc- ɩ]Dʄl+[&jq ϋozHh@DLRqOy/ld-l[7"o]Q7o“Cdc* Q\\jK8o ٍ *hvj-zV5͘V؟f6v&cb%Mxxؗd|bsbWಥLw I/7ߧ"];[[xOm}s/#p%t:@#;+p6%[a)1yHhpx뿠p/\@xg?nǺV >Z;'ŗC5x]</I&{z`?na n(S`>݅}}^%Yr&F] )r0O8WX/>)OoԱɀwus-Íq?wEtSWzzŭy v+.|IB0Yldio>@0@ p :c/8aK:W >N2I=i$mAʅ_ /DY©D\'n_?{Y V-ܧȂ1X ޽6.5xnfĻn›|_)"'J2IVF'ϐ煙lac񤨑&HKc+]mz~&!h4Ig\RNitPJ6WɿߕU@єaerҭDuzJXݎW^ij(p;%d C&w&z 9~%T Q2VH?%rpwp2ɑ"x&])!dtt,Da?lv.lm9^_Z!vWw[Ўa(9C8gTx!e<}SMr K'"{KY(G S`p /I'/>qolx&10B" 7Vr@\\!H<.^2H*nFE[,r^{d&|l;)Y*<>R)qJlIyy>Kp,Z `P:Wxum3Y^k |g%JH5$IgYpNopdpT!¨*v,u"TFgPd^TwO}/XW{0}209QЫoFdң(gqV$ ! $ GFQ5* ni$GxV8@RDgXgd/Zq;:̜BiUּN9dLrc|{$vݠ-v?`rQD'.B& g(OYߤu^$r!ћ(|^͹( ` FMUZ9$N#'OͻHbik4\R{G6]Oθl5ǦMB9M.9V%R{YD UI #t >K?VU9znn#n-?G qrH!{.bj96Q%Ͷ62N0|vϺۗ8^o|籡9ptdҚ,-)-V@pk.2UO}sc,_H۟^ccѯMV"E&r6&49݈2^h QHҺIcG=3nLt$K9T[V]<ܥOc-׼|!MfL4¸#Mb F "(ŝF#NA `d 5-~Gu*?ц(h)}(*sfn_kfwfa1ڧ`D#ax#{w~P3URgeY{6zF1gaEm}n*hAB9s}-ٗˏA^cJ[ A\F 0+Ґa^- UмEa95ȉAYt1)cv8^ix\þC:^=fѬy-W*@s"nDR LHb,4dټM4eesXвx'1z-4o8TޓV󴏉`& 4B:{=RҒ4znGVudVڢnq%*~ԫ!qqɋD[td1Dɴ%'%rg$edjؼ5?ߒ<'_ۄ6:/o%/yY_Y.)hR(䱕]@0 EPVE7A-: +)qFggH.83K}yIw={sn-Dy96c\ϲ\0|%a0҆ց /v u| Z+&z|g֗.0ρχڦ<zwMZ"_n8R_q7=;?_~z79%hncgjKn0I# 5'Z~FceceŃ4F궈y5(W0c6#oTH>y=hO|-O]hNB2gY -&FpT3&*[O[r5 yɹv,|G<K?pa^~x%ndw;nnaUeoϜqCF {pfǼG9h~|̱Af} #}E̼"ȜDD3)23RUͰcYad03$.² a| Շe@DԸLb|IJMed d9Cff261'MV`^ipʰHjTF kx/dspFjqI=Qb%ףd=J 9\3)R1N oY4r]uM~G~mɋj4hYjsVΦkLVv伥qtEP!VMjt8b1dIlMxnv !FH3Bo)DV6F(xaCASR͆'VeQ&,̺'rꗎbIXˢ&nr簍=+ =mߘo/{?m b"Ns;Sdgr!^ b]rY/=dWzlm w.Bby^ -TjkÂFMW M8*H r :PPVG n_?xMd#3ƭ!\S.66fp6ZqvF*WIexNwCv y_~{וYCGoOs-O?as X)/xy=q ?K'r%S~8\^/)D:`pJ^Kc[]8AIq%&<<O/;LȾΐSjUc!K+[UBjyl]Ȯn,+c g.ydzm`ֱV޺5+w~}se=Gf>-.wǎۓݓB=^wiGxx ]-| OVu1>ku N"Ap}T'| 츮JmUq vpy( M0>-g ~4>ia9rtdKT̓g-ioabEVYȺgl3N؍V^a'V["Dy^dJ᪛-jx5ͪժ$wj(ի)} 2_b^$S/盪ewR ޝCz9_>p`WlTAAhLY BT66z3=qzH30 TV8.jVY0͔&ۑbMuu]I1 \Kx(뇂*Њ&I l0Ge AdS.o37w})!`ށMwo>I o̷hkx7_Eq`(iAd.= gbkHؔ9` ǂBU՟'`!*5"W"+6+ߨ IOR2CUW۵LW\=43Yie]QECeN73 nT=H\>FQkn'3cHVa'2ؙ2=:ԳW!B:->}d.F|e!#L ws} [>p| [R 7ͦI~ c.}yP=LP)UR:>k!Βfg(3} 2+mOl?iu(>Քwp\a"&pt CQ8XW!~X0`bdUm6rݚZc%S9-؄# . @hwpn8mY$Y,J7=.'=1D,# 'm6IQ$ | ?ѽ[ w!y<0ťѸ1 QqK`z6c:cbL1_G|p!ڷJAn3G&<>@\^ bt]?~?NmE2K۝dR6LZ^-ȵ??DzY]6t\7[+f.ܖ'DOSwON$S_ꔼ+<-llϸlSWz1+[Z[x>cs'TYF[q3,T\ibSӴUL,XUu#vf&YpDU@@pXjB0P1$Ͱ҄/>3LU2/K.,IلW@p,n[IpF0^Ag*Ehf@񢡙u:3i3b .+2Rk6ܨD\}͒eqDkHW&nl,\t4}a/<7Co2.0þzvWV ?h+&YX$*d!LjoT^(;\#'Q HFXA׸1_yDV A(>30{NMk@E!DN2[AI8o>؎GV/?J![r]w_RV]CTYdVhaBXEm&ƪJJyU 1.wt3|r /F4)%A{';؉5vJ:@Ou~;7!>T#`n\8\&ozB Rڅԅ(d}*UfKLQ)8ݧ"M-=8!^|D@f|S۳ϛ/yP.gOLƋk&M[ݷǪn5&^6rЇ':apILXXeqSـʱ#;DwL?ֿ ~Qj+rPbD3$B\ƫ96ܦ_  f!U̹x uB/Ϣ57_ nmf7JߛխZy aZ7 ap:'سR3I:ae;%7ᛀ( d'~9 1 O2PŢ.c b<1Ԕ炯fYQW4 M_%$G^Ok,7w'(xvftGx7Ǐo= @uhw]zנ^9j8XKa1@$GrT$mdCO3rDZE5KU/A55pf͟#iA5G=Z}jPk==! %C a<rH[`RhiyՔӜDSUDaO/dK_ +Z-::BA K~x̘E:a;): liD4~Nn4re֏ʦdb^@蘫c+؞q\h KAU-!6^Zbbc"B8eFKeh.hX Ercn F?cA:5<'LWG~?_% dhT_ѡͪјH]ttͩ!-$[F7=kiY]QalI7li"KTQ^uU{\%:CoQ>hQ4jc1q +F ~~7͖A]&3rNu笪d2i3}(FatE5 $$.b ^pD XMRО(7{>ͥ ʊp&\{%%04n-0`vo4#ϞE8'WF3U@ m8˂1EcZXp鋻vÐ~+zձ6| ?:4͞.ޟwתm;h{ 6r3yK5#*UmiSxAH[ ,7pA' Yi` &Tĝ`q\kbup2鰶 f/mgOW_u@&t]iO=>|Ǹv]PW8^xWタx}utT_lg.} E!;H`enj:j>޳z}D@oz"toE(LJ;YP'@Z*',6w;Y3=8bQ8/hյ`YUTςf#eaH֟lЪލRW[OJvSEYB([^ġl_RQkwy=Z];9?]bͬyG nx w\C࣋\- J1}ۺ[̰#J88<^agX]n g6daY%(a')e`݀FyNf >:$2{5 6v\,Mlqew&)@J}WԖ28NSW14@I"nY^q ;{S>y+ӨG+Q;2չ)3v>ٙ*idԢe\aS9):A.4YF dF џ˔X)m#EyVGzi`-IG-->FSH~)T~&`oE #ڮhqh|:vJkd\ꑅ៭-ni؜*m~iSע3nDqTxwfeee,c,$nCu vv}c?O ve~;۶dV[Ϟ6Ȫ?oĥ;zէ_*X?{]Nة՟E p8׈)pH\yxƳ&B yx%!aEut@nYV^iUU) #Uaxe*JYwnT~&z%Trl&j͸n߶@ҵCkغM4-Ydd}+0aG.vn^@pyN7d<'\?F|CA-o )0:H-['&->UGbL0!f^Lmsae Ja5xe,au5Χj.kh=09CK&%޳x8(s+W8Ù:eXfԲ/yƣ}P⚏.5=6SL2>pm`֫bz k%s2de̘p,5 kLQÊ&^ڬ`DE k;tK%>Kn019!YVL1!6}i2 *Cm=1,Ld@281scO@0Bc4{v֯́sѮWuö/.)5S'&<w0 scٙz!aNXle7O27CZ?dlS*"f[\Ye^D A11v&"LNE stYчCĴL9n׍+t$QŰ; E C׊cy'KMI IޏѠkÍZ3`cs7&IJ;vںuv-I!ӼGS`d79KЗSN֧r5=/5^O?Jq7ٴ>rq˸9F.5p/rG@&ږC ъ$(ecD&%׎o@:=j tDxdɭG޴Q̌ب% l*6"OF{k5D7m ue$J@G o(=>Zn[v_pbgGZF٧Y)%/[2KȗqC !%%Ԓ8Vͣ5Ag^@ hI/8, ހld2$b AWV^TCuЅt%b +DԒk|1 TNA8 gf3s$|Z{pIK9=mcQȢ@#i1?s@Ԇ䕮W6xѻzd^O̟X_;cܔw\^[T*E>^|"-gEÍOIXAjZ2<,؞R¸5hVZ5X,P\gӄӺG̚>s Tь#d)0wGO. 8TGȫ!kq27Zb j5pY'޻շF~?/-:t۔ ߓZJ+Ώi;Pe7,(B671>" s 帜~fs_pxzso?XDzXA$/N5(텙9;+;r)wtXgw;+V\>8~s7?=<ʳnCRwKjh^BA-FBZM02!<zYB,AƲ"ۘ!6K!pl &F{%33:]ԩsNzTej?y}M9/" g,SWY*hyxl|!1ꉖCgX4VV"3{>45 X95Ji*O[Z(!1ЄeZ56e٘EzWة*`'=,?󑕽CJ$= $N_?wi/|ݳ|7rLB*eп"L?[yeכ/&I<پG4ny}ccw^WOPX3?^Z?[ȍvC3Ojm|r^߫o4K] Ls6BBUFj/uZ>< Y,lO1\v}Z51]GYW𕒋 !LlƜ$>Yb&evYw5H*{A坭 ]pſ\; Iʿ$& 1ͅneb{ʘ?ۖpڴQЄ"$&;a_qSgb+1\qXי:R{U|ɛ&Y%MPIK䘜fK\͝&GΦ/]Z^ͲƴTƞXSʓٴgI-$M="5Mlfrjw455IcZ&Ec7  X˟7V_gu!MoyI&(7F^?KMWtGnj|?҆;KK'xl^lw y0SecUSд? { / TCz/M_\m::Y~" ?$(':CUEB#YXÿ-<dÎn1 z:Cb {AO~ş@ \fI_$Խ~g:tmk=w*챣L,4KA?C5v&Mjs++Ia|C>*?~ {'ɹBSa3dO֧ZNo6aIt*:9l3Ǜ qVUm0:ʑ,PzV2AY/Mb:~iT4wQ6cSsxhajp;j;k|6jS=_J_7މ5:UEYzѮčdѵlEqD>cZ>bWAaò 4]g)x>k5f*7V}]9^a0V^E+LYBz\TC4lDj4%nS[N{F%.~k $@`'OH|DQއ<ԤwA~ImTavv(b}L+E(oţɧC[$m΀X#'Q,OM~F-U!I8%58f.β bk Qu.=ӕk-!(v]jBBu[T'*]QƸiqou_k묱[Sif2{\wzGq˖n;;!W%Hy'u]Z^ګCӆƆn~l#Gv8rI5:zp=\׃zp=\.zp߿_fbo Q%DE2b]Fl1':LsK92v 8'0'W#șeN&[ ga:#?coM )4%&Is1ZMR }MdANǑZ!]u$ZO6:@[7-{gUo VfBk@ORh-1kq!\֑T '5AJ5_uTP9ΡjbqZ+4˟i-OOp:7+4˯洎oTh^Li2-_e˴/ӲeZLi6 0v#m-F;[LȷQh5'iF.BQV.B3'8)4ӶA> Ư)4i%-i#"y $ sLĝYf4{j@np=8)s:JJ(Sn@i/h k~(}ݪߪ^Q3 %W$,Bέ깿5 ӭ [2#MmW?.TR#>r,YuOUcA74nk&ߙ YA>հB`,ߌ"ɿ>C3P<뛵dnn.!nn"d96DAwt'_]#JºTWŃ6VYTc@gƂRe:[ Uի_S99R35~B5!tA 4@W{Ok3&*xf[#X)#*] ]蕺?Z^ 5D;%zh?ͤꭠNM}P Wo(ŭ-Ul&Л5Pk`5ff/~Ɨ5E=^Яbw&hrۙYՀ5F]#K=z5ן<9N¬x ;bzԨfv)$u]LOK HV"ӛk<-Mxt~gXaೀ%K8HA#3*4T_ q\q-XqիV"p|_Ql?|Rհ¾iI$IF@*ӈ %Y.9(,4}g:`[BdHdOH/9NN3#r|5 XyJAZaU!M _Ů"*rV)Q!';M7iF '$CɱOpO0evaBTNiw\9BjM-ҷ@>rB['u-4;`( t|dqu__or rwehv]f \i`$]rW=}A3~X{#+ň9hX {\&? ,@ O/u %t4 cbe,nh>C~6MU4q*?j)C>x}\udH)o‹?O mJ~ &$mބGA悴ԏӷ"H79oIG:8zk}{h~tl~go\%xdPP>orRCyH9)!<$G!<<dzɈ7M9K X~$VMg:+΁ޥ#-McSH_8-$NҙЯ0 0 }PC&Hz>E )^U}5ڰK$Wt>N+z i2溴"hc/$r H+ae`xj F'ʯD`%5d] KV_X­JУ[y=Bfӫ˙9R|J@2Ԩ+| |u 5^/; tokW^jޫD !kz@Uxn|Yisoҽ%vP!{iE'@n\XUf[G>Ws%> FX XX `1x>@ІbTCj%Nߵ-ji5@-7"}{4 -X/: R ܀=rPmR|^-Ix7:NDY"{{iW ĤL&f0\䞷 zż=}8kj oãEֻC@[j5X+ulRbq@T XSDes֧Q 8[NZ~S<q8A|;)=/ڽwWyb}_iPi* z,#G>*xjK)k?s"yϊy޳G9i$.v]A-Di9K_xX&~ұY~}jC6= qbu!FLGC9bxFwQ(O \ v]k.T$3쥕61賡T'9P/3PʐoCcPxekA@)PxW5<`-?-7.l6:}#5ubv} }Bew* L[B߇(};}p80$`~U<Kbs} / r__脫ʯr-R߀6gKJ| CQX}CdaVC7,]BuxΈ[hCJ5sPevr%Kyv-^ /aV~UO}Jg!oOsZKz-f>ewpz3x\tԻvƵ_V !h~Ս8.kUlqb}MoQmUh=, 1zFC3Q>#cCdbw*< 0_ gnׇ'n9+̉mh>N.Er:ӿdJC헤T_0.` abeOwӈ:+,-e3Ze4Bl?+M}.f@opq<\"=.ve1 ᷷Cvi8zS i GվSѲ%"7 %\%5% Wa$v6 j \%bK#&- : ~^)EܙnW|"˭;o/4r>R3g7S҆,xvMo7gB3um!*l ՂvrKR{ n@D`n 9ܝS둳]lpiD.H"ޯ#w_h "B8*dc`[4r}#4.7"_ kt.h3n y/!` [5X[gӥwO _hC-DfߑmWz[]Tž Z8+J'Ç |4܍8/Y`'3ϷC]kbU1e*tM;auó8||fT ;ЭRRqa+Qi4p 1Ɯk`  N;/-4ZY]YL{6Umzώ`~tg8/ij78=*z >ϡ`q4$ \9V~,t>Gދpb=h.`R{ }1}%}#&סf3(W 7@;گ{wG˴ yn`Z, nrvrG_ wG7mȀUV깍A@]uϻk}ѷYh m;ޮ5zŐK NPx,!nF 6 "ZZ>nW9$t nzNFSXDRn[Hڣ3paȱ퐟]Z~ڎp$#F F~,U[]bd"R۝,(s8^rF8p;'5Ydh]PΓ>TK6] 3K7l,cw+.s"M{zb;+#^k,iKu׻lZ䜂Y_ }pdPR'JTISXBO{ ܊lWeVngg> Myam[fd.Hbt[r""]̈́mE"oym i+|'bdsĚLD59SX(q Bs=&O,r)`+531픦I_S584h6c)sg;J=`QeWzX qqiꟅ0Ĩ1PU۶q c `i8qclB816U81ĸe kh% :1=+^Uk~w;s={<^W55e1jW^{WFy+UMh;T?iu{,|&"|3k6]}u/4nzUsd-i0xiS; j͛@!φM'kn8Y M)i3v{GMV7 ~m4$zJpN<55dsWm֦n{7o56~Sm]M+~@mC~/aw5 uo_tަ{Ջu7=h733МXKgl曚5YS|BgHFXVjcFmŖ|'Hgކu956ϣMjc]㙯Q'9 pwF_b5sNbӃl6ޮݸm_[ma]m# jݡE{ -[NmڞelٴOo"H4f WlZbRVF]Җku}ͣ=r-+Ny"9oнz۪w;V^wu1˫nu.P?b+oI[^%UEUO]phI[]i8QoےMs;%-nX5eIK@mBҝrK)#]|Nqq;HrAZ,iYs%P~ZM[ֲܰf{jKtO l-ڳ>eg]vgKAW*ҖCS xyj۷=vyMuk[hфm4o-[-{ol6rrFޯeExleb5ނ{}p bxIuEH!(DH+q DX%/.Uߋ;⾘J_Z=C/% ?Ib7I SH2֚>'řLM3V҇MLߗ>fl'韥 ӯMV&Ӥ3n?}ersP:f^i>'W)E-P'?L?rO(ɴӲON˙DS̺Z,ﴖZɻ'=qqqߐw1θ.?'q?# &V (((K2+$" T{mÁc~˄mmB4[~]%g !B !>'Lr@.f<[Ue21M!aWʫD!?+l5Q\'ב/b&>K R,jM6ZoźbwqxyqxU śk7,n-WPŧ_,LnMxv%֒%i%%%Y%ob%(C#/Br$tiaEbI@ju%nJv,CR7?'oDs~G?WTӨ-h0?AC,}[6ѧ̟6(/_!g̟agJi&&\m/k5bUsxMln7|!I9BcID Fc"/RlEIEE遱E΢좼"wQp9QhUڢ E(m-j,YZpѡ$;AEgn] \p>kS3 KMw~c|Q?PK!f/bByyx惢PHo?&D͎,!d]D4CV,#x|b>+$BV\ʼdʖ2 tr:"r.ĺtu|8t=M!rs}봎[뮤l8Vl2f'%nkm(~iy#mb[8uc4Ӊۢn˱]TncZJ-t=sڞoui60 ЊX?Xvq)MOVu֕UFilKb.mlMc1Rt:8 ۛ~z9+8+T[/O /O u>/>`6_M]mj~u0IH{LllqSo? k>?B{"iCڼ E;eB#>˘eB&B'#mPGy&).fBDAgx0;|J;|!_SW 55>&SIW\ ք[l bl1]q)F^ _(/ C#%;}|i^yYAyEh"JP{NxÉj_O-a;PCxN{ùƽ=\P~0tϸ DFq{*ۋ62 ܅p_kʯח_ o, Wo) 7wwg-|ާ)uIqէy7EL<|a,q>s=OXkƲ1Mf< k)c#~̚?+cxa3zbߟ?3 [}<"|ZD>]7wt-2XXʤ镩+#s;F}+> ^^錚1kD->bjm.U檠QXC]aAY(hͣ ӽSDX HXDpB/Ȧb( J)|H,(RxF,$K?%D2 8->")E3衐Nm %BR*Sm-0 ;R vvWv^8P_8P8T[8Rx^=n;ޝX8Nn;>==Ͻ.p%92wIs6l{{{ý ZHp Z@:(_C{wa'u}4S #] nӽw9TqԶ"3>>CDܗ ֠S{)h$'{_q_[8& 5vҫ: L-f  t/pGsκǨ?< oc$QW2%9g=^z|ag_Q6{{yzND,4,󜞲<AfMvpQx)LQpgy =4yz{U# MvOgg{=iZIFCNOo4"|#S3 KSx5'_'ɳz,W-iޜֈG5~4էq/}18C ~W|Cc6/1/T^y y;]tclN^7GxsZ4xxy|F45`L9ź|LQ?3 #DԺ(.sTÁ9yBt zҢ=DmXt01Nuh5c>}+16czN.C{?X{z~%*wJ_c z:qS"eD=:Mcʉ'Э翭wk>H%wLd%J JD҈2QL-29W\j{FEZ9o-&ZB(LhQ%QQ-Q=Q=:X[O{ƨ}<6'Oqg}[Ca-zlQxPSslш:ѽyUק 05sT9k/0cgH < aEԙ?510>}30/fhN2o9< %'kJp&%G"W $&%#׮iA%%reDD5AUDk6hF}wjq+> CӸAsTK$s;:|E^\j6$ )CHw=/8iƷ&?oJ5I;#;x|52ߋ\EKR F^$%I[yDWU {TJ["8*m5Îc2IGñ~`t5rwױh|qy88C5=)ǙQYGc :f%=]DhO'ױ1 lq:`tmd;0=q RC pDGh#_G}WrP9(!/EW_ʷo rBR+>ǰ$йEW3PFUDի4VT567O]KBx hL,p{}J6\<,s$ګIBAHho' #$>n?Hs#ᶯq,ݠRL"4hð16Mk(d˘+0ؗj#*nӾh7S=㤛YPZ}#U @\D+_\}+KשOߐqdZ(_Ю5Gc"AySySėlq6l\B\HwgVkD X?&>H­|ȷoL Ar$Lq\F )A騛iƊq/0 48x4O-h-X_k)XQv lj0滈6HZb'Rj4I$C dy e:'<)js.,Vk}jWTGZ_\0b6d1øTeUZemZ }܃Cl@|43wdkraG ,KNJA!99ī)Ļ]*A3Lh2aM krOS-qjw` |}KAjL|,i4i Ƥ1=jxHqiҼg8L圩$-eү5M㈧4G4zoj $')f $~KV[h7pgRkҾI& t٤/']%ܟԓtdgn&M)GzpA8SieL:=3CɚIƺ4ME ('E{Xkyȿe\RQy;\웢Rhp4^J`4c9 RY<9"jgx|T&|ߖMS)*!wo.4UB*s]!%%>$ߔoDy@C|W~֛֜"s:N쿠׀_~=k5.eHt.cJtu7J(qQ2Ŀc%cKQ& :%+DFklH(?+d}[(Yw^.߸_d k2GEyU9_[ bMSzlvzSfPv+-#J2BZF@taÛz6]-fOHd-Y5JˬdÈu'%)= Cq)qv@1ٌtRS XICuQt͉GaA\n<;kU *%ZN$ZEh-_uDoxG:Fz\GLhD/"vs܏D7L1hWsX=|oNkj-T|a#Z[n.QuHq!)Lxث|_%fmM,9^9h<~`^> Mwǀ>H0JBMN2T=?@k Ηha|`5ev1/ T;+ ,ԛa3Lg;! 1_' '*M!:$Y (Y,ZNbqxLiK]`b^dZ ߩ3-x̘?+nAS߲{ L23<`v/蓤慘q\6,Ddbd*AV*(Wp]r'1ͪyɿ:yOL75 .kB),@9_˨wV瀷0!~[<n| 0~QJ|;KvFip+#icRHg{ og$2 lF5ZlnV1'lu`-+$-pRqA ~ lԵ + ܤ, i@j7v=u;R%Aߊ]_4W$zXhNC3!9)ydK]ۦjඋ`dH$teL#wҷՕ\]{4@,bu4W`lMx UuaU-V1Nڠ_~< ٫g?LvpIΫYF) H.|pѼyʀ@p<ٍRT`"Z/|&_TxO3%Ӑ 4 F#)I2Ih>9EAG;L@XVt؝M!9mmoa 9K!Jՠ2Jw/8 IuHFA|83 ,Lhx+>4Ig)!K'ѥ!?D}V=,Tq 9 ?: H~_@$?@j N>׀x>i*%{y3=blH[ȓ Lk_*k ƌ*-~e cX `:߃߁5xYvOh#< ÓfAYͤ>ݏ^HJ,,W= ԶgNTg|_ZV!?$q~* ː}!1`V-xHN V~ǼTA[jPOR&.A =ȿ=2=Q:)9K3+ؚTZބg./QP=ZwL'X~+JHg2H|;ku>daC$[9cWz5Z&R#93"oAIWs;$@rXs_Y1وd7x4,S$W"&  B @ JE"u]E]0ng}M=oߺuSnWO u|ԣ;pCSg2Az3eU\(@L~+ElسpAj+*.UMϰQu7>4/N4wN{B| P+؜֣W0!4G @le9 4 &Ϣ54`3/ŵvsn8Z oÈhE˜$fg pECQ"Vh/bӀF# T 䀚0uXbָ@\ CS7^r2 \j@"Oѧ$"+ &%@@?x"{ 42H2zsJh_BF_v<z@ d t Ӏ6 F}U:M P'݁ 4HhuyZ l@7" 8u ԀW?0G3 zr!p4t0 ΀ ==}0:W9G`C h 9 \Ӂ`S죁,%0~́]All08x(0h})e ;|rZyFD<<Ek9dgAn=Û0khQjub@)jMׄ .\Ir.Z5AR{0{ѻ?ڌwR ZM۲ ")B/5%/5zV=[7E `<ԇh-xgjBe>RV{إ,fH,%E?Ԧ y OW»B*I52a>Bo=]?i4}Ѫ97enaB" `}{h6`ܯǂFhՂ,,_kg;=,O}ac=d'yx 15~2"1< dWt(Hcsl.e% `υj`%poķ ,wCC`3vȹ b'^Ay ls QkAňkE>) rĬ52b*k3YGm~ha+ v}loqI3+{]i0ꖰ9@bМ 6綰9,nFX!y)SxSTEr#0J!Eh] }WD/̯0"\X ~j@'vlUς>oVIȱcTLrQwTKVԆIeV22<\}mB ϿRoܚѽFy9}Fm)& s`IzTfB6teaQP: 9/<5<҇>ےU*FwCuC nt^I*bxĆ`xړ#9x^pW,(}ȚU6R F9 B$0xNqjM2K)cF!p-&=3|Y y0mIQ挘zr!JѺ!R!S}YO:4ȮsWtDs&#n4ub%cN;vB. 2l?Ec\&uC!o.hFw鸮Tȏ! =FÁ_!menRY ZmFz/wr;9oU|`\;sO CRU!fکSd fK>.Bh§9OzO?{7acx]T桷0h݅a?,~*BW~Ji~JR$@s# eyz"6/Y#la[%\#eWctFKt#s"E'JdKZO1btFNzS›)Ghټ':/x">/0& 4@Wh\ऻBTVźV aVU4k*˪1f*KT9L!/)DžYfC3TNK~%QB-BB-R>&TEX uQB=+x{@lTz޶ + s98ߑHl(#:RVI'_^6`YxZb,c9 *HM|'G FeNYMʐyxx-:{FD3>q 'F1`LKƆQ0]ތȨHh#|pT鎈%Di? 8諊ߴ0Ʌ'K,h‰ĂUH=eɕ2=oP&$2LfY2L9œf.1L%Sͼa>B%fd'\!H%OdȱHu8Vq OdowdY%~c>DXW> 8Vq|L&p9?g9'űXq8>&Ͻ##{'FMeF85\y9.0ip3pM8圶# pM^8=N_`FL`3SF8#g,0µ11#f"#DFEFZX7,crʈȈH[kv"#HBp6"3"3v"34c8^G. (q$2YdYdt*2MdHs0g>JX&2.2SdHo0)2GdKdȈH?0#2_dW̘"3~"31"?"?"?D^+D^E^ y*_3Rd$Dd"##DFF0pH(h02Jd$FddX`dHHH1"3IȘd"3)"3f_q{;ȝ@G_v Ӗ __fz2iLi[diM%kT"M](YOD&5~i1d>| f$fdH?*GirtHʑ2#M6<"ȥ](Yχ4ҿh2ʈTF4KleDsUFPOʈ)#Z$v;E0fFڰmp/V#wM:d cfV1I6 {ZCD!.gzFak^#TMb/iKJRBb.CFe2]WZPJ7!IUh3-8N0=Ap)lngcȞSX.c(=*RtO))JRzI3'9otb%dd=CֲY9?m{hsGJ_"|m6L,Fngt"v'f0z> I4 kRWin#>{){=Ll$%!%2U<޶ ZŮbL5ƌ8ʴ¯ {ׄn>O >% hLR榚ZIH$1;!ܸs}q\PY%VCz|G.a.v c| eƇT;dyeo"Qes3 *%ʚ Q[s Q3;Yn?Nc,݄l1L$Y2dOs&3xg\3Y鮄KJ&f63e'L\)+aY}GRV{,-+&h%dO@A2}vP\oJO5CFŌN'嵩RU_?2blܸoB5DŽ'%E%KK M!=ZhTɡczf͛yG<4*NS>c$&&mԗ/歄SqbGE&0u֑wWv+r+pE&yE)1|{%d)a^$7U 5ا80/ ΜWu!6OߎvΌ!꾱efoաIbaiLJhXm}7i杺h=ԭrmUԡm5꧎81ǚ5/ <6pz0 E.prs(g|<3ſՇtR--eΗaUl9w_M ?`ञ+j_,>ye_#j[7’YF%'ǻۇ'ڍ6OvqcP}|b\${4Y$#&`509NU"޼׷s*0a„ 2_xNiV2-^KڟfNOܛf{ܱ;]^s/>]txՕl\ள_Tug-ͭع06Zy86EfŇn>̶]rir5~`D+r\hla{KO-:5uOJ\MZX[R.kۏ;> i`3E{n_KSfټ+[ΰ^m{nt9Kņ9\jJ[f!j;9hSw'¢}7mFN}gΐtoIOnhg:/ZqkbGa':l_kJl{,9mK I-NB/!m:s3קvL80$B~W$l fGf6$:isS=!(wrqꨈ :mC#;*BCmC;Νy'G"4|g1,)lhh*V|P_@$ImG ] IvJ?WN~{\`njkOW5_-v]fYF\G`2{V3ɥvtѲi`[I>/+~tG1crXN[,AƗ M`z7xl;&?iz(v M =ߝZE}4=>yT\bLrـ9.9דּJ҂8jjyϕ)[ފpŘ u>pMf>סmn&2Nm7ը7N뗰/V֎uykR勺3J_ﴱ$ގnۍZnĤK*8-I̽2lǴΆWq$e7튱B)eײþ/)Zҍ^řξr-2#7(]aŸ^ @y癗suؼ&nܹsΞ !do *pP^V}QRrze%TG&#멨&$2Wc/WYh.]-FLL `ƓǙ^jvAH 叭?wxtHFOe}>Gn\y-S6'Ԧ%U,*œ]so6rtcb%SzswtFb{Wm\"}ZSi{&}GZcoZcnQdE kO󛬗n zx`N=Խ~Y[J@ЪWmftؘi|i}yyolk vHɫ[,CL/wzWZxP/6<08l5~ěod:q~eU-m9eڪG:/GAϮ.3 )q2Qش|#&͌ʜz yjvkMױUo^ܖ^ҡ/oHԩ־'+0L{N7qrU*fziVډ6tnY\7_wOg?['*~V G)PMwEw+SW5yZ_lvĥ\D۞",ኹ=U.ȽS:&j}߭q_>мwSNo8ZUfI7[F 40оv`ۮD mkaFօA/-p.Va__^28V4kVlOv:{*^ͮz2(޽u=Z4㣞n|6Ǣ^;>?͍;>m;xY"+מs;aҴ6ՙǬmv^JqynJ/]_ <;MIᵦ3"n;,8Pޢs{Rv~K6n۝lofꏷwW;lܗϵUe6dUm߇%q5<sɸ?/$oߨ}jXȝ-|a7pL/LY²Y'/&qnUʵ\ ~(婫ל/!T&G|EKvHogbp&ÇQL2c2iL<9&P"bڦ[Ś?*O7Yeem=FYjOlW߲;/v6-8@Ɩ:a.o꿲΅ur~~Xي}/dO6O]c}IU6u4f cnx'󟥣n+.97)*ۛw.dܢR.ſvy4;V74j^NUO;t]%͘]O+ټ &F'wZ3,h١"Ra%U^vڏˆ_mffeL9Rg͈)r߶ 7) \uOrgGCF.YzԽX%'oWzMseEţa Z7)Eys2F=|ɧյEtkۉ wk͉61̹:a2D#7#.'X7_=2;̢ŋRgT+{bM~. ]7uvw>=c#?W=DkW4l6Mu?6\Zct%{vNo*orXu) M;I\;lFk쯻\ܦ$5zifęqO$z endstream endobj 654 0 obj [ 0[ 750] 3[ 278] 6[ 556] 11[ 333 333] 15[ 278 333 278] 19[ 556 556 556 556 556 556 556 556 556 556] 31[ 584] 33[ 584] 36[ 667] 38[ 722 722 667] 42[ 778 722 278 500 667 556 833 722 778 667] 53[ 722 667 611] 57[ 667 944] 68[ 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556 556] 85[ 333 500 278 556 500 722 500 500] 182[ 222] ] endobj 655 0 obj [ 278 0 0 556 0 0 0 0 333 333 0 0 278 333 278 0 556 556 556 556 556 556 556 556 556 556 0 0 584 0 584 0 0 667 0 722 722 667 0 778 722 278 500 667 556 833 722 778 667 0 722 667 611 0 667 944 0 0 0 0 0 0 0 0 0 556 556 500 556 556 278 556 556 222 0 500 222 833 556 556 556 0 333 500 278 556 500 722 500 500] endobj 656 0 obj [ 250] endobj 657 0 obj [ 600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 600] endobj 658 0 obj <> stream x| |ZyNrdA82p18DS HT$UJZtrq;$ttp/Z3<sN~{>yk?=)1={A}G!? W =.w&J;t~=?m^F3~u"F䚐=gDUI@ɬ9%ˆR"Pd\볭K'_>mY5}{u{9dV:mB!ljZEM}3Ж}ːY s޹l]ζy c$0%E\CF_{sB F(oCѬһ?*h( gM $̟sc]Vހ3u쒹4aJ㜹x"nLTy {o_h=L rS]P(ʑh'ЯJJ2xBpIk0 ]?N]ZF'dd %r$b0 .3%]?@eirg8vIpp }B+N;}FSM0pzNs>iTL#FQJTX$u2 .zZA0xʣz_ O'.ZI)5bEF{0t=B^%r}t5 4 @0Pڗ=CKyM58̬9K y)5 0Ar2E`tp <Azg=$>nE^kīqr]MY8%ϕW*D>I. POlgVD8HQ2F3y=ѴަE)G5 ^c dAEX$zbҞm _~t_XB #ɤ:R`~9nUA2k'!e䓜OJI-nݙ4rق_DmЬ=O^ydfY8.?Gs+er]}R0C?vE'83qS;=vi!!T~=Xȁ*ƪ-4uhm!ДLʧqO˳4_OLkaIVzAEt$1t#8$q uXۑ+{YKk >簿g RscdRGʧE@  o>۽tv)oAF_Aw^Ga?k@AQ>vIR"lQ@<T@GO[Hvcxv? /Asَr^U$S{ܮ(IL!h0J-ώSJ<9Zr;<, :t [;@LP1K΃fwm`mA<)I">mbwۯŸkZ_+w_ $>k+aug-~-l' U!u%.ZS{, 'yH8MTi "\hёg"习MCZ WOJzNgZ2K/Th^/U )ej2NV>SlT9ڡVt,eQJzV1й(wT_A ;S@){ـ?r芧 yؘy}vW<>tZ׊Ii[p<Q/;AAʎy4^/)=䝸UArmKGQ8eVQjH(^Aܳ$`C 3v7  \^W9z-op+`w@3VI>|p%Y"b9y'N>UCrK[q%cWX$\PH1jF(9a\Ur(n uM>' E^uD $ޫ kW^>c9Od=[,=iAqo#>}Ch-%oU2p%;\%Bg$c,;񨟆k1hnA-.+`>+>J]Ղd~u6$2悢.'24& 9v5F+Z;Qm.$wa-^|$X%]qT~7@'YdX5%MHUx{7طtL~}1웓ǻ`w/I ;Ož KEv#("HZIۙJ6p5Ɲ74#)$OFjD6;Wi/p{:DS ejk.5nw`˓`; ~CBjgn);i2LҚ~|ߌ^[Dk}O:nķ׉A1ňQFs)VH w((L٠J܃m!7MyYVCkantwOԭt#?uhyWW޿ѫyWx>O 'w4;$'}/p V4+yR)Oš,mQWЎ[p )<T ؁}G@w"8G)mp[?7(YRKh?$@`MXS +<+-@-ӥ"vGWuI"ab҆W+کl`4TRg4Q+j{E@ //Rk ( 0  *$ /p`{jG@Q =#سUhh;QG,yxO&P 0bsu$v8`Wd(F)`OJ4 Mv`d`?J)O݌o`k$TzAAN-7zS`lkžBi8 % tp  1L8ߡNshP`BDÍK$Nk^KgW]4XDS5 ^T$[i,L 7>}kFۍpc$QSx;Нg.ؘ)DUi -i9Fa-k9Mx^PV>`=l!>l Q@oI 'uz_Wѫ71UzSz= <|ަwKO/{4a6^=PG ǴxT_iFcxO_`W%~J/O*yp^Hf줋 u`a CaKlzJMݦnlm6Mgm7nMʦV'S=H!Xs3 u؅gay[6SO~KG~,yۢOOz):O<]4ΌAӻWS$ۻvIJLlgtپ]ۈ6a!ZL&slC\Vw˭'؆ K"$HpHryեY//DiWtzJ:KrAdk>m1ߓm+ϪH_š5',f5=d~YU+dٲJR& @msj V>'F9rGٲslrn->h;oLANvt\\aJJln vURݸ 9ZfInZ^J.{TԢnPfG OF^zEYw֪̍r"gXkU՝V1-s$ C\UCr1wn^.r&rVrd:m:&Mcor㨌ʱVѶ¢5T5$ׄy[: n)mS1U\r6Klánk#)aNiJӨ$ 2jbEf[eBe6ŇڬU`;)Es$ROU nww*U? k1R}R׉9VAE\\euN*ƋrLJѵLK4rڎ9.4ym!䔥ݿ.玳厙T`ͩryeٛ'?9s*Т7&5 \XxSJ= T)lu `a@\oTg|#kR50\~4 XO. TU5fR*3*mP[U%TqVر,=dy!&QVAkl|ט'5nRA}( ]EkpaMg[asUhNoVF Mf]$TJP%uL*Kc*P'ev|/gtlmݹg UX۪WFf@s[:MVxS4fe AInpmLفHفHꈵ c::3JJXhehjz)p®Wz{ebC2[kڡ{֫H?يZj-FZQ} dkkTbT\oSڐvD2BmnZ7M'ӥG[n+NQ8ZaʭP*>[3T<cHjpߌh#T^ƻ GiU8R«0onxF8 2 ͎9S'ПL1lIoS)S`Md-2QÉ6q9AA Dف@Pst=9 +Zv`yXkUCNp6dKƸCz'SB76&֙Jl< <\)՚C2#PNMOW׃͔q 5eSzŽO3$F ԅփ5 SłT'!D#LDDUOl5(Q"ڿIՎhE&!% oIIH=dUCWx:)eѦ3T,uB _N#Si#5DM o-`VJ%:@VVP  ž.ݧϊ>l鳧NQr 3ڵIf :M`M oTT59W'?29GM298urp;ۃ?Owgq!O`ڭpž ;)`j834{*Nn] bMM$xq/hsvgkS''c#Psks9l6u098[R_ t_ ˟ w-W̹-ϏqTm0s)7p=N[]]P|o!.YulȤ}'D{BYF{)v3"33ioX+p?k)tR Io^9 *EZXP]xY]Oq2P*ˑr1,/OU.r5rk|e2//32U2L\2)N?21Lϖi!p=5Y Ue)E+z[DLEu|Vβe[kF,i{aˮ95 ٵ##rlEم[utYwwZ3ƺʾnM2{kkksKi=L ᛪp   3Hi%;t)z}`)dVky#fE.f"96"sfd_y7Ͻrs2{% 3Ho6//W6Z+//KjMlmK7e.oT~#5NFsdy^)fH ~|E#ъqbq˟ȿM!p=O>A<T:~[0z[ 9)HcrtOoGהLhRk8{5ޓ'ͮqݵjRJ>=D Zj}js׌bzⰾޤIۍec-4K>1 Ɠ-A%\(=oK`;n,JVS=bNJ~q~cQl̦EyT\ sM6iG?m:nĠ|O hP}>Y"_6Q4 Ty 2[IF̽9|?'Z~:)鯢5铴Vx'+\D[.Jm~MIqܠ-׶iokz]&d~o^lqVcq㣍5e7lZִp'F8W;XH1Řt/~<1tkdq+ˆcպea#1p:ȿwq ~׸<@ ƋiãZŇsG\˓Z/*\͝]Q.z}^bLSM֘^5}wF\ [b>H6vi_w ^f}+OdvBgQ88A.نxDh-ʿEy]àib/$y5@K6Yñ?Lӏk1Үy/渓;1K㍜ko4u$N=ms/`m:ikB.,ZU̍@oUԗK;4& xkaT|_$-\35e5ida?9E\O3xw~Rdh*~霞vd7a轱i(+ӏnq=ЈkbjtB:`ݖa/ _ctC1ў81Úgw6|cL_otV4yV"x9gΈԓ`vh0pS4'zjpBBע48;i9lCϊ%^ >^ќ<w4w1=*Ţr=օa{cB3aƃho/t/h4ףM?QӐ?:&LhgBMQe ḶEGz12zGCrtѪ5\tY3' 'Q,v<(mF6ns dٌk?q:4(ɓ'ORFгztYl>ٮmφT$ }Xx{/RmnJkdu\4';vMqQxJ۫UT'pp@+ 8jxng5lOca_vp;bV3~xٸ4 Ho~Bl8x \P3=\E_y0燤C?^$|gX p/V bxԄ&+'.-30&P#~BR}Wß}K[;);[= qq Y};U\“.1XWd8s!M߯@+̺PwjGn]Q;`.R>MJ]s;c+/Uw|H;5xx-Զш-wۨx 5ԃ`k:5kZ\ZrYZmK͊ݢ=w1uWԣ_ǶCFw٘tܗœ.g.CP?W/dEl;KLjم Z&vRήKWL$DfyF̎z7~XiN</9xp⃎x5?vtWkb<_?{}cbvDGDi3,z4GzY2YIDagy`a-uԼeb8n֢FjP;W}(;Ȇ 25qƐK힯6~|a*Ƹ+7萁4#kã¢bȺc/5ҥq$AmFGPĖ/#0!@A :e sCBQͣlpE-)2;RP|uxO4Z]\khEԞycőZ~޿=TL]EvԌ0--X4î%SÄ́Ąwu[ egn>YIO헔noEeP3CFH𶎠׵r_3yЙ =(.g%V%L Ljy퓯iW.k QU2(21.Ywb\166|UkN4轿QrATp5\ Wp5\ Wp5\ Wp5\ Wp5\ Wp5\ W!X^k@?)EeP[C#@FR,J jmAAIOCfn/N631Okd:~u q~ZPl2Be??mP꧃(AIt0dt3-GNVoQ; 5~ô|N ʴ:chڴ=6mM;d1i{ mCЦ1i{ ~S-9ӡ0E%0c:+z[pm::ߒgel @'p1=t)~g@]^2)ū5V>@.nHȺ UDs;:88nu\yp n&QmԞyM-7B¿՟6?:)%rBqgS$>4 2}''A/ח~J_gПgAKH҄!Hp8e ]D481"Xhh Z >?=C^гD /yo4΋DQ+G3#:ցZAq$Nrx@8prd8:78A >:zG11G #w^гO^%SH= fHqћqq;>Ɲ@eb lcI78%F xХdS)jLg1 }l7]eηpb{ )if17cLL5ہnov$2oD̾sL$wwh z9>8 !=_ eZ)'W7 GUPǒR9]{ZEm[eJ#NizA-?Ǣ̧&XE,g7~ e<7"p7pw#vߌ¨9S`/;G{7Ի i&VzNOK-TKӲZO6Hh%hGC|# a8ܾOikml+ 65㨭,)(f-#4ZƵΏw T\jc:ݚZGz,Yv0%VaUZfk7s%mKڛt =k32q[x42`+u.UZ75}otZΛWv773=v{.=;BAZwvHEi#}s^nW Cwo-K)-a)pyҏB䆢|qAUo_go }tnC~Co ~H/oιh窀 Уg]Zmvyw-ݠy>>ZxO-VT ΃:yGѦ#w]4}aJ_|tW2V{A:_ iKVϣm/cNz1B9@ڭasC޴^v<,}s>aܷ /- {ލQ~tiN1tWfװ<؎*&?la%[6w ҫ/Go8m*c} {a+SSv%tyۦm$lS|{v4칆uo@8Ҡ}/|y,PБ;"é>#Cqt20[^ Ksef"]H/Ei}]cᇱäve~gvetuN[ې9}uXtz vL ;PWߺ\b.?iğ\B[Nx?rCL?SPkCmmb[ǑVPa`5.uK?O-{з͘ .poo XLkFfG^fb蛖 1]}34_D^IUh/F`ygnT(Ia5K}|/defe0T 7g>'qɜ뜹0CՀHhL_4=AOh:K{"%2q[1w*&Er|N N-\YmhZ* QhF6ֈ5 FkVijnFQ hH{:dBm5eڳf<;К݀TЫ{Y'ݹ=K$gk\ptӍsKdH\ڈJ7ID zb$@;3wtTnHwGvV[,GpZKh{Χ8S?%SIqy΁=RHqĂ:9gJ9e7xNyDngggsecTy^,Ajtn홇<[AyzJAM@5q2|)V ЂZ" V na-؋0ljpO8m|8`;lǂ]Yk?Y vcN,؋[I}S8W;ÌPP)GG)>yuɛ%HNޓ?Pɧ7' ɵɫ==!pO4- l\2^a1I]t^AÖgqbF\33Ҝg$g$3ҏbyFZ1# %Q$5Ś4O5( OpppppKPPҮI&I:BC%i"֨auv9ޤiF{fn}0}1jsP~̹9u#E9:D-vb:?Xq_$'Z9UḳRTfTם^vrm=].wOvhsnDu/sWBr`mp56+P= j!8 C_Z_xC'(јnLA=CX-+k$meԷǑCBIf'b:PqFR5aupDY' H4,iTRQRiRetnRmx^.M$WW_U}&'*[hb5U7"ӷ--IX);җK"Ȩ oJm\{|`B Pc/ B'{a0{^^ ^5VP` \%@]zۣ紙IXPOoDTb~lnsvRm4mN|Μ_3U{g_CMZ2>jh?~ "!ηo6:6s<|8i(N#AM=k(^(Md?(]ild_BCtn#FS׷·+ @ZP鋡)2θFYP11?ݧ%_眵o^.'[0.`+(/`d%CY7V Jjmq4m<}-H nhUۼLod:TeX=u+ ̖G_===e TJVF>wdz'o2ucuh g¸)z.JT? %YOլGc Toة 9_0~V0[k>G\YP&3~ŸO}/`za}t.?ĸkk*W}JB,U60 8``5u%c{}ٌwn.#`;>~gxMzu;N=kh:~=B0hOE*B ޶Oo>G02ۤqOU #%t3ƚ{+Du\v8-ԍHa7B8_` = R>R; {- ʚSrSg ƙ*\dlxPg M5xP (2?|9U2xVAI;40^T\Z\I,XVBk`mb,3Ŵ 0cw"Pa#Xǒ~:_G\?lGS6 8d\e>;Ic sp.R} ,$pϊ.ǥYW -XOU5 AğtS{uXaO3t($GFx\IF4 R}\IhiH"MxEGYsăb'*H, JzAlfUl;.#8"8->g;wtd$]FyM!s]r.d,e 'Ir&,"!|T>.*?ȟK5|SVw{O}H~,?_ fH#hfD-h$)5F{#NƵuFc1eff4 ",7+ͩ s9|Мg.0Ke s\gn07ͭvsT\+ڈ6HslaE" :!:N})X< xLxxGţ&l6b O'(B<%"xZkħSj'>Q{Js r t&+'3pK͐eG duegʔ]dʒew$e6u=eOV+RW9'nrD\K09#HA`!deYB7R7rYN7 YA=e[d9zɩot-g`׾MΔ3v9K΢>rM}9rA'ʹ_Γh@.r\Hw%r 2K+h\%WяrMr f[n[i܎3p|Fr#wʝ4v]MyrM^~ Ay aFˣ(q*'I*i+7N*gY/Tjp*7&F(UF8M4(R$2,lqb$I4f4hgi80~bd42^љf݌ntN~c1Ígуc =dƘ14li6fgmMccC|31ǘch9GefU͉9ŜB ?{{iyy?-60%SZj>f>FOŴ||42,03ϛJEEz||V2EϘj zZcis{8Nd,Q#担bX.VbxYlb^_Qq\zyZ8tH^'{ț孲S?w{d#b|J>-/Wᑿow/oSON4L6"3b32HHdrlsd!줮({}$dkZH(ZnhUHMoT;W}?}cYs~9$dx3 YbK!DC$D*K%V(%~%**0QC'fP0&Pppp,~?OI<$M &DC!1$8xh2xH<$ I{d=9#܈)0D 6nAE ~x!Ex>DLDBl'JD9QI":h"ZFΗd;9NjuOS>o*Ч 1>5O4>-oЧ @ c}:PNuA=`P4 5D qh $3Ds HgV@58H@\ [{xtGgLW3݀y;9@/@BE@b B}P?  B%@h @hF@h 7RT!H3Ҋ"!cAꉙ`T_kPLlbct#2bRSmF85e$;=rȀB 0!rzpHEqhnÍbQ7F _#;ndӏ kL1R7sOЊI@޴7e8/}n!9`h4&M3YӜqtI AƍԿF%* Q7̍pN0݋]z A t7:Wk΍]7lwgi!suѳsT?v+77͍pnˍQ?D<0U:\0A/R{A"uϵRTD 5Dg?޷KYV!A 2=h "֢/#qFgynF>7p7\΃`pņQ2 &KфE3Lk=1ġDPa a+ڃZ?pziԖ}pD|>s~q=zSmZڹ>S)=FFd{:ԗQä8W`."MfHe0ԳmGi ~ NGiRWҙntl4b/  _Rbv+$-Q>zo^yv! /PN@N!kLLr'v{7)gb2A1ytBT22*)3X4ϪzUZs˓Ioc* {71qp@~޽]k'o=y0pSbB,>eUMW/yG{Qn8@}IG] Ofz d4]O98+gƤa~nNP\\_Lشp_dvTh0gac-]7E|=B]bB_$%ğe]Nq cvٯ1l 6̶mbU:4/1Qd Ϥ4c1#;3|]`hh[d:uȘK\%quʜX1u[=H[$뺫1qkwB W+E'g]=|PLu۟eJpܟx,SC޶r {˙]==C';^Mjm#Ek<,}CY~>dbԾ#1Qu.G)>!6fDrm+KGH9}>G=ThGO:w#]acR&A:762k79e?=sn0䚖k>:v"(i_yӝ.p4?vM%+[Vءow;t9S{y }aߧ*q<^=odk_z*kȗ0#,"iB%|;V:h(zYv:2ztJ^Kڄg H;_\x֩{W0*ѳnk;)Дk\T-S!FMŧlSWO0n XjpJ#þ z'O eV 2LUXǠo*B-Y m#wa1x*S8]`yV>{pQw̬#Jo)A<*Ђ?<@gRjbQ:,NLw4TII(7brru077`kkZY*$kr(y׀7h -$oNNPLq{ʄ-fsFg^=n ~љ`]玏"ej%=޼U7//uR17-(?ל~. yY^Wn`ڀDZKHFdsʿ4T^k; 'vnk1s6޷3q̺|8m5R7]$p̝VQ9xmsӹg5E{6?wyBMkO)D*lQS;3gU/{q5~dnNۏCs:,R{2oņI 5cb#E, Vy\mq9ʡO2)}L |"wdX2(cCi42=Бv4)ƭ4-Nda,ﯹSG-EN\ݐ΢vr*bHJg9P@~ˍt)eMoy{vMMS˲$'*(IOg! +0g3O޷nr]6jXIo& {vsj +I|Ji] DN(:"nMGNק?8/Nxպ~duW4_ڠξpZRK>ngǏl !#ϸ%c }SD苝uW6p0 4-0?ܥJU=۬(VEgG$=ٽYpz&f@<sܮE WWNe&X=CoLjZ*~yה$ױ% Q/"2"K>uS$!2]΃sv8ۖlRӧ '?/|dn)Yw>eoJҩ+GQyv/߷ endstream endobj 659 0 obj <> stream x}SMo0 +r$@ !J=Cc;M;P0(ڵѳcgN5_tW0Qcw%=eUM9e[mxݩٯ&yÃe? tl秾+IX)XOE FrW|3K0@i3eW/JЅ:;IX5ObnTBw ,^>*O>1+)PŚsΈ%6Yiܧ ʗ ̻E"9:kDm]w;~4%H$6}/YCʈ+ RA0q\<`қV]%Bb" +6)ҙG!RUdM> stream x `E=wEBȄ1! rdr' $\D (" 2& x⅊zo\E2=5Ⱥ-E~<]]]1" l9Ńy %^:0'7-DX0fmD5,.:\b'Q2ֳD Si^-Df؎澀u%҇TNVJ1bȎISTWv9쨩<`wW 2װ]+j͸n)&"'Vv=}(9ڈۮVy̢o kHwVն켇DEcS4̸ Үc]W/o[?M)$ӟj=/h%] <Dz*HO@!+%S`fcIF"coPB&g0+NUt-xtދbͼa6!~Qc[a>NN%e`xY`:vs>;v H!kLK%b׏fk/q0ڗ_S9^ _7 FmƘlcB |,;]mwQK_d{%|]J E׀"|q}|#uDZu87EZ l?)m/d^N价77_q<;N4^5nNEs.IOGB_U_\N%ߺ`T~o0@ Y}~:d߳Χs ?nt9]Nt9]Nt9'<_:@%>u~h_o$ģ%൓~!/"o>"z?Pr.rT7v_ !WOAzOMd@cijOW?ϩ„}qq.˛4Nm nr$'rg^,{.^n][UZ8~6P>ab ׊z{NHˑ5{2(G#&0:]ZW=K NilOJ֗ fJiinLTjNIȭwVVbˣ+1>m8+;Jy/٭Gp8Yh%G˃yˍ&SVKyo!Ö{V?찢MޣYlNM0\ww?+j|v>ߥSJDUI2]T$W&l˭ʹ?+T﫠_c00̗x\)(FisQi1N6kۇvj%#%\J6`^bSm{}a3݃n[>lH6Lؐ0byyXyv+ '785W2*~ZՊ !lȬXxlia--lٖtdg6\}fVv-WXZ**m-k[]~QE` ^,AUb ~^i$#vU`!Gl }"[#]LnK3\c. вM|)L[.nxD)6s$lkRi43+GViIsV9#Ҝ{i|+)iNJ4_KsBR/\ϤTO9.4-#i>iޗOQyWҼ#Ҽ%!iޔ i^5i^4H4/I4/H4/>iYif4{-<%.ivJ,M4OJClQ4 Ҹ*lf4I4yD<,ClAiKNY+}Ҭ^iVKs4[Y)͝!Ҭ6in^e,f47KXY$͍,iK3Ȏ:ifK3KIs4ӥFiLf4WK3Yi&IS-M4Lf4ҔK3^qҌL1ҔJ*iFIS"Hi)@ f4$M4YdJ&C&]>4i&UizH]di5r[*TBO,Mz9l*=Nj |ވZ, pv>tZ*ݕ%M Lol2W箌 ̣ 0(o}Pxzl_9p(at?Yl\ߊO21SeNW3cQ2c''ՔLJ.J,4"$<\2$vJ#QI%%%ldRqIF1[i?EI%I#JjGl]>g{|gyI%9I%YI%&9(YLqb{ݫT7^ߥԡw=zaݾC,0wL'i¼BI']!#m!o 9 ySB^W򊐗$E!/y^!g<#d=Bv yZSBv )YH;2B &Q[HB-B6 yLȣB6 yDF! yHlB y@B O! Y-!-.!+)! Y!6! Er!eB Y"f!$d QB! dyB ^! -dBfr 2]5B *dLR#dj!UB*L2AHr!ㅌ2VH1BF )t)\%d!# )R(@!Å 2T! /dcp -|>??0xX8okUp^/ ypsY pދ=`7x<v4'l &ĺVxl b> 6GF0xl`xւ@Qz`5wJp'Vcok[Vva[6ja9"RHȈPElPѱya ^;[[Ywok8 Z|wax7uxKEx>x<=`7x<v4'l  l-`3x < 6GF0xl`5^V]`%n+mVP` K0[ nxf70sp f:p-T0\ &0 T*P & ` P *0 0 `0,  }A:z^  A2FWߺ\_1NU{{.IUS*Ho3KEbZOO3dÆ\Bڳ{Y縧5{ԯ>bT{O{xv=){RqIK!;/oҿvuZ0`|a/ÅcEk]FF;I ݍ"8qvM{o=EOc&5Q3yio[l=C!g?:{^7M:mGGk:Kѧ' St}t}u3Sz* s8/ Lxa_W*I2SlCwӧE=>&!L=MWiĺb5N ZMmq;S(7@SVjuo[=jf :VlhU|IO>?hyz@pzrZztgqahֳbWXJpߡs K*EIѕZLb ߤehbQufޤ03#`RhٰBY 錆L^ǘ'OF*;6$OjD JNMmy0e}O{tq1Gʚ>`1c*Zs7MgP`jO)!*a `X rD"3PZәZt~?΃g 3۫ԔJ3yb۫M~Û'إ.SbKQSyCkXk=*l.w{πkX='R;خ} _} TĶ,0ÒEX(b JF;'~,`Q0FBjJ{@%<,K SLo0Q)"93S%[c[𑌜M㨾k|g]=^?lvܖJF{.;+|8"ԅQ_- +ǔLqS Iz/ZO[_Vb[[4}*ϔUq'p3u٦mr-QȎ2(B[eX; ~m%JnywN(> 01,[D(>9KЄvX8mbAh{2wNד}^ᣯwp\Z\p*'O~Ytlʢugm)VcK;C2fr(u+0gyP3}΅e/Y[A̐^W.֧'߰kn[l>s'\1Q#ry1[~ S#u{.5yƞeНRusA0#Ȱ)Ŝid{wkL`a nV[^R];6>Y]^paD}tb7I=gq@hp3r]#==]BApwm#>i 햬I+#Ӑqn]KM7LcdRvI$١5)29֗]S}lY .yb?v~X-ϫןTbK۫[׫),{rg7fL4EWYbLklk5kw%K|>[-_%GdlC5RLn>56BIϵ閖q=89Nt{FlCx+㤌^0Lkar &ϘG/Q^Ca'ޖvv n߱˧I,bl B[%Qwy7ýho\X,`w3[P{Ew}f5/6bXܰ5d2j6Gڐ=z/@6գ҆s@ N>jO1 {Y2qC v7:ݨfzoWw[fbseDyMȈL̐b^ghᖟZӆ6O)=1Y޶͞uncCU须zwg6Ne&lPL:5)ل^3U4*? gxfL7s3EֶE+<5ptmu_-@id1Pg"H`F!ךIBì~:e]`W_PEg 4!&}}o|Ŋ>m[[Pt/btW}4zSjPswMao7K{o=eW5pi!ŏDFv0Y0E5.oA@3 lϿn3 5:}!i7-g=|=X"K:虮X[O*k0U2񯮰|n3{O2Ų.1o3NQ{6J| xz N:]t՞<3]&O;x:}=֞P{;T?7Qg!߆2c/B?҇ç})V> jPUʦsuujn6+3U8Eyh13K!,# c{d Q֡C[[axÃCXm Yw<8"=Q#{ˆ1mOK<^XuEu_vfθRYkńtrtwߨ%]gtJ~NEFe/%&shzw&/vۊIa 3uG;2рZZ:b~s7Q=`ǵ;k|6Ŵ=p=-51K%gЯ=7t@٣{6?pQL93!m6vM-jvр؅QlCnotSS>ȯR@[<۟C}uA['XuL˻qc5 zlEWuuO0&ueg:Qf7›XڝXoFpgGclxg<{pӳo-xxZ{CT{8«F6@´.Ǫ{z\=?ھ*k{srr_[6m&ik JiR "X@DtaA,P, 82~0#08U=|{<sZkֻ^@'\~uݫ+"u/س$O;"-%nHsv=['V.|mKCQϯ늗xk(ݡPF/sdAFH$FJ d|B!EYD:#' 2y $K&-AůCs >5X tso{G;^ QZY5c. Z@ F"^Q:EaN_T2>ݗJZ˃F6.({o/K'!PePٜYj Old1 fy/#+E^;ȝȱLeH}*k$r, c~f@u 8])`lՒ#] n7 A~ڙW]rS'wLQd~oG/-MO_AsNufVm?-١fDO keR3C9niLmz ׉{ + |JNK#3kmyShϝn4=oL-5ʠX/Q55zQ-1b,'kptæ6AC?֖_45?7.}^bݝTޚNj==_[OS,Rq #sH$`WdJTFƴB CVisfROS808Daeh~SHzl^ h>Sߩ8&gB8$"HPȩQ9Dy5!RBG÷NS뇟Ҿx}42Pd!ddΑc~xj% /w]֘cVueG2lw-Q/e5e*d7OU.YLP]_VA_#٤Ps*pSΚQ6HOp ^G\_'ZDW-a}ku֊jy5#vL:; S!%}MES2_*u+^YJk)H[g]FEȽ#ڿؾƒ}OمE.~qEAx0uK-Kڄ"7,?|` (G>NK  Dh:C5|Sl׈lgX X# q 8x+"U=pxADUȑބB26&"E=a7G`dhEޞ/^fM"5泣^#B1gςxu]#{MMO;LB>e^d.x7 ׵.*Xl?v*o0#`a*5V|v7+\;RͿnzܗ[yUCG+U0^!Q(Hv]Bb; kH3 QQ᳢"B$jc5t@!2GSKEYu93XXDf{;_k߸n̒e w>6n[9D:WN@e0#ITJ i.Q(k;#Sj5SSuHY!w(Z>[!:PR kߒ18ع8Π~:L:c{ _{ YݑIR>B={L-) <}DQPKMZv ɳv< ǝLΦ䩧ښZSo/F1GF َ|t^"Q"K3GJ7+* yZ.Š{ ln_cb]h+:9 }o/F*rC2\R ΥLpQH.)D𫹼Z*p\ՏeeqdYxh^e} ʴk~M%Výt;bqz47!Rw"phFm(HG!@ y!˔Y_Yb9DvC'3$XQvD^O#:'((y7T5H=Lœ5.00slzA-DxP[}` 5g^VJ o2&978QSf JcEZ0O&SJBRBO/)C|\#S 3Z@?dc6 |4Ca_5B͛<&ŔCڃGd $sU<$Rdz9EvPC) iC8C2L39lI3q>Cjr|1 iS5fI5^#_|WI |JΟr/a\hXhn}cGG@sNfSBɕbI4k¨B]!L\e(R A:1|C-;!:dU=GD3uV7I#k+X֑~*9 Ĉn@%|R|c)cHf iOpL^ ʎ/9U} ryVЌeqG AmjPK 4@Έ C'dqSK=6 $6Ϝ5H1]os{|-eZ3~mt8?QgY} GĒp! 0Pq⇩a*AD'lfO%0_Wփk*z5eOrl:xjSIiI%AѶ>'Q3:ƻLx.{ zQ YVAaZ,N'4hu3=(*@[c/P=f t6 5y pUsS2o'Wôϣ(68C'|SB#FVñ/]z9$1V<G$Xc73ɱvogtYV hzrS|:J \k~od-^hT2AMHعX,b|~;-`(3&n(FH0$[+l[CT~& Q)`3l3x^'E<8gjpM>*١M  j Dq%VBQEfeB$ IuT((QVq)5Ut"NX0Ϣ:E/i*H3h\AS.$rM^QG''&[k'dܶ\cg'brA&# }-ygM:vtSJ} jW֥eC"yZ03r_;k$U _nHwkRҍi#bN^Wj{vIɥTlg,ȭZ:?k+|T5V5͐1mr˙ꉯȯ 4Q]$] FI6RyrUHMd +u䗑( 6dfCq|2gXh s(*UܶtJJNϱ{!%QHLaOGU$4vF+ x!{b: =lq1å')6G>^lW&%`L=w&Ңt[ԙf?yWF;XX2de<7L ?\90[s>a\3 u q:5QzMoMCjج!'&沉jIzGl# a.+8߇=$"(H{ OՖy0אo'V[~]ū-2$$B>~i6l [F7n@>Q!^BTFxD X?A_AC:P=MIhqWBcMe3=Z{}3dn;kdEjp)Z bz9qk|(gأ>S^OŇ괨Ht#~2f׈qur]'h+a &x0%B.0@z A@ r0{IV%0`6ȒQa,yF׸lHɡ*%t{]461!2uEnơ ψ~DD2 |Vj>d6-U#Q#S^Bryݙ.f=m?{柀{W#!۹aDZЉ9<9ᣙ$˨$qИG1Xv飰=݇r3$v }QN n %*1tGGe2Qv?CK0`c׆XƨZԋ)YH 軝q['!L9~WeFQ4 u @ E6"d"ϢS9nKw0Br8;nźul7 .{}>XI=ރt GTg[Ta<~Cja4〉QΪ9ыJ"kB͋VV\@~` &x];Pry+W.xieQ~ϑ||"G2 %KG!*ˈ)y7}m{;Eb3=/Vt߉MɓL@C7 ? {If|^^FE~?G,X^t2AҏnOď/QLe˦aJ#}ΐaUQZjgsc:>k罾m ն 7dC٩ofvsw% ( u k<)Z`!~>ޭϚN2"2R&KT{Wm:~p60[9ޯWZs@=0@c`Xcxe4qY/ rԆPc^Hk{o銤ԮjLz=)9YljKVUX7u!0(Qׯڵ^N *덚_wJ>Z;j|Z OݸT<.0&C1Z5:q%.P.eDք+VU];GEQǗ좗[*c`Iװw M5<[͑Orp4m(Iq9Hy+O{Ӷ 9B0TAϐF*T*FhPeSvߩQӄ/zN>M/nPxw?G!߭_<:#IsSJ]%9.̌gn;?ǚS;zrݯiWH}S^΂"%:EDF&wrzo`עuR18H[X A^Bp 2A<KL?A I13%9)VMDB9[0fq r_άy"umiOQUZlV-H{qfߒu>l<ʸȍ#bvv :;zQ/e_J[v30yrՇ{qu)>vx$GexԑWI!55*(Zў9c_Tnӳ&rF{|P9#&0>)? <ҡpCoQ()ޔ)$*6 l_*G'wxK,b,cf02Gɦ_Dl-jɈ:nB*1~rA*G2T~4T8wT  [bH"1RyA*L>*\'z>a:T? 9'VõDZN1wAi'֝PmoيNi~a]wH V}Y*LGg<1W+d"R)W1JYiD$"goKceo`(B"ݕ8"{4P=oT^yO-ٕYhΞE\i{aM9E>Mr8DFUKwkl c>?u/ ",:H)/!t!NxDB(~* 9_~eݦoW#Sn+N;Hcp:`RǩW~~gМ Eh˛_C GJ~VP :.."8r{G>'k %ǢD27ٗL%ra|0  +eSZʗ:dOhR27aw^X1`d6B#ZK< Kzu g|m5<N"|⓯JW8 47]G(-^<}fpSi.4ؕ+qIQu5[)Mkik,|qEyYkZO̾ݔuU-$Ltl L  Nae3ss^u  )mLN%tM)T *4 {}}m [IŎ)EGY'6ZT\srjp,\yShpik#>M'v<8SQ߈QԲ92Z1}e[isIG-8Pv7 jYlWL˶Xag!sGG<<ݷGU$Haw~2ؘAo( [KFq^xGV/C<'a΃o"&)q'*^dIT'/~U70=2i,_[A*+iβ[^$?drpɝJ ,+&#H;OQR)`5'$޷Q] ;3z?,?de[-[ǯؖ<؎۱e[Ȓ8N BCӥIJlJ(-P--v)miMi4 r3ws{g4sFpRzR2>FcA3(!9Dc+zwv7]xC]qρǗi/jio<6}h=i*iU w7koPn3+G;!:%%l$fSGlS3q?{+w.*Cn x Fh rϗaҐY4n0k9k~krpqCz4X.,Kc|Gx1Ỹ1\Exg¯t|~vdv9pܛrM1q b3HƺAS6vBF;eN{i#1=escgT]L] [f~Z[{;zzHLK4( P \JI|]Wax!P)6G\7)Țĵ -J´b %iɗ:?:Y6u N?-S!Ӓ:̀ʹn|T3e.f^E!;- [AMw 8) ν>aC& *›q͈ǛܙzxTҩN˔*c*{$$㐞!o\z),G%; z*7]Uc!s7owpy}MwzYci  x5w$ݍϗ`G4`tk)s`/8şZ_/(!$?&7ׅa| > l#0p1 6-j Ve!}dƻĻr0S8ʰ5V(kuf<02 nb[ogD2qĬxcHU[k~恙~&̫3wl+ղ"О'_?O݉&9-v * c2tN4rIEʪm_p%Y _ׂSTZXm]6xa1H/ ʟ"׻4Z$'ShHJ%#qs;Qvt-jL%s2e'D\*!/q8(.=0H=%[ Ue`% ||s'g.Ў7 "~1FB"II:zʏO`;A+LKSN͓ \c@?%UL;ar9q!"!"dQgkݶ7\ӘUi3=󪭩fS۶ypu7vrWsW$J0HKmzWsQj2NfOL4^J>!LM1DөՈ9HóW̦%weҥ@2l>PVWo\Usk-i徵듍y 76% 1 $$! SPS:]2IUJ2bӔiV"TE4|&nȯ ,s=Ȯ_lk9cK6ץ z:AUnR8F%#åcTrZ60I*^P8uчMAE\"9#sL;Q:ZB#2L7(Y!%3IBN*>$R }2i?r”n~7])9-k8-[,? zd !;d19Y dnʤѨCMPw,I7iG. Kr9jkeq*a!tqT\[v]CnFM_&lROo[6vgM^hSM - 'cRxTePJܷaH$r)TQ;4qQYkaIRˣF+ZlTw٠U[|xVΈk`&A3ҘVcV(AhI )0b2go4]]@2g`IIڔ-66<*p8^&D$s6XV\t׺Oe%52^Δ!1&FFGXڙ$R"OB\Q"R FnNpV-dT8 { tʘkG=dDpC; kDgN:8w zRՐhX}$Iu;U*r&1QŚ EE%t Tl% e2UU5CzyȢ! ̿v <|tꁯ>|!a9՟wN!IeǰVKT,skZ- *u"EGd&Vr- &π85HIz&V9_8؄ˤjEo ZS_lRs[m-d GݘRܱny뱕kVnZRPdCeŅ%E/<؟0%$%*/vQӢ&ɊbNǺܥu[KkW {϶!o7Sٰ} z4=##(q,$c[%K7Mfdg"D$J(6!`7vq?4.+*…}.eCuƼ {A7 rQEv#QVGݳbծr}!9ӔZ۰W`*fZl?HD|?&{M$3kRyٓ ؈davRǸΉ1"h3 R77d sJRmkm&ZZNRs(]SUTa>lcBNb\~<-MO3n5#["˷%;[%\Q/GZ!w%MFHPXJMu 7̰XW4Zs'&u PZ}ai y&Mo_`4Y[:l&RK,qhB1dH q(:8;m``*0si!~+jh N"vLj騦j4IOLdE.9-K3 Wn優<~A ?+&\<Jdu'rY%\ 31rR?)>IgR'fZ+#Gt[CC [R8$FP(  )JF?#G=NOH"y *֦etRful2Kmjwo5{0>3KVwFƀy(`RpXAF&]NEDYDu``ɻ~x/u넏jτS@Yv[%ɔ:2JQMDi pKaӉ  篾^z7]~͠HJr ,PR@'~Ճv5'cp+=3Džnfd]uRa( ֓( /8CEy'pñd.zكrBI-eZp 0"0H>{4乱&%s_P4Q1*2ࢥ[HR4RUfesw4 b&|R(2E2$fe9֗vEZkmSUyS;Ğٜ;?m7`=Um+1ҨS+:%n7jς", 4nʼnNJ`sX9˱?욁]l qq];Dq c?*SA0#ԲP1?59LsuS!e%6C¯uE 5pkrWTg>ٔșԢB\sqԝn*ZY[V^-c{glJHO)Hezф?XPힷIs+rz#S ϑhxXER΂cȍb`< *2y[  f^!3i¯Hlz 1ϛyӸHpݷ6A֤_k7X~>jSRCKַkpvx\͋k.|.ѥ%JMդ |^i;!;ϖQ 8!!o~p3.K1KE޽w% nD,zrHpgx6A~Gɇt'S`4d̽i:­wqM=]&kbOg9@N2x+-W;x8#W# Oh91u*2j]Vi r㼬fg?m8țE0>|udQ򑦪LpƂr~ ܵH>g]+jf{Vܽ|yeQ*:X<׻Uj)f>US%b%be0%wb$dNޭ Wq]9-6M7KGx~Du*2lZY%Hu#}A)O@<) A`[q.h:[;s-2PSY]n}I &XNDq9YV 4/''SIc /s/{K3do=K`Aydp\i2cRbҺ4ZYIpWQzGkVRgV72JLee4WGeu{198P@_jjr^J2ZFYA,v!y[)Y@ipBV1P|t!т Aq!LТ]cVWE ߦ_itqr-X@G =XI`4]Ni', \Mfd+]z}W2f5L {-NlF.&(%9YeF8M9\3S+tINt%ѧYrW3 g*X%Iى ƼJIx|? \n0# ͞_ \_'~k^x;K,6ؓ\D);%{Wn/SC9|QeU5q 4XcܩyE>L7^L0&H34_$%N\$e_ոlJvJ*)\L)w0wߦVz M}jNДk˦sf֙o0OO2AZu ii޽ 鉐j\Fy?f!Ӓ $뚬هss;skr'r_ȫɛlD,W[n|rQ3-@z/,XSمXeV֓߳m}"\.J.ҋ>&[2MN۪+).LzxOſ+1.y˞boottHG& EWҕt%]IWt~RQ^1)&g/ۜvU+;]/Oa)?JDSe6M}RWҕt%]IWҕ{B2y zuB?4=~OR/);-\\2>py\]%\7J eԣ(p-*VpsP_P'9ՏK8FJ N(C¹:2py\];.JdQUȠwI9A%f "> :ܦNh~« TE\rqQ",rQ".YE9(g,⢜E\r>xD吪kG>4B(5BzX&ģN(Bp,LBf3=H؎:<"hKjR^(Htʽ{!ݏHmh{A\#Rs:ZgrɣqC "(q9'G-^cP:9mtDH+;mr;ao-'gLPЖ/֦끺Q(CpnK qyTjCJiH(L[ (=c0&Cn?d4.ɭ3%㴥Y9RIRԉH=L㥜 Q]iQ}ӑG=8O2De^ҏP m' 9D4| ITˣ= ntGrPHǖ#/RJS'L-KN:X#Q^jcҘF7F[% I ԞTz~h-|fcH,1UQNJPj#Z5= F%Σ8_WT{$YQl=+I[% 1ӳK)BEh~:۩WI0.w?%A8&>vZzZI'nmW[3Цyjd{ޘCPL-y؆$IFϹ-y':3DejdT#nsH̝t#A*IއGK)WDgFAH49i.eE;$F (%s¬j| !_QE?7SFbfֻc'OTB&F֬E>v$85@.MfmR/j(i@3-qF'yqqCY6 ~!WKZe4/=sK>su'b_"^TIb_94@= {*3GQr c/]Q H:;#.fmA!60F2:VhaY^^ͷBppKoF!O M~?No,kA'¼7CXh(8C7 F8䃑aoFO`ǡ{`  xx;aO3ggˏ#vA>21HM;?FxEP08}^(<~\X@0GAa t|#1< "3{8ްo(E(@DЦ?#A> ňwGz gGjAEB}j|ᄈ SG Oy-mp { ၐ C1 t-^Od z 6TC ,06 y:> >Ht$&ue4x  Ox3ThFax,@ΎSx ~'4A$:0v'$*8G;4b]GU(}e4 r+˜xz@C> "\(yGPF"xH2h6 @T[Ew;-ah lZ܏Tq=G,n 7F xn|!^x3^b%x KR[p 2倷Vpxx%$;q'] nx/ӂ0vV43oc$SyIJ~ ;KQaN˭O+b⯀WpU(\\9Jr J 8,ܪfeZRu wu6#6Ϡ52_`^]|_e^1?::Sax=YYϱ<͂L3//|} |}oɗN~~SSsσ. `#8XLFV)9r T+JR^+ J2I0EЬ+ ACSC jZS5Q=44CSQPȻ 9HXts!Oۀ2^a11d JE첕+[ΣV͓[1i$LFbrCz2  Sx·FlCQx@QLavzЕh e|d9/@ຫ.Y~Xܚ>6Gf[[-Nί#TS6-S>6B7CO3.I;$C1}?-U߳%Lߏa|,nK<%mg63R[H=qZG*O%B\;`)kM[!y~#Crt<@Hڒ}s 2b_[q{,V=;WvASE:5=n [ /Snzo_p :eVK<7@^y9䕐{~?ؖY G?^om<+f鱸|Q;Z]:z$giKG ?!^\0ޭߒ-JHTY'zζytϻP---FK~Io(O! ~KgI)̦0b )O ߧ8V(s-_iGhySm($C @c/X4=4i]Oa%8 vT{!=%@;t^I﷼IA?1&B]A uoZ7gzc&Z,[[(w)} Xs@qjȹckࢼ9D CyfFb2a%j *RC!u-5Zk܄ZZK]ck%j5h,1.9Ak6fnw9s=s3̳<;9W}?{wffgefeg?,k^a -⬅YYƜrȯ#?ng ҬAہw[Gt[v0#{2y&qs&;KoF(;sٳ/=Y}B#GKehk+[%NHD^K;y{-zC> -owR)Ȝgl3ʃI:"{;!Ϥiη.сQh*OM}7)'|(g*8Nj-g&Yй p,LN͡u#3ߚKsBrUk9`Ɋ+39A9k9@?{Lv4ގyshyg :86S9hUUO']9̕Ag07$\0 Kl_&|9$OK]s1H1wqyuӼQw@1g(*'Q@7,S.{Cջh?d(zW Y΂`/op?v fz窴a_ˍ$<;m{3Vr̥=@O&26Clj\Gp˱Ivͽl}m.GsX;J _ @Eb3vYs/hs)x.n^ȭ n62nh]܊yכ#Uh^1&ww IRVmFD.]{Y9u=d^*p?i3w<橩uPur[Tzx{([N}ivKq{myO6GN]X&+*a"`f1BLOFq [}XivםO{i>١$T,/ 9- 病f旛# Eg*Ыk3"=֨g e:UIc9536k(?3."ob9Pw/Q>*3!+8ofb!>o:3'-lt(\v<4/3%-4ZHx&83-\hY B2g2_wNКu3y uISٶ'{`&Y0 E=8*XAP,.,-Xҧ IkY@:j[7` avN, Q'#HIOYs鳃16J^GꏤKe꿪rY= URI_QvH_WOgo]jEMhõivjqIK$\MM34CzQskIOjQ-S˔Nhٚ_zM6-͓~==$ujӾ kZV)5mԭUkk ړZ颶N['k־#M&Y6k?umUԞ՞j۴mrcmGi۴AyvX{UjowjԇˆG(r~P 7G\#~'0J|G B$_ɳ8yW39|*DNJ;q,qRx]!<'>#.LK)[R$EH ?Qh@]4LꚮOCb>\.>걢HCOnM@5#[+)\Mr- VC^DXX^^k}`+7L?ޒޚNR'n+5!7ڙޛ'J.GZ^QK$n?dPktQrI6&z$fS)"EOSi (^Q4*C^L=sPNb iWʤ˽}Sk_+_wm?hn9Joakz䣮sLJH{U>Hb[濆뭧浟n@׿v7w]M]PCW]0S&c`lxp=yQ+M->qǒ[+8 #8iJ5ҧGq)'0*=Hs8B#2.8#b8 h7n%6{ع?)vxgSIJ3EW}9]F蒘ܮ ͙lŃ<` ݘ)|0(%'M+6(JI$X=EV5Qq(J*jHjFN087)*#k:-qX/c/~QJ IWȫsȽ"GұQq:68FGcqqhud6H ]dH;%S+KF)5E2Ru$&Qk{ȪQh!l5X:JTv:†2":X#јHe A4ҌH~_2>0'c 5"ߗShѶҸk7)}6c'T\k.#JiV2[ً3Ǧo_ǎQ 8J)hH#_q>u8**s49S1N^:QC5hhʣLrNuxh>u:ΙY Kity9)%ڙKldfs\\&_B31[8\A6:Wqokn%L#@(=\Gssya9Ht(orO:QCH4&-vaGynv>,zѦ%ۻ0[꜇)isax `N$]O?yyyyi GKvE#gyM]l+}k5޹f &&:T#dx2{{VQ+sG {e'Tk:%7 S)y3.U*2J\ \5O+t4b].ZZXWg]d[4q5S::$j~dQOZ\F󘫓fEhrnQtpǺqNpnMz5nvS4lJG;WX;.vN{)w<M唪K"j#ֽD:VC4i NȦH׻77; F{{{{{{3sw 1CuΈ1z}WጤQ3bi{QldVb !M-bURZ9m唞)=&UMVi5@)]RzJf3g꼩Q^UNV Eb QjtZ1NW!ѱ%۴dQ ]tM{?>yfofofo/+~R~/]x3y_$/_ٍҺ6F/[Σf#!l1RouEO즜JCGoȵ:"+P^0勬gª7pt]Ir Z_m]7P\o]svPnt |dеru w;)w =ݔ{)P)G#FXc)] f#)OqMNreOA?M9ψׁ+l Q.\j0H/[D5.ŏ"< /a/'++{mD}:{Hi4ۛ9R>bolej|d{u|l|\|B|.O֋)i"~6rrzRq^N8Wů_>~cfnȱtV:Di0}JkPǷ]:;'gCn;bNuYEthOcҭ">iO: )iS$Eb(E8%\EQjWUoj:Nܯޭs 5_|N-Tb1E;E"'Iђ?DžI+q$+X9m͙V, ;iŌ3t2ʼrK˭kՠ⭥m <3L\3#9w$>R$#q]qDulx:.iCb7Jȯ~%)S +4T9'F#PqhuC.Ts]jZ owǒjz%>-| MaQ'-3 ?N?zO:n~4PG_&A>Cyii :m?g!O8 tʛuIGѯVv@[|Ӡ(=5“Y793YϣyT5[oIKİfzMZ{*.XȜXx@[lm1鏰!9{; nWLYrp$#H> 6r%G[v~ bt@'J])bI%ulR V= ~^kOޅ~s>`/ۦ !gL{ԝC^UÒhsz?N9g$B*?|uW,chˠGom8GW6hSn!>_dxz=%˥f؟UC6k{o`~xhw3rd@cx j.~Q)n}<.U^U9<"qUCqIY-"<Ũ{`$p N/'D#`"&lԖ{^9ϴ)Ypby5?;mԍ Wx/2=G1X~'$Q!`@2ي9g nԺdF@Zj $ӔP!ta_M`#5{(G9u5v};wA[GXzogq_V _60#iǰOj45;W '7M :K/r9åBϏb3l8CxUyXYq@yLr$WW#Vk{q<t^Wl:f1M~ "c; Zbŋ5~^OŨ ?1z`Y HŻ: ZObFP,53l[2O\:˨FaEK?E1;HCfڽ4lӁPV֯2:GA*mƊxd 3y#|qXz9ǰq"H.S_(0=U^$_{ku@'4u"Jz0GY8#bwam0Q&|r $)X㯀eY+"1:'$]\k7@7’>uwxVOĘva%!O sTԴF*|rPkmZLk|~Pb-EkZk+Ʈw+{Mت/Ʒ9DyC|y8ɓ l&4`>^2́yoaoygG5zqMi>{42J |~G“0_}{"rReݠ3U߷Ά䧀1ǡ3hKG| |8M%Aϛ|R~ ,|RKQ]r7G,} Ư(X/v? Y~% OqDZ̆m_C΁ #eo3[NNJ2hNytoV1E]Ca S~Qcа6$?U|'bYڏ0`@'Ȳ66mJٮ뇀C^rá7/;)}kIa3"dfcXs ˜` DPe9]ㅶrV~=a5ޣX9RSV@Rj-s,FS4~U~kA*С>׀Jk"ɠB1Vio0=SxAAG"$J ۃZk- pG3М md *f;!V赠#OKZ{i:HBS ,}S͖8h?OLtJBdJ(}4b0Ϛ3f1M3#jLh?oc:Nߖc@0"pP:/U/<LXrg:ie>9Ǩ4+ ܆5; 0ϴ=:Fޯg!(hsP֚gi3 Br (-fyu,4\Bit57sގlRm >D Ou -3}n&5: 7`\?"O3c_Z'/*csss9*]ɴCg{f$B> m~@Oy>6??9|c` ;3֣ƨ?#RVEi$c'j|`|z=4ßqV9V؞z~8.!(?kƔۜ{;֢d'zٮe /ŭK?#. w!k σ4gԉYTc| lԉY4^J=iؼ{DkbTGJЗM{5dր> L.x< =mg;5C)>)Ib.3ڂXtdNZƀnj\W-=VJ$ӄL D~߇_F{>%d4vN?v$qԿ yv} @] SbmWgƛbۄ]D;bH)bs(bXnISh/n,rGyA9+E30q8Yb"<1_,2ʻfI!;i tnVqI"YDWxE(H x 򺸝M{OXo_ő"QL#ROE(%bޓY)VZmG5'h1E8 qOd\-ϯ>BځN~ᡒ }@?XC_(WJF`tßWG- lv^`x>(` 088 XC ՙY@пK_X%E `tQW5Z`ťF` << <I"hi %IӥiQLZ,UJU֜Ru-Fxf=xtSD\#QS~^bG[ϋ^j7Z=* 99F)4i9g1fQ=&tumh|0c]ǖV[Wqt'/M~|uzm2qN;Xkfr!ޡ$)U>!>ۥZYhLi&}TvUuL3䠒%$E Y k  PYQQYsXW{=߷;g3]twuutUMM=Dh")y b>+}1p㥜 ھ+n\ X!~:"%HD ߃j_8ea+,n"Cu"eFR3'YtNMʒ\"W k(\V Yn0%bj11u|L!7U.ƭ^FIs!oCk|lȅ,7O+) ) ~NHHʘKcˈlE9V#3B:"+K]Y2DWV@teDW%RDWVDte ѕ%rDWV*P$>Dte ѕBte]nDWVʪ]Yu+Ate5ѕ&݉ѕ%zDWV]YC+kDte ѕAteMѕ5'DW֒Z]Y1ѕ]Yk+kCtemѕIte퉮ѕu$NDW֙" ѕCte]YWb~~nDW֝z]YO+۟z]Yo+Cte}ѕ'DWvѕ $s0] +LteC 2v0õ26d-[ .P \P Sx[Z9R<\d.J28%^E&sאk\ud.qK%΅`wrp{A-a58 ka-8`' pDʠu D=AOy`B^"GB Ҩ 5A5f(@)(D- :9ttJST%j(KP5P-KBZ"nt7hLjЄ֢`ZցhCƴ1MiShIЊ-ִ5mi[hC{B[ځvv{ҽ^Оv]ݗ ~t?DЙ=a/ڇi?tCҁ/DAW:!)hCwN;zpГˆY˰ fReYiʲПga*2 .l8Uc`k`#b`H(A"),I!|˕[?̖0.Y'[ FAJRYǬYE3N̓ԉ~"&?O: d&`fQzȖ➚[NN> WHB?a$G8$š H#NB_ GMBoa( }a$!p,pz #I#GB_x pG⽯0 D&{ 'L⑉摉ᑉ呉###2Gd*H4<"3yDyDf&DDfdd#GdbW,Y#GfJl<"kxD#G$G$Gd.Ad!U%"<"<"yDl)#Gd'H1H).2W~#S#Gf/><"xDTTl"l#O/9#R#R#R#rG(1z<" <"M<"'xDyDNii9#rs<2yd.\䑹#SM9Bi$<[ǁ7Y3p4#`, 0N3` Lp.̄xK_< qcFp,@0ba<``LB8N,g)83 ̂p WPP:-u}RlP:2\ɍ9q#7wT;8+@o1 :]é)86@ុ h#Ch*@h󟞋P&*6S[6NvRT UJʨT9K*APFYEA])S΂RnawA`B/4vC a<4E+i"=x3:n&@Q2F;Q1pFe i95Eh1Zeh9ZVlV5h-CRo,I+I_:Ih 44@3qLi@/] ]'J",l v0X FQ@].JbvPaWkpZLшXS) )`-=hːtY,IWFe6M]343汅ϭ[?I%O2&'|y`slxxכ"//Mr'`-YK\^v(0v ~%-#98`M؞8W/BR;Ġ˿˜?OY"rO剟*=~p)\6Rǭs7|  TP@ht8 8KkFAx6x^l!Ex/ ?=hQ)G2+B\^(Cy "{%P U6NGpxoM4{cham=:P#, 7;;">$hh38'acp+1 bssə2I4k9sܶ`60~31Exى% ~3!':0sǘzF9c=`$P(⽲@.K4ڌlEKFO;6> .@'Ta!jn&<-2ҥMإ;a@2>˭5F 390`0}!x#n%`2[`pԔ[1S)[XqKn`2@̭$Z=[0ULVvQ(ɭv81Gn$e#T){+J HI!s}瘰{m# 5?)Vس$ca{5-?[$x# CP$ RRDJ)MJ)SL=\Sdp 5C%\T`7žn:co{ Ƕa*u{Q(YxB[+E&~"KD ~WbnjĦĦZĦĦ݉MuMuIiHiIi Hi MMMMM{` [[Sq{3 2 6b&ۊ۞!z\S<]-;-@Ddl`/?M?y bfB͇?M b^ ~aGr963nV!` 1/̃9bF/x6K fcA̐N,i0@n[q= Ybƀ- f ȭp9b/ ;g@FNAI6}w:ĻuI#u^xtCF?AÔs?,X&a7%pdL$og@A5ft 3@URT UGQǩFJݥSGw5zO}>4-YZnEz!mL%-잴D]t?ڝ}h?:z YeX!+J<*]X5XĈ")4 @Wߵ~0z838wߡ)D2\ҿ}x3i.|_XnמwkDo6\Mڂpk?}ỾVycS~mÖϽ۶yc7G@z!_(i$PR^ek ŧBi1:a0A:?X?aHv@m3v62CFW* { 4HL!O9ꚖD:T Gjzsu@v´"qqZFS i95 [Doɧ/|ltkT_(}…Y>oiO4ߛ߿a̓maݧyu&dq< JTj?V3}]; -ElRZ`(^:Dn./cܬӻm$ف{TAG"5OkUuZh˳ԛԞ/0q}{(O.'5m䔵rJ޶3BgVYTiĆ_8E"\fkLk|h ʼnѠ`X;`ECGŌKďQq' ѱ1cdLW~Θzc#tTu\%+TLuadcmwR{L~yܢ#Ƽ\_deQsJBګbk;34{WV{1NylY}r+#>ɱh;/rTpVeau$oGe]R|visg\_ֿv($mX|Zd]Ϗ90@iq j+}V;8}GIV`y1vu3 "{ h6K/hⓉb2ڬ<++s`HˈEFHQ7Bˣ2hFL@ŝMVfSSA]ڎ t,t*.4Fᘙ;KS| H,jh: wn9_:OM6bvIYOmM(^zqIۥ QRUw/^'UPdXDKo eG?Y:1rmsJ!ygn1֭W7˖]Xq{>dsJGyilXE2m~w^.S0zayŦ-'vQ5 zzs _^ly*_T910&?͟<7/c#cƱ#v[s6ܡ8$ku/K)"Z|p;lKxe!]ҚFV4svҥT cLfwZϞd/e q:_f'ڜHM)Tǧ.J˚Fɶ|^,!t)*Jg١߻3 ǺJM8q{wKۨX)_X}q%tœo.KKDW{݉e+v3gj#W0qCǃΰ\F;^K j;U}$|n'̱e,8ҧU]S\ݹbgc}]8'+I_lhm71;k;vJxb[0v4K|J呸K$vr,F|III?J0"SJ@m Qg-ͷWɃKiNOL %*ʘemդǻAu֌*?Qڱ?- YtZkzgBHf?eԤo tV6wE l̳Τߓ\v:íU.]reEGb{6~`>M)wOW1sbn R)KUڡ[>WMX?dSK}?E[z)RϭG[XxMY&OWp*Z{Ǝg7TLPig?L>Zz;g۝Krۋ][+IL =_RJb|a2*C^s1PVi==u.I}3pf䅺(͡+oi5T>8Q-n;*k [8Ygi&^~M$WhgPkh6CU7SHK^}y{#Tz$KfUZ{~@ss6-/{m֙CӋYG~;Q(1ccL S%E9܊uoikWioXkyɫ@םU8Y=A)L^7T}qų֞c'G|7tDoǼgj)/w;U[W* j沷dɾcov8xطu6ɔC /fyo_œN>QiOz=N<֘7zlOȕkϮ9zcv#;X{|kϐ3xOɽ #io>Q]Q*yjdžI13n>tYfdѦTDŽZo<3'Lox׭2wݫxcoN(\+2}jBU3 CL73\3͎)nvs½FK&~th1q ?RH] קDh@07}OTpr`MaB((c񓄐>Rŧj>r\^Q8X}5V':Yoٌ {r?nGފ3ͧ-Ucz2ac'lUխz9\#aK{(,z{8'(7tqi^K8 (3}G9U]465\@~ܬfz; ]xsJ\Y4oj[*[mϿ~/~KչeI!.Ļ%Iwaډ eƸ*_m%B!8/)EId:|;ȉ;_"v#->=j(#[]3c;"#,7M5 xKF#A"!`:G0x0}Q_^Ŏ?]FC t7S~5he˻{5>+96F&B=KxckƮӺ2PٛrI WΛhC~I)=8I??HR.}6YKޫlkobRӧ2o?G_~=XCĪסW J[˨]>$RҦO7<w[,Nh3C_EjiKvvܾe#˪ )w <~Q!jӭվ<ر)u#o6Hґ >Hu0vDoA̯W<~:H{Z"X#.&awg%gxsuړͶ,Em~4o{(m<(D[R6԰3ygj-]p;K]Yg~_ >}y˚[w,8sN0聧'ֺT'Zg)3nKmSvt2SESG:_"Mr*O] ;5o˛!Ac*o Oh}eh+n Ŵ$vG OL8=kGX'/z)mS=qa;om* })ouXld~UU}ߍОY}vM endstream endobj 661 0 obj [ 0[ 550] 3[ 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550] 34[ 550] 131[ 550 550 550 550 550 550 550 550 550] 141[ 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550] 314[ 550] 345[ 550 550 550 550] 350[ 550] 359[ 550 550 550 550] 373[ 550 550 550] 383[ 550 550] 387[ 550 550] 391[ 550 550] 395[ 550] 590[ 550 550] 593[ 550] 612[ 550 550] 616[ 550 550 550 550 550 550 550 550 550] 681[ 550] 683[ 550] 688[ 550] 691[ 550 550] ] endobj 662 0 obj [ 550 0 550 550 0 550 550 0 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 0 0 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 0 550 0 550 550 550 550 550 550 550 550 550 0 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550] endobj 663 0 obj [ 550 0 0 550 0 0 0 0 0 0 0 0 0 550 550 550 550 550 550 550 550 550 550 550 0 0 550 0 550 550 550 0 0 550 550 550 550 550 550 550 550 550 0 550 550 550 550 550 550 0 550 550 550 550 550 550 550 550 0 0 550 0 0 550 0 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 550 0 550 550 550 550 550 550 550 550] endobj 664 0 obj <> stream x\ |TչνddL&3! !˄ –;&oe B *R8 .[V"Zھ+R{H]վI|;܈@8 ǍPǜX`4ꮩnS+̱w|_[]ûSR`jO8ˡqQCs kyBխΣ-,rޟ|۾6ihi;9 W~P?wVC['ӱ|\5M0wQY8% V,naE)O*487,~ѵ~~PӼ5le'udE ëv è@۶4ʿ=l'c2]6r wA̤u4C=lǁ<E|/^6 rP{KcRsZdNvCح=餽18Ȟ3r)=l62GA#و Q,X_B FvRY!B8-}A-4iHqN$D.d0~^ʯR^툩c3?BS7`9Ȏ<|C"_I;Nw}k+OMBkzH[?\b~\i+Pe? (SRz7eQċd!ڮOYl6GoO"ސ@j?C?ox6,](E̿,_aX mߒJ{]K~R!qR8ާ,!W?ox ^La 2rfTr0b,ܐ#` :3V^x2a^`ghW]Nys/PH|w8!{>(*X&c8{,'}Vq-HGL C>' CINBwZ_.9[֜,-L@~Ú&dn>Nn1kr˸;==۸mvnw8.H] Dh)ZĒع(XQ%@ Ђ`@0PsV8MQjg->h`#l7Mn[V aa;;`' wK?F࿽yؿaPN:bY R,/dҾܕ# 9i;!PGX pR:Mz[l u:V%1&%Qlcv22Is6f8F.1Ig4OlojWTPBxڴs-"$IU+{7jSRE N咀Ro_/'Gu![t$\a7bg*~,wmHӱQ][Z.g[X2) l9ctoqbg]ZA{vKX\%'t~^2tg #hPqyF`jZF1C T\4qO$ jSZ r=3]sunO ۮŶlCp`ħhFܚ&_m7w]/eqX݀<^Vl|-vkZ3y |s4'w5ּkqˈϱ9s>Ǽs2fhm̘Yې]_ϫfdOuLyf <)ܤڣ$Z&6&{ߪڊr)':SBK%806?W+tsԆ#BnAW c7Op-(-=<8svŻɎDG7et;mncѭnat3-]iH71Q͌6uB|q>⯈Bg{w x,M?"^GGFq *$*+ N ^FGEį/ G<%#E3O!D[N~@ +A3`"a>jb\ӡ c&VjXŜkb pl`-81zWJ[{s}qMuJ]p{ĶSt἟_ ΣMhAud")%e1ބ0=>߻ao)w[8QPN0< =?CI[j$<OQ_~FGC[EEq|i8KM*?qn&5yOPmhS#\`=fY -h"Fn^] 'A-E.dY|Dƒ!6?F2"J2+evkf˕JNe'xo7Fk4i2mк=Z!<>{׼s.+^6x̹=/ϱ\Ƈ9:̹sgp!.B,.scC297&pQzέ̶WuSn2}aq$?[C&: ܽ$d]\e{$X.‰ЉΞ)\)̕B3Tr&[uߴs3&]?iϯVμIr^imʥ%Qs[W,0SS -%&*FiRD)^&O93%/qe廛U".! ώ8nܶ#`Gp oK %UEHBWZ>ȉAy/+gʧPu)JEk#j7E M\2OϩI>Lj;+[oy%$P Ȁݒ8?n"VSGA xohtɫoBH(l=6]\qܰhp2y#8s,OD&^zolYƬ6*>bdK SMB8zvs<ԉE ˑD<H' $C־cEΝ(PE%Y%+x,iCuiЛ^rB=J&ڶ׃!w)w8dFHKdU=z5IDE?p2}=JlO TTf~=n[Qz9''O[qy5HG58OP7;ĻRJ Z-'71\w78NWɔڠ)O- 4LcP' o$?_f%q)<զ%:Gyfk'E?zTfJ=$ўG.ۂQ@j fHxjWDt>ҧ蕄TOqo17[r0o, Rx/k'?{S~Nѳ(8?'I GwlBh4(`= "If >sM~^ϽzN/AF/49 -xȋn?BFUn3>+ږ;E99 ]ev֩_uOW.6~  Gc(}>=|zÍ=DݤUЛ88ԨOljm#vG 5+ ;YPFJf"snO,F^|er*&%fYӸA=rƖS(,?oڮkјP,qk¯cxJcT@L4WU%3}Wkvx}}ij GGD=SjZ鸫n= onIkj3ȽYyIF&㛸a^ienW+X^D=..n Ѡ'W?8QAb訠3YKQ=?.-|a)~ERrVꥠ,zUY7dZk#4lU4,k/mpUT9]%wLj`V9gY3;,Qڔ?a"BWFFgd 'm_Gutm# ޽%0]~,'{>>lcJQM5=^p\5;A:#݅F]vZ%ёHU"D/k}Oyx;wꟘ2}ku*/ S7?dվ@!,~&/|huY{& ;OOx7s(*3DPۜKe$cS{ms=??0Q3IZ^JL JL^CxQ*޼Atǎ -:*}e昈8k'rTχ#n6I# ^x"*I#-Gx S)*: .%S2ikJES\ѳvӃ'N7b5f|a0!pA_"/Stb|!2r@bJ[*guWyËW==,WЌ^+9 DZo 9]=lRZg[˖ʼn^6jt]qP*pWɘs2fޞV˪v­=O/X8xƢkF=|Jˊey! B#`A[yÉn%o*ղG!/]dz鞦?FFv1~kv0Ir F7qR)z|yvqw5*9*f,ȕLd>i4Ox2X, dx`SO_lkt+ n }VNJUv}t7Y*)1h+ aL= v&z=[bO*B55mVsk ƚ>GMYwЖ՗j;rdgsyժU6vB&Kk*nn-eXt󠫤4Y iBcQ~옉n+k.2:C\)"%Wd˳Q# \aڈZX0x$,,F<@Ġ*4?W+^"zK"2AH#212hLŪ[]"VrkZ{FOb#{.OրW)=DouBT:ZWI*(D7z V\ю}%&XEgJк aJCv*'{6$qV-o SCjG>r $. ގax4'+#˖&0<7SmY h$F`.1VD3u! S&3<9#BC=Qas,èQ(҅ QDZ9)CYnȃ-䞢;'*,:W7CLr1$βI?9mM "wbeh]4 $ViQ_d p+5cɤ4DFc&^)R ^:t/o |ExF9w芠Wl3n2c -aҰ^ ^/,YG]s&؛ו.ٕ&f'J^\TϠ7\3wy^k7ai֨?ՙae ki<ĵ HJpJd2GE-W7+ؕhNw6^P-7qe^(O<$7(?uchS{>x{7KPw!xp}L.dܡe E 9:-<=frL*[zs! cڰ~4jE)yM޵߼t0;'}̣`^&ݑ(-4M_1yYm>%)iX͟Z,?nP&Σ'H 蒓blvSg&.!'0bQ i9Yɜɩ* .>Qx-!^Tvk_eu}ξ[2ɾL2Cm d! & }->Z(bUj)mYAk/ɛwfXygHwn{ιrϽ N/! 5q,r 2q'O,dJbQPR(b |[]Js߂TaDo|r$7lQx țjSj ^,ge\]8&!D%JH! 2/z%X"f婰['6M,ltadøi/U<QxW" IY 83wib7 GQƐW|;vΞw勊$/*^@tff=(Qy yJϒ9kuj }M"DbEgUh|hJBSo,@BEdJ4@XSeNp~^Qǰ.39:Y̗HL !wpQ+g/j'-mBL2m*B}>2]Ͽ 8k 3ZXZ,<s4? *&蟸 j1 UO֤^ qʊ?|Fmό޾ k/Oݫ;Ob47Lt0`\guJV2kH6t&YLĝn"Um7'/#YW\^_A0e 7HeN| ŧc)dr*z.pRWڟulJG7қK z㳖Z(a>%z% >А=t7b1z]j- \ IfS {L4x&JJxK#StR @:e<{p8 _ 'up%ӷLchpΗ^U.ow!|ĖRS(TqIEKKUjeꜣK=ؐ*GH]PkvD35anLV;0VTTv%,DgwԩuzF!$9 3}d(;ĉV:݋Të+"0ݐ<$߸I-\ȃk'Tu-^סPNIhAxcPUt4F/Fx)()n:TYC{c^-RU??@m@o&3(|qe@WuM K?L/}§?:jPYX*iLK$ 4LV* Fi~1{}С KD9NޠP*"qGWjlW,3&iy^sz+4a)1ٳ66-dv/6TYـO-Z Wi >2/+*-0Zfx uVkFR0FQ_sRODv54K0~tɱɌ=0sKL̋~j}*_dYz5o,0xP hX}U]'i6֣!'\+?/r!ߚ(<kD˃1BˬVǡʬ*A{' 1 AׇH@bVk._k#[%-P"- f)Ѡ՘4/r$7i$:Dvo.3ZEe+cf%%U*ahM$[ pќ@jenkBXA9xc<G*ws'U@rѓz IFsrz2Jj^WWr<+MpjQQ ~BQw8qhBuSBA*7*E̼*+*m<՘<-i'~yV]ǻ [~6?sS>sC2§v ;= ylÃO=07V.CqG#Fj IILd^,/\$(5j+Aׁꃴ@zv*rov<S{({AWy^GI prW(\ l(ſx?(3 ȅc Ɯ C ig &kJ۝o}-I`r`1yVؒ24sjL/M&!bOIf8Ɠlq|[J~g^civ2JV 1FJx7Htg^fl fsc0wMb֠a0ՊH_RNVi1D̦a }' sh"=9L5V PȒe‘3Bp Q?rzOԳ_q0LjO3VyNFq< h<<(02r杛7‚!wgv@H&mxRޓah`rZzY0e(hPKZ4v^ITj.IS67Q&Ib c |sdMxSI"I'3t\~ S;+}xp~xc?Z>3 ?>pt^"lƝqplNNGj,hD¹t/9Гca<֡ A7^(qX]QJbq3=?qEНb<} k J9ļ|w"JA){a6E9k Q1Yu# #i /fwg%s49v&F/\l@ǒ=<ߌ/ cOЧ:,T%$Q@au:[aą =T49gB?6̷~>D/z Y7cd޿|g`EKj׼eElH;ZZv 7w?W?&E|q5ieu# p!6)@"9w^Tfe܆,S9Vv:tF3W D3hB |7- Pm'}(2'"uWnόX=XuJ8wWg/(Tx#RXqG cH #0Ng[a]YVdq ǖ96ꕨo}bu%pm4˳G8)G[F;$쎙`2.s,^SM(с;'(^9=!uVO## 1DC/nR(t"u wj!etn놟\۶5K5Z%UZ_=/ajBfLI% 拯g8zr.;Ф/nޡui'Utd[ȩ@cwԄSg8j9!}lE =+d揠ӺhzmrF#9P$r6l;F]Z6N^]>? o Ed`{,ܝZRhfF%Ӌ,- T2;3_S=~U3U+֭ GD00[||#~ 8xNg%}d7 wJsw[S"̡kiD\Qjxa39C.Q䰺H?{%QSnz`Թ3qg_/=2¿P3aYpAOO~ugUΪi͉K lXytF M?~dO@(Nd.F($Ď8v>m 9j_^!uoӍ!Φ~V{w[sfE,-=īJ_dyswLV׺×P3?R_\z!VY^Uv%M]X2uż_SU=Ϟb; Nó-0%$2V@aوSѸ 4#. fW?8[IXr*dWo3ORC#D7ݣnFQyWb1ʬ}f`ĈX`0X2Cx!n.$9n(p313z<}v=i]I֜Y}xϗSHoSﻸu6uP 5+a>2-Bu¶Q?_eǂܐſcn 9gwF=2ǣs-|цB&J#k׵QҞ˯n;~myUMIo^<_e֕lH/c .w}A֝ıEYԸ_3OXj#aP<=MBZM`)~f_%GJln3r ܒTl98]Pe&ы-C-fsh9NZ`6Zn:CǂR~v6ˡ!=IsOM'Wnm)Z05)6LN*LpWoU6exd^y_czLբB[PM+=uM0*kF ؀҉X͞tҷ 0-gǒL3O:@9e\ۍ,qld-iH…ҞW9UNdUAN=ۜ'\'>E϶+W}"Xqp|/ȼrY;dHu%}b*Â!W5oBˋ.90'LlͶ+r^IQaWaŒiIU+d29.;RF( (e 0_%(KNۣY㠾;S.G{M`ak /N]ʝB/XHjU2-1x Ӡg5p][{.]+හ.j6~zd0. } ?)A1O<69 v?s?v6+"@˧GYH;]r[,m;Բ Zj jĖ~Z%w"|frpBKr(wY8uT:ߌ}?~z빚3l(-hTyM /]m/8NDp-Bzů!_ b(-l3%U&=AL\XxM:|tҤ &=A8rG:uբ. DNn7OF39 H M|x_XӋoB&DEUۊӢVb/_zb~:H &xb)9QW-?3܆7:s7mhz.DžOT=kֲٌ z&%kukfr*ɪeq1-$ڌ,\P69+3T m>a(גTcbye FmGTNdcmGL^+YYr3^IÂ^QdH qy?)#-X=nރrr5xv)ƸguT ?%9 9&sYà!|V˘Yq-Ej;b2Z\_oH)fۥK@ N O=Y_55`#qfwƶG$;\#)wgRGi%yEUM {An{EfN *d(Ǧ5h%9TciTp,K3/+Џ)>a(WvZ|[ nYE@EA) S/=Ѥ_H^*m]Ҏ ߳ (u(Py$eYW) ! 6X> [xt =J퓶-x1n2(}#Sp#+ah1J%'y4(8G =Ck@}!ɉc4O5Aql_KݺmeFQ\/o/oCk^[_9#cd P  ZL r50eEď 1"s"+4)Hh9!rGueK ׬c9my5,H/cْ8mSc+Y4%l^aɵޒ,[nVb)UVK8c$I@}D [&pe–$5祯nV[m|JtԔ@4'lnJ-QE?(>ob ,:rT&!9AHiP%!6|0Y7]υj^2P*֪:խ@eBUJY#Z7+0(p%⃃)?V$*+KRNu^;ڎFm_M).Oc[tyI,~q?~?_,ˆ$[[rea(!) %IJ(&/RPJ))I$&R5Ĺks$|,k[Gqނ<>ZoI-ˌ*IϘ[*Vjm(e\nFԤpmZnEvuS~4'U\80X ]M<54hu!c}hSI%99JȘfΞ<^*"}"*fCiQ Kj߼_ixS78yΝQ"`tU*lI`FC߄pn`N_)MM0ȱ፯}qKSn\f>1ϰd as|?[IƯ SmHd`3 \|Z%*L!`d hp% ~12O~ClӌdLې-YjR`)G<؟`jg8IQef PQ:}6yӊm׮32z~+~?X HNɴ0C6]YtZָX|Z#Fw4+| #?2"D nRgYVQ>kj%O=[ uW0shn&1ٲM(,,gےĊ3*Y}LbUyLffc]T(T JP'rq#ڟwN1%{<8)ppOߘ2VXl=%b+ҲM"?XR2Wz?ToqyfU]9K<r&ȜtVFWwy<`тUF`:-JLs%-e5/ݪ$2Q] %=npTz8˜N´Ԇp1.]7m]kظOOI?K ׷Xʮ[TX: /9,Ԑ4'#z&+,~uePVC`![ fCzNٵQT](9)G G]krֱe[iLq칅T.i, h7 v2k^EN8[,<8>10. N/*79fMfRS؇_ԥ#Ѱ?1RnVj-?K"l_ɋóTH*4LY[fӇ6g= =Ӌkj+VOMI)2eĪS1S财ڟ\b)1Kb#㦗XpQ?Ų[繓`w"qtq11Q##aƆHȲF/8IWh(eGgӷ -\ƅnR$mYel8d(o}[J=Yb̦ުך ӕ {${A!CJbBB\nPq CbҧL!n$+;1V*' qL|7hPLW=#.gfFTNnr"eT|Čٚa{ ]b^^^BiR\V]8[#q2SSg@fQ40}Ѹ >tfEtI4Ib7ƵP x۸q ͧ)x] vT=T7-k6=e[]m}Vj|K*ˎkoͭ-n.5ۗ,kk KNgTSu6Lфu”aV-v-ANHNvoْ'Ojr|9jk~j]Z馇D -k)ɯIgH/ aTj|ϛ:M2n&{?2a "z.Zr4DTGh"4:uG8Yt)Ds{|c LW~rMyx]/f>dď_)7`\H~/$3+`e$T"Aj[eP13jʂIoBO DBG V4S3m2Gd"J6qT7&UMR==Ȣ%Ylj: N7Op6؛Gӟ*3Ǿ^YRY=_5lӱa9|oȗ ^$TƎh%N-oZM VJܢE!SN;g(1kܦ :`gT\NsbZe:.fJIsYEca|&aW<,+ajZz*!کSSS#" |"=bv;䑸Cj*)ˮ,V9Y%^a;貢tVLܙؤly oKaqf_ڰWHkUʁot[`}~[k ӅpM9M$譍8W~xR<%>P6̤,?gN϶*g?;\TQ]Qku}U~צN[M#4 (Jr,滆8DԸu\\5ޞ|3<$UU|k@~"oBLK)r=ܞ&g~At%yǚùFR2=ڨs*YzZ?NI/lbvYf(Ҭ™"T"k4سԽTEŠM-vRz n9N493~,O &~(,xvNT+#k3]aUjZ^6gQ)M͙32f5u] -as DPS˽e 7nl\cN|e¥ T!韟F?cvSWo9Ǽ0~*D(&.&:..ZJ>k0棣TVW? ( E@2JuLz|lF\`|SUgp<[,㸈l4>aӰI10 kafP)lẆ3MTn՟ê*'egTh>6k1*(/עG>1fOT|XP~UMT}K)SPL*'JR\J2_VBٞxu[R"RAU4G*~_Ԋ;Xvg$d,؝q5sY,mP֓X9`֏Nf"bo if9.nX6e3{Wg XKX|Qa̾_&]Ujs^~ޝu3<=e=~T?:v3_s/r\|V# .*zʿIxAh)Q&͒wexu&Aюt7"(pE9b4O҄s2-DL+HB'JrGiS0"*sdZ-XCcA5$O[LHz H(4CTqfB戨}Vy=$h. hMdvTU$N&a$RW>+ ȴWELHyd=Kg,ђ%ZҳDKzhI-Y%=Kg,ђ%ZҳDKzhIB(j$EG'.h%pf."+-#pn_+g^A9ǃc?a,_$Cx-@YPh2hwq%#~|yz^"̈'}PJ{ZzPtkt^Ԇ$9=F=PYN xP.rж8$B٩A^vnb xyB<( A<>JuuÕ˅R5׀rD?+C:)JYoȧZV! =v&"Twt Qeh pv!,2h}rҪq->ls8~Ë]nZ'jC6tNV$-k_nzSг\ReݨUl9p>nC%iƵD QCJF7\EY7& yџܨ>2ǖ<eRO VUWed>d^9J7 Kԧ+$Ry%}mK-}M>'t%[Rك?Cvy xWt%F5! ɽNhA%|8kD)wU(җ,G2Y ^3eq-{;Ԯـ]'yW/9xOe`j 5h}6K@Iw o@hq twD5Z. K>f%ϗ@6@+1n~>A~(LʣPIۏ jHӠ,&,xFݨ@Hp._4 b̈́}>#Hv?3^(={MK3E|K~_ Ztݕ>? {[ɑDK Z=/Uʰ^_/g]: Ɯ{}jZސݸmʇ9 _V/&|>0"j~N,.,%6zA_O@|~WsDgYo`P:w={|~qh-z߷xnJw{r[z~ ]Aq4E\]] rt?(VE`&*OwW/yVE__X3^Оzߵ |n`tQPC{pPJ/aO?L &/{ݾUݞ>[']b{г z*@T>È~W{0(ͩ7Tr: unF8+vnX{ܮo Z.ë0Rޡ~78[uwn_ @ 2˙->Plg5tQFKa Ք%󭠧Q.PRX!/7N`-.]#tP L^K c0?dUbfW}؂Ų`R6ٺ@<0 wW8I/{ؕoPaۼ>[p@ ߐ7 =oq 5 >8 TZ*?<ֽ,@Zܕ=~ گ7~}4@mfzNx,sq 0}Uwҵt?@.~/y>s<V{2+oJѨTA=]CFGʼ$#(w?Uz|Ƀ.IRj9 +i>{&׬DA5w h> !v+s=PbH$I",0L5Zhcz.3yxYo,qX8/ _e_|} 7o`ANMM߲pOspgrg_@rwX%e|`_XWgVՀ|-\~.`_8 `<ȃ%|+|;w.>?sT*#} U*JS#UѪhXZY/-&ST) W5pPAhu4Il!lj9A5>^A\/bly"%%,ϔ(вW, #34(<,RL68׫ PswA}^ߗC=( cr= ̤9ceWdǫxd;uVy'' Iu7}2}`R//@=8Srx$PoACTnVIuNsoA}bYPkzyBMP!g5 }$uR_~_r>u8td;o i 4uz#1%j [JOoӾe^ΆW, O@K۱}'Kяzq2xnGzⓈ{#DgQ{O6Cо >qJ$JwR;D!.4Ɩc|3SĖsrWگ6}7_m`Oõ$i';T6ԲEgoіItj٢G΢fA#g+D?࿸yg1{.m=L:;YD0307IC@J(+Z/6.!7 V#;˦`W$fC9l6FKfUvy)[$3m=pMbi3F<''Dd+vg:onq^GIWLr<%whf[j-|4sᒭgu^7e 8P95Q0]7mqMp?C(E-;Tsmk $ VMv'@F0ڻ۟`l2+a_tyhy}KhطQ y)R/}/hCnڟNi?ߡ!ܑToAD mi@nAv;D~/u,X8_C}zGy}^umÄtycBZqS^ %"߼- QX ~Tܱ"]Ӷrgygۜ'`iѻp_[^kk1ټǾbLے/mXCv6G<жcp}Mͧ vh9ݶ Zڞ|mocyDW󅶃tw ێQ 6FǾ;"[=!F{v|qlAGL}Ea_@ic#6B-eA{-s/a K3+VIS'T)?RQJ$JAOj)q0ϔ) sj!&^G;O#._BUjU>>~t?%xU]#o4.4BH6!$!$!ĐlF|0 ""ň D@@DEDH!"R#"ETH)"*E"*!s;bgΞ93sܹwwuh3#bO4m;1$~"VT׆ׇ7S>>>Hl$1J1#ii)")E:G*"=##}#D###c#""3כD,8 *Wv*F)O:*ll:Ցݑ}#TXw,,e6Ez/#f5u7N<.i-AZiOxF<+.S ֊u"*R%}:X\F+IQ ]$-9qH mv#[¶lK\m{maq@nl7&vqigJ'vG#J̄n'QFq&9b!Q |,0Բ ?ց!)𱈠&Dlh :"v$-`Z/xrO k Ŵg?"`"hmev́ψ[Ь N#N>o)1y#7W w \VM{33wkGտﲿ]cU?K/%ڷ]߷}<8ܙ_}zcя+mϕgP;<#2tnP,~nFwh&-vR:.Z\h_cxCO-:[2o/" ;b"-./ >)|%+?)H֕`a=l/ k3q,t?;)#oEHVDm0LQF{4P)rnG(rZU/ʂ.Sy(" z"o_;_R4ZR4#.N1bF> Ib2~ 1L?ML1[4/uMh쟓>دWP-^XxY7otk)> v$7,p¿x@pwN)oΥv:[K.q~+5Ӿ<%gs4Pnۖ%n[v)vsCGD;ڹUSQ&L1tUOң(~vᖹmSa9-,qKBaVh~mO̽>4n ۟3Y/ (@|r;Tߕd *;aCc4lIS3ǒ=?ÿT.Qܿd3,-fٿoo126Sٿ۟E}???3n} h D}Th񱨵wlokTnW^9<Á@(1](s:ΦZ&>TxGBO Dm/:\YD@o@_o!݁$jaZ`&Ixt{XH8X He{,-:?zҚ l ˅BqFB5wڲF4jnQ8 !m win`uls[]4XBC`iWUK{WO_p``@p-7vp ΧjK ^ ӂǨm54z8%=R哥 wHKF7}B*Bɡt;w21r)5xw  u*IK){e :z*:TE8CS ׄQXZZZZZZO4G>^Ж\JϞ-gOSI9BVL - [Yfua^a^[-lncn:J Knk`t ^6'R2Ck4^L$$e*.l1C<,t5N-u+xUȂ͔I6u4Ogx6gx6gx6߈oV8~R)~/ յ‡_ZɺoY_Z_Z{{](aPkBx)Sk|;P SD+wLϜ2qQ1'S)0rkL:Ϥ (.r ISHqISEq?@|b:߉X/M-(wz-)Q QHbgsO7žogpG88igRccř,8:2+ꥫ)t}kwJ:-$LwڥN{!73BGgBPn|̅OTY?4YܫgQ>Yz0yNI\ FY)GpPs;8Vǣd,i}%L?އ\̣g8tnUحJ.iUp]k R)?X@mtgkG*DWzF<.58dэ[/4۾2z%Gkfp64>/o[Ko,e3<_LӬ}RZ3eg^XXqQ=B.ٕU $r3נtPཌ7XЪ^A&ݸ;X_ݰ/]N>5.ʝDQp7p Љq tfi/P&l1Ķ-kϻ 9VAN{/C[`]`-JNF`KI6ù!w>N MCn`=Zuc$^Tf3<tgo@o|n06QrEߎ `1vZQ%'X{Zπo#9{9l` ѠrQ V!ЃPr~t"zǔ|})qCg<\QX̱fbQZXWdO cɞL[=X}B\JX}kQc@W5(9/BOaLՇm;3{\8~0_Y|u־OzdNl'x<8Q,ĺX2SGIk-Vz y ̾)bpݦ&\;|>XOFO}|>1 E\wL|>!˜uW;@g w)2DߣC޼Yzc٨3' CM~ | !b6s }~|}=z!4RuYaѽ|J^<ߐMq3Kihc7//G|3G NhV+vv--VaհM=TNe BNta obtA7Ly? r{B6%CN3 δSngewZp*Ϝ(Ec\pFD@԰zQcF'!lJ8؍hd^!`%hVIWjr hO> |  SN ?.aLTN'?Ur%?dߛ<E 9( ߹̎'|S;J3nu^q_0*iJ|/`t zȭxJ ]Ŵ Cџºarb?Z^}m=bWsn=&f-aO;-ªhF` Z^p[]HB{䵦}ЏbiުNeyF01l(ϵ8 >ZU2J2,0ci7۸_ y]HqHM{U*4RCBAp;'QZZ;[ENl-*O@ҭe.U;CWn5Sr+Ki؟qOn2a0 h)fgt%O1}dJ ^~6ɃPօ~0mA1K yz;c6i\2 }3z.CDGy :XXVMXE5kLցN.VLn?ӿDoCqei3HCmCX`Q vګ]ў@W] ->'(38\Rz f#~v1-;A?@X0|= O [X2jʯ(VQ. 9h) muH>f#XQSXO\ =i-¶b6qnoLYS,<@ט]e2l5 =/v`t5,g,$Ev~?9#\^g4L2-p}}A:0ߪ|ۍ8 <+]'"j |1mS(nCp{Vܮ,}' _U?ӈ=^=lIT3ʹ7mC ɛA?n~}|nL;q~KзGnz=4{O)| > 𷁳o;qvK Q `8zۃscl toct'{:lq=~~B4X'q>DM  g?p8#|?^։n>ǹQ9'n=~b+QWrc߫Q{߫]HXU/6I tDS9IIFNjBH+b\@Q%JqrH>ԩW2ה<ϔliJ2%4Z-i(qHA?S u4$#H9Wઘ1mXi[[BXeP̦`D=? ~-1cc~cq qÏq1Nc i Ic ?)c ?M8 ~q:^kugq31΄,1q6qs1n?q.?-Ǹc?qk1n?mǸq!q1c8?q c|w1K8 ?1.KǸ~/Nc|9w+Ǹ _ ?]nc\?Wqw1Apz,Yx ƈIS({Ɖ%b ֈ(g#)m{)<(, v!v}&~sv}~>]oostT<*gj|^/K7rX+++5rxEū xMRz+UKRPrE*U⤊mG\JUuJޔڨ6J6Mң6V[U[VmjQvv2zzY[Xkk2zz]6ްސF[[2zz[6`A&[Y֟e/W27B['uRfhLfҖYګҧu :AD("[&W-uK)6] dk]djWUv:C@Y;Hwe.եa~]d@rԝt'ҝugy]+d{]wtC^{Ʝ{ɋuz}ıKxeK8'N; 2Pvr9Nc8) Dvq:M99i&9Np8mU b cʫc6=b6f }uEs^~Sd|By<.,_3̯-(g䬝Գ鹅vD2ݓCN1S 1G2AW9AlnNܖޫ클{ ҫ=vQ"DZUH{PZAn@[{#ҫ}v})nH+7#{ ށvr";Ujݽ?r'Dxwa!yWPaF3 7a43hQF#F2h1F#cF7`42hdd)F#L5{'4r/4rߏ4FhdL43hha9F35g4 njF7o4hWF# F05yy(4EF#O,6yhdRgFI̧NO^Nou8E3ȹM$83DsF$;8 YK<i H"H}M.;h u 6t:N6A͜l:HuL7 CNsprP "*TTr$$I&PTV%$̀DD]s wݳsϹ*twWWwW c7Pb2*Bok,)07k =d~ˣ=`5~@3P*FQb2 Q2עFz ~G$ފ"?/Z@BBRandnB֤V%%KTSJGa@ґ4J#F(SQ4HiD҈2J#F(SOiEiDJ#F(L4MiDB&}d|u !A,FI٦4Cٕ %bd)g\Ļe'c%BʂNdOIAB% QJbR)Y*A!U% i2Te~Q@SCe14 - p@"D84g#;Aj4c&gEO Ad{eA1:Fy 8 s#,@C#ޡቈm b"fW HA~H~@f&5RҤQhSrdPrpGI%;A SB)P8#FaG8 ;L%)JQ2d*CaGv)^(-N;Q9!/vA]]ݠzg KNez7%5}>_7Ƈ `B8&Ia  DL1C3&aTlf`6 ǜ0scb3< ^?C!e3$R Cg 2p2- 3gAgh #z~x&^w!fG Obk}_&G݋cP3|Tͷ}CGJ`)^?t֏!c@wyPH??FM|{KIfr"Y&gBm;~M+LqGY.4ټ)@IbjrA & VL8ZcrdeĜ s7Xѐᇆ ?`NBi01 uļwNqmۣA M 1"N4 8M!i>T[K!$4s1^QeȠ@"GCmbb8;'2|Y?G2<2B-OVYǒH/NPx[P 颒˝99AB^Ĉ` ˆ@%u {47(* = Ϥ%Ci'" ˰ D/"oP[~8wVIbE8_g2t%%QhAGˠȝ*bfg///0N'uyIG(AO݂MY^m:T8ff ]UCn7L.#|9OckJhM < RR3 )d!Ub|-bL~siCLJj0Wyo߾uZAţsD6ֵzQog,y1foUzyACFDjmza)ӹ:wvإΣHzGL.pNϠ A`8AG?!brW5{N;ZiX"xbA Cf6t(S`)vϙ6KŬh0qSޠ3q4˳mO4*/Z-Ϲ#_=*L2'o n0ʨQr Mw@໸B"SӖgs. ИhĿ>Sm.mW۱wTݾ_q-ޜqLmD+H VY3ᓵo~usSޚm-L+^VhMT7{٬wK+.&N\!8&q(x FϦfHv#+b=D8 K&$4m'57.<1 {MT-r\I.Iu٫'u5,d*/YK$5+a Sdw'TmpZg /yG\׶#vNg0+uG7;·M_(-XW5Q<:aAOLGwktUWMl}y+-/svzHUd]\m͜~cׁSwbq-fn'Z;x#^̝Ř"ikIo) y*M͌s|2s}qmG?&'wJK[ɄaRhThDDh~աOxNĒ 2W'"2wg36"lC&4AK`TT.9J6Sv*և$fNzz#) 'jΖ钃@<(/Eei|{}۰C"ڣ{'n;|1I(v6Pt㙙~lvث",uJ QyXf|Xx6өm¬{u/TohԿjcsR.ϻ薰Ծ}j{ .xzusMUM *rVjk5Bi2z!%!-qCFf?'-pB%&!ف&+Lw:F KP2WhX1$L؆@uC&u 2I$m<@)fhlhlojela2r׊tQ?鄳_ $_B{E+t3fg߳p2|g8,wmezmETKkb%xFأzvJ70eO\zZ]xMmO3o 6 O/sҦ US˺ygҴڇ(pٰ~-gNW;džJ-˞Dm_vƙխfl!k}[Kn ny&<a.W|j?;wB#fmW>l'~GSկհIَpExp+q~Ơ?OhS}Ool0z˒jJ = fi/wbJ4> u|1>6_YafnuK/]Yu56`|b@A}.Gs%WN$1N3.bs9epq'?Xh]~Vf ➵V^M?zaRӊ>Ze;2n<(~v,kΉE_Zm:g{ܽ5=&ID&pay4KXc#nv}=tZ<}G/+va%clz%י<#uXц7yE8^:2NjIU $F_waR!M,[?$ FCg]VGe cK 'bl rB{+b}@9JNHd HNP. DTB"D?^91^17,v5|׊6۹V^S#=NԌns7c`KsVG4)Vd,|w^.a3f7VR17Υ\ݝOgW}m09d G*r-XϰغõN.CfE5YƇ[/TAO#ؾg\bgFZ#'Uj6u[./}~^\}2N8KiƮ©hj(hsdL#.v2e1= …X$~ =lA48fG&E}HT{|UܚW3Q:n&sj*9M쓻^He|R8BjLLլ2 OYFMdZ]𨑔Qs7'υ̻ydF ߹bf<Z}= 4AT endstream endobj 665 0 obj <> stream xeMn0>"RJ,Cj8 n_3iXc{30DUPkhfр8z҄T*»[C"onA_n EAw_j/ܑJJj<7'chLʒJ|sk^hu-}]i=, # iV?%-) hyUOЉ֢:8qCJS$E$HYPn. 7>۠,˃:YԡήgA巡(yPW8Patyg/ۄx(Ԓ=6cv1)獟$No435_?p= endstream endobj 666 0 obj <> stream x @u?{`G@@RDy[h~(c <*r Dla?(AUIFW)4ZA B@蕠'UN2 Gا6^S:LFɆ@DUJA@maQXCE7UA`47֡V&fn}#j j~߽On7j(ͿPݠo7?U-߿\WGثPK#RTٙ{Ymg٫Y[:-G]w&['̯1=ǟϠ4?i&e__S@sv4X~4n>owA3h~.à9`!̉W jafL]A 0_W 4f A3h͠43 ՃϲwRg×~<Ó~oύ !03!~~ƾ~A3h͠4fЀW$-N\ j@%] 8!R FC p%l`eiBv QQ&EUDUEFmn WؗWoN襓X a 49UL*LAN?6LS-T2JLuw Se_c=.Y4aHo#@ﭾMs?&+@GUrk{&r`3P)4:6Mc -:q Iٿхv_aw\V  3Q`ϫ@ Ђn0  a`+CN(*V¯ n fwp [6O[59}w]GaH5gLp:wmMuUeEI'/-).*,wIy9*eDaqCCb!f1Pj*B /r{8W,-Mvg:4 pxT|f#R )QH?$3s!7yi,tY}:.~|-hq80:e{xܖ"O!ת8 f钇CNzs6a|# +i@ȳE MފJwQᨓݠ@N˫*xauxG &I hr65Ls{"񚓼 Bo•XʳÝE$'&6?Uƚ L*5[^fB{a ~/˺v fŻMv;̴T<ܧ'q:xWy?Z+fړc?v8aVڭ Fj׵557xx3T)fo3jRO?7^)򴜕{uݶ+FB/7;%45mw^U{i&rr,Yc5v`xo/\0awVޣv7A_0ߝZ؂R%6GO/2֫ Dh(4/PhV_@j?\N?cY%E7x/Z^uNCR׍ܿ*roGI6 8l}}*Kd{,}sBu OO8}ƪ FyYK[IqKC{-\䙛pojqVsmrѪlW`P<V'[[*&wO~]Ps. ܕ;r[xJUhm{%Bv d7MvL}n)Mݸŵ꺹-:> 9ǁWpke*s=瑻qT0)Mn1"O[vu9pMCջ$\e˃% Pqձp%A{֟(𱈑o+]QK♺cRgv;Ե9剉@Cej7ЊQ#NjرXR\fz%Kg{y#0A|>*cuuTxٶ6yXM鏀^yYg }'SU+pYᅖSR70v|_.}5|$W5y[{scI;`ۋZvNMJ95Pvnipj/M`?ѕ+\Mjj$ Ձ:gaþWkZa%^=*1f>5A²&WmpM75E _-j t5x݆zUuJW+ߝ^X\%W/sx}Ev?"\E]!_gWWa1D.tKkJ&6aDs\&\*b%ϭS/NIe+j_jk_fj*"SbYarAm~Vj.m c~.wbY%abt](n&ٝ1Ba<-&QB(&E' | c 1B6a4!IEI ˆ4D2a8!HH #'aAbф(Bd[(A'X B!B&H0 =AG45AEP d^C&|G8Mp $k W/ _>'|FE >"|H8m1G G!Ÿ o"I8Lxp:O^!L8Hx"! t&£v#= mVP[DA %pnN];  l#A{Vm-[ ~GLDpmᅈ6n$'@XGh!p=a5:ªlĵd[fXAXNp5*•+K, ~EX@h&\Fp a>bEy9لY&B#a&-! L'\HFJ'܄ SFD5PIh 팕&&"&%!& B1PH(h3 .fEr c9lhB!00AH'R )dpB!@F'b C N`' QHA'X B!B&H0 =Af,Fh "( HR/ˇAuCF}:u5+ԗ/P>C}B}﨏Q>D u}{c#wQ ϨQoDF:z'kW 1^FDzysgQϠ:QOB=0b@=PQPQFFBZxQD=u^QFD݅ځ6QGm (6ԭ[PCmFmB݌ [FoP)17ƬGݠQ!JFvD R}drjqLdJ`yGC6vMlb]`6/x9dP\>#\zX6[y{9ũs `:ް0LAA+:to7Y"Td`ྦQ8SBrcʍ3{ C'F2f 1ůO^11( qczWS2Zk&{&x5Sl7_zj->Ou2vc]+ jfF^&x|[T M/@Tk-\tII/laҢ$tX7x(iEat~A=Hp!"4]Rw󱰐Ƞ@hpx$Y,ߴGx`6ck` )xކRaa][ݛw7MeU)TOr5~aMP ٽ `KAqq7E6D_(A}P0.RX5{p\ о ]oHo;a[QoDxMbpp?<h؞A q܁<콲C61#rDZ?:0 Yx^%8/+~гg۟k_:OYi 7-?_ G(?)|_WpBqPcrO)uvJC T`Y8ڲY\aka9: 7cn6 nl/jv`_+Zal^}Xg^x<-ہտSnOr˜>TV~v–:,<"߇z@nclվm}W?;0grp >L` t4m{ aD9iTfd&f{t,a,٘ŲxVƲ4=:,agdVɪf]V$"d/ z|U MXa" 4@҃N `Rڄ{OUʢ=7+&%`0m?8~ɤP?.B<-YBDMeHM3Pm]qz^2gS^6Rz9;PWZ*3;̲B S33G!82ң!9NvEx(1gP?~Kp_5/9:>,lX=,,,>Ǖ.RLx,kZAj&䏈`]ZܞaqQ&ST4#(3jR떒t?vR JLQ RjQ bHHJeΈԕnb)փtv2?RmgZCVF`y~6 >"gJA $2SkD>+:>J ]bBߕ38c],*RBrgaثh14D ڜ>NQFơm%y%4- w 16VtˍYVmiN5kR&{yqOlnŷ3*#';zTiBǷT~*~LXXJ'oBvg {ϐ{ vt(r{ƁutόuUh efAl s1!xw׿iR#'NNݒwu\?1|#9zW  ÉaC t݋F(Gw%DZҩWBޗTh$9^XjyB:e_'e*&qnj|Tlo9 m\sanʷz8~ˤ%TGph8ڴ[)GAcFf.-ǹ#tD/|x u.|(2.lxշEߦWJKZ*ÂQ1L=*vDPa7wKj@< ̀ )[R߉W>ƹ=J 2 anCӟg,2>rF҆XxE~sTj'%N$.X?+*/(vx5 ΅k߾ή[-5uiq{,CmF!Şa5;On D|L?ݗU%̿1}k\G{:$|b!@ҥ[z?ףNR|UJ4 OdO =*m=_ c7;'?:Di|u@@E͙G}JϡNh@XQ񉭾Yeg]QK_|Qk_:JKb?PN@(޷ZR-$7Ky,3[ #4:T-9}Ϧ BpEZlꞍ=5Xbby0߫ K Kξ8Rb!g.N poMvȖ;#@֛Ǐ:` *0*h7* J-(Jwe*茼ڙޙnN]>t?;=yբSEg#ؒcmܲ*Kfe-e6>W{wǢֿv-t1p yZ<*dV .Jɋ-h>RLrƛ ,fo{Q6;*"[ W,XF_7'?l},)ZY.`%mLYwG+| hl}U}OH&J =&i]3C} ҷk:yS7A?wݲSlW|+-,pW~b4-.Yk9Ӱ0|ޏ²Z`,  첪T-ѡZVt:=IR_pD 됼7"<#ʣ9.^-,|x i0/$[6{uAyR+~/vy_iT\-kj 8aG><CnF=" c!4~8.+}̉{%kWVO'VVźs".\pj[wsҭ_"C9TW9SLj3V7j51) )S.'r%od;)P'-IJ72i/zF> fs/mJNŌFP?H0iԁ{ޏ;FhЋʀUYv)gD̖N}'w]Brx5>$f-.bʔ;F37ݒpnqoV/|$^t_t^Q%^XGzVԋv50b࣬ @I7F'z˵4Qty:_(S7R6:x89nٳ=zf.IM!j/ $Q\Z7l3n=tޑG@h8;癊Kcɾϼn\V`(M5/"Bl,6]H1z[oD>tƙ C+-'+FHr.Rox%C~+3DEfc5*{qMɋ+.w갴Ub΂Ol7%3(C-#^N7ܚtT\ҔSzؓĬq"T|c }^ޫ-m!v&ij{Iހz/p:=5UJ鯣9Q;\'tY7ͩaFz/X]EϙQ0T0#RY\ɔՏY<4W7[B7Ns>/`&&1I4+`€ld$VoD6w*=x@=9-5K;/tÁk2mt/O4?^RRm5W>sPSW̐U_T5b?MqS>6ͫ0n8P?UV;M;f:,XQ駃=.:DJfj&TuoX7)DequIc /%~q4l؉%yyXٸQ;$ 8G!Yĸ"+}^)A$? ,KPF L Ş ?N9bQ«[/9gOX/W8 f D<2W>7\Sʭˉ{ ƨI.JAF|2V"z$kNXv3=;<2NNzr:xAY2׿La4/,3m-8{-ޔ$=`K{22p} {/UQ% 7cBTÒ6cXF~85 fi9MPWe8zXQLS6a+^]zA?FypGWR|4gM]==ԅÇg/˅7czk* kexŗx\}VL#-c.T?bbl_T!X~U̠iAQqicor'WaǒE3r#“ƾNQ\0g& :I0sZk_֞_+/&hK 1H, hF=e"} /p&UX(c@-(;q4߿N$$N8zMݝ/ҡgXDA&bEod_m8'sΒ&OEDe39ЙK~Q2{g-ɠqƒ_>r ]#4.AaAs&ᒙR""YN׮m")0Hd1MSz]`$-K`鸁F#jzfdBNxU +.ж ޵(#瞲Uw}d;jk26U^W$|vko;@Kݖ_=E3ypw,_#q #Kī iOJrJCMퟘT"fOE}!I_lfk~ Ok+D쳓Zv7=:Qw#$ueL,|'5qeiMLb7+*g'z_k%!m&eղݓbl0Vԗ5{THA}@f8ghZ03)Hm@-d5c-J[whjE6Xá-~K O@s/DSڗiGG,Eٔs@n aӡL]&e3]~!v7/JF bQL Q_ &QO"T@_Ol|jyG7%wL_(I߂3>}!>u֭Ӽ8o􇐿x|ꖮIui-Z2{q.A~"'V:Z9V#5\ҨmhnN>>!%^aSՊӵT,1?y# !g\|aKj|&5_N+U 02!Z$".; >/o`y"qWשׁ[2'Ѻ5D9{I\ac6wPJ+Q'P)GS1Q&)/F2f\ 0d+UlCcY 2KCkҩX%_ug~@Ϗ PJ\π^Ng);4w*iGOPʝmquPջ~M} :M{dEX]œp?)ًuF]^K2 w9Y2 B?eC8:LiLdRM7"lto%%]޽S47?jǐ?sO=> /+Fx"+D?hWJjljpZF?hB2hᰛMml OR c \ijmcFN2፭$*i|[f/<~mnceq\Z0d[dLށ18V)t㣣Gd!J)%I%iEO"1{E'#ϿA$7cy'AxtuG;U0@'3Q3dly%GG7gXѲKR B /ҍꄰ .R/S㱫V̾}'j_Zo$0uf7FjRkqgY҉4U#tRY5YgPmTfD(3 O|-zEg X1P)|g_Ò4du8z9Q 3?q*L̥6ʣ.el /dFtw]Pj!őb۫X2$ FSRKJ&d@jŐiS](,B)3a]2UO(a''%<c.{YRKqX˟wwL2(SR[|B/d-S}0s\^"yI!#;HH#:שn e}CIt 3ހ8Ma8"Hyb2T /Xմ;b̬C|cUM;GԽ IެyMcO1Vh3>jC!p\ 0ʀ?yvONOˋ'.P jX~O˯̍ɴE ~V# tsFTj2i:ITM$v j; 1##bGq$+1\9 kGd_C*+65/6kTtyQޯUT6Ч}`=F,;`h״Pf"Y$MVj/yϔ@˥w@B+TfP"T EBǂ¨y0vD\NTZQg19dL4mkW\܄sǑRE^@nTғkM\Q,0zK3n镈4)jL ;)Ӂ3^"^ѢD7@*=:@I?XajV$iTؒwzKne9{2*r\9>?8-JD፣S$Ww'dK?> CP8= Fhm0XSt'P@b9J (躈Wm CMGZ~L)^MmnwTon{<Ƹhep<~7n~zz/?p{;#cZVރV7?VQŠ'P!^L\h{̙7.(P ^i⍨f:&Kz^Ih=z2f Z-򽯾Jݏ͂d(p ɨ $Xf s林Bx5ێ+kEr@r&f܃:H{ e< Ύ6,*G˨%n22ʽyFo Zh=hU?Rk,xrFHRe Zޏ ɢkwB7rJ~ H.¿ߎžwƽ';B}"ogm6{ p>Ǻ(m.֪5p5$<{)[&|A,T&P42|q|沤V05ܲݱuӇ ]fuҟ/\}^뽛65YD[.EGyǜQt:4iT&C;lDv=jm/_JhTj>%#y^HO ku¢{ KtcAiz f wjE$ir#>9i[[ۺvlm]ZqE뮎pgOwZ`e4#cRi¼G< .֤t>}C!Eabһ#] {hڔ#~NaG&Z( G/QT_YY(q/q%c[H̄6%/LI*"^Bihx; "{7l-ϭ)M]n'VwdfYgyL>`,j0)[}zݲ).GUʆ;U-5KP͔SѲvC<'(eqd3 B s v+u?u5pDatax`Ծ{qdn`m:x]C`.0C,Գhq)F(J1XÂ2%\_мdcuvUعMItnWG~fU$$x{wdν3yvb@[)mS #{ 14W!rj>eU_5no̐j{d7]1甩S\ߓr{Ϥ硚,ъRWI[[֔O1ʬQn.&XO9푞[*L/-Klg+N9ˏ>Pr k0qiۛ|[PBi2yoRN=P}>?7v Cto[&X KVB&V<;Iԗ 5mz~MϮ̞r]Qϭ}j=++|Un(t8b ÍoI*{j)m R3cƔ+XO, Ae1̐ TF2FO}?=,ܽ QV+1(b RWPz!K;W ƶI>m8QR[TO7w_aM4hvrgrfEagSC(dNQ =\.(dY ,Y4 7Χc;ShY蜅Cr?nAWŀIrhԟ׼$Ql'6%U͚D*ʫM:j8BI1V{13ӬyNӮpLf.9t#>T| ǐc©9 𐣣 j|ʫˢA C=|!s$g1"\ИG7>z Mp3ԶqmG-:Krǖ;Ba"nPeEjcJZFI;\0ЯQy•Ѷ2/1hP*JnbYsF3`˥P? 78Imt30*!>ʱTbxU;lSq=!7XiڃwՖv3+o%\K'z2t_ƍ;^h0N"58>Ns5qK&n]$8s8/0I .ӊŃ "N NW|"NW>@"NWg&W43P-rxuuu3v[ۻBgv7 ITt0X}dh 2"N-xFvZ!QgANJ'Ҹ1ulΏ"iQ%Tl5H"};:gl.JIYV⎤G@ 9%"xPC̸M&3mO<%ni;A=ys-uo{ʐXR\.xwm\7,'cfJXTA 9 6q6$tTTDdCꭩ;l2-k[8FEZJw"o)Hm;s/Cʗ/ք~G!*0B!4JKu:8&p8q5fDwfh΢X-a.S4j9Z?a6uյeNTbfce@)$'нA0@N6EB(@2d<2C=~SbnCj7%,1a 8ƠTJ"deR26<-iQQqݳ#㧬\ľ ;$ˑBa&%RGHY ~1F=.00p??Ef%Fag@"Y9mh\ u Btp;kZ(|B;WɔJ X@;8%T"D rNkI,F!Ld2($D"f>R3Y7{%f(x {p#0E)=(T`wbT"&EP~:d&scar]9{լ(+{-o[+f` NHNg!‘+WX(Md%s6w9[f⚕Үjx*)'͟藚%ΠղmZčr6O0~};-JÛy"aJoGГzBvBvW3݃rdjP6lsdmҲ^J"E^bZiQʨg]֝T.W3 :sE3 ٌ nc~C,+kg?РʞE#.sDudl47er3XPjʼn FVvvibip{Ꮎ[dY"㭿ysfԭqǸ[~IGC"*d*culʼqK6HrBgך]V&v D')aZb %?IeK!rW;ejNv Hl6AM4lSؕ >y;]lXs]ڝz!U*G._ߠLW.kaT9*8@:7)9nZNv$-91#1GNc?՞HGV|yxX&@D"8EPˠ Ej@iurF"ѳSS|"%JChэBg$.ƛF,K%݄/>tTHL,Io߯TRL ^ʩh Ôr'HQKY)gz[_%>=<<*P120wA`KS, &I-:?NMݹ⏗ݲ'~Et'ӊ\(>xɠݙ1'k4FN{{TũU42*Z2Y فXr$?JUVή?Kk4tQBnO޸-Mۦґy%U;knlݷpj_LݞxCh*lQ}\GK82Q{%H(A|A~ ;U#RNN6 p"P/:q@؋-to>*{fw6,lɴ,Ժ'l_陛!W:#+\jQ @N#j1 H$ 7(LH$ȪHnBt^a&[ԺI|vpџY㎌=vgwaqyp皖f(9/2cdV@k/ӌܐ=L@'U*b1K8V2JZ7&QLDFIe>Q 酬D0KQ|szWSio칫+'c]ԕ9/RZVmZ* mnm]?8g2Z/]tTPbdQSPY2kϲD>>Gmz҇ Re{X(nj!İő_/BHK5'n+Xd`"l-+Et9TC!ys.]{|^)u8sW ՗@Cc"S/ya% KSFBtR)^J&ik- 95kL\\^QG׏ {*sΡeLohvԛ^cPQ9 ƘQ*V Sw Z$XF)DZH] KB\Raz=\ԛΟo=? c>XG-!Pp.gY~@(y)]׫װ`@& (XXV"1>Ež!%+Y,TWM4ư)k ?ځ*32 (\R߃_U>j̼Dqn(1o_Elm^`]JAj/7TMsIǬC[v0c}#{^x0ħiN4Mm3<9 ^ѐ;V5w. XފLȇ5$h 2j1tz@Lȵh4?a-yTGĶI&o~Yr7\k#1͸+\:ֵp&rN@<+EEu]saDDEBt "C`fM`0CM6zl4kYkbR>rSkSkY^>jS굨:g4$n5k9gf6ﵑ#ex•^K' ά;ª#'!/=|RlL.X>>ɫ^];+ﯜ!6aaԆ'ۆm7xx\^6iE=[mՓ<[(9sLnL|馦) j!^=MuyFt_iy =G|י~uNKs # 7MqyCv$1㝰67aʑ?s!iq"mߜR? CZۆFKx1[alM\˭8/5nܛB:tr@;⛧ك~𨀼LlaDaFЬ.;AĤVb eaˍ͡$ůRÚKvNM)7v.]<4225\i\q4 6+~VOJJ|DS#H{ =1^G9gV40sąISW$В25gάY}7*|b~{)eFXYamjYSmmTm3Ƨ⯏KHB !<3zM kEspJEh' Gb< `C\3J•4{Q=bȋHsb˔goW3>Լ1szހn*$h$IG|hU|BBAq@i(IߒGA|H;K89"]MD#FOկ_o2|𵄉 [~J#dI¨isFeߟR)/N: Kј1o}T7;Ӹ6;3La0zMk Q󠟥%2ҦoJ=wso}ܣR*=B_~~ iZ&Ob1ϸ5JLσ6?c чrFߤI&==駙#3:2?}L~broN·v=GoRUZ֔*}ww쥠] ML-Dkrhi^v,{t=GwbM3gMXtװXܫ2KUy-KU>fek7f3^檼eu||OdG 9T^`:Uk؄/v oQ8֙pBulLbʏ`In׋ƊgSTހSĭ*L#@AY;+bgW^+vVx Y;+bgW^+v~Y>+gYu4 vBjY.cUn kzяˁMhzpHmZ }8Q#l-ve KPq9^Ir2$/-3-! m"Ԧ4j+?5ߎ׍ô 5Y?mFQf9dF΍å>n9hƥHwE+d RkhC6jVґc /&D~s*GZG-@>:Hԣ)fC>o:McUՓ&Ԭ ICvl"KSDѹx;I% +hv-P"2x#2LV P# qSM$u=~w$t'7|MQY0ѯZMـ"[~_B4Z~j5 _C\?eOƭU,6vXo0V' e-|Wb$U%njReDsJռ\]5\vU=}1T+_>5*Z5KclۨFKhSƋPr b;@mgj?O(5W3- Xi/Xo"1xZBg#jVmjh;mHQtZ4u5䋈1=T n'B׈PȲhSԜddVJ_IphQ.Tj<5GwvHXZS [F);)DyIgeX5lPU|Dj'j!%>ֳ~e͆VWy&WX4nryN{;4>E{y%ofNeM5U$x IJ6Us[LDhhs\5Hywי*vbh} p[~jTc*D{XbhM6| ,!|Vb̟>b,om :BP=EZC\@Xݺ%awM BPal0ZMPظol á%a_[[kp\AtH?lll 7.k T>c[(h5` h76bHң5Fcoa_߸)Ғc .C&cdUE1r]Z#cI(1F?܎/@5,h ;:p 6q snچa`ShEcSkG{ B+pglw. BH 7 gP #F+#/h}Mjo3B2eVkM B0]c |Xe ! 5!l )4v4~tBf/ 3˚jp c a_co7B*,Ne3j|=؁{:Z|~EOԀC/npGB4i4˂\А"ذʸ^10$Vm#76c,f#@l< V7GOO㧇ǷB.iaoij^6yu rD|?- FܲeY)$F"+VEyr[V5F(ZԦo5[v2U>#<~(r1;| {re]iYceXXĐsbvoA#Zacͬ)F?<4\T0Qs h)Ө,dWUY%obT,` >(t)z ,Ҿ KڿgioЇy"[:WϏ{Ş A,Hja@BgUp <"<4BP~0\a.y<E|P QQ-]|P !8;'2 |P%Wૄ*B5[_'ԁ\,!GtKo0AW34ohn?(F $xo@]C߸qw3}t4:A'u?Fo瀟~sחɖ_d_J m~W.~O?C^>>~~AA! l99 <9<9 <9 5kkS$l4%K20N#{R"0IJST`(M> =̔2)Ti*p4 'ΐf Y28K|Dz8G'."P*`a)!Ҥr 1&UH* X#:_+^guNjuZ zhaֺDfKaֺd]20ELaɈA/!ACB^Ͽ*81"gO qU8RKY~ 2yFY߲hW"2Miee 3VWYid3|+UN8-K`|7au§'ExTҶ GA"L$L% ̡g||\^JjM .L;fEsE׺kuߢ]U(Ǵ:x_rSe嘿Ip0#"E{3q"X*ƸǜFS짌94Gq DDBY qjwr+!{rc/qIx*;zDGqY\"T ˱:rM՟<&QPƢ+ˠ2(7sܮ*P,\ӑ3kәbT͌a(9\y[0{k Ө_vDCY0r Jǖ_6v+Vu^YQ6lEفeʾQ|LyP;Sj9uA-go-SmrǪq.5Aʤc^/KB=mY*.PV// ԟV_,9ZY߇._OQj6n!NkCCa{ $/(ZjwSG[j(1&﫿ivU!O:UOv_ ZCS) ;*-uU$vNp4&QTDK"0,YtW_uʛ{){c{vk;9mO&< .S1rC}{oM[=4?Lsٮ%=x}=R\M'Iq a\q'rd$BSj7V#+:V#8T_QvȊkDy;5:ϖ5ѽqYi5Fxd:.TZ{q>=ltSMЫ+髉pլ&bĵ:oJiW:5o ͟XDj7)UZJQ=`RÜI5nxpŢ\GslDIDF{ɤI3`49CrY5ov^ʺޚwl>ϧ6o37|B ,j.(KsMzm1q9rV9sVk7l"/riw_E3n~]r VŮ|;x7Nmp0Wj3 io8_mPq[~7Y;_7% ;Z7 o6Pݹ6]]vw-RWmwPmY ϗjj#q{s݅uלӵ{s]"I==.c'{ʴgɻgP{{,Y,UM;a֥xqSǯ-7&3 -`J:E$U]K}_ل:܉e!_e׭k%2:䨲uUۣE+] ˒E);xU9]97ob ,{}fk/٫&vkP?mmm﴿jӾ~~~ NO/@1+@ũhlTDx:U'rų3>vqD hx1"aųt~=%Y^f6u^泣'"`X?gϮ2'r A*YY%YJ/Z._g{{nҰzWg ##cڱڱlm@kbOh-Z r5>mn7gK.eQάww054=4z} Tw 2 qBh̪1P[tdH1+L(*+AًrBV]afP2a\Z֢mwkEw"vdaM;LpNa;j=/P>z~imcDmAK(8Yd26` @ ]DS,#h4(h4 (3{}6ϲq96;{MܯVW'^++/01d0%Rq`4eLMM%&mZhmZlj6Ls  (d:YJ!S/XqFbIS ƽC"%K:NW KJDaJS ei#ݦML[LML80o(*]50$2 ].eQR0.93VZRkstf#e2 יGl> y̗2h9 fo`:-EJRc]%ZƂ-`:ſ uJA pIޒeIriu4++Ke&|=lA|2gzL]|~ vA0EKTh MP-,Qci]4i']8ylFd[[a-fڊlJ[Jjl-"mjZ:۳mm[U8E{gg-O&˄3YJ~??h;8?3r00P]2(4̭˭ww4?Ҝ,uu%UUKn,,!˽a !MCDD" "`d@bD@@Dd% ""*" tPqpA䡣$y|2af'=U]˩S;}fe.1O,ᴺZJ+IZnBfӒ?oGǛփ[埭xEi<-|GI! q&4F!B; (tG'~/bx~s<Ƅ S(L3fxEܿ˪ū)S:ʹ{'P8T-L=(pZ ?ǞPBjq~'SH8路eSH | ) p=aFR(96{)L2 0ߴg  j7嬠86QxZFa#);Px2`ag3w%L._? 'SA Y݉~a :;.3s)RJ[)l_OT @sv CJS8pM.*%tVVW̱19t][~ulc'Iy88|s?6XG)w>i'Ɂ}ra<ا0'Y",>`}GUiU6ҞhKVTu:^'+u3EtչIE1YƢkOQ'e OV\T A Y&Щ!BCUHa0 )|y)3Ma,dxFt"B`80>_FtmΟ qcTC!OirwǥkF' SwH-d#u?w[ n?Wd7 eлUέȿ Vk5ڙcE oW`]W)<}ȿ!/#gzz^ۤ [Fis)6k"r'µs#̠O2RCnA**r40hC(<W6XEJ;WAYE#3MD@lvmpNqGԈ6f/ 6 I[=ua(~Zô ʝhs= yZl)? έUƮHc 1x/?atᣦ=3TOeT/`Bz=pj f#dԪ[z pox5R VRQ۸Su'Lg#u@>cjb!s΀3r+:gc:{@_:9a'?:mnVP rf(/kC,ׁm; E>`֖ww+X4Č8 JN@}Qs~ȭEȳ~|M=@g۰.E`C;s;y"504y w81AO}Wr[av=9o5ZNO&{}aN骪 Us3 X+l2Z_sv g}_O&8+t6fdcB剜aF6/BQ:]Yl^ӕ \b}rѝjNsЬGx-fsi1^F3%xZXHc:x3sC\YUqH_ɫkmhek}RYxG#xBzxl. }V8 xv;OPj \ 9{5rmnkbuk,@/>4X%5!7&B Hi( I6G  ؀8Ցw ~6A+`]?UC7z5ƹ"Hf`}M>nԦhװB'm@ZmD]`]_ 5hp^/c*= .p'i+l˫_ݗW:|K~ u'9Fgxp>ǹPC"U% I `88?ӏWtI.X(eA9SFrO'C@߫> ĝ*>|G`p1i !Zq +[<񼯩:O J:DWw7C9+F:W@g=a8wi٫%p{tx/`|WUJ. +xn'8-ɬl<=i?+㮼 ܒ@gV^̴CKVQvQYSGd( |js=رV{[ @ hk5Q6>JYEU=E/]e}@19硜\fOm֐7T/p"]k qg"4-9J!`o {YAE>Q֛|ljT퀘 |BX 59_]|wBVqNy=pC, y,Tc#a7I`tI~X%ΗŪ 8;NF T Jt:ʱ:aЖ/'1O5_9T&V32MdA%f1Uh')h45f)ev2(\B0MT"0.}"4pʁCH:|::ik"_IFk &?.nGLC;Cu!zF j8eG'x-i$JciSk̷ųEV¶WVJ{=J(Bɩ!vmYQ8 ~#Y3u)D~xxF NPp/jY9X@ߊh^ BѪAhu*,/z$j`-Ye'3+PfYQH uB(>o}GS~  s 𗡿C\}?$|r[Lz`LsG!<+pu+JX,NQPK&F䠗^ׄFՄ.w0 yv͟G s}̬C2D A\CAOtC<Ɩ0Uv>8 4ʯA+/C-bmρ$ ̈a'`  w yY'@X d%ZHQDZL1둺.H~%|&G4!>Y:-X8qusiEPQs?E^n.X'( ~) m9x"U`!l/4uua@c}♚St0 xU䟅<F\a]kZb=eνCWI,w08Yo3PS 1@\gCφpn>;xMHi!-d|wp[qGX]1j` e_vhU{X BgXETYj%Tn K+v!ǀxU+b+}*|= UjyUM*~D!f"(:lE_ab($ۥ$)r\]UqI b?_MEsWD=DE-mbyX]kaD"LX"NDٌ4)ڊ+ĥZ׊.]To2[Zuͺx*-RDKцYty'!b8NSL tf#%Z,qR\&^ٓb(z0,<`O`?ࠡCo)K-F <<4lL-Gc3ʂj きi֣ 9N<`1n)CÁc%)iYyEeՅu-cIzzp'p/ 0c g/1j`kcq@? al vfڃÀ%I2,<"2j:6F6Nn,#1 i¶`%>`-`vN<0l l ;nX# 08xqEca"x$`)/P\x,Ƿym4~h>~#/5~/i,8co0[e5vUռQզ?qD,cLLLBt%IWԉRVSo#3qZJd2UflIMVr,3弐.\3\/ <+B iPub_F(=w(CqTv(5x[(.5S1:(%fw̑Yzb͠BzL|&=^cL\:?(;~R_)Ni!~26v2~󽡑$vNcy!3{Z%fa)Yh+aCE/* }WZ?*V(ٝ$'%C|__=+j j{Wpo Wp_=ݏ?*.1)b:S&Ϥb(J9@L8$_|#Nx?|x?|!_%x?aTΕ#r|F,7b|N>'v$]K%.n[>HE*l9RDRYRuRDR]I'WJTTj%-[ZU{Q骃mCҧ2zzQFX/Y/HYa5WWe-uuYzzCFY{=2g1[[2:nu//d]++YZַq_2Q&q~eUeUI?Ўvd2'H)隺lkڲʦ/StNʹ_eNɲn4T7-tN-uNtKR52]g [2Sg,Zde9;v(/ѝt';β:_!/=uOQֽ序#;]^ɞe.zg\ls=Wya^{2ߋ"U^Mj˫h/ZbX˫՗^Syٲ/&}ᲿY7Z"{V'^,,|__mf5A/e]ԓzRMO=,K-Z[]کeN'K}td{snnyՈ=绽)F5}}ww!wPG;q{- w|7 Fވ;q;|wnn3vH bL<,z+uU5Id'z^mTťTV;Q_-VK,5[Q5O=櫇~@-TpK"G:(|uATƫ 6uθV]kʐ͸6Ƹra\%rP^^op0x#D owf{sEuMP**1J\$H;hrmH["Bo:a{Hm>)).mnjPŜ<%|5|>E\>a:k鵤^ xczqKeQ"np%пrFP^.@Oԃ55fG!?']勄sPtODLҜItJQ.6g)vK'}G8Av Z2F֓/&3d;Avy#r8Y:sSȾ͒"L&U{AyXO"L%mM"*YZRY+B!_YC˚>a-IaY[6 20F&R9~ e3F2lND6-V2S8([v6:=u5ouW7±X(_3%v α;#̷il{۴ yV cx{}zGĦpp6]mN;ng(W ZNmh'Zwo:us=4haAS46IkC8.2[fzrr|JѸmHDX$X@?OO"ٮo 4;M4//\;W43vOH3fvOSL='Ks/V*{D:IdD&ZD55_m//E;#$}|DН}  p1BX^ p TW)!݃rɿ|~?ٿ0VY4}iA-C# !oؐI^>2RTyL3%fH hFDL!oD߄4=lO:if>#ckH$IZ&w/,Ӗ(ՂhI$=Ǹa`L1 Diԏ1 mCzccc1mF#Ych9֛i1 VlY%bYiV[ȚLE=8`,QZI8+*" sdGG!d$Y)IJ}d$&II]dH=[J9 d$Y IGMdQ$Ǚ&l$KkȎ(5+k EvC#bH,$+!FHuhYz}zFF=s>cOvdFЏ&ЏЏG3G*9#  ~C?2j,jWN9ō*OR^_P:lhdb^^ްXW7_ JkhOGꚺɺnSun`gv:[;.:OOn[Il¼p/ҫXg\_/\^*/.t͗\CW\w>/բZf/u.yI~]\1? ~rz࠸VW5^ _t/=_T~u/5=տ<}.;J Rh0*Xf',uZ"V6@>J`c7a8[ot|ei[%ki8+ӂ1V&QB@tK>#ͮ)1/OOYNjTGKJ;}99k'>ʵpUU>aRpƨ: {9i//+xQ4_$3kٓfYTzc6 K)nY+#ru3?oX/DȶO;.־mpC)9DXz9'MWlϴT 3H[yi؛+or=<@/7v^Pf̕qdsaUMQZ4V8ʌW՟F3*ݾӝFH|O*PJ0%?kc !a0 0(%!eC@]nC*ɘmm\\Q6{Qc|ϟF Qܺ*J>25xt!thC@ggVKgz"8շZ ~5pY_ɶ4Zm~ S#Kioi7vV[2I'XpzhȊ8lg[t#gU~fi!%Kٺ!´G5бcu rbʫV7iB0FY?^ֈWE/ *ꆣH4qW |+F( jG|& `څ$%'42bTDD! oǮeexB/5k'JdZv BK)x!Fa,\Up6 }e6 ViiXGt4~VS-{+Rq\0^3>X#^̷5Iq3v{T- A(A2'%|MZe'j\ut1=jq^2t߭) xϱai*+9pj#ߵ53jxE`VUń@ꌋeb +!45+[ȰF圂'p9$r"0ЌHQ4LŊb$#;ia_-Jvѳgab355G'LKduNTǦ'ˋ5򻟣ݱT҈)NO\E[53(C}gZzA\#ab _kMO:zmIYA/FYN1G I&&d6hctuXFCe^0`W# JN `ƭPVCh++UUTe*{3q×@غy mP\FBf`r  YMֹ RFl6~4V: X{x3x}ij[UHdrg (º}f(K d^Փ0Ԃz߲ \v~?mbtd9eoL6Q ܯnXMj` Ϻ'Eܫ"$+p`@)Htm/hl2G vFD8 GزJ@av< hX@34&iPQY=w {,a~EPQ\<1f+d|Fi(dTD}]XH,wBV℮%ti,vn-c=I.Vуng]2zsᥢJ>xŐeĥΞ>v%mLv s i%Ys:S,O\UF&7?QYS8iwt߾8`‘s \4#;4m3dTSQ$fњ.ӘSEHuW$P0e|>gLii]: oh͈s1%J*1X5>>h^Ij pM .&.?"Zs{ v^Bv3!/o1fQ<1haxba0<8V?w,ڐBnp` H#?B/D@ !3o2F; zl';LWr,;HZĘd0n#({LChW=e[dtX') ­ǚ+ĢJNw&L8 F;ɛ@"auW_@T}%5 !@AV _*VڄխfN$#DE}p7=NA"SaeREV(u}.i=as%G:g;`y+_/GՑ]m}6WKb4a^9}XogͲ],<cel)<+IM‚I[lNWw)X9- 6x"mI!K`I1v #yD{zP<=i7R5h 0zgiC_-L%#&o(PoKTPZ`DcK:&[F =ΏY;)PC M_BAn ׯ'v d =AoINFڻY$veDz5>1> stream x]J0yY^pU R&0M}{'\&|)do݀@q;@bnIi}͸4E4E\3pq_# [J߸ e0m$mz عs| 0.z\uȖfTjyj8/y4}|m̒)uM)B2oV endstream endobj 670 0 obj <> stream x| |E3}@84z$iZrU(G(MM-@@,+®``UE]X<׺mM) ?/ygyfy  f֌o5@]{š2@>Fgxd3y/Srb?2]NЬE6[`FWSsO}.o2z\*-|/8wߋבQe=DHZ-F1—; iC|Bx?]1~!ovɨ+yI4ϷW4io@al,[*@q=]N? W/]0j+9ţ<ܻZ>;++@ϼJF2zTzDl~'ORPA9od/(gW^|r3/DRIsjN >Rd{4ߪ^QH)0;, XR} Rn+IPw`BpɞC?=THʏ{߃ 1XGA$b4Bh8 q ɐR 10HF)jH #`H8 Ԉa'`$aBh1 À4ıĒ1 3̂ l0#hl< '@.b AXP y%8& NR( &3ES Jr8 &!V@)b%LF)`:0q&!΂r0 "D20f · `b  q\ .]P#.y|eRB#6fCRF542D+\h/͈_[D']` W hB2l hb;\;īx58a\ZqWq xVIX mC;:a 7pFq\nkoUV?ě:-p=- ou6X{؀6?&;FnB6#n-=;p/܌xlAnA|nE|n;1|"?"F<>qlG ;>Q 1q  3<! > ߅`'!x< 33<; WX~twete`[ ]]C20)''Dg^0Ȁ %CgW"j35q)vvN ;;BsOuu>~3վMuVF%TjNqj."at%>NU6Su CbX< bqXlYb1S,f4()bQ*%b XbA.}180?y1?~1߁v̛0_لy9zX^G,J(bQ,J'PV1oc>c> ̏bއy7yf^bXbXlr7+7ߨTn+77*7[)7/UnSnUQ(pU*YWŪUpJPT @F}ϘAXO/ɵӈ/NKg l7O{jBߨʺ:HRUxF"P"S~NI[ku3kL[7TwU7֏0K$do?*Uw^LX&pԧ^”I]>(_ (̴+r{͍FˎڋR^m^Nr_s__͔){_}RDťxmR)kUޮ|<<RPlk65k{z(|M/iBRIExՑxh!W{}(6^cw-Ns .oW-ᚹ[0"qOrr'P>OGUt+]a8߅~MM-]?/;)=yy@>/!_)(#KޥdVW$(&)++))Ide^JFiW)w*O*P=Vf sgN|y.wBq+"0J!4ղa  |xxdCtxU'zW$ړTv(_7˭\R.Hv#.Ùxxn 8[T(\kGd.~l_%_IơPIn ir|w/>7 W?mY-"{܍R~3]OWlLѠϏĥk4x^Aȏ\Jv~)|{yr@A LB:\&%) |\Ȃ5+؛'חe4H6*#IK"ǤO(A-xu7M[X(;@DUUr\| f;>)cIa~^`%9!۔‚ 4eb6-_MϷ-/qq5|y[ŗFFSB*G(MJN152*'?"K/_ɚ_2¹EwG蹕VsY¯\V:22B[V8."b,a >!& Xல)nQaD~Eh'j6rn?WO[7 Oeu+օkW%FN(|X2&/} %VD(bM+W  RJФ.O5R ?vQ:Π'ʱcfL@kRSOJIIV*iHUD//"xHc!{֦QLJ}7V'W]LF8wb #wܶmbCdTl߼ʕ3gaڸy[ 搹L A7-)Ϳ]55.%9bܳJ fذj%ϗOPuAhׂ~iWg] W.qV\-r'@zo2^7>[/CdzlV!/BDzJAaqɤRDM,֤O2J1RtE%# rƍϚT:YGDx+{StloNNtn0wM\(C׎NK%6 b DQouH3ݒLyB)rLOPN{^|xϋ1o:u 79,&e-UK4?%VGjS{~Ww̺w=ybG&5ݸ=^A>~}"Mϓ8IBv=Ȉk∗x`$Fⓒepr.$5bZ֣8yY$ \]I "c#J&A 9ED q,.jD4 MIh0!?05x[]_to$Vaa+w~ݳ[lwnj$ۧ^C>´E+& &不.R*MM0d:=vǕTVk֠O$(4qJ_9$}~s)\*XWP֣Th;H UxOP@8^T)o=p8w<7"hZhvq'IJrnnuW}R̀#ʿ<#(C>!Ow\\׮:_)+T6cB΁RTA-P˂h)I+ N!JXH*HT*lb=;zx~.qSzRUUR@jT :1IPH,FER]iKu%+ 2ZՃR=I[z-éz3^V jIǧ>A4j6V>#yBavz^v9Fva ,b]hKl&3ft`gma1 Bf:-`t m4[llPRg}X1 QQuCdscNpQf6 LN'[(wXR5^#x[Z,Eneq-6"n 䢒llmqەN-F J'=AFG6c뵺-M\ngl9[=(@<llT'F;;ȋqBup P~HBYh굸OkiMMYD0&e=F9ڈYUd TTӝ-4[:F6!m457[Jf춵aixBɍxr9+הMn²oFZnFʔ6 lh9&%IGuo7T\aC06Aksh~iv*48P/MEY=ekD:LdemNhy+Ǝ$4٩ $!]cyTU.*g[܊D1Acmۇ"ny.Q:P\n>B`rwL8@Gr*#g>L=%^6n-aw'eGڐ^;[3fP:C#pg`b3A8ǫks&lws# PFņ5F PX.&bY u)b{ )RI7qd;E)͌`<hj1ڙ8Ύ:Y؝K ;%xƉ-U-g$ibT>Zo$Zі6fifa@6Y]!zbFF+/`iJd푤=t\ɓ}Q9T&& hfֶGCgHAҒr?'.ƥY R0*H)Z``dQ9̣LڀD]\ =Ed#+'O⥏$el~QǻLRQE/@cĴnvblFqXiK3rJ{JJA݌Tjy6x3󋷗P`z$z]l|@l)W3ٽ,i?lb-E󄨱 S`fژGֽ il(}:5h\8*'gU3V;8`F^dg]qM٘L$yv)kjr2ǼUyzcN4Qߒ^=l< y>[ҶQMO =bZOKKX 4Ih {Zϰ^v""qohaك$󲽏>ݚ~n RXDsJ^7'vf6=-gշ< =Xyz/!>Ezҳ:`ǚ~qfni% l镠Y'm`}O=N*Ʒwܙk27J+,=yknWwg)ѯNogƠsG@bdj {栳^ߓ*p볺F)"Z"rm#hvH4Үd}_ij`mHq|ي8Kzc&`ųY#yO'&v6jamn5BuFT-yM·)n}3J'Z膉@OZ5 K9ўrvgmAQÚXW snia1gmy/ Du`,*t LlqH D٤Xs7_tD5C\v ?:WzMkd6rwxt'qPM=OYbNsN|OjcXzXSuͅO,AwFv A<(>~ad.`~2+@THMEߕ0+(Pרa\w:(k)#SȳynFExȚ"v볃ZF5j(e [K b&K\nJ|B7]uLcM 99;xp\Cn9q̌2ܣQ""[ZnH'UB x!T]C>6+"*[ FGnb'(Z^a^M"OVOHZpc @\?*%JoOг4%@o J Jk]TcH'G/m5&G0a5dlj:TFq~塓!iV!rאpn !K{+#Sij1Omޟ~z)jWn:A1f?[,=t#Q۷ԂfN/]ku黷7(-4+D}8GOjr!jD-yeń[Ъ;7FƧ]l=T3c/&n_gemiW2Q+nxӆnߌm×e?|{w<@naNć-~Wvohsl/'[8OP0br%!L}~L^O֥J:MWnN?e32LW`ЗӶѲb} ;&h+RQT,RG")x>6йo{(!02O 78ǐSƪW?}]{rᆎYZ0ygE:k'TK7'|![cuP;s֐tzjbaw۠Eνr]xG;N֓juSgp_H8ꫬSo;nCj`/L9d(մoH.Mb=VpxJ}Y WhzAPR Q@5gqA&80ыsfyGӜ8-iقpyרiD?8ezxɗ3KyS$E@W5ztu՛.QQAڭ=y;}mmsDrKA OK0R#vtzϺfs֏_/b| q+ `WAl rYLUhZ̿Hnq!k~S534g]Q^nSsZ`1E.![ıJ:|0XiZ0.Ԕ8r4rݜ񣺱F0!Zg A*\;6eX uVޡd_>!:.3:4u}ΞZmd8_b-/Xňza!``Tr@vs, tK34 p.n.$zAWP)P<rG*`۴~d)OSl#xy:2Ɵgݔ#wD6s{3rC|PԈ)$,oauÙˁOD;̏]BV 5ӿpj",OH=eq)xOhwM 3Mk ?9cHhWZU'7)^(Y'$XOȨ8+OՇ6U`y᢮sIkMj't.J@jN=4X>? 2lp.2_A * )QZDi2V{bIabv]0m ߡ~X45c[^n`iMI&&ghJ d^OJGԟV5dn_}tb^yaeP WO_z7βFӅ&8ikxzP-W~ƈiِ'NH .6tY5-YkalƷ7I׏仛A#mZZFλ岋PEQ}kMRNCrO%.Pjqed.>LJ>}\b;Zy2;)6VM#OF&tS7 B~BOA7PWOqKp6")Eҏz$@(I+=.?<2ߥ¢h20^(ʒ؍EٙG V~\GCq37y"q)1y'PZ.#ͳ>@#=0l/,s Z=&ۜ3鳍벱;i'K/#כk\ˉ {JutZtrVP%ɱoF}X9`iLw8;gEf3pM凛 N"7zL: f \/|zOG\p*+;X4~ZU""n3~JPr`կN*R'6?JL4nT-c]7e铫>ʲ*3Hzk;x!y.,sK|miZcNBLC0p#Gd^"N~G"./wuq^}gND%KݹXԮZH ;zɨ^KxfHhR5EViz i׆L̙E֛(:Ah= ׏dNjZG.fXj9ostD.dFRlM5KCHSg!041`Um8N`5RuL&-'6mb7ݚIRa[/XK{ՎG&͢ HkFh4imtyȂD4/qkH0>zpd'*[_}ؔCemhah8%OO5LK*2eVc&+e'Orrr0dn =vȎb(Ao~>Οy>-Psk= 'XO:n-O juY!,(^/{=f9>K*&$B_ Eu-,av|qzXhZwߺ3̠S|ԶZ[ҞXlL\*APԟ endstream endobj 671 0 obj [ 0[ 500] 198[ 979] ] endobj 672 0 obj <<81531FFF439CA34A92C326F43369189B>] /Filter/FlateDecode/Length 2104>> stream x%wxU93w&4z @( : J/"JK#%Ho"J_Ux],t).*H Yfίqq+*r?). ]#IġoI\ e.HE )P"4='~&áҢ+mVB۰8 Y@;fdž):g <釺?=C=B9.mYr/ÐB k 9K0BkQ? `tux&0Vq ?\%O0SLV8(w`hLO)f}us^aD >@Yp,n)K噰"[`a͂uu؆z]ظ6)C6mwg ־^-x‡*mJ{`gwWox!|Pk mg**/* /u_ ʥC U&8=:刋p)LS6n3Y9˹P?.|.}u} WGBpE &p<qNd(Kr)!T w'M zS[aЩ!;hN\H4qY{Q)%ti]BЛ.G:ӿ&dl:A33lTg0$iQFKQ:M0r[g~a~aFga] $&myf9Nvs wov +:Ӆs.*Υ4\f,9?\)7t7N8!C@13~DAT iijC!<"ԑG PDAMRkA:&`R*ݐg(ƨ3ŻC? }D&蟦(=iMْPÔwb**.4TLGcXS~yPɘB-ȴ_FA'c:i>-3H0Ӈ6}u Ug릇VtE3g^)#fsV`G1us^|v37,ރW)C3O3e t EnXP:Y_E?ނkv+(?6ӂo3/4k<ƒh칡 ~/+RfH0tos5ݡ ]Ƅ)T o=) mYn Z*z Z 5 '62?`mDpf6y1J&$Mf&M%C# ()~mdAjR-MJ42[ tՙ+6D&ik}uk 2l$dLƇ)-)Xۚv$0~ەm{1ۛ=[3gv0 w0Ty;mG^%۱M;]Nv1]\JKr+v9mͮV(V Ee.b+^)bO9׮%/GOvCEy7 ɭ wf2Y 6e=!x:hewsױ Y+ Hw#ˬqmŽEuosIK6T+F^ bex[?Mxd]oK6wm#䙷#MlBo٥׎ ct}DDJ:Jd2ؽC-ɂP1` M22$ CKC3 -=S<64W M'~0;_7cͩoI(.6iϡ|=Ƅ')$]ÿ.F%= 8"_YyJ,%IcTGP hE UCrAg` S-SHi"R%/a?7pp%|NFp8!Wyr w"Ýw> AD$2CEƱE;)h2+z$=4[DbFl{AlSR endstream endobj xref 0 673 0000000000 65535 f 0000000017 00000 n 0000000078 00000 n 0000000623 00000 n 0000000922 00000 n 0000001773 00000 n 0000001933 00000 n 0000002157 00000 n 0000002210 00000 n 0000002263 00000 n 0000004033 00000 n 0000004200 00000 n 0000004430 00000 n 0000004554 00000 n 0000004584 00000 n 0000004736 00000 n 0000004810 00000 n 0000005053 00000 n 0000005354 00000 n 0000010389 00000 n 0000010518 00000 n 0000010548 00000 n 0000010705 00000 n 0000010779 00000 n 0000011027 00000 n 0000011808 00000 n 0000016101 00000 n 0000016218 00000 n 0000016389 00000 n 0000016630 00000 n 0000016747 00000 n 0000017381 00000 n 0000017707 00000 n 0000017824 00000 n 0000018622 00000 n 0000018827 00000 n 0000019095 00000 n 0000019212 00000 n 0000019418 00000 n 0000019704 00000 n 0000019821 00000 n 0000020540 00000 n 0000020746 00000 n 0000021036 00000 n 0000021153 00000 n 0000021666 00000 n 0000022118 00000 n 0000022235 00000 n 0000022440 00000 n 0000022718 00000 n 0000022835 00000 n 0000023191 00000 n 0000023396 00000 n 0000023687 00000 n 0000023804 00000 n 0000024173 00000 n 0000024379 00000 n 0000024691 00000 n 0000024808 00000 n 0000025147 00000 n 0000026119 00000 n 0000026325 00000 n 0000026621 00000 n 0000026738 00000 n 0000026944 00000 n 0000027245 00000 n 0000027362 00000 n 0000027762 00000 n 0000027968 00000 n 0000028274 00000 n 0000028391 00000 n 0000028508 00000 n 0000028713 00000 n 0000028966 00000 n 0000029083 00000 n 0000029454 00000 n 0000029660 00000 n 0000029933 00000 n 0000030050 00000 n 0000030407 00000 n 0000030734 00000 n 0000031076 00000 n 0000031354 00000 n 0000031683 00000 n 0000031800 00000 n 0000032005 00000 n 0000032273 00000 n 0000032390 00000 n 0000032507 00000 n 0000032624 00000 n 0000032741 00000 n 0000033066 00000 n 0000033379 00000 n 0000033496 00000 n 0000033809 00000 n 0000033926 00000 n 0000034228 00000 n 0000034345 00000 n 0000034698 00000 n 0000034903 00000 n 0000035195 00000 n 0000035314 00000 n 0000035663 00000 n 0000035782 00000 n 0000035901 00000 n 0000036020 00000 n 0000036139 00000 n 0000036471 00000 n 0000036590 00000 n 0000036934 00000 n 0000037053 00000 n 0000037378 00000 n 0000037497 00000 n 0000037615 00000 n 0000037951 00000 n 0000038159 00000 n 0000038458 00000 n 0000038576 00000 n 0000038902 00000 n 0000042226 00000 n 0000042345 00000 n 0000042464 00000 n 0000042828 00000 n 0000043142 00000 n 0000043261 00000 n 0000043575 00000 n 0000043694 00000 n 0000043973 00000 n 0000044339 00000 n 0000044458 00000 n 0000044665 00000 n 0000044932 00000 n 0000045051 00000 n 0000045407 00000 n 0000045614 00000 n 0000045908 00000 n 0000046027 00000 n 0000046340 00000 n 0000046619 00000 n 0000046934 00000 n 0000047239 00000 n 0000047554 00000 n 0000047879 00000 n 0000048269 00000 n 0000048477 00000 n 0000048782 00000 n 0000048901 00000 n 0000049276 00000 n 0000049566 00000 n 0000049906 00000 n 0000050244 00000 n 0000050616 00000 n 0000051004 00000 n 0000051212 00000 n 0000051500 00000 n 0000051619 00000 n 0000052003 00000 n 0000052122 00000 n 0000052329 00000 n 0000052581 00000 n 0000052700 00000 n 0000052819 00000 n 0000052938 00000 n 0000053057 00000 n 0000053393 00000 n 0000053775 00000 n 0000053894 00000 n 0000054101 00000 n 0000054378 00000 n 0000054497 00000 n 0000054616 00000 n 0000054954 00000 n 0000055073 00000 n 0000055400 00000 n 0000055727 00000 n 0000056066 00000 n 0000056461 00000 n 0000056580 00000 n 0000056787 00000 n 0000057063 00000 n 0000057182 00000 n 0000057553 00000 n 0000057760 00000 n 0000058061 00000 n 0000058180 00000 n 0000058572 00000 n 0000058691 00000 n 0000059030 00000 n 0000059345 00000 n 0000059696 00000 n 0000060055 00000 n 0000064309 00000 n 0000064467 00000 n 0000064625 00000 n 0000064752 00000 n 0000064784 00000 n 0000064940 00000 n 0000065015 00000 n 0000065247 00000 n 0000065422 00000 n 0000065661 00000 n 0000072836 00000 n 0000073046 00000 n 0000073398 00000 n 0000073609 00000 n 0000073953 00000 n 0000074070 00000 n 0000074219 00000 n 0000074336 00000 n 0000074453 00000 n 0000074570 00000 n 0000074687 00000 n 0000074845 00000 n 0000075064 00000 n 0000075585 00000 n 0000075798 00000 n 0000076152 00000 n 0000076303 00000 n 0000076409 00000 n 0000076515 00000 n 0000076621 00000 n 0000076727 00000 n 0000076886 00000 n 0000077105 00000 n 0000077318 00000 n 0000079688 00000 n 0000080506 00000 n 0000082177 00000 n 0000082766 00000 n 0000082943 00000 n 0000083183 00000 n 0000084671 00000 n 0000085246 00000 n 0000087111 00000 n 0000087529 00000 n 0000089163 00000 n 0000089570 00000 n 0000089790 00000 n 0000090197 00000 n 0000090413 00000 n 0000090837 00000 n 0000091057 00000 n 0000091273 00000 n 0000091493 00000 n 0000091906 00000 n 0000092122 00000 n 0000092546 00000 n 0000092766 00000 n 0000092982 00000 n 0000093205 00000 n 0000093624 00000 n 0000093848 00000 n 0000094270 00000 n 0000096332 00000 n 0000097230 00000 n 0000097453 00000 n 0000097880 00000 n 0000098096 00000 n 0000098306 00000 n 0000098522 00000 n 0000098898 00000 n 0000100473 00000 n 0000100752 00000 n 0000104844 00000 n 0000105064 00000 n 0000105277 00000 n 0000105498 00000 n 0000105716 00000 n 0000119941 00000 n 0000120152 00000 n 0000120507 00000 n 0000120656 00000 n 0000120773 00000 n 0000120890 00000 n 0000121007 00000 n 0000121124 00000 n 0000121285 00000 n 0000121506 00000 n 0000122110 00000 n 0000122328 00000 n 0000122689 00000 n 0000122840 00000 n 0000122946 00000 n 0000123052 00000 n 0000123158 00000 n 0000123264 00000 n 0000123425 00000 n 0000123647 00000 n 0000123867 00000 n 0000125973 00000 n 0000126280 00000 n 0000128462 00000 n 0000128866 00000 n 0000130992 00000 n 0000131378 00000 n 0000131599 00000 n 0000132205 00000 n 0000132423 00000 n 0000132877 00000 n 0000133028 00000 n 0000133134 00000 n 0000133240 00000 n 0000133346 00000 n 0000133452 00000 n 0000133611 00000 n 0000133833 00000 n 0000134053 00000 n 0000134273 00000 n 0000134609 00000 n 0000134760 00000 n 0000134866 00000 n 0000134972 00000 n 0000135078 00000 n 0000135184 00000 n 0000135345 00000 n 0000135496 00000 n 0000135614 00000 n 0000135732 00000 n 0000135850 00000 n 0000135968 00000 n 0000136129 00000 n 0000136349 00000 n 0000136562 00000 n 0000136793 00000 n 0000137017 00000 n 0000137150 00000 n 0000137182 00000 n 0000137344 00000 n 0000137419 00000 n 0000137672 00000 n 0000137844 00000 n 0000138079 00000 n 0000138264 00000 n 0000138515 00000 n 0000138753 00000 n 0000138979 00000 n 0000139198 00000 n 0000139411 00000 n 0000139633 00000 n 0000139854 00000 n 0000144678 00000 n 0000144858 00000 n 0000145104 00000 n 0000145220 00000 n 0000145658 00000 n 0000145950 00000 n 0000148479 00000 n 0000150513 00000 n 0000150733 00000 n 0000151188 00000 n 0000151406 00000 n 0000151906 00000 n 0000152130 00000 n 0000152350 00000 n 0000153756 00000 n 0000154491 00000 n 0000154712 00000 n 0000155198 00000 n 0000155416 00000 n 0000155937 00000 n 0000156161 00000 n 0000156382 00000 n 0000157736 00000 n 0000158468 00000 n 0000164078 00000 n 0000164289 00000 n 0000164635 00000 n 0000164797 00000 n 0000164952 00000 n 0000165162 00000 n 0000165372 00000 n 0000165523 00000 n 0000165763 00000 n 0000166003 00000 n 0000166156 00000 n 0000166322 00000 n 0000166494 00000 n 0000166671 00000 n 0000166881 00000 n 0000167091 00000 n 0000167263 00000 n 0000167484 00000 n 0000167705 00000 n 0000167856 00000 n 0000173694 00000 n 0000173881 00000 n 0000174068 00000 n 0000174215 00000 n 0000174372 00000 n 0000174583 00000 n 0000174941 00000 n 0000175059 00000 n 0000180645 00000 n 0000180856 00000 n 0000181223 00000 n 0000181340 00000 n 0000185405 00000 n 0000185524 00000 n 0000185643 00000 n 0000192566 00000 n 0000192777 00000 n 0000193131 00000 n 0000193342 00000 n 0000193693 00000 n 0000193842 00000 n 0000193959 00000 n 0000194076 00000 n 0000194193 00000 n 0000194310 00000 n 0000194467 00000 n 0000194685 00000 n 0000195048 00000 n 0000195261 00000 n 0000195470 00000 n 0000195617 00000 n 0000195735 00000 n 0000195853 00000 n 0000195971 00000 n 0000196089 00000 n 0000196248 00000 n 0000196467 00000 n 0000196680 00000 n 0000197359 00000 n 0000197577 00000 n 0000197938 00000 n 0000198085 00000 n 0000198203 00000 n 0000198321 00000 n 0000198439 00000 n 0000198557 00000 n 0000198716 00000 n 0000198939 00000 n 0000199244 00000 n 0000199466 00000 n 0000199844 00000 n 0000199995 00000 n 0000200101 00000 n 0000200207 00000 n 0000200313 00000 n 0000200419 00000 n 0000200577 00000 n 0000200815 00000 n 0000201040 00000 n 0000201260 00000 n 0000201558 00000 n 0000201778 00000 n 0000202197 00000 n 0000202348 00000 n 0000202454 00000 n 0000202559 00000 n 0000202664 00000 n 0000202770 00000 n 0000202930 00000 n 0000203156 00000 n 0000203377 00000 n 0000205377 00000 n 0000205823 00000 n 0000206875 00000 n 0000207226 00000 n 0000207585 00000 n 0000207923 00000 n 0000208270 00000 n 0000208612 00000 n 0000210356 00000 n 0000210764 00000 n 0000211793 00000 n 0000212151 00000 n 0000212497 00000 n 0000212837 00000 n 0000213199 00000 n 0000213532 00000 n 0000214718 00000 n 0000215094 00000 n 0000216551 00000 n 0000216959 00000 n 0000218174 00000 n 0000218555 00000 n 0000220055 00000 n 0000220462 00000 n 0000221311 00000 n 0000221673 00000 n 0000221960 00000 n 0000222273 00000 n 0000222556 00000 n 0000222874 00000 n 0000223103 00000 n 0000223326 00000 n 0000223556 00000 n 0000223779 00000 n 0000223999 00000 n 0000224388 00000 n 0000224608 00000 n 0000224996 00000 n 0000225846 00000 n 0000226210 00000 n 0000226495 00000 n 0000226813 00000 n 0000227100 00000 n 0000227421 00000 n 0000233630 00000 n 0000233841 00000 n 0000234203 00000 n 0000234346 00000 n 0000234488 00000 n 0000234624 00000 n 0000234780 00000 n 0000234991 00000 n 0000235331 00000 n 0000241471 00000 n 0000241682 00000 n 0000242016 00000 n 0000242154 00000 n 0000249404 00000 n 0000249594 00000 n 0000249709 00000 n 0000249824 00000 n 0000257000 00000 n 0000257160 00000 n 0000257313 00000 n 0000263060 00000 n 0000263177 00000 n 0000263352 00000 n 0000263594 00000 n 0000264873 00000 n 0000270435 00000 n 0000270645 00000 n 0000270985 00000 n 0000278087 00000 n 0000278223 00000 n 0000278255 00000 n 0000278420 00000 n 0000278495 00000 n 0000278737 00000 n 0000278919 00000 n 0000279170 00000 n 0000285363 00000 n 0000292392 00000 n 0000298905 00000 n 0000305056 00000 n 0000305236 00000 n 0000305483 00000 n 0000305694 00000 n 0000306044 00000 n 0000312517 00000 n 0000318905 00000 n 0000319057 00000 n 0000326129 00000 n 0000326281 00000 n 0000332630 00000 n 0000332776 00000 n 0000332921 00000 n 0000333075 00000 n 0000338604 00000 n 0000338815 00000 n 0000339173 00000 n 0000339309 00000 n 0000345366 00000 n 0000352686 00000 n 0000352848 00000 n 0000353038 00000 n 0000359900 00000 n 0000366855 00000 n 0000369103 00000 n 0000375017 00000 n 0000375227 00000 n 0000375585 00000 n 0000375722 00000 n 0000375754 00000 n 0000375920 00000 n 0000375995 00000 n 0000376234 00000 n 0000381897 00000 n 0000382108 00000 n 0000382477 00000 n 0000382594 00000 n 0000382708 00000 n 0000390203 00000 n 0000397517 00000 n 0000404585 00000 n 0000411164 00000 n 0000418076 00000 n 0000423455 00000 n 0000423574 00000 n 0000423693 00000 n 0000423812 00000 n 0000430255 00000 n 0000430396 00000 n 0000430428 00000 n 0000430598 00000 n 0000430673 00000 n 0000430920 00000 n 0000431131 00000 n 0000431498 00000 n 0000437703 00000 n 0000443677 00000 n 0000450235 00000 n 0000456671 00000 n 0000463369 00000 n 0000468195 00000 n 0000468406 00000 n 0000468775 00000 n 0000476104 00000 n 0000476314 00000 n 0000476638 00000 n 0000476773 00000 n 0000485697 00000 n 0000493109 00000 n 0000493320 00000 n 0000493655 00000 n 0000493772 00000 n 0000501561 00000 n 0000508471 00000 n 0000513914 00000 n 0000518458 00000 n 0000523752 00000 n 0000523869 00000 n 0000524079 00000 n 0000524445 00000 n 0000524562 00000 n 0000524680 00000 n 0000524798 00000 n 0000530054 00000 n 0000530265 00000 n 0000530641 00000 n 0000530758 00000 n 0000536810 00000 n 0000536948 00000 n 0000542504 00000 n 0000547274 00000 n 0000551470 00000 n 0000555257 00000 n 0000555419 00000 n 0000566601 00000 n 0000566960 00000 n 0000569229 00000 n 0000569347 00000 n 0000580226 00000 n 0000580463 00000 n 0000580884 00000 n 0000645930 00000 n 0000646404 00000 n 0000646790 00000 n 0000647219 00000 n 0000706170 00000 n 0000706610 00000 n 0000706966 00000 n 0000707244 00000 n 0000794163 00000 n 0000794464 00000 n 0000806776 00000 n 0000806820 00000 n 0000807154 00000 n 0000807182 00000 n 0000807612 00000 n 0000855288 00000 n 0000855662 00000 n 0000855988 00000 n 0000856016 00000 n 0000856204 00000 n 0000881543 00000 n 0000882024 00000 n 0000929656 00000 n 0000930201 00000 n 0000930585 00000 n 0000930921 00000 n 0000976226 00000 n 0000976621 00000 n 0001019656 00000 n 0001020050 00000 n 0001020384 00000 n 0001020684 00000 n 0001033932 00000 n 0001033976 00000 n trailer <<81531FFF439CA34A92C326F43369189B>] >> startxref 1036285 %%EOF xref 0 0 trailer <<81531FFF439CA34A92C326F43369189B>] /Prev 1036285/XRefStm 1033976>> startxref 1049907 %%EOFlibdigidoc-3.10.5/doc/SK-COM-PRG-GUIDE.docx0000664000372000037200000272607013560273131017150 0ustar travistravisPK!˭ [Content_Types].xml (Ė]o0'? Nഓi ]i5p%MlHPJhh79gy"zV)J$낫MJ~I䐩 %{pfr7"_\J*DRW KGJm%CnazX|V c d% nwqCbԆDUJ 9ȸT0cUtb]7D83YS4e_Y·Cyө` oL4飶m'Yf8f9rHZeɸ:q[ZryoqWTV4Em} uj+3~Y j{ ݑ?9Ve„4'ncDnݳAyQZ8Ƿo!@31*`'ْhCX7#_4_c2s6 h;}'2,U]_-0cco[G߫LBX@M&uPK!N _rels/.rels (JA a}7 "Hw"w̤ھ P^O֛;<aYՠ؛`GkxmPY[g Gΰino/<<1ⳆA$>"f3\ȾTI SWY ig@X6_]7~ fˉao.b*lIrj),l0%b 6iD_, |uZ^t٢yǯ;!Y,}{C/h>PK!/word/_rels/document.xml.rels (XQO0~Pq$4MhrKjؑRsQ{Нt|yXWF(dr!˔}\RR\_}py#]I&[BMMtͭ[6<%x4:z6OYBUQ nTA=gPQ݆\`SRC.x<.pY86 0Q,]Ru%s: GtT::}8&7dAFM^t~S+тe>9`w|̎>ow-4>'7u}أvIOCk @OF>0TA\~!4 z޿p:un`*vU߻PWzڙOمB yu3{<^A8b&~F-d+cU˹ЎQDwQ*,A4Xb :~ R5/~v$Aڡ_*{<@Pg?P%QüS A`dɄ?~2m|tlǝunfJDm1Ա] POB.Zġ a-2*lfi;v9) l^ 8V5B|s?wg!1CMەa^5AexXi{o0o*݁BH0RT9oDc_cqڏc PK!GP#uword/document.xml}nږ#whhR+8CkT$ޭ-c 816eHkFKH,}d?cN`!TKZ09q`ƚyc9F3Uܟ7㸊Q Nr/_69Xh.Md;<>:rԾ6PÁږcuCYݮjGqy6O> mK*Xqr^s֬fB_](shٽb?mh;/X'm{ 9Os>YVxdk2>Nc`}HId sS^ej268\btCtWg[dIvư}#(4҄N6}j[a0]kS5F OY+C- iJۀMXA̕Y 2c`6I./BXU*ŚUFB> pj|m?-b5xmesG9tcl7;kGɀp !ڴMZkՙf(2<|Z['ږܭ* m/Tn,D^ Ev;yVƍK'nt`8!Nv̳eXF8mښc-WbfzշNM`mg+f0#͌'aBRGNt#/ DNttiȉZ -{jCGK2r-J:@D@jH1Zi2GZ$:IVU}cUDHl:IS  YjHP-g('+r>Ï?gQ.IK\⻍Z, \Boۊ¬`bVI1>XSF& L5^@ qѰXeZDq\@ C>[**٤ժXy pߓp<=SO7a*6ʶT~l)t+Sݿ+-=- E/CTaɿVQZ=̫ Ő\NXl&\Dr._s 08Ά!{'' C44cXA̎fkkX)ODwcxr'rШEm4S٣xo+7QIJl$B5lݶAmPN<%ʩj ?n;: f\I C[ɱ V4ZmZiOEF϶-׵>M >ImfÞ,۸P^.$ݧuJ&وnѰ| %F~Zhn#j`Zgpy?֭25`@hA*_hFr ~F.`w4?P`bd8]T%>8OI|*_zGǁM)bhR#ba2]s5O6;[N4.z/hҴ"VC_dBBXd @U% I L ^w=4)B&uK/"A!oښjB^bc75"(sS & `gUR煄sXu7tI<fjEdETvHnUN\$%5wg;/&ʙqO_~V^,W6A&k/Eۂ4ܷ%豻gC(BG.@1\!Áy`mN}"hj]WM5P! Xc"?B[U"(|U*|,yKjK)}euMۂYS9 F5F.F;wINTH]j:F#Êa\#*,0zKdkdq.>LN2qԏ2Itka,x1jC1[sTTT(.C3˼^{8EgjZCnm/hdhk s Ri{\g# 2"ZM/rvlaNȰl~t vePbC!KۿT1I -Eɵ&fc[(lQ) %%@ډc,&Xo#}iLwK~nWL1ף0@1g|Zn:%X, [Bi^ҜV vh pvo1%2ZXY5O+f:^eL &ʘ)XbˊLZ[Ct+C!`[Gq[x e532LN9eF5/Kڿij1 wq񙞶̘4>mzʬǾ^įMy1Lhb]_܅)&sUm]㋄=uom.d%{3+έ> ݚP y_weZI>1se9 vsXC8,d88wz;IRcNˠn Jx| `/9^fKܿol}cVo3e凶ճA^dGĺN!mz/YP}~lĥs%;]>ZW0ou ɪ5@mLBJmdxd^eYO+߿RY$0\jX 3dӢ\y}>+]CH-gn,$X50E\/*̰ǁR8N#&<.ڃ6}.+خjBlۗ[Dl/dZBI;.͓LK5i83:54:Wj Z55KM۲<%Y݇Y;&? ;+I{}Ek@Xf:4ȱ-"zM0!}sǬrJ۫cI/M5(ޟKMY9h-WtgjSzNWoCSVv轡Rͮ)MT" s[=C] ;F,@ zijӔ.7'!+0O99ӜRӜWQzg|\~iJSV`>K3pJv\`RV$ۙeoc˞U+'#=iygp۶egӔ&7Qs[):S>YazWo`MMY9lӦ,#B1Y;e 4V-~-mBXQ{Jgq13is)+SVK8齩VxYwv<wuUq3ۊM\OY9xȩU"جLSٶLw\wDdNo;c6+tmrLT4;*D-lP}%c6@v%fu#j_FxNf;zIWDVkZW.V/ȜS~X$+h:l/Mךb1um 4[\+=bk\XGw-iO-Hwa,z$GMexby/ w'+3iCV[:7]TW?º fD2JJ!Fx ւi@#%5x>qңt3YDZI-?k,;<0m m챖+1K @a:z[sy 7Vؿ@2qWGMuoVG35q &o=;[%CoPJ#i-j/08Z/wq>;؝P*^pAixZڥ5&^F}r!/]+nNuh%3;/ rSϳn/[dh ɛl(l}PN A4 pkbzm6U"V uX(N 'v1 &tIOyhfNiP?@!ezf0 0EDTJ~DZ[〗MZԐkuJ ;}|RM mg+J5>1z"9{"Hkᖊ+rmI7*FWص,Z6e8|dZK]Fb|t,FTouDihj ]T"9i̩T,|ySųJꂏ1E稊ɴ5f0 %WZGI`h/-MkF.h?_I/ă@2R{L aȁ&ɮϣ#Cwi- 3~$ZCxszDbW))cQXغj&;h{ۖhT`Y!aD)1)d\T LD,VB ~+a<]߀,ѶBp+\D̀+ %mW:r?ED|6}.>PfW `ݗ!:Q%'L ( RB =c9Q,Զ6'2cK sIT][c)NFE(UҢ ў:N\ӢMZPwiQ'O  CWZ$YbضES{sǔ;cT48gcA ^d0/9qSZĸڇAަf8jӇA)G5@ ``D՞L"#usquwIs=rSZRu,!:N`awvFa1+b"ˊ1 C޶<91 \c/#xbO2N KCТDW T='xdtmbOo,8LO35QQSG10_FLM-i2VtCi't),~D<.ޑ7c\MiMN Yɣ곙z 1pƺ6]!Ack?G1 YoLWRXJeR3(nhh> ,Euw%zMu]P\Eڏ|DdSzU' \/@o@@я$LʦDƕ4r8v("#4 .[WG,Zt K!.EmJ آӝɧDzIsTE9H:bǨ8Po* $fi ~eQ| !G&n` Xń|b` ZЅ:px2Қ0[.~s!1Ç<ۣ%6=#xa^j ͭ05O(:vJZ6\=:e5p05f\Xmtj3C,K ,vPQ/bTGw;'2`(2ɱ҅YeꪙI jQ`ϹҰNO8ʶh!$]u/4[u_}s^yኴ3絊}D(֮^rO6[q%v ֌-N»ڕ'LS(x/XTgRIyp8Mڏ{h'hڸUAPloqj[*234}\3Ipݾ ɅԨsi>OP }mZr ģB PuLMPQ2ؖ'v.zĕ(R F3ȕ* lf/I4g¢4U:I#Fŗ JT1Q ޔ>v QA `$mdRxR` 5HKAJK Г-9*-Kuk]BHJiYKHQ-M6Uzޞ+b3Zh3 ǵec>_.H KX<-0sZ4Y8U) ByA} o Iż O ޥEi]ېAȼk(qEV|y .V7Ӥ O*y:s0nWQ j;[ >]d k܇WiC5#Ɖ|BQ2P"I(vQ?C#IƨA)Pp1e ҙK+xe^@إnU1pjGb060 !嘄yW.,A3c$wёBl C|!|{G #rI֤8m bsm!, #rP< UsOIW aCB96n-rm;PVpy ]GێAl4ܷ 5LfrE$gC~ Аcrb̓DÐup Lfr ŤW0oB 7:z3ȱ7P6CQ"@V \\zUtpBI#zuXfϡ}Ү`R认[ c5V0`M5 oedߕcp0kM8\M5ڎ[S>]t$ضFfVtdNh2s1'r ቫ c7L)M1MF>(C7gj.Nt牡C-@ a=y)ccq'xO 2ӊv0`!\SqOr]W EH[!SFFEpxԺ#q+Y<<-л|Jl\mafR8 +k|R XW_A,bL=  oHW a=5 iLV' "&Vp"A*-]Y(^@R88oQ\+:umLVt+yu8_ϰj- %_^ik2\2>a1z*bΗmBz{2b茗/|-|DE>>4 *nʂVAi3t<ݏ6_r4 n8wg RWi1 ӂo!D4 wEo'_# HFό} RK4jog~ NNFY(pdS(eF8#|fEcX|>H+]A- \(1jW[zlU {sC!BC"M7Cn[-˸`+-?;` O5O狒T@@5Q%38HT@M[Ta3Fh!q7WgF" oQȸpx}e(=fU%̬z^uNby2G 7X+}Ai4 N^M$ȧ2+qe<1H4J& z/za 3o!s EHL0Y*p;ar41- :{Ym|ΐ_[B`H5?Njo *0EC~YLhQ:BeVa~5Pbc`{ni{6*r6V l` /Y(W atwbY}un|Ψɱh$Id]Z0Œd {lJ|2=i,Ŕ.pdcb_+w`UNr֝Z\rV,_4ZK7x.9nMޞ΅w_Zj*rQt|;-}/j]Wӹh^9}Ɠ{0xT`eGXx R}~qz?%i̶G廯f˕΄T?==4ە^ޞǼy_ijz9-Wj-`/I{Qի+ح7 2Eˍh_k/J Y}k_/.6ԿxINj^ns,x^>:\ ƟD^_UY~헑|{MٷY(@l9#}4~H_[A[V8s@>yp枵:{#]]ɾ_Ӄq ˣzu/Í,ǚrdb_OiuupT˸y*?sL //|{޽֮xP܎ f<)ʭo{rݣ'?_ZS~JW9~=x\5[S(|w[ ő֋7M:ZW-iP[v~ʰи?<\_'&VS9zjvh88zs#&i~ ^ Gs͍*V͓v S}QΏ)Zl+n{mO~ /γ&_w_kcUhI~ %$Vx~fb6:Z8^Tc$J41ޢETG%0{$OZ_ۓ5^@1͇]}UG]?_ X-YpHG0W\`$^(m}_/xӭ.4yX]Z4h-U?X+L!L--kP'xXoN;:v%(u~+ ez~GH= ij1^Z#o{AR-$ʰusU3qzrn$yLNƉqoR:؇l½#8 ci|qn2/p:DHR$Pu_ D WJnGk٫vÁ]giaRٹ!֋(s _L!䔗/,q 2D`<,-ya)٬m7: mM2!Ƕc~EᯅwyXKh$v8g )i^hw + aHZQĴ3}mGd_n|p^UpNb҂Q9 -Ի.&)Q461-c}1UaP봸#T$h1 joYmZpRod89߲tsʣ&HODWC~5؎KI?DGIp[?"vӱ(QY+\V]r'>cwUP* _\NgYȤ&sC,ܜWw&>9(rī[)6;yjuuHbd;xnڕHuʭ'R"VI8pz^"e^}nZU;bU7m)]<l/"s%6 lV~s{Yk+tfs.fE6ԡK@&nϽ!=ړЁJЮv2āx6iR-w Cċ,brľd( }_2+ܿ~_"&aAXEzF%ˎ #㣍{A;59?`“z<ٹSeGZgKu=@^%eE:Zwݪ .oBW 5M4 C|yb10{4m/)a1,a䄋7ZOoxe14v^{#}F/| bL;nKDRwŰ evlw=f*S٩-[6 B@Fc~>Ye U{ÐKZlMf*4!yK+ΪG՞N`q!ȜTR.{md%Zu}*1bZSGJ9y~]NȐgkJ[w:n=riYXImvJ!A))\u*eD0ˣ7bdF1W<@bvuŢrάVXIOɯR‘? kL]ċcrpɸ8Рo90Ԉl&AH`slo^% w4)}?g?HG~AYS|cYz |z9\_L-vioi<1d 9FΎ;is.5#D$|,2,/LL+~:ȜPvHOas`%̳b'mը wܞ3^ ?$|"enzx&oYެ7GhB@ZG%!YeFdt^πJr,Y& YQMeݒ='e6G4{_Rks`8TCByd+-&|aCL5'|T8[?+I'?> (}w0#'W[ʨ}Ӆ*SRqqZc`u'd M$99*,`8!mv&#C]|3FA^s}Sމ^y8Z#$n%f3jk9֍an韶)_Xi~E3rlnqLoqh7ƿOqF=C(\GgQwv۸խӉV2 1!]g̓Ζ@sKG=t"2.wv^rlk٣0ؘ/6eCHnH&lO"^KwM52(o=dsX f S=?B$$6He2Z*"sQNi djCO@ KAʼnTd Ѽi7"ֻ%[- g^v;pm Yx?χ#пY.s~ǀ`ZO=HmChYlHد@Po+\6˶2&O]UvٔV}:z X/U*F~5?@-5 ~G(m@n)>-=wN E `%"$Z 7sMe`x<ޝzJMzWBnurE%2yR'3 {g.۠_ wAPS(k)|Y}?_{8Tue\s'wVWG'ǥ_5Ea4}VO:l%dtNu <`5t%W>)9EFpP ɗu7=z98&%>ףNj`W-/0Z0t&B=znvMaoeAe\ 6i6] .WZpvβ$k<;20K3ԞvP 3&T/w^W7)t_v3s\JD yn`g/3S=3iާbW #sܨU;MZ~IR|97L\9S >99nX'{Y '}6~&@*]X_bܶ,8x n+)+H)qN1+6Y/ ,hmueFѻ(%&Xpڳj*%M6K_܈fF.y1L/k83Z9|H~.ՍP6 #EmokΎ]:͵(sy%|]7;&~ULj+5pFR XW.x]&/SukdfQa5(/](G̪$X߄oyf$? ߱  ~K…~SLzPxpk≊'2&~d_PZs|5c[fGeZ: kٲsED,F=(-6b զI(+Иh*k1?>şs{vF@&o \m(1[tZфSFpU?fCOR@դJf.R~]IeT܆X-6ټTp0 fOM.,+ƂxfinRܵyy%G!,s|Ѷ׈gii|RRZT c/lxNH 0M` 2![J4A1˱\+` lZޑk#V~ S[$dd4|u}X(jB?)Ja9lX.N0}ij-WeoYY3zkɋ>IP$Q2PMye5J/H / hewb}@'O66߾JQKg:7oJsէ̄Ȗe( AG! (`-?<}zlL޾VOaZb|xd4w"_n|◯/8,-Koݯ'S ̱=.,cHM^{Rcj]ΓVhzst87)LOu9e"X;{L?gx@!0ڽV~|Vgm@^g հn=`oXk=-z0Tc>&ľXr՝OkqѻxS`=UaL bLB2s r/AakG#7C ;{g%6҉i[t[Q@VPY%˺^E;.SfxMOnp +/G5byoԱo,^b^RX؇'^ݿj)ag᧱/9zijjHR7*3a`4X@Oa*4jZy'ݒX4N6%soH.)t):ߎOhnS6-4O[fP|tDOP[;W^*\ۗޅ=6#PHB&16xc-WD9SN7^ hn<L#p&],P#6:)u|%z,$v;x_#Gs?ZwwF=>)+bWK%=h%WtN>쳴6[w.,n$kfzGFRK*?oE27ӕ6ZC SY7mQ鉇S{ZG]͑ -CueLoo}Eݘd<0;pU;Q2{U/9`}Rˆd$u6>;4\~e}K tn)6Xy9^Fl7z61G G1RQm5 !y1iSgM;J+Nb G7yV1Qm1ht͟"k)Z%&oC@|T;Qsګ:e1@2 %'I"iF%UPY]7% 7->nc5 1l#:n9AX=u<+ `Fx뎂'lLWh*l *>CW(/3Ufd5 rf"6R#kbBNWryi#tIlq6 2O'~]F\L_'G/ %꽲+ǽFɓ6r:vY R ., ˎjvsɩ0|-Cz:T{sOxCyH]1·^_a-0+jXnٿcTp"h]+wE , gR3܏z<%Ӯw띗@489Vu)y,;tzjo+3(غLLyBx(7ʉb/bʊagYs}r?Dn>˩=z]CFH44t՜,}XaXʼ"K>87eD(3?-, 8'c r${o1 7M78~@ G8^q ACAi}#_ߴVނk5qQ =-jg2)jdAwol_7KI 'ؿ5OS}V^zAKܭl8KhlU}FNJI˸1""5;`{rz^jt<1j<ӻ o/.p@M\į57v8te/2%$Dhqt>;؀6WObҔңLf`rr;g^Wn)1/ B>>AF[g~ &C\:o \`V ^Wf3.=;gVKj/lJʙKu?WZ̀}ftt'1e֨Q;*G[ X'(AF :{ϡ@)}9eAW4;v.dYQ߂ؐw^JsYM0J6 Lb@gQ=Dd:ԙ8+m(t0>kB[H\EyanMrtvi={IcaYʕs#'lQ,ɽElmӼ=ڹƽ}ާvny,yߚ[ЌudL*TǦ~{Kj\fqo H?};M;FVvvnȺj}owlZܸ"Л |gԢ|@ a[*aߪseTF__qW)Ȫ_D2G1G/h3(tv3uOmJhc>8K>98:i<٣~.^SRl+ơ v8Y]MҢ-p E_&462R݁"S%~lo[(CW#7Jt;.S]9'n(dYT+i1[G9݋'4t hecx,B{37`X)u~~j}g/tbw6ϸǃv?^RXKnYfl'`AKK*b0db]2V'鶝 ͎$_.?n20hr" vGz$i2߉OWVڞs{p4~qcL)^1:%vOSs`nt_pXY/rVX#r9׺.k#pͯv闾MmI<>*sسч*_ͪ(AqNv-{%eZL?EfBQ/Y  sՑVVwX V VF=JE:gdy:+y,aT7tזDߋQ׾?|L%_\ׅMγ,IE2u%%Yf0!9}/,39ŷ;jܩL.J뼀rV?~tph%j1 +8m&%Fw83bK=5,t=w&vv3:y$9w.ıص.r>=@KwNvF^g.G(hJQ>Gv%Ɯ)2VHx%hFOUikvL ouI(}!^֤ue7t/84?(a>Y.DJ˹L!L u8/6^l[ɅY{ zZEF$,mj#457|=~PFG'H,c"qtt-;?J& ⟒5_sJdjVp>)|5y9XR*{#H4zL{t X y0O`?(b,Fxg|p6+Goo{6U`~m馰I"uYBԴ.^&te3{Nh >t1_G1ϩpߚs&I}PMȼlQ2G:e)&3UjSu2s~j;%H뫶YqVX Bn)a|=U鎻A@EKkׯdQQoҞ ?:m1 "COP:ߓ<Zèqt[L=[099R BqN@<Phy1lyA@7!MR!9JXZ&YāsĂ_C{<o=@$kS5:"]u P\D{j>;J|N/gP6b#(-b= )޸''Hpgq-C}Ql`v*J?SIڦ\e_kƗ9,`T:}VrLY`cdPAav+bڌM(r/(WO=KO46楗PCSm L]_=@u2K2Ea220itRzE}t"??xiFL7;gK yt+26#S) No# m^AIݗMO 7> PjM8Jg1)g,4,U>_x'F2d=:)bLY}W@(VԂZRUzacT19VRw '>ҳ% 2XgAZd `Ꭾi5*Y C24 Q}[OwDPDO|ejm^Z,#|&DBUӇoA(ui;("%UӂT<.ND>_R ,ՑZl"Ț+)_^n/CivPv#{(<$ 5owKz 2^z!kz8pvON-ٲKڽ01P8eBPI@Hi?m9U:H Zo,&H6'+)Cӏ2$s &\ƮEt:z-) 3faE%a#\kUp_9b|GGs.e6|yi71/KēNU?|_8izh{V$_>Jm? QP`EqgH~]eWw93ɯ2 f s|,5z u.. ܣ`U{!^bgNO{-fRr+ Q,a}89^`Z`tE)[yy(]%ɴ+ah%D~k,ޥPC@GU߂0{ OY9/v (r yD9y΁R׺YMLAz/8ڐW+{~x# Ʈ2 |E`Yj_t,[JKɣf⡝,c3$D[/gnRa8r/ &[:m|˦\ r+[pO/Ce< *uYZC L0NZWHeZ+ kRN!hAo#qr"1Q=#@zƊb ޸83>;+2ιy H a 2ג#*$KL*֔ ό}^1#u>@RȆ=)#u$# I i3&vEF%9r^j|ZEnGnGd}fVl`4;6wrbu$<3#\C+U⪳oG1Кo-;'ݝ*HM#149H @@id W9vQB@^2"I̸f !TsL4gm% S<Yh%ݗ,welĉ xI3^UNXǂ({88FL1srr!-2 [ $Y__Z.@3|A GLf -_CrU}7$?kWPKB-7Y-lR^GEj|"wpk~k~dp_gj aL*_h^l;~YM3 37s8dOY2EbpE|I3@ĎxEB-': PU& pVM>s/IEH")lD tk7NFC jm8t76\xPgv #2\! GGz5Bf2Os=0\~_ys\ 4a9*wkΌBF*ʊF̰\>F9Onx2HTS>[_Y9 >40GP}={kc5ï{P ޤ__f^E*=,LwN{&B  <5WLUr;h2C9<hs Py U͉;KQ?~/̜iּ9 ߛREB)#$Ri|n+jz/"vnzp_Qp=EGS"bheGpxb;t 9wSۆ֪Uz\ IL5YIn" bvspF$khO2uULܜpq7vu)U*+ W-UcË7 8Jlcc8T- sIǔBNDp22F@k) 8>*|f0d+? S:$apjM!?l(t2AN{6u6MӪE)0'[f{wyYD#AԥLԵCANZOhJlnQS{n/G..41ҼU"/㋤hf l&sR6Ɛ\({>S#wGNN x푇,xo >ܠf*0AI[) %pޙ-$o />&Ц|2~sthx>68|lJ*TjL0I>4;C rhno3l 3h O]s`9(c".^͆!SB'$~37 #Ptkl28]BXJׅKvJB7 [ft}XLLFGsd}w#+nE`he(7'-;.zw雠F5Tl35z[ 5 Ń*9ytmwKNw17즗D#ؕYր9LHd@d](j-NØtd;|ɏ_iLq޽baAw3;7j*?KI1ê8#T4@;] EŹ ZK U_&,䉹-ÈoJ}`L?I6Gwk& w#g$mQ7. qq4jbsВޒ޼ %NFp^JvkqRq\=^US~9 x=RsmjՂx]bfjMbre%UHs֮Q[$lޘ&`%zW?ͨ~u"@5 {av `eX J03PTRW_U{I`#Sxc^_ye0g&PkKLt;%olLzUEo@ǭ@ 8g/,7!nNj4_w05=9FWcG}R b y~nm Dl|/WR2EL q/dF1B*M<|: fI:~ 'G#L{iLwgSkcz'$})>@ rmnu̘ "=Td%ږ3Wxd7 Oc}cg$w3 63 B*ᨹmW4Xg˂qz~Ѯ7c L0P JGx /<˄QV>QsmnNbIV!fvYZG fR[ 1wL\ο<=&yiL;+2cO64 g>TȞRJ" ?! /4Չ22'eS*LJ1#z c]"@3i!"zf@v=ȯwQ |PiNpu}G@v.Zmײfglo@e8 `ջoVHύ5Z_YR2 MH0:$!‡F=eIBX'ߘ{ v=&LnAT>k=X<'`N¯&t ~H. 2SÊ B])1)[~^&qTö/#}n! 23x}xl\z ̞@р<GbsaO V1=qVg[7\@V,zs$,u/nGAjEG>C+ *~&qp6 .N:]DUk ~hX\ˀfυȌ*5RPH6{yܰߡy'`֡WNwfD!g~ \q T!iuwl~͗]$3}x7!8GyxBzGT^?/yRER_;F: Մmh>çC]5)roFTR +P)AjPB4s}fd&.&hһR_K*qK$ `0 ,iY8MGhj!E;g`[t!o i融+ sA#/B hCD^Sp`."_ YTLD2Ǿ\BGñ/G./lN˿bd[CG@utΛZnرӁYyOmo qY*]OO;fEI@$x3as}~:W|QbW▵ҏe~ ̦{J⩁7L|1S E˷o{O%>] $c 7"RʳL$H{. Y;*kY$@Dyv'\FFG0!ҷֈ%Oyɉ"x\6&=eԂ /yA-կ,*$>{p] \u`+GH"~k -j찁j*Fe+ILjɋ./UoMiFw&[IݶkGW>q5/IAc[ 5P<}tv]_!C^Jc➾]?wW~;Tˋ46ZOެ&RDZc.4o>-EFuՠXc.yδ@}V]U*"\[Pߚ7M9Y,9K`Rv`Tv 14u\j6+]m2} d? ՚lT6wx)tK*$od_[Z"3JZś͇9\veս_]^M^IP| OŸ݅a3N*;;)pa{Q _ Q><{Kl ؍ozzul1]Z_3`룧 {|CWfQ!7&hVƲЕ}8'ֆ6Z>a@ 9 tvDGpވWĥjnC2˙pC;D~*&k4Daݻ5z9QNHZ_7،]JV _1W F6_6jV N, (A` ݲXDBS⢜uY P6z)- ǣoKJLNCvfyZn] 0 wl :; HBbclΑ+|-|`婰p!,H\sw G[4AD)<0Dtmҁ]`/G޿<) 7now,R9~5yybUTR(ߣ`tJ*(.tqe`e9pa. em>RbPo'$ yEB5f.fR~%0pw9g5yO`\Jy}%ƿ{Pr]uDO: [JBOYJB*4rܹ=enoo2џ6zKt7am2,#5lm7.]7q Q#rP GS\vij6O&>tae3iRHkF\n|۟K Χ'iR+dI}p+=Cm(t8a:1lR!W7? ,jO/T^ox j$GYk7+K}m\_ѭI#Wp7G͕<'fs99zﵡ%2 G })ոc\ZHgʃMzבF"{Ffi~kJTZVEgݘ`K #t g?j~Wv0L?YzOdηagInv"vTñ[ՕvseD҆{2|[wu~k ;@k ϶[b\r' 1S=r>( CJu@" )(X byc`x|jG$r (jx`_̓p7FV1 uwܻMzz!a b eQBIo [WLu~fCua//֋ƅhPY˓ | =+H6pÁEgzv%}"37s2S}`y1.ȴܰW[8ӶȘ}kcvLh-4|=|Q63@;sɠ͞{35  Eks@- `\f\eIuUfCRZv$ʕ l/|x(^W߀[z;gX K=bIԇt6k1t̥;_ Y N09z"aaJ Qmr#S`.̼,<Z`8K JW (kɁDJc77=umf Bg+ (z/ tyYk[DUYۓw3s6)##M@ ksJR*o@|?Rj ^o$U. sYp|^|T$leD)@@LJ^ uoXWhK`P6qB]d{B4EXo,T, }^IxԨ?ʼn1}B dBMa0C,j0ȂwXNFf~E 0?Pq' >zЫ&18Nsٜgz)'2ؤG+Kus3 l|ݙ鶮67'VKDz +dL+}ed/BP{Iz57@k-Xg}_ JpE V7 7QRIu^3XIAZ8!soŲGJBt[> m8WGl< Oy,GDVTR>uҴ,ݾ5sT8Mރ@)$6`qA]+?Ĉ}}6G:"ˎ^^L@@btDm$)4ۮSI؎d(!$p1ezЁVwCn"(Ejm}Χ2pk+5ap.\/g~Tp&9F^$  𺖹V :G%v6Rx<3pT7pU.g9u[V]-D]mMۇkpx}y 1ַ6 M%>Njy4r (39 "Mغn/N- F=Aj$  μ*D^a` 3a+KX_ G(B2@_x#HL¿f89Mz l[Yvo5F3{nM`/ 'vu]5L_^74j%˛fb=' "oYDʵ|-"!n6˛xFB`u),eoǀTUݩ?c ښN n qCH}.7ܝ́6:!}6 A }U g-M V( @˄%$FnkTBC,qdkt%,z QF2,W;O&iHy^8eSkgP]H%!4ك’ j6 YdePsg(5n׌`nFJ"> q>d\$;~{GKAB^=Cqlmt> ҙưirG+q9݄ wUj hSQ3FZ# 닦,haT)jF&bG3ؚ{iCyyXsTpZ&6يq:coQ4): \ C.z{DʏECs*g1vkBk i",3 9O߫uztujlv t5PǬ>ޒCѬ?$m}܈ZRZ->M.Okψ` W\MFlBbJVUzPԡm}b=&$2dLl4cZIF) !@:r=J!dM[AE\ۙvdh \Gih^$RYrF$BȪ $d=( 3-,{Wo;Ź#]\TPAFi4 OҺ'g gqF"> =8`;O7̆F]>@NYMV́_:M{P@F\w.FUB1ar򷗱1O9pGH҄1Gn- c[-2oi@s- aYwC%рllxrPIFupLw.Ĕ܆ҥ; 8FW=+E[}~FM},i6t]4叻evhJåM_Y5yc;&fV)z|wIós70epWXby\濠r$~GŨrѺbhޕ1'ѻŭǫ ϱa}ep}(؃f_tr_"}r7,>3%y1Jxf̾܇a MU{B~S\FCT,*' Њ{F?4[*{: o},ü?doݬF:MP!ڿt"_P%Ha,7Bqz jc9F4$dڶ4{`E$ .SĀA4e@3kUwqUb7 9=i,ˏ!3͆ "oxr^] U%ܞU;KjW.N[@<h*E ƟB 4/8@BYΙN7R}a8(T3.@üDu8gw:S@|*xS>|re޲"=k67rrȜжsNSE u2"љMi'MiC #D0,]UZs<cAF UF)yYƔ^-d2+.gvo 2>-qUkSemxp<06X ("9SxO#H ߏ0G 4|\ 6@GTӤfV䅍\ bgo\LvK Q%6Q Dx2ia\.cwgK)@/OL+;>!.nj;מ9pG iAa;E HkX.TbCA3ʿ[zâe^3;+gKVO+uX*w8wo%L!KuG9Uo҃slQY1}o]wmne!o+I h8y>e1[kYdW0Eؑ.r߭{;4;G|eE BbRfP K3ކwߐ0 !cP8%3=GVhK h+ڭ"y^ߞ#-G̣[P&ws5hd^"R'+a}_uv7GOaƆ Xb`u A::z#zE: ~wG>ķ&-qdt8-O }59zRx)#/pHw1s<]YF>,J?opϙRȆR'c4b*OS8e+\xrN0E ӪQEu/\䚖_MBKnO >o KBAڿ[eux(N'0\ԉ;&s[Bј^wǮW ޡ% P>sJJ*u.S$]3"[cba`VV_E뷵|SZN"YkS]庎?dzV i9嘠j v$75h> &5ip9vuzsGHHrMZ:xBo>!t{/PvVޖ:TG@1=lu\X:S\Ah A}ϙx.JSq~8rϾw@KYG~d`Q*uSZ+s܏M*|>B_iw,);]wNy8rԤCr5ʜ;%Za0ٲu];(%|pAGgTZӦ'-kM7iR͔'T?93gbPYC/piWOu7vFĴ aE֨|vqn35+#T#(ÉUE~8GT(;3'0yMXY h>J!]ot'3!!i༨R}__gͻ3w#y'st8}Q*u|t}V&'CVY)xa)/JeVjPTIFE^oNfbL@>V'-B;.aO^nNjc!1OiS̱ uf|l>>o0%F,{iaz'"TLߔ ud+nOՎ݁C Em}>(`eX~<}򐪖ߥqw 6|cp<:tXn{ɞ{<@&sJ%Ç}$(8#lU_&}K?v8;RTgv9Ni*)oPXg+3]M |wmuݻ=0 ~WM}imݦ/\ͧ͠;|Ϋj`v"Ծ1~B5O8/[r}i[ $LU]ϿBЍUM8׫ P޲A *Ѫl =@9;|Dڮ^+{?v~? ٯTC8~Rɏ0^w6b?e<?;ԫ/+$y`Al));nQ? GC5eMUN}Z [BrHҖ?A?*rJsR0O(0 ={& v;p uDa~j{WB9 NoՉڂ:o)J{̽z7.DvPv燦ԇ@e[l@}0A)$DVh 8o< R"KrG9FiHHɡG9#ď3VBl"WuN-.̻H%f ˊ$~TKaww' ?ޓ"A# w%9Ԉv]d!t N4vt&|he7̻3z z09jo%aA0?A&<@+1߮@lPv9Wݐb 5XM-Gx}y,=v|N2dhסȴ݄jCh05&y*{MaM>~JV](_-e+*//cRm妾JsI-Ant2[T]~-Bqa,DC)h:Ң4&a!KPzsrZe[S&՝SXwJDi${MO]{wY=VgY7]V ,۵e{\lW&G UH bsU,$Y1BgᲑnm=ˆlT2*ψŇRlTq7#a)= 6nڎYlDSJ>9$rx-mXGpv,.J؎wᄒn˛3oӯ5 e=t*t ]8B;`P&(y'F%N|gu*tlj3 8YuHNRKS/>Iq-Hųq{9^]AsݯC'y"\;80éeFkRVQJY0a}: ~\$5x9EݣQI}+|op+3HQ5O byoSZevn%7e? v8g7|7FE/rhí?W%T.Dt%PҐ|Wë.(]]R"W\ilG?mo.pKTH`>Jg2b,atqMy(HK]/PC{%Mvk;hs<кfg0>n7C'RA,,"S$hp#|ҁ`uY^|:a-(t9Ͻң毽(5̎Ju͊z#`_e7W*.(b|E麺_lQmbrLy#,c7OR%^Z&rf?}=Eʬ428hxMq^_,Vj=5*.֋;`H|ńcȁ7+o@V/ֈXx ?]̧]nҎʺ_oZˠ< D)ԌDTXYfnKtT8i'Dd 2 #j#Sv4Uu~{Gh.;^j/8 ġ.,ߢ8Zk}R|W:[9xGU{)`T~ir|_R_`6 x{jӤ$G[t7$o]hOpC+?<!չR @?TH!k͓~F4]7ˉS¸V=: ؽrp-D!i ؁{{v+'' UyPiط7~<"25s(ݴ~6T-ù"CGkmԍkӒsWkStd~pgĻz*XB5TA\^ڙɿW}}4q$MѨ㱖tI'tvmlE[΍\^@&|_7t·Fjkp 1IM]E9Ab RG\Ra;3JF{7F䠖K:.syZӲA]'}JTF/GAs\NA4 Y؎mvdW>|7y.gєG:+%e (iqn9\<б>wDyPN,n]s&ӱ}*{SxOvWb ; y`ɫ~7"k '0>aZ1{捵MƇ7AG5؈~[𥈍c뤻, -76Nk ?RSԅtC`z Tm3D^Z_2$CH1_]ԇ#ri 3o$Pd6flCrSq!!1 !]GO()#=.E>KI ^/.R|WhZc3"دD= | ΍ Pn4͘2h wk(,a8J׊G^ˍu3늊X@=ѩ)xoHAJȍB$4~!RZfՊ*sRkc7qc( nL|~ҵGXҎW?74}Szt!(:X~ͪ4kQhw8uoKeR4⁀vAuj@'{VZOLJO`+K7*~'5D @Ô<o9(wP֚ к[Cul+Y:CCXL+y*w _1 0t@' C ȿ :ӑ2A]t#:ort/R2+vvOB /l90A#Jkh/\'<;ng1Wu xD*0e?[c+{1Ŷ+*?"WD#X/9=S7Ȏr,N@T\"Dܢ^ EFSwO,8:3 bN@<(`:fGAMyҵ{& nVL_֍+@i 7* "*e`-" Ep/ 8H$b=51,7AJ)9ft#1~ĄhbZ^QBec6EP_ΐĎq3K{G/\1ACqYX>қ=|^٣>#= izBswT/ k٥‘J";+ ]$6ßoACiKfAyh<ʴ$Х:K>i_b4}=cˎ~`<&2}%@Ab8^+)$ dҶ2Gx0p]?vνt੾coRHjlm=y5G4_u$Xe:/6#- [`es1`XPz^Y ]әO'c zD)n-(퍻2DlžOHLqK{Dʀ>l|?9@ZX'6tGu2' LȺr> _\U e=K:֥}b|(4nH %7lFoSGfg#-\7X.=R 8qp+5 *%O/JǺkb | 6v-iH ]i%/& %D>hz۝I{! T} @]:)ᦰQca+g~/s2KadeG^{e W WÒx%d5 W+N)ʠDj+ $D)塑qeW>o~PZpH:TP/Xi56\"QlԔg0uHThBk&ʊAJ@V&s3*,r0[խ)}0>4 P>6'r/$JjA>X{z%>|(Lױ!E\ޫuy\N_OyOV OS}{h.жe~wy*AtK[4VU,?:2E,l:NPzn(I.Bo?;TDwf<샓m-1hɋ=Fm@p&pّr `Ho,-ˣS_zҢY\aq\VaP;*e" L-X@:;dъ:܃Vz7D,:4,psuOf=;s0]Q`pK^|ϳ@wuH+<4E"wLdrtTW TG3=o^-ٷ"s6! /"||=.ioⱦ/iosO1DT߂}_Ӷ#ڢ -( "l "xATWZ3=kaCCCDL?r̽.g[] Hn|&}`+t*ָW Fe ~dz͋fdh52͎yJ f~_Z(I'u%nf@E +`%[_o1_/&)z s&g,cWB+yw?8_UILxc`lN0Q(>e ?sYq_K{d.h8)[ +w8D:Ä~ i4Kψ>J[#겗4bp #{ȝDԷv?{y \Veu/ ASRs>@\:_?MXŭ 웣}nz"zxh ARœ5%v u9 7א۠w l :ACeL ݅-#z̾xZத_|0m=)0>‹5M^0SS%4EGz=$yq|o7 {_N^^}Vʵ%Kz̚({ ]@&%&{Rb{y TAkALbH DdB@^fK^PG)Ov ~;Gc{?Wnsͭ|JbK%ɇ,ԯQ@F-+`x|WH̴ok,),PׇޝJ] 9 r3Q=\HH5Hf8uf> b:bzK  TFJVJ~7 jEKa#$XUȗCH3g,/A5nͭv P *`PsNPjYTtY簋+uYIi$D~jԟ`ۺHZJ^ۘ$y.NL]<7-erÉ,0:<^iw 6RXnNȥfen1mc6ERw:8ͷ=D+ОؙIUOg7ׁ\OT x=gW᥃TN 3B-+kt9phkPTN}K__Z7nqva&;+>C1Xmm# Fվqɭ<%1\e(?wģysD\=3܊UKxv'rWA#)! h~/< P¹pTqizt^T CZ3cAX9NwPʭ:jm'O9*]=n=6C鮧 9 mA+%b# ͓ZȤFaSZ:/%Fnw(h Dh95DθљD5C.FOt+9C8A}Akb&k᳒G󺏛l @,`[&PÞ-X!!iǾ}LQ*߷ȗR KpIF s *\-徻Y'8;HEw_9rcD[zezo0kՎ_-c&ji[PYqb^6C-n>,7m4X O 6d|c_Gް<9W|%OFF_B!42@4`H5*oC\:38S@=HB'lLP׵O .y(>W&>CՐHYLɥ EoAѴRK2Uc̽.Qʟe-cq>| 5t2E.  sJO oٰ(݄k? <'3n|WNX{i!"R*XG5O# 7*l<6H[tq眺khP%}{EfXôT Vf+U2-du'U !7OA I S3bfJ"!w5bEI5wpVR۳uoZdy> -YmiFZJP^WAS "IrI= A)0?+(K5VFqN\A5ov \ar2I\:81.%?5%!OpD T,| gFl M=wQ/X! &Cۃb5YL,mQ|@^}ąU-nc+j)^Z*Ө ?C aSO(vDl]OtᎲ呶sZZV[ɎPuUB&D@gW>?o}sq h +otܦϤ?U 7x 9Ā;oc2H,)(va!̔O49|M &;tr 6y@B%Ds4]ړ{bS\]/;JIp2g(S5^q^S$BF(^##!y"S;i^"fj!0t/K UL~?F@mߐMlH~Lp{6F::%lO;;s]m8!8+L$+34ϣA郺F4gPa24#^`T_5~eP)Z_A#y61՛CJnů1r-+SPCI S! ,/)ʦ'/B 4n%L8mŵ੤7J>_)X}{S 4ϫ?p:;9x ,8u-%f N d=b@h vWYZPV&;IuJbZ A9!JNJtj/kޡ=*%Gs2IO~D.Hu:3`dgU>}Y{TLۼ8YH!@\8>"쌦z/:"bS6)GkE}3!˱ys&I 5 ,FBfv>9hqx?\ l_E!FKTVQoA|8ƕ4~%@B'~;]ӂI `“D{,ê7g{pR'l:`{D`eA'3Bt\\ J'ͤL_/qQe6 y>_R=D#kgz=غGPmt̏3QWE7i9uߕb~%mwH[^{M^QR4Cl#{GqNaj âW#2 [l@.y ?vՈ>ѫ69{-t~qhh.7^\Rr$YlH < yaoɠ8zfPOWBUw~>7@*woB +#w9R% p#\2OeyLX A| ANMu1 Vtfc/P.Я];\٫ăNlTu"? jߦbϛ yexI0aDr[`fs(mJe %RfUUS*ZfmDM0RZVß#-s˗Ss,%yʝ\l]L~,Lelu%G?P9e4}>8_ٳ;,ZRٽs$t Er ʠcP >Ⴜylʻοȏ$6Ů ]!c dOR= jo?wDS,Q;AYfkWig/:րUtm)1Ñ"s{?dž?^uj>o-xx'/gSwle'1 XMבE%" 9Am}MCYU71T+S7M6?J}8o/.͗O( 5Hhh<L8Y露A΃EMFo_e۾JCR'? H<6+n6?@ײkdh^)ٓz0GY6 stTY\@d*wF݈IQvh C @ ~7z{dc?8pr:C}DFEԅ7<.Pﵜfq`G.hfp(RhA^Zh5Jv3v.aX y7ixIy)ԂG,=huA#8p}qag4\@w^ǿ_BcsNW GBqiЏ!8_ ˨@w+ׅ-ri:y:ZȾe 4+x9Bڛ2_Pka)vHՒ׵vρ WoT (4v:{bӚB#0e{y_-- C3 ]z4lrf1Duĉ~@r{ƩC}AK%zJ$I+{+cif2jl3X@97}،MUzeM%E4\LP.]ۦg:;&ǝ6CΟvKpKCϐ=},K'օ^ ̆v/[nމsG3[`PWĽ7 -VeI1g ȡm?|#=*щn-g,ͻ&lw= bc Jo4s52eTZsF ^ #%A T0-؆RX1ٶvpm@h(/ҟL&5ڋWg\WfL6 (@^˖+ݹraUXN/,+Z;q,:D({ -'<^xVп&]@w_vR^R"H s\>ɠh~ +3oMlH|a/5k cCRY+D$#8dTOԀ|swvA˾Dort4:$%rG.2V):oV`/e-vg߮wk4 2n|_jpUshͳ D)LP9HmI1kJa/gî4mμ[PmzBn:F8━>Xs4?=Ò; r`˵ C%RXazi?8+=昝R(i{C JWHrrQPRΩ%RĽ!u+S2C<*͚-chmȌ @V.ط襃w9ڔ67>n6"wt>;"Gq'XhKA~x;` YKY"`SJJᾖǗ&z 5X} \P:#!22PiQ-tOJ8K$ Xht䄉G*d'33 Ao8졌XB!ȠGF˃oH`Ef|r3L`ET.uDϼbjVFtB=ahsV5E%w6X~expxG)T%r2#9FA+9+!v v}Tݻ~C 8,!ou1mpzi>r-g V(}ASB@;ZͿԿ:%H]"'O'C q޽ZrxN8ZѺّ+!lm(b*XW } 6+7R'L7޳vgצ֣ DP.c=֊Db/ bEL\jvhᮝ» N &0GkÀD'wt_YfDzڟG7 ]<_຿ʽ7v6A1]$eWp4؛V~]_B>\mӮs/J$Nyay9Z2j>ܽ!'@~6*We#SWZPʠV ڏ$}1DiyZm-B`a0Z^}-7MSx0O6*m=1Ce W~T >F&kƓc@V?:)~hPHo`X@$s  `Bz,/\hc3W ;UQ8d}.Bl^!\! 47NH^^a#{ȴ#Z]p_kMط^݃¥(ܮ2ϒdL.=e|G5 P Ff:_ΨqhC p~_mcTõ߶y|Xcf\x8 IQ'.:8-ֿ_ESJe=>Hw1䅭elW4n`.O?onf>3~2%NWPB@z _~ٽSk3L>7HizJ0@+GyPL%ӳȻޮ[h FkHB~O?^>\qFX "P¢l,(n`ܟQv MDMIHd0+ 諤;B&}fd#nV9$\ A̧C 2={2o}o>MX~aԹ nI<9tajS!6d铧.xB.ĠMgF4(ߓY zi@ -Al8?rjC^RRsY)Jy` /%OS2@r$j"nsn=f,c˕^͢jϦy^ m^9#UjB9h IE tYI\"!-* e OmHN}a_.Zm+rC8\3f ]EEZ \y 7ޏQu$ 5v!*IuDz G>AS7\}[[dAx޹/vڋ$+l+PዢЉhoV=~\&+(G, (]c@BY,Q*olVwR-4)٧wRJb!1523WDd/Jb-Ú)(p,^H9[6UT08 qɚh  f]CBM|/t$Oɬ!FIOaw kA25lʉob\-i&ƭ#F[ iv6h)O\vXQ.K||IM'ςd/$̈w$I.(ty"8iyM 2}؈lVڞ{UG?5i@C@w^@b5wS.5[Z`vDb Xd/=ICJ̛' {ʗ~Q|Z`z >QK ӯ'tH\pgvm *p.wX2,?~\R&dif[nF/nL˦Geadnk]!w䚧zk;8n#oBzRexpҦ~ݿr kPxd/x 9Q(8UX: afmj=Ob_)kKT(%@Uv;6TSI/9ZKGmxJZj _܈7:S6B%Q<;'Jnae`zj ^eK@:Բ@Tdx{׷a:乺I^@s+vgvR [ HBɺd\'BeLJ!(V;"N׷ Tly[ GGq_;Л*1ry)o;1细> }tݯu@y*%#PO1e Ʋ Tb+i!c}8yԊ֟>mb@[`;e~s%pLfV\q%M}]?fYm*yV[Sf9 x ?W=I?Xɚ mwcɎ \@\pJʅΌunPS&gG5K^~p:puKe ]{moa['{2l{'h ֠%. >up[x҉)8W+cd"c2ˠ 01&YjL ƞ_im5߶Q7#|ejk{>IA,2'2iX| S l`nYɳ hzP͍*vSnoxݖћH.V=Y-&Z:/oz!ޕ=d"=z|N E -6YBFg0xf`2Srin `ʁ}$tO'e= u竚{Kg{UC1u sX^PެN=rZǶY^|>2ӝ}j _ER8ʌ%RAe:CRU./*< Hf; ֯ `C_Ą9ƃfrk9/̑Ӣ޸Kv0';PО ZQ(Ɯh=-\ JsɬupMĞ̌\즒8} xRWA_>8`b1:%Jj)@_p *~Ow9:[}kkE.{t9=L] 7ŃoYf<52G5? _KR@vWR(޲A9,Rnf;T!8 ^^AJ؛ Hcb"u fjX*C5Ռ0R \~Qq,1.ۿ*5Ӯ#蟒NB'Y}6@ 4K =gF .w(O^wbb{* f%EރTdd&Y@HVₜ.%x$AAsOݵwU޵|&YsW_URS?ZJc|*x>9Vղq,aX5UƐ| ֛d[[x9BqĬTO!Jln%56fM|X>'z-_ (DݡD -G#RV-)ox=>Xؖy`wkX@b}<z,I¸LX Q{}9݌b??32GYI9(`;pWR_*g;Z gNs? lR|Y݈o5z K}']ͫS;U1;[&7ƲZVT[0ZUwjv'v~ ҍRī[Б)jmlOpxP?@~MF:*S^ƹF5[:З_hzqE瘜i8>{ߑv%KXuE`f<$,]7:?2kY=T[9|;, .rp9_Yv)Y )2YO4NxPpx~Li ֜":6|[܃w 9A-PV1]1}G;zߏEi3L [-P"*hoGopc8<.oqٔ[<:JkP7p }VY|P6Xmܑy0yh,K*ߩ#1nOU4w_ #ׯS46ɣ gt^*oxaF7diyBvGD,2=0!nȤGOtPC{l̊UR[>N]p虐,v#fPVplɑG+*h6Kb\P+{;`Z|QmT\3b{͞r9Ų:F_;X|CewBER~@cw9-bR\\5wcC*9_ƫd=z5Ƙ` wrۆH(bt)|'4gg;& gd;)b=-;5Fj+7VF^{iox%o/ "3p_cM Nfq>n GG7eƊCG8沏TǨ2ek?NeЕYk!=nm;-z>A,lstw7Hˣși 7A:cAbI'*k/PMM(o+td%H5MZK8@0!NS ˁoybA'ۯ>^DDjǾl [JF3X4Y<; j47y OkK/ \sܢdlWg=c֤(~,0c3T[6=/|o{_LGW7-2_oز)ͭ8t'adunIm5IO{"(cJ3}*ٮm|_kڬ0ߡ&x>^@Šv k|b7r]1{tKH65] @PiO<艹 F~yɯeeQ >E]\}e =SRf[qb|Q=xjclߵAl; Y/ۢu#t%3.EBkb=1&]U&T3?dvN"k?fҮI۵"cnw{\>eH?o,usrM$= -PC;Aqos=I$\,xU+ʱ0NHa_{."Py ߌ#{ 6U7r.uw7YC GQ@x;ԹA ,`׽& Di̴پ.dq`]GqzEֹ]8ȑ͟OޞX !hTix<}f7 @3dzz\[z{Hw=̝iK8Xd@MYݿ0_Q %tf A]do j8Yb<*sgQW9ž5/|ᚁ3N-;H\ה#^/mZI4NvapףS!|eIo1\:qpD{{w(J(0 MoGLm8fɷ⇠u.[J :>α蜯ʗ6# nLTJ\~`.N*7^W[ zAϞD` Ecshyp2++Dt NkDdtȓuر K=Ja-\9罤Yͮi/=<c]d4c3C2 긛_3,¥>]-}@ܝ:W-iϱS/?rߤ, S[Nn_CNLPl뺏veNBol\y n~<[-ְϗ)2ǝyL#ƴȘ/gy6,w7jTo}xxi[N^Ѧy>ZQ&0{9.o; R9hV}o1;)l&A\!cL=.{kF> jX?ΚZ1d4vES77_K9뒿Eis78 \/Ac{oީEQڽQ֎Y礻ϳ;Xq dut)nطn}$bFuղv<,6)ϗq& lӂ͢{!A`ǒгFqGʇr}9x{GEzR6fFR:9"f0'd3P0i1:h1)i> /18|u5lpQtP٤e.3bժ)+>o._oF|$^FJAMzDyB C=M5Pv~p{(j __ZRo ܣL2d2# kbn{DH{}o[ºIܝk# ~^l_H)=yH햭Lm矦)!尚o 3+8UKXVLSV%'GH:ch`n|p"1VfOm=$$)g; ieCF;I%sc*`]?ٍ~Uu$@DɇK> &!dYOO|47ZYMd)U?EÏaC#2I Lj%oCsS҇\-#EamU>&v'kfūKxVbJӜP"Y߲߲>K5S; :RTj+R27Oֳ! V9օ"RLJ^D: g(cej-~H5Xώ^FY8ޙyݙ5h#Tbk: ]/^UM Ov#+Il՛{Ο~{wC{a 儖6 .Fj֧ ?'Ur:[B̤tͺh>~+0Ed'GA+&%d!UuU6vo9Cq8[bP9|1WnWK/cǙl&ͨ<&(MRf]/:܂{[+N#)ī<{X%{c~?i![wƭ\+_]''Ac|oYS|.n s)'na|>({k}'g2@x.0̚вj߿3~)'s#8H;'[)+6xhӣbWfpK!z^O˭Lqa3I@̎Mϕv؏ ԣGn?W{0$΍&E;ԕ]kMg0{nzG jBs >5Fd¯v??M)<`nZxXzn.bRɅjãDǷ*Շ4FlPaS`Oؒ1Cf._4_ms[+ؖ"C+:'B?r!Hbzf|VP^uc9>]Bl N?sİs/%'̞yhۡ(Xw@L:63hQ|Z֗O"!^yke}ֶGS籶_*}g2DD8\IlZ&k}~8zJGeIU6)~b{otR7vѳ-G6~|`sFh99;~6p{HpSl^pO%qu;{g':#3:WfulNܵeN1龑IZbmʧtClhG){>9N̏nZ:=\|u-`N 9ie`l}!<1gcwCƄ7Xh5v3x^~L{:W |LJlj_E߬(5|8JEoXB˰O ߻# P#nH@#[ebj2}H;|!u z<Ӯ" ,(+qy㮏 ÷Kf%ݝH{RBؿ[/F:E"!PвCLwH{:ˉuf7xG~mpFw0H.X:Ee ? K2#(9l883]aj-VYTud;9'n',8|14cD L:.>d@R7wy{ImȬi,,/$[<})} x=@MD_9u?!tl}GȆe-ix?w T^H5}XGƒ^g-k0K`^1*A>,.1zh.So3z+W¯OD|yW@D茓hd@߮ ^ ȕ@mƈ~c@˫zT)%ZPfEkӑd}キ*1n=A$F e.BWӢͧD@AZC4}Ol_E(!_jl@}Q$2z#,΀ ׭p!cG&nz+|E zݠRҋږj~=vb7A}cz<.O!~e[oq1VQ܃Kr1{D=%$Roz>ɠu:>9ҵiˣv{ʂ{9)hX(a1mt2=sSw `҂m WQ֠߇BW!?y͊B7UH3o.Jb4Cߖח.Yn!V 8jI8Y~v_lAȃ;2Go E؁}k[Q}(ʘ5f͐Hq ) +;jW^V@g}{ N#}HkwJ@1q^To§<T؏K>JբwfX\Fk*Bo<Yfb8^.rx$ A  (i@n1(9:oК) r#[POXþ^^ʂ(7H]pa*%Ts5W|Wga}I2Rx H'3}WƩ~DÅнV|'sФM,t"֧/K9{Z ,0%Ŕ7h-TO#(7J o\x@5DSȗ~fzɧ(0y4CIHDÎ ={r嫘7Zy6"9Ŕ_Ylײ'OD B`{/ 2.7棓@l&zϼY3܄J'w)mNY;j=337w]ݔUZ{m:|2F,ڑG"_G!W,Rlv6joElJU}1@U& ˘8y;ںuXIcZN,nd F|i}*-˻/+R,I3#2AUPvjץ9։ZzD?e$1dv;%F·mك܇ L5)H| X8|0}̯$6SmWLxQ'dȰ>u28]j{/H"I]nMn 7H6߯/!&cpY"$\5k\~v\G [9 ig8z9l0a׽FJg`ͦW ĉڿ3]l{+41m^2WLj)~BS+9l5Aѵ,&4WaM̷>1:lqg96Pvxú6 O-aGJ0΄jg0m=p˟\p/]5N_ ֢›IGrZT(?IC+{ixKP9 ϙƿ;<:I/yP*@+ռ+\ѓǩ%C 0̺áߢs6>&@m߮R AfB7'MQ"AC6aI_ ı89Mi ߷EG8[QƎ&0bNO蕌i7qm/X٦MV%=rS0UCBF`$Xi`q9YlhqtQP$^ƽo'J/[oAoO*,dYEACڨc rz~kO xW-x(P6ݞӈXY|vm)]8* CvEpR(Aև*,ѸX:20|Bc.IMk?"\o1iyJIlL,Ǵ[YOL1{>OӃ G D\I \f06K"`T} NbeuW}I齥7 5|]W2׋AÑ4+'k;E,ϟb+<^uXi1ݯByJ!B ad_C2{9a榠.2Ͻ[#\Ͳ f#Crh{<~Z~5GDOӽF@nF.:/A_LV,GjǨ(+ڋ e>Gp @P}eU٘Ag n\٤ů[!op%k~YY5$s e`_7Ǥkdf5|[y_*b\%krtE-u0̲fi[is# QX,bЬe5x+qDotiK؎"l咉5 4dE[˦ `?vQ%7dRCOe1nPU4{!*Ջ+FnY` l>mA20v=KHtUF Oիͼ4Km/m0}U+'\fJyh\ SS|`fNM:+c&z4P%Skn g,+w@ s6oqgv(YE^ ^N ֤L$qMoHoUO]SXu*~BO^ѝEXIk\@8Zιn6̹o[05f.Tkc*4ShBH1-[ *+K|IJ覤7O cLh% X|A 6 lS3oP# @`H >NZ;T]шdѠ)\Tͭ#<ڂ\Ab*gwAȾ,3_9l.9xL?ars]̽fi!`U.iڝ#n1tӈه߮Ws Fh:@ܙ~Sb#W$W"7;Lrb*s@dx_X*a_Uh] *T%^@q`'Vj~N=DJa%(or^ڛIDNFw Lc,~Ur'Q _z%{5gt  ^GnB6c5ޝ "K#@#<Ӗ©*@Z#[4H|mt󋿶mU&[_cS(ժ\#%0jǪR y2AW!nN;L&n G~P&x zѣuߞFY}^7OYDg"mBnyOQ%iIEP+^kG}t(澈Ņ0ЈC;Y.qQYa"4E3b^Lu]<j &{nJ}Aq*nPb8# Yմb,>$򒂡 x&%=uR =ߨaMr 2֬H,=t94%nIMqi\Tb&I%74h rj*S$( \Ik w>@93-2_a7De2Kc5](rGَ ,TC׸Fֻ Ykec15m/zJ*!pa,K@F,d4t"š;dT;5cw@_n0Lww$hvm GF0#V@:ᏹdˈCT|by뷍vWݝbDgC5>urȜv޶E9rl/6+#λDv^g ;V%*)1( ˠ@mǰ_;NHY c'V;Rƿ raV 1_ g.X٘0r~!ֺ6T :y]P~AGԟ ׂ"3HR!`;sμmKˍ@ ~1!|$Aߊ0^=oדI f zGR5~ZVa%I5!{aFKg/|ä-N' ]GDy^J'i'>_H1YP~Q[ys~+=<)ͼ V\[;&ƣxM%?rRt-{ EQ|]Ba?p %f3ri ѕ*eZ$J9~"Lr϶YԽ٠,E̼7rP<[kzz.DfI.)EjPRKXZ13@g,Zd’@ضgI`QNt{VDc4Mq_`7sW{S7a|$0w+"L*q~gT(xW,S9X-+|rfO>V@w[1@;!UkA/24Akms. &jwN0 3d xKzDУwT&BJ 欐!W&9_93-wK·D;|ƾk%C'ʙ٬`]xCԊFOTX:E ?D %GIw$QD Oz~TBvz^. avp~ܣ\y?B|*B\י3vEQHWI~. d+ATRVp1IwzPd0*ubBꝆPrm?͚ 8WV~*ՙof\{Gai'&p_i?{V<)Ϩ^tNGQ$ U{5rgvU\{3'awN`Q|x&rN ~81w^nn`djQ{ iR 2M=8q>(M/o3lQ>o~ǚHh y2+ Q%-\srǔxdo4ݿgyDr`{kfBY '|qYT˖gۚH9e2w;Ks~CtBTO2 ؤ9iH <0i$<|&$>>\rwV8Oղ Ov\Qzʊ'1*v:O$a<ݫ1W}+.ȭGHA B,3ސ)8Αa,yY*%]ڌ"RpӉtW [^(#}ylU}sI ww>|_j DG*' Ʈ£bq AddĵI=2wd6ܭlo jYm,|=Ǡ?fz5r~ :/ f">ߞr!$r'u2M=%7ף A,vpڃ*Ε^ÖPWc{b|m#LA B栊F$}B ^SW 614p3B۫#kkk)띒]_@ &W'O}>Azn]Ay}yaၽȰ}>]O d&1) ??gjoIoF!(S/Tmib~ߡ2!Q=pW|HƟd/ktBT V:wm VNگ*@+S*$YjR$k+OCG*9GFo~f]H\񇛽+Ynt@{NQ^9t'=htiZH4,_? Arwu#.ګӓ>aJ>%Η)xP%@$&w8!gGm+@fB#(,:`hؙ7FRc Y {YlC9yJXD\xH?! mNC~1YJ HK(Y {Ȃ ׸zy6ߚzU ,t WULpS,| -By=1t #"˴B%A mr KWč~t=?S Zթ** jFNw6ľsϫ57[-c ‡B-<~C&r)DaQ}v \}n+dh5 .ɢ]uvl!`Wj0MeC{)) g*x6 x]/oH|>ݶYvIҚQOܩ F:/ <2 e-qddϫ!9f osWڛDx@Ŀ+x /nu#JA|{LVg"[LĴ2kBn;C6Φ) F`:9MӋ> rBVOKh!+CYy/?tn.k{ )kqhGύpg,f{f|yIp GiĹj&yϪ)n7q;Eqlg&R)TO4|˿ muݎ CcH, }qXR+9'm(ك[P;D֮xA?P`n4tO5ͯùӦ/r1dT*07b"0g n3$a! "ת"]>_]CD*#r-N/E|bY3R;-@;WATSv(EM^iy>(j_<hG!BDEoS=wm{s sϋ`f= 3pqhARgS/TV:Qo9_`Yˠ"Ŀ[ܿ:7aC.3Ƈ՘N.=i~=ʴkHrElȿAP_ >V砉rH>a ?%Q'86w"䌅owo-Sm4yL(8q %)-5A~4Sp zeKO@057?YSb6["- x?@7\j l%_)9@ypݳ=_Rj-t}H@\Q] L﮴oIjsV߾"V󫂢>O{p S>KW=_תevO)2v6d@C}3JBaoI|i=Ƈ_70Fm11 Ml`'ƯB- 5|eK'7vp hV3Jm>i6s jy4_늄['A^+a=}{^1*DfA]x_Ohˡ eMkFwc`{rwt>Hڂ 8,x;f*\"EIJF6Cb6r `k7L{Ld0nQ51uVh>3b>2i&`Y$d QW,˳+|lCLRˁEl}#`tBP = g5uA]BUPTI^ܐz(8ا-g,5Qr7*὜7^>"ԎG(w9Vї@0"rYШW iFqzDݏV^3_9Avm.#~Nb &'Aׂ̘jwcJ "3q1 rڦ{cd{)]" ="*S H!/! IX!C MEA`ҷ7RKFe l(€g>]Pॾ]<$}{|~bECd;rhr#cl }bva=Rf9' 7ϓ#HݫA߯,z@{)KDqB u&8 ` Nf(R2]~U4$9׻om-?7 潩=X=۬pbġcUU͌ 3źKY2,JX' QmTA{fd L y͖@r7v)0`MfX[%#RI@%iw lNSx媨3|DYF"P5DZLEp$-o!q|23 Zs]J$\߂A|(ƽJi~|w'dVa(r2`WK.(yEe"v_))̎ w0{ےGmr9o Oyܨ 'ʐZ5; WªR^v Ga;y[&vuMU9T/&ڷ wߺZʹ,U0z}/·` 6Ip܅JNL=ko4lY^x^^Ǔ`8=t^1T *Hq[0R&l>xYz z<#*3y *θ<mE%&1j<IAxFZh2Lc?h{ NFȋ{tD]4 K€HCWiza4R>Y!h"4hh.U8^j <~p=]Z83Oc|ظJ_,'2 xF]a2:}%1}xmgэxe*X*nt"`f{]z %X_-ȅ[?}+Wjo +vj~̾|VwBnŦE-B 㫰ѫ&7 /xֿC~e eD06;Iۈ~)QE<|G]cO"~Erk?!2 ph"!;H6@N> lPɂZ a!իFF&e#zRcGZL2Yp $"/5& {kO`o[߂AM uBtA^>!4Ok"UC:=B‹~H_U-Y[ =nkB m$傹[n!L;Qp48iNo3h*$gEc  3ӺA!~]?A8BR (AoTD9~I%SX 4{'r|uL;\vpl3\on5eE*W9ݿ8hB6뷫v{"5~'ڿGh\AMrCu0zbX` vKT *()zK߅!}ԡR63x hb/ ~l:x SẂAF-壧'?j!g&o5ܡN_WN1?W7c4"H^m{ahW`x^ `fc6 QjYpoxU?RBGAZ~!&HP峟tbY~+ҝP% m3a,E Q 򶁒>Y̞D'禮24׿9V:XQ(!?Mv1cU;4={cs;Yy%ңt`({cB*@J":1yS_-|,.2fZ9g;A^!FY6+P nƩtj~].S*|6'Eq+k# ̫ay A|i<7w>5);sDGKJvvי/5 dsDK}.އ =gA`XXuB{"yArܰ=U}adWt)~}ytL^ۙvcr1ֻdؕ/o%:w[~$k̐E@[,9uO(X3/@'э&*gusC!Ph] Z>") H cV¢d{3(ZBNɷaR \< w?I,'TMXA \8庴9kF9l:b,bOuБټE;vi%5"- \^R(j@G;羌h}~+Fd+k_oy2 RG51W]';G!Ҕj0])"Kj>>&F P Vk+4%UKP}AhjL&_cY\&(?40/3 Uq04}#8xRvycwJ%Poʜz4 u(23Tdx ,]LbC?Osѕ14[AĮFrݻ $#-yE <:aW0i{W tߊMDaqĭ36ox~1"#} ֦sPt>^Zts\Map $\_2`~ aB@s|. 5T0cXE Is4X ̴WwXz:vCfeG_xW:Y9Gh9"zu#VٳPGQ3H4pBko'Gfhckcj }p#WƽW~\l4H=D蚃(/I~wn/#P/* Au! %1(<̓{5߉`%*@5iל5kfx6)dpLRdA Vb>fp[#3@F[|yFhҔ)R7 ~ }!BC^ `'lߘVOPiCy:fП+ ցt(?@Hm6Vu S̏qTtG/7c%׷*ћf%  Rbŕo[|o#LMoSgqESK~BhW !۝3uo/YH3ZElIP qŏ8P'op7ڭQ.8ϋ= #Rms9խXov?/]h2YxsBNPǎ`'ʿ vx Pk][Ne8{}]P2?"N܂i@T[} wFydϯ|bM%0֋_n\ i}'Ї; Ѷ@ɓh}9Ey⬓+gMZ B5,zlT++Z,]mHs#3I~ 4Q`tY?`"@Gr(RƟߊ>_HFRL|(Ը5*sktekmЅC -w'0 8B^`\Z|fdo9V^(`K6owy9IjjVorی}!* -q|uX aff#ֆsZk+n @Z+r)x˯h#hk)Ek9 pgĩ3nNϿql铰3a;ݝ|0-CT6ޝ߯-0TMdf34lQ5B{yu FS@3WXe {+w+KC8_qɛV7vv6e{Ț^F&[bWU;@_ꨰØ,bOPٷɧ.r(vv,Yx_h&ĐgPP/1F?F}\զRp,S[29P3?XQ W5kgğ1->i)wG'w`YzeU5]P>.YxȈl32~r-Ɏ%?8:SV4kr}l"I qq] ±Nj:wmuknC6-Í9h7iLpݳe|98` ab69z>A{q>ĢL `TBCq){"]%BJ>kG(opWT<'[O#=H1A3ۢ#jl1:DׂL}9y*ڸ1lLZsKA*77e.o t  @<"u w/xZ4X:"kFWe{WYQI17 94KO ,9š7;S|SXYQh )*7y-- @~O'?NpBIYλ>}nєl+PmC}E"w8l䁥?cJ6&D{Q\|݅ 諛QH a ܳb'ۉ pZ,B}>~bjx!#{ÿ7'WIMu#'G8S@Pb KIc4 r4I!qg9wz X*Eul3 toݪ8+>A @̀` W7BӘ)u ;`DO R+Y8S! KSǂ;s:(\ǧutٚ*Kyz74^Obt&ΝHoơWاS ?>ӗ|A~e}̿=v|ŃxFv\/ ߌA^)vLWhj"L5Ў~JnNzCt**ٯ~1_5jc~0;30 COy`[LSk 0&CԊCh~75Sn9yC5:P\{j-Vץd\ X³'cĂۛ]ثd|c;ߣÆfT{a_G3ybRX/ds[!]cnHT7,l(P{gJºN`v4A4"QUZY2$BLX4f廇5nm?TrHo"݃ m-Q:1&I/]ǯKثnu=e2RC%7l?<_C.t/6mC yƵ[>l^zw9LYS5L 3 Y pKwZ+` '  @j)v8 c fDB ۑVhqh5Pu$߯8lZuKƤۈeV&ܡ]%K0ܝO:$b-0fnKoLr4g1͛r{j!;uҪfzOP܍@{_"sdQ`d2#MOw2Ye-ގn&[͆]B\ H4CsfeIw-K:eo]ܒvڶd*=,!uAR2 "1FaRiE}Wb1ފmEVG КGy/e7}Q' .oD~I)8Z[#p*x^pE>qyZ-!$bR70OO*;,k[/t0ѝf˪yZFX$ƨ5C)*.poʛ_v_?9U6ϑ%̝ ǧ@,a<4-R@59p`)zS4Ry<@q}Ԩ'6 !Z]rVȊ:d>c/Mj̔JD?l KGR -|.ɾK[-_seY<]4R0=#v*?0t@p,"0\7@v:)ՁRy;p@ ̯gWW)?Gy fS;/y}7e0}Ih> _8a͇U[4)Qo~~tLx 4+*@}`hqh =b˩f tz~[Z^!%~vb3R "safۗk숟J1)i_p1pSz :J&{j|]qUQP?Y} qu'/G&WD˔>8uoRv%M#7XOBwd P삪Y^i PehDg{7l6`/=뀊'æg&{;5Q؝V M3ECl1t@E˞}$JACC@~I, = {_+yCNњjYc&Ń@@t^3v's+G(J4n}"~|FЮU:p|C̪R%C^|@廤p~ ;ѫ%acL!?R;,e'{g$ אf쯩WW7G'5a%Dfc#ĵΗW"`+([8h]': <$ ٟj 5|a@g41pbC#$if-=_~<1;mK_h8KL@{`!ۙKIrBgq軽/vօFNVZb%؝`'k_Ɵ8#jlWu3=ዞjŷKZ*!z9{TBlXm b 0Qg*eސ[~}K29uپIB}N9 f+gwd7u 37= cRd+1ѭTiJ*9ȪCz SChwVZz LȞ|xHgF92cqzN >c *WV=ݮB(wMO(W?HgSx[GnIAKZ.:WսPCnY=J H \[xI>ϥo geX4'ʧޑL#_6g>hk[~H u 1w)h=[;H5nj߸ƠM1Q:KiBA>MxW%qw+nV}T[ARsMg߻AFTp2D zT2: /QA P })Wې+pOr;A˓_gI-R &h BR=>GQHLt_s(xeeq궷g`gp _WDLzPXn = HH Ga$OWs.E2h?ƴT &ρ9F:mt)5S.:`6>Z GiMXz׾3h^1T94 /urEM}S+ˀвZ }&r|-,WnT?C˯z{eUZb>bR~k|ݙ<^2ڕKsL@y;RG|q ,' _i3@9i0\] TTkJ+@d2Gҝ_pvVOwPZ~զi*Ò|h8fH&Us,/34QR_Ux@@Q4fI˦L7Iڎ& e 9P x"WSszBf=,}$W `_7: xio&["5T7 "M@yPh#mm3H= ǢLTeGY `!XEnG-SZf_j@{i΅XwC YOiJ[a~z~ڞX񙧷+z5ƻ5Ofy2U=^o@ 4fcufV7+ <kJJ&"^ cb\|юkU_Y O)@qWf@h{/>8#5N^o}i tb`jGJS](fSrRM@d=oQtL^N9e˥UcFZ iG,?W{DufC^d!{{ʠFHZTw<݇oT0%pAt8I@2W7 v<ҦN۔˯}b<*HYJ߀S^BM {Ԕi5?f;$dmb*6MUfsvqu'e0( YĒdB:Q/c+tٔU  @ӓiƒ7I971 '-v/eZru&HO;8@wU7i[#; xmdE"}HWd콁V1c'FrRݲ 5l4j|@w!l3[/ <]V\q蚁3dž,k͢_$szڋ[ξO} <٘.Z? [:L+B >s~Z~k `eV SJڰD.|w;Ǫ !؊2_BQ)EkEmqӂG>ت98 A5U;l(CO,aŗP,7y[%k\ (MPm^Fwh9q4Bwn,0K*WMl MEߞ%ʇ ϗ`EH};\qCUYvtR 5)xB(dk4Jޕw~ĦFc(n^{z?&~96duaBdac(cDbż2fb8d OpoL[ޚ1izk` qP>"0A"P؜z*5*0<= ^:S b}7!i ugB "E} ; zӃwQf稜9\!OTtv!^Loyr!a(SC꧵!f=h3 Y2;1Eh†D+?ZiIQ<8٢%0YW7h8C fev`,@Mb+J[EW[d$p^OiG{s"0Gʣ{nرXgL-\ZGe;d1FKp9@"L'Oџ$_D*y.}ّ4_m~‰QT6gީr+Ywޢ/}wm!YYX%ۺcz6a0=ʹ]Qt0c(j|; 7hY]ҎXW-*ݩ/zXz j5[=A3CוL-|A{q{Ɍ bvoNNnNإ4^[XkÜ?Dx} (в|;9qG}êsľ-xLiEU=t@U2Bh)VЀ=NzP@9fVj``p%fPP'g5Yݿ Xo4c'TҔm@)xc{̿r] xo:bcF<IsJ{7M}d* =FmNr;,( RՋ'!mDC˥!2*r1!$aUI%;@*Rc%=WLX*>r+Rca)|?̺8a`5g*)؄xt/2br0L~!fZESsV }vX9 6ӿ_w?o!x9+ u>Kk /f([_inL~`>,;eT>YJԌiٌ3Kv1CR\]0|v)G; #$J rEB5OP]RN-T$7hvs@iD3'T5~'%d)'셣^nSgNČඬ !@5Mbx{W$d@J}ZPn[ ̼n pR+^vNo~b.ǹ:mS]ЯWPKfX{Ό2䆢'_q0F7@0&Md[o͍vc9&{]c Ȭ$ ^T5?qA-Mܩx' ! ICZ}pr LRtbI `#PXm㪀>ڝ:(99K| [5HqGD2 z,+8߀5^<;AYcbo.7\ 閂^1K@POæ&nHpe2lS;p˩ìK>^z$!'K|v܌;w HKZctC9р 2=7rBfҥ Ia-Cn ]P "J]82wvB܄˓eІ*AL꯲bM{7mg0Ṷ`ybGs]8D Db"\ |߳L]>ٮ` VId&\FSu"n59BƎֵ B[cK8nJoniOPHkMܶdvvmZ00 Yq1(A>sv_C^^ܪRf2Oʸ \Wʥ[aZ:稾$*} K/z*Kԥ߀YΓ>BO&vs+`]9c91 һh.~t M)-;ޞ~%c9GbF;iuw=ne;h]XHݎGK%d."C gW>1Z:@2QGGdR$~~55N&q$&HvE}r`$ٿsp.mk QtZbÉC\<'/] \[)KAޠ, /1NˌwX0RpWkM>$=k#$X 76^> ^_)l"{2*h0QA}TɷZގDiG9Fh||)@Q<=7NM;+ qa,#40_NWzO]>]Wr *-5Y*M!IFU!/"[qla.c1L3E]dRj"DSupA  *{a#YfIS;-=,3jG E~bW]jlh:T=ɿ!8j5(O񺠁ҫ>P&s$),#+8ko@[q6;,CxWQIvۯs=RV* Pw b "fċ{W7!Oڕ>vz)pzR;Vm@(!vI9~o㳄fgƾFU\&nY'K3ށdEgex JGqbGLP+A9ʎc-pd߲R /E=pO2A9 | pþp3:;) @ՐkB9pۍnkwbD}sZ xBH6YsoҌNc00pU\tTn<[xexb%s= keIyool/ '|>VƩh5 $+e>*R -{2Ѫ=Z@/ e⧬L132]̿jD|Vh6lKٮ{uF7+6W!,z @Ag !{x)`[!JRL?etI.A#ҡAL 1m7vWgH-1+ KFHb~h} ̺oXp/FsNo^7x4t뛒mx1t do!xy[Pl%4 v gV*4^cYK+}o˦>h_j'JTo_a\A@#f|BxBl/E ÍjdE!rIXMѪgN` H}u" t/,gCܺ'1@ -ID>3f'с`j=!JsO~l8\ݿFi)$9˴OB^ f,K)hRk7b}>M kQ  s6Ep2?MтV)12|iߥQ $lv}`}YB6R1XTx͸i]9t:'Gx 3XR*W1Tͩi4:b]vIb{~7)DO ]p}Z%5ހεN+ X|Hi rJ񐕜*t?M҃5@r"Ͼ[ Ƅ!F #D1~okE|wЃmw,{)liURJ"Hv6ovk\֒躃Ȑ"u?ه5ؖ:Q14<*HA.y}`۲Y'. lS8'#5)pVx ! P9\d#˂ ݜe—}5 |AK\ϊiιwfX`WDJlV~NĺG=[a>ޚp/PWî9@ONAFL Y# ]bQ1gqr?[5%ƿPp< .Y2O?j{NQ :5uѹZ0z qa!s)ҡ ~l1`Fio|U@ᕉ^MP3{6x`B6+Y`p[_FxΆbbU rHw(뼛&19nQ ʼKNM r<~$ayNa"_.2 +1%wv)|Pϵ XХ`--ߟ-8 Ałh? X q_~_>x \oc@ft9J5HW"O JJyST(#0 0p=x/A%Jbk֯bdEGf5瞊Dy`}~~FM4snVՕn7rh([=?dA qn[tw_mEw6I B){Nz j; 憔/φ8!\a߄9Bo CrVv;nW͜c|!{^`@S9)e骑C!竑a>s.g)åCr\ׄ+Y0 U-=g5L.[;<띫un?8VJb&臘 ns#ge-:L{ZgihN0dQeձCХٕw,||elS<ݫE^Z Yf6 ETB`xO٘z^=p $:PGNVp<R$-<2ۿ\N{'U !)2%h^Q2"IH>e^"Tf%L>Pvv@WRCH-E1X=xxtj=bhP9[l3.uf[Mɚ/@4?&YɁ<ݙ!Q3y"׈w :?ڒF)Ka2GR<4WRꞍjAh4R8Ahs^\45Xuof_*Ӆ6:6ȸq` Ja) ӝH2(JX0 Q@WGsj ٽ0նu5,: "9_F%nTkrA&)3$V$V@} j2?1pcJG.V)]L+ G/lGZHI7bEmw4vlSXDG̭]Lxy$k- m2 gҙ5SjR)؊@ˆ%g x`p*9KW1I4Ju!UIM3XZbmV5i'}qvJAwl 8;jhAnK-0%&tqBH0yjJ@7Pe Yd62, e@,T H==nHT R2@{= aDiuAmCRT?6݁0oW46Ӆ^:D~w8 V_ZK:SVBg)Lp\o й7CgXO\¬A2:PkY 9D#)cWz:V wrv#OSWP%ӝ󀛃M|t][ܸ02fs}T{_^wDl:d78Cn^f5kjb+2Z1&ߨUц5;tۥۻ0KK6/5[fWA=f21{=822MYV:mze s5ɢFfە\'B4^l]TzbQ{x:/MЗ;SJEF4s/*gp&O:AT2$+ 0Çi8d-sɑ([`@B[8 sH fYhZbD+A!Cxo #+(d$N)<*sWGhHÀnXu?`=[y磸I[{vUŸ;}g25xTUcyă p]BX˲0(_֊H /9{uˢWKlu /ei3|fMѧK,4'n`eh4"T4*4T"YTJ#@Y:TcoˇVeex\yA3]Kj2\Lx_īBvƫ{5/֫ȃ_je5$kcr;%jW[+qQb^!~ 4P:=-[0js8- #!K% -Z`Tcb.Wzfړ61%lp[mwZ?~Ð p8ejvy hkGhl> 1zu> JB͉?3Лt x%'&$nF,ĭ~ u$˜2Ee?bx-ESJm|OaܢI C=Ƭ"w%`$,zT5:g6.Ҫ^ի6Z:@:{bS &A;CҘFX_0e Vwo".Pv¯T-]-qc<n)7Zsقlb.EqC}C0!1`!j$Aᬹ}FN .E*!LfJ jTZF{׋.׸Z?4i59w!gs ^ؿbE^h5VL.:&+ J$fSWw,բPR}WX;v1sJ|膽Ą>0O6V  @pL0l5lU8[eڭ$ )@@Z"UlNjk _1\mrdg*.6hqON YKm*Pu|Ub]1m;웝Zq2UFvJG'Dl%K 0\#xV+ތo& ZvFe34Wl RG}\lŅ9afzk.2{Fs;`'5컽Edzk >E[° T9AD T^bͥ 5^B>F;01 `ڏEJG6CS'͉tzfsD;N%5гƻ>^e:^-/WLILNDIN]╦\%7Cϗ !S1x”iUpˁybhHf~xy7ә%N{X>^Km ܌qSl[d EЍG'9o7=lVAˠp㪋\BJvCOEW/9(BQy07(̸BZO 偒i9^٭/yEbA k8 Q%;'"^nNgc)A^&?{`g5ȩIJS!)K^%Z I,~atAUb{k{P_7ֿbzmB]>G|Q>E(J<_T.]PuABh1O+z:h8f'8]yX7i~W޳3 ~qGA:pD^dr#Ew8x:ރ㍐h]q>՗{գ-*C=Tq=L6Ѱu5]BN. IN'$5' bYsw:~#t :hȅTs ;NA}́82NBo 7GYyK9p#cKڲݦ e[?K V ǭbNA[W࠼!0p_z O!Tu'n! TQzA~ȻC6!xHVݫFK4T"XhEM2DcCj1Ss,ؒ'S #9t j$M3(B7{t}.ORcע`NџN'!'v ˞,hFQuQu@^ 璔;1t |XvVT/|Zy0VYkMFu( !AGL{ V^]cU5W:?PᐰxA;@/YbWfs#piYٕ{\(V2Pqky*9Ь|UZZtVFYOT`7Dk;4 ®bfIi"0}bKBΉ5Dncuu034vz&zBuCлK *5D[܂ 2l+g)RZ,R^F8n*T򽄸:Og9MmdBO0 ͝@&'$zF;{`sAwOs`~N( JXV*nMtZ賐n 0XdQ-OUG[%;ndRtPU$ #RI!sފ펁(Iˬ.<]oم\#Ū4ƴ"KLhSVnQ _m,:𠘇 |g9dQbj46~k\ dxSJybICYH僉Ưq%ȀPw„eO/-\Õ`VsWWq%6C\WRK(͒Ct Q Z| ne@&Y)8űV3?܄or}M<ϟ]< x. ݁Խ^WC&d~f8Hag蚿mc *1-[pk Ҟ :AXJݮJ,2^5e=Tkl;A6#v( Lk0Wf}C`ꪌ!S ,dL$DѣUmVŮfc@o*(v9ڝeWYFj ,Qm@Z].1S3?"g!aT-$3 j99E'|CY<<:WR %B$2@tC T FI%Tj)|פլB 87q{jMg&JKz)b/H8X֫COc>fH rP BW>3o:O:θڍ]&O"cvc:k`%\2 W4=p>sه{2_@ĉtzȥDQñcp sMF7s4H(PnF9va|cO+EsǢ":E%VN|SOkv ;O_e._yn:Zh_j}J[إ t3j~#Li5KܨBF0mnˑj3ڱ`ᔣ;'񒳀c1[ I6Vq:q7 6r/VlN:jAU�:$-]q`6\v7 Ъ'B`&o2%K:9FV .- S%kfc;ZG,Mu5J]U%RS3dL93@x)r! z?_*@X.7?XC*|nt(/,^(Ƒ0/ ;2#s!8TڈT+BR2P9MZKlss[RbotRoB PpńbK. S>!YԄn-]xKcY>_;`|WkD ASBn3~uqơmafWNgjTq( L.Y|tLqR` 4wRJ2[F7y5K>N_jjӪ6n'bU%[PZRLzǠ@+uJ> T+Dc9ҥx(ի H2jDwIy3+x c"n`H&6ߔL|z|zr,#b(%fx|hxCw;QɑDE?jߗ>NLJ& O ~Y?#/}XXP.РPw`E;E?D{>.waa0vg ~wϣb\ҪolG~o*x0mmǗ4-#fW]VOyQIf5Kw.5xa- [4f J:5tԮe֫+r&t0Km&̡S bSH'6{:#t)t:ە]yMҬ|)r*G_˯}LsYΝ.{.R`c9[BEiM8D cL<HiPN˧N׊:T}-ЊqԨ֊F}Ⱅ1A*V00މLֲ 8ɥ]L6]tV\ :u&ZՓY(jE<3wzpvʕA)lIEom!*MkWWٝmL'zobբ/~UMqU0 :bT0bG f UK'^aDZRA7q(U-2F_{ӧuBw~ #>DLWt:ɢIgiyq]<ʝYE<Iki><@pM{v߽Hq7؏D#HodGJEpFi@->br+e2wp:J)w8-3{8s턍u(J AC= cv H&;*$ύ6'Gedzw QZfLP),?MIJ(x?vS( yw9▕U@dbVWkŋd+;h{aZOeJuwS6<@0xc]H=4j.u3ϔq04w$5Z@cʛL.A&n?kzxճLԯI>f84ci`M]Mҳ~/Y`vE0ai'x裥7D4j喝-k牢,,0Bl0%<ߞ4l1뚘%[qJ9;hEXNAcN6ŊU3,mU=ueK/]咰VeL%&j4*eN1􈟚:DjCjܘ Y넯4{& fx[Bq.m3F n[SsQ &aQDwi1)-ѫw-6,0(dPJc'ӇVG̰fu09MF;k.phiݵY:E_.GPnŽ?L1AՓr8s6]bK%1V5QD∭yC荗s"Lb9DoءڟՎz RZ ?Lᴨ7qs>퓅VV-d'&؟g+B(Ԛ%&Dq= Ql?e}ξڊ OUȽ[񺋉nĸ ږjee`p仳xm,pEPBHҶ.T[Srptk1lrtՉ[VzP4vKSaT>:Ћ: $w<;󷶞V|<jbxT05/Bؔ9=H $%$WX+591>cr| ]W!_vu%ʰ-[G9i;~M&uL6 ET" &&(J^֜:V  u[Pxþ:M%29fVtIZ\d6*5a/C#MǦcy;v)d?h7TuTCYʥv4+} Z/X>w.mה:48]U=m48+VթT7H=nջalLpHBk=HJrI3QҢ]^ۇ6ζlj{KN_i\cݤF<&xZ63¼ȢXɵ#|UK:U&2 A٨OYʒ"W-]I3ԀGstT7 >'95 2#y! >f` >'~N1ZrP 9AjRb6!(۫XTթ&yR7qP ɰfX& >" πU@i4dc2#4twƶc @n68]#EV('_3A&'P4[fN8 )5MH8 ۣgp`Up@sNR(+#ָh6CSne7WWҡxN4Q'i788ߑ_:ԭrn%urkrW*eݵ&c\fEb]4ʪj捎1{Yh7eŪ^5Uv[loɆXG[L#.r%lZb:w<33 :z{4F;i%8MjGK&f_tk W@ eX4%;0-ԢYq핒9zkFmy!(ګbI FHDf&Va`[~3pϝ^I (O`g|Rf:G)a+z;EI&Y Ťɸa#1zbD8+Gٯ[֦xf #Ea賡\o[cNL/W hұ+!@- 89hqҎΑN:zZM<8x3̉$7Qr7x04##'ZQ&!)=p&((^fhϊb P^u%[c+*u!K$7SL0Ju3e8 +RSi̧Z>Eː3uIƵ/W:jV^͇& (d7Z!լB橶UWu?LZ)OU[`Q]r%;`t7-Xƽj;Qږ!&g#inXne压 F)ffT2nH{uIP ;p0,GgvӞIxytEٮ[֛maN41.k9n6mfZzKQ/4ߐR%NjJb,b/Gru\ibut+</sb3ۻkQiuRͫ*{637%99D3^n418:JEB4EsK~qL.ylf/2>~B\?\WuPwTkbs7hX; 6yY{GQe wR'?›̀f@`.;dr%I`>}$sDmovf+y$-Ta}n 64/ϱNb䳃ޤQCH^g5gXҢ5vLp3WfQ̑4Fs7XN= HΩ'ܣfR%E(Z]n¯E1RuEՅ~\/6Fdx.(5I. )c862/":a~껎%Ttvf}̚0f ]'-*Σ5ᰘLnVeŞ E,o+.ӭ..+jsx-*gg䎒ƷuS/3O}Џro-OF퍛Xթ}ik ş՛{#p_[cJ/<w pqng]x:K)PgC;ł%k]򿦿$_4pޫl kk"V O|$w.xFI|kACn 4jžF7P*c('~ 'wkI„ "7]Y]A'7cSivv`6USf{ N9Pݲl?GX-qoa>$2GVkr\6&Jc/7rgxhc8eG]L+c:]5Υ紸v{A)yagfQj8h]O`˞k'ӱmsdEi7^mݪPw±4Eؗ /|aΨ;|.,:j]Cf -NW"9vө9unk[%*9JFoR];|.Yz?p4}Kв9čby8 [+2\' :4Exi2D^*lT\n)bȏ)8<8#MùSn+ Nt2!iv149+~˱gYw6ǑK rF^R=@<ȣVA\~xzO*+'Rv-  [?`hS'ep:IF/E>2M yX Iqߋ6izy I|3Ҽiތ4F^l/VQ+)> e.6$LG6-z;.jLx۷hqIPWYgռ|XT띙lzWl)rO턥;qq_n2;XZ}O3Sn|Rpi,ym +Vj."6 KGVUʽ&x*.1 % _(|2y%tLҞ &ό^َ`'d='bVVGdKw?;] I9(I KR6 z9IMtl<,Hp1@_(l et+3 R2c?3,7A)2uCc?64H($Ny@se@4//yWB: 0n5dWT'(:+/hֈwzK؝B{r0 /z$IpgI%%!S%+_ >~_dyzu]'趷ܷܷɍX+_; ? "'8 :($ VM'UL063'b3nE6$NDX9r;2uJ՟xV\C yE0+͒5l`=׋hxD+(e,7B{mv{XU>_VMna9%V)I!jBe6{ϩp:9Zz-gBDX4k1Š|7('Wm&uK]oRD[乾IkW=jzåj<+I( 9ltm3i:=7\l5QJ-άE])j 2@\GsYɝE_L TD[KVF9 [|Li/C `|]2NG/S2QN~!ZLVKM*=#Jw,Y9KV=^VRO# ya4ODbx0!F|mPH[?YNIdZ_qwj|i,_3^-EcdZE 9֫[Ow{pXZzb3ƫ q!o9>k?{h' !~L~X>0*= 4ZaxU \ ksN:C4ʏ^әG7GB?HrM:м4EcC`__W4O~|WozLYK7< ?~hXQҾ7np;`]=BWI}4|'L6 km}9_No{&@RA?;:$E.ǁ.{mp|8Z^NcOh{>*]/8%$_{' Q#+Vc0!CZpt'g\7yaTcG6`#5`TE \ ,޻_-vNo%$A*F/#.ţ?"v'vg hHbp^3~ԙ?4`;s\sO.i:_[i4 ;02%5̴8?uwX_SwFz5; `µ3_|H4kF޺,_[<>k+C tBaH$^h~5ڣ 5P-@]~P`Vi]d H<}LA[:^߻>n$B9E@ >"U lX yiyAn.}_h^{ ǵ@#c:\Km  ;EB x]ޡSX?t|/Hn"Saci Mkg;Jk !(B\k Cx~-`5ďF6r1_V By0i'o7'7cAFǰvZ>`9فe aHA Y2}`oU@.T4`8姽 Bl[(:*ˬ} aa  L/՟]d_5,]rAcHB" e(է <(Hmm! N!|>UXѸ= Fh/Hm4> -`Rcqr@Iui0iFE?[aQK6]ㅖr : weuEhЀ@Uow w%2`cAyG V 9: / ]z "yYB|8?Qok P%}N{}*(YOH+<nJN ) FH`Bk.`@8\_e!ɜoOUIZFX mRa! G;0e\kg TՀe NOxʶ? ^Q(We8 }@5 =(; h=JaBWI_DJ  , /q~G{Sf jX!)N3K"$k!~@Hؔ eY"_Bx^K:I$tE8na hy9Q 8=<Ӝ|mU: fІ6xlo G5z~gH6O4#/gB@ udeLX9p( h} FBj*N`5_e.st./kjtWV|~Gt>^yEd?wq$:"4@VO)8BZ&2MaL-x8;OQ"D&(k.|aPqmjycS{}w:#]i+T[|yW7wLtӁǨhGaWP5څ<4n!qukBאdފ@cw /8ԍ G=?ׅc xA;9-Y;|{@9Q59^_7V !\9Z9dMՕ]?!Mڽ`eˮ}ݽxHx9u |ǮCJ EBT|yxQD%H=k0\4pA"@HEK,˾,-IWp Ξy}/~ܺ­~q w֔zjkzC]Z"~-a((}"=-^ ;lŕ&/ZxHBݕm0%تt4yE$CxEB- qTFX8 y%\Q+IT@UdBt&g>rdoqmRjL^[M~Wƭ<4 7EY|^ (o;tI$E{BՙgBrǒz߀`~D~7 0<)_h*(r" Q$g/Gk< } }i" S+!f?2 r.!L ϽX0`(1U[=Wi:\:C}8mdZ,',.1+`!q^S$Y &JDZEK\p!& .* WRީ?Us5vvd?F3<yyÎ %B~3`8.~YɻC@Vq?'gm¯:7׋oMfx׷ EZ|Ep "KUƧoJߴ]`ąQNj^f+)f M.+b*Y%KA+|%x \ŊIhŊxi^bn,RB3>#Qt#̞9 jxɃ)rfB/Pp!H*AJ|@̵_k!*MϧO ,g a yQ쎳 QU` H.__*U7T)?VnP [[ܨah2oE"Ss] yDÃ-ܤ߃hnFfsA8}P* f^ZJyU3 9 /@QZvՕVa^}ʎBD+ :VBeov|rCp!BAMԆFVaomBgj VU ːUV)rB]qU(•ZI+QUfh${ixhBZ^4v V4#jΞB_>5zc3V^DJkP|[ݫzF:ߗ%I\2U\?`ܠyTe.CzW5! ;1FV5"\O0;'r`b)2'X7/"vZqu?'D!"!J$0@!?qM[6?17뙦]=IOZo:^+_잌hz8{ _6KЗlFy*IE @:\uVQ UxzfzFԾW %SSБ;\pǫK>p՗O\U ޼- z*88rR]K\K_\pp-p%+El r|'TPrR ?W48)yBX݄t8v>P1|(@PXᣬCav@x >P>p`EY)^ ErUÿb / ԹXl핞PXݼ2 jg+0H"a t .6Ƈ%-Fdz62^4x޳m>,a |n^+23.='YN2h*@~sS}z@z|@:h|fUW`ɇoBtՊ4WJ^_iQI?^=v.~ zm6P8,8Tګ9k>0&xA*X~9Ga/`~x\Ç0+eW/^7Bt"CmπW6^=S (_Bxhګ꡽zD`)+/`~uai^=Wߩ" |j~OW#{Ѱ+nXWW|Hm8Q{AȦ_zW7222FE3^EK|?W8|la|}g+`8D"8O 'wëW{?^AF ?e>WWߪ*B#<#7@xW?^=H.y4 o$D]AffrDi\wO]2R+|Z$JN5tB4hg\_Ip J"+/mCmfy:yq -T}L ׊[ZK0턺^Di*Vn'qq{9$ýoHMg .ߏ& G9T?g( 9QK+[ӣ'^|B-cYOa⠯$WPUE7s$Ty| HϋAB`eä ROOnt_bgzS 1!(T[)l!ƭ×|^/,$3H OU cdV$T*We ,.usTĮn/nL{[9dk5__]=K vcBfIS&SKe{\$"=,R7؁[ Qzɥ^\g.,Xt$ZڗW`*?sۤp; zᰗqYĨ/zVx П0r-`x?MiDz8n7BNk߭IBO>d|='̧µGq?AOxpn‚w~6Ao/88]m4W0|8Ha$ qD5= i% :EUH#`oN\@ߟEܶx_0ͬ'ķ5׊O^V_fon=d4M] Ҫqxݧ D诛Q n|_("};ʧL.2s⩁r#>!]U!my݊7uAe+ '6o\tY%CCpUU|ŃxM(qPґ\=c'hŃՉduJkbxtpK>K2v HGM UxMw Ewh=i'"Y Th/dHD $ %\= C _HAߦ'ۡkvY輻DD&@Pj^%ӣIѣ4qnB]Kc7vQ=p87:L#[}/փLjn6#Қ9Nm5zqlOa@cs'ZzhI0^o }BG};V:ٳL֌`ԢbDZ-iAțkVfGoOv尫R^G]Լ٣nlFڡ֩]-j4YIY,\y[YxawheAg,V{{Ν9yz`}5Ojh-& Vl;T-~BXW7\;t䔲+G5)/'giwl5\֑iJ9#e:5Y+mh-[=K7tN:1A 9o,_qSz2ĘHX VROݕS%0j35 wpm4i+ WH;HXI_6sZv2_ޚٌNAP7baXOvtPa-iJE?d{ɛ̷&{bmffv*hGUÎmQw4HW>IS#z9:Im]PsI#9&;B>\([VWZYsE䮺=;YD"϶2tcV!LRs攫˸B18ns(ƞ 75m vH-4É&N0E`8Ni5q\mzE[Y^L\Jj3m!]qzd1lvXNd,I1N-'qF kQ[L]q5) )Y5y:dV8%;$Sx4ylݽǴOjCכLZ;_9 [VHbk簕KKQѬa?Glj6=.$~Lu鸅16nu;tޜe.5G0'Zؤҝ3PZ+p%*SU6⡰1Zl7:=8uw+}lO$>ԶWHلӌfz9F3)a[(]\Z3E6T! ΨlQ׌-WGilݨvE"NOVu}Y"zrIBaܐȝU yjdil孖á|Pg[:kD?n4̒e︟x}9W n2-t6΍e-YQh,bْ˔9yOƢە {:π*JѰXżb'7(e<ہLx Bc0l67Nhvን[=ط)' 1Z(!l;-<./|0e><`×#*;2vKeўxOqCGl $Ihr&oJv1no`νDU56Y͂: p<8؋NUuytgo.̘JA{!H#r'K=7 JVKw3T[I`6'Cls"RٖTo;[geᣡ;eq ~;6&5  =cqfX1%h1ۋMۙ{R-l`6476eNzGc3g΄n!eMK$E&MvAn]=1b8uz~5ϻ-e8?p$IVOk̉)D `źbiƭz2tiz͕-(glq yK[rܛy_Vd;GAqCOkFח`UtڰZZ ڑI5%#h/sMeRm7a!jl-H=So1D蒞5<4,B$É)ō]Y机A '5M2adK-_ήV*pzJӵMn& /~+]gF"ufNwt7ʫa4zo6d9Fe׽\;>h]i|sZa\ڽZ=mIӉg֜X2p' W[dty?7ٳN}w8\eLec&7yD`*cS6km83v8N vi)ύHHix@ZfsS >9VoI LTgپb#5\f9\-g PˍAw2w3Ƚ6i \,ғ8M|H-m {ѭ6zӘ CjP$G׬,dZSPt'C"do6hf!38aǓr^U} ~rEc*־tX }'uN tAAtW;oZp(֒6FKe\t :v -49wR_c$ͳ D I.J ]&at7sDfK1YmfmH=q`o;?k1e69UP)I:ټ$d G;Y}COu+D$uPbs,{ZLzZ4%p,v@p$w=4dsI>mq5">LTF{l;3;cS.-Xi``N6+ñ´tnӼ椓b U0ڋZuLdE bGFXFԣG'gio%w7-W֡oɓޒӬR_@k%=Sdɱ_ N@40?e9pR7? Ve+e`O:&cNd~h~@@dmz4 )WAcvK) wl Ap=ӚTn[gmDF`豿I-Cr'=,\npnFYs^i`Bff-w[L=16|!@oHA )1iCo;[X&;Y3LCwZ3wdSͳChl^>qwN!_wj kXvv#"Pvq#X G]oE2(}ÙjsZKatIhUҊ02x75uRPD>}fifjFVrW)UېO˧|l}m5 ش,ݮv8d3:=o|V幫:4Pݴ;ls DkhѮq4 :A$ Omֳ.}WSFc·XiIvY6ҙs[^x4vr$ueu=^7CPI'lM۞SRtiz`sL]m=8cImz-Ed&d4JvoYZ)Cj0Fe\ fiSivN,6JE7u]wDzSMLE{!b#;D:PO4p b jeM7L3 dؐɦN62OĠlOhr?1 /< oM=lGfMU^,WK VfJEeMo?qpg[Z9)طA ㍏©aY^*s | v_&J?LӔu`'rdũ7UG+xQ~ Y)I[.; H~MMU²^{i.7 k 7}v(bPVXR5-o q'H&X2\hM n%Cd2z7lV؎YV~`7aFq!n b>eR a]cwkdauUu5&2WbC>~s,6ɤe3O~Ԑb7<&~NӣMA -r<,N-Ɯ0𘞱ی-ũ{ÉVp;1h23 'F[OJvh ؘ"5@E8S/{[9cvx=F҇X{؇i: -r*=7zg[3sP'<-olCpŌ(e7u[AEq ;͌zZG3jG-{rm@:\e;=fsuWؒ9'ov>!>&s}}Ʈ DlK9XGmlwGrb6Vq҆/9!>Ų(nlj)q^"M"!ɸ=\{4Pm@D>tIi Eh1O$$0J{.Υ˾YfD;fX~x3b"h6KIu9j\V=Hļ؛Ы3{Ϸ5+?VQ ho.N{ǥey1u((I MpdlQ~bsUe!!MZ?y/+ %>X'z|<ߵ%nb/ x;Eܿ @BQֲKAq}eƁ=F;4ĮjM5}xr2m jo_/UP#:nS}^G [UU0Uc P%\ ZS="zp?F_@ދ}we36e\ UB A'6ϰ&(&oqރ.fP̳X[eׯǒ&&K4OX za\ة3 hfS~tsEm9g4 `HGH$!'?uCp l0+'{b9spmSKZF ه)z +`&X`H?cG"Fx<~g *MX0C7-#lMnh()WT\gbeKxXy7ϹfqrwŴ}#:]nMO+V=u߇/aX_,8V,\>`7!_dXr')'F/U4q\c 2"Yc=d'6Ʌm`/ ̍EllںXiG J#E|ZB,'Nl=@R̥PօmX y45= OBSCpՕ$0|l薞k/7Mﮁ)4 W!Vx;8ד爿2_.4O\* i-.ô.IRêO'ڻ1Ƞ}Q-{~w,p&,MPt?O*͡ ԇKk͟@85DںSEWW#zB2Lz~ÂcIT0B5NvO!q]iSjƜ'`%/gwhP(.~t5%8M ۭd#4aH[~Ɂwᵻ ~C#='vm䨇;x5VX ^^ÇG (^b󀙍&c@Œ?W<|p" 95X2^+ٓ5Ŕ5u7h& ]%(1^o>6#SdʙGg҇OZSɡe }^/ ]%&z,Y5n~!D=}C)oxP]J@-ǛGi Pb<9STCV5r!ڝ/?QudgrQ P ViX;-I=}r-`/7e ONTNpal?mx@+04D0/b;t!/ie?_ҹjBJ5dRœd RB_W8^Kz.76%~-睥xSV1R41sQʋ~/ք.P+F9|=HТЕG'kL_@Q%1l^stIh3K1k_pn4MW7% d3k;HN~5e|4+l yjݦ\j ZJ:>p4{x93#ޔ$LFh:vK_t-X̩E1o(=LiXY7Y/OBNdϷ~-Tq0&Z)Fgү3-ܸq3whoTDj Lޱ;h`=w 9(qŊ{iJh_7py ad*0.syh`E%.]OW#F_rGK3na[{(Ĕ vJ8O<ϦF.x3 (&M=:6*6/.}7*J <ӝ˜ ^XP37<{6zM܉|᳻u /FoǂNrT]O$z\ƚ y5oEC5-9! åj!?u~QSKOK,THpY\ƹ*/`GML=9Ma|G3Цol.2.K>'Tk|/G=MNig+ lip8{#3 "K 5 e.zk֞#L<@s☸c89no^s)ڰ[(u;NB)+&GWh c\ 2 s9;f&eRxs!ӦE >w=b g?eSi4-on?e9SנZ3Ku}ylkv_Ao`r"JVg}l~M~x/h^Ju]F(]O ֤Dk鱾͠c& pC^L|x\;fعE`F[ďuY_r~ (ք5uuTW_L#VkfD|J( H-}n0hY5[JASz˵.]#|ˠ*(2OUʬ 3`j;(PFc@'2~O߭jZ!% ZhrD6f ԍ<[DX%2Mw՞3ʇ9Rz&z, J :Jvf>0I)6l ,DA&ǜ(S!`f-=1ǒ1ޫYZ ĥ)x,ۘs0n#+tP5] E^St`(xi҆duL{*Mc?}94e/TރN+z=-zΜ|9ɝT@;YS pp @gxћ$kd8F B%T!d Lm=٩P8$b&nN>٧V L9f6%MR4mh_S +h+?ڼ|FtAì g|[$ !'C 7OK&4*N-h-Z|}w= :jJW0{٬q_~PvuOCIxo8!; 57"=QRw4 QYZ׿mC݆|C&sa#CVŒZ[љ`wD0XrDcTG`2g*߾6HݡV/Ozhw^&_VTJ#TEῇ+n s \("] r1B>NNwUE#HS"ooC@?u^elC'*Ol1s9oJ \bֈ% -e?PLzϘѿ~|sW@!@G= kB6Bs_Y~Äpm~R@X[ ҨM3pK5%S8C?pսsw |Hw !ũ&=$r |ۃnhoQ;]YD<, mANEAyU,:&>.Ef$v!Qk7]B>^pFeZ5͜ K9wu8U)Sd!>LOGP WNo:}/!暾*>> P&zdIGi`*q,|ZxV0{2Pz c4簢ADɞܮ먝Mu{kozfd ̫\@?HL֝@Yl0@{* ?etu<&=!n4ܛ+'+apY$пEAve\#CL8ʈOf`~Y~녩AԦuvlտ)j57 qs@Ws$A $}R *lm {W΋Wi_EyZ9 pc`~:2GkܼEO9oa{@Ac|<t0mqCq[FWzkD)w*?$mεElr.hdw>{1C5*ck:i Ó*1vQ8zMkK 1 ˽DIЯ0A7Ttd&_?|r`%ü'Kp|P!-M+X7qZy=Ni?+4+bM..;[>VcK3/ di<8C{h9ddn.g mGz|ќ\QǍ<VF˻ԚYuԼ=҇c5ݶ8:Z^q$@# p17nu7*Y0b\ `ac*4; p_wLoDͳ˘IU˻u[Wg+YK RFa#$':&z6PQ'SjmFZbwwuNߒzomR.),*pϯЎ #(:A[I2LlAsJZ=xcA9 Ztvc5ovܔ{_o*c,OKVlyP̲r3BA^ibves@Um!ұ^dNZ1;ewbc~Xp"hm]+!l4_S.ZSxɃĀrVgt3hRkM\nD|Z J<+&sʯWW*P^^(ج_1 HW.VxΓ\ 8j1534%#Wnc ,ƪۜKR/ T7o %^WRr*)[drх H1 ͭV˟kajk+KqW\W!cnnߘ&g*{9\(hZEǖr| N]9Lp#*Zr{k3& kh ?(Yc'Lv:_Mߚ?XrRUTr5؆vwɴpJ9}A7U03Ε"*.;|*^#݋Q+Ae1`ҿ;ZYb(y̭oG'^СO]ʭ`>Fͳ(zC?EfY 0#hE.Uq(uU{dM/Pl9aLܧ*~}H b";OFAdzMx<n_>Qߣ7Uˇ`;o֋g$מ)LLx4.+[*V*y̸rC} :z*%>JRɜ obn4[Ӽ37ua Bnooa a6 h*$䬗9+΄Eo ~^BnSJJ^~a*-th^!ӹดUCS ,en[~b4O6+r/Fzd#k n={x_V~V<> O^Zh(C%O3[`aHS2}\r e:*("ǯ3Tѫ<3cWegGiH{D@%coM17c[3Z(Δj8d9' Іd@ ]<٭`W/>q4#6K!D3hǘ#ҟn3Z'c,T蓪thqߠ< ~P23"fɦU!wﵺ4бi'E7 v4o@ #c,$`I;[&2#]9\oa9~h9Yb89U,(^\cNK#^ &w,]E'端D#!J]HĒz./EL>qe' LK> s%0%^$bš {T͝ xj!Vq'דǧf*+mYL{/;=+5H[8J Q xX#) AqHg6 ;^.>:ye17V讉JP>Q@ s9%al w:ߩƚb,$5_]:a-X|3nYUՅh':Udʘ+x)zh6<]p;"WCg4jMx^Z Z[1P]_ӽDHaAlG"%K3ATa&7W3]~zAM57+ܫD}JťAFTáaqU᳞]6>"ٳw犩W!cINƵX|RCO`{$v¤:Xc{olQ~1px_ryO;r{:]4;~S_t% Uom/`aVv"ZaR!e%[r )q,E2 U% ȦkgߒxpQG{|޳dAVgrO^+@K Slt 8A V_Rx/×Ȑ% 0`AoXLJB> 7%n%;[;QN|GQIJf|`{CSh:xea7՛UҧM"g[@bùʀ\{?% / S!n.v$>&I kf礙'J_X/ZĻoY@_)4Satc!N°s+ _ddT3ajVG/d[a67_bq07el9kк.lz+N@׼:"}zA%P_}T,EaXC:1 "K>Rh'~ _6iӕS2%Y!FHӮ}̓Niu4KZ%8gL̕NߞVj> W{;D~R[(qo_18Pym^g3A3p5 a^ 7(g_tl9~ })v_ў(XSV#?˵nٚ?|/>A Xf {V2sY0m?.a'*U^ (hirϥ]w2t%wP6P ϫ('^3^e6Aڍqɼq@ c"Œ<h?nUI% G` z0Yјz_)KPv'hJ>"wruGIP4h&jUZ'щ~)sPd 7ÁÙ|Wc8.GrZЅNرR68YXC9(Z# oBW Nk;2"AK~#D6a7xâǭ,%Gl7&o MaX#Ş̘ GvL)p*HUs߄uI1iPȅS4 ?>vPo>lMw:/ON\0#wZ}P %]Au"5 eUd!er=a@ϏP,.sb0=RĽ"W~Jhbmto+Cʅ7 JD\x_8UK{-Gv @NYuAZyQcޘODX! 9gT":-OS7M'VnRϬ9,IILto*JlZ*[P.T_߀;~#K:_ˑ-o& 輸pJ&N+~_[-i7s s!GƵxbOJҜuC Ըua h RTU㳯a <vխU+)jin[Y[2l^d{gnr>Y5 UM`-E~PmUe@ԫ۹3Sj"lyM\oK Tн9AСb;c-@du=2R?lblv>bhMCƭ|"^oaţzq5?7w>7'⽚\nJ i7—!Κ;?!z-0 ֦a\=Z:z֙K~5r"p7uKN?=K߶E" _A+=A(` VqS"H)̿ 6C~%r7XsJOan" y%ˑ ]ooU[{hxP-Pf nKm1[n7BaP'z4Hb:62VCe򸼂x8H±*ؒn{_{vptMZ5we;6ELL._}Ff|Gɴ_ޘw@un/2652=(}L1[FDȁ/xK[:-3EoZS2Q ߀pdžkR a`{OEorhnAFݡt'o?7N" aDn3msH_EL}ǍiurӀ"w6RgzDgf0&/%88Y j#> q /Y8Ag&I,yUާü^X˗iK{<Te@@+=3pį6]U1*Р^)> hW5APڣyMB^sb]{2Ս<E Y|%!usfn= d c`fRF Xr#ZחwoU ۠x @vOU:uO_B ] X[A;Ys=5#w"PeY;/@%xQhapx9iW=(^}9սWa\wPﯣa}=i^[ŊBm#c+M );$/jizl8]o!󷒟mpW<񺑀{\8R*M*/K./0Tu^Fg\w_UQe?{/> 5C`.+,fɂ3Zv6p]̛֞ }i=i H܇ZSh~ 7&"7*Ⅷc?tẹέ}gJ+!27)Ao|Y )6"w]^:D4 a5FKff$)DCXCB[hՌ{T*\1T6:m̯+ 杵PݽZQ' β4VN/ZX`\7QSح0XY1wFUO)-/i7ϔv%>Sҫ*v_:q9=>z#G E~7Bu?nUƐ@p1soP8&+ZS LaR#Y~ u:˻.Tߣ0wS*c]s9B}]*~[g"jfzhVcqx#SkʃyiOYR:Rcyx86&!(>AN0Sd@sHK߬q#!9i,Rb6 5v.7bSC>ܜ78[r"楔>,\ZOwb D1xiT83Ngys@AI\w*Iݶ.qGaJ-뇇,E4Usy ^Q* ޽V9g vl.[g8\5@a5SOBD7^%):2&:_ ڳa5E^Sq=bM@]>@ qp`:Kհ`ӄa+7v`ȗhnWu9ǚPH x daL寤QiY uΐ_}x>?יTH9 嫈hce,̛:BRX {)2:͈QJC<<`s!Omhѩ@EX3þT9C2$Ecp_i9ٯS./98% t`7^~ߋ1G,͡i'cQ& Nx#gw?'FIH̽v!u8ZbLH~A_I1z?^qd:-sa'Zpxq-wS*0 lWRr+#Gt@)0O"IpIT\\,>lo쿩 wúzp!@^7_iN|MĹT|"y=~{Ԧ=CX]&i1y  ZB*]3p ov^,{9tpwLxRC a8] {}@'a / !QXV]0HI{<[["(;$a}c,S*x'#s f%(o|GRF.F˗fvޙ Qo@nwsL)tۙxT90XdrO.µ?yAbo| %~ռ]nFbv\4yc))!@bj-. s0 y|aً@ #?m,s$CJ͗_q'>'Wim1P$] %l4_gp=J qjՐCF 0F ]EC3a2&S6.8{\? kP{3-q h)e/ĮIR'^aՇ.1mEPA>K\1 @MmmqtC/+qH!XÖ=䡰bqYїo5`Gx,<,C+q΂h8}eMgAҷdDn?H<0|:N\;v-&zK{' cHä́u7eݚ4mVDdaj|yt/D #C [?>K}dj=ϥ.u=~ZI_>~7#!nT}h^"QmQ;]~BJځ#y,\kH`vײLdǥ?M3b[los:%d~E_ڱd'~ j%hR8>FHY]٧Qi5 F+?7Un_S8?9Ty sL〵t8غu،/zYTs)R $QDiqIåwVFÊ*$ՍIBVFB>$7IeW&2m"M36kiy)2%=-]QqTZIioXv%]'ˉG0MƎ]KN0u\Hm\ߣҡ<0XHa]uW%ߚ֡E7몘S~A`"jn&)z] JJA %>N#ł\yIyP=XYQY~{#?jTX}&VsQtvdWڑB wp E3SO Ƈ_SFY4?Ð彳/HX?/5THvi"t^~CqVӕU ; w'NjDk."aN>nKТH [>ntӕx7PjЕэǀRv=)}Cqis{R&ܘE@" UllIRYT=yCf͌)W+wt/Z ܒAGk^D<6TOE-5ea}=NbT&˂9 H s0SF"ݠUA\@멆n>k"_5+K)_sG<~t59b{ Q%>xdT,La˻0aH|t.'¨ۮ XĢӽ),j`IU3iq^:Ի5B5j`ag+$[/];w [lqu!l:E7/7~k$a-{)LGc.mq}Ԕ~{Q ߀[777jE 3uA•y~['@;QEw_ gŠZHa  a6!R#< 읰n}9"eiPRx5ؽhKqEп+GcZtwm!ao3ڍPn>=M̧$#\o@j'Q(CuT PlIi(79U%*`4ե1z:Ple~efƃ@"6(lhJuаjrM7q#JLT5XKo)\TR`hڪ"(Nf/-g) %ƟS $ B%u kGmmʱ ѝ;r |A7Pe1=b/j$1c AɫwKEDt}d+l B3.pm58N`v),a({тEa Ug^e07ч0h'cK/bxVA NΒ'@fA:x)߀]%ao73np;yoӝ8*d}9 oC5P ^x_*odKwk]8|]tKS/N&1R깔nkrӽY)0tB7-:S 3W,=HѨ?uv:?%}Ȥ@;6[=i *)lko\lr6QcnJ)8V@nxv.D<O.])Nb i:J*HlT8=~}'4 t?oJq!4,OBǠ/ ǟ}5oK^tC27IO1apQc 6BہCK}H:bI3}-RXL:U}bLCpg?Vw7`( )MȎ zF=A\FB.#BL-m[8YWlsxIZӁ8U 7TB$ CkʜyG.1Mh:MќONzZzw˪ku@#-w EX/mQUC^ %snqtGHԮڅ z7w/$&w0) PQo}RHaݬ#Υ.h=>DٙD?=v⓻/߼ZL\g#&_}yd=B >|·C[̾~LQ̱y.Bj/^ZJPԁr!cBR`#*w7m@#cٸD:{z / -i?=vF$dY,i=v+t8 ϸ㷤#Č 5[Ɲ#Q[{JSsì#f@ N? t)8j!F3=3)=8aQTU*(3$6O|1rd- 0}HP*]aS~$E_᭍"#?e'r{Fwr;m^B[?._PgvWq sFTсψ:7IT mJw2X5 !d`2nֽ#I]HKfWjCԧg ^ n]v!d yZ=p3r*.-F7Q ^6`b:/z,#I  +jp|"\UP+"8jwV6+Zk6z}LJ^F*u/V^`Ca EO_aà(9?hIɫRGc"ܑ7;8@?5]b߭w~GF7$zG|俪HbRDl%lTXlXOn% % g+R=P׵%[ofBdwS^,"}{6AɾOҡw ʃ0@x\{aAB~f?x_XH"hmy{FzS@o%lفvv=U(1(xG RbW#};wLtn}^Lzm<249Cl {y {yղ{b0hHsgB8@o~_wGt{¹XVPTC^@!/ rh_+`rҳ[zg@ШL<ˌŅ"lPo@41-nNc Gb$>Fϩ@}t F'auSStrv%9(Ŀ)=Ua]|vn+{# WBNkOhfxG6/ͅ; 7nEm,,$$8vp#( B[v4 HkhAB(xS G亂p|dJ&UEa"=2eΡF HsI}hoLO&9 -GNf;`rW[*m=MVFA?!x*)M3"pZ$iԔ` N՟^۾.^txSQ.%8 v}́]d6YԊh%T:J@ş~i vQ!uAQl;]6@ (%+y" uu;I  pq5! 0˧@q:a[8U(Gj_ܗw|+LՍ~-F J^ɠL^1_bΈ`-5dyʇq 0v25/oATY\k:LIȷ.o -{@Qe%aRL p=.ܫgrFu rM_|!*Ey_o_S'o /Yhfӽ& xBxbwp_ ,6`s Aʤc`nbh:pCSHM*V_sPOtBpJ[b^Rn0P~4|nPbz|BBB=Yؕ0㻿+ S*r!\}AEr+dʽ \v enވ3W끃^Z۽z!"X"Tʢb'9rzSPCu_ovNڄ9-`#:z mԟ }39PϹj-FFe?יcHv6柺gBv x=U.7+v!ChL5&ZF.+xdd {PC!XN 26_- /X(- 4<7BjLp w>oM7}[>5,0{op (7SMJ =VQ4dz)D4090{쳂Dr&(cL bd_  FtN|SE$ީ4(-od7Q4!ZiP,f%[?5=n#( w\b}@8 oS77q'%^[?)u@#Pbket Οf IZǿ) Rc~ͩU`\6ͻ.Bf9$>7b^-ݡ_߉K<9 :K&Hǻ[I2lm[` iOkwcc?(.91 nXWYB/H@h`LD DbeC0ml^fO7SVq^O9\_pG 5A 5yƔk5 Zy֔>7gc=ffy9 L}tΎKָ E%V-F.Mo\ط@C+L LUSTLiTҶBLRRGu|-v, & $lt*X)Kf$9HB]{Cf m4ZM֭d~}ciR֚W&U8>}[o@PGau̶Q0' L̑S}Lu 5ֲ?9gH Np[Ul#B[xeh/0^tV02W -9nZ$'u? kWsf33k _WVսEt1@|Bppȍ}N[dt171/gO H ,Nl.-ys}, iF?=] ctS"UbHP򬼌5 ==}@Lr&Ho/|,cm$`1"CQ; h{z.qjvS~|I-z#+aJ\$Iھ0dP&!g! QDZH0)<ː oAZl=٭:(/Hy{{MtE&Keb~'u@ҧi~@VKۘ3EmgRi ubn=E7)찝J=g3tc }GE܅[:>sszij M;Bw`*;R4,R rHδ_$(%*XoPN1%3 ĿbRyGxX&|7 ,\šq>~<ϼԡe[yarӷky,*;CpG: Q Ó^H UZ}'8E0_~T AqLHIBO^ _g< ܔy29Q]a͙BxZH6bmwۅD1kqfYka Fl<1)HnL{K 񸹬)_+x5 @f]&.,.[7 hI8>dT@gmUd' @!r g};mZN$/i}ۙ4|)[A*KŽ!5ˏ*@L'* .Ix_K~eBSE\fo,΀Zz >5a]\S&@ddY:w(gnkTTҰwdvc{w{!à7Tp^]>FPvPvǷa3AƄRǦ>1{kO@f7 j`Oavmo^nYae aHpwW ~%S}}o۫ b ySIՊ7A~BOOB 7V<>P $5h̊<,~U>$Ыᕂ?nix d0 ejd`ZA1 ^Ӆ+ ݎV^7ë|(gTL37E-uz 3{Cdh5|7#0A9 vzH;Mzv,_2|.΁O $H=Nix};4S -yn-N*)V&AKțQ*!\nos֝HO*a_e~(l]qFZr( մSe d/IrU_ $EM>#0sdd_v"kAUX~jR^fDk ȇ9V;U (p -ԦG|r|Wo7fn8Y|ƛ PG.vT+&5?N<2J 뫍 :Cy!,}S yb$7o)#SXNbEij4]˸XX ꫁{ ]~;F#\["nPrGXxE/,$ ;73FxՉ31)jXחk +$dpMj9Bv֋CAEnbk]%vxpҜH1NȚ)S~A;xe񐞎CDٖs ol%se!/N՜ Hi7˝8B}0}XJϛ ؿrgo7^`q"vaxn}/ xrк0oeQm%@OJ}p;Y]xyx %dCxӎ;!46Ï[<;ؗf@2AC# 8aolIO|9I"xUefݙ|C9>zx3R/heay@祼N~_B(z;&Z"XHg4$q``1H|u}MMy #sq[ k$g2gH2̞5lC;[p=ycKC%)EDAgp >HOEw￴|v،2 ¹9FPz7P*plm:g$;9aOGNԽ®f}D7tܼ3AR0Q,%^N6%]5AS@vc$WVeIFoO^xTr{Tp+P6.Ic ._NJvX[9iۺM>mеRT)4e0mCvpAB|p.5LJS2qEs9z’k:vB߲3Z@r[\jI2T> ܐH|79p\cDYfK2pi(ZTh(8^`׻?grq.RoHZQ]dtmekfeiXQ2 S<}vQ\G"\N!|,y/xC^SKp2Al]Mׅo\Pk]ij$Z%sHM|W ,Nwv$˘h/HC_QQݸk}ғiMab&hm(5BBI/tRL@r[~E (ւJ<_V3s>zAMA;__#"!{m:UP 㳅=Ay+rE^sk++*n2su5 Al iNΣKtp)M<_;(p}MyVAHEjXgFyeS!oN Qb*,~+~ x1Yt{/o|(U Q7# 1q4djzozup6[<̌<7^+ܰLtT26bkxv3#9vl;0~t\ #fv{PIYb>[O~礃"Bu_=P'rzE'e?!4dN~-/M:6QU#ٍvƒof!@gOQW4+ٙ|hFN;R>Լ;].[@ I]bDsAu^Yju#ԬAq{L'8l$TN}t d:I!s7}Py:1ːWizp?8fE(2&X:-o!UqS ub<78qn5NBA3-ͧXFfML n(-%v.sƢ-0E ;J![4- {- "%#70Pʣq6eF ʅI푫ܭ.ov&'d8 v`%XHHIBk+Br-- QXjZ6Ҍ'" I8j"ҁ3ٹ 3+sX_1Mkkb=A / nتN\y׆]G,QT߉O38 _zܡ{/D{3o2I H{Y]$3C(軣Ѫ2q'puEdVTn6O?7D"G7A@Cv$PŽ[5ʝ6&(k"s:ph1$/ڂY Sc@3jL7 7maΫ|~k0FV.!7Q! i''KgCR%h^, wKɃQ)@/Z")h(K;g ,[)N9'Tb*뮅OK@ 4vAUtz8l[@E^b&"/ NQ[@bmL%L)+'WFgC5  Ӌ31F˅6&cc5| w5/BK]Sg}g+)W=eWf &1nlI󼃳F\B^jp_F%M݌_mHqm٘Xaju>w~P 1 :~_%!._<yў2oAbNo`tH(qtC̤Cc1-Sw<[~,߃m1la499l,Yuhe}j#\;!/2қ9iwrpJ_宅8t_J }H[UQtwrySpX5<,,Ik; \ƎI_; 3Hc6\b ~!CN7%]!o|(yb73}D݆A :H h61tQ^6J`<.T2Fb 1fؠ '>ﹿ/oiT{ 8Q!-ThAn8| x IaZ۵永5o7KE|`quGW,ݲ90aHreB Ϫ7|Lн>.H$d(Ͽ+]PvC`blл1)9x)+Bٟ '&6f4"߂h.d5V9ꔚݽE`0ҳ&? f罇iZc k? ސ4!m8}.ݣ D)}~칸V@ *foS`ǜs %A? x×" A _ifdCx޷^qs]3C~XPQkW7i_W oz~ xܪMq)UvrQ\X@*hUjQ/z'lMNv<[岫xºö &qޡ#hJ5[Ӭ˯ZiR ӂ1b%U*ydPnЇ}/5nN=!\z]/v{L{D^<[Vu^qg_~O_P:7LKN%mv>3&kbLo B5(+=\i#j}&zs=|}^;ҿiͷ'[ ,OIaqt!Y(/5.ta .2 7Ӏߎ]8pK5\ VAGP<|/Mұ*)!7"%lBwBoZ/$Rr/n~[K݉gǴZ1NJ1/Y)!QJ SG_w6&Јty7jP*(ˈ ]65odIb?EDwR>6ZeiR~\\:^z2 %#9&ԙ :(yk#1G0C0ߙ#I7!Żx('fW=zI$@H8@ylqEzq{5U䡕cCTx;o׎ӌn; И^=-KT_|]}mMͫD׵Q*!ElAq—{;Q>(:x Y7?ƽta'Q.w p/BGv 2.phWz3N%s^{֡~)SQb/ueqO)J %=+ڃS,"!uǘsʫbɋ sRM=hU운B!/H{? 4+boL|?Z]=֎e[r9qcFY ɢ:z4`pj4jYU2DO4f]?Ĝyːl| }'"ұH aWya1o)B:Av߂Vc:"y% {)< Ln+h\/* Omh!;^_aޭ{rG]Q kf ӲGB{ ~4Ё @o_SFV8y~k1BJb[Y¾KNl?-?ekmyս߀R=ɉ~uA%LsYZl.ϲ};etw7y09[YbНvD^nXmv@~OPo {p*ݔQ" S$3NOSX{5ah Y,y8jǸ7 /Z ;<^֭Ʌ؄9xZ8-}jX>-[2<~z M/ƐN$גƴre9SN:R$'(2;>{@-\1DKʳ1ȕ  %' 5{lNݫ-!_\P%ڗoֻ&99&M=>Fo[ iGNtȘLNC,@h]4]aJ⡴^HjebVKy7@ZF5bz{AJV-bch5SNGu_"ǀL|# XKvh,}LKHY=MD)3J*0: (7! D}u+'Uk8WcgخbѩB}#MRB?eYėJI{V||4_Emp8/I>6 oapblOA^"|9bt Ϋ_#fٍ2x8tU?߻ Z$%-=owP8jµK4f @2yagB^ID`Ty'\6_{A!x\/rxX^\euEa)8cA#7WXE'P3g]Y.  6Hfb1M~=iD_`\X/᱿ d]!es?R^{z,Ra`L b,9b~{|WzPCfli;gcM^zU:+E'M;dw4p`VpuSnV^t@/7 <ia,0&jDxiwHôж^.FYjeK$/VW}@\(5D؂֥M Hƫnm-˿ p[<ڶ)_MoN*@0eh+`.U&1("obٌ=N.~UC4]' '2ad/j4j;uU iikj|}k4w=t9ns |O+>yw1y>B۰՛HM鱿}7`2ׂ_ar]mS "|~;_:\d9hV `]I"~ҪlggwSrvs-x훪(_0Bge1r4ӒZٰg(V/0!OxUtƑ:;0h[\ 7pAmN7a@X_1o[̂N^E6:K3wݽt^miB$@_/dDlB6j?ӼK0hNC`,sbK׃/'EE8TA@m.nȗ<<9y;\|ɵ&^rux*3`5]Fxר܂;>迶%]-ORKER?u?j@U]n 埬^.ATo*>1} _|0|5|(ڱccnSkϻ`DAkqڵ0Mw{}23 )[ S5X Fn[Pd 05x5D-5B\HޒX~zs %"y/-pi;;VpsY H: Hh6hel@% r[=%Ie\)034Tu70ߤ1Jsη10r,6 eӜYW|[㋄ತ_N0hlJ>|W~t Y,yrX}ӌeU%[ӹ@$ 3rwSѹќ\DA:7ԀA_||8 0w>̓LkS -7TWui>2iyw!">ق4"/p WrYK2uJC` V*f*v$4tHs5RegYbvb$GЈhUl L\䧻9~ ,%Hc|ɧ`B9 2' 6qZk3! 1iVNaz|HN._ J#nyȜ\r{\*q )Թ ~ tDd> LqcenOy¤w=wcgQ9ʽHYp.tҠŃhqyV0%/-p& tv?@myݧ|3păX8STP ":[pȗH0*6J0Etq :bu׾ZL)S@3C~oѤM9' mITqC\X'h `PxQA]F?@3]CH3ToƟ\Pa 颍`#tJXrwjH*\͛ !j&o诵}za3 _T 5#_2Ik@r )tar?n8.hQ :4ƲI& unCY%[hqmΒhGFV y|w4q0#SUo$|UmDt`=Ue\AmNSU (so+D}0$=%-fk1 FBQq=t}MBՂtri Nb& W uwP?iQ:˦6ԋ|DqQ% ^^RpRER]KL˽^:FT.n .J=}c>ʱ}iImP]ϥp燙s#W#X4lv<4(IU+Ө{^ "N_w"p@6A~ߡHgۅ-a"4WO18ջ %?W9WEdтԽnwӇ./ HGؙ lV̈T`2[Gl/;\Z߂_ғ{7ZpA;#sq6bk#C/r=(,݃ح0$rH@z@WX!=Yxr5׳=nlMJ [1ȥjl Ak+/W WЍW:RaBBgI("g3Q܀.2}$y7E֕CLoЉPPFN{sQ$-~hJ4L,rj$cVR&rˎ#+^6 S9. 6H?jnDX(+dYѿ(oіlQw?YK$Q`zu:KABP7#|"-â\YIJPg0S2G M~8ę$XA t=@W>A\&{ 2—HnfZuQhvn3&i5P ~]) Mz/|B ul;7pŕ8&wsF{`Ox6蔂P̥iF`u"Ha*А'T(;%`VŻd3)\R@_GA'.l–rAn0a a ,S*v3( =(aJ.#Kϳy"23bb_ c? F4ID{ņY{&%>Wz?BEĴ4"k%aDƛHҎV9ݚB$LB[BT r(@pCvJQ }ģ5Bw@-ƥ?p*$̠swY#ZtC~dq3a˕|]JZЖmTؾ,e[/8ejp il>7T8o,gL8_p) nl4hEFO:yzכ傼>{.mņ}Gy2鴤ZqdgF-MV4Hj$տCa գ FZ>/hk 8.":=0@tcbstb̏Sx]rAIݺ[qC Iz&O(hwB 3 ?w|V1G`0&۪j[PđBE$xS}˾)[J@vzk֯+Z&,EY8[oa3׼8sɫe#r}vƮ7.󏠕s /4؇((4ھ#7힗+ E ǂhv8N/\(QYbv6&M ۭG'lj,`IIWέv{g麅#'F8$K Z; F!L tNtf'{R:v{7| #)MqN#P*#qwBxmfFgѼ0Mq-75~%{ $[cx>%@h}('FC6MRM>$|"eG9o3A!s26#׷=荿uhcíyҎ9ϣM#S?qrZ162u`qX3^'mo)y*ʀbyLb@J<GjƮ]X ȿg?!“(~˅Yc-!QG|;yp@kJʆ{Jtؼo@Q⩛BGW-{1;z"F '!H>1sw@t_]9G{_$Q{s~p$pxG# `f 5>겝F/G|9oo7DBn 1j~YȉCJY b\F9R&k.\;Ўf;Adpfʘ<ޡQge a.(pds}NO[IO~*0k8F^_sO|/:{bUXBrLJW< 6݂tis @0g7;~p5йK9}W{9,>h%՟N 8AesX:4Gr w`o-v9еrVo([@/uCEGm <^4i`p9 Į>׶g:`a<\qQ;3$bE+7F3K?MJuĠdI_@?l=n·qU=Hrl:NҐ)z<}9Yсݴ3z.gPE\]7{dȿ/ݸ-suβG/{\q B/FZ۱4>\f7!A^R.NC:%hՏ. +wa^̶!Uj[ C"& M+7I A#̌}*{nb@Ca w8awSy+&כ$T<%d [nY6<), m_Bw 6:$BFMDnDӶS -te|ϐ;7 Xv߆ BnҵfMBǡÅ+vA3|RXJpYl0> 3}lHcڤ~{]ཌྷ>%IpEyo^tz %FԑBm)t.++U?qNdn3^bPʚ,rӣ=(sMY :Jg|w,KckaS @ub3ܯOIȑ݀ >8[emtNX5('؈F0] F+-$/Ż S`m<9`XuN9PH@XQdȭӛejÜTiVJhϊ{XVw_D৫̭(v'ՇAHHwbq |!0  n#p$g UlYBJ FC AƏ3A-'w1@8'4a V Eoߴ[Amp6#kB5N0]la." 9O#tzc' qMoK~tʽ݃FAf5t /d%EhƔK03k`v"R(NGlAYۢL{Un#5]ќ#EWy[QaKݫ_Şi N{9Zf3r {t`uedp)-Xɒ+υ977oE o"ġ=)ͷ4>H /5g{M.?؞c^f6_̙'!*?\=c/;KS3Raq^QIPtqC^N\7|Sѧ//g7Or-J)Pk=ڳ*u9U^П:kC8֍Qj{Ip}_v$FQQ7`F3CNBX )[m6y2F!^ =+% :A=օ.KL_z;͔rPJ{Œ>tB"1ٓ.9@] Zk lIL>S+gN6(4U^J|P(c옱YLa;1)08Tm;-O.v%5 "K' eAjW^ K=sT/py-빶9lt";vvsf?Y] ;:[ޥbE8)jf>Puno0r U/|S*eۖǰn滓JZQ3-4ۉWb?ZU nW%p,r+*SZO_ﳧ lL:hk,M)JlkaD]جo! w j .9T +x YB5A4:YqIb K irÀ %HmY:Q%4)9l(TW[j_+SNx}/8{ ZAKuNy{Ra<)92%i*X]>)!! m `il֯E‘}g!_a.+K>6}܁l~ d>~{i.'5\ r{z; JH*+xR;QljXJ4_b]~b'V>ℜp=}|zFSB=vOl~a !`9R•g m< bTϮQyGr{}b\op5I);dc t5[6:;_W/$കrni %䵳/-%W"A.J5{#~sN@2?,-yA$wN[6Yq.s fmv0Gr.TU:3Z8Hc$kb8OLQ”K]c3]16vӈU̖?r\a dvOyʬǦX}=g*Ȁ1ˬi\FyAA!х)͘yύI@7H^(;3G۔g]K\/z0 I=d ;qq_9Bu&?qZʢ+x^Oq뿂4j (3igJzR%ZLIAgĆA`GNA'8H >l8S|zd$c$fD@8jĐͥw}d>8AN;Ьyyhjhy 87'mx%UO7L37{B 2^qA$ .}P{VHhIvl^ B!H``1ǛH2 Nvեzft0dPa^zÊ9smxQ"]BB< S8K*JW{WGlAoO 10AK<yyEÉp} p:yV^9WjD̲&^)H)9zkKIq  CZPQ9ӿA$MJ(<:CG>*%٦[璒kjH])]{>ZbnD)#J+<"2굿p~2d=ŇTM ,JJhW{0 dQݾW3Qf@Cf4É'}+BLuKOQ8{+QSɡFp1 . zEgpW{Xˉl[5 (֫+E~y&E g&&@Tef B'>FoʁV.aՠoW0*1@rH8R|23'ݑ\Nւq%wn|rS$:m7o")( rbwmΕ$q$[Giw|Ѧg{2.jbf /Nl,`pb`k'oX,?N@Fs"*AZtqbܵywCjN.+{A$oLu7.ܵ BQH :[JpS˭ed?,I]؈v8vR>R/0. 3J,Ήgd\Ṯ/XldFo!~\mxv03~C,M:ۖT \'P'8@G@N=֭_훽}TCì;f{^PۡY;&W?P<AؽrE(k+M> ),ҩ_%ʼnTc#A$bаY^Iuۂal=[I&o9Lܤv{\a"|;AuBg5j~kKkkymfyzm?Ewfͯ3}ʈ_~DY+ un:p;6%xҵVq4ZN>:;R}m9W B QEc77 n \3)RӖ|GoM?Dmvoݻ-V&ޟLǽ mnHn>*`B!p:/*|"yeK6h?śF@pM)dx57c'@)؈$% ~O*ȕl5zIM&/mm'Ũ)q5x&wayElO5on96Ā,p`$Ā@s#R)^?Jpio!  f|P,f ?U8ANnͅ;ב~c.mEE[rYz &ObҌk^xRzTq;Ԟ @e]L@#M2!x^D@hX!cɰݝeqӚV"?F1O'MNAʢ\7stR2aX9\>s`^A1_W [F,3[^> bj3L2T/A[9pG=kI;Ewf]xj+(ϾPغ 4kL^zMृ?呓5s=4x>Z=yU,ĻS$~m5i Yp:6H=FD D |.RX.t/'sU 3Y7~Ǝ%yt~eP=SA?`tnNOXbDQCgpk^:YM^FUbv^^H43:xaf=_}DlOς@@ ]_?)vp.ud h,zZ DIQ}j_E|SG|S1$˝v@8v@H$8lp-7JoO/ V[67?E'tv̄+?k;_A5V쥣T7>dT9b6%zYdb'5 [fE* `$eI*bב6+Vxql]>N;#Ji_9ӹ<$Sj=๨F:ݞw ˱w$w $u.1GU 1uЬ=3owW"CL76g=eW A^uu5jŸRwi%~{m.!o\r׳p%Ifw4Vwd2׊V1Kocl~ǐw_/}ܞǂ(N'Qw}]m EN?89Mp̂07ʧ\V#oϨtVkhPs8[H66ּ\\Ы#?%e]qu8[3]EU7# F'J R OPpu*B*4saJW&a3wV ^ b0R+& {IL Iw%`2Wv#d#h`j*3Lyx R2ldO Na+D:SoZ'^DGjt"zf ravElSCPaVjY >)YrmOel$=H/da:]e=4T(b&H8"\q %?m fq'I5`5@Jz4~|oH+Z^hL9{ dưeV"qm'yMDydi% ֕P_ɲʶe? &@QW=@ԈsM4h@5Ts ߦ=?׈P =QJ&0f\!9~YTd;ϐU  hUB!w'+By9^ݥ[; WX2FbZ2, v~GHz[Y)OeDäv¯\ل6K|،{? F^=QلkLI7; x<; SN&h^ ʖ`l]]>#C*џ@|* ثuX#cIr;+Vލ`̈F}co€b'Pc]W~y&%9=uFvoV2cЮ6j[ W0CSVh*_ad]efEsuǕZ]HR bW.[ň/ [V w|tҥ)e] y,]^h.vc}^F ib2Xpm7 ) ɠħ9ު+·>Kb/I0,)ZO ;d]z1E9kKQ-6R Hˉ J!~V@Q~K<|JoJHKRMԚEെpXnO2 6b|۰؉j~;_1z'ެq3|m:3)]d+TR)8yޫfuEaq3d^JA9lk l뎝8 7a~i𰆾) A B 'Z) j"3 _ !B|.Dc؏Z$qjh !)4'^c9dp1+ק|j8gk.~] L5Q j֌Lc}(]A_f9Xe0!XFcCgm}u 203耘aXQMck*NzV;͹T[ߌ,*]\]cz^fxԇ0o\6K1zXn$U6c/ObF8A' EAc-Y@`3y0c8dUǍ{[|e&7H\8ƨCw7}70U "lNgXW)N_c@*n8*?]N2H|, j|)ZX cFu`z3^dPxmRTLW))&&|U~GGC. O @A( ^y9g:Zd))|R@1ͯTZ hh'.e@In ǁ}c*Ȥn(WX.sVvP \y$\~&+d8|( 9j:pӜO:[}. o;\W+2o^O'LUȃZsVi0Nۙ7:Roy JpGKX ՈKiIۡC|@2derB>DF1t sYmayA[eωaoaE<\=zNu)d7S4ݴ5 #!UE6Ȅz 3T,gwP\nIM%{%W5΢46 +u "{Np"z:f?9jh\UeӶs5CRS~S ,,2\FA9tݯbx7fbp1ϓ|^-7z{Z0B6R[%:Uhw9 -A Ze4;~9 4jS +okHJxKg(u)o'<$ q$І>/[G{⭨ t[~ v-Ё'M%-@ =8N]1ȩ";;˲VIN{۰lVȱeb JI{̑X'[]Xsjܪy8PCisVdpn}D20mtMWGk9Ōh;tK*$`[ Գ)QWzzuCR}gvK+vx$ڈ9\lw+Ltg=m.Z,o);kF i7|\F~$ڜ^Jxպ۴Jߣu焽((_" %^Up߼ >Z)l*j!CF۟,Xp~~-?/ -1C\ Fc<6V<޶vY'2_+&y AP#RQwu1 |dRL)Gx 䧜h0֞0= U`|Tr+ݳBb;V~RTij{Ƿnu$nfZ NOxQ$c]|˶ #ew,~\85E~O峡7> >w!Oփivws Ro=xb #Z9Ar$ˋ64:K/6l~*͘~h]Ei&dmjK 9H=`1ִ.Te[šE#62(Po^BGg]@7jON\D#tP:ƶ› z9#oTK&pZ#‹'hK<+ wCt˄%x ~䣙gd{*se>Fcc_A?|d(O(͙bpKVf/ _ ӟSg蝹^1 I)#p!E2RSVAR4;vdŷOآEcC,U9;fˋ}b3I:ŷ%. ! Ů ɪAL _v⫝B5\Dye~E@k[s`.Xms66 㷌oXzkQ$Ni@6[t8?PI; cZADl֬U["ӧș}<D~T3s!8 6&`GcyI e@&@;g:BcEpuCc)c;^ēk ٻ ij#Bw*7v_w+"&0ilzp^!oQYzC\P&5nئ(+M?!|퓋h-zaegoˡOJɕp'"zM>*HD>T,1 yHs~2X\H#EJv#s5 = 9M#^T8_0{M(; 6/gPv@(UzcWU)?cu`ncuYƟ7>eJ0Ŀ=,'S/,tGQiaYk KS<ҩ $$DKX X2s<1Jjo\Xq;Xز~t+zc0CAWN7_Q*+sl0p | X@9l-+6SCY*_9T%E_$U3sd򎝌nizEev>'A-;O8y} WLx+&8 'E_PLJz\bDBNӐ( ۦ=6h2(GB.M7GOWN8B֯#q+5췃E$CA~owCMo/"Z'(7B#FJ^|A()ٳ9 ; &./&[ޭyPm8lw@~SJEԡANΒESD<;xn '|2c_plְ«M1a cI\9+ -.잖?6<-͑:` tBn8<Yb"][:Jְ&7V򖟜}(p@^< UKpbI(Z]Y,[3;8w]'٨UGو۴7QQ/8U {[˘Z2H" j$zUK p~julj'H嗯vpBR c'aMo㪾Q$wkk\?f(!K=0|`U^`IU,QA0[e{mfq \P-u7jwRB!@" -b¹S51mrvNϾ0N쀎7aB本F}be@nQhA_z,WlCr.'8o˹<Y|z;_6}=J(* -=Wì&L![?.|)ષ;4@[dV7kSѴjhrKnǵ1x^~zLoMy2ǖUu}cO?p,0cf_XZ1mCC)<0n$Z;oPՌj ;f?n<`/rͥ~jRWlӠޙA>\5ǀT==0[q(4/Ў@TiX&*Ќ*z Yr1n( @}@ס@vJHM m'dYąw s۾2O+]z=ҽdu>aa3NHEz(J{1ءVWiQi rxg|*C Qcq}OfnPrU^$PR)Ѩ2s4aAR. &0n9)Pk Pdrla )*D5#Qvb>"n0\=IYoGW@Z))iv nk}YL\lU6?\ԙ炽\n! ^BغpE^wQ4}eg|: vF$H7Ã!SMQ KP'F}Z0W[>y rCI yK,^9ۨ2.wRAݾW8PDɻ|4/NqKplQ#5<} 18VYSbؔ_DN(NLĹSe+xܙZ޸IOcG^C.&T_Sڙa(H4?ȞPb' u m {[Na?om.Exe@`(-3/7(s?29w ?޽jν1rA6MÅӫlj+.!}g l$*YgQ.P)&/1~wlX(^z6$#}"v^>mu{0:Ąù+׆jM dq ]6ΚAݓloB$3]53/:eX5%7kX.p)x]T+M',g^8QLЯG}(Pi o1ՙ ^}J )L$'# c*r8(UyEaoJٳ' WLm-}<׿G@AU 7̡6M5L(1xD+\ ӃRD50(cY`2ܔA#.pyEۯ. u='ҁ-\AisBm@zsCJ3q8B89M2 G7kوM#f|pZ}BEeD.gD3)n#ߓlE9ā!>il}Z& ?=r5xH:"s~G' iF 8Rt0罨`Q&P-7q&4E3=O(ƑclnX$vm}In(1G?ySd1#oE ;zDtOOf ?t.N{gB r 0^`>'2 e=G#A^SEu.l <:+09$s^|1!:)n,r'0 " .D[(4u1>VX ̻00laG8}S{Q;^sun?H_ا]y6ش߁It/RDJ#r8 t㸨KS@az }YsD;9mm:qgڦ(AȩZ@ExȲɀʩy#\={߇9"Ў~xpc|XaiOƽ59ڸ{9sR#@S <PMg<'#80ڂٙi4^'6~Gx0R$|a#ÇT=F2a6Ug0BQ16* ߡ'+͓O#$&΂}W"s{;;7Ja1|2kDC';ǬH |9C$>% iφ.IJWXv]\Ձ7'@Aw5Ϗܹ4$Ԛ?q.b -"1LG-y]gT# RN*xDNXo4%}"6i|NS~vQ culBv)a1yzZ;Ƴ =\kXz $VVxg1YtDwDmpM9IV{U Ozor6~6*醵ywKCNX}`V纶˥_s-mSI9=*nQ ?.G( P;n`kJr?^׃R9d +A jVۉ=vs-0sBe(b'6`ҮجH5 *eWc=x!>:\*6J\u! YiK#ZQ6NXJ̽^j/M3[9E3ѧE9>+EM3I瀻aK]W ๢%B>&L\D ]7 qlA=uN_K2G:51*z0M/m:sO?2J^+9i1U}jW##>nb$HזFXD&S,w2T"?F߀ J5Z{ _&b:ve)M4)pAHF2o,=}X8.ٟ$;o!XQVy|(dP~$\[.5N_zvl@jBtycڏUC[2<J]Mn{ Qe,%kA7zrzL}M8.]f|--8((lbc5%|`)&#w'"85$3˯0+jK`y3i|49R lR2U\☀gD+wْo6@qܓF4fZp&Ns"0J@dwY/س!d<(J;ܳG-w7ͣi){NlGf`k{vNUo(6+L=*"NIA t%hˆʝ] s_!>bL#>ƨ3<$'wB}8cexL-%4MJ4(q SC „<DK۫XVu[]r fv 2 @p;Z.D@d#*-yr(7c馏iw yL|-@X9 vn{g:qJb`/߅Ыp{3"jD6@v3WWIA,Tuxq̽W6qK$T<>׽n#DGA]K~CΫAho'~wwH^ijF&̎o ɥ ofrnMww!cT~߲gFknomSdyz TuԄhpie;b]j "zYO[!$onHʘWȶ@]}%~ 'ik63~OJZ5Ze3af2DJ^JQ?4X4ݍW*(% JWNsW)n\r Ds d *E*ⓛ,|,1AM8(;:4rlݳ|OSJ{A>FAEXK(bsL +8e~K8lsa{trEq.n&6WӓPPpĢZYln4h"druK8S@= <-_3nM}*8?f2@ =sIG]vGw=>I9Yt]GD2ܚ۔'G[hCC#a+寉w5 ɟr`e2!E+(߀m|DL.qrbj~jW9k %r{r xE5ϲ'eMϠ ʺscEźuK,W:y/8ˆhh,ih ,v`y[vw zA f>6b=sKN774:L[]֗Z"D](,lL-iaCݼwMX)k2ĩE  1Shj=2Ef ? U< Z*Fߤul J˾5)O LwDӽfR]ԯvi= t#&=#jwnQ.X:e oʐHsk B8DHBzґۧͻudnWm9;uj'X4 o@.XRT^YMF';bѤl Os$ ~{ԭTWWD{WI)ᆱ_d<`,XnXڋsaLo'K0|&t;ʿ \yIo(g'A T)@ЭzP;t2s=t23L6.>^pGfԅs=^XK!?q~;J񉑏F0e5Ϛ  ĺmEX7|H| z$ǪA?yqQ4ӻ>0w!<&X"9w;GZ # ͠>6u@GThӔyyvܴE ] r,fbîAlKڠkg>>\ QEfoAͣ8g:: ]KگJҘF V&4D`BH͔&Sc>5Lusߪ[}:%_7`81>V<ހ# (۲(/Ul\+߃4:!o.ؓbT# ~X0WEHG oDc) b l 5ߚ*';oZhf3ۄEEZKhgw$)׈Zz{ ZtK!#c6풖U >=~pm:`041A=+ʸˌw^~߽M'ƂaT({v3S0tu.Y}@&Beڈո(HHpCV^3Aas:*籝 Ey/1So_>[ ;\: sR;߭wK\N\ӹAiVLScYr}gI8SxKrZs,A_\OA(w[UZFND g[:Mq뛸D7 !H=hSwX 8svHW:A"5:[n/9$̐z&LŪ,=a>Fʥ3h"#)ĶU7$S #7 @¥^ 3BЃ'pH*pEQF 6ȵ._E_~5~g! 29a/0q7;D16^.kﶘpKkQMp0-hP[v^6 t'B]+L)8آvSC /fI2ziJD,GTT^GpN%^˵߻u2՗QкMD%ktyI.X(v"l}}tS-jVCCD֟;l1D?qU9ӛv? wB I\W*PL !N5TKb;œ_Оo4xi*OB5p{HC7 C֢M%rA72! Dw5/!Q_譍QPT|?߀WV/8Vu:4Hn+i>Dd Y ߄ZV[5>?G}29P >k*0^/TJa  (f0±"4t{u !C4FU$:dGܜ7bu¥ 7`45~Wu?ٌ~GC[ ΋oQbz⇖?y1%&yX5Zo J HAcM-`$N96'%9)n*S%6/jr - q ,\~!>y4a˃?}tnwgTlEIt|FSGQ3[fy_U@C?X\G$+U=TfH6*tDLTnow}H)gB?~dNB8lPPRRAT;zCѶ`[ACq#5 8`_$3ȱ2㏈#~u!unK},q]䥚N|?Ÿ6î}w(u o{(uv ~甪 uj92ة[b稪CC(gv[]v[̪v&.o WHN DxV)|t",k8hI14bfҡ6d! YJNͼ.'AXm};5w/䨽E-y㇐PQkJ`)D{#[~hжؗ_ލwdm#*ynDU ct+k9o}ɀ2jbmܩw:]`Dsk86Zߨ~PP7+d$Sk \oS?f[0DfDliMіʆ>b J~TC]zuQF4=8Q@\ƃ]au"wTLͤ-Z%v# Y,_Q@8dLXۃ $on\kW`|Q/B˷8T4J`nч/ /[a,ƯT˰a^fڽ )!K9IA4l-"oBHҖtaî CrˆsGPB*;KiV8N؍ 1Q5>gh{k73& |q9]У< |V)6CK7w/|~pck4#@Lu]g<PJt.(4 #MY %c N20#!ߩhr:qD FEǼ AW{',P zmZ vw~Q(@#P, t[_乔a? o;E{.4C˙,CyP,P c;}P<љ3+r} E[1oO|~X YO5!d5 E]l ^`¬ P!FC!{-(lŞG~$ U5 }rveBj^1j !O#\$ lI}fu .$}MYhrdNH)%7r x妆/QlO#;D7Gt@=Ȏq~|Im*TqI{ /BмȮrÚ&^_` 8tTPn=XL2[qJutKgNE_2䀞Ԅ=7 p.k7- .T icjQ ='{OjoM9P38du@a lׄM2xѿ&0/elY2!|r 8`<m6& Pv}] VR{$&x7l/?.b}r\/9ZZz NEq;6d(-Ye4PZ\6㵼:D# aŽeSKW46*0 %Nn|Ik%BcbE>ۂip4JR< c".ё5}X}pDž;7Ѫf ӓ'py^@Uԩʹ:+h My{n9AVgy$W%m;c 6l-ʵQΝZQo`ݞafq/D΀1̩!o i~tOik0ڱWizPSfL]}>GXxwx񚱞lO)4 qtbR:͐ٽHATS*(d*J.<l.緛 =*,}Hᐇ7mw##Sɴfӱ =Qe hq%q`%~Q+(h儮c^T9s>LR '# ̅p' QDki%nf>nԬV3{l[G%U-)>ܢyk񖝂z'>gEkV<X zX>iH*;Q\ {Jn#1i?Rt`x=Ptn:ӚxUR 0gĝ$K˳SNT]E__n7N"C,]CC}9gq3qadC5%q÷b$8vW,XX!Z@q"k Zvgj"NDL#VF{+tV-K/5UP 3>ajuد4uhg{#3מ,%`ʕf|o^~YsNHgrjD<'mUAz]X^ͣndb5YvcHfw hiNKPڌ%HN-kpD0Qaug ԟ(|zh4,+ +"V}F&*ON$k*XpPȞBA'^JiW57 gŁ?-zˊ`Aܲ ~m]`s6Keae'6\x)=|]pf;;Bb5~$Kf=ms 9㪣=(pmrWS 50WT:uz49-57idJS<={)5t|rM!UBxpʤI敛fbEHW=A ~m]ɣ 3+<2FKg,aH8-MIdMur )dOI9E݃# r&1}:˥ Cep )3CHoĨ 1DEgc|@.z'~ΠܗO6r4,IJC4ΙW bSؐU]89X\nӠ!WcEM)\tMt7 W"(Mx{ ׽v_QNbr6Rco8 d7rڙ4i j+f 8Ov]5-uxu;5>=f~TA[Ƭ|Y>P#xΊ# "`. X^8@B|k:'婮_!JD`XJ} 9GzivfEO9¬m,4 joSFiOJm;@H#S jmRDjڽ/Cth|O*UO@euT6#R kЕk9axtm+!k,$?iIjֵes?D!,S> vBR@!9JTU3s>eSP/m B飁57I&ښ e<=,m<")7\iӊ(wJ(H"[k ,s (;RD:2'`lelADx^'))yOXxUQg$1aUJ{x$lQөB^rl¹̄Ui lL0'|1g ۢ{/i CL~oׂfT!"W3;XVVڥRras>o%Zðsכ6ZHBDJ`ʹ֨Ndqz{)=ZdM, sfAKhU!]T+M qԠ^u M݂M:/1",OIG6xq{? a^++A [#CQf};{`OHGbe.87?j)z#[|PLt,C) |d/P(`cqZx#P~%w N;5cOWLeCb#! &2Z s/Z(zU%fv2iXZRܲ1/fo xHM.U `A4'UMhv!zpM|ؤd53hd\>{ }`^yhQr!מ"i99Ԛ:`݅4݇$tH}Dw,(N:^pi4+7r}?9_J r0մ`^TeG̜|A dѾ?%Y/ '%g.Z%xyڭ)2{Um$?x]H=- F \`3 =?B 1bЧ>xNU CUɀs̓0@%WۥISlz. B` .6:/B[P6p}5 7gyONL'L@pZ=[bB{XϘĶUHV[!Oo5 -E2mhFK¯WGa17d6Z8ʭ}z^׮2Vmz@O L 4/ 88/nN NKCo3AVc} §7 OPyv̘Q5EiYWD˱H~F^ѭ4aŧA) L^]ȽID<ϡHiԑN 1 pݷ-2IM=`_kH;k?'V0 |$qZj[^Ga> T爽͞I.j>xo~ykUsP? B1@%_josޠӐh!(E{'R=s۟!^Xr 4Nm,۷Qw/2[=5AnP9Mv!Gc  x ߡ@aZ>}%,<{]zy6Ya㊓Pnq)]okSE/cޗsM| =ޟ Fwg* 8Mߎd˄ G|[l۟?=GzͱW)ˏv|_~>r/?vܣj6_4Q{O8_9'p&#m_?OESȿ~Zyv~ۮ{^^%@~6bq2oox=o*s~w›_kiCNU6f nxQ$C?_PoQ<,_ex_4rU5yE~ ϿN 0`8ʇbG4YK71:OՕ],E/]E]A#xItZޯۖytK^Irq 劫dM17զFD]LSVlþtyM &,KA #L v|u<WE~_=ui 1_W.?֭ ܳ97l\&~~aGdFy(][~H+q9uo)͍!5oY8>W_7S Bw#(|wRo6DI~*jD >1?oo/2s "=gLy‡ce%ߟoq; /?>nǿq'ɟ(JǿA_ǻ!Yvx+9&kG9I GU~g?h~ϿPhkw[taZ76yOA~m߲U>~ M9-Kϧ8!OI" 4 ,'{?/!ZOW?oi<@?{>߿"tc] 0/'VbxJgrPAQ<(*2,N%;y, 9eU|PL|Dp|ّCue]<;-N{aEZoէs]*k9_D@Zީyq߫+M3N5J!@<צ_T˺tEv;<56H]Ib4Y+n̽87yͩm^. T[|#P֫p3#xQ_=so5gÞ`E60Z'kUf3!B8Q}YxoN+{TdSݷ PAS&ٻϽ}uHe'qI2c91_kwScj2Ӗ$ȌRxr N,Os$NJF7?놺HEqUr2|2HH S11fkz2]|8F]=U)gmf x?M)W>Y8i4Qb4&]4fdrR~MCߏۀά3v&zN'a03zjsɻR=Њ5 δxhη|PM 8P,^ |1J̀CKi5ef'Eg6+aWҖmCڤ{ y\sdΗj\WqAmF4L[H5c\jXA,?Cl6=g"^/FՠX:t1AV|oN ʡ\B]۳DYKG>oa- `ZSrELK79Em܌t:ɥ2!L%u ~H]3esJߒ41X(+2YI _6 7IJ6KQv$_Bd^QQ"tv\6%;j/އu x*!j;-,~oշ]lli6 i˛MgIӸ__@2!/C2ID׽FudÉHɟ^4I OH~BJH-5cxkHZHg^ll*sYDVL[V X&O|Y5E{v/=L ̓^KA@x܏( ]J4z1 f4,Vz zdrӰh-pvZ&)ܮNw4fdp AW[%aGH*(c5P'a3XȜЃX\ҜNMӬgmŨAǟ8?:A7.ob4σ5ۀM>J+x#Z`hm{Z{S›~k!hn 83 mx1o ه aue2a/~@rßUtәc +H68\%D)(%>\mx=ΊXMsO)X#E%:xJyiB &)% >{aO:x޳<0{D$,JV1M+i@K)9+daQI>7^dHLDU0+^d9=h@P񙣛K(<ݖ+7H{ȟ@~$ !< *7H8U$n>"'=ccฅ? /bOrIFXcOi~#U?#Gn=Qs_#BKI7,.wd2S7NW\ J-nKc2=3.-PN^>l#)*yf~Q J$BY/ǃI\W4|`F%fCu;+p9(W>cX=?8F/E\>S@BxAԇ(,K#3*ļ(n6Wԧf~H҇Acx M6(M]@ +s˾u)yؽʻ1^[ί46`Uy\=\_w]\̇sm\?oȟqߎ?{ f )%^kFs;Gkҍ{>L#Do/c5#7sfU8mS'S|Ƿ} 3_~,#2xE'vKCtQ(;Yg;,斟}S"SO?jnr}Eh^kG`|k0!nk/:NCs7o@hhqg2K(:HglNF{B$̀wSefHtQ*0JuN~ެ>h,l`͍4^FK`E5Nx^+~=EG4TQڀIq.@]ekiFbօGrᡘ]oc& 8u}1zY,OKő]2ZGt~`Da_wRh 'WG}9uo/dfExҏ5UnATu @Ss~bK ?6r:0r#ĩn" m5wd Wbgee'D4V\&D+ T23x0l8g$)ap_R)t1 (}K6£^ tgshГo({I7N;}ڴԦ7A>ox Mvf5 z7K] OG|o="qAKq./ KdABH={yi]j)EZy@~ g:r B `#CS 16RqآRcgwH31W1㘿capW;v87zw zgsbYl¢³if+PǫN58- x !57hp1DSWk3xDPt tj WOb\ѧ:!(t:ϔ%ȅGƁi, L_xrRFy4ξV}(דF $m&Xl_]:a6{DAA-0eX\V$W^})@gAAa)@&(H p' 6W RpuQ᳂ T?]p?hB |;RpChE:O8(GM*+i |~`;)05{Y?4>iO%٧B$PR3ZyWZŗk B$_F%V<9lC{Ӑ1¦cXPx=60ۏ36dS*K#  0Z63r uGDFg(sl/66v4Wt!U!wWL8O ɑS[f4'Tը{\č1y5\y-oKʅm*ߗ ǫ8 FiۼI|gT 2n~ +ئ-36}Uʸ Boߜ;U8|MxM"iժg%=!<*&@@PҢWchqNa x{§taCѠC{9MbJYzX٠DCQ)WZ3L@9^33[YxZ_v#YA6ͼZcˣ¯2)Ӣ'O{i[i_N`[uMsz#S<[ib7M9jsfBZM}DYzZ<.=rWNmw`l@IdXZjؽ1Vx%[Ǜ}ČvSۊPIh fq\KcDzeGn-g,LE {ݴTT~n!D^ڭhtHShaL%FL[jVh@;'G}h ǒ%\ׅ#60hD*%;)'Uԙ \&+dnv C]zN8@XÙقJq\rQ*j zdj)m>k &= `Lu2;7rfGOIBg+)3c凵 Q]4f7)qMON.J{4Yo~$g&mRd $|ldmzKwY$k$&nK4/Yc,sP\F̅=;WE$,_ Ut9Q(2ap)vs؂pvO"rYQhr,1s;qvp$X9 qgN'Hmi$]uj95ҨnEC!/Ru?kn-̓lxk.,K(%IQn0h/Jv@ڪOf<'L";El{iƙl5+:sqt0C B'`pT=c1c.ed6&[X,ţ za]lY$ #Kx1BTQBWz{JLVPw'Ķ 2P6)0Jv z B+sd}_􆷀%޲]ыqD+)})H$~ C7|oAbD_Db ۉ H,G\A:r=#Ձ15h 7>*V≯Im<HYomSa[bU#aާHE$ <] &>9^maAZ79J]bbOx#k?tݰ;3lDLf,@ȃy&ˁRF8S.otzn'v9m'\_P^AN,]$M Xݴ߄v;4_,q/(<^)tK'1"xSN-95gcX~6 e9V.0 U c88nOZ|%tXXK)>0Sg.zoϽWzoc!?օ7~S{ZeX9M mKlI .\Ʊ^J>1Ao  :s_>]q }ZhxEu =rV@&|ʼ(7C^H&A:cs~}M->xHQC<`&P cvToxG'lQ ۻ(`S685׀Ϧ1dnݱ? ofg Bf>1,s䣁.y?\ζNsՏQ?M~[\M9 >=w;OϝaAjz} lE 0átsNcvY&hKFԴD>7Zpt& z)jG'Ric}"al4S eA\ܺ(TpJ/nlf(0U<{\U\Đe=0eLl8Ӕd:dWj~<@d?wn0ɤAdbJMj%6{`sE?>i ~!>#OkH|l#hںbߋ46't/߰0kUu^\3"NQ=馦eL 1=?¥᫟C9C>Kyw=Kin7ѭTZniXPsO|1J/ӽ>꧃e[YFս|s%I29OYېK7rnPDTr'i e8Ϙ-}}1q>!/vXәgQ5 HB˄ZR빅uh3 v=+d˞5ĢHA% *B`8oGyqq}~<'?V/ny}+N_S-/8a̧7r>G\n#i~=tъ5,߆^Q~~'QN4}o?vuG%೬Z>tVY_? Ycu64UkB_gBCtBWwd `seze\$T2%m d8c 'U-JK@JXćf`:-6Tm"A98I62acVV}m"gts&VU,槱Ŋy*EH|"@\ Qi|@Qa$r}OA)fǀSEO} Gu_G"9ޞ53肶;)ʦ6-߾-ylT7}Vg\-sE|%h&-3oGo ~ B3M_㺟htnZQ튴ӃPh_D Y9hNϾȳ/ԇ1WHņz rX?8vLxpHCzd\7 3^6Ô3Nx< Z5,qIGT +ˑeDu[#nG#6"!.̶ȁ K%<"<[̜q{ { kb8wW FEpR늙n爣᯾\[wUs^ǻHg>kmFIr&WOQPY1xUs*)@ ~0ӟ]<ެR?#U=tLL0YFȅ"8(Bl92" F!Z]h}ٹ?-PGR={36 sudBl 7R4JGk4}MP>4!v<" A@zʢ lU6)GUICМ, ER4s"QdܭXM-4E's&m@nߟKڀ?ۧ5X{x tG\zd ]2ltM("٦җ‹ul<"LKvO/$Ԍ>I lׄ"͂rWQ[ӢPa$1lD-WeL02OT%"mIJC(Bi#c!ˬ"63pɀN l)}\@Jϋb3XPǖ)UXLrH9d7c!Do:pެNnet$9H`ą7/\|o~AĞ!W|RJOׄa&s9]]wDvd^FRgnO؃]n>MapMbN]gS7 S#,rv"i W㻦 7Evĸd2@򾘫?D)Zq3 SB<%`bsh`+&%h$e9!|X_ H qɊfRGLEa %nBSuuJQCvf\ZKB{d(^Ĝ<5<=ޞ;P}뒢T3ޜOջW(NLठ ȯ̪̬ʬ^1+W@yÁ Ș=^Ts؏H?!a?&UPd7JA?Q=E^/iȉ,>ggfNe2AQ=Tiȉ"GˍvXI5lN5JN`,8zeZWI=5;]E*J WᤝYu0dė wnF`'#tdF_>trl8e6Ma;9SݰKPk[Id0^WBM D4 cpu7I^l^)Yc}5-iu 9dÄ́>|iIfqzV& EJ+/vάXdBȭV9ًݒLݛ`ntI | ",vY[ &nӔ^:< nx"r'|]*F?L9B#f䋌Ȏu3aF[620Јn96uu/jث[\8VF;1Q4[G3Uv,r\C/^gH-[uƶ(oyA,m, a0؈!Yvz.*0 `#A(Ve.fc}MugiBy|Hq6SPҚRְmKuJLryf^-un}in56͜9`/WWs_ *Uw=|t_ {UUVٗB^ ڀ8Th o_Ɔ*v)_BG^7=Wqx̢4#kSxD9z=Hw:RΏ5&̯Z[ Z+m~!݂0[hL$ c{MGBRzhc)aK&%=Rvrs~YpIRm J]uS*IHRn\mfM<`Q-,J0NmP^4svwZXk϶.KBd8q*MFxyU@mc}_ӌa4(#?^Y1YF,"ٕz7 ǻ Ѝ=e2CHf[DL3wiB(+ "%B3%b3enV=xSt/i*OOn-ZDeh)mBB[_ݳf ڔm၏nvgH©n6+(9'SHQun;V fv1nӱ{_rvA|Fz< y 39nI GWz7Wq}1U5`nk;p$-ѤVzy}0]vQW7 R=skEb+S U^T%z`/gӤ%a YتuM@ , >OȆ xS c<@]y\$vZAuhVz݅vaTDqZ.ahHY7HO ʼn!_G?Zo#9ȟFW5 xbriFQX((Tcd Kmne {"#&GXc Os`Gofydwa="]k՘l^H5[;0"~!  4#}湄dY5DB&;p7qәuU3ɥFzVbcQ8,Qp[b,ٸ0R[@)*R[8'Vg̱"V>k\pt(h$=o_ 97YꓻI9ryɋz(f(|FCfP|7 qP?/k:IGq͓޿3c4b%1fGFxdGFxUx vS.X/56tcg_"H`4>D:7l#Q0bCྲྀ!hK[f xO'ylyJL!"O2HڲVt L2AnuVkY =/2ྲྀ*.<xr=dme|9Rhw4T!`г쾠SPEGZi%zܪfCv@dO(zÊI 暮/i_?˷&/~Qo1S_eǦ77{痗\ڞFߑC  [/;@ ~Kz^ri]52o(P5f׌{#rr=b 5i,gJ&W (³ zu{fv5qtTyp+[5 vR< m[ AsEk>L80%)5/0nO,fc[̂ךv{]$a o0ya:RqU$Tڬ='Sj EOxMKVEƜ=7kFqS}fk^xHx40x_#,n #_{.{D=>{^9Tw@'Bt7Q~vAIq.6RhgDUoT]duXšE{0L>3I`ԥs`jp>)d8 #=ω7">4C'G#īVb̛ɎY5VJT5ڲ2#{$;`o+@Kс?x@mxP{MVL3uWuSkcE-&u*7-ZL9b#=U|IwqӋkdnj5]{Ć/:X"*;Vj|s7s/* I6 ˋw}:_}+k1,kIf3*.bz$*fd :鰅#{5ΕYɮ#?"&n9*Ed_>VVŵsϾЯ[ѿU>o^ {dAWۉiJ1wHF!HĞBؼŦg!<# 4*FDw*er{ ԑRͧIv@6].ep<챤vqeg =+"5#D2B$#D2B$B$3[[ʾ~  HIw)v9LTkO35;״veKaXҰG^^VLM-𫼱ԕ.%LǨkaDx | ؆yZoI3WèeB7`1Prc} @D5@o^c>;Þ0&nlO4U{VM{Vzx9^BO=wJHgH&Kc5'DgP[ul0mbnF\ <),}r̜I ړS,T>@F6F>LIOaGIV9 lFMdp4`'fbDno+ 8w?E*-T<+ u>^%*˫Ox]aF=34:Ga|O?q{qWO$9-^SyEsS(+>UYC<}G0wY-D:rl-湱6y s3YYXq46Ĉ&fn@ecI _)%2uh-Nm3rCrtS-}&bE׀r, ˃ P."5޲2ə*u@RUrcuE-&NHI Roo:ӽW38=J)4ph\pV݅[b(21ٶJTn>{?ʯ0cJŸ`eUdgכay[|fs4ͧ/gɉۇVECxkR=yY䗏(ӏWOe7)F.ã'?ijek~H0<`3W}KOj'CW1(Jcw,CL`PƐBm½7jgE(mdL(#2c0f~Lv>|9㉹-3JnTlSKl sbD@I8qPe7,5b RR۲*qstG6A76#Shc6߾kEw_zf>تFADM" v_J-+ c܌ŦP'u U[] sp z"f)ξӡ V1rVdM#y^*ixUl3[yMWkm>NB]n 97! 6fd ݓR20O~\YZ6$9uguʢ(ޔ~@}k6v^+lY][ǘ~|=s9ƾO;̡ Dտ@GX}(9 >TQ!k (< <U^9~CQ]G3Ea,<_cPmJKNY?ȅ-=bMHOjnNW5U8M )z]} .lXMԛǃgURL`[gLC%G\\bri 7nnU3N&2VYxBjPEeWNy.y^N ,@Ď  u3]$ -KKҵ|醄blz@gb7  (J{oZZq=*2R$+siLʪny &pI =z)^ڛ g4ɹ6J/sj٫Td&-D_{B{m_ЦɧW~EXE~=+ fJu]߳~4^Mcϡ{qy}[_ h;_ӿכ[RZN:K2pPWYWXpr scăPpD#gOiHV7LXykғ`e֓~͞m"->n.Aźdt|iBtwD9=ZX،1]4qZbitKh Z*EMϓ@X4׵q1'8˪iKQSΖQmm,xKOpꄑ&wO̯k[m'-qd~^-ZP= tAV9kv z8;&!wY`Ղ_ y2Չnʍ1[lډkBW=tbQ/Y2ql$̻Fk^U^d/i_/9玴@=_K> |9d==CRX)C=UV;ji]d.ƮuFeJNFxBK#0S/=]Yhc]!vA]+іlBʌmP)W=ֽ`H;Jymrswʋh.D0zVq:>X*<ԤUI;\dDS{eo,kʼSfqiD"ȍɾ9_^͟='3vPps/ću{ɤd>v+]xm̸!V%z? >=QbP |P=s o={xgic墇oLXV)@T– sJe+Jq{^vfgNVWT=e6'xP/uk6΂_cMևL6kl;zYćXK9趛<qUN`iC]Ylt^i YR#o!MNqo%:oV"l0"Es^ 1WĊH( Wϑv.R%x,n-lk`ݷBݒæ4ԙؿ[=n {zݫpcp/lQ!A:6_33,Yp @0d~s_}9{7q<"_YQcu7A?8Ծq9Vؠvj4Kg9vS›=-\~^zsQ>6!(QA5$hD(D>$8s;Z2m]ܞ$Ī*zͶrnCAŋonz+.B@p!K$P,oSS7!Ledi@NI} u:&`2wq"xBd9ꕂX"y,c ntxvFN2V^aLz+-*5kۗ|*c>Kg寈Я ''og_mP_ ' TOS8wx/bXǩ:{177g/~_d>|x!EJHgS> hm/wQ 6BsП1E.X Xl{)#d|hn %|RSіjlvVdF_v{-nd x2| ;Nݏ[Lm*ģ2NELbjAm1lX [x.5cKVNta[Sļ9-/sr:hyM8zecx&3DɕK,U j7nۢ*gL!+RLUۍ}a 76G8Y^|]16 u&4*!fhè8lc;x2Լ>c:%V?x)G?(mOk3߅{|!aYϦ)CQ|nj @o:EBt.## #P_ZPԐ365`G#KhT{;TrsVn 5mHdol/Ow]PR :/xJO'*;g˪40RrcW r@tN 3è "&`zxboeϤ%JPP&MkzK6d &\WSp[&4B{Mve+jvNCA92pCCmj= q-a"4AG\Vʎ\e~ jy^#«,˾ury~?7׃Wg!wO?g>b_6\8/ߞ,:xΌx9Y3o4%bNfyO;g83;FAOwrT/~o$7Isuz8El?&AR4I,O/xؤmAVoɗ:+]1ab@%~ hu =v/c*z~P_ݮ~tGL;+^ÐS&Ve2@ю 11+ltГwNV3^w]3*cbH =${o T6x*=o/BzA' Qک8ȟMƳ֛֛ЊTR &&ZǨZFxiYb,8Bw8WhXGB xkcecQ!̼?afPw_QFk=4U(Y*ogZ/k/~qY:uP Jqͫ[ g GOZ%:U`E GVs~ UдJW cn6g9ߌn B#tt`4OOʏ%h Fny?$ d),)x6㪾3iI}kƞP48G$ 9^ a(Wg{W0o-_m]V jo>xDܧQ|Mٳ!B7/(Mɑ>eCDvY/~P goґo}߉ INύ&Pد!9=wܗY@7qSB7h4:)?  >N;d<CO>B?Ѥ#9WIf M3L_iG)'i7ѶEXdAMfW:\ \LsjԂ\N?PqTϬD2Ѩ\V&vWi ~ sؗ+>'+hQ_?GCXEZD q7|B+4O_dC~"ߦVr![V @#Q4:vR2!v68}Еi^vkQK1*m©PXs߫Jx@^Ɨ&!Jf4N_{Iջ_༃r,+_waQʯ'S/%-ڌE{~ߕ!"N32DhY_ bF/liRr FYs\|L۞F;hwAw@wHu>k 7r9 h lBY0ML ((A(eR7Jyz4.9,KoqY_I\.FQC\V!q:~b 3 ދ,NWINdv28w"$B| >yPd4>`3#zQ}wI{;ҍ@t,%UyNo|zķ"u}uBbgßGcT8W8SRq$u/$v,]ἀ @R.[ reB8xj`"N  c~CJ}{c#zn -jH!ʄEH~o` ?׿B$. WXK' og#r>;mܡys\\: &~R/ H FҤ2\/5r84,g %1 9z/81&| } ;0O~.of]"!(-ߊ%V7yF$~5GH\UߋXeT֗~J6 %<>(n!3T2KC}Ȁ"֧) I,}߁{/ 72`]}ƒ"r }Dn<C%#`qvymL_>@>ҮDsg\[ WUx8e(TxlkvkE[ءveclɩ'z$[O4hyG>5Nz[322:K $]oJv4 dm6i̫ӱ7,YhZaJ{@eI; uqFx+'q-EFRQ5?bxĘs|}<rq{rGC[&SI;q#.o{L&&vjev sj6npXᵰmI"ٸv:cUNhhNk$A3ξͱeF!ѥb ^FEDfukV9kWwc=aO)'#*6rspAzug;aY$3 5bq2Le;Zh­B|`u(y2#0})N!Wcͬ]h/]Qơ1Y!I ڹ<jO^;Wtf:6JsGYrjoi-8|JշmgO]\{٨irhIm д7Jx@E=ϼAP8>5?5^P[N#V9O_MT)a~KPJ*&I8Fic F2ɫSAotqP7w{`n Ĕ'.uն비eT!հv<pP26;wXV;FAOkӋLZ̼7Vd\ds>')f>ϙF4Jvgtl?Ξ9Z!Q&Q<6{(nDtFtn۩{`D8@9ΗC׍x81Cnc2S]VX ":Jr}d0ӥH ֭|%D͚u`%m[.8y|eN"sw#1^/qv+wx9!&X~Ҳ>9EuiiB#o"{>&n+9NkXM=3Fb'=1Vo^4tL4rMffY]بPM*: ObͭjXJƱȈ~}XcݧgSSP'e:E]t:܏Gi\ Y:HΪKP>սZSҎ6{vpŷ%$ِ]1Gƭ{Z Xt45z}8Q _7tܜ,a{c#*.Q얓bĤLvn[E#l-F嵰nMt읊ͽL^&TIߞ = g-F#a$5KLa3fPUĬ][K$fCflf>޹a9-jjMޮG%Ati0:dRq $l@QXifDrvX(2iX몽5VUN0BO:ʴM.$Vug7O'H4rNjBd8]NY416jr:4ٟIFPJs>KNݯ=Î>cq٦rP-dskf{Cl;;ge W4g1f]j5Ÿ?QdO΅JYÕ!SV;"ێ ^b6٤\ Vw C=39zSCjg|\=8V 0fmr&c816ݒzPjkx("։~?]OȔÄż7sbP"C}\%qФtP)eLgOCJ3 5 sMyvgS ?:K2JkrIRۧ[j6Q1KE&89tn.HFYZfm䆞fpUbˍֆ(# (;RىcJ qd7#b'K: G]kF+jMm2%`:U)'>-Hx 0\ne]+R;jPcgA&pv:bPaAݺ\PiA[4[0XUF4VŎd4MyZ&^s}sŘǰ'gXėtyˮFżjӵNVxey;l2ݝ:f.$2ݦIHQX6q[b:_sW55GQaWꬷKT~)0,1]I~cJ@ _=5_*`."Լnm' 9ֱN8.Zk.۶|'zx$eX.njrVSh.Se1՜6m` MQk O~HS@kz`c呹# ן#Uf;Wi)뽈 k@-M7rqy7w!z (N _F`N>A0!*GA:j;3>k:ش.u H+q.X#:M(8I*.uͿ)iitEYLK_8ZSf/gkBZKA'ozuWc*8JTǥ$u\ڲ 75%k?-"XhYdd_, S{0EkE ! w: i3BƵ2  &lkMxB͜`TзZq31M/631us4@,^9L:a£ֿ^jĵklhio녮>eοp ĕ˅Z D֨:")Pe#PEqp^b+zpf6CAd]oҒQ)8^1|A H?H_r:/LqL-L&Qt*WM7ƚo7(`oP'ޠȿ5L~IQL>e4NU'綟Lafn]ij5Siͱ7s)kSn}FVrZ0ȋ$Ds%n]o0fg.gaSPq(E#RqGRK.Ꙭ_m&D"A!:uji) 'c,nM1DLaX殶)yUk*[N`v-1"wSQ_ Bv[q1~Dm?^l̎fZ 8F5n\  nl5?jF۷! =śjx`ii}轨^0~}9x(-|T&_"ȕBD㷂CZ POA//֦KR*Z:R)Mw/Jkp{q+oHzTXK$aщR]ѳ^ʼƜBIF3n&\S{$5HꜫZHyhHݴۦ9LC-Wzq^+~\so%*i"؃H;0UǚT4YdUuԘLZޙU%N?ZîbfufiOz?'2?7?F(\2"G H%-| dazZ>8g#E g?BpRhOG( C9٤h 0' OK,] hR;&ڀ 4EEW`8}ġ4CMf)"^N#.D󘁓`hT$`s, tXRyg`'$CB] 4X βƠ8GZ3,< }rڒ^q:>*t6mlӱC@Ov|J9UZZQ@HS3ȑ4HO6Eg]YoIJҧJU'{*[T&؟d 31gkؼJ]V=0E !'ibm:VVyэh6@Y|c cysp4˶SC. ǯ#j#7=Kdnh0Y k"Eg+X^R%h#$UpuYih]K%5lRد(^aX7JqrÙW/I,nM}}POvtr?=<:g|[IG ;8ZJ!>i?7K~WsUuϲ<,mܙM;O'嬘 UEiyc\YNWVtkǹqAG^lpkyNu'%CqOK˹1[ LjY_q]('Qδ5C DžNӮQ:B 1.']J'SϧBt/tsrWO'JF9S5+,ݬkzi_MJu ɡ|\ p;eq<"?V/I#Dظ8E<|$`LhpR':^ڔ: /OI`A`DG=I$YDE ?2BCE`AVn Bj*I҈Q迯b1:&T 9WLi ugs.~=ȁ7j&w,pF5E:[H) \ͫi87~2h_(=w~W\čɅr·ɫ~4ҭ5okˎz҃=Q]pAĈz V;w6]pGodxX}TXMR4b#vwEZ:@yMBK}d}cbL_Jp]]"r5-'\ɝ{ n qYR-mSX-wcda&Gbk[]'u !@k |_+P,_NwO0+`FϡE< 3󕷷OEY!=O?^l2@8m (=N&t97̱ y9\4 , S=<;@+9><3W7}-yt9t8^; R|oҥ^iNnJ \={P?1OjGc/Npg,')>LN-F^or7띦.oz);մ|.䩚qB<ߞgI>TyJjK}t|\K y5/TIN1XAU?a\Fb2kRk3h Tpj'BzXc~3gB出K,CV2ug1 |Yx@&c:mmt!UVi5,sp 935Eu;3%q_ZU(0pe9buCJ,kU.,+;u;,圢 }sP52azN^ѯIm #8^c۹vD"!/08N̹߿Hr^Tb[VNyƷ+! xd&6քB zY̍N3C3Nߕң iRy(wv!%r㺛 ͅx4XZ)sqv9t#~}z*+8\I7݋]KpU'ƾ7*OK')r&F _םe"s=gHWaL T>gԺS٬| D@{)N$|&* Leo0l"tE6((/~a?DNLQӋ<Μ6g',X'iSV_wn?A'= x#M$',3!N/~Jt+0|*7%lS܌BDl ;(3-w>?=э9TrK8\@j2_C# յ0+K3YHRM&bk,ɞ V jb=臠*->4ʌ"(@R EPOO Tׇ<飞0 1w`s#Zpt ]mPz(EV/S)WQj h,l?4_G> X;JWپԯ͓~9ߞi0r;JkbuT}=~ŒKs߭pݬV)}>SnzǭI(즬KqF ANΣ}j[g凤aM-N9n>Vf=w~W/FYX|~?qK&R\{}c-(WrB4qP:8)Q"IvRc*IZ?ZRݣj̷~Bi_IΫ?gLh6r)Ivҹ*]=W>+v_IF:5';ahg᭦ ɡGشS#H$wçc+(DoVmO(]?/rP%s̑2qKuSEk91jŽR 6U{^L~4viA$#\$kgtlzk#l3eCNȅ6LiN;^+דGvqFҼXG 1zVBUȕVnܺȩ^]&4pKM re?jgܝ&Ni|ܪ$il|4?SIGl<⥣[xrG{U]/uFDdwϽ'gãx5Q9Df )[dްmDl*o)z8=v,\|Q婙uUDPR=) W޾+Se6qo{!S> g|fЭJη_M4z+&5P52x#+oOi1 i&]"}L#s0s:V]NgcR*]Đ%?1B.+}c9n60yn3?XAUhL_S=JevC`:?X'sMZ|X9VN g I`ɑcVxy9%bdDY?k[zU[f̶c~"?_sŲfHJ"&`pT^d>pE#cuDw4P]ËyNjƆY2Ho6DEʩ)&dת/bHZ?4Kݴjth ki eIMכK*9)FOLR cYak m,\<6zT=WzcPs{MtCka!J=\<nB`16zUwY&GkyH[D .V/'_>"6m2]& }io(@!ж-{>`iTG̎iy4ahe-vcH\$MS +?aC`3c+9-LZ׵NesSwV-:pky"$|x5V쫻1gg;n|[15:EUzCW" ʥ{6.teڑJS6%+M+cCRvggi&DOV@!$fv!'V7<f&J4.|%7Mz@C.]!9=ĪOsRhmv lj^çy [%8[\vBy' fa ~+ԃk2weW}/{;3vգq媆k*3{5)+E'0>Cf.ίs@\6+*ШS7i͑t^'F$ tiهtʄ/,X0Qu!l5Y:< Ցp.Qy@ !lXuAП^Mf\<u5%kk? ^`v^5{>d6dy$m;[üLo5DQ&>u@/#+ LPѣ,X6m~Y!bfsשq.W'd^rog+DpTdM|,(Fh56Gb ςۻAפs0oκ&URj45VWuNtؚFAisO= U_NM"-sD>Eˏ W$#a&EdW`qVhR,YK"?ߘ ˫S yy%W:_M3=0 b>z8+-,tS7"O&ɤN/n?󷳙T6Y͝`C :H@&u:n>R0M42|+r2.$D-QMfC`d\ו4~P|1^*c;wݛs2``jd y ܧ͵^Ma{ЅpDrĻɤW)xmlIz\`XA]|@XaL殃m p=,h 94.c50*j֓2 A!'28]>t@q6^oK}qxNʒ̈>UzFIf4Щ!~gb!Uo&-k6eG7AuĮgx&Ql=0[zfd ˞8] PrSy%ŝSM&rtE}tΈ' "d` Mo3A$"AsZn4ͅ uuؾѯ V3K{;511 `Z{v]KWW6ף=bmݻK7Uk5˱b K%5m'8r̎rHQ%-#OLIjZ盽3@M+([D SۖPSS1(ڏ957gJn.us6z-O7W#ؙUᐓ`vyHzf\NGW?}1N ch۬6窎]_O4_2&K4$}m-Jn0[ JchˌD\Dy%撟/D/uBj7"1S2mUft 7f$r' ^KyNͣybַ sZ2n;-{yYݵgLJQ/o-k[ឲɾ3?s wK U" _Yh&XVSt2%gA#FS[rk f0wӀl/b{UلXc ׽"S\ߩ (x?y[c ׫PoVOȼӵc9O?OY776UHԪV.K 8*ʋ&Յy9w;?6Ky&pwHl&O~ib8FV}}7/7V>%Os$)f:` D4"e¶C2%HA410'odzZi`p7IF?klpbWhW";]̣\lV2KSMY[fO%\-j|ش)99x؇xgW9ĪDсr,Zb^rzs޿Hh4o,of5`hB #)K.!iϱmMuyf[o{Ǧ=2wngJw5zU8}%┢(Ϲm,ZƷ=]BIP5X##bD-C Q5fd OCC9|vt =w}JO?M?اq_T9|^eDd ]VZ.I2S6$Lr4rʁA܅5/ETc aBPLänr> ,1z#PMP;/U#܊IlGEgW%s-n /{FgЌص]ceo}EY#0j lq1c8h>P3ak΢9ѯ/Pm4+-6vu=oQ&t{"<} ;< }c}ffA5#OO<~UCnU6HPnzJO"4IiC57Me"!3FՏ;gvѠ_p/47IcХ1b)=+iԨ9[Წ&IWeIAuK@kA9%Z+5fY%ae-t-D^jPJ),mjL]<6E(.9WY8\Lj>|crT_p(d/ȕ0wc%<Z<%6`oƮ9}AHAT6?_՛T't@fp}&+ԇ_kڅR1\SZDB3ky xEP a A>!1{1ЃLg=EQu ___` o% 1}=;H wފxlo{5o|x 1z~-?4'c'';Si`az{釞 Cbsz?rl"07|Zږ^D)yTZotiaw_f2S|g=+Yz`!Z5ģ^cRg<}{aնNGc*%], ֆ70>M~j Eo]!nBUVud|A"UT4Y`h\;%ά~ʆ2gDlh# fC6yh2%`CnhpAOH2vs>rT׌-ml->過`'\KY>!d9n#T̅yn83@^ RͦS׶2 H#Ԅ(.#DA:@ Ery`M)=^tV{_?_)V(ïP៮f3];3e)]1l@2j ӄ Q vN@e?}[A2@9`sf B!3 37v#A ="GϰQQ&n <]f ;8u0PY#_H8D hKreQ6$AG3ZHuդ@+T'ݚ8 7# osL3<)8Ӈф5b.xUb.xÈ9Nd8c93FǓ}Sq7 Ef>P*E>FTv|0g\4̔/E{5n'7h\nXy[b`$eSNS%>ЌI)!@*tAgatLU@eIj ]x} Z$x]7$VTtcGFoB7x{#>n+WM` (TzRrIEfDZGScQBԓDzKMs$4tZljETt(+0[HTn daDpP|gzKQ`#[8".%%t 4MԄ3EOm-~M1ZXܫǝg `񌦝lo2줸<wvp]VUAm;'9tBXT|% `켰.T?6ks'v2;&T)>i<%VN?̨!1&tjKPBAmc֨HΙ93N14{-!)D҉2Z69"4[4%OY7 5jb"hwtK6"0om; \m__c; Ml' 4"΋k/b%ə_B.n)t`E%j IMMQ.U44eD>6E.gXv>"A4_zɍTxyh:O [E%bSy8ˡ7y B)"B(D;+K!7FJ #I%n\}( "%cњ0?o@Y2/ϒ0[Y{i$FbÅY":tX5Khf64mL`H1#nO@Cbs!AvzovSkQ!(G7|2mUCb*:b<3 (8{N)lmf{R2ٞxg E\Xa2lqHbH:N[##9J_ 0ܑwd7I|RsALE҃3).cdX<%Rߢ"Z9~4XEfshjVsP6xNNo(ƣ96*Āvf⁔qN ̫NCDAHC[*W6p|z`'$E!]C\~N,RƮfA K-95+k#\F%B\~Jw 0+ PL,%,z4fIu1;Rܳu 5-`Sff?~?=PY Ki uC#[ 5TtJ,P ]¡; &Sw"g"sB2y 2A3 K5Ko8p9G߳I_:GKE@.nd' _JsjTҙB9<^p%NmqJT>jN3ҙAܟWH"R l&r!zΰ_ a]M8_5 $4U-2*}x*&#brC}6 KZbl½T%$TL |mI%! }ʫqiX|߉~o`,X@VW 6yJb_=k?ŗCm3y1|^̏NkksYvmfxہV[&>wkcpmW2m Ǵ33gnLO={V޿&YT`nyϿ퍭:]{_[&ET;v]sq-WPX9 !FAe B.tU]T M"QmIm&fT*p4iRt1Kt"c{pw^?뵼I4ѳѿ1I}+q^ \JY|tQxJ VTfA/d\7NK/~btw*zj$=\^Va ڞ{W,:+ԯ61:n^LJF]F35x27Z^{*jw+ ۻzƼ{Km>g^SϽn?v|NI~_LTBt}a;'IVbz~]r x.gUoy|xhit?7C3ߌ?+3, eHoq^/=T L?@1XsJ9r`pC1jKQ1 Ebİ{~3 c٠aB"- `yzX 2czIO"6ު^~kjwQAD`S,Z/e?ⓙ͊Kd\8=D*ݥzsSŕtIDݜ\JGDohLs^y+B=knR_`os lx28)~n ) ݗ?@;zmo9?m 8Ǐzuok aKLh* C Sw 2An9i4C}vZP{yΕC_P-!o1܄ y`,z`i-h=m ݑtU`&O3tS!nK0Sj"DvO>\v]R3es a/ƠJTTVHj +(fKw٣mNwmagO9m [ l 6QNN^S>MEw5"wK*/꽹*nTS穇b}kߚbU.W?ŧX39" |'~BؘI}Jy-o_L\ 1C R;hV+P_a'>|nD02+m;<[5 dKSolYX^8?rOoQ" ř6'tƕ>97\e"xiDݜfϓ^}y'pߗW1iyr/~\zہ8>6WTA^{}6n9 g.oۨ^֨Y_:uѽ|QTHM#^3umI06rԿ!| :&+*>S$ o!X5+I +u +]9Io-kf[Kˀ.RͪS;W0!o}״ݍ_%"0fR U-0ϩyVC |qb& M Iq6+{Z$0d|B;ˏSzgpL>ls:`^*K'N_./8mZmX"7<%^JB?Γb5NBw |(]C/;INv) pY*VXe`/vm$d?2Co!H$3΂@6ec|S1x" W{[e5Kױpa7g'6&q =AhM/Biq 500A{DJɆtT m֜-&|C40 T)q\٢xC%?aղ0<%^M2N ROrڽ+CȫI`͆f.#or8/cskҙRiKo6Q,%y%E_A/TZ!" |s/n6M7~C6nV1lXÓ]>o1~q;ȳ-_x^QɟrENZ|~/eEFj3QW+ =?!T#'oBZ;)aGj"eT;ؓzk'r[*(n~6h٧քz"PWx]Z[)RrX+iBMg!h*%5ս"E1f.Alxw]6AS-~v=܂#C{B!%~1 $^E]Jrz"8& 9􅦪M+Tɺd4(H}0de;e;;B/GP~ZdQJra]6✐t)YɁG: *4{UW?֓$Ok4+wj$dn`L}:d yMºno} ZD=9-KlTdqGBjKHvJ؆6Ɩ^36l6eVd뽄Q~aE-l\|yNVVjjJSD+FJeə,RKWeZŮ{kQaO'I"iFC6$,<Zxsg\N @PBzi'^̜^j/w;mƜE:m߼7A/ F#ƻwN"S(~}+ ]$Y~i=G+r;йN:GOL-OT3oyE}}=Eu;ϾRnWAY4LjG감Ik?+Ò5F|C>_p.{/EdC\D)jf${tC=Y$or ޯϨ%VOjW ΐUa9CLv ߚu Nӯu P2nFL0b'&j`/ B_1 g7cmJ m~3UYU1jrZƀ%{Oñ)pg 3'Ga-/z[e J!/=o<)/RPTW]1|׋.V(?شٗ!6եMgy>С}KjiYqjPh=4KoU:y&O`bQ^6ѥ^k8j~27m7GL]M&ɻؾuHV/e_lԑ(ߓ&¬MA2n/( st`BŋWI(%pIҤ J3Has` vi'fk 0ʘQV@2Q&(1ud`O)|G!|_wYyy N̫pyǣ:f%6G-d9fc"v@d0mJ8*{]ԯgWB[ޟ~AV۷Ajq+5L$F *31Hjb^$G^z9+ǼyM!̓8#Z0#z\>efQxa64V|[w4Q{>GmQ9ll]p3iZFlG ܤ퇮9;zּ'[fɋT Cժs+#Mm40gX >(P0\O)gE'lQЏ-%}}L˟Y+H/+X&nih\hV̸Ρ7F[rq V 2_@`e){T9Tg,A#!nB<0v?@)::,fQɖyd ePjsS%!y^悠\Jj ( >pya]K+_EeZ3b0H}=Qs8??@rM{`W[.#h9DŽZzn]S6v?KIIΚw*v5/|pqcQy<Q eֳ{5P\gr9ɝIOI}Lܩex񳺙wB-~vz%h)+Ko 8x i!w(urqȲ;DFFu@&.LV}?/A꠭ϡq?{﫢8Ԇgj=cﵱQqOuYN٬aN+3{>jҿ߽\mP a<ݿ?p!G[ &%?О#}~! ^=E?CY 6$ӃtcFhO/>#A^yRmbI- voK3L݄ ?DW1 {[8s#ja~/` '<.}uVl|u?F}`aw|/m[oZó0% h'l2S!MH]"Mf$0/9lp:­W~O4~/sV#c->ɯi`[qOW8  ǔb+BNC_J;eA終ߘ'~ 4 g8z?@xy ߏ h7Vg=SjTa|ׅlcBJo#-~ ^~j뼇3^<+l$#? 4*Y!CR"R :fDp-4:ey_, 6Tۉ4 Չ yCCS*#27)12Fi=_Z6ܺbFnb}hZuPп%0z ! EtGO}ςF>^ Lj x?Ep}f?떓EP#v';g pE}enQG^֎lgxDiAHsji0Y]\IT약0q5 t7z:ڊm50aȪ*7fxvCsidmgz&m?4F-xJ$$hsPܸyFgyD]@Pfoyj_ ! W4UIBN73iі6Q~,- /vm̬`M~ 2,CZ Fzq!GŒQHȖ{3 s ?Ec= >BNݗO5zղ%_tvmihjq?OR voks}+(# ~FxHS/_S9c 3  + !hTg#Vּ#-/3 i)-b*~_Г<ץZ^HTe` ߽جK|YYjI[rRU |9KScQ0!7KeUuzs1! z3IK{ySS{wV%+Kȡe@K_$;X ,_)͆y#UDhΨW" ]ϛo.n1Bu[eUmˇ2;7=O$Fc.k>}u,;b$rؙdr_]bf1AO %^dZ X,VU+gB(˨nQԕ:;Sk&{(M42bY8c{J~jFr}FF {QgNF(礌},"4wy\;ر鋥 Sljxa־23>R2@'#FK_gʂy|6/[*$Q wub0O:`Dy=h//P,=q0I5FW{>L4if.N ͸}>ľK&>=”,eoE8/gm*>W3c8s-2";" զAGsp~dǯ^k,LLo1 7eDE{ȀX k6IfFMI̤^~Lqk3.AԜsQTnbSk x5,}bq}/G. tNZWtN^%ǽ^ vH:Ԏ(9GT@[?粏s nܢ)qt#76R6Tټ 0 5h\#}p݂q%<8f\+ȢQ!^(8U}6g6Axuν!K[\./APRC^ǃrwTPy9O#h Y*TYkIi֑tGv5oz[nlo'—TBv!BKqX0tKqC5@}jcXa~Z}RvHKR`,qohx"ub7y|['j7MK/{9 a}#[n!;ۉٙ0+q } {hy7Hu{)czW+]R=}-oW/h6=x>щZZ7wD%~s5}?إ&-wA tP Ĵ/-VFL.sk'1c$H6'զiHrնiӹI}KfGQ3sɷNTI(Y^P-+wVFIb;o/{=ڕ>9OP2D|׬.+QEr ĘwPߔFDƿcn&.K(X?nyk&-*:"h$cE#~+QYwDRn辔 jkWׯ#lA x1cHWC :CFuOv_Z/'kSP\~E'.>`:`cƧ DY,>G'^ν :ry]Qp '~}xk-Wְ+ 0YCE[ُ} qwku~M|K7cK|ȒwZNwog"6}=bB!j*c @h>يDK3GDF|5^) ʼ`&,D|7哃"ogG%OI2)@FX 6ñבSq?F>"׷=4( JC][CzQӛ]& Ť)?7k}WjJ:⺲"Ci:H) }Я**GtPC=lK\r;0=Zph1v]ZCOCP/ ARPv&X ZG->2S+LRgΏ%⒝U%=~zJqtqn h7SWvaz8,PY T !UuR&4Xf 7Ky[ C8t3ݏ#Wvmеz@o䒻.R\7+{grk 04L Zi*:$%x!9V=?r `AHY=:grJѽK> Jg4Gv)ѕt# fG;KHk}wת.D!X> ֺƹj&q9r4 zaBncǙCQ_>$sbx; Bh^0lG}9hIa$ME\pbrBUޓӀ!X3 zf8!޲c/ؘ;w\IǸ!5;Zj]`JdWۙ)*qw)+9DE 7H)S䟭frfh 賄UDl!Ӥ9wqƄ *%oʮ]y#sZ,_a!ӲZm 9YTR s=zh+'v#RkpRѷ6 doȿH>L4љį~L]tH-c0tБ:ܥ(! 9k[.&c2S{SK!9j4;wo?(?MI ms~ڱ@sHL᠚R:C|e( K15 ~Qrߔ=C,mf({WO3Eo"|?uENb}wкD=6|/H˺Ur5^aVtU|oq5dcETu=DWFP|9"3@)?\d0ݰt& z߀=kdT1ZdH{ua3(;j'C8)7,El*>Bɴ+9@1?:0s|lY11Ýо'O_3> SI6;ϐzԀV@\Ͱ4y!4 W7OkH\AirTn7HM8R *WV^dm]'%=aàR0Y6(g>.o)[d[g8o2GR3#aٿ+m Fb'̝0vc] πD Lxsnӧ %$]6Z߀Ļ<8|-d UhѸyy&  qxm뗩i'ƞq ߚ?I]cyb~X Ԁ#/dlߗS}Kksfl.%Pa3 Uu$vޑ6[;gpz_͐3-FU~ op|2 IQ\߀N/u ]p :Gv-N;Хփ}V q/`R[h*O<Ōr]=lH! Yj'S-Eɟ7WF/oD7 Ԥt,^8}~ݾx{QV^ME#Cm-I-?n |g8^Mdm2I5"wvA?@K|GMѨ.~K)Oxlݿq&c&.az8-B ށŞw<}UXf ½yIh'RWL7vJܓ8$tޓ9-!dM* }!,EQ2}W?Quꧪ/c`?*<`(RC?Ki;Z$cDQNϛVfF9'sgj;-/& ~h:3\s c[>–% ]9Akz9>]@ݕ`q_q_p'f_5Dv!qp>#yÿ|F4 r"A4lPw]\iG!<˟Jv|jL}ԖGvF&=4-Kr- ZcVo2Kt+6UJu>{88  S 7zT.Z )j<4P;_d沧ؿ Mfx>ق0GCꟾYH$6`5[+s;4͵Aae h%O{%ې:4D̮mRX_B9Y b꥖[;RIt8-uv:o?+#|>MWCpJPvw,(~G"|rٿ65Ի "i#;\)IwKP<-gĻD"`NĈzVs:K\*;($Ijvک$8I 翇˸B.`r(z z ݽKL:{d%YUz[jEc O& Yha||ӽVN͒7MB uД|f/!ԒXsUdXb0#`0fOAjUW}"fWE&RdUp3O@HO5^eQ}MynHJlh)&ܒ7`*UiC\$@4v{9Hj1N}k/9y۫X|%c tiLP#|/tKb8)a ȹ[HA顖0̍Gn%1:`:i8@y=v{ d ܹ$LBVnjEzPO5 3m'Aع蛄Lٌ΢NO6&7(F8\TG?g,,{kдvi=nO#q>xI ~dhI1 "DWIDdvUђu:NZ}NbHD^q"ȳXd\m<ӚJvMuhmwk%ט]T n mtC " RxW{fyS7e0=Q +!}B(C{ð D#pk&7>W<['T & 0溯lZAjב]s$ N>Cu,yk`ݷnn;T$y't`aL̝&JD`}IqJK@nG{ԉi2J ?aFIylE] sDeam?]hȌ|xt5((8 <؞Y2`߯2#$]*TgA..7`a(`vy>蠣<16' cWPUbi\I^*+<R {+{Qͩpf{Etݤ?s%WBDK؍R-I nʵ& 6GsC?^?^q4 IO95OVwB5ո 0g9:ZOJ-oJ8@9BFϐ;/=Qϻ߶]@nU\hqeW%GogI BDWrk`DD2Ó!M2qmPpt*3O_jᕝ}XSo;IS&Ͳ[$![]`LUϮ Q|o~i,C[~ Hoav Ez]~VQQ4Kx8;5UC<7tVJ U.8S){ [ܰE/O|XqNb'X.g ɧ{޻0G2.{W$NQPgu n30se86x1Le\~vЄ۝<sK< RB9no]2k h#(7ҦOK }fQ.ĔF92yu\R*S7{5$w@Ѧqʡ]R=f12k1ATO7<^;EƯr2HL7Q6AqP%䌴.Fk 808tvt7}׃HIu{/⏔vWh sf߄W`Pad},v׎|:yXtxomq)"`(dʌ+q .X?c?[S}|*ٝF#`2__^?+x; A bsRU?XPǧF/X)Wn30 PKIٴᰮ/䁓}"eNB{j6@ (ROyOr&DtבD TrEl{|`_{@ 8^2mK0;/8yG2eegP  I|EZ68 -kwct!$54u;+ř}F_ eU',ЯPYoT+}To)8j0o&NtNg%RbNƂX呿jma$(.}Vhk%0C'|4`d7b-pbqбu'(nxbZ)@1';GD@5W_fS}JN߀VOI]׋x̺ncn׳2{]AsE&')QII5m&44E`zo>y`~PʀG+C)Hjb:\ ћ&ͨc>U`{n6ڗ4氀dUNB%.7J<ӐKM+ e+o/PwNSĘn,1{ib-O;~Q!CC6~Ԏ%W/(Sس3`Iq.Xqrw q΄ gCk#%+g`0vE$JdZOnveUȾbaW?N($ٷ#4kK v!&S:ڹ¦'qUͨp&Jd'aCfg{8h+o{X=3ޝo\5֪};m_`}ܺ)0F2 ŘϘ/SQs2#<%x"] NIa8 ZAHBN̗-/.8)W( K>WB&ZwV9e0q671jhJQQF /We)/CJK~ }&2XOt݆+VZCj)O$_>DptyctÈ4A)D/|WʁwzR5!}^gZ r[3ą̸h%5@d$؛V<[ju-L ׄWI_CFe3|3A}bFGgmǿERȪi 1" !.K^ *8m;l.J^nPBu؄$_1NY ~}'ƹjH"j*h,0\~~bn̹*6[ucO.] jQaXC:ǭ9Z%mohQHmBS JAA-dT$|rWW:8҅7ê^cRTh0oE9yOHun*>b}7ƮewK JKSJC(25|LFiH$68gM=SC 11_B ٤Qo֞muj'BNy(s:P3܊h+$I[ќ$ a߿\ U};cX58(H/ql8譇bth?MoCZ(2Z@ ΀{mǍP&b94eMR{V@,Nh矆[|s0*w.e=})ҡXyɹLt ໌2jadmb_bEEVgl~!x;>3G]ס8I!xՃEch/k)nv-GaaDg~ߊ15ܗ̼T< l-Z sY\@g\02^5wC BђfHώ$OD-KoI dعo LmmOj_@39w{No_ 1so_ F?`;w'~Iq{;B[[_y5ڤ0mqMF=O ^3-À5(J'*@֑r؁ G)pxn% sRkAB(V#ߝJs*[( :> qHYPu`B^eAhwmI>D@ά:}k: :lЀ?B0,~d톏c @ǩp&l:TJP)AU/t<~A;|- &XH5 ]e8\Az +I9<{:g7m=iX'> r\3+ t;cq5 ހ /w}*B>o?$o@s!rl Tw{F9[ r7g˅P?F `cئq{X@Rw5ṿU$WSe;k*rqzE5Qv{)Ŀ;{YEK鳻)|)kC~s#o֎눧 [}_I-ͻ.04B \ =Y u3?]ߋ}Ie'X ⼙YSU+ s@Y[NʽV7`Bȟ7)X~hHQRb#p" $ U(p1ԢY݁﯅qjz}uJx}flZK ;hAZBuJv["F,AYU ] 4ghNOl1CgC П(u3A>Z(ѧB^!W)sU$E;/? 2홋7 |Ӳ/;yYZ0,O55ND-1D:!a"^H _i^$EL`!%Yk$C`f|ԲG5)f_5yѧnv N֓V;u|6~#s`Í#7:n%XRNRV݃ݵ瞣&S`~Dzf9dWĒ;.A /iKU$߾)%4%ޥ\gBv ie~ZV숋 Fzsᑌw\A/1{],FlhOBW z-H]4j6x;fWG1JXu* J?}rc]e{|·8Z}Z)U:|pXo6P͔bd(37qF񥝻oN8#pgGH`{i72n꬇C#,! X}ayl-EQPP$QS=AU} 75t+Ptƪ@`q,^vq,MR&~1ZJ߀_Pm%քR&V0 hC-{2u"&U-_A" a< +!IJgS|am=b6ٱ9)@>%' >Zb'#Z53Ц+ tp^=㮞tm> Ț# @6 j|̽UM[& 8i;z:*!rAM iϽlu$ь~"jq%dʢEzUGxmto dKWP6K ~_J!η5(H㎟R`'AG|貶 Ry]q(pmx aOfw{qA^=iXYW "A$8t21xm5|W'߀밍HÊT*}&^1z_zGøt]bڽ|5bJ#7yL>W/4+; TkI9j6v5̙Ir=CǠo S_s(;TEC<m6&X vBk_=hKhv\/L7^7L\V7iJ {cG5D&$;rLvm]V*+iF[(aC%NQl8ƪ7!X>L^v!}\Vb~KD3U>`-^tUfXI'^}׿DJAQMa XKae!524+h2?֕ qM@/"⇯ n҉V,q0.мns'|wYoF@ 5+P@/m\} *FO{ Dl#^Pz̅Y2kN#shҋɝ1@W RSmIK%*!'#B` h-^.Q0~A20S-*.ؽBqf00*>*2 >qeR*6t@>Bs K@A7jɞ=VO~#`=9\fSBiO*1ҏ<[ⶠ,Gh-ݗmIݫWTߗ5f._~vp䷉, HUq=_2-r.A[pS/Zat'_1 {[q<֡bgƹaF…OwuEw,~F|e[ b3e"z\_:<ehKˁ81P3r@%$4^^ "XC:~3di nz2p+q6NPgg>ͳ^e_.6TJW-n)JW#}ۖ3IAİøJx s3j}G4l&l*cG|)|,zwA*sJԨzӱP'G q齶eƺ6Z)c؂RZv Qd&)HC) dIicy 'IByNJ3ȍR\as|g56[->i() TBbB.Q&w߷$vEX%JĤ^tйpLҍ9b&(/*SNsuQ˓3MOZWlM M—r:R`Lz^X̅i$& F@`@E^#?"yX V'D>pJ,${$LoҠM/ i&D,R̸B/w qWVtj(ڬ _3 bFQɆ+PG#Z1?M9;Drw ګбkW<:XKݺU7 oͦ$) tl,38zaXe$_7QY(dr+q`czw P>y!c^l/RP}2sbxeK.ZaoI&H`a_d@2:n@{p G&銚jm \n|ton JMw)I]#w=uHJ#ՐҺhPPR?,N`[e;z)o֜<л"0|lݵlz.W4(XC@]895>tTq27nE(*J! #4&k?KM zjL)%o(EEg4yWSl+R.ǧ}WJ ѱ8lv$j&<3bO 6 `/C>ka&X H{ 7A϶ju59 lcraЙW"$Bljh? 9tY\BeDɏ_2˞ᾑ@5ZSc;eHk7_wb\Gb  ӍB][b 'p֢A`x5K~ۄT;DD:zܒmnyϵr(T 8hۀ4ߵߔԗV0UEA%'0Sg×TJ)>i[wCcd!\e@,)-fO~B?y~,;a|1R#]uoǾHQ݈dTUL夣 fGe}SAuok#\mӁ}+.]_#S3%_(3cl;P $F\ U8FOpzd#s^,ڋ|nkWmt'c7#@![ 9f|w3k+(߀(8HKtn,CwI@ ɨ=j*`kZea8m[G|a`~nZ|[\\\O'%l|d'A uy)Z 9^ܤ4>2wK+r2 Q$LE.P~ƻsYg n|MK ,h?LJbc^Zּ~|񧽍"4X皁ౠs5f~2-qyS,)$/SqʸT#O ?:l]n^ہUb-U~;MxALOr="t0ᏉA_GB@{_eTC2YJ2%#il'bWZ3#U]Ns HsƑ3P\Sx7bϥyhHJq9=?c@\h.A0|P+d5)0iAJD?볗A2߀J_ֵ0A%o ޤ;v0eOE(Éc~Ɋ}{`5^;fo 0sϾslyEGzPnqg&` ts\7 |mЧB@R G^a(*lBF],03ac dUp-_<8n_$-:V Ȱ@3'-B抏X3u~?`  :ho&^!1kO4BEPѳp >8Bl9PPwm>m8x8i.Zx5H 'Zv?'yc@h#v f!H HƨV^GrXb<ѣ~9'8{A}0^EqM'^Ỹ\Ck.QtJ$u ?y( !U͝+@5K϶ C'wK6cL4dy!.=IVnM1hby 5}b|m $|/NIN-|>,b 8JN<[ *3@ڋVQI"sm v])5<̔vz軟W@*da{`tľݛdch~r=@_8e`۰+Kp^Fރ3(}_&*cс-o2>/\1bG-`"}}<u|Qdj5d,RH6E\XKLYՑ^|')ߓT[ z*c@@kCJo?AAG1(`-Dڪ(WD>;02$E:tjVQ( c"g]sBH}G-@x9/\!bzjc1L)4YIpֿ{|\;9I q\>=PBl;\7( n,s<0Z&Ҡ.s*hܐ/"8c[(>!X f&˺.M~J8Ȃ]8e[5] ?muy0x>vPcR]YW #f \d YqjӚ7CVmdqt$jr"%t0nWeQT"godžU‡4ѯwgz{yI.Fc/M. ;R 54 #Zw˜3rǰK掇f>nj$^RL%3ZͭX򉈜 9^]퀃{Rn*dp M~.8Ts K9^TxJ;}S}zZV_!o0-_|ȵ7שaqyZe=  DpM&_+P)t b뿐=~s正[f=`6 q z^'a $ .:!<:"y:lp61lt ģevv_a{oRHB\dmTq @XH `eUyE|u.~F[$v.5T]Ȕz<//ެ 5h>wG"+w4vQ[_s+%%W&_rmZ/dsysyN3ቌ_[^Odv;\L+ XMX/7Z )4ufnA/ShFRSxax4 M>3 8] *d"ZKD-xh((bIg|]-I\ Z3oiԿRd9&GKyDqPRú0PqEyȻ +$o-s)4CiuCȒ-Gpm>M}rpfŊۦqzSڻhRC=?Ao|L:>߱ɹ^;{$ THWh"0sw=43uf+5TAPElydZ9Fg99ظWE뤅5/u8V.†5|x\q8BRx \.iwdoT5 8? X <`7cS֓=nq'/J 'TImDY&h|oq)㕟 IODK^!Lκ̭+&jKeo|`~Hb_G?|rbYv8r֗xF%gy-`$8(¾p[vdY\s0,=z;yu^W$@܍*d DIdF/zlV: ?,~. m@;o"#Kkw,!>AQgMMDw8>D~zQa9ZYwCte;̫a'o3,q޹Ēf#o; T3ZHF+01d9qmݝotkY63HMd4pҗ)+<Eɫ ,K=sJ:_Y}+jo|{߀( V$@I5S()L4ł/B@D{4|*SuePi\JoS>zUޓ`.TK "#ӽI!Ȧl2Ƴ{ڪQ %[*H?Ezv#?b8/ʼnU]%a9c ǽQθx /mvٮ+x𵘇j#!@ F@ A%jqNBR*C{졁&zDF-WWj8DA}i J=ݘ(UP3[?Vς/Ǒr'(̳P`Ȇw#{:b9hp_L^ϥ H^_ʐ56C0a<#U/yU`ԽrskAŋM4u$`$lݎ[B4a#{> 0qNθI36aгRT Ϩ$uVAۦ XAϴIJt] [ %;oCߵ2+ǬNqMuKkЎ(x>9H繡έG JW,L_I|eO0ie6Cv W5+lZkhKZL|PVCH *6Ar L}y0'M_G5}7tNnKyI1/ 8~ 1_ L9&0oNFḪ(^}ifh{1N%$Uɳ:F-7}+t8Jү:h|wG[ylRꦣhWOU?v0UhT?6EF(n[ttsJHV^!bN@ 6`kcZǖj.|GQfbz@{1%ڨ>Lc{84ĻT Crn=#isA7 f6UK#c"?Y8| i2=eW䑩3 ;l̥YiBQ鞝NN3AlpNaڃq{Ul<&QqPz7d8m+v-*! ]+A$M86 u-PjS5i̜.JT=IXU+JrOKQsOq3(1$NJ[Et@K. ooT7BPi)BX#ס>e3Yf[# {N>$T?l.ќ:0՚895;𜘚s{,F8*Y;:;b&QXAl9p @n gHcRxވY[[ er~2v=n") ɏ4gy_'V<f^PsѣsF+HP#J8*XUN?LLӠ˄;O!1u]djy2<t*Ps{z.#0knMwooQt`glgPPSQ2T@.6x,Tgt ?5 LR'^=] ڍLceB$:/>G;Qa26 &suY`޼̣̔6)]9FNZ[8{v*ԷYv-^u*aHC6G^_tOKl!mXґPov+X=SL擝fBF$qrj74DeKwyx;@[ɷ xt.g]v/㊠3afX\-]n |]WCf0 a6ݹ5ju?C(΍v|AaZ&읛l =mhU>f`]]6Uj)G_g 9hq1m,ԃ>>1,J )cL5o`(DHr(Lڋ]97H<9Hg ׅޗM id.噸pX` P"ﷷ kBSnz<`/Xkw&= 4Q^̿mnk7 .ѝ<>JWq0Q9lr4 D8vi$<ȏy& U{4Q|y7A> gwD`l>,?=s'$+A{UAx#|(lxvZ'Fq&ٓl@>n]Z4 )uQrzZn{f;CZ( C 8oZM7A. .AR Ԗ0Speb!}L?I (Ҷ{̪x%Ydmߝ);ݐyuO6f-&D삄 5|mܥkĨ%88^2;*<,$eC8?9 E@,Ga\y-`̏K U9"n~ՅH-bR:ռ+3R`ޔWU˱w*3 P]{؂Yٖ^P)#xJe@Z">_-Ĭnn/`3<ؙFʁ?.<>.0@&eKP.HҞ&`B h@WX;_15Cعs!`K'p`E nP 9\n/hou*@7gW ܇@E$c:[bvw $TEqiF){[Rr" >炭;,_r!T!h& R} v*u+H<3`6| #$֗D\G-uA {^`!f>H& ߫bԪ4D{Q‘PlNMI]..7NOP~)Zmh' ٍzLnJ{ۓcf55@@ -Pq Iw_<ڛI'#P«VɆr by R3QzDn9t@Mq Wm8t $oS<,|4/"ـL /4<@\ RrDɗ{PM5txWUfTfCuPm 'Yԧ[}dPcn*8Hso!O<*>uqw?(O\gs_Eneo t̻cs4pt&T)QU= nNU)+L?V.,r" ɗPo` PK9O S X(PIU!*.a:;h\Jt۞+Y, p\x @tBԝZGPG@v=".?!}VWOTȉ(\-^8̮!+nܷyE!CBquFn1LJq0yJԡ ve-hXI}%P5S:hnր񳅚Seahmz: Jl;iaˤ|r/Fxl9*l83iv63:Z.?NL1PGՙ`prR+9*~XK|M&ɞi )MtxʮߗV  ]~e}vxq\1ؤf d[ PA8"&!"ƀ95R@b9%`#=l6 O$&Jl1RFQD+#5!nLb71jwb|ץ(!wE( ?_9B& ACdd"0BQd`ܓYQfBX' :RQv; (偏i>FA#~^! BSPfPmM WNyR;?_~4^߲-?K(e(' J^Zp(H~j~ΗUíg^INݻkWoŸ,h|έ_*?یǾ{km/xx;  C"?=".2Mk -\Y&ؽ.0A/w(&5U >A2X~/w`loy/wA=/߀?:90/Y¹!DqH~x}'Y&~%yvNyy?ת6wAwkP@/wRV!zyu 7x=aG7>}}ԏkPؼG2x_rSw=P7 0E `WLP(A3%_ߘK o3 r?v9"r-/y~M#2<)|%\ń+#!0D- mml YJ^''جL~` u.a語a]> GpVy=;mPJMR!(-'Ng].\%Kog^[چtmG 9 ~!l8 $_sS7'r?xWP?a@+{J\%qdA\ɒ7( .]p C5ƿ\z!AG7QhAdp*%eAoSCUWT}\ϢOAiZgH>,@ nq3OLB༥r"{C ʓA$fVWɪ iS ͟uT/2v <%^ j !z1 'ݺ'.hRWB2Tw>vP6 җkO#_B 3 mC"~ M;VCnO{@cxdyO9,"45ڢn^fvag>@EHg,E<vR "!φ)lD乬 q#|A+=>!C!e\5сs7EXgz7} T ۫{=y׮T'FJD#5u.COؠYs'ᆵݎz]Y//#& weh?oӷG j:| v}_~נ3 ػw:Lw=(zXʠ&08:VzX^o|`6h?$f +o ) /wV%:mHo*\>C9Hs+ :|x-(]NfjQSA^bݻ ;GCA:3Q\m`2Bed7 /V]YՒgA5S{@rU*gF0A/MZ8mºžy+LCYO ;:}ZrBV27#sPIU2X>rƏ?-?rQ0]~~~ ChSN8CsQtI`6fWuќ? ]>\tSF]S:Y\Q+ABFz;3ۢGB,37E^PBSC]3}.3RO'ݿeBm,*hSy*]# {\jQO@y}Bb/SڑQn@g} Z cgz:>ُIcKW}S{G}++JjC8K!g4{ '5si g P>=)5uloԁ}FL.M1RcvŁ'A#ؕ-m6lCOKulL-O JQ,דV!CmNH74eLM҅{w~>scXݖaF>Y- &}OM{r1ύ|}7WɌsiS;V_RNOާ+ Po?/rdHɷ'P/adz#0g|{~XW~'(I,}'.!_u4[1?? o:pՏomylPvD_$ ^N , ػh!#sG%?O)@I ,s P[a+a$W2Z& 9Q,ʇ*%ñ~>5Sn1bsܥm|Bz<:ޝub3Ӿ4-v1Ƃw'Y,'s!Pd^JWy?[Z9@idd0 d^u5X{z-]Eo̜tӿ|ң&u"`ֹ֘u@Drp/wn;u+ :\*-|N@p1qH䌒sh g]"ƫ7w6şypӉs`k2AR 7ǤN'5L#a9`$&̸d8UJ;K-Xe\ȓ Y( @@}So`ea7 tm XB_ybxdMes+`xΰ#Y^U:gZ]v"TpRhi =^?7PE~Co|Wx+c87V^7}C_e At_:o 9FER5"ofze?b#*q'GK<-ԴV> 9 v6E; w_lDW'r|Om\)\ a9m $5+FhFk ;"T@(p%,ăP.Rf;uZ_ӞOO!8;+=%(qڞA…îO>n!IuՍs{;^|'F* 2j%zϒtyX?xxVf띗? ~k.Uy{#B.Gp{,1/N纛]K9U/0 rgT|!0au>Dk GLCq7\*_fޤ7̛[!>|#Φj^aD8OqV'Uii;\F4/KKm ~Xh3 tmk=g&/\YtlԃSRƵu>YUtm Ɂl"up$Ŭh%SGFDT =IwBe(ҐchǾ9e/YlG $X*HnΣ9 T#&5ly4kW=mĤ.x s&|=br{͙FL=|boԋoLnBʺzD9z{8gێe5>Cf!=‡k}X}E-‡ٮoPQr)={PK¼, U;U)SDO -ڬǔ$[Ip{c$1n$sPpn43Q_hB6"Hc L9ok -%?V`]6xLbrWȜ D yy˅1 *?B&>li{٨mR:P2TPvCM0wyc\0!/hboEg@~VJbH˂'ڻ<&Om6ܸj0CA hW,l=u(tNAl4[ &:9!8e0"ۋ Tw}pvy<?H8|w `eZ!eZ%o*8Lb|66 kۆ'"2ALRܾΦgq殀ŒXG2w BӼULG\ip7 %$eј`KŘ*LFD⎀61AΥ0ܘV7m/ }K+`'ag!tI஖ܪFnM F.*ffِz^&7g,]8"eJogq9Fj#Һ>sacR-[/w-S7N!!0-׸T\̋&oq p8 ,v' NM]X^F<8?=`>>/c#1V~68?|qyoX }|aA*3ǟl 3_Ѝ׻9 pcC26$cC2>cmIFlqGɈW#@2z=2YY"p`Z !$c2Aډo|Uhg\6 xkYmm)B/TҒVGbvN,eG _VHӤ_`K}&O|<3]iW. d9FHj,vv|b>jD.,6'j@>96TD|G yu}k) ~|].^߶w6ȝg3ON )V2s-XU܎3w^(8/'Qq k k c$jqlƑ:ic(TݰgEuJuʉ~"R[S|ȓ-/SAlFOr }LE(L}2(EabdG [Ib/BlM.zu%QζYok0 P!D鉅sʳ8M֭mK3Rl,(ˆaItVŷN2o1nƜWT)U~HgxJ/Hr6 I9ja\7j0h](~f\[&Iz2I םcqbSz:e6$FBzDK@c:ɵ[E^e:Ob/EXX#@?OMU vWu 5zAkg&(3gV'y(0N۪#5W @tK)H.%\.>a&|1;ߙ:I<ҶpxJW!38\7F/! CKG6yfzXq~bLQyHa9oޠP:.6 4 CIs΂iax6)xe| 4P\lh* a*/oa>pb>2Af9o< b ٴie [{Vo0$5A+oL[j5}{ʂ{tp%(kqZAMB15)XH/ǰ/{2 <`> 8F]1]n:Κ_;N}hc[{|z\ 0 =Tm[B^pLѤَZr-%(%ڛYW{1z3lSn 23˪mY!#.(jbl: ׫3'ȶSMv/Vx*$;H/}iR:4n؆7Xv疴1q~x]TٻH!pņ yם0\xFo֓)\p=x wיm87БC'ٸcV;{ϩW9}%Q$}*-Rޢ)m;jt{|08SvP[%>͞ 琷`݋׋ !Wuԫ TҗѺ8|l  LqJ),IL4Q*5Δz}f ԬW!Bop'_e%EV7YkBѣ`;Kc}y@䷔.V%SOaW#!BYNIk]3dfzOݷ07D'0b= SӅNo{|S茵vGtYl /:kp5=yf25x;qp2whѹ7OKtt?r̎X%Ôĝew{[T\jƁfz91}1scR=g6/1]LVFԤ?igK8n ]ر-2u=[Vحk[w }ZN|םh%@>h0 W1D!\5_&I/7b|ZS;fg+rTX4Ul =RM A|e!8 5"\EapFo5g05K|v&`Vn!2=ctkvY#q't[l[2vCHv$%}bX3| νkgj18C6.xexz3E&uM9ۛ28ɔ44']3b솾d0k!l{r/uwGR? ªD{1kZڇge1hiW~~^y.|wa@3Ǎ.K`JNVɮZ(Z~xZw`nGLNLXyoΧn}ȝZ 0H69,e{9AթѮ3 2`QR'htA[P l%0jzǶ t)vFDA+Zcя9%ςvSsnmq b#]n{eq 5REЉIm] '"v˂:^EOd]]m0zۧmz;Aq^RUH&?QG} {IiҺEzԞj­quAIK__8 V͜HZiDa_eW ~{KN|d^@Ԍ˅A1f9m?Il PVM-/ȶkl Ƴ]JK!(+eF|`_xF:., M5;mP&}8s/iU4MH^E? R0E}rx=4O kg+tgQVgQ2a6[哻jjj+nֵWI[Dp:KœC'"ӉN($dY0$8DZSrG0jy 8.9fVpzvNdLt2a3jQF(CV7DI,2p3c 9FS.NŒfH8F%{EQ~w;D7E9RsL{gC`=VK{'z?  ! UVώAS>>2&I \0c/8׹*aeAPl S p*¼4:*g~B A @E^J[ݣ~ӻ-+|9uOQ3#R#u$fS֢9~3z,r`e.m7RӳSRL4Omu(P~2qxH- 1n;pI^ B߇ x/;w9LL%pMt=N] Gv ڛQLsåŠOqHa16XDT)MKh4)aq ׹Q\Yq<Æ_Bdjv"b*CE#m^$qcdܦCldr}&ҞIlOQ {77BfWb˷^|(!Mg<]Sl_D՗b릢 KB lFޢ4TByhR#՝z k[g#%a+18YNL:n=||>ۇ׳uA#;Y⬥kUP]AR g?7E##q*:j~@w/o#1Ƌhh_v쓻@bt&܆|~B'3#n-.3ڧzg"xw<7(@77Pټ?捇uu\73cuܐ-H]cuIqtcڜ,Rg0X;HiD)gUr4zXIڰ}1f.,q6oK@gۙ.a}#s?0eYOYFRԝ)@czLY)뗟hϞ@uDZ6tC[;,Ky$.1{ʿGxoN3v.O̕뷑>룷9_go$7 Îդy[eȕaыuP$O=E8B`]u)>Q9W ㍇OKɇ!,`#$]F@Ifu훲: "c ZQ$?T"`B~Z@С .|=Ơp m ~ ~XS>0 \1cX? =)g eJ{#n5Ƌ&~\Z,K'k?$ Of`zፃkG?PhG/\۷nՑS?'n󟿁7`uNy;|[9p' NY+=}-?#8=ZCC5!yhHmaV9ZTV2dmC*<&)rIِ/ej@` hYb'uYd6vl< * ||!Y1pA7R|EcyQy>^8qFA 7d\!Mc]0u^Gùa;|\ K\vU95 dpfԘoRfLa|vxhsC^ᗗ[ں=>MW_s~^e]Eny4r ?̧_V>j/f67\bį\}E>8oZEvxs#V.DΫl،6wpӫiO~(J}zW~|?Ͽsl+Cn)PT924Qܦ}_rRSQ˘.82[~CKI$@TqYMSVUcqZocTjmhc.m@xצv\IEӑFd &RKjf38(Q!qm.ĆֱHx*_ș$3^!:> j ~qfz a'7It}v-W}i]ta.~͂}ձqiA\5 y {~WuϜ\/VۡmWf\7؄>YMyȂVGt܍ ,Pq -{;Y 3/ m=twY:~P) \h36 f@UD55B .mƫ|);7RuyT$ܺɀi>%,Aڈ?B@Ar%v=!>e.J^Qb2&Q6ǵfe $ Ҹ@A[*ǎVaϱG`2w$rAnJhRb]dEbcToC2̨ 1X(6}$il zLCn Z8ۼ_[߼7ZU*$NuGׂjUO{{,SboK|OZJ6Ɵ6NGYx6}3Zos4L3ZJB>RKy&q)i(actXz{R A Vx7WSgg.xw b Q&[vX[!pņ •6MMW SprD1uۦ&Lx3q1{d;{o =Y<uT2=BWhS)*! OY0ͻiwB{W|5OΎ|An|ܜ6~ܥuH:VdI=Xep]K+RF򉇍SBҀ S ;uw Ƕ/%^JRzc"vΏmGuBǹ1Jp&Ynz#5gLُ1S<[4lm9nzZyܐ=J.:W%pōP{X]CQS i>ҴX &E5`qKᓡ lo=7#bY ڎ]C^ >{fmT7PE˃Į )lz$^^AΛCf-|VwK-}뽻CdZ5ǽc`> z^d"x[9 rO@3 jVeDtkb#hn{1'FW`&\G1;k{Y\M;H #naB珘 kq"Xf1˅2٢(Jw'@T$Eg2+=Mtx+S 6iՈ}eTW:t?n;"SnO|'{{Q +ߧt^|zA~>H=u+Wx2L(!@'(.Z5GћM`a1_1whܼit_;t1> `@tmmh,xQ=,GU<Mj")\Ґ6B1mlA-*;AbEn@ 6j<B_*rT%f< FPq(mĊPM5Gi45; bO#>9Hߟ+<U:Θbs78#tdf1 V<;;^YWI|+w4aMWHHS*=vюJa`k(f8_ˀoœ_Ca'1eWF|mNfo'm1ͽWmm^kɶyH5T@C 5s +}x|`͏o4=h4EAҽ+UY(;]כ zK%X>|zH)&%Q$s޼ϗYH=j#0j̎x_3pL5 u´ٸRdK\/ETYF7XFK&f|6x?,(&KxԬb]Nxn9ƻ`LHGrɬQϙ>{8 G!aX)ͥʼn9aWС tɠ3JddvtpLpF2\񶧡9:S&|FCeӀ_n]W{(SoiL c1/B{ bX^( A.NIe7!4}a?:5Dҏ=BOh l~>BOb*0Ǭv؋'`ܕa7MB9?U1 IfVr* e(^ƒ÷B掖@繳P¨w\83 ~-!6H QZ!ǭXO!6q猠9$'Su!6k6jo-5ҟ*z|ӡjzP!܁yXNH7^svj7Sfj/#gY-0+诹ET%*ȾұQծqr5 2&SvWЭf6}[DȹQR=a3B=;:"q逘6.9~ E% ,4_M.?C^ER7`p1NT~yHdfcYp-F, sljD1"a}D$ F0&8^u iafM6c| ŏ/VEP7 z5- +U;ArQvBYnfdGm]I %_L]qFPXѦq+ &fJAvc kRH\h08GK@Sb:=Zе+l1?Ju2@V\|]o |g++ڏjoZ 3R7.SƼ\. ڧ] )pS O;Ŗ.Uk5v9 $ƴ 䛐NG~-#$a aH:a4E670},k2פ |'gKv3 YLȐ }yE r5^L;(fKxbv۵ai( !#mJ6/[nI|'daNP\mIڦ6I@P*Uù8r$@Drb_K$דvݫw+/#~hֺ7fz?淇v~^VOLno9vojt߶O?w{Ǔ_?? ;G~?BͳV?[^~Iuv<^}c׫sz}٬_6.nwM,|:>`|:BG/^mgj@$zVD_ Wkjqm>E]*>Eh*nݿ#4mpx0 o9: (-# ^XC!QNW!\ONsFC;!}j6ޛy{mDk$(19ʤ|%-yji 3oqPEZC)__[7ĺ.&+U x"}qw#1 ^`Yq_=zc>Ja'ÙW,qG!KrVa*LbZMѵixE Ip Zп ܢ{(΄k;؇T\w~85ʽC0FӄβQt6|*F7j*P*rٟ"%h*B"OT|_]5b3q}ڗybۯj t)4&#sI< =eídrC'f~0"s^W^tyc' 2d>۫/DžmL{9bq}oJkžuC9%E ; gONF |ңo36IfOpD'[ wY|U \|A:rx/TlBHƢxA7"dA? IVK)B}k8.8%J]NcyP*'[q^ 2RLpo_{Fd@4$VR<ÊR6;aYs"v5䤜&_ɞ.i;7PCiVCxތ5oQgt?-V*u<1pE@>hwG;K>j?Cf6?\Z$_ =)dDBzTx %& %:r]onuod sXhȁf_*^:>JR0D$f] gz}hM6'H*J߹@SOyZus7hR.6^ɀ } J$VcW:zl OPPBmԼW'V9<5@A7kB{eN:ըzzIzV\1› ٙoyE[0SHop*Wœ !E92wЯ6 RZCǐEl&W_T-0V5 qn堆Y @qUVLV[oT:,7r/znLY7A 6 ^j^U|OEBF Nozސ~$rW3QQfOb "[]nt[]-[$[QaR*DbmyJ_vo ф%P=_4/:fzfW0 E|Rc~0 h,Keb2Rz ƍk7o¯S7=JGXF8G>>v2YqdF1ٜv=l^Ro4pm#:L˩^ _u3V-^O+K5<^:Kwp0vnk!Qey/ ;~C/[5ܯl$1\62%T;x0{@u·1ID759s)8_̤E:歾&k; #25I̓,5a'xF?v웿TlĹaݥ.UUff]0!|NYpV,h 'v} YVggp~|w\āNjyve vy:'߾BR*ULT eth3ZPkoe}Tj_NĹpʥsTj EקY?a5 hCD3uRl!I:# mH֠{]",byWE%;fT\J\s7r|ʪN_ A5HDΊBkDjNߡ7T%SC Rf=4` 8F*fs~< ꤅>kYUЦIfӔm='D +rn. E\r}uy T /*+kDޖW޲=Kȋn;'/9zQfX7ׯ9is(L5bi>T=!L9Ji\yiw ΆYrH&݂$nVfDRֲYtdZC<3,Ρ-x4 -%*7)x_R qÓB]C<) "n0x raI VRGvGMDgcC@aX2ˆ!]TQzgh7joY(#k?jg>e ݥ'!.׏7&t#QM?]gYO9L 3Y )srAgʨM;xEůS4r|Jj9IY{ZN_]_k&!Oɿ' ( LB(@ _88*ز*#Ub鼞#Bw#"O ̏~9ʖ&{^nv/.f H$3J11u T\i+Ľ9uPh̚ak ,@jCDF86MtpuRY1yش<;( )-R q.kqWTƱ@ڬr&dJ : SZ'Ls@PƷ;h0(d:׋Z M%ՏE&l-6Bf2e8?$ pMQ08'c`ֳvB`uzg3~%mXW3'Qs =j+4 p,4 9uq3l Y$ҍ2Xy wPwk躺YFS˃*w YI6S`]o/eT $%5Hm" *#f6` 5SDEڥr7!>yfBW8yË5R ꙥEBA.r$9I74KJ¢ǰ)qN ʦ6 -SzN`^Sj ?P;Uy1RrKk^8B[9꓅a4tXG|77p/Ցk3ac<N̡E/p6+8o#,SoF̈dn/ށӪuNqX(W_F1ڒW`AF^>oU+.zDa,~Û ~sM>j2P&R73)%kSt,.6;rbbG@b^KL7=URW?Q';:E7a08 Fd"'DS;ü 2-K _ 8D1s(%5zvMFWZ[/x}.W4<Ÿ^Gc {034LFCL!̎k:'ߞt>`s9Y&xc[$qʘrÂ{P0+VA5a2??>lz(㔃\3Dyn`&0*VҘ|4 6^_>ùhB,@1 D:?.؛a x Q8?8ԋю7O? FTV55FC??  RQbv)60 Ҍ(- ')#`>?^ѤH6[}bsB!Fbao@%v\D.- ?c}է)lKg3嘤ډ$S)kMH0={ <@zHX?]wQbcFi2tvZzt݉k2R-S9290o[ ^tS@4!T"m" g4*֤&D0^:@щw 6+6 s9) <0  )r ,do(dgfˮjI)w(u[{,i{z  ت^AI@ᡄR+s+Z0ʀ Q q0C!4v^^Aa^8Q莧#3 >qt+kI5IӕGqȲsOKa`:H Br 2)R `pW0}H&gЕBlȕ}_L1XM&Ҹ:Uc'~%` ɩdѸ#9ObvȤ [1lBoCYd[@t[HjXVܶG{2p׺;Ͼ;yxYUYq#^x7O)T^TT }땿@HBߺ:bWoEqȷ)|,ibXCs 1 2/P`Kj**d:>mB]ܨ(~,% j+ Gk:r?Ʊyl'9;xP X/[x{W+i[9QoBo~LdRDhn{'uGd:ȩBn5]L.SLyA X΀LET(\W{XG)O% 19rZ.M>8xM/.eZW+ФPI4uc0gYx~k$$ UKgcB$Wɡ곦!yx֏=Q" "s_1]XE 3" R;T6`HMgmOs p6D#v̭Rʽo|Е: ו!,ũ17ɕD˒&Z3cXR7 K˔k8Ժ0'N#o'CJ+3Tp I$, _yT/jez"Ƹ 844dyRlm+F &l&Ɇ_"@ N?hATj$/#oݐ$ 4g hKCS|@u$,pa d_J-H#Oe}/&[jHqO= ]0py$L8D`aV2c>p-F~;C_EvouT('b %^ܜt8ϴRlӻQ[EPjH՜sDgcNj3h>C=+`rKǥ\{- bfW3Йed.iƓMBd0)pA0>hGy'$z@V5\-<3Ҽ62=X;|H(fY`MbG#=yTz 2E7?hc -|\/2yS,aݾ@9uI'`$uq nZl5$_U3\>Bn|nKؼ8mB>jJ{17/;،_vaSwd%=ˀ۪bKmk-JF!*YH"?qe*Q2h蹄fw[wexmN,+ף %kYSfk.#.x  -t&EW= 1uI.Wsp`iTv7/,!7a#JΆLSa1h֪,Fm2RKA/r:( S6,yu莛yhr聴*VGCTH:  )]Fr\|G{^jeVp]`3z%z4߄J(`|Ng jUc4+'|^ :>= dQ΋<٭VvsbeRh16DD2#`M0lr:fPLLj5:\6\ 3bF;5=+\W "ԊI3 ʤw%J[w+7\2kٳ~" fe+[Ztj,c. 98hWE0ԽիWA`5(;(\=DE0oHK4s$S1q3E !@x=HQtQJ*C7n5&(&ke l7ǔ7*v ٖni)LJsr`o(aHodݎ q|d6d1LHi}t X2φNS5H?5}2+5@m%/JZ>mNiN1Eio$1EU|OlWf5Trs)E09@ Vky:)wѮ3N+q;6ܱ⦁]  )Hr/d%M;}kI^G1;g("mS'Yֲh1M/>[ԓ,kϤle=ˏNumԲcƄrZYn3?DKZe4y7Td lJ5j{&Sm~Rs(js4 %7/op뢉;y׍ :M whf0LQVd`jz ] J;EidԨW=ocu bMl[FwAH11y&{1zE|K,efPmF4B]C+31P=hf!fCrT3765ѡ9F(d&nFOlN'^߿~HbUX4YԟFgMNnyc pû!Nɔ)t ߝPNY)]x K*ҝӄuiU;rC .d derleHPPŞQyX Ta[IP绠@D]DuxLѳyҐ|d\t}:őprBo^m%/bY9,M4?ٚ۲ Ӽ FQR}Z]K)<h;ap?W"W#Z%ϵEKx`Bߢn+)ՙt}]B4d4$CAQ PX X+0&|2v@#6KvOkP _~ ںj/4d1}%"n_"a%4?@F@a\Ì X[%F<:. zf%X$6YTlp-m[3%b,vJ AI #x{[JVľc_0Rj_:ҵ["'4zN[,lR62,,D劽&ƈs"!bօRF0OmRBm(eZR;Ɂ]v}LIvU-_6zTb+V z4K$U00!3ʛg~:#Q ԿĴAW x)4mPǕsUrziB4e\90W)}Pe$GҜvW(^⿐OׁNvqQf#|l>~]ʛgJ)"րl|$8RBs*e4Flhxqkߟ;pb&KX=%`"vęqTv.v!HKkD@81P2gs>̉-  Tb>I`.hLBuKn>&LJQuP\K-Ffް5$H z !> xK}zѾO󗎮O52%$MnpU-!0lUS ӳ`cY,W85+JbrFrfwQ35SwQMx$Ysm%τPaגyNthY}9ܦGgF9.[G]\0b8{D &`ՃzjkÙZ!?I 5-Ӡl6|<ةCUS(B^ 6-zyعŒT gY`ye +$wU,?!Y|~<(#QQ1T@HgAei䎓|1縏S:<2Gc)^HޤIFzNBhoa;.hKF#GRm{ͥ г$5ˤR)2]6K̸’mCJn|uclUIRcѯ]wYˋ:y\\y5Ͽ >YnWIM)qYygCx5 pYUۏ xl߻# (Jr-35;Ұl`ٟ|)Ҽjq>lanqH"Q0ʶɍ1;.uKНa0^3ft)=jFog 7Y 1cD,ui%Ylb̈́=2qȐ,KNgb,_ Q8W(.R'r|%_co;F^%4^m(/_';Ca3@; rL G? AQBc{l,=XVDP4|KSIN`Oڎ&eO-Ф g>R4S(vYƁEV|l ht4 ,;h .ib@p1#cU\{8Fy%)^v* 'f1`r%z 1IpB,6TlQ92`F"]Pl:r<Ex-yʰ&C bc bH+P WI^>ylyAFn6Vߔ]UkPJ v+*IΚ99Xx1R[jyX7"?0ٕUeLy |m^&Y>"hϓ%#7r*pL@@l+s!q A8 e0H7đ.`N@Q]3beCEyHL-GǓ%80XA|P,%Qw ^׬\-1[߮KmZ?8+}(ft Yk]cr:\0ar> UwaDhzncmlnPGМun-SvNk7mؔцc60bvAKEeLb?ᵣUaI"#mi#!$~9Y!H 6[JcS"mXam~sҞW̽ !#% ]|LRB3&;-ViEqH^hȬԎNߙ-*ѥ ` R v3A}O0JmՅ%Q m%2,|NМ_ XKO9# CRCa%0ͼ_*Pvޥgbb=BtUγ~'}8Ŷ4 Po.Epbϻ/KB`ZH&H:UjX.@(CM[/i `c #Y&/Gu#ʼFzCQCW{~ۯ p^Gw,fړp$܌JZ`OLFobvY|A칚f̦+l5c93hsyhImh#ˣfe`כW2}A^I\F__E3QuoU=CuF:ok׼{aͲ=+L&1L)u2}r[BK҈$XJ{;IXHu}xUaq0017nx=`4FiU@XK! ^4tv/==p~ؐBw֗c}%\me0nƋ40 7|B&; .L;av#l-u N d0D r pDfj(5uu3YVsv幜 ^Lnncyg]O5"Lqu+(}m_.t/A Jv2\8:Dzk2o!2BpY/n#]~p:%>eıb"^"_z%G_ѫ棺(y֪o _4^,KKί2L : ˳N~dm3*O,#QD.Ym %Ko竄prqfw9SPXAF`4klDڳAxpM" @H9e&\ku:-f~ڨ;1lEimfnWzevʩr^C`- #Dެ4^ޤAS;7`8Ǥ4j?\;5,oin5l,j#0o{}OĜGĂ#=s[uS&{,6\^&uNlCK nvͮ4!|kb_HBƔ¤ǽIHE'yU85Tє r% Zt7ڦYٻ纳Tr}*>B^&2HT{s B1 %Fq4&Z;X) ;}λW JR^0y/޾?x?B展 KdLQn{wwJ.u.KYR9^Y/L~:`m RXe0h4,W@j6=>hG45+ZƁWɮ䁄dqrU@޸ 'Peu7^1L֗XBp!( S~'FN> vN잲R؝BR~`y,-PwzwE;Nr,SPS !I/l2oQYB~L [j!m*Ex7OGMh1$E* e,UR7 H @;)*KkiDl{TYITfTOG%!1C.MR[hR6zψ+JmK)M 2& Sҧq7&tvug O!\ F'E9`3P@WՉL dDEP9Tk^v|ٜs_@X0TEX^r:&m_ ORz-J2 =yrj3r7;իljӐ0^UK:Ǎ)eaAd}_0/s[x7:LA4m$V! sm6bNlf48 ^ Yd4"Ҕ&M+Ah0In}~!lj"m%bXA$vdf-m[.PDqx5>=cl-<[[b(+ӗI/a&Ogwy(!ɱV:Ճz! A$T-C QA˜yAh^WnL#>VuRTf7('{W(M<.$-ROG:"|ɘ́e sa2cq|cV4'B{ ?/{ ) 8`~>.RZ]n.fN*r:8k1 Nm̡|ߣ?H#`4hØR nCɝZ|ZQu s)6Ai>\[U^tX̗Xj=# uKIkUC.:%o@|u.E;'13" "O,0lN/.|^'u.Vsb 8y- QK<oQ#iG 6h?p{w~qx(œ6ܒ2>u嘷>i=*'x<=G5NaXEm(\7aķWS9J?4M|_]UIP)(t6&8:Rel-,5x"QTd#[%^A*! +Ұ-gbR)v8*/lkwK,eӃa'rAQyy{j|(2x  H R$\@!A0 2 WhM[ׂYxp}*/^E#ՂG?m2h}wZ@ vobwܶ! ˆD7m6Tۘ %΢ۙYeR(Q^/K8-XZ z^<:8gs6*S$\褪POLy`7^CF/xD+EbuL_[8]çڨqhD*!$z!j|gQ2 `.0`p.3ЫXr>֪bVs$KgGT({J{A^g:ڥ k[Y7^%+%bi 4LRX-VPc/Imj% <|t?W_8;'`ěOiȐU%F>JeJR~@(E+0./,dBC X~_V)2$1ϓ#i<D~pJh _hD XY99OꏔlCF~ wu(mK01J'ӌWW&ǤL[98ʄDW2! {Lp <*E}K>@溚\|m!/p}:䩰]NHPqR¯zNņN}xalk.jڬҩ ݅ݘ 3Ql1e!2 *92N^2L^YUIN%SIYfum6mR{'Na0=}m rqr24*,!ٽig\%GaM,FR1S6~A8f)b(O-E%0"Lm({T&WǤ=GY=x:M=4glz+Lr%JJ8iUN?y]n ).0`"Sߺwl O'`VQT>YVë2(MC3[@A%SSm5+vA9*!ƑY=m1uxoT։qն-oSL1R 2ϙV@2'1: kP¢ȐL`V[w-u}xw4t0 \Qc/B%.C`/!U *b<]M,Zst=ֲFl3YtE<aLjRU~)1lv\|6vR'7OwLP :MbUpuE;z?RfM>i)i'>HZmHM<1 ظ>]fJE(|L^g;Q^㼜MR,Rų!U!:OrAl>r>r2w 99.':AQeюdԔɂ O h=bi,-7hWWmJ~}G{}4eMZw^ =DxA]vCl,:9.x捂^vĜ)Lf`iR9#4V!8m.|?:QjYh vs־XAsmhpL;ҝDM:xZG9ڃטq/-&zbV¨=1sG`])wsuډeԨ\jxX`6 FsArM>ģ(xsHR4!(J~%?{t])\m7@ֳ.-=K2jcra $WZy1 K iW{P= CbD`RzQY"~pO%(3=43BM>BMYC Q1.q73LձJVe(Pt yj*(!vm64jEaQ 1qm=TMΉ?R\b7hGK5P*-fFbD+lt EX[)TM-F2Z pfRl8xˇaΠ7|ЎSvzU&P1En055|>'Xc;rxN; fwz`F4*]Bj͕._JT렢[tVÊ j4VڂkyY 'E?>Ԍ9l^[VSKжA{H6ir2Kp6݊K{H ,③EaUo"q|1A{dXgB_^ T@UFt7Qtu7UTw$ȭ((PL)ir_( a+!sdaRMroi|kP:{/duR6Ax!),0@uyyFEM׋z+P$D8 Q)~1x">!2RU/~+oMD3$ʳL/fh;PͶǓY Sޏ*,6nq'IJN5 }VjLw؜$sb4J`"SXU*Ճz*M-Hp` |KOR^2G\ 9ǔ IPq叠1,̆<ښ94XB_zUQTnOV-aאF>x܌=x" \ޯF}(rc5? pO}HvA!,GIM>M~K٧ƕ<˯ٚX0ۉ yKޞ/mu_ҷ'At{ڞ7q/),"aAHty4{2Na#yBqZ7h_V/ Ҿ7^xzroM4eҷJz]Ɩlr\¨$WѸ$ DYeF6oX%A Fg2z1~W)-|_o6<;3{D f͌%!2' ^]=a3fFqBJ~h`14Ҭ ^>ACwRk!ͫĺM5 ]#  m)fP@9I,jjm. Xbjb<{ gOG5NdU9I.^yyd I޽ŇY/xUrhˠ՛sO6nw ۷g110Rd^}xsr~g#i9>E]*`wp?7^<$ᒴrС&^g+O@IN.NjtiI=JP({u)ZzRkmz|"h8YaF o"ӎ9$g3a4@El9R j 2! Զ.ڦ'jLS,jMy,"NhnS89ZɱF##RX~XU,Y6|d%"w!e*,e۴ `Q3.w"uN^2h1 r ;y5jIω.$P':ԼBVԥi7'N]dXm9CM`Ѥd#OAD;i%b8BGM{[3t|f04N~=cJL_Hdeɼt7Tk @`33Hh /k*RkyϤޏP:H*pN;@NL %EBqT+&@B m )t&J,ic hZ=^:7;Ԝd(c(K݇WH܊f6 |lHdu֤UzbN9΢ϲ,A BX%'Ij{+4;XMț`EfaIA2 K˓zO;dmP*KJl^ڋ(V}YTl1u^!%*=vr&|T`Cw9jBwcJ;/*o'%tu3ݰf%h1ǩȜIʝ*'FsīQ'MlSߍ7 .\h`O-| (E(hCb@Ugߔߠŷ Y():DDB{bO}U^}k6BY͹ MC ٤DwXn5,V=t )ߙP]em{36k+/v d_/!NƷǟNI)KVgHTHb!(F뇕f+OVl8B)U ue ʤ 4U7Q)1N}wFYWv8Va9Cx9*uPm}xxl FeS@RLNj6t$6A[|d.ѨH_~}sŸ4J*zۆ,0S#ȣ~9LcD[G~1.{%l\d:e})fg*Ķ$uCe _[EC%2@ؐ"rʒgCӓf#{`d| `Yծ gL~V8 z}X3M:k 3ESǻODf]T@H%C”z/K^2PwݶE*(̑es x Xg/+?eZpzm |o%Ѻ% xuK/m%4t:~LFKr]7#Ш -fUf]ǿ<Uj^&x"\E!z ۲Eȹ>g?YVV_d<DPBH:|`rԦkSIQ !E+j8n:_?|Vۯ4J^AVX;U }AzZ?<:QҮ*vj6QQ59&+7:ߔBB& t6feϡ|AǦU$Ca'LdvN r"H~һV;n4Qz#&`wePmpOI?aq(-t"K4nuR;'+wNM'lS⑲)>N?M*x jZ `\{|9.? ^\W{?GFިVE'lVnYG|X?Nko~XKP%t(1 V^UXR`y&u߽1(C0Y+vFpHk¬qJ+n5 FTR(sP?NNM`\ŗ:\q8yMn6Urja*mprnIi<nb"8\Q\i CؚM;-Xj(I:maBY?1;Δ.?eX5Ot w0'  U,PMtkzs-8Ї=ϕ슀 AF2$p `ÏտDy䵾@\y%0V#Fj#)4+'wS|A3T=1k0JC'Pf.̸CtHđ%M-TPz  9Ũtì^mhs0KZi :UiKKXPuLOc?-h,q#2BH$젂l+};Of $(L*2~.ӊI3"Rev `6 t4LXp$V$ L+CpRgpam')KЕbEI#ېm^v?tGɽѓPՀ?gj8KƏzf뱨%LSdycMm"vgѤc'-Vu:w=T4)B^"E"ظ BN<\#v<ugWf_TK\I:R=&`Jk&2y"N Ҵ8 (mgQUjҚF+e Zr*v [6a 5xwޙ|ޑZ6NhQpxcA Cl N/({s? Ǔ^S\ݜJD2(f;͵6"A<[hi.lQST5>+Uo߀C$좧j@:#!zb^m0vs0[oGݢ^P c`|m!492Od˗7EW^dj} XxÑ<$yTJ8~== 9oB.$51"T aPFDqI.xu8&LtOtބ8Ubll0@tDf[l&" KixӔ-.w#HXL'+Lx9 p$}rؒ QQVk*tt"!$vOFs%7s # JYVI0r儵uQY'zTI>"6Vkg\INMxjrWBJrrX4˴uϴ(x}2u[>MmCxu&MQ}x#pQeoJ]Fdp5#Nvkg76 }ѻCQA)X^%Ua ;:^844a4@uzhs̾8'" rpjQMa{NRd/g˞t;0ASq)Lp1Cx*q7v5΍ b@jfO1OYm׻0 "#}@> 9ӡJBK]=$lؖmVl' Jdpnz7`j0ӽl`cH+b;+\{@:z/-rv6U}ؐ"=jv/3Zyʳ/=F+ hU BߑyE-s7JnDyM@xOq4dvψOqÄa(,b^vp{;%BdF`aX]߈FC9 k2Ne{xmK0b _ 乏{ڒi0=aIL|s?+ ܟbiO{?W P*2\2-iD)|u}x~bڔ^LvzAe;Anyp?sTP+R67ȇzC$ĽmBoU{Fvb9f#HZ"8qM#Kv<΄0Y:*-J4#hVm9FQ۠⬲b&O` `\n5AQ]'J"\6_-<6@G +zNd YOgy?Au!Ձ7Y E#XO 9WJU9AȉQRܬyL //=ֈd5cFr"jt럋 sLa՛ ǥM:ea5MLR7DZ@N\ZWi<%>ƇC0y C @FL{2BVLoCEAZn} 7w}ݿtyq?9ZzBM]%t~MӲkbTtװ?| \/So`j(eG- =B~rPe7Q gko9 X{geL01I`HIɦ /nW]߾{ؿ,A('S ?ot NS71N(I'^I|` t} ֭'}zsps/czrzg(t72S29 i4X9 G0x|b.qwAL7@k{hpBm!tCW 5"Ÿb "a \>4[ xx!z"iv-.݈ h%u[G_z+ʈ] ,83-8xJՔC r7YJ3^\%Zp۲LZ"g(`:i}o006Agun `׵}OM`ӑP"e-ؐm!K~%Gݮ`vry?i'=a(ڼSBۋ7Kfi0v[6\DٺȖz̽mX`CêYzysV|3o6R[{Wy nKnNCgWJ7-uA1#Y R&.ݱB)oʽ |q!uԵi0=WU%5ִ UzFF2m%SBNcW0D;3V\1E%!_ޥOYԃh2.DGO}w-JҸO}NۛCV+xlJFBMrPZ0L}$dW9,5]Q" W5̶Y@U9pKzb(:Av7*b;G@$խ".Tޕ"3Gp5# D4F6'Pթo7¿\c --V WK9\DM};^9_Ð6|,~U䓫#$=q( w 5Y ;PH2W~63[]isҫeFI7(138fMMպWK3F aH]8ܙt2Ν5 %)S%->';`M0آ ]th#17kzjx%U[vƫ-Ŗ4=p♒`'T˦P1f?^K[Op`;-^5Ű4:](GbV.T-JJb[c)l4O:ALYf;nyBحrR93'UT} ]vXm+ U7u:0}۵7!Jaׂ!)7W^GuO:OO&N,G+M :ZQ֤`^"X<~lߦm*:12[\} DO-cDBf3~<%{Kj7*U7'󺤴.c7*qqi݂"rmPqBL-ʖܻRѭ^Wp8<ʚTY8LђxN@e)T1_ S+ѱqoTT`yOe<4)~e%T<#j8Pd+vQK[ chALZNJ-fιSvT^ȈA_XǼ%w.9T9m!YlvaỖ{+[=rQJnw2U5X6RAPv}^ePVi~r^ Ŏz@*gN"L}I kз'5`9E@(dl״kʄN96 ʣU@M$DlNUSXe4s$ M.)G46@ڦ.6F}f.6x!KͅM]]ҷT@b8܌AH617ceiJ!$uCSv~, [S0N[M@``z턋&;nJl ܜjȤ 'eoAivݸ?Ͳl2?XҲk$ӻ .M1xxPLn I ,Ҭ3 H @ e:*Ψaf`ssWą1cr 9ɽbfFP5q1ٔ{N۪7?0F07M<,A s}8S1$ ók,],\>@}"홷5Or^@7DHQcm-1O}MUzbϱ~坟8)OӝY k|s9J f#_Zg{'s`z wzvK0  a%%zzgĞdh (%́?NU  .T 'aQ k4K%өxnD̕m p %%uIciC.MrtUiְtxARU8qDjq 1g$Vߜ>2G\DY,I|d8! #}hr䌘2Xgslwm@ɍfc闋8-!ތUޛVӆf|v 9S@*UZ>sAJ##WzE W7iՔ3ze U IWe6|W1 ģ(-ELBdFLOm=j;HÚt_*T C5. [N+ٖo5 ZwK72K`Tմؙ~u DzHsÌ0(j9Eڵ- !+꫶s;r|9u7eq+︉~x,T1f…ꔄR@.QtGCDC%/L q-XBIAio 6P]p};GeVEa6LmCw.0 hѐW"TX 2ȍ#F?9d6L  *ߗɶ2ielbN|~wq$vYucv}y5yk.[<΅zPDꇥ~VmV~G-Tzbrs"\=ؐU[==ѷȱn&?.P kI\Eîgd Gq0}^VFVip;SzNXKk.ذ`(e{ (Eh&!qE湘n=!B!_'``Kbhp:ف([|[Fn§j>!5W&^٭}|; X Nn$ Ub0se{G(j V'jv JaVc} fX7 +Fi%z46tC!KGı;ʀ<ܣW[Q]rM]- 4(Fe`wkmc+d֠_sVO_Bg!~E-~H\!Zf0-nUtQ@Ɓqv#%WthNr&"\<?Ng) jGs\ikq' _EDq* quX1WLv,"gV/';ηw$Fw$@w]1>-Jr]"M-%C")?lhpo;cz.:"R7ĬF >fw+} bTp")ւTȝ+r#hjHDCYA_0"%v,,JQp? c"8C’I`lp,'4X [}\[ΰg |%V5L!D4LOD` t>~:1x,9r-PhT18p'FW rlİ pN>DOØښG56qc%S~b5C\L\L[-B &~ );7 G004jh{Ʃ6I*F (dID>Xo9Y幜t0܊ȮMS"% IKA$4N6hmtTQleiBVd\| ?if ]*7R "G=0Ĝ)`Ym"O Pa*TըhXvp 5L$C{c膕X# SS%wwz-)#*B Cb>H^3n6j!߽#b9Lŵ6$v{T $p)=VnB5Qh.z6J1̧Tti/Q<*oZnDRNS;Z1Ȗr.rBeSxV9xVr9s+uAn )4pEXMISN7W>!K_*een G~@7ʋa4MC3H["pXE8<1S%?!NYIRN%l9-1kKNOwucc4LXD %3}Dxtt~,,1 w`;d#@|U͗amJGC]'|)|?dO^)+ɾB޻<9߻㠤ۡ) <+l / פ-ۺ&-=J> 2 \FTiEqٮmB2S.]@ Zv.O oC$`fJQȘExu H:ՔEml ׶_W_KmMckD!p|QDsF=tXے{NQܶd]n%`36b>%JUh<"'+jƃ8^04Yk|P ZQB&S|>oL<%kk8 .ba%8m)`JkީN\ żTmfH,K~4  Du[CU" ENJu%1c^*N 2`Q V2K):Ks{TtVěDCGd[ .= '6K{к@qH'2wGdu{F&>pTl֮&g%ͫ-zT[?1hhrN2nVw|W`-Ljtn*g/ kOgʆs5v]vʹ*d d(2r(ǂ}hl#Uh9Ԝcz$I.N6o\h^ٙPkcu"geR+fEz=8̘!.V_{st|vM1YrVMw.r_LVB*Ϲlr]Va Z u#5w>iWbeR Rtr1%FaT8ݸ"Ω`DS)@h()!DJv[MxmR)dUMn**]NOOEr{~x~T ȝQt}ӰgѺÍr^< F^sl=x(#M6.S`iq WV}ɩevG%3_җ eL)N!)hߩ}(S?XWmR;z!s4.NM c;~iok ,a{G_-.%iKWQ R^8P9&IUN اw|:h P]UuGHm`-]U rd FQ$WE)"չN306<;~sAPˠN3l/zuY.qV܏>l4 H\B7t4xts?+y[_yI)ɥtEVIkHOֵgL+(E;+sǧtH.E8=ڻk\(\ Y%̭NuRiF$F))̭ gvvhR |%2bS RVTW*2FKMkJ:vmH S!i1˿Q X)mj1 ^j]mQ!-/d-7L(w,y#[8 J"4z՜[fX Z0sX,Y슥 46ҳܿ88jS,ql IR?LK_ec9׷>ݿ}Rye#ȒWa޲eT|3En; vLn̳ /57:u|g:훪\"CٞmN/5'sU{uV Fleh_p_kL7c-bnn(SE #>-#-],>`H{n-c l40`QZ`6X. 3ٴRWK.!n{x1擩b鐜R 7I7't{Kr3]f7W8M<_ (mɪf 6 H?~FOF[LFX( "$( ''x'~F j)'~>36;0b4H1S/8A4}o(~"k2g<)&TTR^eW0ߌuWJ_sN +.5q䷍+YY]۳OC9JG͑i$oOM p^`BQ ɀT·OA_)=ȱ<ʹxa  -of=V=MP~Di"֮ZPO YAE.v̒fyx⢇h_S-q>SFJպ 9.&M`3f@\-3ݠR۰] aP`M j^ͻ%-vڅgľ㕋<>73`g$щ̮XĪejA yJ/VNhMpze]J8~mqٹI-/n@ZDl9VEmX4X"8U ~ Yw꒧Eg_y[Mݷ^ye kgQJhut=eAzn({z'YI~Y౔!)nFIe^@x@ 1$/!Ih%| j?Ue(G~S%7MGNotlѹWX7T+DzcMPn]rRAj_6]>&FY@!ˑˌ`\W%-DTjc*FTpB5 fum <7=:VU˜+}T73h@~`1F#zIz{MH,%R_o;آz~F\BB} JKP2!% Ek/q ]}"E´ ,+,)-J4Zѥ*7B )kUx$DҪxS;J֢Ŕ\W$C.TU)G%_Σ==F75F#1D{AQ*!^OX_6'?>Ib%${uKy'>Pǁp"\I^A!L_ %lG*PLNك#(hWr$֌ )U&y]/#rN.XFLVK.@R*< Y'ڍdNڴW(mNK8⨔M_@, & M_a RJqgeHO4bĂuAJs-dZ*bfaXFO:L5877RuY_輰Ţjs!j R²8HgqvVr;)""M#,S]:]ٺli7OyA`ad`_^@S'U5: $g!H-,d h vaud,>B~8'khOĆn0~i>$I~8 ,4l2`ΠjjrɖRl6 XRo> :P8a*0Lwq ]Q:Z9w2s[8]J18*tTMxgXotaZ*;]'ugޕm}Â&S2 9*O}sc,M:!(P-+LӽӃ2߭)--РGgoR9\a@Z$'춬R:1zvt).,U}^(g#^gm>ݧ0;im xoִ=[}b } n'kȫL(s֛(ut. WmX-Nt6<2|k bj)ZP"Q'0=) =,w{C=`߿E!ulyYrb,YT?ڸM_;6eq[<>(OtNKћSk+B#)-S &uUb^vƩӧ`L`T}OU0gPÞa4PPHm3upb7t?bwnF0=P>G/9[zJ-D!C׸B@xz m5J~XpFz87ѿf08Ӑ&&SQԞˊƫ`"iݿ'G k\[Є9 pwѰw+Yhdy O4) frJz)>(2by]5VE<)9 !L/g/#R_Zg(: o0_g5BMlߺՙZHN!uc[[z.5r7,sFe:#ܒ' Oa} ǎ J"UU8"ȕC,,hdJ8+ԆELq4 Q~CsMlts"YLI(JQd@dHDmMg\MNޤVL{n]^Lg瘈jp]y͍)% []"):6K+[d0 iIN6`ټe=ZBTTҁ}~k& 7鵡Nj#Z V糬Ck4QsR9vnu$txuxtS˺ h*V sNk`|qc ʁ~-I~c,Tʵ;E-}R$˗칵p7Ww4@Xqtw7άo%(abBp<'.WK}֝I5*º5QM ܔ+dɛɛϠsḂz>`̯sS?MgƁڼY &Yт=h*5&FE#, C1Nh01Jh;|5r* "KD\* 8kzm(gK#iV8"љW\|T6 h2sQ";MIk4\UmϬ(K}Q"x9'T"돆WDd$Y-U_Wq Y~g"~J3ӷ?"@Uv>F׉jgxv>=Dããóc9s#'gg{G# jYŞ|R?~^XW}(&bI++ <㛳ף4"+{Q$+ͷ\!*yl2 q=c|xrVgX晃QS-_iNOsjiX`\$ Mǁťvnj"+'ۀhDVCP~H CnjmW w0.&,;9KOaw`-;_zc)DpGŋaʽ4,i0R&I']h3/$>>_?i`d|̨t;.lZgXޱ]vm7 I }A$W o$?Xa*&V +ۅ5XwG(Nke?T6{$S/gY Dꊝgh 6{f/Wyv'ݼ\ M1ǔ/>ɐhP7pM-޴yyfԱ ö{Tv/(RwOHxۆnCF8@_SR5qMI+0[ӿWĘ .;i˰Q :}\6q+"fl6I749ݧ^Pے/TQUKp |6[c y9Y=L :L˝|Oxgy7SqH4[;Z_bM8VhH_C$Mjbt-s+qUȞ]6d{vBqdju~z:O"+3"\3@'>q$:`C1C/"?{߶6e+8#Q.(FHTvvH8IH˜xвT/=W_r ;(RRC̽W}WuWټVhqy ̫FC\kW̳wρ &A&r⚭zs$vtۅP,zk@2|wy=dl(W^g^0 34C<&|ƅ> ς3źՒB^9I"Q}UBဎ;l$iC u{ѡs,cJﵣqvABءč}#ނIoi_pmڏd`nvkr]au;]=t^|Zg68(7^eG8cB5 w&[ N50 *LVN "F(Hts.r8\ IhgG%^ӻT~׋/_ߝ}xۅK+b[t@%A!J }}鰽C ?"Scj VY ʴS:R}> t!kL8 H,5ٙ]׫Sv-gg<{27f ?#p!f1ǨE]I-]C0Έu7vw8xe$'l'~ !J:;wǿǙpw2r&^ROz ПVضNv_[gqpf)_EFw1ǵ|pnV4mAqQ{s0hvsptèJ tɴ:ҷ~IQ%ud>v;pLi*lϱ +y~0SinZ`g0?1AO/vFz ;>4VQ6թ6񖮣1 R,SC6kƢËa@aapb.EVy5X4YKyj!&$EQڋJܔ%E4<;[z!OIyUVI0RL0 LJQ6[œlrU+EeaM3Z#|pg#I|S|{2h<βڡњ < ܠ幐/ph҉F~EiHI(7tGJAX1&>;PPƯ#6|5%_}iHɻktr#I/<-~iPSc⥆TdM]7mu0 FR=-xeQ_%6;3R&frUp\û`-ͻim%Hƻ /J I5p?Nw,3 m ;ۏ{] WI[%)t5I@c +'rZ t42Cq9k/Pz֘VO|+&ר=1R;@R".0㛋_pmϮ3?aeF]2Nf~醜} _DtVwpi3^ M&;,QXuT&GCyb|'+d; KtoB0*mi;gnZ%"4d/FT띒udw?  (Q76H䗝CF#5{_!mWN_9)IA?#M@{c fxgϨzJo?DWqBs<4ub Ke~ I((y8|hgF==?zx1goC+>"ZTK䝵MoTBub8Ob"ta%aF7}~cGӋ #1rQ#?;==L !%4$s6}=2/16ki .ϕ|碷{y a%-mã5kOlшV]^;~;?9Ň,XAuYNޖ8.eu^qoA: ::9,ݰo M0*T) ejX6+5KCKmΩSe`Uތp6Ȭ}?фx(j7R0痈Z5?V pQsV:H$ hKjg<)kZo{|Kexi|\[/0 ߝ^]_|˯ex'i #LRR#(n^ҷ%bfQ&6qϭx?s*]Td&XavyKDߟ"FZGLȀ9 rVENoex V˖;,XC& t,w&s71BH~حԞ4iMPIO6I,3 }xj8u٦T傘Gˉ@4W_)̏%!prK-ֳtKg$m[B;9=GH rƒ3cp~25D,Mv_+@3 dOl=hDc/QiirU'>H@(TnVeFqtq"*7ELеud`: о?{OaI1m [$iO{Nk|HvE@Z}^$KǠK+f<R}.j޿qe>LϦy\4EW C6U/|k/P{=8<6Nze)+NIia)XƫRY#;9;d[-iz'{A1R R-\HT+Z_o(:/{ԸѰ#Wɳ=>9D!">ܐ1ȥMe7 I$!x~=޿%eǟΎ/|f~‡/;=\D_v~#[WwWrrD,"I}tOpW]*n܃K=BTs֖q=⥆2S]Psk"{͂`bKfquts$w '1١tMQ' zMZ]<|h2c6>gh.D`klN%,y"2cNB"XavrYzEcF` L؀؛B4}[Cs5`U6j a}6w`gTbn{-}|%FQ+pzM"Y- '׳qg)[ڼ =Ay|>h p|lnjB h2a4\?ċ;O`-Ҥ(sb1p*Dn^{ywFSY5 spgo4a8?g)M#ooX.)-+3! 6IL5wwJL{xQxP~M .-史 74y'7kBS,ݐ-?9[K-ub/1G {aץagã>TuFiDj;%W=\.K`5v{9qΑz*s'րx)-sd@N*#ݚVIJT\[3=&Ɔ2^+_>5o. +f(\kia^Mo,bX0?D!QIn?249NOU~!iHp3p*>׀CEXr@y&&,6Fa]$!C4[vV ؕ@YEmgfXzht[5 ÂUP͕Y_"6b.Vֵo-b;A3ZU~(KAςLDXN$x :niXb y3xmR : ћ6VwAA7hrwtS'%qъ9I=6 R,<+ hC FA*-aG]_ 4Q++7)tfKm6OڑMDnC^B#dx$n:_:WWj`!OK֎\jiډ` )Ix66TlB[ =r^ȼ,j#QA{hw yCHPeX1:T:S]$T3Ojhʭ:Ƞ"[Xb5ҰfnIqOMk@&={$D|RJm% <.^gEIM|v|jXr拨K 셹$˸9vr 5"J)ɯYv*kY{`q%y)TԱ|po**JDY Q8q,wqU:7t0)2qwj| Z@K1Hi8}t=q2QIU,;>la!HinB5zZn[2"Cz*k<\ RHA\R&\:71(m@fֵa$\Zd(+*KĨ)2+ סyDZ-WbY7v,-JքdV'L7˲ XQP$™f *=Q[͋ $GS R6!h iEF|nyV 98,HedT&\+vO0gckGnE[cyivJKU˨E^U[X`eϮ*p=<` yŤ:Z,Oh]F :]ݮ,n`L%f(ICfMQ ltmo`-vlj9,*ućq\fä͕r/wy0= .O7uЈ.QΉ6 &XS^V9b,&Ot(NC,Jkiˁ\,,j停lʤ?фӨkW&ZjȖcV4jV%(`S}ȣHq+yFB/$2~0>BBDJ֥KãKBĉUR;sZEݙAw]"m̬ ̱5 M´͉9t  R5{cbCWUwqܞh/q)sSȌO@=ƳFuoihX8+,LL9s#Ưn5b@VxYM"\Γ#nkو8 {j@e4x *lFR0郣 y=hb_zKh% aO:EJیfRѸI|cAtz@\B@,{wXsO0cOW^g^0 3L7bMx=;t] &fn9V ǀslA21trKhv+w]ާ"HTf^!YF_h&k9Y^fV0aṋsЀYRsE0j^ǖ(>\-!ɃA7m4`@CW hKکA:`rhJ {]3+4[#Y, Ad¢J&JOY+X8JDI\;t tgJ %OCFs/w b,؜gh(&;r0i9a+K9?s4n8dߩ嬟".Y 5REQD$TbF@,o.8y[.ɹ˜u!WmFM"YH2DܢhkB/tŀcE. ɄM~y?6x)OanR:Nٵ:N :nm N&Zf6s8Td 95osҌX7|A\X6S~Y@dKHrajX[@_[eB V^dL_j:%P45yq;9m_\}zӫữgǏ;lfV M 5 /کtY_c5%,8$DBbj9,3_1)GA8Iv=Yu,-,^رv#eKEqebȀK!Pޕ{qIpDUC UF?^f[Y*lkg!kT5vvFNWpܸ"Aݏjlt€"+/ߡmxC!ޠ_SZIX_1.$mr!3Fܷ }aK!`>":Cl s$Գ0Dch?eiZ;)fHq#f1WN x@7 ( b@KO>pׂ-Cnw_5F~=/8qvs4 SyMAX ozM8H71}qٍDI[y =Sv/<]аKӲ8ҟŗ zK.,L*R/]1 "Sbk;eAOTŶpYCPQD6ţy B)ؽ ?<L;df3d]]S݌q9O~x߂[OH:v=WA,5qr+Ggigwr0|8lӇ0fn :W­ dp 0ST=B%>~6NzF>8,YSb3CbC`2QZ7 +)|@d|ti}l5-q5o-;cS*Xwʥ?*IT]H*@Ma<Ӥil0ti Ik}{ͿSi3x8H#aH('BnoVLjèzni8TCe䂥r9lhs_bM*} ˚{o)} Vy^9"T+k,l@H\L3b<}-4PCOɅyYDqm1':VCv+c&vVp;ڂ= x@7G0j*ןʒEL2u+?!"(bu ~qqN rzU"\V~DI\TnXLm[;݈ g^Ģ~w9B$ ,F AZE9FW +XYD#㛋;)6nִͩh6S覂Zka/cIdWrMV,3ZPBQ:Bh,3ڶ-'}W4?Ŷ-|-`LmyoNN97Go^ 4̸/t4} #V]R JB-ª,8ٗ`Tp5/Qj8"ص_UK<_;A(9l%L|PUaq<ox!ih$Ӿl%6 tmb`6fwfE̿J@^q0ǔDhQ{C d)ͧ 'm"}wb:a)]`#L`e[E2A Ac0@*GG͞X7qsft$[̖PzHťwφ'12),VX"v2$.[vq+ё[ <=Y<,*v4Bwof`ө_ 1VmJk?AE0+fļm4&ȵq8JNh?#7@6(se?lo͸\IյuVM&Hc=<W+W lfsLgOd!u=ZKW~չטJGL&OǘWR {P[U/e8\Zy+P…=ys6d:EXEk`'<ք) ѐh} Z}QVm51 %taE*`D&goj"0KY9-@@ $N j{ J?J)EP*%5W\=FB{A"+)8s]AVi,JOy"StCe J,͵j `-)}ĥ3ѦIt xM?`L7kG_r2\"M/ܮGZq~@=?X_/ |~`=`evE4 :Gwfp:!IY? ܡs[n XyJ\z׀~ G\р^|aK92G:U5R ӏP.J~d͜r?]n"זέU׭EٸMY eŹ];@Ɵ'vރӰnmC.}CSdRB @d89;A8j%[}ʤ$N)D 7`a. ;ʑQBZ$u%J05|"EaAa6E頔Ԧ-nbן,ŭqpM%;N{Pc'?e]/w4 K2 ֹռuk1䍰DԮivQt&B.Ucyzׯ] 1uIke(uZ|U}0F{يhN4}XKېjZ6|gQ7M &e>{'-d0Tj+EA|;;qm{H[C"90K|)}ƫe_v+|"%[%OYh8 5L"$$#:JKy8J)X1hz}qS$D>nYxƨoZNԣ p+Zde V}ړ$5+Q*+/[bm./OET;J HSo Zl0˻h:tHۀVƗܑSZ6N&u#+ei +b&j` a{WRAg,mQle͒n%<9 (֗e0*!*^ӏCoٜ[4buy*x}eYkȬTG,.QL܀\6"7A < \|pHV "<Ae.\t.j/*ɸ,;r'`7n aGXvGc#ƍ8W&9iRh%̸PE]IXIdf{g0xyq; $m+_"uLK]5ShjjPяP#.84?r*яS|n I`6kX̆k~  R77IӬO 沓Q*gh*i dg`M%6`܉MƓ0}V"U!Yz&"d6e, iؚAI>I®8;ߥWd-lgTPѝ]+Ԉlݛ lʣ$1&EbCCOA+P.LiJ$m;ZѹYDYP|jX>6?sQVGks* K!k!1W/bQȭJk!FYB-])\n6O-dgĀMLd:}(@hGY4(:S/\dRlq6yQ,"uyyxBZtf~q /OH]Z̽8#rR1vOj=A2xKi\v/U?EoK' c8e^?HyNgKxt\(m?g=#t| pN?>80~z nrZ͋8Q⿍4 GpvF1k_(- |{(}a #yb6c/B/Λ˾S:‘x|"O9 ӯjps_?#% h4'.7D_O8P=Pk[^X%W!@p*+?#Rg#وTJX3x,)9@:;hbPfr4ʀ*zZ7c-yBm㷏21(a]?BEx&kʪBku ԊYS-(t55zz`?fi(qzؾkw#3Lcֶ0.^lMOv XW1ZnH;)GFyH*Uv%ϩ俹 b+".{R<`1!0HNg~ w6`> Ș7U=nE-gZ%KL~mR3O3<~Eϸ 3ܺ8E5Q_$'ׄYxDС/^ gsG!aBz&8fC2,}9mt""+Mi,vuKYFJ|raIj@J}eଃa!:l6fifEٯxTy(Rmo`Bt؟Bx ڝVhˀknlnީh8F?!d<<2w}Yˎ9%:R[!ԫ] tU`6$vLzcԦBs{5PRLOۇB砜"싈M 3>,9I2Z6^?n)膋TQ !/re:ͬX : 'Y4~&|,DlWGkr}Cԏ_S.), pL'pw@O E*dnw B״5TXl\MPk~V\gaj:Σ0y_/*+(YQ{bgفx- xބ̂.Vaβ{n8ze>5?%#ǫ91OQD@@)r^ z _aLr4~QfY}j,ϣHTf*V{5pdU\eX>e$꺓vHYUXLvdV;DmƧ~BX"Y!L֑[2..IK#q~j:Ȫ#ZY]snoyV+ˊּlJ{+(oal{O 'RQE\ ѧƾA݉@%|:wk2=1_-N15]c(eNgH!`hXaH9eqDPtX*CTegӟ9aA"RG4J:\DC;g'⑀p/<1|olR/! ?Pe>{PK! Fword/footer3.xmlUn0?=ĢG5rInCQa$HZj]J<|ܝ?Jf,W2AIR.7 hLP%Ytᬊ3g64MPҜĎ N*s#Pe,IczZZYZb4)SgGl‚N&q=`Y32n|Ij]toSRtW0j096ފ-杤&Bty&嗜ʐ b8{Œ)*D?iOC^"ᐳSR.{Y\ yӽ߇v-=Pg{ܚ}s _o2N*D :b/a<>.WǨ 2}Ó>b 7Ltv ߘ`Ȓ])A1M}6ya0MU"\ YF]^SǓ(k&w1,Q70o)LZv[*0"BP%Xi<{ 2ߔ^:M_L.ڷ-'lcbq<2fxzn0?ī;g!P0Df)ZZ` ^pˁ kqZPK!.sword/header1.xmlXr6}Lü%6rXMӱI LBb`HKz ivnL"_\[ m*&ALJe1omf,/RBLa?|/RͰ0L&2tL97۹L2jfwl&Y+vaRDSXqTT) ؚ)skwrKI{V&RqhDKbW{x_9U2u;Zd 6 [\ԐV*juk51jF(nS3R(ϼ(Q1 ?*"56k$9Eqt.S}ղliNFo@ܚ&/E$>J Q#] {U?zyz ` *Tӯ̊gLjc/VE*_n@e˜X=(Kh`@6莵L ‘AzX^^]BECoexm'r35?5"ŠsM Im2· =J*%&?b*f|xi`8qpK|mo2QC9<rْx.u!dbfTa I$NމVʄလ/aGK4k]ul>:?:c(FBw_(N|w߷/ߞN[4ޣGᠿ_/$:D?4S9sՊM}clJZW"ewA8Ok5<υ篿 ;^Tyib`IpjI@伨XFO/;n-u%7"x%ZQZPV^$ |VF0=@<Q13+Hڀj^oE{c\B+`iFw$C>% Cu:dUL%1'z9c,u+^L킅TI^ȢC%f)OSt*: ,?Xo\~_4`N%܂[kiV%NWX>'aoqDnEZ2 :Ƿqwg4kP~T/eb)D1)8 oXSSUztC"t@g+wK^JO^ѪPK!d@word/footer1.xmlU[o0~QC`28Ut; :G9pw"2\L JuUwXGUFV,!{f뗻:l\4!s&CLR;<muƩs֐W$j YT ԒNir$uv%ʌP7\pGhTNhSVPp 6sJ2@ ZْϢŲ}V>6GzZc+'po#kh{߈=3]G<Ġ#^sJ$j\i2/C{R/g(;f8y%52 n*'7dsu%(X^~krZ wtdY^0 Rd+I*6:Wi!;s~7p^Nn.xxQ61{|-0yE =D7> WE{Igd~-Jw_mW=Gz62WY[CS5,-#Gx!`؋WicBQGڴ_PK!YT word/header2.xmlWs8~4l~JJ i$殏a P%$0_@iK~Z}3aJs)FA D"S.O'ÀhCEJ3)(xb:px*Be1Endr[9OrnZr> kRNWd´P*6T.Gk.UNnIhT ϸypPQV"NjB;BP{8yNeΙ06b[ 8Hx>ƯͱCl+>Tp@2Rg.xϷ1 B~n̊INa~-5B1Eߟ\5 Zj,ɟ`l5 `t,i'BHEg0*AE',_wJʸl`62h)WDlΕ6"hnNdαU; B^}6 oAۖd)2Y7`8p,Ga4 /'¥2a8z'N|'tK]tLaѦ&UL!s-0Hs|Pr~[&' g ߲,IB-:'DCqc c.%Qz46+KJD>=bHEa Ǜ;g[Z)WJ @ZAWw ~QedE61 Xvf+܆,k6ɣ]S^9% EN0/ ݳ2-+~KD(uŒ4 ۛ[WXv]3Nt}y( {Q0=qx8u03+Aq4w-ط>rk~kwvFu&Q8>!m'D5UB8&?! k  7+m %5oɅ/wc+kU >O j RZg؛lt=(jP$KEq ߅6 #-$TD" ~v]e1CPK!@word/endnotes.xmlmO ߛoPӬ3E[>Ro/neQR~?.N!$2I)XarC"9dD)HGng:z颀F$:QHT+aa5Eqr|ZY Pfi!Ģ>ZW#Cȿ:b\F5ctiHWٿPGu >VSPfmK$ 2(㫨ydkQ NnGK’R2s&f=ٲ9.-eΫ4d .] i]:$B xU[/?S$tPK!Hword/footer2.xmlW]o0}y/CIYa@IۄFyۡZwaAWѧOs` ۞Hԃ9!U%EA:? /r]26[ΰr ci&z^⼋8D"<W9IҭIMX.$hE?nAàL>DgQ; :tK(831b1* `"yüyjҊut7ۭ{;:og9=կJeB=98`k?GKsUHoB)ՊI D8FDQ~v1dSH\ ANo\cM(\eg2VU{#)!hÙDci<\c<#G,qll@]}3댇bZͻ eL r"ZMe0nȭ>7_[}D"KA<ᠼʎ:SǦH}^"79s%/'{Ǽm޿fwJPK!׀Q@word/_rels/header1.xml.relsj1 DѽJ(9J^[u( z3Rv%tM XJx?l rQl$(ú|XѬJ=ʓYT g S)1뉼MUC1YJ*KhL obg$Y8bui}R*Y*d5c |-Ɠq sٞCMPK!word/_rels/header2.xml.relsAK1!ݝD^J'A&fXo ^<<{oj}8P.iA`[ 3\& 'ʰVoRbY\J|Az&r"qU*uLҟm7+ igzS49M8w 0uvS4o7E\6J.q:D, ۈˋ܋[(q1X="IGx-nuf}Ȥ8icvo8@M yRY娺#-ȉ')N.I!z$\uؚ.W.M m|,hc =Lz[,RmPC`$*aK[b7l,!Ffp!;ζΖBd2 Q&G|J:#퐾0׾W҇sa$MCR@qyڡRCuF|*N&ޒVk+U߷sx:8 jUN^WX-!amg .>A0 QNfT , ĔnU@ۚqvQ>ݺEWhSqA(SiP➉$XT #!1FS+7ݥtH;L)9RPauNt`Y gI8ih; pٿ СDAsm:{ԲdQ %x\٤C"Ml='Pl`{Lu 1 > ^'ЦIJr5=='91[F ~1ﱴb*~W{Zݑ/ck'o'fa܈{g1g)m(SN//3[il4?ޕ2ݸ#7n* s2TԵvRF4]Lr aV;"@|A m?Bħ빊k {\%] 3e4RԈ( &fIPHiyQGx5A59v".Y\ͩs.I[O3/=f- ?E-pDr 4 PjwPh l!wi>sݤm# ̰py0eL@E/*F ~-0&F❲Vw"|7p"uytѭ:Yfrclq ciQ5XŸf=͠_P2jUl*GݚpOM,+>#QG.dͥf|U}"esTܾ᫈s Qr,S<HڱL^NȠ.hd>=n$yT0.#R iVEso48#Wކi>5!28`?Ytd®XXP{vp'`,mCbn#l # +.!4AL x "36շIuw6=rlq #|WgNjz{zn(j;o%5#.1^tiW^{ ŭ <`X,RsP>Ompz)'8%=C ~!&pyV(fv̡rVAY((;F=2' %- Aa7[kpk˯>/-o"'F,E}Yt zh Iiڄ%d=>G~!<:Y\q,x2Cǡ ov G)0}o 1f?_u@JĆ2; muqsTCqu&wD/y@cV @saJ8gh1'zxU=OGX!B*PdwQ8Q׬%5Fb|1 H*4SD{;!=Ġ B_SjknP}EQKKYK|qc8y6 %! FC-o%koU|I:0r2jIE 90\5ʛ1s1h0B> cIDin&Lۇ(-v pP2'ƴYazGjь4@|B⪓'yD`ì1<Ŏ8ouF0 Q*NJAoa_]#"Tv/eVڏ?&5k_1K~ĴsmNVː&K ;@Oo\nJ ~@O[\U thc:Wx<◧o;''TH2?ʦu5 kG얗mўP,lnT N"Sp{ 9Ӵs!PK !3tjjword/media/image11.pngPNG  IHDRIsRGBgAMA a pHYsodjPIDATx^UյQQQA`F_/K'//1B0~g̽1FEŮ (ذ!Hg瞙Aط9gko hfZ'bEѶ:ZritGVx<[׬5̧%M7%2rf-|3VRˆsRTYRi/ʪ6LCs{oduNm_em+`btִ#/Bd#3J>uhyu.yrt^op[cnZ#e?|FK iuolEt޵wr(/bsh9Mi_#o>~ !uJU֢Uk{߱ښZ d; '`]6l;oAnFnE䟌[p>u,mz]Rf9Xi۔PuAqe0V9frzu /&[ux+m79WnY3%a9Cqy*’ʈ!ǝ=WPOtn@F5G4KYC4KP-}>yZV6T+:rcoFB$樈d<“[p>5%2~ng[~QzeŞq_|Ī~i9GXa7a~dӬ8밵?ǝ>ˋf'm1GZƄ#($0xpy-t芬/ӹwaFZ=| J6<]ߑhs/ȷk֦$myko{u@9;jc2fUx!VxVwU Inuc 0f_rε,?P+Ib9 .i-~aH>@+yV7pVw5mU'fV2@ˋA;̲0LW?|:k^&74.Ov]޶uo{=P'l䋫n3 -p=vG.-8q]|Q:v9q[ݤ&~CƄx$cu {1U)OC!X( e,{\Ymf/feqì2q?M?IrZU ׄk|nUpھ\-2E [y-q0;,{?W "grh_)?O;PTYuUZݥĞ47mӟ.,? ăcr|(ݕq#co8>U1{%U$63˞$"BkOkV̼*Y aO,jg+NbR6[kΪo5[}VUM' 2M߂2IC-ca5^;V'+s!ee]=^jݯ^ix;5c-ߴ[9kզmA,{#cMwYx۵q^^?e5(V(|XUq\څ?OQUgXKaQ;1ec?&m؝߫BrʻN[ߨcPf5qXͤ:aAwqCwiY[(4{0=_އ :rUWI#-.2DUVEIeI{3\0 T+?ڪ[MV<;hODwRg2\d|v˕=P=1%wM)<Ú>{k<*2~iiÐC-3}>N a{[ GEndٔzo= [8Eݻ~;8EJDaSvqj5XmV,sܾV}uC-]bB[m[_۲^Q&+Ey#[0IDK8w8?~UaO&bvEvqCw'J0~_X K)>y}/mPw,,/m822c-gӧbMҔ}kHQ`{_eN((n +hxPneJ}+16 0io˝ò&;͵DmZ퍺ueɘ-͍lV!YªVcˏVU4S .$LK~~[T ۗВ'KQW}oܴN&D.(B{(Hi2+˥|J6 r=T^c:DZ(Wz.VE',+0NLMWreҺ HZnjF.(A&a*eWۣBAw} a' l:DfgQ,^9:빮lVe Y_cMG8XGYy@+a㡛Uִ*l ZN8c,l+N;р],8 +I fG+`n7)Oeo=v)PTUe<{dBeJ)X>5%N:]SQc(cpwZP"wRFTʸSL7n~5(3K?6cy܁V_3~)秎@pb \3X +~]~;>aՍ=otk5 '.amw=-ƭN8Њ'Bf魜YUg]ZƲ]6P8M3+R-Cd!A֐2c]BH)I(mqv**FWRεGm&dlcݪPE*Li oS~jDQ߱_Z!JZ:, چEm^l ^fc[ֹʗçc!'(jP$"ܨZ'5(mńT\!CCֶhcWWPMAX钏YQq,cAo~>U(Fr⁞ 돽b=E^["Xd`CqΧZW2&Eu_箘q&):*2 SFBMDQ[4n^8Ui"27Dʑcw+i;*%|C1jsq\[YKcw"Q݁ V.](*VC^@Sg"k*lD+ "UAj"r #XՄj<v+AWqcgd>28囨1"ф"kX=DzņA\m ߢOr[ G< +Icv?OC~<׏I5dae*#Xi L-ܼ=u{w20] 6v:fg]rv]?ڙꎑBhRsq SnR\d=Q"뼦nxU/YSW\{ʌEMTq!V;[ɣ\"0NP+K>~Gm|{J١ v i21=$%/[KvQ֩:qgB%;Fd'{/H\0e%0 LߞQVA>X.4VL[ڿ,zeL|I!V2qA p!iVѤbV쨃~.D[TϚJQ_`8բ2@AĸA9+DP@kZkx 4+W]|\VmRʸyBVơ֐,~479nh{v/B1fZE0  4.[VDD?G}2:ш5;ЄG/m;!(&'KLp %[Tkl-+=g%YF )T,j3Ս3i6`iY,p M$-J)`<{ +xfQ qVvBr)bܼG6lGrQ1Y9"tIҹ[},~^{XʹX)%ow9su~ك!-N<j)g3Bp󦣔Zy奞D'\ع\h*VÍ+K?R& H?; d"ژz@zxή}֮pşnG+}DQPѲːÙSmG[gْwesٲؒ9wM/޿׾`\ޣ'IsE_Ob;O#σŖ|͖͘a+gL3_f|V|VzVxa&5dS޴_ZA)@0=\儩ǯoϸkw-^[Ǹ|d[-OkJȮş\F3 ki'C*flvU 2]yN&b4@.\ЦԪvc=ꅘW+&pc/98|5BVU|f5\WJVtCVwU2vEF|GV,盛{/g1\d`9;FvO #FZ>_Q垶Rլb=,ji,xf Yh`h[ָu[9%[9[oL>[fdYՂNJ9|*/|hZ I\T.>v a-i1ZdMIV)VG_1u~*sA SOSP 32PC}j*EQ,Go+ TP@JXBCwFcY_+mc KwF(`|Z,=g'?{Yf8׶3K_nK%ΜPU;qiBYˆқ*Ž/#@/{7_s"l&o뚬HrIԜ2L16;O㷖6v1̗m.8eu&='|L\mB"IQ)KJT q,@]|HӿO}z%v]O,{M6Jd/D ]_߹[NQeMxSڿ*cQT󻥨΢BibY!{T3v?4`楰}lWRRLlXZj6+N~7UR\\;.+y)IఌVe\qSؔ]@v([SYG>ƠN}telCbOl|E:WTQHQ+q7U!*-RTb(kfQZ*N:aI[ V5nK(Ƴ Y8EQ4 b YQخܲ/5Q+WU(AՃ*zW@R\E0weK G.΂揦^-E㈓""ZT2u(YE%9dn:ʺp7SEЕʐAUʱvϩb7rڣwø7+Vp,+BM5-MTu"*lWҾ++?Tk|'կ)W,)'шJ `M`u Nr2]Rr"Xfؕ gYAO(4Z`gq!F˾@'uqc76> TW: Z jI|Yܵedy#TNt|4qc M OmS¯qQѿbxV=}G6S |nCN=t0u9+?l{ ,k4 8(ZSnmͯ2?~SQg5m'PP_H&EDJB$`FӧraK qV2!k{a%썩kەp\ *we3%_KQ{.ZKFЭ( Wz<.]4I2s#;un/-E{8on)}x%as!ma<؊iku[uwE&V)Q+NQBiQ]{g^=`~ P{]+$lCO+&r~_u]ޟˢ|QBqRmSTYT^y>z@\iJ!]*:TzY#>v라_ZR="dZG$|pd;nfs#EPîq#,kC,T&cn~z%NP")N^4+Q)*iIDɇ~cF!ҤZ'%o,:U3'.Z!S}uQR&׺ @p}U͜rQ9܈M PSBl!RDaRJjjB$%URxdocTF9N_Gw(FC+nK:82Lݹ[(@'5(*FW ]+ǕSuwEXs\(ZE{`O0gSz=c^_kJPحyOZXLk~=ʶ9u% V^u!aUlT/TM f ;u GK87 v ܳ6ۚfo1f -ԷK/JFNΏ[ -:pR-NuF j!]žgaHA+@EUı=:1 BYKԿW|v/X#I9Qm2Ҿv}= #U>cXYjV մUp C`,X'<%:'yb,p=SJ ك/K4hmFZ M{>{nζ1C (\ wq'voԠh}n>OUVJXTXq<;( <`NQ (L ~[v-E p~x0ϣ'6C}{٢o߽Pb΃|lgӷ`VՅ)eڣߗ!]nجM<Qֹ5W?eZJQb iO5љѨHG \Er}9zE)|v7ہ_B9 %7=*VzQGAM,[C k ^ 'hlo8TQGg`;([s3K#kMK9VpS_dt, TJe~8N=Eݕ!\wA KOoTP:^QDŽH%>w\3u6Ͳώ8@C{@=Υ_TkVXKN`ՙl֋7wE3ocqoCnOfbϾޛ}%{IV,}f#MV.~V̛ kMk;QwBǢhVJ4Ҙş} t;L#-Q+jENЦIo E2 P5NHmWUQ!l.:1ŹFޱ/xV|e/xň(=K^׼-_-ceXi?xtae;0pz{lޜ[lܩ6[0jQϢ2z vm5{%4'~L0n HJNA~h'Z!䂌gJ~ƢZEiu{)8{)cV[ҢYM!M;vI0Ӟ}} {)]=t3#PB פZ]]K%.$W$/K8| Цe<=_uXL)/rIC OʒSl95PooYm!m Ewq:oSO*8𓋋.BR$zssQZ17Ve[sBF\:iI;QQ,f=sຕr4wb[o޺_HtN)؊nbbD!|mTW5ȍ>ÁߝlJq7yGTg}<~lMIGY #0UaWK *UA<]!P-c5J÷pL,*G-~9_Q4))SOQ)lI& g%7ͱS*V:kڻ`#l 1WUS:X=dɬrS&dC[7ɣ[<6P;*Z67P\|Y:F(#8դ(q"ҹv"*"='"}R V8oH^W@EGtECia$nM~-g,+MEun΢zZw%5;瞛1V}%5n$ i͘pS1,6O#MVHsD U`s*^#g.QGjj)Io U4 /zldQE7)UC(%u #~D0MH:÷["b`َ!Ǘ* ](*X2&u, Z*cwdv&u!i4|+V}.\U17@9^ JlJ0G͋}MˉJD/>FHcDe)GOʢh'mx(%s>47ůu.4XQb8z Iᓊ')s8"8Ę]-Ҭ-\]#:2aY)u(jwU873ГXXMʰPXZihHgA`q8aj鲪lj"=U0nA6Sn4Q_olT+E呅 āW%s#HP=G=8kHVYHݕ,~ c },_3~(꼙m4:h8  조|Ǎgo3z]-z7u Wmt쌲%1{Y |1 ׅF:6̀RW!EKRu+Q3]H>YEt3{UhcZEB ;:b`6l0 7u9 A犰]Q7B1h(U" K-aW QI kBh)*TjVYT.fsV҂ B[ܮ.#~u롨}+!kUAkLi5\J-O9-* I2VTm=E S q.~*sOB"ס0ҿE-$O.E-Mj׆踱#zQ9~ERThEb.ȆWV)j|,#TvELE XK;bOr>jg-s̖n闢G%?AZ>-qY_XA;E=6DmWԭEQ6SQˈRWJԴ+Aţf^KElJ_sT Ze `SlQ%_[ n ߆SUts8Ue ؇SnHXkU ȆOk*+A3OxZdvQ7>eV̶/f> ҟ^ω~Ϯ̔vB.RY/o ??Q^_!b+h҈RXgQTqܠ?N!gMN0UmJxroԤXԜaW|{fjhA) ƗʹK+-rBKДSTZ:A~kDQ  _ 69gٲwIwm/?vrOm#whJ=8v~jϕG`~>`u*FG8QGWq]5ӈCZӶ|ŃK_էp(/R"m*_WIQg#"ZJxM ?yoM#L50m\Oї.ܪg6З`L ,eļI.%[]xPZTicRt5 <4@b5d';.Å| |aZҤuX:6'*1B-.2jr &nWMBeG)K8?)v6EQ+ȤyjvөZ&c?*}!a '\eאq%2-G >'Ucu̡7*+$j /"c%)ayO"pΧjˇNғ RUB +)0ϔD=!#Ba (~++HNx:*)?.2[$9rFS !-XD(j8Ɣ~D;K'xh'"!3GIF1l\m'5X4<{ J?Uf9dUyޣ!jj(U EOW<[ "@V#qyQ◽ p@X(J [Q=m %JL$ ORY*!S7ownWN??k:Aĸ^o7FAXQx.JU"ZymНB\bnB蕊nBy #~qTPTg5B_x-a+L=#2=9|9 *i}F'z#]^),ˁ!GGrL|ܞe R*R4Ye_G!@UR_Im YE_Z n>Tzk gQ'V.r5p 'Mԥl|L&+y%бGDWTϾbf;Y:f}wYujDpV* Kl8 [yHxii10*مHM| L~m;lIH$%DOs_? 1ь8'6v)'C{{IޮI_G.Jl~#JC<^SK #/P8"z. Hإ`)mˈVDdgsӊ"s[,O`N6YrP=^'v+80±;M`ǥ33gl;7;f]JZʼṡ1f?I!J[\21o} )x4sCVQÉ6iSRTV{ȗ2 -@x;"hIa\WC4VDZ˱"xCzMqrXr}޿Y1޵nγI'S8K*T`*.'h5oTez͟Gֿ*ZJ*W7\cd(bhW%EU@cdZZbrNt쁏seT&ɇtAy4mFҠ )6"ʠHwփ.T ).MSj޾v  ?u=*mqs!9o=uG2[ODQ]7UZ휢 ˅yH)veG}5/UxmxDA=`ys:=U걒woTTҧ*%6-M ohRF_*sEf>Qѥ$V 6eP}빮|sW6Q*r`MYaBIQLD ,p 4Uot-nsͲO캊YTnk,S0iZjtlg|ՊuAҍ_ǒnW~HEʿSS"Э8g\6w` 05_[J]y9/O]K:VTo%.R܀񻰛ߋ`#cz'9++DVuO?r׺.w+J!tSp[vxWRwjhutY^^Nj"!|ʛ7GSiYTw.+B(=cJ|17s7hu@ɱ)i8Zhݢ"GEU0{ nvñmU'zî ;E+k "cG +jWլcrfBQUHF \}ƙtj{nζI!{.RV)lHY7o>gT˥F /"MyM$ឰ[/@TAՃ2"e$΢*~E<"bS%H4 ɲ~)Oē*> RW+ӆjJQ7fMT<*nZ~v.,o5DPP8rEE{"8,Վ.%=ɺ+ڼarJQTϺKQVx :?>|A@m'B;0tG|Rrqcʺqs(2JOQ>L˗'R 7%>(iɨ~ ٴyWjTE )S kQL>pG6_Qo*,F4zi2T8'瓍5:מ?1f7ۗuRZğ|Ilh;a7d^)sB)d<_QPWzTFW;fZfe;'fsɋHҡǕiyH?z%O#Iۮ|jX5FBv.3[Qi W,+\&j"Q9x* "pYmԜ& *VhOoYzNQ]L b Qu:vNѯ#(IvEbkP.E,9{&%w_`EWT]lK[X(RZPZvmqEr@]q"$?PuPz* 0hukPT8瘧~S.\k54-#E-Z}zR?/]O~a܀@U:vH4ߝwTw|T?,*Ǫ~ih:2%P)~k~sOJ ͠kvSofhsMl^R^?)PNQGGͅӴkHO:w5R4g'P2,vQu؀Q#A~c)j=x ۋ"lbXV¦O^+V`Q}<ϲ&Ra8EeC"S 2єJ`qe^9.+9CҭKU8N:z=BmcIJRk}.6)bFo]TG-eSoɶ4Ċ M('7łn~6EHj`~Z$lb訠zjt^]ı{}>M=Q(Ǩ^e۝, ca?x*9WMq IX-&BݯPS"?RZn=N؞˿Ұe鼎]K{1Yvk?>_Q'ے7v=ͺR' l' 3^e!<|SGn76V>?jMϏ7E~C썧9^TqP YWZްH%淵B-ٙJTII໖:!!7:6G_/!YM' i烒t]wBʟ Kxd2t:o]o_Fԍ~Hنz74}]j0u,'QH&NBW.Դ]}]~R$$z?R}jYn0os~JvU`VMƕ8U('r0vw|j# oEB|} k[lgy= nT7m ,笣YVlNa LS5>u i/~*Ҕ5D)qϕ_~ $ uMT%!JLaYPoY.KsN#6v'أחz([o-?pf[2~M&cקr9a;VH7hΫ⯭YOup5kZ&Ll [\JPTVѧt.s\m wμ( ruk ?%sa@ҸhIQeڕ`)Rzw4{ȗBҧEEJLqyTcflzepKCABBCB`0WcU pWTgOH (ҘѮ\O.}/r&zt[}CI1,0uk]FQK!ĖAH):]]QURXL<}S_8ըwC;?p&8 EaQac^A O]JRaQ:v DM>'osJ1OyE0ǖ:"PXn> xe8J},`%Ɇ*r8%8'q'Lm+VA bٔ'=ˡ lx*%)SBc!J+v[@ uį2Jkswa!$?B=&3&VeBP'_b_}0 $&n$P$ï2O,-$/z;OO q@f?p5fߤ))j M4W-k3^fu}2[Y7G3_corUW۫\a/=~xؔM_}=Tګ>N*:zF^x솿gؔ8k(oWOɱ7Q:Z#lk^WnV֓QXvoF\Ϛz$ N]h8XmQZ@L )O 7+ 4镧 v,4EGMʹ,*mmZ cv͹vek > /:M.>!xr{=O=?ڦ?2^{aCCuN?^"{Kl thK|䣗iOޟ~zN[AUHKQlsZ"RYJ& B6XñiFxo ,Z26OXlcB|# 27JZ /rGxиXǥj6l wWo'o=l M*A͍mRh5 dh1Ɖ6qWB׹cpLϑqC]Dg']m52pn-VF&ofBVlrJtO3SbulfxF[ēʏ6X}M'WpdC7cPkgc(U߄RCʊpMG|}>jҷm 3xe5!H;M!kF7 ׼T])S85&L7,ڞ~Mװyl\!k|]W1l@66ҥuEʩզ; ]s:=gMv |ԅ鲱pH& *O:#qٕ!|T!*8*GOdJCSmrFeJW#vxBէ[C)y|5rRzէv5DtX;;hG{5Uz08Ls{S箿EHkA@.b"vB^gU+%qx׍Mwj3!!OFd`(bܑ07g5u~/N|* ),cԖGz8AYv{hvO&Gr~m_w NupoHuCM*Yb %QZGS`m%+ q,;V.ɚO'p8fzs3M;P* `׹}Ezee0.Su}c|QiwWf\w8&ڟ2FtUn"IREz(rmj.~0zH[ZD{K2,`7 UDW%[Ӓ:,(p_eEYkPR Ez;/.#(ؚ;VK ڬdRu1>*VX¹ {5M(j"< `6)WʺdR# ʣ5/|-ǥ~Gw6|sұWATUcrt퇰>5z(KLE;VB Q@e.ˤZ?kjT\6rE!om(R=  sNJ'~Q0Y tfƪ,(dtb*2KPRAnulODjh2\:Mߒp,am[twK)>}ΉE%r-7uk]7_tx]s. Bg:HU5kxzJ8(>:@.?U' Z_uNʵSE R=; dWح5FGh{nG=}]o*Aɯoa,F:L%.o[@5Ӛ$@eGB~2K2 ÔQk_%XJBc޹{>EoyEUM7k#t @%^& }*zS`'`{-'3nG`i6EFTm<ߣGI *>GKbKrT\^Qr]ea]HcG%Ju&&~]^_J"s<))8EJJ[`)aRTemV.HB~"nuK=t\].b~;{bBJ.Bf&eW_D-sm3:*ҦFwJ{6Ҫu1Z( Z个ަf_Y,^ w8J>gkS5YpJI@<*-|7ףw_&ΜOl4 i>YH5ݤUNugނ)~YƲËFy. p}iq+W@e1-'Dˍ*Wѕ(w)kJԷIۂF)iȇII١j ڱi~dm ^>w~2S _4TE{ %._iTYSR !$D$"d` rueEy?\ =ЍIvWu)S6UU*Dv_ Z~. AJF`d2{ZzpzíUWܷF ^{(E]hI9øGrO\HWRTݥly2WTUuJJO2~Q;d "2vp~k՜c >x"jbE۵_nY6[n)ہF[ql?'Ks`azXJm"I}rP-8'>wܖ'THJcӮߗu% MSQgFZ=[lUI˼OF޲% $)er뫒#/p˦q[E-,KAmyFK+‡tnҌmU$@Y!]ݿVfUV[h'EjZxma'B/+r$E=HgK(?6|QxJ][G>gIcd));XP)*L>Na@VA;:Ir3UVF-Ԥ,~WFp+;YJ~(h״4;KT&~)j#J* {Q]hd^xBǸny?--sUl*SPEpUL> z˔ʵ>QMє?aWL$(+ h=ZTBiu2 "b9Isqy0MBH(S S[/I#=i/cZ{ `$͓gI;mlzZEꂮ|SY u[؇ X,m`K/XLN s LWȗBwB%$}Pp5j_Hŋ6,GU s_F,u d>0Ksqe(aU%*Tswq?;SEܰ/߷kn$/gTG4. 8-^ n_B@Wh( je♼HYA ˶`Q zEDBh3}?Z~&.+^t4~^ ; ݒ}cǦylGT;סOVՉ5cTGKȆkB/ىmJ+uo^T(op#&CtUcSp}V*~M;.t涆ISN]",wP֬7ݩ?kc\Lp!ETFz'Unf&ڦJ_|M4ߊ0(rx2dqe Ti]%C"rzhn/knoA@Ka~+ܕR4dVXChEkfdrکXmlZ2am`Tײ ØhjTAʯ\6XջJҶT67iToժ5xh":x@u 6"^JBs{xUn-yKZu<_<vsŸHĮpzp\Wdƛ|=Nt> 5V"RT= M$]_حG\БpX{(4a#҈Z8~hvKZhZQ:=nػE']wM[metFGduw6@W%SyLu؂cǶ}p<`SmDO%)VV^U(\CQ/4@%B~ǞIENDB`PK !3tjjword/media/image12.pngPNG  IHDRIsRGBgAMA a pHYsodjPIDATx^UյQQQA`F_/K'//1B0~g̽1FEŮ (ذ!Hg瞙Aط9gko hfZ'bEѶ:ZritGVx<[׬5̧%M7%2rf-|3VRˆsRTYRi/ʪ6LCs{oduNm_em+`btִ#/Bd#3J>uhyu.yrt^op[cnZ#e?|FK iuolEt޵wr(/bsh9Mi_#o>~ !uJU֢Uk{߱ښZ d; '`]6l;oAnFnE䟌[p>u,mz]Rf9Xi۔PuAqe0V9frzu /&[ux+m79WnY3%a9Cqy*’ʈ!ǝ=WPOtn@F5G4KYC4KP-}>yZV6T+:rcoFB$樈d<“[p>5%2~ng[~QzeŞq_|Ī~i9GXa7a~dӬ8밵?ǝ>ˋf'm1GZƄ#($0xpy-t芬/ӹwaFZ=| J6<]ߑhs/ȷk֦$myko{u@9;jc2fUx!VxVwU Inuc 0f_rε,?P+Ib9 .i-~aH>@+yV7pVw5mU'fV2@ˋA;̲0LW?|:k^&74.Ov]޶uo{=P'l䋫n3 -p=vG.-8q]|Q:v9q[ݤ&~CƄx$cu {1U)OC!X( e,{\Ymf/feqì2q?M?IrZU ׄk|nUpھ\-2E [y-q0;,{?W "grh_)?O;PTYuUZݥĞ47mӟ.,? ăcr|(ݕq#co8>U1{%U$63˞$"BkOkV̼*Y aO,jg+NbR6[kΪo5[}VUM' 2M߂2IC-ca5^;V'+s!ee]=^jݯ^ix;5c-ߴ[9kզmA,{#cMwYx۵q^^?e5(V(|XUq\څ?OQUgXKaQ;1ec?&m؝߫BrʻN[ߨcPf5qXͤ:aAwqCwiY[(4{0=_އ :rUWI#-.2DUVEIeI{3\0 T+?ڪ[MV<;hODwRg2\d|v˕=P=1%wM)<Ú>{k<*2~iiÐC-3}>N a{[ GEndٔzo= [8Eݻ~;8EJDaSvqj5XmV,sܾV}uC-]bB[m[_۲^Q&+Ey#[0IDK8w8?~UaO&bvEvqCw'J0~_X K)>y}/mPw,,/m822c-gӧbMҔ}kHQ`{_eN((n +hxPneJ}+16 0io˝ò&;͵DmZ퍺ueɘ-͍lV!YªVcˏVU4S .$LK~~[T ۗВ'KQW}oܴN&D.(B{(Hi2+˥|J6 r=T^c:DZ(Wz.VE',+0NLMWreҺ HZnjF.(A&a*eWۣBAw} a' l:DfgQ,^9:빮lVe Y_cMG8XGYy@+a㡛Uִ*l ZN8c,l+N;р],8 +I fG+`n7)Oeo=v)PTUe<{dBeJ)X>5%N:]SQc(cpwZP"wRFTʸSL7n~5(3K?6cy܁V_3~)秎@pb \3X +~]~;>aՍ=otk5 '.amw=-ƭN8Њ'Bf魜YUg]ZƲ]6P8M3+R-Cd!A֐2c]BH)I(mqv**FWRεGm&dlcݪPE*Li oS~jDQ߱_Z!JZ:, چEm^l ^fc[ֹʗçc!'(jP$"ܨZ'5(mńT\!CCֶhcWWPMAX钏YQq,cAo~>U(Fr⁞ 돽b=E^["Xd`CqΧZW2&Eu_箘q&):*2 SFBMDQ[4n^8Ui"27Dʑcw+i;*%|C1jsq\[YKcw"Q݁ V.](*VC^@Sg"k*lD+ "UAj"r #XՄj<v+AWqcgd>28囨1"ф"kX=DzņA\m ߢOr[ G< +Icv?OC~<׏I5dae*#Xi L-ܼ=u{w20] 6v:fg]rv]?ڙꎑBhRsq SnR\d=Q"뼦nxU/YSW\{ʌEMTq!V;[ɣ\"0NP+K>~Gm|{J١ v i21=$%/[KvQ֩:qgB%;Fd'{/H\0e%0 LߞQVA>X.4VL[ڿ,zeL|I!V2qA p!iVѤbV쨃~.D[TϚJQ_`8բ2@AĸA9+DP@kZkx 4+W]|\VmRʸyBVơ֐,~479nh{v/B1fZE0  4.[VDD?G}2:ш5;ЄG/m;!(&'KLp %[Tkl-+=g%YF )T,j3Ս3i6`iY,p M$-J)`<{ +xfQ qVvBr)bܼG6lGrQ1Y9"tIҹ[},~^{XʹX)%ow9su~ك!-N<j)g3Bp󦣔Zy奞D'\ع\h*VÍ+K?R& H?; d"ژz@zxή}֮pşnG+}DQPѲːÙSmG[gْwesٲؒ9wM/޿׾`\ޣ'IsE_Ob;O#σŖ|͖͘a+gL3_f|V|VzVxa&5dS޴_ZA)@0=\儩ǯoϸkw-^[Ǹ|d[-OkJȮş\F3 ki'C*flvU 2]yN&b4@.\ЦԪvc=ꅘW+&pc/98|5BVU|f5\WJVtCVwU2vEF|GV,盛{/g1\d`9;FvO #FZ>_Q垶Rլb=,ji,xf Yh`h[ָu[9%[9[oL>[fdYՂNJ9|*/|hZ I\T.>v a-i1ZdMIV)VG_1u~*sA SOSP 32PC}j*EQ,Go+ TP@JXBCwFcY_+mc KwF(`|Z,=g'?{Yf8׶3K_nK%ΜPU;qiBYˆқ*Ž/#@/{7_s"l&o뚬HrIԜ2L16;O㷖6v1̗m.8eu&='|L\mB"IQ)KJT q,@]|HӿO}z%v]O,{M6Jd/D ]_߹[NQeMxSڿ*cQT󻥨΢BibY!{T3v?4`楰}lWRRLlXZj6+N~7UR\\;.+y)IఌVe\qSؔ]@v([SYG>ƠN}telCbOl|E:WTQHQ+q7U!*-RTb(kfQZ*N:aI[ V5nK(Ƴ Y8EQ4 b YQخܲ/5Q+WU(AՃ*zW@R\E0weK G.΂揦^-E㈓""ZT2u(YE%9dn:ʺp7SEЕʐAUʱvϩb7rڣwø7+Vp,+BM5-MTu"*lWҾ++?Tk|'կ)W,)'шJ `M`u Nr2]Rr"Xfؕ gYAO(4Z`gq!F˾@'uqc76> TW: Z jI|Yܵedy#TNt|4qc M OmS¯qQѿbxV=}G6S |nCN=t0u9+?l{ ,k4 8(ZSnmͯ2?~SQg5m'PP_H&EDJB$`FӧraK qV2!k{a%썩kەp\ *we3%_KQ{.ZKFЭ( Wz<.]4I2s#;un/-E{8on)}x%as!ma<؊iku[uwE&V)Q+NQBiQ]{g^=`~ P{]+$lCO+&r~_u]ޟˢ|QBqRmSTYT^y>z@\iJ!]*:TzY#>v라_ZR="dZG$|pd;nfs#EPîq#,kC,T&cn~z%NP")N^4+Q)*iIDɇ~cF!ҤZ'%o,:U3'.Z!S}uQR&׺ @p}U͜rQ9܈M PSBl!RDaRJjjB$%URxdocTF9N_Gw(FC+nK:82Lݹ[(@'5(*FW ]+ǕSuwEXs\(ZE{`O0gSz=c^_kJPحyOZXLk~=ʶ9u% V^u!aUlT/TM f ;u GK87 v ܳ6ۚfo1f -ԷK/JFNΏ[ -:pR-NuF j!]žgaHA+@EUı=:1 BYKԿW|v/X#I9Qm2Ҿv}= #U>cXYjV մUp C`,X'<%:'yb,p=SJ ك/K4hmFZ M{>{nζ1C (\ wq'voԠh}n>OUVJXTXq<;( <`NQ (L ~[v-E p~x0ϣ'6C}{٢o߽Pb΃|lgӷ`VՅ)eڣߗ!]nجM<Qֹ5W?eZJQb iO5љѨHG \Er}9zE)|v7ہ_B9 %7=*VzQGAM,[C k ^ 'hlo8TQGg`;([s3K#kMK9VpS_dt, TJe~8N=Eݕ!\wA KOoTP:^QDŽH%>w\3u6Ͳώ8@C{@=Υ_TkVXKN`ՙl֋7wE3ocqoCnOfbϾޛ}%{IV,}f#MV.~V̛ kMk;QwBǢhVJ4Ҙş} t;L#-Q+jENЦIo E2 P5NHmWUQ!l.:1ŹFޱ/xV|e/xň(=K^׼-_-ceXi?xtae;0pz{lޜ[lܩ6[0jQϢ2z vm5{%4'~L0n HJNA~h'Z!䂌gJ~ƢZEiu{)8{)cV[ҢYM!M;vI0Ӟ}} {)]=t3#PB פZ]]K%.$W$/K8| Цe<=_uXL)/rIC OʒSl95PooYm!m Ewq:oSO*8𓋋.BR$zssQZ17Ve[sBF\:iI;QQ,f=sຕr4wb[o޺_HtN)؊nbbD!|mTW5ȍ>ÁߝlJq7yGTg}<~lMIGY #0UaWK *UA<]!P-c5J÷pL,*G-~9_Q4))SOQ)lI& g%7ͱS*V:kڻ`#l 1WUS:X=dɬrS&dC[7ɣ[<6P;*Z67P\|Y:F(#8դ(q"ҹv"*"='"}R V8oH^W@EGtECia$nM~-g,+MEun΢zZw%5;瞛1V}%5n$ i͘pS1,6O#MVHsD U`s*^#g.QGjj)Io U4 /zldQE7)UC(%u #~D0MH:÷["b`َ!Ǘ* ](*X2&u, Z*cwdv&u!i4|+V}.\U17@9^ JlJ0G͋}MˉJD/>FHcDe)GOʢh'mx(%s>47ůu.4XQb8z Iᓊ')s8"8Ę]-Ҭ-\]#:2aY)u(jwU873ГXXMʰPXZihHgA`q8aj鲪lj"=U0nA6Sn4Q_olT+E呅 āW%s#HP=G=8kHVYHݕ,~ c },_3~(꼙m4:h8  조|Ǎgo3z]-z7u Wmt쌲%1{Y |1 ׅF:6̀RW!EKRu+Q3]H>YEt3{UhcZEB ;:b`6l0 7u9 A犰]Q7B1h(U" K-aW QI kBh)*TjVYT.fsV҂ B[ܮ.#~u롨}+!kUAkLi5\J-O9-* I2VTm=E S q.~*sOB"ס0ҿE-$O.E-Mj׆踱#zQ9~ERThEb.ȆWV)j|,#TvELE XK;bOr>jg-s̖n闢G%?AZ>-qY_XA;E=6DmWԭEQ6SQˈRWJԴ+Aţf^KElJ_sT Ze `SlQ%_[ n ߆SUts8Ue ؇SnHXkU ȆOk*+A3OxZdvQ7>eV̶/f> ҟ^ω~Ϯ̔vB.RY/o ??Q^_!b+h҈RXgQTqܠ?N!gMN0UmJxroԤXԜaW|{fjhA) ƗʹK+-rBKДSTZ:A~kDQ  _ 69gٲwIwm/?vrOm#whJ=8v~jϕG`~>`u*FG8QGWq]5ӈCZӶ|ŃK_էp(/R"m*_WIQg#"ZJxM ?yoM#L50m\Oї.ܪg6З`L ,eļI.%[]xPZTicRt5 <4@b5d';.Å| |aZҤuX:6'*1B-.2jr &nWMBeG)K8?)v6EQ+ȤyjvөZ&c?*}!a '\eאq%2-G >'Ucu̡7*+$j /"c%)ayO"pΧjˇNғ RUB +)0ϔD=!#Ba (~++HNx:*)?.2[$9rFS !-XD(j8Ɣ~D;K'xh'"!3GIF1l\m'5X4<{ J?Uf9dUyޣ!jj(U EOW<[ "@V#qyQ◽ p@X(J [Q=m %JL$ ORY*!S7ownWN??k:Aĸ^o7FAXQx.JU"ZymНB\bnB蕊nBy #~qTPTg5B_x-a+L=#2=9|9 *i}F'z#]^),ˁ!GGrL|ܞe R*R4Ye_G!@UR_Im YE_Z n>Tzk gQ'V.r5p 'Mԥl|L&+y%бGDWTϾbf;Y:f}wYujDpV* Kl8 [yHxii10*مHM| L~m;lIH$%DOs_? 1ь8'6v)'C{{IޮI_G.Jl~#JC<^SK #/P8"z. Hإ`)mˈVDdgsӊ"s[,O`N6YrP=^'v+80±;M`ǥ33gl;7;f]JZʼṡ1f?I!J[\21o} )x4sCVQÉ6iSRTV{ȗ2 -@x;"hIa\WC4VDZ˱"xCzMqrXr}޿Y1޵nγI'S8K*T`*.'h5oTez͟Gֿ*ZJ*W7\cd(bhW%EU@cdZZbrNt쁏seT&ɇtAy4mFҠ )6"ʠHwփ.T ).MSj޾v  ?u=*mqs!9o=uG2[ODQ]7UZ휢 ˅yH)veG}5/UxmxDA=`ys:=U걒woTTҧ*%6-M ohRF_*sEf>Qѥ$V 6eP}빮|sW6Q*r`MYaBIQLD ,p 4Uot-nsͲO캊YTnk,S0iZjtlg|ՊuAҍ_ǒnW~HEʿSS"Э8g\6w` 05_[J]y9/O]K:VTo%.R܀񻰛ߋ`#cz'9++DVuO?r׺.w+J!tSp[vxWRwjhutY^^Nj"!|ʛ7GSiYTw.+B(=cJ|17s7hu@ɱ)i8Zhݢ"GEU0{ nvñmU'zî ;E+k "cG +jWլcrfBQUHF \}ƙtj{nζI!{.RV)lHY7o>gT˥F /"MyM$ឰ[/@TAՃ2"e$΢*~E<"bS%H4 ɲ~)Oē*> RW+ӆjJQ7fMT<*nZ~v.,o5DPP8rEE{"8,Վ.%=ɺ+ڼarJQTϺKQVx :?>|A@m'B;0tG|Rrqcʺqs(2JOQ>L˗'R 7%>(iɨ~ ٴyWjTE )S kQL>pG6_Qo*,F4zi2T8'瓍5:מ?1f7ۗuRZğ|Ilh;a7d^)sB)d<_QPWzTFW;fZfe;'fsɋHҡǕiyH?z%O#Iۮ|jX5FBv.3[Qi W,+\&j"Q9x* "pYmԜ& *VhOoYzNQ]L b Qu:vNѯ#(IvEbkP.E,9{&%w_`EWT]lK[X(RZPZvmqEr@]q"$?PuPz* 0hukPT8瘧~S.\k54-#E-Z}zR?/]O~a܀@U:vH4ߝwTw|T?,*Ǫ~ih:2%P)~k~sOJ ͠kvSofhsMl^R^?)PNQGGͅӴkHO:w5R4g'P2,vQu؀Q#A~c)j=x ۋ"lbXV¦O^+V`Q}<ϲ&Ra8EeC"S 2єJ`qe^9.+9CҭKU8N:z=BmcIJRk}.6)bFo]TG-eSoɶ4Ċ M('7łn~6EHj`~Z$lb訠zjt^]ı{}>M=Q(Ǩ^e۝, ca?x*9WMq IX-&BݯPS"?RZn=N؞˿Ұe鼎]K{1Yvk?>_Q'ے7v=ͺR' l' 3^e!<|SGn76V>?jMϏ7E~C썧9^TqP YWZްH%淵B-ٙJTII໖:!!7:6G_/!YM' i烒t]wBʟ Kxd2t:o]o_Fԍ~Hنz74}]j0u,'QH&NBW.Դ]}]~R$$z?R}jYn0os~JvU`VMƕ8U('r0vw|j# oEB|} k[lgy= nT7m ,笣YVlNa LS5>u i/~*Ҕ5D)qϕ_~ $ uMT%!JLaYPoY.KsN#6v'أחz([o-?pf[2~M&cקr9a;VH7hΫ⯭YOup5kZ&Ll [\JPTVѧt.s\m wμ( ruk ?%sa@ҸhIQeڕ`)Rzw4{ȗBҧEEJLqyTcflzepKCABBCB`0WcU pWTgOH (ҘѮ\O.}/r&zt[}CI1,0uk]FQK!ĖAH):]]QURXL<}S_8ըwC;?p&8 EaQac^A O]JRaQ:v DM>'osJ1OyE0ǖ:"PXn> xe8J},`%Ɇ*r8%8'q'Lm+VA bٔ'=ˡ lx*%)SBc!J+v[@ uį2Jkswa!$?B=&3&VeBP'_b_}0 $&n$P$ï2O,-$/z;OO q@f?p5fߤ))j M4W-k3^fu}2[Y7G3_corUW۫\a/=~xؔM_}=Tګ>N*:zF^x솿gؔ8k(oWOɱ7Q:Z#lk^WnV֓QXvoF\Ϛz$ N]h8XmQZ@L )O 7+ 4镧 v,4EGMʹ,*mmZ cv͹vek > /:M.>!xr{=O=?ڦ?2^{aCCuN?^"{Kl thK|䣗iOޟ~zN[AUHKQlsZ"RYJ& B6XñiFxo ,Z26OXlcB|# 27JZ /rGxиXǥj6l wWo'o=l M*A͍mRh5 dh1Ɖ6qWB׹cpLϑqC]Dg']m52pn-VF&ofBVlrJtO3SbulfxF[ēʏ6X}M'WpdC7cPkgc(U߄RCʊpMG|}>jҷm 3xe5!H;M!kF7 ׼T])S85&L7,ڞ~Mװyl\!k|]W1l@66ҥuEʩզ; ]s:=gMv |ԅ鲱pH& *O:#qٕ!|T!*8*GOdJCSmrFeJW#vxBէ[C)y|5rRzէv5DtX;;hG{5Uz08Ls{S箿EHkA@.b"vB^gU+%qx׍Mwj3!!OFd`(bܑ07g5u~/N|* ),cԖGz8AYv{hvO&Gr~m_w NupoHuCM*Yb %QZGS`m%+ q,;V.ɚO'p8fzs3M;P* `׹}Ezee0.Su}c|QiwWf\w8&ڟ2FtUn"IREz(rmj.~0zH[ZD{K2,`7 UDW%[Ӓ:,(p_eEYkPR Ez;/.#(ؚ;VK ڬdRu1>*VX¹ {5M(j"< `6)WʺdR# ʣ5/|-ǥ~Gw6|sұWATUcrt퇰>5z(KLE;VB Q@e.ˤZ?kjT\6rE!om(R=  sNJ'~Q0Y tfƪ,(dtb*2KPRAnulODjh2\:Mߒp,am[twK)>}ΉE%r-7uk]7_tx]s. Bg:HU5kxzJ8(>:@.?U' Z_uNʵSE R=; dWح5FGh{nG=}]o*Aɯoa,F:L%.o[@5Ӛ$@eGB~2K2 ÔQk_%XJBc޹{>EoyEUM7k#t @%^& }*zS`'`{-'3nG`i6EFTm<ߣGI *>GKbKrT\^Qr]ea]HcG%Ju&&~]^_J"s<))8EJJ[`)aRTemV.HB~"nuK=t\].b~;{bBJ.Bf&eW_D-sm3:*ҦFwJ{6Ҫu1Z( Z个ަf_Y,^ w8J>gkS5YpJI@<*-|7ףw_&ΜOl4 i>YH5ݤUNugނ)~YƲËFy. p}iq+W@e1-'Dˍ*Wѕ(w)kJԷIۂF)iȇII١j ڱi~dm ^>w~2S _4TE{ %._iTYSR !$D$"d` rueEy?\ =ЍIvWu)S6UU*Dv_ Z~. AJF`d2{ZzpzíUWܷF ^{(E]hI9øGrO\HWRTݥly2WTUuJJO2~Q;d "2vp~k՜c >x"jbE۵_nY6[n)ہF[ql?'Ks`azXJm"I}rP-8'>wܖ'THJcӮߗu% MSQgFZ=[lUI˼OF޲% $)er뫒#/p˦q[E-,KAmyFK+‡tnҌmU$@Y!]ݿVfUV[h'EjZxma'B/+r$E=HgK(?6|QxJ][G>gIcd));XP)*L>Na@VA;:Ir3UVF-Ԥ,~WFp+;YJ~(h״4;KT&~)j#J* {Q]hd^xBǸny?--sUl*SPEpUL> z˔ʵ>QMє?aWL$(+ h=ZTBiu2 "b9Isqy0MBH(S S[/I#=i/cZ{ `$͓gI;mlzZEꂮ|SY u[؇ X,m`K/XLN s LWȗBwB%$}Pp5j_Hŋ6,GU s_F,u d>0Ksqe(aU%*Tswq?;SEܰ/߷kn$/gTG4. 8-^ n_B@Wh( je♼HYA ˶`Q zEDBh3}?Z~&.+^t4~^ ; ݒ}cǦylGT;סOVՉ5cTGKȆkB/ىmJ+uo^T(op#&CtUcSp}V*~M;.t涆ISN]",wP֬7ݩ?kc\Lp!ETFz'Unf&ڦJ_|M4ߊ0(rx2dqe Ti]%C"rzhn/knoA@Ka~+ܕR4dVXChEkfdrکXmlZ2am`Tײ ØhjTAʯ\6XջJҶT67iToժ5xh":x@u 6"^JBs{xUn-yKZu<_<vsŸHĮpzp\Wdƛ|=Nt> 5V"RT= M$]_حG\БpX{(4a#҈Z8~hvKZhZQ:=nػE']wM[metFGduw6@W%SyLu؂cǶ}p<`SmDO%)VV^U(\CQ/4@%B~ǞIENDB`PK!sΖMCword/media/image10.emfO]v<:&t㞥u\G< eddApP@=ƃ@C ^"#2"OX@NZ߽-%=^ jړ/n'_/dWNe12/nOOuNeu{ْ~_F^ӭ3y7N:;YcIH'Ҏ;#ܨG:G38Έ8Icucd:X}dl/;i4[g/~,]?A^vod?]o66}tv]dtsבX%`dllٕ!V|'lƺ }-,FNl,r'z6z4ٟ-]Yo {<}/̚/c粏ZuwY6!zڕ3@9'sYEv^c ]3Biny~tڏk^veqEƑ/Ƙu7@r:qi_Mj;MWy*+-}xO1 ;f ٜgln7~݋c#˙u67Ow;OuU-dϛArY?9;?;8 p@8 p@8 py|jwBRuہ|՗WJN}U/}݌Q!p|/^xӾn:d3YW^>~|,~8^Ph"j uu/%E|}akx\/L(*RIx T.s߼Bݪ82[z+angȪr`'DQ*Z|P&h=AZ;]=c/pʲʲǨepifY@63dPMreǖ(uj)3R[*/qIvߟQY&凤V TIp4ߐ Fex@pW_EٵkwnFs4YaN)^įdi9˗72*V!_H|Qw{N MA?HW"+Lo~g,_B\yʤv_R@_Ku!' ,{EȲ?bfVĶ0CV9DŽ͎u6AN􌽾W9_,sBm pt0xJJ 8 h?ƯR`'*m4YN_ qy-؟:~Ncuh (Yt xܭ3jYT)S*ShK8| ݺ.! ֽJrhQl91 hl= 8 ל:2iނ83ÖHz2Щ&ڢs2Νoc|%g [ڤ7 />9aْ*𥝚[ѐ׏eg)me1T'bsj(EF3NtXfԩyUiUJ88::Fᘯ6 ef#,cMy VYEmBtF**@6%Qz]?vCfW\w,؟/$/z28m)A&Rذ 7g7̸;[ʘLwlKҞnsAcϚ.utr*%+.74&*˨{AVH6R>ewdF,v)ȧ⬢1"(xH_E _bo9\1\0QNO]UskξyKٹ`]J{ |ݸm~嗏pQpb†ԭ1 V2ݦȚygy܉,YC_ex Yɯ_ϝ:Bl䔛R[ VQҷQGPbF.?s%ރNe% 2I1|WϑTW˯+xdwэyjũ5aU7JZ5Ŧ<='DÇL//YUO+lhOmJ ÖE-lݣ[hQ s!d*V!{C<ENbd ~u&]DOwV*!+Y~,^&3_c'[cB+41S)m~Yq~DOTϚ\Ӟ_;jh}fg<0qsv<% Ci~ͬwrAc\uo6b!oŕ, Ng0D _u _;^ϗZfTw ;[LMIb %q_gͺP6/ɵZBepy79ixt?j˼ f%3/ u}fu;@cêl7/ߩnet^1eF RlO|̯n/$kG2]|`Zåd@ O4;3+YΝYM-qLN(uw׀2ζU8سKƖK,Qw0_T^O~䚥F]%Tow&Wd)VOp _!H 7x u6d]gF}Za82/ a$M=<_i1lh)sh^.oLvAl/1u,QDxd uhAAAݣ\-X .㑅5Hoz8άd—z_L25n-g8\jSwvY(Rدgs* (L+ <|_9,qQDѐeCQjSA:)P$ؠO kZEYKra+rǒ|`Sh( 26"_i^3 ɪEF'׾bDɯyՂ089J7>*YhqTS/FnҖ,,V~iDe[R-,l?1\H0%*'WduoGr flJQ9[DYVvOcu)opY[ȒZO|!+X2ҡN_O {E!L\YSt%Ovĕ$O2#K (l~R& ]qю 8On1ԧ={I\*|Sh`&Ec~ʷg׀XKƚumUC@${X{jčl-1pռS#6/Iʯ$;EֹٮzUڒa]btrnW2S;%j+WYJ$Qv\Y\1Q}?Qq[I|%125ܡj?dI(i(|I+n=keH/ȋccQa| $ju&-4ױV5 :E?1!-A9+rWݱsN(ͩ;{"V51`?HXKFuШQ!Kr)kp` fk* JFVը>=6K◒RH^ D4 1{Sc X>)ȯnj!dYԒqFT+!K YI5jQH}m[mL=AY|\ ά YI+ BUVѽ䗩YY!Xrу "+i>+`n`kޭƔFiUM Ƞ &xlڠOj% cLkl=2Q<cb5֬-bʋGg \=*mWՍÐ 숽J V]>$Y+rb-]xzgtdtsmI4Kd۸皒i uMW3" l]ӼnjSwF\W7_=eRK~~x ̠icd:/myq(;p\ Gm×}V M)Yge"K6 P%` S5(4W (ׁvw&;ޡȼ5) {dA^- VЇDq bZvD#d v7E2idljv)*g͇:H޾mo߅5JS+ H%C9 BJcS ݧk5Z "L%O|w]w!PVugl^o6z}e tC]7g5z$TCٜ8=bVE,/.:vwg} !GI$r 9l:Kгϯ[R qI2ؖ".)Nfjܼz8! n^שλmVes(,YטtJbg,G0E/{;V¥'$Z#|IK:Y;5Do DUw-XkЧO mWf*m:A[u@ =oa^-Z u2n0>iةnUIdRBS Д}TI#/[pԾ`9qW5Rm6: 4` D-$-M6\T=;۪z7mesʮ_ʲ k@Y`T+muh"'ΒgxtS 0)m,qOsv}1q< BuiqvآIP&,L\gkx;1BĔ)iq^)`Lc+ÚeϹ5.ɕ:iB "ePŒCNmK{"ޫ&HQ)T9+k0i0$ri qu7']{1%d .BGjdPQ b ٔz`pn]f6{o߇~.ݟ]=ҝ_Vn_ dw'gd~Vi';w=keE'?iefʙ?EgޛߙZu\YTBO^ k˅Ÿn'_/dWNeeLi2SY؈{|F0bqZLƍy' G~gds|Ԏ>]"^ٱ=0g 37_3e s~앳692˖zBece)zwYvm#4 l8j [W}e˙e=ٳ%wfpmyuvlOlv/;ױ _Fvgf!36[&Y L>:7ws%kz1oȗ Ycgxr˜FV]N/Oeֳ%|f)y ~Yggd_|f' FAΖSP ew6|{ڤ;هZJ? Qp(8 p@8 p@8 p@u"A[Oح'= /U= Jpq~űڋ/vMbwnե8 | M}[qEcTyšv-J,wt).Bk}`;WOSkL A%  m ".ygl@P\J"Ut6!ŊAQy6szʖ%-YՖt@yFGirm;&plU%A^$UjL.v,X@<,qA[Z!1kƔKE艑|Ythdآٖ8ǠYsJpNRf?K7)"Km+YI.5Pth_(yPpyʪXoteC(_o*^"AcPTk(Fʀ2f C/;5*%͍n1D\erV}qA,UFimuh(4]zi;k.[!XSΪߙ}ȓ'2aWG@g KUu8$%gz:fZ85VIX6 rhŗFb-Mw d-(ˮUGV\[֢\$mM<|w1 4I;]0&<ODCS]YPen=u Y ɒSȲW<>UP1hD E?j綩a+ bКSS!USΊ91ѥ~Pze^>vz}ɸZdPp}>8i $b"m5llX^e@R-ZH)ސr|%WȲ>d  PU^-cի6/19e0ּmUh.5ZŽ8[VD\MPv&Y~EVr`Eʓ]b1 ,2H%aKPh. Fz^w 4^&Ȁ,ϝEx꜀:VYN[AB?2Ԋ@٭[0H7nb`$k& (ƚSpͩ-v-(=c>l鍤( h-://?_ p,M~a YSN-Y _کY ~_vjҖ\Cu+6R4m4DpA!5aX>aF꽜WEhK\d~coC\i1҈L;֔`mU&$LXnTOmR+/ iSr'c7d|ʥ{w ")2IB! R8'|[ і2zla!5| `(qc)_/|vÌkJmtζ$64{r\G'R⾸rC3k`򫲌ڽdՏj+~O3~]vN6k1o|**=/,_i1/Jq!ZOl5ȯ,ju߾d U57kkvk<%/ɯo׍]W\]~E '+lH#0m%m}wYϝȂ5_JܩӡK,ɯ|FN,Pme-}y%fl41Z=hD[FZ W(z|,Lu*GqݘQZ3VuڋUSl*ӣ|r@T?|o)4"!UΆ+ަ`1l) [=Ō8BVj(2ۈnb7ē_P*FVP)wXgu*Kt0lUrZgBܜ/ber;0vүu=..t,K8^LKN5[ 6 hDK딘arIoZN{W| (l_u=;+w6ԉ2 Z\,qjUkQ,-B\ DQ..n\~fޮ-Yq؈5ݜ]UUXyB5g.'UBUEٴ}n~MܙyfZm$$_odlx_N䗋OYjk$ܕZ_By.ahrEbqe*0pPgCung5#S.aK Fԃ;Æ2BN_ThS%!KgAQ'DZ9D)= )5݂p2YZdJ/|$S#(_" \yå60uwkǚ+I*|=wrJB8r *ȑS,'ETlS +f3x,QbR`~2˥?|3`@ pM6W]Y=-J~!K*5sYp\bm6f\z_W(cLs8wu_Tf8ј%W#oN/,U2#̈,(RVXE &6$Piҁ{//}U|_f^, vbj$q+5ك8$QٱZt% %bjw4f"1P:䗓"|(T"SX'.)gׄxe|>!kSr=Z.v{A=Cqmq߸e#K+s(eJG2Ano[XEjt$@mEu3ˍ6HeQɕ׈)=|KbmFVaj>dI(i(|I+W7'-kK/țW +hd2+tlW[ Yy{ ZQmBثw0YҪƀ+V䆯:zs.ϑ~OCQ$"eS ,_kכ!6k-dШ^%ɵ28Yꂯe W`_@ĥ$H5q Gۓ&dq5nꌎ+F4qAAZ $ס춏o,kx"!"+2G}y-^,1LW!+i%p5k,Dhb*z2485"ԙ=Y>.*r[[cʎ*d|a<;&^R !E0 {)Ny&FftC$5cOgmMۿƚ~b[beV !N):gG=;f|Y ]/϶Wi@Ⱦ6'zSm!YytseNӇmfI~sb&T|lB\_)B/,!ZN?,c&S Yf'^a.(wk'hf?B*q8v}Fv|gk3p,brh,a0?sfeQt p,|ebQae-eւ7>϶ICIdV0%ؐ$+8{yӻƧPQʒY㧶poBv);ڙgc2EW/T՗:Xq ƊAҹj8ĸj<齰tH7{C{+) P2 OD@ hFqbZND#dv7D2hW͉S~*Ce25^{goߦqj{E $:R@䉞(dl *A3e >hhB4Kc?J$^]߻-qmq5q^:cusepY7G5v$@ن8=bVEx^d=uz !KDI$r2K3feϯ[)H5 FsHY#\MO!ϋ9ln_xI CY,֬[呼Ȫ2BE)v);KOj$΋5dI=9ڸ}O.4Hˆ[\n HYWeUxB?Zȣ,,[Mq4*G5ΰ(Pv}m[?}U|}d+L鞕 Yjʾˡz}UٖG'29 a&нnm_ rYgb!"'dYGY"k'̺1B hڳ([}" eFr*6J"J7o{5)By* %(,|wá-^QX`uҘTR!+o_YfoC'e"SH]F .?)&(=Ϛzõ{fqO_>Mq}+l2d/)De#d@TAem$nB6t\+ PG'J-UtTȊsґe.ʶ|amBno?Y&L'JpN8K1%.# JjfWw8y~6mOe(ܘ+JK1tQ` @#Ռ4KpQr2Pheme޾ eY5,0 `@N[ zd@sT Ŭ6yތti2#>S/Ln){ugFk+ PIK>Œ?TÅChj St̆#G'%L(u3UaMȪw,5z+2cKfua SEY18b4%FL ST\/[q:Mr}Y-0en#}Q '$~ẗ%)E¡|J6m e;@$A :5'M^Nh24F a#S s46P\#=~هƚ c.>)!4&YeʩX% f*QYZ#=4zۻCa}}&/Bq02ˣ& dySF)\)`rIe08棞 P&~1F|Jkss\+5i ٱB R#˴a':h*f/ђkx EY#SRSewUQY%4dAA^Oȩ-o']2 #)lDyIj,þ9l8pyy u?!oK >Sp1Tj Tg.}#Yڔ\?֥ .\ pA .hիWύW~~צo?W^(?PK !   word/media/image13.pngPNG  IHDR65$sRGB pHYs.> IDAThCY tTyMYI$(AV"p՞TGED shRV"0⬓Oa3E ˢ0gB]w"͜ȶl|>-$n̤ⲆtE6BްC!Tk9 sp}6UUb(ķ)(,[[=IuJahGJ( ?6ņHMz^իY2.y?j݄[`__\†(pp{}ZML$,UbDNm@_Hֵ'4Ë:b0|׵q-FpoIMCS#x6ٚja@l,ZlyIVe`C5RBdUsiyzGiߐ`ZL!J:,llzCznJJ&t1?.I#t_!R<[Fe[gbLhW_`0cSaJbZ|F3II rv$Ǿ/6LcJ omZ(LUG;y7@-]ݠ.}>,R{K$i^]lޢ9Z4 xugFYYQwnت3L}AY+߇L <(IXT5ʼntvH= c57Bq4ʑWI(FoI?D}"L2>VghEvlNUʹovn>/gl`qG$t3B!Uٹ$wIKݿ?XZgW9y[ Sso_uU{ lAi\M ^jRqCI]u%P!3Oosn; ކ+cԋ5?nջ`|Fs6V,6n º¿3zf.\`0[7kktټgqGb,2+7*ٍ&!%jL٢SSh`ٗ~3~')Ōa?ڹs 7篇+p1s,Z?uPc%L%RXH=<pE|N8^xܨ^:/*{]Ͳ$zZ oFκ%G^5bs$:s7GiJks#= I( BqAէ4{0JQA{ݵ_k$niD֎ vh~_ywd\6֡fPROE9ؿVd)y<|!tv kaBS`DbksY*@;$/Pw~|^=Z_._qPbu#Dc4{;X"Xp9q5G XI~zZ*zEX@ΑO^ zEܔ 3܍8 MI^}uPI?!A&cxScyā=ctц1hsє|phz˹g'# FOx읜9^*b%߇KdFA}aέI#b֖%aXVI3ziSd~y:F:d=ֺPn y+ aj奴wJ3T} FIm307xO* $w+T5ZD%~QFK#t~hCa IVqtȯ %W T2=R|cF˧<} |Qi`Z~*|*!zFv9 eiZc3Kx:q+NgmBأ%IM,{j|J m-pz~۴}bqJp@ĕאcpJGSi=9jX^5Bj=/uk$+g_q]V@L$32ɬG0V?"I ~E- !Sa-z 9:$03- ^ /YbGWxu9rEJji q lgցlqu9fŠ)oYnQ*4K}8Ad35—,!ɚ5WtexkPפP|JmC 1̙ЍИcឹT(ښ.Fg.][;E`i 3_PyEXS!p> >sNxIYzU!5'պ9(3.Y,2wDb9cxh!DHSџiEQF>;.rber"2n}_ MTX`AvƀF1"|v|x)LD͒SDCYELrMqzq:f= HFT-q._4ak :/+UL-0 G('zi#?2ibƉ?}gh؎ҥ vWDekP (aOUJR8w 0uvS4o7E\6J.q:D, ۈˋ܋[(q1X="IGx-nuf}Ȥ8icvo8@M yRY娺#-ȉ')N.I!z$\uؚ.W.M m|,hc =Lz[,RmPC`$*aK[b7l,!Ffp!;ζΖBd2 Q&G|J:#퐾0׾W҇sa$MCR@qyڡRCuF|*N&ޒVk+U߷sx:8 jUN^WX-!amg .>A0 QNfT , ĔnU@ۚqvQ>ݺEWhSqA(SiP➉$XT #!1FS+7ݥtH;L)9RPauNt`Y gI8ih; pٿ СDAsm:{ԲdQ %x\٤C"Ml='Pl`{Lu 1 > ^'ЦIJr5=='91[F ~1ﱴb*~W{Zݑ/ck'o'fa܈{g1g)m(SN//3[il4?ޕ2ݸ#7n* s2TԵvRF4]Lr aV;"@|A m?Bħ빊k {\%] 3e4RԈ( &fIPHiyQGx5A59v".Y\ͩs.I[O3/=f- ?E-pDr 4 PjwPh l!wi>sݤm# ̰py0eL@E/*F ~-0&F❲Vw"|7p"uytѭ:Yfrclq ciQ5XŸf=͠_P2jUl*GݚpOM,+>#QG.dͥf|U}"esTܾ᫈s Qr,S<HڱL^NȠ.hd>=n$yT0.#R iVEso48#Wކi>5!28`?Ytd®XXP{vp'`,mCbn#l # +.!4AL x "36շIuw6=rlq #|WgNjz{zn(j;o%5#.1^tiW^{ ŭ <`X,RsP>Ompz)'8%=C ~!&pyV(fv̡rVAY((;F=2' %- Aa7[kpk˯>/-o"'F,E}Yt zh Iiڄ%d=>G~!<:Y\q,x2Cǡ ov G)0}o 1f?_u@JĆ2; muqsTCqu&wD/y@cV @saJ8gh1'zxU=OGX!B*PdwQ8Q׬%5Fb|1 H*4SD{;!=Ġ B_SjknP}EQKKYK|qc8y6 %! FC-o%koU|I:0r2jIE 90\5ʛ1s1h0B> cIDin&Lۇ(-v pP2'ƴYazGjь4@|B⪓'yD`ì1<Ŏ8ouF0 Q*NJAoa_]#"Tv/eVڏ?&5k_1K~ĴsmNVː&K ;@Oo\nJ ~@O[\U thc:Wx<◧o;''TH2?ʦu5 kG얗mўP,lnT N"Sp{ 9Ӵs!PK!Fg]6word/media/image8.emfOkەukBA:]=IװFy]RM;ρdRM)*7h5$SA$݁ 2x` zIoo]wUG*T%Sgi׷HR ?'S߮T}U*I{_*ljM_|J_OO1j{~=T~vVZ_B!>|^_͇S`/1={~K_|o;_zY嗴9*^X9}Bw?޽{XÏroc޷g0_ ;ֻ>'SW\ww?ݏד֧|={Es?+ǕEk'/>s7Uw[ۻJ+8~jz*7Yd{VW})}c>fY|?{#T0u>㺛͸&f˺fa?g\wuҝїuͲqMD,匾nmu7Q7/?їuͲqMD,}Yw,뮻_ϸƬ uͲq]^/M5WO_G|j`vveN{2_O0XZnKW[ ,yrV+Q}^-yby~^/yH_-y ,3K#^b<ټ}+ ucg7κ:x> eY8ϺllϳVݰ4 +؂bwi\''i=}f_|1M.kٝj,1;V//j^l Yt%Mhb@ӓE]_ro\̛&۟L;bX|x8 eLxp26_N~m;ŬiC͍I}gg˖eF/2]׉ |f=='@9fŬFֽjgqcuZ휝63݇ dNm%sa:~EYL98=j\w!Z#O_frZ<2ZƸx-y:d-gS2fG˔8Fc.ܪO$WmXeʺʆ˻])\,Ip R*zzU[B\j[mn(;#Kjq@9Oǯت4f`ddFS_LkQiK0_Ui2[vu4f-S,~ +f 9ErxVOxJ01`V2ůUl^ d"~9|PVJ2mv_uxv.e=2*W@\i G?xeVd\oB6~GK]"eEJ::l2kL+#-c !޻+0ֺ 3ne0Xb4Z@Ē oV@< o{2žɓ+l\/>d .6b]'DDzGY,`Mg {Z|#-h x׺ 2LU1!>IbAƚ.i 3MT;*W3~%o^ q "~q!N4zGdФv{;گˋy8KxeJ|\nؔ `%_bg o ^HS{QʳBLxNYsLTM>uR9;m]]//罣#F_\b2 *~xi#ȯce.Nxx%G y1R7`ǞYmFTV5CXRD(vvʮ"ݱ-ܺ$2.1}`*~Y{˜_H'k^ttcY1Uozȧ'judF ;d92[ٺ|>N U;bkN.'}@qOiX!AGҥ5r+m>y?b g!l8{0;_jr,cԺFwuu~=:*-ga^ ǯq~hzx氃Jz 8rPt=C&Wl5de7}"{xv䋵UC&0ɡ:b|7N}UXE;!]Ykl8j[OB_GF1Ot~턜gk kutk6FPZmp[^]uEzu> x]Vv>_ex~>d 2jwatX1" qϚxHR}pឦۥ}xwyɮ1˖ɳƎ{AD|.lٮ_8Kk\y~ՊL=ݓ~4RZξ`!UCY/S fC4eO4 9ec;Uؓ L"&~^7v9Z-Y޶Y7hk֨}c0=`+\{믜_ 2fslxn2V{ }ёu1kxOŒ_** 56˷!,eN/O_k_pʞerd+`Es3iYr58-bq,8`/bj>5/*P_W%? \Dtu;u꽡<GTOycQBw/Бk_¼2,>$윌Tk~cgP;FX~,68%^5Cͺt'N+|B<{Yd6NWY*~z}$M_{ +`_tʱ+zW8_Hq6A#K,XfA]/_g$[wjہ/~!Pbp_!Ǥ]o 9lUE2wN_ ^>k8ˡ:l+t$H߈ӵNpyu9pt#F\1ӱɼ7򨤘Cb~b͜/,[$ ޟă/ \=WxLa 8"~Qj㬁Xx9WXA4FD)/Ov~g>Eid_h>D曀S~ 23aZȅoq]+7tjy~2gu0te1Erxfa Ptrg>/^OCF>b_2)W ĵ/A. |JZI~N`}q.;<~oLr耗lU_xΗK&+.$,H\.8,ߠF25x¯OhnG''Fvo hJwBƞȹSȖ= enn=`O9e3'yxhW&e_kmNzN+JreK l믐_qv9j mE0sx2y+ٌTġJ5\·7+W .owRk}W j }Uq&0zC['h+e6 ~N9Б/VfD)@ ~IVTuBt dTn<̱| .'oY^A /I.%[^ .vLW25f'hⱟ^JDVu&'61\}يUF|fwld甭1phN4d,Qs - f|eBck^)+qDF2͢vĩd, L|kdɞN\N/W .jER(Ez /1A=m'#Z x;h$̋@g*+oLi[_a59UXU~x~]Ԍ넬!S/L`Ӷ^C'Yi/ /t9\4 +jiza9CwHz sc:lŅ$ոhL>=૘:l#P;fe_YG7iuxwm:4cR ~[5vNYBs~MǝJ?HsZ'od+1FF5-~+X@\Vɬ+:23'W)햧v^̈0Q畊_X̝g_xy9 Pn^G3-D;[M@:41^q-K6Ydҡ/m?Mx7;2\:e-!{|y|>\va+ůb@0֣5N / լ%~|J?!\UjH5pJD[ 7/ Gܠԋ_y=A+dBG/ `QL|XjbGH}Y!ad<~IQtGMtzgLX_}bws~Q 5Tx^/LVͧǯ8v/ A?5 Jfu1/_ C6tDez 8"~Ë́[`Pg0=2v3B rmd^lܣ> m 6N5̳p"tίLTiriAɌO/YA ]X4CDžrE `I/yRXٛVG_soVn#^]JuK_quo:쥇7 eӶ]q[Ri)xYg`ݱos1[K{ -{ -{ -{ -{ -{ <>T*UT/_{}[~~~~&g~SSa?oc״NO~*,^BT2?=~|L۟N7*ښu0Lݻ޽G姿ᯏUe>7_+*co~^8}~|w(U~=i}ɧoSU4ӻ_P}W|_W+V'o7nWw_}xɄorj|J{>fmpσ 5y`x<\bQ=3#wOu*bmb>O?o*HUQ}YZn[[`g/fmg]X<߲,g]6vMٍLj{XnXDu`zlA4۴Ǿa/ژ&ҵN5KȎwtXr@/,В&By{41[ {k"ȮP7`e.\YˏO\1E,C>< 2&KNijeK2#Zٗod.MD>ٞϓtRn3biV^_Aճi81]vNҙC~26t0,^]AIeJ*YiUνW ~ΥlGazZeJ9 2nxԲ_N 2.7!^أl%_lD.Ln+q įy21N LV%/x Jk',I<Qyv+mѽ2 mxx4`VP畹>1yr-ڇm_ y#Uc g(W j&8zLLjvh^Sȕn@h٦zX#l+~mwG4/W|?_8Îk53~aL.Or+ч&Ѓf1s~ZskR_;β2cL9ů`i;8yB'YiqzfHԄ߹E. E2~˱['h6Cqzdai#6W>C6=˖ⴣ/-EX'B!3=y3dsВN>^`0FJ+7Ñh랣NϨI ʤCO:lIb}l8QF{bԋْϴݒdK ܪ>gHXFȟ[{ǯf{{/rJclg5xd4䛽IH;IӷOD6_n'_>gRH:we7퓳Cק'cSi- _獋4˨Qܟ[ a6~ U$(rtx{q׌hqYsI1!fP>g\^,+[(mv__ NNR(wĴh9{% 0l,~+3_Q ca1ws389-&#>d .6b]'DDzGY,`Mgb Y|#h*m+^i6YZז_靟j;>‡v;ȣqJ2[=~e!b~yg?K 0Oۣez3 9Ae2",3cD#I|¶@Ǝ*/'ͺk2;w:K5dD1[;Drl!!c"مů ^ax* oVN/ _,h nk=nĿevů^DVfˀ@ +4iLzc ? ~v5/snv/P`p cpYů^o@h7ZmWdl,4c8egh /YԀv eY+_UK%+-åJvW/{A-ֳ:y)/)`x ߎz* Ȯ5j6'!7p73%^]ڮ1䲕W 0a"~E|GZW**8e|/~zhdSf8/v2cD4K✟5=M۷KU]_c-g1k2~uUsfVdz77䖊r?\rgb?[A2WqJ*#~_X9S%=In+Hj~1`"m5pf{=f 2͵/*9W'p{)9^[L{~HC c}t+"f]D̚5^2yPyW_3tJp,Wv9ZX@? |_0"~){>ca5ƯԃBhf bּOkq;(Ȃ:Y`${:@a:~_NJKi.r[S W{"1م3$6F}pkƨ2_j_1~XW˰xs2R}uAqaWz_!e=~,2ث,jQ_&k__S \I:؏b}+[/jbg4h4ȂeeJ2%x֫5/A. ?L1rLƯ`s_~i~;xfvl_.zБ }#N:!SAMrpnFI|zrL&Q!y1N g1f̗qFحWctV~#믐s/#5g "p+!r1"OxyG-A÷2"}oRƒ0/~:08cCf e)eg_H'j'ZT ŵxⲹJů,?L+ټV5dd/"aX;RĚ- /2+יhO"9Yީ{fgݒ_Yx5_A/j$3,̚)֥bdgٽ%;FC?YiA1Fδ>=$/b*"ۄc2fϓn ,A6Y=)9FĖ= x9k (/GM{43+.+V-}&r?6MŜ1ޛwJ#:CQUw$r5V7Vp 7hne`1`fA$kȡZ_ ܪYkrC;f^!8XlzؑX3MG,9IW _-_I'Wƙ´q-nx_ ( x =/;|ĶCG$Za%YQ) >Ё'Qf0gO 2*ll)Db͜b7 /I.ů)R4"vLQuBtz5f'hⱟ^JDq\FFL>1d+Keǯ0sH^ ~E Y B=cfm3,vL>5ݐx:_H_qvBYN8ӿ2A/b,!ۊxю5jEF%K'd12Q/Se+lbm'#Z x;h$̋@g*+oLi[_f59UXU~x~]Ԍ넬!S/L`ӶvKr7+W >R3!3:!=~E<]78, )VVXbC_4^xnL痭d5|\X'޵s-{tgeA,dUJR3tW ` bn-%gJaeoZҗ~o̽Yᯎxw7+=/}WսꈿB,gO%Nvu=oI^v KeyuǾl-{ -{ -{ -{ -{ -{ -DR?O+ ~/ c/M[~LPK!0C)word/theme/theme1.xmlYOo6w toc'vuر-MniP@I}úama[إ4:lЯGRX^6؊>$ !)O^rC$y@/yH*񄴽)޵߻UDb`}"qۋJחX^)I`nEp)liV[]1M<OP6r=zgbIguSebORD۫qu gZo~ٺlAplxpT0+[}`jzAV2Fi@qv֬5\|ʜ̭NleXdsjcs7f W+Ն7`g ȘJj|h(KD- dXiJ؇(x$( :;˹! I_TS 1?E??ZBΪmU/?~xY'y5g&΋/ɋ>GMGeD3Vq%'#q$8K)fw9:ĵ x}rxwr:\TZaG*y8IjbRc|XŻǿI u3KGnD1NIBs RuK>V.EL+M2#'fi ~V vl{u8zH *:(W☕ ~JTe\O*tHGHY}KNP*ݾ˦TѼ9/#A7qZ$*c?qUnwN%Oi4 =3N)cbJ uV4(Tn 7_?m-ٛ{UBwznʜ"Z xJZp; {/<P;,)''KQk5qpN8KGbe Sd̛\17 pa>SR! 3K4'+rzQ TTIIvt]Kc⫲K#v5+|D~O@%\w_nN[L9KqgVhn R!y+Un;*&/HrT >>\ t=.Tġ S; Z~!P9giCڧ!# B,;X=ۻ,I2UWV9$lk=Aj;{AP79|s*Y;̠[MCۿhf]o{oY=1kyVV5E8Vk+֜\80X4D)!!?*|fv u"xA@T_q64)kڬuV7 t '%;i9s9x,ڎ-45xd8?ǘd/Y|t &LILJ`& -Gt/PK!蒬word/media/image1.emf=+ݖ5HG3 `:tt5f%'$&s"谅:@lZujuBsgtgj{W_]^jծ]w׏]? _9+o31JW27l??_ O&'_?yBr"N¬ø~?/~&N8S~y6!og)ǿ1-e21#mOɍScCMDkE )SC=?94Pi9X/ҜiΏih~I9 9E5Uk.+4$)O\K~׌\?~Tiۈk-$Ǥ$e4Xr5W܊⚑'׏j mqʹ$ar5O8~\?~TI8踚On?ոU]Ӷ'׏jǤq5#?I*'Jx4'IJ%kR5!*?)I1IJRjI1~e"s5xJ4'-$y$\\?q 0*R}!I1Iz^9I1?s{~:7ṝ$a}Y <ү9_sKssV_-zxtE j_ exD0iɞ?5k @\r 5k @\r 5k @\^w$7v˥ޤ%B;k 8^M O|x3[ЇF?zaVY+(7_n#yՎ&?ВvGrtǏ7>{>z_>^ 槖\Gi8{- !G@(-d ;>^Kktt ).\N,@Kڱ1Q+ѭ hm@œ$ڣ ̠_]L^Ck@{V \86:phI Z 졻3}P hAM}t6gHY,,SHNv 6NlFt1-G/l~V_(B\/fd\-E1DGv~𐃿^. "3b|6a|:.4Ԝaj@W VrrA{`TέN뢮#=HҀjGxZ@[bC{p=C><Çk Z12/獀ƈÌ 9OiXOl"I&r^sСdS|/-NFr7Y.k_@gggjJDeZĩq ~Us_|NEg[1T}%zxx`}P;99dސ@Lܭô"Հv$ ʧ[8B,-V7WS pzV]__V+ qiyx(YeřV ,%}7q ⸚ˈq!߼׿mERsy=??b鑱\-+^b_m{8\-fJ#B4-6 kw,M*JJ4bV°a*z ο*/OnЋ7c~-v;PKB!mǯaB'P"׼(_mt@F(~MKU"'TN*_j9G1/k %9ZuVS^ø#iRخWKWrLUQ_n5=|jXN3ڬSEO_:ϲ/3W;,LTTʥL˄{w_?x hWZ/>'_ MIG bAmNUE!? ~\*91qk[{~WVڏb di/et얐O-_ޅb=28AֱJѝ|-Gb/WmeUCŭSc>#FѦj(svl8mNkW|y3#kwy=b5қ VX~rMR^Z Jz*ϿVE>Ri~-}s{j_\J"a$~~,458l/_FW_†6-':*)a)#G1(CIԨb%D G)Ew_cT+8cC)7H+b ,ruqwЦ3+}a%b֎_~Wu~i i=9Ҿ(}E%ZRJef S )s)6eF(.נּ>w戮ߨuGϿ v\ 1\v_9pٙ؟$X˘0"vE3=&_a9࿅t7o=aw;/{- ܁.(3 ePR琞VKekO|.4rŕKZq"+fh]~IK֝c*9,kߝ Mٙ!m ˵bA\"̫Oa\@alW>qf? p[ 3e 8*"s/cׇ)rHޱ]["爁)S3\[f %mH2S;38<H,S 2#!Yye`{2 8[js %jMC%3Ĝ1!ϿhƂŐ(Vbe-C$ZG9Af-qj<&q,]&8#u2ҀыW(&vML3Eˮe\R:kֶV|q!Z"(0ΧLP>i LBC- D~RNzT._hX/{[ {"@> j)"}JpA;PK|P88ڒ1b0{JO[I ze)J>ShqO>:!\m]?,8,/H8z| Cn7. ?A|RKYDŽ@KcDhcD4!G*F*FKj\&րX/a,dKCtj̉EW@>尸Iz_y'քY(iSŧLV cY7"˥={@X|`M_O尽^ZQ/Ub藟 U;hTKS1r:T4H;ۚN8§vw{esƌ|A-0ɴjfL"$mՂ+4z2h)a^yi9/ʗw~XT)䣳9B-e !Hȧ͓!uz^__OɡL?d}/Ml rp>i9Aۣy0pQ,`FWOiK8?hF֮ lEgfd-K3# ,-e^*Q+p0oX9/"B>u|P*STYBGA|k̅%S6p(/ .DlmiN`8vj1ĖduM"N#(OE ԗ~iYHEo[#׀c~`m2~+"X M-"J`E@~5.~h bt*AC>ȤF ly`2d1;鶠\dMDln>C-=;AO푚nPUڏ:᪨ZZ?[$| _02T?_c* mW$XgFg>.Uvđü!|Z&\U&mZܗfgj&j8wJVs6vcnq+ˍ# (č$|EJ) e|↑* qSǷ}a3iNJXlVqmt dC؆8>;g{Zxs}7xj1׻Au*t!.!dB ͘G|nTKfEFchc=u b!bȲPTsrI+qż8¼m+^:R8d\0"N&u`*AB>sQK,M&S~\| @Hl%^Y )_5ZG.|my`iH̄d!4σR\`-"c[pK8"i$H&O<,r 6|㰥%|nV<U3E E7*m!PB/EqH ga4Z& &d銱, J1 8V47ӯ+Z4nC1x4R lҳ483; _`-_9(4?~2`^Jc@T-\.q*k2ݭK`GTZBbe p_ 9 ӒV)2Y(`%,A4F!rH~aY {yQlOK_DXmJ4˦qJT&I#S4Rl;&䷭W?Y|En~b48Jeg]h-RI>qh{)"b$EDq0&#T΀h >/:k_jזN9`4O\ʂb5uec,ʡL(?'vW/5َ!-#--yQKjA" E\N'#5x7~qZ|i4(|N4д?/t ZoU%WsbYr7Z_Pb'ǩ=[p+G;5%l2NNM._g*hh%جɉ.-߼|eťο™W֯ap_F7g@ɖ*qG1mě J >Ye|%3ŏϿ_A/T|4#mMMkuSk~5~ ?+, _ZLvV_V^Oj Y.|OS]|Ud~o<'L<0W >rnϵt:+`_}Mfѧ"fgQDYDO-|!eΡ{z:Yo>38>>빰[yJrGѲ~1v%[pCNQT?#;P#`JW0,h6XOĖn^:d4+v~.j( 墱8Y!r{s=)u+ kĭ8kJc.^C=aPxOa={q4gUr-\ t.sdYn85eu1M3/)W֯>uV#W<\TliZ\L2-@YU (d bV7ݸQK4b*AցL߮0> $­j¼|ESI>LkDZD|:梄Zaj-NYq`/~Y b:pϖV09FkrYvME)x)A9x|bLi.V]xdrߋcRH4>j.Ljd)%"_f~>YamA]jgeBmEh|l-u xc[8Db,"@OӤy4m‡2[cq9YRcJ@Ju LEjK 儸?mo٬_ +| Y\Ks9ӐBj7#jкf?=^кl_i\ɔ 1Zod |,ge*rݮ.B+0ZOʄ͢ZGD9񼍾$}r!_dim;ο Ƭ t(#bB%Bߌ͵krnB9 ײəB\b+#ctkM7NӯG/Rtҗ-ObL.bO~Łq)۸v#MsP/)W<7K\C[*47חB|cm.h~1`]ڬ$PJ/CQ|l+P"ҷ+ S9X\$,SGڵpEqh;2Gh$.}Ɔ녁9>)bF|AZ7AEA? ť5_;oYyyЯKb\%,~ҧV䋯>6ϼbk{8LŖX|/4 9L,gkciyxu{a֕GN/u V RX* 4/Yiү[[X+WSQ:TrIW p%!rR#3[Ҳt-+vR-Je[ѯwX:%.ٔ2E~/ K#EvEFNF^tUʩ-o\ߞ7k ڝsH98c_A$OmXWB>#_{Ͽ'EOFKPpU զb>:Η0k H@5ԴEC֯>BE0T`"׹ycTHfי]ՈOi!3tl>9JĪ ._}T;]$R&[x*ƍƓμb 4`T}u.pqFrϰ`μڀP*WM{m@pmkc9VM O 4rQjS1|ո+(OpE W%h},6Xl"v+gƽ_Wrw*Agg,/iVj~5ߏ1op~m*}償Y>jD̬|Z ,K45vUM k^zeȫa+;]}(JBG~ظ?x0/& _As݀ >fCbYykaD.x1 }.Tpٰy5/DoGb'v^Lq WNo0KB: >864HԛӻYh?嗥!+*oINwt7%D(+ږt$TdJwǏ|h?\Qwl)>{(k^G8Mt̍"$$LoM CV>|%eֿj4!Ͽnň~O{C\i]xנ\[pG7Ly9]ύݡ^^L_؆dKJ/կV%!%.^x ޻Zz׼roFڼme8ҹ-bY}Rw2Yں{˕7WLjWbYVL\:; 1Y4&j&–"G:mW72w8r\b4Ў,iұ˽8h6ڦFO9_Qȉ1 3|Õ9obbW `w>/\q˗G^/O93=ץ D]l<="~dԸږ&Զe–߱ɼ@[ \;'WWd zpip OYgiٖ8dl91Vn}$o^ kˑ8X?m`R_q_;*e{zq16>hMwyj ۄJg#@wy|R;/M+'5--E a9f'+k[G {V}G`; D$bbZCI_NxS/Wb|I؛$岮aJ(sťà])\LGme63m_T#sr Xb_%rvv+/OB/?鿭$_@~֯>¥!G%p< Al+5O|ɣg-UfT 5gK*v+;5pDM6 "1B0/5?dٛ|fGsʓ@Dj!Fic-hY;[ޛɯN B"@(~ .&e/_4rɆ-*O+*6@j_}ugCاk p($V||<~p3/-PEOd5Z_اs VdW끖_Фw:?q<`U,W >!kt~FV?wN>O徕ͽp6R=բaf^.H\ŏ}?2\֯>:C}w9,8HA:8}zX>==}97XF?>\Gه'a})oY'Kjl<~9Hr{ï%qcG6iW"Ȃ/z#1ٛ]b=}"xNޜ>iQ\~^>11Päˤ'uX&W>fhW1NMŤe#[0|nV~io7[@1VY G 1VgA)bJRk"K]JUdpU75ZM:||ݎ[1۪4d="-SkN\ w$J9)ia,^5[@ vb0{K%O[eR}jŇ׬%fjL2֚A|p>:둊_OV/U .&_%)p (Mtĸ1)L_ "&CD& \8DwGY*ɓQmE hoZ~]nVX1Yz[N!Km`e5Yx q5Ni[9U~ 0Y_Yvj|uyNkNj R"+YzVj8;rĄ)] V|a\H@)ƭiMYײo@J֍/ ׳45IJ~/-{kl;,T{-Ԑa6:2ī6Bd |j͇2"/KCYzʗīR&M99V|% ]WAa .}lI5Ga_[}$̰\X6rW?=NLR+3w{'z.r:]4 #dTi*(.nwt73J7M~dI0:W^s~GTb/pFhW%/b4UlhsWKfpEx#b Y ڃŔ~qS 3}x5Z4?J5τ`] GqCLŅUwĊ C9Ypf[v4_=A~|>ssݶ-. 5Ќ˩Ek6%97O减p_]JB1F( IQ<,9V1b9)u#P!Z@)Z 9c MŸ(ӲyܦFUxvwsRdc/b}ۻW.&]h޳nrRD%h&d(!@}Ue-\4vWRxeHňWZ'_a@ľƁ}wpƗEт+Y*X#0,hajGZ)_컶%軮ƕSi>2cW+w,@-/,ӴS1❑0T Pl66W KZZXbU;\K); ͛ yE< VFᐳ**P.M\__&V)b'E{>j?/|5Z6JtqD~O}E--c+jg6c1wZŁS#BnUB-|r+_? .tV\Ys-#]3b UϵQ5ًfc ]bF_S!:@ pb"YE6#$6p6poEx($UH+r5(m;;w!"ؕ1UXj+YN^k:^_$J-~1Ô@c]^W:7W$ :&)8m1 Q1\OU,&GY [>}_)\D?c~qTdߵ Ю4o_I(o3=>i!3y ;E[21 4젋a<@b/~HmAGC9;Y }L}E^h=6E,՜ PQN߃#&*8(aW+Ū mOYk`|e 0PV\ͺ]"ZW͊2'SFU_XjkCEK+ u`$ЬxP1P;듷m$ 4س_py|e5W+V+uVi¼bz)..I;Xao bWɀ1TL#Ҹ7N7XV\~cF/+i^J*ŮkYzX #-r|d}̱#<̒؎ۿ0IxAhjtnL->uw)"᎓_+/F/p1Bc4855YȯX&7E=m_ޢ,CD~6\L-l`h)0䧾"ۭցa4ce ^=_KK \Yzf#b:1z+?V#v/+ǪEW}a_t&6ܪX}>V|SYWfYwk!]1\YzX#\ mtN遶\[HbiH̵ߒ2Q݂Y>=l$M½CzMqqw2&tJ-.#I ,DСS7 6\- ;_]ssz}k{̩ꪞUwJiuߴ'6i:lK{~E~m#>N3z_>iy_q;Yؐ[ CrxPـ+!@|EJ "OJj.ɇXfNJc[Ϳy7lŚ7U_a(彶wxsr}~:j/]ۂzJu`w+?ط>:ײ_mʬ_aE_U%GXWRJP2T;7/{hll/J?ʎT\| E)?cXum\w_B|#RGZRj&5+)d+ozZ7)%yQӗk~ Eg6WW(*D|wjd;qk$,T hT~:JԱx˯MR+JW"H}E}W;K%m5z:zO9_?]z_BT1"=c "mR1^XS\5\gEJSd/ccߺoƏPնE>#_H]D*7JZFEKCz voݽVpE1c p-\KY^\O2WUXѯ0\ius%ľ8b|YxgFOY8הoXyJ|#k& U S~SvgႯgE>#>Ky __Gl&aھL޿]wjV)>Ac%V(2TI~RfaŚ":PbT]ظz֕K6n89,4?r| zp"bϧ߮wÇhPJW*#Vkɾ6_oh6cL>@ ݨݱs#8 n콝Zi͋Q n|x>.ی *nVf1.n,O-imE~kh7hެ}HoW/$̷7Y@n i.֯n->= G/։{{:xfZfu 7m}Uѯ ._'?gGo JfE3>U?\Gm @)W|gƦ dKђyWƭiY1|\mk%isߗnB!vvoam2)p[v*.]{+"͊6nR=/]_LZ4 B.޸K EŤhѮn鴿භv;}8\u+E3\hҥeP7W4)]eLJѢ5t@JH~y}"V:0*ku?/ӯˣW6+ZZQ7ٚu"7wAʕ&uM}\E!+Vx|땫R1C k :-KLt{)X~UI 7+ZTLZ^]\ˀ{G4lC("Ru:k~Iˊ~uF_Gl%k i{{0[Rn1 9Ʉz[kU д![]g[AW^ k7W`hhmkIeK@E/nra(ex~v^znmuFpvsR%W.SJ*L~P4˸R8Jz 7gU됄l(L* '*]3 [*f-O|cuu*OVAgCD>[(ZBϮT8[}̮On,RX_? +ӯhFiee\nNNa'UFYnU>(9qN+M V <ubl/r+eu0H6x:?bn^;tin{Q7NܜLް+e EE|K}C/lR4E7s-(uuY߿~Ym{.Jm5=! ]e-&kpW'LM 7G̙ ;lp+tY[A\<_0x0?,uB6u_\lfm èz6mMѢϊVS7ZFik ];͢vne"ս4Ȋ~m{)_B .!vlE .u:\P戹E!j-­6nm1|H/S7+⥧ECƽ#f1|~U*wnWg_Ǹ-ZmvKGe^:ƅ[]()ٚU 7Wz6Gѯs` EiZ9P kRĀrdQ.ME¢%_Zzu굆X NpBWR7nMnnn|iѯAAǣԬ+WUla=u{:{-#暕pu] *nDP7WJݤkm u3EuBQ׬.eAlץ|פW 7Vd NՍf%mCn]&Ьho5҉)ҸE2,W[Ŋ~ :FZbm5'u{rIX-R30hU˿,Z`:3ITla?\mA-_Z~_m/[] E&'?Wm긑,e9I4!cpMʯt+5)1MEͧQ+g'懋7o$_j+טNmvVqn)虊I*uiVGIKݢeܢHˤnAKׂn|_F|] p*k]ܕ)UnEE~MtBm*ԭR4Vsh*VxlaĖƨX_ kMLk7׸|r%]kI~=%Xe+m$kKݸ 2[䛮fM&][AzaTIZr//V7o$_믿kL|@/jo`%cE\/MlX%EU+v}CO~ZѯmX>_.=?qr͢_XX]݂% (Vmz`%N--ukfY>?)m6Èv5Fu.N;eÑ!TlT6(Btz7)ZPl_b+c%E6K= _{^]YWT3(Cg5}V+;".s~EXK*h?Boa0믶rkz\B[Z- FW`UFP7DE{HWT_k%wZZq.p8;q UyzebE_fܘrZسki)ZT+5r_n7_FePW[yU%.m@#L㕊YQ*4Z9J_Ϸv+2%_*Vk?~pQ_#W^]fV*)Z(j*EӥtO*&jyT,m1"Eɺ}C/CC.ULԬ+Wtu;q=v@[ѯus-㬿FQ uY3ʊhz-1nbMKնE}#Q_RfBCPĺN[㝺f\܇" 0\~N:\Bi;v٧nAן:x$_^6*?)4֬kV&89:~풃] װ"\b+xUayǡԱi똤>_ѷij&vX5TסAYa(=KD,Uik299E Wu`ޕW?,ґObR4ү+VЬR`ަH ط/iVZ'?>Èr5~ՆKŅNYE~e9r?Wf8_! E!_D%YkRiukeSk;#Մm=\ tXT{R1?$˕K3Fvp>E\|K:nFT1gU18!*Vk; #v&+GUNZ&>Fʔ;pQzQ K0]Sϧb+ZQVklNz#kk+/Xѯ֎e)__k\=B*xW:(xWy+Emh}ϯ g⊀:W~aJ>SIJ/m.Jc+9-KŬTQ(RRov^F`$_{[UӼ62: *"&w._#U [d)_\ۡieRIŵb{pnbi57[Ym90b[~:])Q+Mg.J=.U,~GkyFW Q5Qw뷕+*ڶUүy+O~ -쇯Bb aoʸr﫹aT:,B,)9łsɜkn)/ԯ<9,/0\cuq}pc gm[qhb֯Y)Ks#&QRYA00HmE䁫c%ýN+%׼ƨX3.FU;*V\V_[N}57n_y^)uَR[ҭeOja.E6ݮצ+9j篯bq#T;TS"hEjk$_;Z٧tOVjUؽ[GŢ~i*/ Rvz{I}΃Eߥ$YR1锬t߇ @+WsÈp: g!%-/0\j+yT>-努7bFfi/Ȋp/Kscz|mMֆ}lnoE| ýNuzzz;=OOegӇi}{/ԣ9#}4;I{^IWx03זS_ #v||bg迍}~X/j۾GR<;opX nݟG_w[۲HNF2V [k_@lavQ ɧ祖 N,EcTR.T{fﱭ]4&WdCSmCS!,PєQŊ~u5KZfp)}XSCa^nhmkkI߆@Y݇J52\`4J$"5R+KՀ#+_, [/B j?RKHhӥu.EM_Zl9?YvQ Rb|:ca񓓓l5"Khs)tp@[ J*M{_l%^( hJF (fT3ljO a \{a't *5଄;-,Ec{F,9ܨt۱4"JMqsB'Po3&crjK-?y*wZQRv V/Nv{b[cqԉX_0"RK/P@KѪNh$Ǘ E34Mv+%4TRK2/ JÓj0F)B* %%CSC؅{6 \Lôdy%4V},EOѬ1 r51;jk a}0%O2>S14(yXoxWp9ٿQ:_Uk=Y6:pNQUgcTԫޮD]ԪwvQkm:kNkoUO2>1A/SG#΍82}u~oUPJi5S>kY'@ɟqd)qd䷪t,0ukO[XƧFQ%JiƬ(S'~sOo##U̟kT'@mhI,{RNJOX*]VZZUFar6e|0ʯ ?ii[z)\2>qyK׆ϟUivZ͔| GmcSwܷӪ?쫣?6t܏W:W{;_4v1YzCstu{`Vݵپ7jGo ciG9heU?Z\OOdjyVF@2e(#PF@2e(#PF@2eVvް'Riv` hs J~F`G hlj?N*TJgQNK0)S?#ie_gy9˲~>zJ,Tu䏴#!\+/S<a'V?RmJv_$pPHRK\GHD+ \zk>^ʔ#;zRL&6')ik_j `H^ԯdǾGe "8?8^jV|J],mnHN5ϧ|j;!1MN?л"D劾]^\ٮlY4G{\z>ψ\(VLS6X[./wdT1(zf "aJrp5S&.[-ԑ$ՀnmGjo􈾇X3C a iaYc_w/F@ca15@FSr<}xw7WrU@ct輲@)N/uH|>n:55[jqTKd{}u{Ԏz_K3ƇLG [/5VT1 G2?O85N^۷o?h^Ŧ3>6DM:bhxƯ_ꑃar;+N åRz)2zH68lF;^E U@%_-l/JV~ 1'{eINO2zzz"ө^c>)DGTˠD \Ǐn_ɻˋTF /MOO!kU?~vXJŧ 5~_)5XW,O?𖑫[|[QYԏf!=&u_yvW/P."^x羫8 ^/_BNtXtg}~-R9^߿zJU/3[q*M\ `E_h#wqػ`7~52s?5*6䴜J%[թ`".P~E:U^JJ1\k+]ELsWm\S;j/E]I- fm/K52}2o#~ULW9kgd#7=cW ;2`o^>}/[%܁'.t(3eP䐙U?;S_n@>'4̥_?Mc[v)g/9v^ԡ#obulξ&ы+EJcd2i=?=}^R:K{m5_E- iSjRۧP\ߏ=j"~Mi<>|Ka]n1&+D .߁j$ԠS"y|| ?RJy|\Q⫿Ą ő"3*p5i}4W3;VGG>$2ê} jH{d_"@`g_}hbwMtP/F{/S 8+r'/ae1?|dq y^J#%/rЁT:,u:qn~ l! 6_\=Rr0'6s;hJ&`D8݅Nz_y'ӎ34O*K؈v%PXǩ:^o-irK% 0༮b #ƀtXRșP:gʼ;[_#Qmz`/7j*JOY߀ɏp>-\_}/ڗW~yR2zRd9Nw͓cMD}ZmrG!ׯz. rDCK|2:=҃aLHx",I6,ٮ "OY˒9='HoA-zг+ F ?_}+ډIq@f'7(UJ/V]Rk KM|lØ.Ia"Hx)N:YĩjN 'Z*E65S$SE vKj׋I~/[ȀmyG@c~]vD8[ :DV" %԰@~zfhѯ#6Hg#ޱ5 ,"?:~R.6\`B҉C(mlQ_]PQvKZ/?^ ֧_"JmWV) NfTi$N{AOꇗ˅fnT<[b|EU#{7?",'#.g ܷBwQ}˽/;F@oY~srghALM01{3lA# ~-N3?$խ};E# kݜ%JxWMlŷOȴꯐH<_0:E(2sB%dm'e9~_6kaዏST`9b.Fs.sQKX.E %.$+QrΨPEG 4@0oԧIcv'^D8$,\6|[RF}9Xn۰ 'v7[^E1~y~-Dw-b>CEv*eOŋ%s3HBik$9X 6&su oZj<6e% 9:8@;9 DtW}{m Xۛ+tG {d/Bk&s 9N:_UQ6_yFz$6&d|3㕒 X J yA|V4{|7ӯW44nC i|zAdfEkt8əg: _`-_uP4q߆}irǪ_RUPRJK`G ZBQކOY."y|z>d^+Tp~i-PGwSb)$'sWs<ס a_>˳bgv 9M˴F4GJ)6S*h@exƑPxLZC-/=_d),K٢W _VCn#XԊ8Q9 cjrj ŗEH`*H,x_Ljap 9|۫3v|rz>_:#E8t$~ 4v33 ߶K3CS_Jfddm SjY\Bd"_-žOO(4C˔ń~I#'ޮ??b%G]~K|W~?{yBZv z,=#}hom WE7([R.>?Y9~|sf dzN5?\Q_1vE_6-!"|MyNOJ4`mEfg Ι KGS~"ֻN;d5+:E>)\|*ꬡʖEv0B3פ7`Lֈr%|r \$sṙk28Ê;U^܇[f9T}@[~u ^ pw.{es#Y:fM9~e72%89O )2慫Wt\uKS^d bUVݸPKcR7 3PJS~ $¥j*}siI}ZnR`KL,u؋F1믬YqH2sY 2bZld"V[|+t `W19ph[ӯI;1U. E&_9^p?E0L/vEb $?Hދj<^™JUԤHn?Ј<|E͊~Y}.тX~] ! 6ښ|f-5&xy5-]5D2bt46!­~wBF r Wۑ|j&bѵF/w⧹/4lѯK> Y 9l|Hy~JM__쯖#dV:d,ԘY}Ɵ]^]}耯v\iAiZAϭ7 Va0ҲF:G I]ԯEuxʑNܷ7d.Y=\dh_C2kS̆: DGf;[ԙ W"X$"X$[EVV^Y;3gw3&Ko.OdٗR fm7YO` I&hY w9qg)ta Fk Prv-[ y:i`y^-2ܣ -u>Cgpɿb>}R?:s߹Gſ\AW\k Rǹ/߬E<@oדi#XI \x_|_V^ƌl<(/%b&E0nb7?h"1bOf+O[/]|4_ ÀI\mt>pQ5fdШP=uڵ psN09?˯m-'N_iglT~?VH0&_]`yrqTabS%(c%.pDvTc Mmw[oطklf9xUbٿȩ8,Ĺ0>D<?D]?*V^=Vɓswe _6kK|+?MŏWEWwLB%r#[^V[kCِ}T.JD0y M~pQcʘEϰ/aLʖ9Nz`B1OlS_ˆcMi_!# + _]`\,1z*̇_n1+5Xx>狘Twdx.}@MPx#W!|aL!Р6fm^x2v.n P+4 -揣|VM@Yg"<4&"kmU(:Oܯr@SeqcL#߷.v?U;ޥ`[.fW ]j)nm0A$30;~Ç7W׏N{HbE%|r5}Bo mJ: } %_ڎ'(Q6u`0\?=կ^ tx:Xci< _+Xp1v^o"{e%h W?-R\+| V W``J}>]y]9J>9u|e_l4g1FɃ#B#⿧^_?F=MZ B\ C2T*y:n8m>?BqFu= +)E{mV/zVٿjO1߰pq|ZOQONم)' &*7(/bAYAl -rpڷF^h=Ūp> a<)>~Åaؿ ;*1QP)k&Qp[k"D'1 Tciڷ7D\kIhp}'*>&-_Ҽ8dOW 1:$:ғv)h◥AU*E8G o*1UL+8A@ ev`#WɝF1lK _!ƍ`akRxq;'!j[{#pX"&5⼪B^EjվvH*/Xܥ7N*> (n)'B+,9k˦|uk彥Ѱ,\q%\mJKnH$$Ĩt Pj"R/WVܦwdNv.p-$OqīJ_DkKԻKݖkא~Z !@:UvZwbĦOܸJ'܀qe4j7x?2˶yjw"[LGKG)OO j?[B*s{;vZ `\ECX]m2Rx^Л \Ī"S'ʹeS0 NGk3k=?yM#}׾?֞`t_v%_Do>YàoI &SmHM8E_;xBG-Ųu_8敏n5;NЀKݏd_] 0Nq/ >$p5/Vߪ.Sa~RGj'.uP?WІa.SCV۸_KPcvxJ:ní_ 1Ƒ}_vvFj+1#sPߵME߇{djuc+d78| p!-֚t2G⏗Fb?W .dIY wp5V4İTbWzG'J `2 woJ _Et[G6T"Vu:bk_/ e._/>81HT-DCm&OA)Aީij0+4mtVB1izYSɌļ$.F/06 bI׏L.0ٿadX#P,) GI*7[̻ōfxӌfEdĿT|gy\z%_S\&xvCyDQ>gwCk^GHJLF@ :21Ykh6摬N>/*_̣L:WT| E$L T3^&=`ݸc|/?Wq8$V0KZyRj"PUtX0+e\Q 2E#АLMJ!B3jL .f"S*Eq/BԤ_뗀VF _C| KI?nT@# :/!ϸ)djUps Êj~A6'+19w658p>@dŚspqaRMp!p>bJ+>i*XaJ&dq+fjA#b."&^X3q~*O_xy-M_]cjGYk$O "$'\ԠMB1i_Pa_UOb^ huӹ!C \|qEף 2-"t'=s6*# \|Z fU O"Zo[=a႒./:}ߏbU~i z%~*pMBf#Q3ȀSb'qXi}C*=wcl Ŀ+U ]s>ET|(;A☙Z= +퉕 \b@62\t7a-ˀZĀC/)^ Z /%>ӿp`^Co\t=BBiKP ը!Չxj^ oMX"22.&g>U*8BSM\͈BP>/];q8,\|T@O_z6ơ=cQuVԞ N=JEE7r"fcLNI¥ɘ27$hڦ44K%u? pQIYgI됂o߆qJG/U3SRm2I1<I`qZAX *d0mbl:bY[3R1ٿH+ "k8J61!bQơ=VFBƢD, -15m+pYD.Gbhi./) IES*>3`jc@cھ&6b$l„(L~ުOJjFB1ʗ_-8sKƇ+t(5eʸ%Y*fbšbUj ip#P-έ F)cCoJu? U_c)ImbsKy!@RAjcmI* m[Mn@7\9X}9ȢZ_ ν| k,b/t}.6q܈TD4å!,P՘|yIuh1b{%HYhs0>}po7k,| >P8Z Pv"b6M,ƌ[1U\(^x;/ӹX7/+~(DnJ@1VЩ,P6;)&\CK Sus\+ಱª61X. p|8y4'}P{!Ɔ1\p|5=P l`^/x9dłaYTbV( _P@bp1䓙@bh|a.{ ^^^j5WӼu|rS׽b+ JLl@kvy+ABm l\bG@\EYň! phG؟mUT }(Y%t6㘙fEϗ 4,OC{W {EjD9űf Tp+[sX,W\v U!3X@*sT,,lu8&ژsM"åF+*du,m/>|BB+T_gND+cfT+TMǜ[XfYC SNTbfw긟Կ@+VhEp~L. G|A8xq؎8f(AhBI NSf\ Ė.㭘@GL8^+ >ÿc|G WeA?Yh̜ӱlڽҙ@O&Iئ" 4n/Kć_Ρ W簰&p J49SxXC35FF%,6%L?"FJwU+ʑOq:A '$((f}~ݠHyl̹_$91&xZ9E1Tl?d9wd (]&x}0g ﱝ{3N)?cf.еD T6 =ϚebCoIɍΑ&\PqBpPz$F1sq#D1=qc?_(+)$gMZV*¡fb/$\Vq?l?m>s~cfXmbOLb%/D@WFL ˪"m4, 2CspY"h%.xBg(u7ݦ9}%,t3mCzW-<[Q^|5F 6 E*qh`]"b%Oc>edłaY $ -+]+(l6e0ƒ|uݶC8P__ /v z4tR>._׸y~+m☙ )YUODcfާkJ\Kտn1( de.1_`űJ}LܤƙaxeI 8Eb"u}y1p~=oy-_H*a/8_ڣ@eOCqjvs<L:Q1V13uRF9L[+^[J:5o_:9C:WNY 1 ʧ,bmbbŖ1(V\|9&n0IT p+c<-DCb\sE'Tm!G(,\ٿ:X-\LQ }p-T㘙HёaERc~K2tXVcGK{K13-U_)V) p?Sў7w;f;=?dbl,RŖ T)fF^`s Ӳ"NJ-cl+q=J^ 5o +_]2XK^_6F?_87\I?]3.D]h`Z26;c% T+vZÝ_J jTs4 6+QTk'qL h^s}_gP!W.ō6&qUQ,`*㖊(-ub,he^l+L|uGGS=+M~l- \6n 7E_J 8IX9$Y\UUFQ\QV$J3{ 'SM/!|}3.e|,0րOۨ@ĉ.1OĪqդs512^oX˾G  !=+_] "z/KB[ULWr^Њ|=21&nlebh*#.Y$ĨF e EpV"bzp?@1XDҼ8d,Xir"lx07)uʝ, f"> __LbaGK1ߒA+bEb%Jm1TUtWLdk($9""Yu.j^;8u dY6l*EOTu BǸ? PV Z-,xgce>R3mp7nH`o}K#&׬ĿbvoPX5 CQUH5fC 1Q x.UbS*Įpe:s4\+׬ Q4VAlqϥa.-R3*=N0cb+.x\3T!eeŠ "\^\q1_>F _m J1{?fbJGXL>7+fUs'2%c RD8vf"n:s|᰾M? ,oO:\DSkV!ePme,ѿTHR$- 9cm_D̪MX k=tJ (.VR7b6&hi U&+U8HMoT@ qk&cV[P W3==ȗ_\p1&Ye=nZq{}FYPw)q]GG[/׿'Jj07d22WwCbcPnw:%%)qpêM.C/|lqyN#ꯧ"𣸹XsZ%vpbe{ĀedtrcALt4fWT ~oXB}NÅR=_MZ5z\2k/nnWTqSĔ)kȪ) Zה# Y?sq1zY%G88ZkeV+Sۭ\lMlK/Ɗ,y=>KK/Ez28|%p m6 \LS qajU #[V@V #f)MrWż4}9{iĤwr^ѻ͆_ԑm^}fUq+j7}h,Kʱzʾ`Z5.У擉ߨ<ﶂ4\/W&}jXQ\.ZYGs1L.ըXSGx~5MA~K/>u7Hp+F Te.V`X_vL1,c >j7dB\w7ZX|M=n̨&܍v5 #nd9ڭRSj[qɹ\\m-|\}ͩݜ5 ʱG_3N@u~uWڿO}%8K_e5Z?VT]̵4IuV[5\_qe4~ͭeݼy7p{~~OG[=h}عyf3V.hO`TrH26<;ڇL:ګ,\ŲA~WsT[th͐%f٘j^R*t|M2Pʽߗ/e_wFͧU׏T^޹XYåܻcbL2M1q:Y_)t_v{. sSղs7лXS\hfVչ0 9杋)n X,bĐuONNvK~E48]ŸsL^1_֩3nЄ_{.wS)Yg5jshiSLfJt7uX_f''gl;o[\ռGP\Eէܚ^6|JMc!b3MÅiC(]Fq6^:8 q_wcnם/wƣO쟇 'QL\Vn?p#59ֺ/R]TOu_^o_r5o;ر9t#qBrd/0-V/bٿ )OÅKK\c &ә;/ q>xJ2-[Xy5B鄋T_q@uoVNA[+/0ՌU^L+nY|EϪhS/X&=W hr1lW^4/BDr.{_@܄kR\bWSk!/@ ݹ-Ce~NH st_\:12Eb&/]8׽/ w3[bp~4.;H#v+=P.V_2y/ھi0>P@z4.2fhspeejۧS|ݴX@}.7aq}9/=q-d!.lΣd&睽bug /\6uNu~~f(#gĝlЃߧ-V1Dmpa/ֵs6wr\L2J~? c-#Ҏef˔Jg-\௴-_-\=s?՗2Lj矰b <-|v,0[K4?bѿbl)|4!eI5pW" ._N}١9DNBz kp d}v&EUJMVQ*kUP569,4yqh>w,S6+]g—^7Ŧ29ZJ12Lu[**4qw F1l%mM&[By^5.dh+/G<Y7cn\nڜpp#LݎMŏ@qF5Ljg%~p ZQYi`C׀?WBʹlQ%gzcY颅bԣ# I_Mŋ ԝ+Њyed .Z'܂g0dPYpN;qhqci^k?<zʫ/ |I7^ԧL'YI> 'N֥ ?2'y{I` .>Y_. x Ο;e@v.W?dY@v\x_&zt9g/̅`&x .]ԅEBߜ9wgΜ¹'ʵJpY&YNڇLb >b>jZڄ~p`;{yΝ}|ݧOӺN>ǏX,sy3gggsR{uY=g^-E> s\:ϓwE+^Pp8K8}uUC2G>xY,NRx\D\& _NٳG1s?n/^wz<OFww7s> ?/EZ.+N })JWӓDU#D39) ?˾{|$EXf܂yOGAu.X{1P&T^/_| ,e sq5ub Yv\NiV z j9=-H߁}-}h>~'31L+EpNn]Dj^,D$#9%{!;Acǣ[ S>SY,,q%ٳܛ9Q,>LP?>MdZX)[H,{W89ypuELL JJ=} -is{N]Û'_8Wr#uO{cu|B6ppt%Ȝasv;8s,:tDO.R\?| .=7%nI;061wr5ӫDDE%!99(+)E]]NOO:}X ={ztrzy Xb-B=y* (8' 󆭭+vrCjj>1^R@u,r1{Y;;x1)!l|na wüU7lpQ Z 3/`W~ɪX\cOn%=(Ra}lc9"$i?B,$' )6qHLLFNv+jP N9M&[ Kx,I^}o18_i:m2ڞ'.!9~ e {v;x ` g 88;0КO|`!E?@7-t]{s GMG-wƑ@s5ع+nڍ; !8ы~ۏ+5&jC ŗ 0\%: ]Aƥ Ý1[r;\Һ#]Kַ[;ޑ{DG#6"1`; t9FV.>ɳxJt(%m(A Mh͟^֍'prOR+A 0r 88v7gPl g${!<NI1hƞ^eRv-['lf;a]Xo] љhVɓEZY8;}@eKlR^ǪMgU˘bWbcV:d`܃sO8шxfr"bH$c"4lA7ԻO]8JQ\T&iJ]щN:z8Oσxa#zɓrt% 7P|?ZZWl+hpK06x碢G0:D>O_Ow)}Ɇ;ݡ-6oi vmh6d36zb'Xy`?VY{5,]giźՅ^:ua5`a1"kƂ]K` d!hy"s++ ]چs5pBhD&|‘x(D]XB*SE? (FKQ4:Һ6e"!ɥۇ*x([MDQC=CΠ8S` OPkpnGX ݣ;VۉicU ܢa퓃Qpa lSr#ۻOiG񾽴a;ykݻٻkEK+6aXsVXo%V>Xj.!(n4c ,L`9] 0 Xѓ ׄ*8&mLyac)`Kv#&Tx!'}f,XrZ6R2󑔞RatSV4¾f$!(>JُЬFxĖ-v?|RW3'7(>0j`,gX8F 6k* m2o *B8GbvlsF&Cw`bB`plDbv2wu2Y-ؼ}f/ߊMąxf BKF9o NJ>HcHYIXL__.t5g-x'CsA0A3kKAz;"; [hw:61pKIHO(AP` G4V4A߇DʠKN@Q44#8pMGPw46>)p G@J5|Qld5L2AcێA3A' Z?Zo괭X랇M>X 8DfD؅d=*=ԋڃ]̌iH?q\Lh|rlܰvۅ/N\'ޞ5K\1:<_ޔtuQJ\D^eq%kUB} Ͼ{1h2RسwLn&%`g58bc$l 4$77wC8&$$!.)i.*EbFq9{p:{v mGދh;zΔ*#&uOH\|TH-~1 /*C;8g91N1E=0 ^9 #JOcs6Un#Wyb{ St6ه`{6X;c2FGbmM5Bl1fwŻKwc}$f:Fa6_o ޙXdvd}^]L6CE'ys #e 5d MR/gpZ{F+vqޞ0GDZEvf{Ji)#`0D'ϸ˟օq V&c\bb,iX읇~y[ !( B tZl gKl~;6n"ˋi]Jk`-7u9^z{&f؍VX+ ӌ@9_Y;(,RluKAفsFWØT1Rj. h..;Eӂŕmt쓻q+<­neW{)ML!]:y 0.r-_]~! -A9AD"hִ~6IhǮcTFbg)6;F?)$,c 2dY-Jfzm8q̤T(QfvJz-&?F]@qZ#Gq`Zh:9X$β:zFZD^C4͕k_-w=~x~w˓xE QW|  &[7z͑31txZ?fv ܃ZzVL>f.\oo{/~˻݊ɳmlo G0 2|сn.s6ok@嗢[Gw >S S,E-v`}_/+f+Kr9cSZڰ9CȵcVÊ+8 i FxTA+]'OR-}e_ `mIZ-F A=6r^pH?a $V+ҷ %pFIH1ǠP2QIOHa/ЂuXF9ʪPf}:3'hN~/Y({ѕҐw1Z6>&kmmv 5LH&q4~yݟ1fRs+b6w=b7#ug8ҬÐ0m<_-뷙fL ,4VQL ?3ກV[߿>29b"WXז0cc-xũ2t ƌOfH`npMFpK?^'Y} < U]t"2Ra]lo̰jګrx'#n#<*a Oc]]]kDXYYaɒ%Xt) Ύ :vՆ帠L/9 &2ݔ8ug8y uG]vlMZxwǩƽd,]`\w4BY;06xE>q?.Tzg ck s͑gN윹 _i&aْ)-&M,c!w=ޏo[&s9瀴MAX8c޻1f$q갷n8ػTF! ݝlS(>:Q y/ tG#1,*keZ36E7ckVck|Fd-"dT\:bSX{bQ;N5j>s<x3O>X oVu0f]Fi/JM>KFv37?ڌxTh+QZ@k*3}lB:V&:|"p?姰dE_A40IAsPhbd"ʐ ǽL@Hh$74 5ehkC[aZѽ9nƈbǖpl[凢ZHjEm`  (H&w|o)'(FxۭB:%{QVWS͝fHBɺ2%>_`%J#38}˸G|WLZj9NͱM nAeb1ޢOʦ!(BM\o3o6Lwy6}GiSÊ Infx '-4Xtl;MՃ㽒\@YE)ޟ5'B04V[ )V?YZL6z!èI*G1)"tZp"aY9E*v{rѕ]"T;`(˭@c5p>)v`uu-'y1t!~Li#)Aꖊ2Gƈ};I'`;+F}#ǔ%7ф Rc7&M Oki'K.w$J1[u)g5ÝWm^Lݕ !XZ9, 34HHLCX Y8ÃvƬd|cƌ?L5մBM_sRP/Tۃ"tmCq;::(q>ĤX7o&Νɓø╗C`]z5BpDDTQphF}-;t  2 ̭6ݨM)G^x6Ё&+AcmE]cjr#5G%N0UFd!݇6\Z3.~YLFo2n@4KG.҂#qNۉJ0.EtE|$P'Ny@ b_`.t!8CܪNUQs;n{ g&p22"5@^"2İ_ţO>o9)h@kS ғr|ԳL`a9gz Q[IQ OM+ KBk6ax兡4C I74O$iY۳rUVWz?I 9V :CSTV2 {؍„d3A>|-Mh?̦L">̛9EpL{~Rڃ 5)矅 ۇptŔVt%W jxKE[]=jsȑ#A3KjI.T+**h~́X2g fio7;p0 1x3xa7o-<-̝3 o2F0G>rD&_]HCf^!&yҤ`8|H !vg\jسYqYȤHFCU3-<=̒sH3ݱ>0fΚ+3]Sc+JH?X_<<Y\f\*!JN/afE 5(/gE\J>Z^+ W1?d=[`*QHfIR3]Qh(_t{b-~_ľC`2(4FZr WEn^+0 YJ9OrWOd0m<`&'M c8&2L$Jf12D^s^}ML1ؼi-\;6`ެI8@P93w7G,^4Qa$qsTlh֛xDZeoQ~lf7G #^'EBy65hIHΡeid٪ښq+O =u. lbu8BCE O)B\{ßxaؘ=&SV\[R?bjjev@n;&D碔'%>>̧䣺 5 ![qn_YJzr%e7oL2e1Q2>yTi,Ñ )[ZN2~,5GKyrƚc*Ƹ#]ٻܗkIc6wbkD;#0SQST!112GLLҐ iQ&OœO?'S&`Xd>VXX+%(no+V\XQ^N6(BQ^6ҒQP#_yQ-%c*wa?cz<$찢( Ij$'͈'ϭ# ܏ -ѕh61\mc[Ml">ށoy U";n7¢bCbfqJd+9$, cJ oh6q\yU-^yY3٤{ՑwCQRXt^e躙V1ۤUuh+!섲26tUt4`A>`e'fRfG^rvUS1q6Ipʾ=; Cp73@*DD$!j銔fv׿)xDEꑪzL./XByа(˩faYJ*Ct?% WǾں& =S,*u]qC-横1li9vw`F-l0$fԭ]g !1mc;;#yߌo7zS7$3aO}f,5wY16@޶ fPH-Y u6;if/,gp]"2hŤ}0b G~*Xֿ6<&Y&1mM]s{܍\ m;*'eQ>$`.V`eZl-"Yt~c.;;?JobK#ʫÏc̼׌NH?Ǹjňt}T^e)y+K]b|t \[V>9]\Oey3J?M+;jLϣ_h*CK`*v 7<xv)錮StaNr' G^ۍ'g"rɸʧzY2I8l02p 5Zj<]J]M@[;ʘAKJKcO=_2l(˴e&+f^w2?-7o}BR5Sh9d8Dtg>VT|1Y,:m۰q+/Q:#4[J R~A}?l,)ƍos5s[qŒYC-o 7=5=V$*`2qe QOvQ\ xIO{_r)sBSڱ‹A^ j6Rigvr{tiԇP M_3HZ0HӞ<ހL,YZ1ǎw`' TP@ڙY쓸_[oĘocX`.mZ0eX)*0'^ &ZL휜쐡ی[ `#6m`]t#aAx걇Ak~GWaO~{t\ȚItٜXum&Kn$pV_{-ZXj{"@_xSz ,q6xR;y 3`Er괙(5RH{W'rr d;:: D_`͂ ?kV'yZ":8-E@jYsOmeDfboE1=bZ# l e0MQ! VpJu dѼ 04yr3n?Ĭ%%!=3tlձ$+KLjX>͂Y}$KX󸤊TcAm'fv`\̰5 viW^ QL)MfP/pUc? cPCeJLJ3'FBC pn%ˑU Tj偛n w\6 eۑpֻ0j{xf7r )P*U jOWF [ww.>g,,wd+7nPK%Y3%r59d3h3U>g~ Zya˂`evkSA&:,( 1$ON vbo=ǴSXVӃK4cI/(gi$A)4Y%)ғ̤QU[w4ܕ uOC1q$[X=<>v)eaniMXF2r f ߖrƸHO:~XO MYj8tT T+MMIB_8~xcMe4z\YKV{Sg1koa(Y^]ܢoƜxv e6b*3`MFd((k_Th`x <3ǨsS6).N1hHΆ;$BjP%E55u_\ &j,epI@RM9S+՚D)^!#*;ٻ MhUCFSȫ$ t `e >PV)ܷVgGA02.rJM_+z!xg 6%rTO:0X4FM * p!㡭T(tȊg? Y)ajV¬i\L&}ǀ[ndձl֭߈In<9xVoqU1`%)m&_M?{5~~\cnszcԁ@xmP|&=J2q1}z͌H(cAbupmv3a {,͔"$+r؋U>!j0V36XBńK*Jvm;tŽ٣STVwfsr\R@:иJ++[~aYYsbgP;xKӉ|^e^ړO<vlft Duou}6l wOc47od-sR ʘy55mso} ۶m3c͜-7IS1vd(lvEYU=%4.#xmVdVJe\|XAQ*4J&?bU*b(DÝ6oƄAmb;'r$LuF [R%e$H* HWFΛ_l=); ·rȆMrbJD̛͑ldm>H4*SV ;66Jr0>jҗϫS*ʚFdpܪ\W)drat>lMXr\,mXo|`ȡ=>.G=dա|MIW_n &gΚ߱,]PT "91qc:3tCEhe+VaݶpGX\wq ޛ>[6K&Bt\O 6q( YS{̝qXq,gs𢏌IkfPl%8șQeg`cƕS\b@Y, $jxH,9pᙕJfyXО5Y,B28qz [vG`N d$2oD$AƄ% ?H7@JJ1EBfrTJPD{lp1med}@Ueekyuy<-^D|5פI /Ykgxyq6E,5[F5Jk[0,66ʼ| 􅿟׿b8~"&\)~w1f$,XXFu0Iwij/6aɚuʱl&uf;ģ b8jTP@&`LA6M̃|]h /XEXP:ƙ>Z&ZM!|k,|J`nE!# > Vlx-Qǰ؋ `>X\\:956s$ۃo4R3i PajΜCy93f\J6y1f)7H^s-3c2*DSR !5xLK5vv0Y{dK1J$tP=K@s_e%u cyDHJWK_';wks(O$((^fYLx͌ضVi?rXl`/pv( Q8EdJCت~)(L*I)f.pqNeDWS2nvğ=öD<̞)Kx/ch`/.~!Z+:H-g9G.6Gq|=i|D#N8eHY-@xV {ui%L8/uB2C- l pcՈliBhY7pL]R@H^0u7cMvIYxe"=U*5n m;mVg3f@o~2ꜫXw+nIc&ՆO$%;q#UQIOO7#]F|-nsk eìKB챃W^M+1ُɶEI4ge"`r,Ԉ6-]X91T\ol o"s9+5M [-R'cK<k^ŝGM!fjp/]U|'ϸ Ga޺xd^al0 a.ң Jcb2u0\(s?wR6>mIf]5,g٫JRbJdkJa-ukzRf^)XqI {)܌%IGj!tnsg 1:+|,}X/W7/cI*:"9U#vK. le{?due!.R壍 5O{ќn`)@)1ο0*FTȣ7'\]Z!1k\s1KpNRARƫ1YJND|&s[0Vi1`&Q~'x}+j0סtK8ҍ}>)GV[ڵ>=EscƶTyv0݁$9-x9r!dUXe֑"mrYH?j$7ΌL@'LS vV禍DV^k #1e"Nsa}}L CgCU L7\K17k~n&ȣOpuqF'Kq$('EW^\*8˕ENl0iwD"5.ZI#=RQ|0[ЦҲ 8qܣK($աE[*b^+%N9ͻ_tàwҩ-pu2Ϭ<ONڱƷKݪܹYX~rm!N.[mܗ^]sU7ߛfh#+WKM}=ͣ\&9nǞ#Ͼpf`{JLolULW} ?O{ְ9S \.mxw8?ǜ MP8)Lf1Trr[YkzǍ_lE8;ntsZJ2zJ"P H3ffi%沈 %GLd kn?|d9U30:#boRC+ccm!ܩ{`"Lk}U]];l /Hy~(#6tpe{ 5!pL5j2|rQVq=X|4 IH]d tUM.Y3,4Z[u_}P8Up^|c,^~cQĞz)ZT|\4~dwMQlb#٩;^yo;kS( D+w8e,ԆVXG{ a%η#H$.*QWJ潖U` W^k%Ȃ:i4uR[2oƃO2bBUUC |v d f(ni"5u3O#x}X+q=ƽ7 ^yTRJtȠ:z|_XI 2;60c,ES,?V<{1}\7F,9ti(E{)L燽`f[|}Xr#O-ZF~¬W<[qIR&Z) :يdQT8PYǞzISߟmā:ЄI\)yҝ?|pr2@% IR.O3KR%3zuO)6$)`DIȊlwzIkbÏfq0U-DMUVQr:*a"ZEџvssdvGlg{v{\$11aϵ'ՖsxFsU(c2Wi9-KԶa&bFBfҏⰽ<"J"1+_'-RK?fWmC|k<&nӝ'uO9N.<=6[*f-SWοQ*@^nQH~<"9$8"L_}@Љ4l΢kEa˂@))2%<**؂$0vg7(Α.Ľ?)"Rn靔P@6K+kV,̴bAZ@XXNu۷ۛKYH04FuE.&8"B.CNB5K%l"{ؓ߻`C ~\әVqu|z3P{z()Ն~)͔yw.c۩>{2jL8q,]rDdr^{ijЊ3o8YjzЋ=!R]6Ɗ)skLI>Z.Y9O 8]%rAಞgL}r_֍!lt$Tv/]k6lVp/; nZ.HI<k&!Mr>|D*Ȭ='{FfV谳&1,MQ_,pyHITg/2YJD:):YU`R%X w(n>Zi{Mr~cmJ=̦u IVLZX2M@&ɭ;" $J{MIGЏAz{Y/TP"Suak&c)**8Jq,W,U+WP|[(/@7S2? K7yʙ-k)|^[f#AȅyURTʣj""}\pyLXzr(S=9>%v|s r>! 8drIs1lr2ಧJBܗ| ̋41n X˝P Nj̜=n3Ͻ_Z\j&)ʂ))P\٧4Q~O9;65'L5#50e&^djT?Ayҵ1k"Sn͌-S~aHbV8Iڮs=f۹CTe)V&)`x-D"q^^bBMYխ|@qb\č d](. 5]ճ3Hkzb]}Lg" @ψ^? ؼm;ۛV$CjλlŦpZHP:frضn6/]`~Sd[n):Irtba_oenml\*wZ~%# ),T֦¯ G\h ;y7<O8j weqE6Zi>nBC5_=qf>?~&WIl{ <`PexIƸGJ,ܥˍf9K:Z\?f\O65G-zT,%@jE[P%plzKQ䜫!} 8l>s٬|`ZPs="G0g`غeP@`cS"*E uo΅6L{vsiF1T3HI5iBB)IV|EX_ۛ66MQ)|ZΟbJFr1oE.5UJ:CVǓ #:77`D ߬3EM5ȼ*ٱۀKThڟJN*׾ ~_1XH+EI*U-Ah!dvu4+i5Y"w5b.ŒG TR*6$\E7_)$*BSe1-*WvMuIY.ɶ{]''?/>.p弇,lSk#*~KTG:`g0ynRmx( } -9 &W,]EWX6n\@dE 2P"Ó8=VTO8Q:P* U]R|umܶ K1_?5(=!רQU8y6-6CS,YEERk򍓙47GU\^i[Y"/Zgj鰗_Ì {7Q;E (j>/ZϤP]mQ*`Ɏ!2nůe\LEQ$~Lx1KV[e"݊W̥xK{TܥlQ@: X"p/`Z9griSΟCeCXCr99r5#x~ē1׳2 A. ?Dž"x\ ;Gtfbl²ib 5-X7ޙ{X9{9c?# fmZY#sDFyx<)$Qn#zЪe;gcpL"!d* x-្%Q%A$= ko"UP̵{7@"744Ouꋖ~2}ֿXyRzE;l^›+20̀slɫOF־=m}I9,z?+7P$r f|EYס`dpnwBĄx0v`]ݚmCNfjp9Kb8%7_HNN1#BnΕ 'r S8t%eyZJ2.b46TrjT_VS3Lq'W/qpJT=aV>QÍWuMmkeTHger{.ڷk%UQS'{Iu4g7g\lr&-K.fgT@"Yn4qe#3ŕ 3ƒ=9oW!$y 9O{@둻(\~-"\(Qm7-"1PZʞ]CGqHp\8މӣr* >dkXO@&ICc'j|f߅Da O~s(Baj;F2k7X86/~E hlɯǍ.JLMCay`@UĻo{c'cXI-0+`U5ojB^nQVNⲇ{X$^ [ d^iy W~?>RB YiB4(XRj]՞'JVHKn2RKl:’57#=+4K).L{b^H.ɝ|L=t39©Crhqh3`ٸVq6<1?B;)G22%v =ad7pخ |v۠3 .qj'{ y B:4ʮ2ɔWdIag̡'s bBVlVSZc}-*d+ŒE!ZB;M,zRO1׼L_]g@Ի))1lT &ͽLS(^쾲b+ՒGj9fٛty%[OJyKvcDP(@t PGa"5^$'}rox0F%>ld0YmbT L|߻ S OkspX< AJ5-xUl>VOmf='pVĭn>hNok%T!LߏQOF08h-kp\T ##D,'hD{h%.69i7I$=KCS/*B덷)7hklNY-vj*6_f]Few)ޒkMVLN̿:`r#ɳ`(c3Fk @vpQQKaћ+8ėkwK@ ~Z9=)2'u`XWB ;>l/vD8 ƾ9mє \!)6eb0iɕaiՌꩯR{v+_Y+W|c#xCuq6fZT3njKzI`:ŕ-^ w { /D4ul \3 [2T~J&dtq]ȋHT&PnQ-kb.)j.*iۖϒ<拂 VzX:! YDyoYA aÀV3c _Xܲf+B ͚^.r̼`Y\rmw6/e\]dY,HWĭcp %phĉ%V\,X3!#vǕFtIe2z_Ęe-GOpQN2ۙtX} a^mt*]*)QJI-JJKQ% ,Z!y \8{'ORWMue$39&!e= .~Pf<E5щ\ !+qAtTS՜+Cj9$,\ʺQ^B@fsCoƋ|=y,#QʭqD?a]<n1[ 5.J(mQ|>tYJW]1X"Qċq֞.}.VEChS8Mb`/o;pd)tmcqYb9Y;Y>%".*sʅ4KnSl( Y: W ?Ww%J͆y6AbZ.~Zye5 ?}&O; ȡH!?NIa6ѿup 1H ~Bx"|$ (^FD#$ yT,-'8k(O|m cͿiRuj̞("S9+ƾ6oQ/[nՑjS@_3)Z(c bELp/KKQ|%'ToO*|Egb\Y:HYL@',RU1:T"R(ܢ~QoSY8WZ},`_mL #]U?Pwpn3G;P' WWOEi)ȶ2MޝlۣX JFxZI쯴I`&!hPd'L". `OF2[٘0NҡYkp>&*  O{/~Fn,S%8ӝY-@}9 \Hξ7XL6zxHMh zkfi&K3.ilbm_)撥œJV eiU[%zN=xO[Mwi憚>4LNK_wuC e4dE?n&wf`gH*jI.<,mZ`VV+?sMe"OYiިmi?P2L 2WQmc65#CԔdeSB-}2$BHM9SDfMbp3/OC2/%ߴqܨ' ؚ#$5ӵa/ۚSZ"t{8N>Fڭ%5-dj͢{\&;vigq9nNz̀AŒVÈm8 ϲrO]"(:9iAZ hZ~5aClڐ{(#@`4B`"K4X#}/RIG4KmP=kLe,ʹP;n,9VT!{ŌkA-.CR͠6{oP:/- 2-"OqݽqEȌ+'ߥ1Gͽ7w\{寘@պmIKasI%gLňḑeurXϝN(˝.46s0K]3L" k%+}']9T""W'k]@e5P`V6)@ʊ{y3DX(gؒ)%n ~Ifqsa9Wky^GcىQsFykJiFPuXC9d#) !Lt$3P,+)i< 5#M=pݚ5j*A$_cj>ep[Ô_0s52 @=;m. g&B73=ƑZhq0$ AXKK .n W&>1ca\\4nF' CS|`<5?2]C8ԑ\{xrLh9kPN>fMqXhѹ;Km\@" ;ʲfBz] &m]p͝YYĨjoI(8-7(tbPH&RC1,@K*-G,Y8we&^B;%:BEo$"㋜~i$Mb>e,5J>|e`_aH%S/XbM(vhp^`KVK[34KtG úT\a#3^ "i#(fЬc9.@MR L 8/8-iJ`jUQ\} 5cy(|"W/K RMKCe"ё±錻Db+)V3ɾ+(>+1f9.p0;Dn=q$s1ZfT-*'-'/K,Δoeie.;q&Ljak{2^PԪ&`i9oQ =-|n2Y>Es%աEsDDL|\FCI$ KܝTj%S%wGE#p+.uV&%W.JCFzz , \]} 11~GWqYпLLn&g=J;^oJ^Y¯RT6G<+a$fNdKv%1X[®E`-+eO !gQ &R $šR84er&8eLYJeʫ~EKEgNXtmr0^T&ZB4\4Y0e&pi,.}\Կ>`W?y/`}L*ɚiIPQ[.wCV \%"6&S{^E''VIEl#awܤJNұGG&C`ҞK@euD{(!+Y,ڑr"MAKUYsT+Fdԉ-Z:eVtFmbOMm*,œYT[T(@pYvJYn@5}2eY)8C ڢVJP+r@__O<4';3CnY&-ꠌqJ)[X$#>EH'(VR'ףʂ( S|loYPVQEs%Ũ{&BQR Y, Z*X͕_hR|&NC?T Q(p-zю \`&e~&46${֭dVSc tE=ttqҊ'ib5~TT;?JaY#&d$h09v(v_Sk2=%L?7`].4®K@럹OsdAQJj+AK(2UdG5^WG}o ?}ځ~aEi譮nrו/b-}^C*Kѡy'@W*dAt*^Mz*sɖC5>j"e꺎qhA"k[~,{StեL6'" $?Z*dhl%,j+7!I $PI& Y% kM=FCʁj\=Fo)k[Ie2lӁ<lj";ˡc9>=2?O{3:ir5L 4)E4I-@%ZgGP.XkTd},8 jYjWYbO|_ߟTb@S[5?_c-֬rZA#FrjS>& iEL i(K,E4,'U,듀^cا+TO(+%%@٥VP2LX!{Nן4.Ϻ,B_tOQ 엷05 N;G)F% RS}P*K|%k,TSX/X<ڕX,ZӘnJNMvNC4eՁǿ`W0?5_b+ 8|IENDB`PK!ezword/media/image9.emf=dKgV;+FЎ@cbZlH2ʑQ YƽF!Hy^㤐 Ĥ\ ZH3YI!C9%-z'[YI8qO9_/˟Տ..+~q?_Uv}O_^߸o^\!Gf_?|Կߖ-U?^.[}:j[o͋O~|T_;.oiv԰VЎs} S{vV?1\JLu@=b:jwUp_Q~?/qz.O\^?n.O*}Tp}\<:uL:S/u{@_Vlˀ/WU}s4Uݼ xZii{y_22ı/r k_辅5IOtK\}8`b@~}pࢺ,>>/OQ>/c@٩w}w <@w~UUĿJ{v{@H_۫Jӻ៧ $woX~7T߽a OUS]?s_ h5@@i߹Ҿ#Ҿsÿy+|=euv%|](@΅zwnWօREiUg_kڷ%%R}߾WK??+h7@}_7i߮y5jU}_/_|QWտ9oU[TշκVƹ/{r?實^9Pڋ4|~k?տTC 4L=Uð>|MJj)?\^dHrwߋ1NϟG<8y#pG<8y#pG<8y#pG<vr>=XV|OZϗIF@,,<1ݍݾ{îOr<%Cb brw{w^իQGOϗm@%泩 qͫP$^ջջ3u|^Xb6oo/@kLj=얳t||6o|{,IoH`H@|zWKy|ntsc_ݹlj_b6#b0PXx$f[A"z߬'H#a |x<p%޾|3ﶋYD&Ɛm͞fe#H" NYXQ]_%(XԐH,1O,]`g[5;CG@btgHdx# Xb9őHKWtj6X OE)x#"P 1ZN/1Oc%)ic pKFחOz7 p "ЫxhznDܱ^ȷ왌!0Ө^,S0;=bϭ>4,1nEPX"Ch!!Tdu\1n|9!!!AJ@r>$JN7aA5' p: HehvFZ,n|h)lV,4M5:gzc $m8^Y-,y*0_b%ᱚH,ӳ񉀛Xb6#h&8%"Ou _[`Al0ՈkDfٔ@ɛDac^1(Ah79gl"ѭ'8EK$#Lx$Ze m083u|sx8sbT1@aW \hX $>vcl7.6z:&\0ALmXbegBp겂ďoǚG({\ʒPQXb+o.m&떃e`-f9+y|B=A'G~}=Yzh8`NJIw1 Q2IeH8 T PBjOs5HPXTc6NXL}w92a3X0$MiM1*_ *m܇DۯfBD @b9Zt^ m:4u\u _,1e4eHXpD%Vv/!2 >%:0‚]1Xzh5}Ьlh,<:{~Hphe@" WMLYʷV]ʩH,a&f~bcأf 8@#ka M Ո-:Dظu< DrPgGx"! -`.fWa0=ug | epN'dZO` $ I* ̳^%"{a;[ġmS'bP43 a|zhH50ϰ1 q5K!%޷Pi3 q  ϒ0"?SZwKt`H DQ1bkS"g#6:q u`+<.c }<:fNnࡹu&@@9901_6 6t{T@b:`Ox#< |L8fO솓K"+7B7K@x K$GMiގʕ1$=?PKH-VqDl@{*`b,6-Y-: =:|+^GG{^Lm:#dA4f%ߠ a,Z І%:{# D_r& oP!F GΤ čbrlT.k2;pb/3 &ѱj $J*Lr7TO*L~cTHfur$bM]jqi+#ggu KSԌqa6@\L-g#!HPYG9 J8{9>Ur{Rallz?V~Fev#dd 1:,k\%BslM.Gl |# 49@B uƒx=3 z 5 6TlyILudlq!l; aq9 Fb Ii}٣jh7܏e!ᤨ $8DߐSJ 6W=0h|IC=?I߁Hq C]*0K%aeH?m:'%БZ\Jx@a_"EDʂ/`6̊{0 9sq3Fd5gn ,M>uU$ؠ#rQk*}o.LRAqU.L#BK#c<&Á)fG.EcF͌"9bl=I-U n;*k8 ~ LmwE- -$[}f8B)&ftύ`pEg2IH1ҒTk,@֪K),\ sed%AǔC1L=KT7d}weֆ57u4iHb# 6a­$e6!²hQgY.Lݩ!O"/9 ZNJ!c)+;[Onw7>n D+"rWYKDfrD {hU1덁OOy]x wmP`:i|pk*O`;H!)D[ m᧲2+Ђt2ͧZ+b\8B%F$`Hg'pŭLq,l_݁ױn3:ut![עy\izX֣C|8%GL;OЀf 8<8D`pKAW7@&YV N(x){ 'uR1=&M(d#x{?U9&dp&_b@-~/xЌnwvSug1y3*A)n0L:إLGO[ljU:TB/ 0H5u"[vˌmi_30c$.lbF2Zx; f $谋J>jt%[J5xLE`=SJ€<,H<죚IX2"`}fcn NfP T \P 茙)};K; -b/^ ! #055,xb9K;{8-b? N+By)՜]NY|I­6&6%Zm7է22.,A|;LDcqS}Ϟ*ɠC2pFѶ,C(fea f!!O|Epe]+##LL24h":BXWQk&9T_TP `m]_Z+T4|?6 0"N 5Mw!q!LI(=֪\fGdW5,z3?O|uM#2CNr:_f`N0cxo15ymCr_+ k!@c_ȡx/#̍MX]WWġ-7Pē:s!m=@vve(K$okl-)WP8UƟQe*<<]>WZexu)MAJGu~A'%*G .V;lAP1kr=+(/|ps Hpw$*o1+sRsG aADm7|A2B/Y( nk<*>Q]笈!ۓHԳ!D!Z6a ӼƢAu#GkD:-~F bI&ql}ȅ8E&޺\<Q01% 0F&O=8J1 +x0 1im BY+#!M3&v*UhC5:0iԻyCB~^8~Xs|PB{faDxr<іˡU7#IXL #&YDOBfrBŽ rb%t\Pp貃 I2d%*em:7 !}Kr7G$t_YKo$>̶X .3v˪=1m *h`B! T43eB.TCdEd [IYMPY:; wU&F0hܣȖznv/^` [qO:L[=b_۪m!p"Hqd%F>KVt!"M'TǹW DC$"Ū3{B@*Aj #aY:x:C=Dߚ=$EʾDGwxP!'_d^Rw|&+!G_:#8M H:]nh3 q.z 21yn8ʷ$30;:W!z*k,oHCO|`x6JW l0$_rH n0"\dckeWc S:$lb6U\VwH9VIgoiuxIKRs5F= lനGj|w, fO|.u/щj=-Ҍi8i"ɨhw]BJٻI-/!^E(tBJ'P@ȁE 5_) ockצ$m]9g7Xh蔵jx~? [=\J2Uqa6]-lj"| $-x&'GVh`(HSД`o30kpObJCӭ)DM΃WC\ @j 8X%,r׉U")1r=P|;;/~JO@.ZA@FE5c /y IxcAHٌpQ1b~ ?d I ^T!J$C&~\0l-2(Ƕ5@W lXNJ=.txxY,XZL,eO"՟<,Ye>x@-mE^E8C2 Dڎz@ aR`bb )s@)$ WMdZH#s0RbR7Kcyq\yO|mX a|Ws_Zh+&fc`@ 0 $ˮ;e?Y!oRIzt,Gl,Q JyxcieBD \= \7(XYZ/*깧 y9PLŌ)獨Inj YXIXtI&F\]X4c]/B%6 hA-(W_'pTp3Z8 +E#Z!!HPC?ߝ΋jǮD=n,S^PuxX񦼔pKV|ۀ ꣄"SFT)$ 0^򈜄7l|cH ~vȔ*q{ehxY\қw?{@DSb $=ҤJ~٩*@2a!V)4 [X@n""懢jRf" :GŁ1;n7{p6Ƈ͒kfUʔSϽ7.ՎnGF(  Ylʚt, @!hKbXCkQsWG<>DUB%kW&qw#:ziЪ*H:u=di/FV7FЋN̶,XQ/PNj*y(3# K H.$$ rQR=2 ">*%0WOl>LE ~Cҹr4CYb35oe^2:Ҟo 鱇&\#MlHkLY/f.(l>+"PCQRs:3Cr#ӳY!2/!Z]aʠcery#^q]_&|Y2< -6~`:uDuTXXvGQ $r'}r3?X[MZ`AXCDJj8c!a&gr"p8EaNMs72d#e#b2~ҎqP(6XauSdK s. 1*<8=T\ `8A}9bn~H IR>dV8Jv$=%f^Aɴa@۔cުBږ CHh<]f-)k~GzC,Q>Fj8S=դvV:LޘE5jÂXUKKȡ!^p2g`>V)7rX& v{p ;$F)#N6+e4O'L;۠2ᗲ M'K;8b͞L#@eCvŚc c3]5W ?eٞFuG܎o2w8^G W`ρ=m[F D`Ueic7R#Ht(UJȬ;3 ю3W _Γ+)KrOR Y1FfWSY2~'ԹݜX41NK7HBC_(@ <\zbaɸRl `9! @i&g0!p]~3I&<1KȊ@ 旰 ۭ295"* 1: q~5ڪ7妠i#Ly3PJ5ϡ^3i4[`Ie jb2%(oI>$'L!IlCLL>W&i|lfܾ}S5TYC>s Wt^X8 {2Hz&M7ZوuRĘ% }"Nk\Cn,+BaYof2m>9Ѻ-{Fk8VjxDrAOm+[U$\fm7hk⍵L16CR^ьI+bVƕSlc6ޣ OEz cEaA ۪/h5)gD}=T_ˇګ~k.xys^qom)ކ)RFkxg~3ϫ<Ay*˂em]G`2 b (q3X(m@``A+*7A(alH;Uy7j_Rz6Fa-y;˨d,=t4ʈotp1 x-d| 4 #/@WQLru 6*+<^:Z>zhJ0KQ2&;gr~CkY {E2 xD=j0o<҆q%!DE|U2KAZXhC3PfM˯Y v\9ea6yЬ`wX%H1|~Qc>}0F2q9,1X!Ѐ 2ʀ`# P^ ^K`5u]3ΞW2TzA >'~!C\oPj>3ƧAB~6 ս.Z_<1:FyUyTAkBI2K;R{$nO\^e NmCivD`QF^ӒE I.jnA.?ϗ5?w磷j9\|eK^VZ 0($ {0rc&!i-NCm?gԽ>gl&1Eg|C0`,;F9` *Ci%[:y':M>n I+/%GU?Fz~?C ڮb0raN-n&ZVf޺mzlo}t׸ #KޘII||VI֐fX4E>MaW ZGw٪03لD1 Qn1DHAQs{}ms ^S$9'xt<&@is0 4\Ul~-7(? A008`怡\:Ⱦ كHyث?!tuj9 q4GF-A/c4eYq )b,8(XCY\"Cu+Z,]stdQ}oODfKx/|Χx6I1i-\Ϗ)?{5Cm`@pَKXP1nExAO7A&8Btݙ3  fc8?;`` WLcp窾`'UF呜DRX }2;:Ԛ{y X(`ư1 ψo,S6v^3x%@fp8'qH%w1J#3|:ϾN輎i3wӁ6?TyTUյuJUiץ7U(U8]>{ퟷ_wt@T߾ft@ψ"o;JNP"Яw/wMw?y EGj#!f? 毦1tM%_EK*MXzo, n%_Pпog8nw%}W~_M;6B%0J`(QF %0J`(QF %0J`(QF %0J`vFxG* /g\oi_n} %օ':f뷯Yz1^I7?|닗0<)1K3IĻ7W_^ o^M.N/\U}v~.,ϧח^ @+Lb֋|zr?^K% U Xl (b~}[o˻MR^\]3I)*% @b1$녁ۮvjqsute?:,o9N'@"ě7^O-7"A"ΐ8; GɔyO$`a Tys(GĪDbeboxf%o_q{[>\]C"ī_n(D*tX"m6)X̦G OE)x#"P 1X/L%)ic pK&0RK*Kn8OՆGFznDܱ]ɷ<2}`QcZ`v~jwvK Kfӛ+8c!Ȑ )$,aHٽ~by|DWL|/K^2D.kAT| Kf"!F_g6X$ Aٍ jD@bG,юSmx1X`H ]216/cv,XHJ<\KS}/,u|&&X,7 `S]*Bb$— X05L5!"ϟI:_ev]Y/9P QMp@X؛.IJ85<8z=-?g:~ K(\{5^D@;„W@^?/PmE7o_>(,oy*CK^)YbZI/?ZF;tĚ:p3// bT1@a RhXs:1;rt;rk: uf㽰 KlLN]V5T(&nKG57{ۀeoخrJrvK78IQn4qOs'ƒq RRḿByEG?-HܣC0ľd87K~ k c, 00|튻 %6%kC£)MxN`}jƨD{\Onzr$w[х{Q0yXc\.|ĜIДͶ#sb  ؽ{?l3X ,RcLlX 1 O6{ʎx:1qw'_O  HD*FS-Ur*KXXY.CD5@0EqX`'{SB5co6nDuQ\/DgQ,14nK(ԁDLxy<&~"|)?:vESH@?&W *jJ7-۹!?* Kp qM&_@UW I]wTCDC#Zq,Al PB|im5W7k:@UB"傢/Dz%fZbw\D́w(8`dDbl8 H%j{,9E ?aAt/C ->@}{鏌#K06"/ Gt'z7< [12'>0#MX"CBc,QsHSϩ`C\G ں]oǕGj{\3 `G݈'zӛDb5 SZr)eά4Tr5d5d>%Q ]-/6)a 7EzHO VfD ٤* $ ?I* ,KE,y(16]3_AAoimucmٞ)[%Xug.pS0_ hb s x܈*^ )o v$@"GB3`Xܱbprs{sn6Nngn啥m:^GP]{k|w^]Wy} VJ-y*)P_I~eacCx)5 TID x ౞^Kaf|)\QG%;6Be u>$ri$u׷1qv*g 1?Gx%OE@c#I 1$uf"Ѹ΋T%#!ݝQJ019{ s'1#2 aM.ěՑK @ $n/ 6jn 2%LNRA6{3A25Dy<2FZ2`W _al@i$.!͒g2PGw Can|E@ EIzufr@`8PKM@EqJOiӃ (s K5 W`ױY5PFg 7[ ,Kd!FR}\{Of8tπa 8V\^01Oj NZ#':+pJ#X|[| s{P r uMݲ (rCltGDr$0-v\=Lr  F*N hO1@WL`%+%Q5Ca\Go|~^ W=r6¬$r9EVo5}$ڰASt$HKΤ!Pba#3iub#1N0\ C^-K$+, j8{abl83kIFMg:D4HOUw1o[0b2SaY݁Çxzdz,r\PƐ lїRSUyG<rJđ?~*;!-hϦ\kEKWBBĈ LtN)5{:Ȇȏ*<x>^G]@x/Hς:>!00^qx cLbY gu?Cg<*VS$ת)uCBV<~O,VS 6Ǥ uo P QcmPMg,/.R/ vzc7Up30726- W3~>B=^)Yc_0{ &PJ%%.[unٖu9j00@~t$~ ^h ko3_@IDa|1 < A}Ԩ'[J5xLE`=SJ˂w,H<죚IX"cQecfcn NfP T \P 肙9v`#w )[L 4^< CF`ajэK,xbƒ^Nk.X°dž|wJ5vSaV_QVhu 6ޛS S1KjA|(>뾤e@z1ϸ>jtgOpJa|ɠC2pEѶ,}(fea fyG>Ϣ  #1BVQk&/m*0Ҷ/e-* AN>9>6 0"N 5Mw!u!LI(=֪D3O{؃zM)1#ga]GLiS*Η4Z 1)5y4`m/ }FN`@^ B{an lºg%b%7F߄b A&Om--/:,j)?le[RIc9CVns_0c(8?vs[|Q]^ >1DDh,H&:Q::<@d fauHIݡq[RAepՖ%~Qn̊ҐK(2B._+yY2q<:䔦 :\yA'%*YxqcÃlVBZa& =_ Jsڴk\ou9\Vw+A;&u2? ;gEl}腽8E&c<Q01%mDpH^ɓ,G)fbE:GK;Um# Nz$B8=0^[G"&s y)TA?bǔre֯L;;P de NU~%Cx) ) 05Uem5'LT!]a&,dÀo{Fga\Xؠn3q]1 M9ٔ+ [eKՋۛ)/">tT8ɥ1$?Rtf/ vKք< Ja|WC38if. ЋV`l2{pEY9o+8 xpRmUxlQb押@xWje"]DMG!p+d2"$<욨|c6W=7?iKjCi B}Brv\خ eB"woxR{kƨˌ5ߟe"P<cOAEbAeZ7x Y6-3d C<*f'ATy(wv'"n A.A({F_!!zW. 㭁Ѫa/ʹGK/ƈ 1زa?–SQ~|a1&M˙7T !C1 =r<i*`#I,@X&24ÈI2* q'\ΣfrBŽ rbĨ:D.L QIq\e8`!;qBR YDIJvYԾSve٣fNY_YwzY|miK2<\Fv˪-CgbQeBBboGAHJ𔲲0_DeB.TCdEd p|6Bex4U #)sB#[R>l7O xɛ΂=G+l9[aؒΞjo2 #d=0|b2ݭ ?1 (6I\+RJ<%!D4E(V  T Te ˂Aa\$}kao^賠: ULn}-FqQ:D ^, $/Vx1IiV8|{M_0_Gb\Hso-ݐ4jxtZ5MNQ <?dȟ ୊QH[iqP{$S%{"Hl)+VY= ' 7 r`^Pn@Hx,LgrZkBU|e. ' ظ toCS1}(7@*۲h+a-i??ZO.[þG2@ Nc{xi\7 xxWc /u ).!.oCE^R$!LL2d A(dSPoG9Y%9eǚtQq[c dje)r>6zg?GfWoyl;,Z"tFYP_:$ J'p`V,V)&&9#eNP!*z?ts9'42#͒|<<;+㑯 P=jK M $ã7&AJ8>XM5T.ɢ&H_IVhI ^*)PO|(u"ę7u&Ks-Z9..%ߣ0߼AcRjFo+WyT=exb*Fܦ1oDMrS20j.Ĉ HX˩}I BFE+^SR[8*-$OY4ZN*;-H<=&xTq[{eA 0l=fUoK k HQY>J(r{;UnDM #%IxΧ8*0:znLVGjK^}Я%=u6LRn=F\?BHHW,Ɨ $c! jHG`:Bd 7i CjRf" :GŁ]1ۿ7{p6CnMYu|s2gzos!EkD=hVjti6eMt, @!hKbZc2_9WQ/]2iיK6-Vq'9!GpH$p]$Ko~yhRz9z ٖ+=I@2ex$@pY %%h쳐.)Aq*DiyᄇB)Ȭ"#n_t er@vT 6&Ш.!Zu91XbPCusg‚>|C.i4L-ّ֘>_c<zF_y"0?Hb:h)7":=*y ֶpQ0 s=T}-WHMs1z}S1.Dq^Gѝp9fqH +=b>nӨ5C(9G+jdhdIIb/mH*38b`@&XT`/8< Q`UQ$@R#oPx5ݶ X a` dnZS-5'U"s7BQf, =S ?YcDV}EyR7P}\?&Z:ۖ!窼jR\G'|[أ;wȐV9f-~e+ю*K $  |FCtH*pxO"by@J + H4B[^U  .# <#؃$Y KѝT*F`P`r0G=!4!ѝǸu6;!4gʐW:RcUEP2drN*ش9Ţ?C2'*2.K:6ٰ492FgأF]J`a! إ=~0j6RJ`Z)Q܈dUH fT!sH%0#a]DDO2`5sEePxNu6ʢaQ]=7XCS޵f$*hR\2#KNCYITcG[hFGceV ?H)l2 $A$Cï-7p+6_{ )sfʦ&nDzM}edU44Bdz^=^@ǢFK[FGӠk)$Pmd9v[UIXkQ0#SDf›{mzE S,KFlf'O=1Ob x J&4!c >1m?4 IR>dV8Jv$=%f^Aɴa@۔cU5-.#xh{fj8Î!~)۠4dNcfAlh |Ͳt}^)E1 ӱOXAf+2G}Qoyu%Nia)AJ`){bD-RB;be,jd(t؍ԯH@2 l$28ΌJUBByǗ$ De*6x;fy×cP0@`nb̮dNsq9j}ibnq jG4eXr!3Kƕb[lmC BH5>!]R$ L-xb&בN|Sc9i PYbg_7lh\RXSh+sc/4:ax;ߚVgx:[n :d<țlV*a>b{2lE[ޫ&%;(1Ey;LL!>ae Hb\j`,(6Hc39US *KKx8 =7pE5ukaX!i$fm@6"yfD21޳}yG>2"EX*qJ lVz{ʴDG C6_iFH-T!Ire[80mf)+C{6__ӋzL)/hd 1i>XL'BGƓ@T{AVDVt{YGl@9M9G $P}ݦ.W\z}qomu6&Sh3 IS <̨V xKBT> 6"$$mc7g2߬0CO^/a &uS-vIwG08pلFOx0(6C =v@9="sm38ϒ-CP!uTtG –wBa(lmشXef<^/[x B:y]Ðy?QLI^ًj? ${j `d yM`q1w$C#bDݰxc WĖ7&_m>0I" -u?ˏ-Y',=+H4>B3?T =0B7Q0+QQ7H c60#901NE3$rkۤ2]ѣX,S檨akwZoo V"kyRtQ-xCx)i{韢Ma " yA@|A !C:-[P{[bwHf],l8m?%&!8cU žKGB{z'.F^4x RqD `ؓ1wZ'd[79G_Ɓ`XwrX@T֥PJ:!_6u(߻=I\G~)9b1OrG !CQ/`(ÜZܻM UMilV{~|l Z57HȒ7fR0&_TR% =ԁuӘ$_) D]j !gvUXRO6+C Rjc6zCD ߱;犲ʀL!1GJAKkMb6<+jt t;t;?Z/? c|غ?3z;M c&m\8ͱ6λ~Bap1 xz$  H@$  H@$  H@$  H@$  H@ \6MsjYt2Y6 %)ElYB~PK!蒬word/media/image3.emf=+ݖ5HG3 `:tt5f%'$&s"谅:@lZujuBsgtgj{W_]^jծ]w׏]? _9+o31JW27l??_ O&'_?yBr"N¬ø~?/~&N8S~y6!og)ǿ1-e21#mOɍScCMDkE )SC=?94Pi9X/ҜiΏih~I9 9E5Uk.+4$)O\K~׌\?~Tiۈk-$Ǥ$e4Xr5W܊⚑'׏j mqʹ$ar5O8~\?~TI8踚On?ոU]Ӷ'׏jǤq5#?I*'Jx4'IJ%kR5!*?)I1IJRjI1~e"s5xJ4'-$y$\\?q 0*R}!I1Iz^9I1?s{~:7ṝ$a}Y <ү9_sKssV_-zxtE j_ exD0iɞ?5k @\r 5k @\r 5k @\^w$7v˥ޤ%B;k 8^M O|x3[ЇF?zaVY+(7_n#yՎ&?ВvGrtǏ7>{>z_>^ 槖\Gi8{- !G@(-d ;>^Kktt ).\N,@Kڱ1Q+ѭ hm@œ$ڣ ̠_]L^Ck@{V \86:phI Z 졻3}P hAM}t6gHY,,SHNv 6NlFt1-G/l~V_(B\/fd\-E1DGv~𐃿^. "3b|6a|:.4Ԝaj@W VrrA{`TέN뢮#=HҀjGxZ@[bC{p=C><Çk Z12/獀ƈÌ 9OiXOl"I&r^sСdS|/-NFr7Y.k_@gggjJDeZĩq ~Us_|NEg[1T}%zxx`}P;99dސ@Lܭô"Հv$ ʧ[8B,-V7WS pzV]__V+ qiyx(YeřV ,%}7q ⸚ˈq!߼׿mERsy=??b鑱\-+^b_m{8\-fJ#B4-6 kw,M*JJ4bV°a*z ο*/OnЋ7c~-v;PKB!mǯaB'P"׼(_mt@F(~MKU"'TN*_j9G1/k %9ZuVS^ø#iRخWKWrLUQ_n5=|jXN3ڬSEO_:ϲ/3W;,LTTʥL˄{w_?x hWZ/>'_ MIG bAmNUE!? ~\*91qk[{~WVڏb di/et얐O-_ޅb=28AֱJѝ|-Gb/WmeUCŭSc>#FѦj(svl8mNkW|y3#kwy=b5қ VX~rMR^Z Jz*ϿVE>Ri~-}s{j_\J"a$~~,458l/_FW_†6-':*)a)#G1(CIԨb%D G)Ew_cT+8cC)7H+b ,ruqwЦ3+}a%b֎_~Wu~i i=9Ҿ(}E%ZRJef S )s)6eF(.נּ>w戮ߨuGϿ v\ 1\v_9pٙ؟$X˘0"vE3=&_a9࿅t7o=aw;/{- ܁.(3 ePR琞VKekO|.4rŕKZq"+fh]~IK֝c*9,kߝ Mٙ!m ˵bA\"̫Oa\@alW>qf? p[ 3e 8*"s/cׇ)rHޱ]["爁)S3\[f %mH2S;38<H,S 2#!Yye`{2 8[js %jMC%3Ĝ1!ϿhƂŐ(Vbe-C$ZG9Af-qj<&q,]&8#u2ҀыW(&vML3Eˮe\R:kֶV|q!Z"(0ΧLP>i LBC- D~RNzT._hX/{[ {"@> j)"}JpA;PK|P88ڒ1b0{JO[I ze)J>ShqO>:!\m]?,8,/H8z| Cn7. ?A|RKYDŽ@KcDhcD4!G*F*FKj\&րX/a,dKCtj̉EW@>尸Iz_y'քY(iSŧLV cY7"˥={@X|`M_O尽^ZQ/Ub藟 U;hTKS1r:T4H;ۚN8§vw{esƌ|A-0ɴjfL"$mՂ+4z2h)a^yi9/ʗw~XT)䣳9B-e !Hȧ͓!uz^__OɡL?d}/Ml rp>i9Aۣy0pQ,`FWOiK8?hF֮ lEgfd-K3# ,-e^*Q+p0oX9/"B>u|P*STYBGA|k̅%S6p(/ .DlmiN`8vj1ĖduM"N#(OE ԗ~iYHEo[#׀c~`m2~+"X M-"J`E@~5.~h bt*AC>ȤF ly`2d1;鶠\dMDln>C-=;AO푚nPUڏ:᪨ZZ?[$| _02T?_c* mW$XgFg>.Uvđü!|Z&\U&mZܗfgj&j8wJVs6vcnq+ˍ# (č$|EJ) e|↑* qSǷ}a3iNJXlVqmt dC؆8>;g{Zxs}7xj1׻Au*t!.!dB ͘G|nTKfEFchc=u b!bȲPTsrI+qż8¼m+^:R8d\0"N&u`*AB>sQK,M&S~\| @Hl%^Y )_5ZG.|my`iH̄d!4σR\`-"c[pK8"i$H&O<,r 6|㰥%|nV<U3E E7*m!PB/EqH ga4Z& &d銱, J1 8V47ӯ+Z4nC1x4R lҳ483; _`-_9(4?~2`^Jc@T-\.q*k2ݭK`GTZBbe p_ 9 ӒV)2Y(`%,A4F!rH~aY {yQlOK_DXmJ4˦qJT&I#S4Rl;&䷭W?Y|En~b48Jeg]h-RI>qh{)"b$EDq0&#T΀h >/:k_jזN9`4O\ʂb5uec,ʡL(?'vW/5َ!-#--yQKjA" E\N'#5x7~qZ|i4(|N4д?/t ZoU%WsbYr7Z_Pb'ǩ=[p+G;5%l2NNM._g*hh%جɉ.-߼|eťο™W֯ap_F7g@ɖ*qG1mě J >Ye|%3ŏϿ_A/T|4#mMMkuSk~5~ ?+, _ZLvV_V^Oj Y.|OS]|Ud~o<'L<0W >rnϵt:+`_}Mfѧ"fgQDYDO-|!eΡ{z:Yo>38>>빰[yJrGѲ~1v%[pCNQT?#;P#`JW0,h6XOĖn^:d4+v~.j( 墱8Y!r{s=)u+ kĭ8kJc.^C=aPxOa={q4gUr-\ t.sdYn85eu1M3/)W֯>uV#W<\TliZ\L2-@YU (d bV7ݸQK4b*AցL߮0> $­j¼|ESI>LkDZD|:梄Zaj-NYq`/~Y b:pϖV09FkrYvME)x)A9x|bLi.V]xdrߋcRH4>j.Ljd)%"_f~>YamA]jgeBmEh|l-u xc[8Db,"@OӤy4m‡2[cq9YRcJ@Ju LEjK 儸?mo٬_ +| Y\Ks9ӐBj7#jкf?=^кl_i\ɔ 1Zod |,ge*rݮ.B+0ZOʄ͢ZGD9񼍾$}r!_dim;ο Ƭ t(#bB%Bߌ͵krnB9 ײəB\b+#ctkM7NӯG/Rtҗ-ObL.bO~Łq)۸v#MsP/)W<7K\C[*47חB|cm.h~1`]ڬ$PJ/CQ|l+P"ҷ+ S9X\$,SGڵpEqh;2Gh$.}Ɔ녁9>)bF|AZ7AEA? ť5_;oYyyЯKb\%,~ҧV䋯>6ϼbk{8LŖX|/4 9L,gkciyxu{a֕GN/u V RX* 4/Yiү[[X+WSQ:TrIW p%!rR#3[Ҳt-+vR-Je[ѯwX:%.ٔ2E~/ K#EvEFNF^tUʩ-o\ߞ7k ڝsH98c_A$OmXWB>#_{Ͽ'EOFKPpU զb>:Η0k H@5ԴEC֯>BE0T`"׹ycTHfי]ՈOi!3tl>9JĪ ._}T;]$R&[x*ƍƓμb 4`T}u.pqFrϰ`μڀP*WM{m@pmkc9VM O 4rQjS1|ո+(OpE W%h},6Xl"v+gƽ_Wrw*Agg,/iVj~5ߏ1op~m*}償Y>jD̬|Z ,K45vUM k^zeȫa+;]}(JBG~ظ?x0/& _As݀ >fCbYykaD.x1 }.Tpٰy5/DoGb'v^Lq WNo0KB: >864HԛӻYh?嗥!+*oINwt7%D(+ږt$TdJwǏ|h?\Qwl)>{(k^G8Mt̍"$$LoM CV>|%eֿj4!Ͽnň~O{C\i]xנ\[pG7Ly9]ύݡ^^L_؆dKJ/կV%!%.^x ޻Zz׼roFڼme8ҹ-bY}Rw2Yں{˕7WLjWbYVL\:; 1Y4&j&–"G:mW72w8r\b4Ў,iұ˽8h6ڦFO9_Qȉ1 3|Õ9obbW `w>/\q˗G^/O93=ץ D]l<="~dԸږ&Զe–߱ɼ@[ \;'WWd zpip OYgiٖ8dl91Vn}$o^ kˑ8X?m`R_q_;*e{zq16>hMwyj ۄJg#@wy|R;/M+'5--E a9f'+k[G {V}G`; D$bbZCI_NxS/Wb|I؛$岮aJ(sťà])\LGme63m_T#sr Xb_%rvv+/OB/?鿭$_@~֯>¥!G%p< Al+5O|ɣg-UfT 5gK*v+;5pDM6 "1B0/5?dٛ|fGsʓ@Dj!Fic-hY;[ޛɯN B"@(~ .&e/_4rɆ-*O+*6@j_}ugCاk p($V||<~p3/-PEOd5Z_اs VdW끖_Фw:?q<`U,W >!kt~FV?wN>O徕ͽp6R=բaf^.H\ŏ}?2\֯>:C}w9,8HA:8}zX>==}97XF?>\Gه'a})oY'Kjl<~9Hr{ï%qcG6iW"Ȃ/z#1ٛ]b=}"xNޜ>iQ\~^>11Päˤ'uX&W>fhW1NMŤe#[0|nV~io7[@1VY G 1VgA)bJRk"K]JUdpU75ZM:||ݎ[1۪4d="-SkN\ w$J9)ia,^5[@ vb0{K%O[eR}jŇ׬%fjL2֚A|p>:둊_OV/U .&_%)p (Mtĸ1)L_ "&CD& \8DwGY*ɓQmE hoZ~]nVX1Yz[N!Km`e5Yx q5Ni[9U~ 0Y_Yvj|uyNkNj R"+YzVj8;rĄ)] V|a\H@)ƭiMYײo@J֍/ ׳45IJ~/-{kl;,T{-Ԑa6:2ī6Bd |j͇2"/KCYzʗīR&M99V|% ]WAa .}lI5Ga_[}$̰\X6rW?=NLR+3w{'z.r:]4 #dTi*(.nwt73J7M~dI0:W^s~GTb/pFhW%/b4UlhsWKfpEx#b Y ڃŔ~qS 3}x5Z4?J5τ`] GqCLŅUwĊ C9Ypf[v4_=A~|>ssݶ-. 5Ќ˩Ek6%97O减p_]JB1F( IQ<,9V1b9)u#P!Z@)Z 9c MŸ(ӲyܦFUxvwsRdc/b}ۻW.&]h޳nrRD%h&d(!@}Ue-\4vWRxeHňWZ'_a@ľƁ}wpƗEт+Y*X#0,hajGZ)_컶%軮ƕSi>2cW+w,@-/,ӴS1❑0T Pl66W KZZXbU;\K); ͛ yE< VFᐳ**P.M\__&V)b'E{>j?/|5Z6JtqD~O}E--c+jg6c1wZŁS#BnUB-|r+_? .tV\Ys-#]3b UϵQ5ًfc ]bF_S!:@ pb"YE6#$6p6poEx($UH+r5(m;;w!"ؕ1UXj+YN^k:^_$J-~1Ô@c]^W:7W$ :&)8m1 Q1\OU,&GY [>}_)\D?c~qTdߵ Ю4o_I(o3=>i!3y ;E[21 4젋a<@b/~HmAGC9;Y }L}E^h=6E,՜ PQN߃#&*8(aW+Ū mOYk`|e 0PV\ͺ]"ZW͊2'SFU_XjkCEK+ u`$ЬxP1P;듷m$ 4س_py|e5W+V+uVi¼bz)..I;Xao bWɀ1TL#Ҹ7N7XV\~cF/+i^J*ŮkYzX #-r|d}̱#<̒؎ۿ0IxAhjtnL->uw)"᎓_+/F/p1Bc4855YȯX&7E=m_ޢ,CD~6\L-l`h)0䧾"ۭցa4ce ^=_KK \Yzf#b:1z+?V#v/+ǪEW}a_t&6ܪX}>V|SYWfYwk!]1\YzX#\ mtN遶\[HbiH̵ߒ2Q݂Y>=l$M½CzMqqw2&tJ-.#I ,DСS7 6\- ;_]ssz}k{̩ꪞUwJiuߴ'6i:lK{~E~m#>N3z_>iy_q;Yؐ[ CrxPـ+!@|EJ "OJj.ɇXfNJc[Ϳy7lŚ7U_a(彶wxsr}~:j/]ۂzJu`w+?ط>:ײ_mʬ_aE_U%GXWRJP2T;7/{hll/J?ʎT\| E)?cXum\w_B|#RGZRj&5+)d+ozZ7)%yQӗk~ Eg6WW(*D|wjd;qk$,T hT~:JԱx˯MR+JW"H}E}W;K%m5z:zO9_?]z_BT1"=c "mR1^XS\5\gEJSd/ccߺoƏPնE>#_H]D*7JZFEKCz voݽVpE1c p-\KY^\O2WUXѯ0\ius%ľ8b|YxgFOY8הoXyJ|#k& U S~SvgႯgE>#>Ky __Gl&aھL޿]wjV)>Ac%V(2TI~RfaŚ":PbT]ظz֕K6n89,4?r| zp"bϧ߮wÇhPJW*#Vkɾ6_oh6cL>@ ݨݱs#8 n콝Zi͋Q n|x>.ی *nVf1.n,O-imE~kh7hެ}HoW/$̷7Y@n i.֯n->= G/։{{:xfZfu 7m}Uѯ ._'?gGo JfE3>U?\Gm @)W|gƦ dKђyWƭiY1|\mk%isߗnB!vvoam2)p[v*.]{+"͊6nR=/]_LZ4 B.޸K EŤhѮn鴿භv;}8\u+E3\hҥeP7W4)]eLJѢ5t@JH~y}"V:0*ku?/ӯˣW6+ZZQ7ٚu"7wAʕ&uM}\E!+Vx|땫R1C k :-KLt{)X~UI 7+ZTLZ^]\ˀ{G4lC("Ru:k~Iˊ~uF_Gl%k i{{0[Rn1 9Ʉz[kU д![]g[AW^ k7W`hhmkIeK@E/nra(ex~v^znmuFpvsR%W.SJ*L~P4˸R8Jz 7gU됄l(L* '*]3 [*f-O|cuu*OVAgCD>[(ZBϮT8[}̮On,RX_? +ӯhFiee\nNNa'UFYnU>(9qN+M V <ubl/r+eu0H6x:?bn^;tin{Q7NܜLް+e EE|K}C/lR4E7s-(uuY߿~Ym{.Jm5=! ]e-&kpW'LM 7G̙ ;lp+tY[A\<_0x0?,uB6u_\lfm èz6mMѢϊVS7ZFik ];͢vne"ս4Ȋ~m{)_B .!vlE .u:\P戹E!j-­6nm1|H/S7+⥧ECƽ#f1|~U*wnWg_Ǹ-ZmvKGe^:ƅ[]()ٚU 7Wz6Gѯs` EiZ9P kRĀrdQ.ME¢%_Zzu굆X NpBWR7nMnnn|iѯAAǣԬ+WUla=u{:{-#暕pu] *nDP7WJݤkm u3EuBQ׬.eAlץ|פW 7Vd NՍf%mCn]&Ьho5҉)ҸE2,W[Ŋ~ :FZbm5'u{rIX-R30hU˿,Z`:3ITla?\mA-_Z~_m/[] E&'?Wm긑,e9I4!cpMʯt+5)1MEͧQ+g'懋7o$_j+טNmvVqn)虊I*uiVGIKݢeܢHˤnAKׂn|_F|] p*k]ܕ)UnEE~MtBm*ԭR4Vsh*VxlaĖƨX_ kMLk7׸|r%]kI~=%Xe+m$kKݸ 2[䛮fM&][AzaTIZr//V7o$_믿kL|@/jo`%cE\/MlX%EU+v}CO~ZѯmX>_.=?qr͢_XX]݂% (Vmz`%N--ukfY>?)m6Èv5Fu.N;eÑ!TlT6(Btz7)ZPl_b+c%E6K= _{^]YWT3(Cg5}V+;".s~EXK*h?Boa0믶rkz\B[Z- FW`UFP7DE{HWT_k%wZZq.p8;q UyzebE_fܘrZسki)ZT+5r_n7_FePW[yU%.m@#L㕊YQ*4Z9J_Ϸv+2%_*Vk?~pQ_#W^]fV*)Z(j*EӥtO*&jyT,m1"Eɺ}C/CC.ULԬ+Wtu;q=v@[ѯus-㬿FQ uY3ʊhz-1nbMKնE}#Q_RfBCPĺN[㝺f\܇" 0\~N:\Bi;v٧nAן:x$_^6*?)4֬kV&89:~풃] װ"\b+xUayǡԱi똤>_ѷij&vX5TסAYa(=KD,Uik299E Wu`ޕW?,ґObR4ү+VЬR`ަH ط/iVZ'?>Èr5~ՆKŅNYE~e9r?Wf8_! E!_D%YkRiukeSk;#Մm=\ tXT{R1?$˕K3Fvp>E\|K:nFT1gU18!*Vk; #v&+GUNZ&>Fʔ;pQzQ K0]Sϧb+ZQVklNz#kk+/Xѯ֎e)__k\=B*xW:(xWy+Emh}ϯ g⊀:W~aJ>SIJ/m.Jc+9-KŬTQ(RRov^F`$_{[UӼ62: *"&w._#U [d)_\ۡieRIŵb{pnbi57[Ym90b[~:])Q+Mg.J=.U,~GkyFW Q5Qw뷕+*ڶUүy+O~ -쇯Bb aoʸr﫹aT:,B,)9łsɜkn)/ԯ<9,/0\cuq}pc gm[qhb֯Y)Ks#&QRYA00HmE䁫c%ýN+%׼ƨX3.FU;*V\V_[N}57n_y^)uَR[ҭeOja.E6ݮצ+9j篯bq#T;TS"hEjk$_;Z٧tOVjUؽ[GŢ~i*/ Rvz{I}΃Eߥ$YR1锬t߇ @+WsÈp: g!%-/0\j+yT>-努7bFfi/Ȋp/Kscz|mMֆ}lnoE| ýNuzzz;=OOegӇi}{/ԣ9#}4;I{^IWx03זS_ #v||bg迍}~X/j۾GR<;opX nݟG_w[۲HNF2V [k_@lavQ ɧ祖 N,EcTR.T{fﱭ]4&WdCSmCS!,PєQŊ~u5KZfp)}XSCa^nhmkkI߆@Y݇J52\`4J$"5R+KՀ#+_, [/B j?RKHhӥu.EM_Zl9?YvQ Rb|:ca񓓓l5"Khs)tp@[ J*M{_l%^( hJF (fT3ljO a \{a't *5଄;-,Ec{F,9ܨt۱4"JMqsB'Po3&crjK-?y*wZQRv V/Nv{b[cqԉX_0"RK/P@KѪNh$Ǘ E34Mv+%4TRK2/ JÓj0F)B* %%CSC؅{6 \Lôdy%4V},EOѬ1 r51;jk a}0%O2>S14(yXoxWp9ٿQ:_Uk=Y6:pNQUgcTԫޮD]ԪwvQkm:kNkoUO2>1A/SG#΍82}u~oUPJi5S>kY'@ɟqd)qd䷪t,0ukO[XƧFQ%JiƬ(S'~sOo##U̟kT'@mhI,{RNJOX*]VZZUFar6e|0ʯ ?ii[z)\2>qyK׆ϟUivZ͔| GmcSwܷӪ?쫣?6t܏W:W{;_4v1YzCstu{`Vݵپ7jGo ciG9heU?Z\OOdjyVF@2e(#PF@2e(#PF@2eVvް'Riv` hs J~F`G hlj?N*TJgQNK0)S?#ie_gy9˲~>zJ,Tu䏴#!\+/S<a'V?RmJv_$pPHRK\GHD+ \zk>^ʔ#;zRL&6')ik_j `H^ԯdǾGe "8?8^jV|J],mnHN5ϧ|j;!1MN?л"D劾]^\ٮlY4G{\z>ψ\(VLS6X[./wdT1(zf "aJrp5S&.[-ԑ$ՀnmGjo􈾇X3C a iaYc_w/F@ca15@FSr<}xw7WrU@ct輲@)N/uH|>n:55[jqTKd{}u{Ԏz_K3ƇLG [/5VT1 G2?O85N^۷o?h^Ŧ3>6DM:bhxƯ_ꑃar;+N åRz)2zH68lF;^E U@%_-l/JV~ 1'{eINO2zzz"ө^c>)DGTˠD \Ǐn_ɻˋTF /MOO!kU?~vXJŧ 5~_)5XW,O?𖑫[|[QYԏf!=&u_yvW/P."^x羫8 ^/_BNtXtg}~-R9^߿zJU/3[q*M\ `E_h#wqػ`7~52s?5*6䴜J%[թ`".P~E:U^JJ1\k+]ELsWm\S;j/E]I- fm/K52}2o#~ULW9kgd#7=cW ;2`o^>}/[%܁'.t(3eP䐙U?;S_n@>'4̥_?Mc[v)g/9v^ԡ#obulξ&ы+EJcd2i=?=}^R:K{m5_E- iSjRۧP\ߏ=j"~Mi<>|Ka]n1&+D .߁j$ԠS"y|| ?RJy|\Q⫿Ą ő"3*p5i}4W3;VGG>$2ê} jH{d_"@`g_}hbwMtP/F{/S 8+r'/ae1?|dq y^J#%/rЁT:,u:qn~ l! 6_\=Rr0'6s;hJ&`D8݅Nz_y'ӎ34O*K؈v%PXǩ:^o-irK% 0༮b #ƀtXRșP:gʼ;[_#Qmz`/7j*JOY߀ɏp>-\_}/ڗW~yR2zRd9Nw͓cMD}ZmrG!ׯz. rDCK|2:=҃aLHx",I6,ٮ "OY˒9='HoA-zг+ F ?_}+ډIq@f'7(UJ/V]Rk KM|lØ.Ia"Hx)N:YĩjN 'Z*E65S$SE vKj׋I~/[ȀmyG@c~]vD8[ :DV" %԰@~zfhѯ#6Hg#ޱ5 ,"?:~R.6\`B҉C(mlQ_]PQvKZ/?^ ֧_"JmWV) NfTi$N{AOꇗ˅fnT<[b|EU#{7?",'#.g ܷBwQ}˽/;F@oY~srghALM01{3lA# ~-N3?$խ};E# kݜ%JxWMlŷOȴꯐH<_0:E(2sB%dm'e9~_6kaዏST`9b.Fs.sQKX.E %.$+QrΨPEG 4@0oԧIcv'^D8$,\6|[RF}9Xn۰ 'v7[^E1~y~-Dw-b>CEv*eOŋ%s3HBik$9X 6&su oZj<6e% 9:8@;9 DtW}{m Xۛ+tG {d/Bk&s 9N:_UQ6_yFz$6&d|3㕒 X J yA|V4{|7ӯW44nC i|zAdfEkt8əg: _`-_uP4q߆}irǪ_RUPRJK`G ZBQކOY."y|z>d^+Tp~i-PGwSb)$'sWs<ס a_>˳bgv 9M˴F4GJ)6S*h@exƑPxLZC-/=_d),K٢W _VCn#XԊ8Q9 cjrj ŗEH`*H,x_Ljap 9|۫3v|rz>_:#E8t$~ 4v33 ߶K3CS_Jfddm SjY\Bd"_-žOO(4C˔ń~I#'ޮ??b%G]~K|W~?{yBZv z,=#}hom WE7([R.>?Y9~|sf dzN5?\Q_1vE_6-!"|MyNOJ4`mEfg Ι KGS~"ֻN;d5+:E>)\|*ꬡʖEv0B3פ7`Lֈr%|r \$sṙk28Ê;U^܇[f9T}@[~u ^ pw.{es#Y:fM9~e72%89O )2慫Wt\uKS^d bUVݸPKcR7 3PJS~ $¥j*}siI}ZnR`KL,u؋F1믬YqH2sY 2bZld"V[|+t `W19ph[ӯI;1U. E&_9^p?E0L/vEb $?Hދj<^™JUԤHn?Ј<|E͊~Y}.тX~] ! 6ښ|f-5&xy5-]5D2bt46!­~wBF r Wۑ|j&bѵF/w⧹/4lѯK> Y 9l|Hy~JM__쯖#dV:d,ԘY}Ɵ]^]}耯v\iAiZAϭ7 Va0ҲF:G I]ԯEuxʑNܷ7d.Y=\dh_C2kS̆: DGf;[ԙ W"X$"X$[EVV^Y;3gw3&Ko.OdٗR fm7YO` I&hY w9qg)ta Fk Prv-[ y:i`y^-2ܣ -u>Cgpɿb>}R?:s߹Gſ\AW\k Rǹ/߬E<@oדi#XI \x_|_V^ƌl<(/%b&E0nb7?h"1bOf+O[/]|4_ ÀI\mt>pQ5fdШP=uڵ psN09?˯m-'N_iglT~?VH0&_]`yrqTabS%(c%.pDvTc Mmw[oطklf9xUbٿȩ8,Ĺ0>D<?D]?*V^=Vɓswe _6kK|+?MŏWEWwLB%r#[^V[kCِ}T.JD0y M~pQcʘEϰ/aLʖ9Nz`B1OlS_ˆcMi_!# + _]`\,1z*̇_n1+5Xx>狘Twdx.}@MPx#W!|aL!Р6fm^x2v.n P+4 -揣|VM@Yg"<4&"kmU(:Oܯr@SeqcL#߷.v?U;ޥ`[.fW ]j)nm0A$30;~Ç7W׏N{HbE%|r5}Bo mJ: } %_ڎ'(Q6u`0\?=կ^ tx:Xci< _+Xp1v^o"{e%h W?-R\+| V W``J}>]y]9J>9u|e_l4g1FɃ#B#⿧^_?F=MZ B\ C2T*y:n8m>?BqFu= +)E{mV/zVٿjO1߰pq|ZOQONم)' &*7(/bAYAl -rpڷF^h=Ūp> a<)>~Åaؿ ;*1QP)k&Qp[k"D'1 Tciڷ7D\kIhp}'*>&-_Ҽ8dOW 1:$:ғv)h◥AU*E8G o*1UL+8A@ ev`#WɝF1lK _!ƍ`akRxq;'!j[{#pX"&5⼪B^EjվvH*/Xܥ7N*> (n)'B+,9k˦|uk彥Ѱ,\q%\mJKnH$$Ĩt Pj"R/WVܦwdNv.p-$OqīJ_DkKԻKݖkא~Z !@:UvZwbĦOܸJ'܀qe4j7x?2˶yjw"[LGKG)OO j?[B*s{;vZ `\ECX]m2Rx^Л \Ī"S'ʹeS0 NGk3k=?yM#}׾?֞`t_v%_Do>YàoI &SmHM8E_;xBG-Ųu_8敏n5;NЀKݏd_] 0Nq/ >$p5/Vߪ.Sa~RGj'.uP?WІa.SCV۸_KPcvxJ:ní_ 1Ƒ}_vvFj+1#sPߵME߇{djuc+d78| p!-֚t2G⏗Fb?W .dIY wp5V4İTbWzG'J `2 woJ _Et[G6T"Vu:bk_/ e._/>81HT-DCm&OA)Aީij0+4mtVB1izYSɌļ$.F/06 bI׏L.0ٿadX#P,) GI*7[̻ōfxӌfEdĿT|gy\z%_S\&xvCyDQ>gwCk^GHJLF@ :21Ykh6摬N>/*_̣L:WT| E$L T3^&=`ݸc|/?Wq8$V0KZyRj"PUtX0+e\Q 2E#АLMJ!B3jL .f"S*Eq/BԤ_뗀VF _C| KI?nT@# :/!ϸ)djUps Êj~A6'+19w658p>@dŚspqaRMp!p>bJ+>i*XaJ&dq+fjA#b."&^X3q~*O_xy-M_]cjGYk$O "$'\ԠMB1i_Pa_UOb^ huӹ!C \|qEף 2-"t'=s6*# \|Z fU O"Zo[=a႒./:}ߏbU~i z%~*pMBf#Q3ȀSb'qXi}C*=wcl Ŀ+U ]s>ET|(;A☙Z= +퉕 \b@62\t7a-ˀZĀC/)^ Z /%>ӿp`^Co\t=BBiKP ը!Չxj^ oMX"22.&g>U*8BSM\͈BP>/];q8,\|T@O_z6ơ=cQuVԞ N=JEE7r"fcLNI¥ɘ27$hڦ44K%u? pQIYgI됂o߆qJG/U3SRm2I1<I`qZAX *d0mbl:bY[3R1ٿH+ "k8J61!bQơ=VFBƢD, -15m+pYD.Gbhi./) IES*>3`jc@cھ&6b$l„(L~ުOJjFB1ʗ_-8sKƇ+t(5eʸ%Y*fbšbUj ip#P-έ F)cCoJu? U_c)ImbsKy!@RAjcmI* m[Mn@7\9X}9ȢZ_ ν| k,b/t}.6q܈TD4å!,P՘|yIuh1b{%HYhs0>}po7k,| >P8Z Pv"b6M,ƌ[1U\(^x;/ӹX7/+~(DnJ@1VЩ,P6;)&\CK Sus\+ಱª61X. p|8y4'}P{!Ɔ1\p|5=P l`^/x9dłaYTbV( _P@bp1䓙@bh|a.{ ^^^j5WӼu|rS׽b+ JLl@kvy+ABm l\bG@\EYň! phG؟mUT }(Y%t6㘙fEϗ 4,OC{W {EjD9űf Tp+[sX,W\v U!3X@*sT,,lu8&ژsM"åF+*du,m/>|BB+T_gND+cfT+TMǜ[XfYC SNTbfw긟Կ@+VhEp~L. G|A8xq؎8f(AhBI NSf\ Ė.㭘@GL8^+ >ÿc|G WeA?Yh̜ӱlڽҙ@O&Iئ" 4n/Kć_Ρ W簰&p J49SxXC35FF%,6%L?"FJwU+ʑOq:A '$((f}~ݠHyl̹_$91&xZ9E1Tl?d9wd (]&x}0g ﱝ{3N)?cf.еD T6 =ϚebCoIɍΑ&\PqBpPz$F1sq#D1=qc?_(+)$gMZV*¡fb/$\Vq?l?m>s~cfXmbOLb%/D@WFL ˪"m4, 2CspY"h%.xBg(u7ݦ9}%,t3mCzW-<[Q^|5F 6 E*qh`]"b%Oc>edłaY $ -+]+(l6e0ƒ|uݶC8P__ /v z4tR>._׸y~+m☙ )YUODcfާkJ\Kտn1( de.1_`űJ}LܤƙaxeI 8Eb"u}y1p~=oy-_H*a/8_ڣ@eOCqjvs<L:Q1V13uRF9L[+^[J:5o_:9C:WNY 1 ʧ,bmbbŖ1(V\|9&n0IT p+c<-DCb\sE'Tm!G(,\ٿ:X-\LQ }p-T㘙HёaERc~K2tXVcGK{K13-U_)V) p?Sў7w;f;=?dbl,RŖ T)fF^`s Ӳ"NJ-cl+q=J^ 5o +_]2XK^_6F?_87\I?]3.D]h`Z26;c% T+vZÝ_J jTs4 6+QTk'qL h^s}_gP!W.ō6&qUQ,`*㖊(-ub,he^l+L|uGGS=+M~l- \6n 7E_J 8IX9$Y\UUFQ\QV$J3{ 'SM/!|}3.e|,0րOۨ@ĉ.1OĪqդs512^oX˾G  !=+_] "z/KB[ULWr^Њ|=21&nlebh*#.Y$ĨF e EpV"bzp?@1XDҼ8d,Xir"lx07)uʝ, f"> __LbaGK1ߒA+bEb%Jm1TUtWLdk($9""Yu.j^;8u dY6l*EOTu BǸ? PV Z-,xgce>R3mp7nH`o}K#&׬ĿbvoPX5 CQUH5fC 1Q x.UbS*Įpe:s4\+׬ Q4VAlqϥa.-R3*=N0cb+.x\3T!eeŠ "\^\q1_>F _m J1{?fbJGXL>7+fUs'2%c RD8vf"n:s|᰾M? ,oO:\DSkV!ePme,ѿTHR$- 9cm_D̪MX k=tJ (.VR7b6&hi U&+U8HMoT@ qk&cV[P W3==ȗ_\p1&Ye=nZq{}FYPw)q]GG[/׿'Jj07d22WwCbcPnw:%%)qpêM.C/|lqyN#ꯧ"𣸹XsZ%vpbe{ĀedtrcALt4fWT ~oXB}NÅR=_MZ5z\2k/nnWTqSĔ)kȪ) Zה# Y?sq1zY%G88ZkeV+Sۭ\lMlK/Ɗ,y=>KK/Ez28|%p m6 \LS qajU #[V@V #f)MrWż4}9{iĤwr^ѻ͆_ԑm^}fUq+j7}h,Kʱzʾ`Z5.У擉ߨ<ﶂ4\/W&}jXQ\.ZYGs1L.ըXSGx~5MA~K/>u7Hp+F Te.V`X_vL1,c >j7dB\w7ZX|M=n̨&܍v5 #nd9ڭRSj[qɹ\\m-|\}ͩݜ5 ʱG_3N@u~uWڿO}%8K_e5Z?VT]̵4IuV[5\_qe4~ͭeݼy7p{~~OG[=h}عyf3V.hO`TrH26<;ڇL:ګ,\ŲA~WsT[th͐%f٘j^R*t|M2Pʽߗ/e_wFͧU׏T^޹XYåܻcbL2M1q:Y_)t_v{. sSղs7лXS\hfVչ0 9杋)n X,bĐuONNvK~E48]ŸsL^1_֩3nЄ_{.wS)Yg5jshiSLfJt7uX_f''gl;o[\ռGP\Eէܚ^6|JMc!b3MÅiC(]Fq6^:8 q_wcnם/wƣO쟇 'QL\Vn?p#59ֺ/R]TOu_^o_r5o;ر9t#qBrd/0-V/bٿ )OÅKK\c &ә;/ q>xJ2-[Xy5B鄋T_q@uoVNA[+/0ՌU^L+nY|EϪhS/X&=W hr1lW^4/BDr.{_@܄kR\bWSk!/@ ݹ-Ce~NH st_\:12Eb&/]8׽/ w3[bp~4.;H#v+=P.V_2y/ھi0>P@z4.2fhspeejۧS|ݴX@}.7aq}9/=q-d!.lΣd&睽bug /\6uNu~~f(#gĝlЃߧ-V1Dmpa/ֵs6wr\L2J~? c-#Ҏef˔Jg-\௴-_-\=s?՗2Lj矰b <-|v,0[K4?bѿbl)|4!eI5pW" ._N}١9DNBz kp d}v&EUJMVQ*kUP569,4yqh>w,S6+]g—^7Ŧ29ZJ12Lu[**4qw F1l%mM&[By^5.dh+/G<Y7cn\nڜpp#LݎMŏ@qF5Ljg%~p ZQYi`C׀?WBʹlQ%gzcY颅bԣ# I_Mŋ ԝ+Њyed .Z'܂g0dPYpN;qh|^_͇S`/1={~K_|o;_zY嗴9*^X9}Bw?޽{XÏroc޷g0_ ;ֻ>'SW\ww?ݏד֧|={Es?+ǕEk'/>s7Uw[ۻJ+8~jz*7Yd{VW})}c>fY|?{#T0u>㺛͸&f˺fa?g\wuҝїuͲqMD,匾nmu7Q7/?їuͲqMD,}Yw,뮻_ϸƬ uͲq]^/M5WO_G|j`vveN{2_O0XZnKW[ ,yrV+Q}^-yby~^/yH_-y ,3K#^b<ټ}+ ucg7κ:x> eY8ϺllϳVݰ4 +؂bwi\''i=}f_|1M.kٝj,1;V//j^l Yt%Mhb@ӓE]_ro\̛&۟L;bX|x8 eLxp26_N~m;ŬiC͍I}gg˖eF/2]׉ |f=='@9fŬFֽjgqcuZ휝63݇ dNm%sa:~EYL98=j\w!Z#O_frZ<2ZƸx-y:d-gS2fG˔8Fc.ܪO$WmXeʺʆ˻])\,Ip R*zzU[B\j[mn(;#Kjq@9Oǯت4f`ddFS_LkQiK0_Ui2[vu4f-S,~ +f 9ErxVOxJ01`V2ůUl^ d"~9|PVJ2mv_uxv.e=2*W@\i G?xeVd\oB6~GK]"eEJ::l2kL+#-c !޻+0ֺ 3ne0Xb4Z@Ē oV@< o{2žɓ+l\/>d .6b]'DDzGY,`Mg {Z|#-h x׺ 2LU1!>IbAƚ.i 3MT;*W3~%o^ q "~q!N4zGdФv{;گˋy8KxeJ|\nؔ `%_bg o ^HS{QʳBLxNYsLTM>uR9;m]]//罣#F_\b2 *~xi#ȯce.Nxx%G y1R7`ǞYmFTV5CXRD(vvʮ"ݱ-ܺ$2.1}`*~Y{˜_H'k^ttcY1Uozȧ'judF ;d92[ٺ|>N U;bkN.'}@qOiX!AGҥ5r+m>y?b g!l8{0;_jr,cԺFwuu~=:*-ga^ ǯq~hzx氃Jz 8rPt=C&Wl5de7}"{xv䋵UC&0ɡ:b|7N}UXE;!]Ykl8j[OB_GF1Ot~턜gk kutk6FPZmp[^]uEzu> x]Vv>_ex~>d 2jwatX1" qϚxHR}pឦۥ}xwyɮ1˖ɳƎ{AD|.lٮ_8Kk\y~ՊL=ݓ~4RZξ`!UCY/S fC4eO4 9ec;Uؓ L"&~^7v9Z-Y޶Y7hk֨}c0=`+\{믜_ 2fslxn2V{ }ёu1kxOŒ_** 56˷!,eN/O_k_pʞerd+`Es3iYr58-bq,8`/bj>5/*P_W%? \Dtu;u꽡<GTOycQBw/Бk_¼2,>$윌Tk~cgP;FX~,68%^5Cͺt'N+|B<{Yd6NWY*~z}$M_{ +`_tʱ+zW8_Hq6A#K,XfA]/_g$[wjہ/~!Pbp_!Ǥ]o 9lUE2wN_ ^>k8ˡ:l+t$H߈ӵNpyu9pt#F\1ӱɼ7򨤘Cb~b͜/,[$ ޟă/ \=WxLa 8"~Qj㬁Xx9WXA4FD)/Ov~g>Eid_h>D曀S~ 23aZȅoq]+7tjy~2gu0te1Erxfa Ptrg>/^OCF>b_2)W ĵ/A. |JZI~N`}q.;<~oLr耗lU_xΗK&+.$,H\.8,ߠF25x¯OhnG''Fvo hJwBƞȹSȖ= enn=`O9e3'yxhW&e_kmNzN+JreK l믐_qv9j mE0sx2y+ٌTġJ5\·7+W .owRk}W j }Uq&0zC['h+e6 ~N9Б/VfD)@ ~IVTuBt dTn<̱| .'oY^A /I.%[^ .vLW25f'hⱟ^JDVu&'61\}يUF|fwld甭1phN4d,Qs - f|eBck^)+qDF2͢vĩd, L|kdɞN\N/W .jER(Ez /1A=m'#Z x;h$̋@g*+oLi[_a59UXU~x~]Ԍ넬!S/L`Ӷ^C'Yi/ /t9\4 +jiza9CwHz sc:lŅ$ոhL>=૘:l#P;fe_YG7iuxwm:4cR ~[5vNYBs~MǝJ?HsZ'od+1FF5-~+X@\Vɬ+:23'W)햧v^̈0Q畊_X̝g_xy9 Pn^G3-D;[M@:41^q-K6Ydҡ/m?Mx7;2\:e-!{|y|>\va+ůb@0֣5N / լ%~|J?!\UjH5pJD[ 7/ Gܠԋ_y=A+dBG/ `QL|XjbGH}Y!ad<~IQtGMtzgLX_}bws~Q 5Tx^/LVͧǯ8v/ A?5 Jfu1/_ C6tDez 8"~Ë́[`Pg0=2v3B rmd^lܣ> m 6N5̳p"tίLTiriAɌO/YA ]X4CDžrE `I/yRXٛVG_soVn#^]JuK_quo:쥇7 eӶ]q[Ri)xYg`ݱos1[K{ -{ -{ -{ -{ -{ <>T*UT/_{}[~~~~&g~SSa?oc״NO~*,^BT2?=~|L۟N7*ښu0Lݻ޽G姿ᯏUe>7_+*co~^8}~|w(U~=i}ɧoSU4ӻ_P}W|_W+V'o7nWw_}xɄorj|J{>fmpσ 5y`x<\bQ=3#wOu*bmb>O?o*HUQ}YZn[[`g/fmg]X<߲,g]6vMٍLj{XnXDu`zlA4۴Ǿa/ژ&ҵN5KȎwtXr@/,В&By{41[ {k"ȮP7`e.\YˏO\1E,C>< 2&KNijeK2#Zٗod.MD>ٞϓtRn3biV^_Aճi81]vNҙC~26t0,^]AIeJ*YiUνW ~ΥlGazZeJ9 2nxԲ_N 2.7!^أl%_lD.Ln+q įy21N LV%/x Jk',I<Qyv+mѽ2 mxx4`VP畹>1yr-ڇm_ y#Uc g(W j&8zLLjvh^Sȕn@h٦zX#l+~mwG4/W|?_8Îk53~aL.Or+ч&Ѓf1s~ZskR_;β2cL9ů`i;8yB'YiqzfHԄ߹E. E2~˱['h6Cqzdai#6W>C6=˖ⴣ/-EX'B!3=y3dsВN>^`0FJ+7Ñh랣NϨI ʤCO:lIb}l8QF{bԋْϴݒdK ܪ>gHXFȟ[{ǯf{{/rJclg5xd4䛽IH;IӷOD6_n'_>gRH:we7퓳Cק'cSi- _獋4˨Qܟ[ a6~ U$(rtx{q׌hqYsI1!fP>g\^,+[(mv__ NNR(wĴh9{% 0l,~+3_Q ca1ws389-&#>d .6b]'DDzGY,`Mgb Y|#h*m+^i6YZז_靟j;>‡v;ȣqJ2[=~e!b~yg?K 0Oۣez3 9Ae2",3cD#I|¶@Ǝ*/'ͺk2;w:K5dD1[;Drl!!c"مů ^ax* oVN/ _,h nk=nĿevů^DVfˀ@ +4iLzc ? ~v5/snv/P`p cpYů^o@h7ZmWdl,4c8egh /YԀv eY+_UK%+-åJvW/{A-ֳ:y)/)`x ߎz* Ȯ5j6'!7p73%^]ڮ1䲕W 0a"~E|GZW**8e|/~zhdSf8/v2cD4K✟5=M۷KU]_c-g1k2~uUsfVdz77䖊r?\rgb?[A2WqJ*#~_X9S%=In+Hj~1`"m5pf{=f 2͵/*9W'p{)9^[L{~HC c}t+"f]D̚5^2yPyW_3tJp,Wv9ZX@? |_0"~){>ca5ƯԃBhf bּOkq;(Ȃ:Y`${:@a:~_NJKi.r[S W{"1م3$6F}pkƨ2_j_1~XW˰xs2R}uAqaWz_!e=~,2ث,jQ_&k__S \I:؏b}+[/jbg4h4ȂeeJ2%x֫5/A. ?L1rLƯ`s_~i~;xfvl_.zБ }#N:!SAMrpnFI|zrL&Q!y1N g1f̗qFحWctV~#믐s/#5g "p+!r1"OxyG-A÷2"}oRƒ0/~:08cCf e)eg_H'j'ZT ŵxⲹJů,?L+ټV5dd/"aX;RĚ- /2+יhO"9Yީ{fgݒ_Yx5_A/j$3,̚)֥bdgٽ%;FC?YiA1Fδ>=$/b*"ۄc2fϓn ,A6Y=)9FĖ= x9k (/GM{43+.+V-}&r?6MŜ1ޛwJ#:CQUw$r5V7Vp 7hne`1`fA$kȡZ_ ܪYkrC;f^!8XlzؑX3MG,9IW _-_I'Wƙ´q-nx_ ( x =/;|ĶCG$Za%YQ) >Ё'Qf0gO 2*ll)Db͜b7 /I.ů)R4"vLQuBtz5f'hⱟ^JDq\FFL>1d+Keǯ0sH^ ~E Y B=cfm3,vL>5ݐx:_H_qvBYN8ӿ2A/b,!ۊxю5jEF%K'd12Q/Se+lbm'#Z x;h$̋@g*+oLi[_f59UXU~x~]Ԍ넬!S/L`ӶvKr7+W >R3!3:!=~E<]78, )VVXbC_4^xnL痭d5|\X'޵s-{tgeA,dUJR3tW ` bn-%gJaeoZҗ~o̽Yᯎxw7+=/}WսꈿB,gO%Nvu=oI^v KeyuǾl-{ -{ -{ -{ -{ -{ -DR?O+ ~/ c/M[~LPK!sΖMCword/media/image7.emfO]v<:&t㞥u\G< eddApP@=ƃ@C ^"#2"OX@NZ߽-%=^ jړ/n'_/dWNe12/nOOuNeu{ْ~_F^ӭ3y7N:;YcIH'Ҏ;#ܨG:G38Έ8Icucd:X}dl/;i4[g/~,]?A^vod?]o66}tv]dtsבX%`dllٕ!V|'lƺ }-,FNl,r'z6z4ٟ-]Yo {<}/̚/c粏ZuwY6!zڕ3@9'sYEv^c ]3Biny~tڏk^veqEƑ/Ƙu7@r:qi_Mj;MWy*+-}xO1 ;f ٜgln7~݋c#˙u67Ow;OuU-dϛArY?9;?;8 p@8 p@8 py|jwBRuہ|՗WJN}U/}݌Q!p|/^xӾn:d3YW^>~|,~8^Ph"j uu/%E|}akx\/L(*RIx T.s߼Bݪ82[z+angȪr`'DQ*Z|P&h=AZ;]=c/pʲʲǨepifY@63dPMreǖ(uj)3R[*/qIvߟQY&凤V TIp4ߐ Fex@pW_EٵkwnFs4YaN)^įdi9˗72*V!_H|Qw{N MA?HW"+Lo~g,_B\yʤv_R@_Ku!' ,{EȲ?bfVĶ0CV9DŽ͎u6AN􌽾W9_,sBm pt0xJJ 8 h?ƯR`'*m4YN_ qy-؟:~Ncuh (Yt xܭ3jYT)S*ShK8| ݺ.! ֽJrhQl91 hl= 8 ל:2iނ83ÖHz2Щ&ڢs2Νoc|%g [ڤ7 />9aْ*𥝚[ѐ׏eg)me1T'bsj(EF3NtXfԩyUiUJ88::Fᘯ6 ef#,cMy VYEmBtF**@6%Qz]?vCfW\w,؟/$/z28m)A&Rذ 7g7̸;[ʘLwlKҞnsAcϚ.utr*%+.74&*˨{AVH6R>ewdF,v)ȧ⬢1"(xH_E _bo9\1\0QNO]UskξyKٹ`]J{ |ݸm~嗏pQpb†ԭ1 V2ݦȚygy܉,YC_ex Yɯ_ϝ:Bl䔛R[ VQҷQGPbF.?s%ރNe% 2I1|WϑTW˯+xdwэyjũ5aU7JZ5Ŧ<='DÇL//YUO+lhOmJ ÖE-lݣ[hQ s!d*V!{C<ENbd ~u&]DOwV*!+Y~,^&3_c'[cB+41S)m~Yq~DOTϚ\Ӟ_;jh}fg<0qsv<% Ci~ͬwrAc\uo6b!oŕ, Ng0D _u _;^ϗZfTw ;[LMIb %q_gͺP6/ɵZBepy79ixt?j˼ f%3/ u}fu;@cêl7/ߩnet^1eF RlO|̯n/$kG2]|`Zåd@ O4;3+YΝYM-qLN(uw׀2ζU8سKƖK,Qw0_T^O~䚥F]%Tow&Wd)VOp _!H 7x u6d]gF}Za82/ a$M=<_i1lh)sh^.oLvAl/1u,QDxd uhAAAݣ\-X .㑅5Hoz8άd—z_L25n-g8\jSwvY(Rدgs* (L+ <|_9,qQDѐeCQjSA:)P$ؠO kZEYKra+rǒ|`Sh( 26"_i^3 ɪEF'׾bDɯyՂ089J7>*YhqTS/FnҖ,,V~iDe[R-,l?1\H0%*'WduoGr flJQ9[DYVvOcu)opY[ȒZO|!+X2ҡN_O {E!L\YSt%Ovĕ$O2#K (l~R& ]qю 8On1ԧ={I\*|Sh`&Ec~ʷg׀XKƚumUC@${X{jčl-1pռS#6/Iʯ$;EֹٮzUڒa]btrnW2S;%j+WYJ$Qv\Y\1Q}?Qq[I|%125ܡj?dI(i(|I+n=keH/ȋccQa| $ju&-4ױV5 :E?1!-A9+rWݱsN(ͩ;{"V51`?HXKFuШQ!Kr)kp` fk* JFVը>=6K◒RH^ D4 1{Sc X>)ȯnj!dYԒqFT+!K YI5jQH}m[mL=AY|\ ά YI+ BUVѽ䗩YY!Xrу "+i>+`n`kޭƔFiUM Ƞ &xlڠOj% cLkl=2Q<cb5֬-bʋGg \=*mWՍÐ 숽J V]>$Y+rb-]xzgtdtsmI4Kd۸皒i uMW3" l]ӼnjSwF\W7_=eRK~~x ̠icd:/myq(;p\ Gm×}V M)Yge"K6 P%` S5(4W (ׁvw&;ޡȼ5) {dA^- VЇDq bZvD#d v7E2idljv)*g͇:H޾mo߅5JS+ H%C9 BJcS ݧk5Z "L%O|w]w!PVugl^o6z}e tC]7g5z$TCٜ8=bVE,/.:vwg} !GI$r 9l:Kгϯ[R qI2ؖ".)Nfjܼz8! n^שλmVes(,YטtJbg,G0E/{;V¥'$Z#|IK:Y;5Do DUw-XkЧO mWf*m:A[u@ =oa^-Z u2n0>iةnUIdRBS Д}TI#/[pԾ`9qW5Rm6: 4` D-$-M6\T=;۪z7mesʮ_ʲ k@Y`T+muh"'ΒgxtS 0)m,qOsv}1q< BuiqvآIP&,L\gkx;1BĔ)iq^)`Lc+ÚeϹ5.ɕ:iB "ePŒCNmK{"ޫ&HQ)T9+k0i0$ri qu7']{1%d .BGjdPQ b ٔz`pn]f6{o߇~.ݟ]=ҝ_Vn_ dw'gd~Vi';w=keE'?iefʙ?EgޛߙZu\YTBO^ k˅Ÿn'_/dWNeeLi2SY؈{|F0bqZLƍy' G~gds|Ԏ>]"^ٱ=0g 37_3e s~앳692˖zBece)zwYvm#4 l8j [W}e˙e=ٳ%wfpmyuvlOlv/;ױ _Fvgf!36[&Y L>:7ws%kz1oȗ Ycgxr˜FV]N/Oeֳ%|f)y ~Yggd_|f' FAΖSP ew6|{ڤ;هZJ? Qp(8 p@8 p@8 p@u"A[Oح'= /U= Jpq~űڋ/vMbwnե8 | M}[qEcTyšv-J,wt).Bk}`;WOSkL A%  m ".ygl@P\J"Ut6!ŊAQy6szʖ%-YՖt@yFGirm;&plU%A^$UjL.v,X@<,qA[Z!1kƔKE艑|Ythdآٖ8ǠYsJpNRf?K7)"Km+YI.5Pth_(yPpyʪXoteC(_o*^"AcPTk(Fʀ2f C/;5*%͍n1D\erV}qA,UFimuh(4]zi;k.[!XSΪߙ}ȓ'2aWG@g KUu8$%gz:fZ85VIX6 rhŗFb-Mw d-(ˮUGV\[֢\$mM<|w1 4I;]0&<ODCS]YPen=u Y ɒSȲW<>UP1hD E?j綩a+ bКSS!USΊ91ѥ~Pze^>vz}ɸZdPp}>8i $b"m5llX^e@R-ZH)ސr|%WȲ>d  PU^-cի6/19e0ּmUh.5ZŽ8[VD\MPv&Y~EVr`Eʓ]b1 ,2H%aKPh. Fz^w 4^&Ȁ,ϝEx꜀:VYN[AB?2Ԋ@٭[0H7nb`$k& (ƚSpͩ-v-(=c>l鍤( h-://?_ p,M~a YSN-Y _کY ~_vjҖ\Cu+6R4m4DpA!5aX>aF꽜WEhK\d~coC\i1҈L;֔`mU&$LXnTOmR+/ iSr'c7d|ʥ{w ")2IB! R8'|[ і2zla!5| `(qc)_/|vÌkJmtζ$64{r\G'R⾸rC3k`򫲌ڽdՏj+~O3~]vN6k1o|**=/,_i1/Jq!ZOl5ȯ,ju߾d U57kkvk<%/ɯo׍]W\]~E '+lH#0m%m}wYϝȂ5_JܩӡK,ɯ|FN,Pme-}y%fl41Z=hD[FZ W(z|,Lu*GqݘQZ3VuڋUSl*ӣ|r@T?|o)4"!UΆ+ަ`1l) [=Ō8BVj(2ۈnb7ē_P*FVP)wXgu*Kt0lUrZgBܜ/ber;0vүu=..t,K8^LKN5[ 6 hDK딘arIoZN{W| (l_u=;+w6ԉ2 Z\,qjUkQ,-B\ DQ..n\~fޮ-Yq؈5ݜ]UUXyB5g.'UBUEٴ}n~MܙyfZm$$_odlx_N䗋OYjk$ܕZ_By.ahrEbqe*0pPgCung5#S.aK Fԃ;Æ2BN_ThS%!KgAQ'DZ9D)= )5݂p2YZdJ/|$S#(_" \yå60uwkǚ+I*|=wrJB8r *ȑS,'ETlS +f3x,QbR`~2˥?|3`@ pM6W]Y=-J~!K*5sYp\bm6f\z_W(cLs8wu_Tf8ј%W#oN/,U2#̈,(RVXE &6$Piҁ{//}U|_f^, vbj$q+5ك8$QٱZt% %bjw4f"1P:䗓"|(T"SX'.)gׄxe|>!kSr=Z.v{A=Cqmq߸e#K+s(eJG2Ano[XEjt$@mEu3ˍ6HeQɕ׈)=|KbmFVaj>dI(i(|I+W7'-kK/țW +hd2+tlW[ Yy{ ZQmBثw0YҪƀ+V䆯:zs.ϑ~OCQ$"eS ,_kכ!6k-dШ^%ɵ28Yꂯe W`_@ĥ$H5q Gۓ&dq5nꌎ+F4qAAZ $ס춏o,kx"!"+2G}y-^,1LW!+i%p5k,Dhb*z2485"ԙ=Y>.*r[[cʎ*d|a<;&^R !E0 {)Ny&FftC$5cOgmMۿƚ~b[beV !N):gG=;f|Y ]/϶Wi@Ⱦ6'zSm!YytseNӇmfI~sb&T|lB\_)B/,!ZN?,c&S Yf'^a.(wk'hf?B*q8v}Fv|gk3p,brh,a0?sfeQt p,|ebQae-eւ7>϶ICIdV0%ؐ$+8{yӻƧPQʒY㧶poBv);ڙgc2EW/T՗:Xq ƊAҹj8ĸj<齰tH7{C{+) P2 OD@ hFqbZND#dv7D2hW͉S~*Ce25^{goߦqj{E $:R@䉞(dl *A3e >hhB4Kc?J$^]߻-qmq5q^:cusepY7G5v$@ن8=bVEx^d=uz !KDI$r2K3feϯ[)H5 FsHY#\MO!ϋ9ln_xI CY,֬[呼Ȫ2BE)v);KOj$΋5dI=9ڸ}O.4Hˆ[\n HYWeUxB?Zȣ,,[Mq4*G5ΰ(Pv}m[?}U|}d+L鞕 Yjʾˡz}UٖG'29 a&нnm_ rYgb!"'dYGY"k'̺1B hڳ([}" eFr*6J"J7o{5)By* %(,|wá-^QX`uҘTR!+o_YfoC'e"SH]F .?)&(=Ϛzõ{fqO_>Mq}+l2d/)De#d@TAem$nB6t\+ PG'J-UtTȊsґe.ʶ|amBno?Y&L'JpN8K1%.# JjfWw8y~6mOe(ܘ+JK1tQ` @#Ռ4KpQr2Pheme޾ eY5,0 `@N[ zd@sT Ŭ6yތti2#>S/Ln){ugFk+ PIK>Œ?TÅChj St̆#G'%L(u3UaMȪw,5z+2cKfua SEY18b4%FL ST\/[q:Mr}Y-0en#}Q '$~ẗ%)E¡|J6m e;@$A :5'M^Nh24F a#S s46P\#=~هƚ c.>)!4&YeʩX% f*QYZ#=4zۻCa}}&/Bq02ˣ& dySF)\)`rIe08棞 P&~1F|Jkss\+5i ٱB R#˴a':h*f/ђkx EY#SRSewUQY%4dAA^Oȩ-o']2 #)lDyIj,þ9l8pyy u?!oK >Sp1Tj Tg.}#Yڔ\?֥ .\ pA .hիWύW~~צo?W^(?PK ![zz}z}word/media/image4.pngPNG  IHDRgsRGBgAMA a pHYsod}IDATx^`=ܽ۾vkeRwEjS;! Ĉ $?^vmNys+{ |.G ,A.=㼹m~vYAcϥ+\هAE~7Z^ϝS|}ϘǺt9| pyss?}>qci^k?<zʫ/ |I7^ԧL'YI> 'N֥ ?2'y{I` .>Y_. x Ο;e@v.W?dY@v\x_&zt9g/̅`&x .]ԅEBߜ9wgΜ¹'ʵJpY&YNڇLb >b>jZڄ~p`;{yΝ}|ݧOӺN>ǏX,sy3gggsR{uY=g^-E> s\:ϓwE+^Pp8K8}uUC2G>xY,NRx\D\& _NٳG1s?n/^wz<OFww7s> ?/EZ.+N })JWӓDU#D39) ?˾{|$EXf܂yOGAu.X{1P&T^/_| ,e sq5ub Yv\NiV z j9=-H߁}-}h>~'31L+EpNn]Dj^,D$#9%{!;Acǣ[ S>SY,,q%ٳܛ9Q,>LP?>MdZX)[H,{W89ypuELL JJ=} -is{N]Û'_8Wr#uO{cu|B6ppt%Ȝasv;8s,:tDO.R\?| .=7%nI;061wr5ӫDDE%!99(+)E]]NOO:}X ={ztrzy Xb-B=y* (8' 󆭭+vrCjj>1^R@u,r1{Y;;x1)!l|na wüU7lpQ Z 3/`W~ɪX\cOn%=(Ra}lc9"$i?B,$' )6qHLLFNv+jP N9M&[ Kx,I^}o18_i:m2ڞ'.!9~ e {v;x ` g 88;0КO|`!E?@7-t]{s GMG-wƑ@s5ع+nڍ; !8ы~ۏ+5&jC ŗ 0\%: ]Aƥ Ý1[r;\Һ#]Kַ[;ޑ{DG#6"1`; t9FV.>ɳxJt(%m(A Mh͟^֍'prOR+A 0r 88v7gPl g${!<NI1hƞ^eRv-['lf;a]Xo] љhVɓEZY8;}@eKlR^ǪMgU˘bWbcV:d`܃sO8шxfr"bH$c"4lA7ԻO]8JQ\T&iJ]щN:z8Oσxa#zɓrt% 7P|?ZZWl+hpK06x碢G0:D>O_Ow)}Ɇ;ݡ-6oi vmh6d36zb'Xy`?VY{5,]giźՅ^:ua5`a1"kƂ]K` d!hy"s++ ]چs5pBhD&|‘x(D]XB*SE? (FKQ4:Һ6e"!ɥۇ*x([MDQC=CΠ8S` OPkpnGX ݣ;VۉicU ܢa퓃Qpa lSr#ۻOiG񾽴a;ykݻٻkEK+6aXsVXo%V>Xj.!(n4c ,L`9] 0 Xѓ ׄ*8&mLyac)`Kv#&Tx!'}f,XrZ6R2󑔞RatSV4¾f$!(>JُЬFxĖ-v?|RW3'7(>0j`,gX8F 6k* m2o *B8GbvlsF&Cw`bB`plDbv2wu2Y-ؼ}f/ߊMąxf BKF9o NJ>HcHYIXL__.t5g-x'CsA0A3kKAz;"; [hw:61pKIHO(AP` G4V4A߇DʠKN@Q44#8pMGPw46>)p G@J5|Qld5L2AcێA3A' Z?Zo괭X랇M>X 8DfD؅d=*=ԋڃ]̌iH?q\Lh|rlܰvۅ/N\'ޞ5K\1:<_ޔtuQJ\D^eq%kUB} Ͼ{1h2RسwLn&%`g58bc$l 4$77wC8&$$!.)i.*EbFq9{p:{v mGދh;zΔ*#&uOH\|TH-~1 /*C;8g91N1E=0 ^9 #JOcs6Un#Wyb{ St6ه`{6X;c2FGbmM5Bl1fwŻKwc}$f:Fa6_o ޙXdvd}^]L6CE'ys #e 5d MR/gpZ{F+vqޞ0GDZEvf{Ji)#`0D'ϸ˟օq V&c\bb,iX읇~y[ !( B tZl gKl~;6n"ˋi]Jk`-7u9^z{&f؍VX+ ӌ@9_Y;(,RluKAفsFWØT1Rj. h..;Eӂŕmt쓻q+<­neW{)ML!]:y 0.r-_]~! -A9AD"hִ~6IhǮcTFbg)6;F?)$,c 2dY-Jfzm8q̤T(QfvJz-&?F]@qZ#Gq`Zh:9X$β:zFZD^C4͕k_-w=~x~w˓xE QW|  &[7z͑31txZ?fv ܃ZzVL>f.\oo{/~˻݊ɳmlo G0 2|сn.s6ok@嗢[Gw >S S,E-v`}_/+f+Kr9cSZڰ9CȵcVÊ+8 i FxTA+]'OR-}e_ `mIZ-F A=6r^pH?a $V+ҷ %pFIH1ǠP2QIOHa/ЂuXF9ʪPf}:3'hN~/Y({ѕҐw1Z6>&kmmv 5LH&q4~yݟ1fRs+b6w=b7#ug8ҬÐ0m<_-뷙fL ,4VQL ?3ກV[߿>29b"WXז0cc-xũ2t ƌOfH`npMFpK?^'Y} < U]t"2Ra]lo̰jګrx'#n#<*a Oc]]]kDXYYaɒ%Xt) Ύ :vՆ帠L/9 &2ݔ8ug8y uG]vlMZxwǩƽd,]`\w4BY;06xE>q?.Tzg ck s͑gN윹 _i&aْ)-&M,c!w=ޏo[&s9瀴MAX8c޻1f$q갷n8ػTF! ݝlS(>:Q y/ tG#1,*keZ36E7ckVck|Fd-"dT\:bSX{bQ;N5j>s<x3O>X oVu0f]Fi/JM>KFv37?ڌxTh+QZ@k*3}lB:V&:|"p?姰dE_A40IAsPhbd"ʐ ǽL@Hh$74 5ehkC[aZѽ9nƈbǖpl[凢ZHjEm`  (H&w|o)'(FxۭB:%{QVWS͝fHBɺ2%>_`%J#38}˸G|WLZj9NͱM nAeb1ޢOʦ!(BM\o3o6Lwy6}GiSÊ Infx '-4Xtl;MՃ㽒\@YE)ޟ5'B04V[ )V?YZL6z!èI*G1)"tZp"aY9E*v{rѕ]"T;`(˭@c5p>)v`uu-'y1t!~Li#)Aꖊ2Gƈ};I'`;+F}#ǔ%7ф Rc7&M Oki'K.w$J1[u)g5ÝWm^Lݕ !XZ9, 34HHLCX Y8ÃvƬd|cƌ?L5մBM_sRP/Tۃ"tmCq;::(q>ĤX7o&Νɓø╗C`]z5BpDDTQphF}-;t  2 ̭6ݨM)G^x6Ё&+AcmE]cjr#5G%N0UFd!݇6\Z3.~YLFo2n@4KG.҂#qNۉJ0.EtE|$P'Ny@ b_`.t!8CܪNUQs;n{ g&p22"5@^"2İ_ţO>o9)h@kS ғr|ԳL`a9gz Q[IQ OM+ KBk6ax兡4C I74O$iY۳rUVWz?I 9V :CSTV2 {؍„d3A>|-Mh?̦L">̛9EpL{~Rڃ 5)矅 ۇptŔVt%W jxKE[]=jsȑ#A3KjI.T+**h~́X2g fio7;p0 1x3xa7o-<-̝3 o2F0G>rD&_]HCf^!&yҤ`8|H !vg\jسYqYȤHFCU3-<=̒sH3ݱ>0fΚ+3]Sc+JH?X_<<Y\f\*!JN/afE 5(/gE\J>Z^+ W1?d=[`*QHfIR3]Qh(_t{b-~_ľC`2(4FZr WEn^+0 YJ9OrWOd0m<`&'M c8&2L$Jf12D^s^}ML1ؼi-\;6`ެI8@P93w7G,^4Qa$qsTlh֛xDZeoQ~lf7G #^'EBy65hIHΡeid٪ښq+O =u. lbu8BCE O)B\{ßxaؘ=&SV\[R?bjjev@n;&D碔'%>>̧䣺 5 ![qn_YJzr%e7oL2e1Q2>yTi,Ñ )[ZN2~,5GKyrƚc*Ƹ#]ٻܗkIc6wbkD;#0SQST!112GLLҐ iQ&OœO?'S&`Xd>VXX+%(no+V\XQ^N6(BQ^6ҒQP#_yQ-%c*wa?cz<$찢( Ij$'͈'ϭ# ܏ -ѕh61\mc[Ml">ށoy U";n7¢bCbfqJd+9$, cJ oh6q\yU-^yY3٤{ՑwCQRXt^e躙V1ۤUuh+!섲26tUt4`A>`e'fRfG^rvUS1q6Ipʾ=; Cp73@*DD$!j銔fv׿)xDEꑪzL./XByа(˩faYJ*Ct?% WǾں& =S,*u]qC-横1li9vw`F-l0$fԭ]g !1mc;;#yߌo7zS7$3aO}f,5wY16@޶ fPH-Y u6;if/,gp]"2hŤ}0b G~*Xֿ6<&Y&1mM]s{܍\ m;*'eQ>$`.V`eZl-"Yt~c.;;?JobK#ʫÏc̼׌NH?Ǹjňt}T^e)y+K]b|t \[V>9]\Oey3J?M+;jLϣ_h*CK`*v 7<xv)錮StaNr' G^ۍ'g"rɸʧzY2I8l02p 5Zj<]J]M@[;ʘAKJKcO=_2l(˴e&+f^w2?-7o}BR5Sh9d8Dtg>VT|1Y,:m۰q+/Q:#4[J R~A}?l,)ƍos5s[qŒYC-o 7=5=V$*`2qe QOvQ\ xIO{_r)sBSڱ‹A^ j6Rigvr{tiԇP M_3HZ0HӞ<ހL,YZ1ǎw`' TP@ڙY쓸_[oĘocX`.mZ0eX)*0'^ &ZL휜쐡ی[ `#6m`]t#aAx걇Ak~GWaO~{t\ȚItٜXum&Kn$pV_{-ZXj{"@_xSz ,q6xR;y 3`Er괙(5RH{W'rr d;:: D_`͂ ?kV'yZ":8-E@jYsOmeDfboE1=bZ# l e0MQ! VpJu dѼ 04yr3n?Ĭ%%!=3tlձ$+KLjX>͂Y}$KX󸤊TcAm'fv`\̰5 viW^ QL)MfP/pUc? cPCeJLJ3'FBC pn%ˑU Tj偛n w\6 eۑpֻ0j{xf7r )P*U jOWF [ww.>g,,wd+7nPK%Y3%r59d3h3U>g~ Zya˂`evkSA&:,( 1$ON vbo=ǴSXVӃK4cI/(gi$A)4Y%)ғ̤QU[w4ܕ uOC1q$[X=<>v)eaniMXF2r f ߖrƸHO:~XO MYj8tT T+MMIB_8~xcMe4z\YKV{Sg1koa(Y^]ܢoƜxv e6b*3`MFd((k_Th`x <3ǨsS6).N1hHΆ;$BjP%E55u_\ &j,epI@RM9S+՚D)^!#*;ٻ MhUCFSȫ$ t `e >PV)ܷVgGA02.rJM_+z!xg 6%rTO:0X4FM * p!㡭T(tȊg? Y)ajV¬i\L&}ǀ[ndձl֭߈In<9xVoqU1`%)m&_M?{5~~\cnszcԁ@xmP|&=J2q1}z͌H(cAbupmv3a {,͔"$+r؋U>!j0V36XBńK*Jvm;tŽ٣STVwfsr\R@:иJ++[~aYYsbgP;xKӉ|^e^ړO<vlft Duou}6l wOc47od-sR ʘy55mso} ۶m3c͜-7IS1vd(lvEYU=%4.#xmVdVJe\|XAQ*4J&?bU*b(DÝ6oƄAmb;'r$LuF [R%e$H* HWFΛ_l=); ·rȆMrbJD̛͑ldm>H4*SV ;66Jr0>jҗϫS*ʚFdpܪ\W)drat>lMXr\,mXo|`ȡ=>.G=dա|MIW_n &gΚ߱,]PT "91qc:3tCEhe+VaݶpGX\wq ޛ>[6K&Bt\O 6q( YS{̝qXq,gs𢏌IkfPl%8șQeg`cƕS\b@Y, $jxH,9pᙕJfyXО5Y,B28qz [vG`N d$2oD$AƄ% ?H7@JJ1EBfrTJPD{lp1med}@Ueekyuy<-^D|5פI /Ykgxyq6E,5[F5Jk[0,66ʼ| 􅿟׿b8~"&\)~w1f$,XXFu0Iwij/6aɚuʱl&uf;ģ b8jTP@&`LA6M̃|]h /XEXP:ƙ>Z&ZM!|k,|J`nE!# > Vlx-Qǰ؋ `>X\\:956s$ۃo4R3i PajΜCy93f\J6y1f)7H^s-3c2*DSR !5xLK5vv0Y{dK1J$tP=K@s_e%u cyDHJWK_';wks(O$((^fYLx͌ضVi?rXl`/pv( Q8EdJCت~)(L*I)f.pqNeDWS2nvğ=öD<̞)Kx/ch`/.~!Z+:H-g9G.6Gq|=i|D#N8eHY-@xV {ui%L8/uB2C- l pcՈliBhY7pL]R@H^0u7cMvIYxe"=U*5n m;mVg3f@o~2ꜫXw+nIc&ՆO$%;q#UQIOO7#]F|-nsk eìKB챃W^M+1ُɶEI4ge"`r,Ԉ6-]X91T\ol o"s9+5M [-R'cK<k^ŝGM!fjp/]U|'ϸ Ga޺xd^al0 a.ң Jcb2u0\(s?wR6>mIf]5,g٫JRbJdkJa-ukzRf^)XqI {)܌%IGj!tnsg 1:+|,}X/W7/cI*:"9U#vK. le{?due!.R壍 5O{ќn`)@)1ο0*FTȣ7'\]Z!1k\s1KpNRARƫ1YJND|&s[0Vi1`&Q~'x}+j0סtK8ҍ}>)GV[ڵ>=EscƶTyv0݁$9-x9r!dUXe֑"mrYH?j$7ΌL@'LS vV禍DV^k #1e"Nsa}}L CgCU L7\K17k~n&ȣOpuqF'Kq$('EW^\*8˕ENl0iwD"5.ZI#=RQ|0[ЦҲ 8qܣK($աE[*b^+%N9ͻ_tàwҩ-pu2Ϭ<ONڱƷKݪܹYX~rm!N.[mܗ^]sU7ߛfh#+WKM}=ͣ\&9nǞ#Ͼpf`{JLolULW} ?O{ְ9S \.mxw8?ǜ MP8)Lf1Trr[YkzǍ_lE8;ntsZJ2zJ"P H3ffi%沈 %GLd kn?|d9U30:#boRC+ccm!ܩ{`"Lk}U]];l /Hy~(#6tpe{ 5!pL5j2|rQVq=X|4 IH]d tUM.Y3,4Z[u_}P8Up^|c,^~cQĞz)ZT|\4~dwMQlb#٩;^yo;kS( D+w8e,ԆVXG{ a%η#H$.*QWJ潖U` W^k%Ȃ:i4uR[2oƃO2bBUUC |v d f(ni"5u3O#x}X+q=ƽ7 ^yTRJtȠ:z|_XI 2;60c,ES,?V<{1}\7F,9ti(E{)L燽`f[|}Xr#O-ZF~¬W<[qIR&Z) :يdQT8PYǞzISߟmā:ЄI\)yҝ?|pr2@% IR.O3KR%3zuO)6$)`DIȊlwzIkbÏfq0U-DMUVQr:*a"ZEџvssdvGlg{v{\$11aϵ'ՖsxFsU(c2Wi9-KԶa&bFBfҏⰽ<"J"1+_'-RK?fWmC|k<&nӝ'uO9N.<=6[*f-SWοQ*@^nQH~<"9$8"L_}@Љ4l΢kEa˂@))2%<**؂$0vg7(Α.Ľ?)"Rn靔P@6K+kV,̴bAZ@XXNu۷ۛKYH04FuE.&8"B.CNB5K%l"{ؓ߻`C ~\әVqu|z3P{z()Ն~)͔yw.c۩>{2jL8q,]rDdr^{ijЊ3o8YjzЋ=!R]6Ɗ)skLI>Z.Y9O 8]%rAಞgL}r_֍!lt$Tv/]k6lVp/; nZ.HI<k&!Mr>|D*Ȭ='{FfV谳&1,MQ_,pyHITg/2YJD:):YU`R%X w(n>Zi{Mr~cmJ=̦u IVLZX2M@&ɭ;" $J{MIGЏAz{Y/TP"Suak&c)**8Jq,W,U+WP|[(/@7S2? K7yʙ-k)|^[f#AȅyURTʣj""}\pyLXzr(S=9>%v|s r>! 8drIs1lr2ಧJBܗ| ̋41n X˝P Nj̜=n3Ͻ_Z\j&)ʂ))P\٧4Q~O9;65'L5#50e&^djT?Ayҵ1k"Sn͌-S~aHbV8Iڮs=f۹CTe)V&)`x-D"q^^bBMYխ|@qb\č d](. 5]ճ3Hkzb]}Lg" @ψ^? ؼm;ۛV$CjλlŦpZHP:frضn6/]`~Sd[n):Irtba_oenml\*wZ~%# ),T֦¯ G\h ;y7<O8j weqE6Zi>nBC5_=qf>?~&WIl{ <`PexIƸGJ,ܥˍf9K:Z\?f\O65G-zT,%@jE[P%plzKQ䜫!} 8l>s٬|`ZPs="G0g`غeP@`cS"*E uo΅6L{vsiF1T3HI5iBB)IV|EX_ۛ66MQ)|ZΟbJFr1oE.5UJ:CVǓ #:77`D ߬3EM5ȼ*ٱۀKThڟJN*׾ ~_1XH+EI*U-Ah!dvu4+i5Y"w5b.ŒG TR*6$\E7_)$*BSe1-*WvMuIY.ɶ{]''?/>.p弇,lSk#*~KTG:`g0ynRmx( } -9 &W,]EWX6n\@dE 2P"Ó8=VTO8Q:P* U]R|umܶ K1_?5(=!רQU8y6-6CS,YEERk򍓙47GU\^i[Y"/Zgj鰗_Ì {7Q;E (j>/ZϤP]mQ*`Ɏ!2nůe\LEQ$~Lx1KV[e"݊W̥xK{TܥlQ@: X"p/`Z9griSΟCeCXCr99r5#x~ē1׳2 A. ?Dž"x\ ;Gtfbl²ib 5-X7ޙ{X9{9c?# fmZY#sDFyx<)$Qn#zЪe;gcpL"!d* x-្%Q%A$= ko"UP̵{7@"744Ouꋖ~2}ֿXyRzE;l^›+20̀slɫOF־=m}I9,z?+7P$r f|EYס`dpnwBĄx0v`]ݚmCNfjp9Kb8%7_HNN1#BnΕ 'r S8t%eyZJ2.b46TrjT_VS3Lq'W/qpJT=aV>QÍWuMmkeTHger{.ڷk%UQS'{Iu4g7g\lr&-K.fgT@"Yn4qe#3ŕ 3ƒ=9oW!$y 9O{@둻(\~-"\(Qm7-"1PZʞ]CGqHp\8މӣr* >dkXO@&ICc'j|f߅Da O~s(Baj;F2k7X86/~E hlɯǍ.JLMCay`@UĻo{c'cXI-0+`U5ojB^nQVNⲇ{X$^ [ d^iy W~?>RB YiB4(XRj]՞'JVHKn2RKl:’57#=+4K).L{b^H.ɝ|L=t39©Crhqh3`ٸVq6<1?B;)G22%v =ad7pخ |v۠3 .qj'{ y B:4ʮ2ɔWdIag̡'s bBVlVSZc}-*d+ŒE!ZB;M,zRO1׼L_]g@Ի))1lT &ͽLS(^쾲b+ՒGj9fٛty%[OJyKvcDP(@t PGa"5^$'}rox0F%>ld0YmbT L|߻ S OkspX< AJ5-xUl>VOmf='pVĭn>hNok%T!LߏQOF08h-kp\T ##D,'hD{h%.69i7I$=KCS/*B덷)7hklNY-vj*6_f]Few)ޒkMVLN̿:`r#ɳ`(c3Fk @vpQQKaћ+8ėkwK@ ~Z9=)2'u`XWB ;>l/vD8 ƾ9mє \!)6eb0iɕaiՌꩯR{v+_Y+W|c#xCuq6fZT3njKzI`:ŕ-^ w { /D4ul \3 [2T~J&dtq]ȋHT&PnQ-kb.)j.*iۖϒ<拂 VzX:! YDyoYA aÀV3c _Xܲf+B ͚^.r̼`Y\rmw6/e\]dY,HWĭcp %phĉ%V\,X3!#vǕFtIe2z_Ęe-GOpQN2ۙtX} a^mt*]*)QJI-JJKQ% ,Z!y \8{'ORWMue$39&!e= .~Pf<E5щ\ !+qAtTS՜+Cj9$,\ʺQ^B@fsCoƋ|=y,#QʭqD?a]<n1[ 5.J(mQ|>tYJW]1X"Qċq֞.}.VEChS8Mb`/o;pd)tmcqYb9Y;Y>%".*sʅ4KnSl( Y: W ?Ww%J͆y6AbZ.~Zye5 ?}&O; ȡH!?NIa6ѿup 1H ~Bx"|$ (^FD#$ yT,-'8k(O|m cͿiRuj̞("S9+ƾ6oQ/[nՑjS@_3)Z(c bELp/KKQ|%'ToO*|Egb\Y:HYL@',RU1:T"R(ܢ~QoSY8WZ},`_mL #]U?Pwpn3G;P' WWOEi)ȶ2MޝlۣX JFxZI쯴I`&!hPd'L". `OF2[٘0NҡYkp>&*  O{/~Fn,S%8ӝY-@}9 \Hξ7XL6zxHMh zkfi&K3.ilbm_)撥œJV eiU[%zN=xO[Mwi憚>4LNK_wuC e4dE?n&wf`gH*jI.<,mZ`VV+?sMe"OYiިmi?P2L 2WQmc65#CԔdeSB-}2$BHM9SDfMbp3/OC2/%ߴqܨ' ؚ#$5ӵa/ۚSZ"t{8N>Fڭ%5-dj͢{\&;vigq9nNz̀AŒVÈm8 ϲrO]"(:9iAZ hZ~5aClڐ{(#@`4B`"K4X#}/RIG4KmP=kLe,ʹP;n,9VT!{ŌkA-.CR͠6{oP:/- 2-"OqݽqEȌ+'ߥ1Gͽ7w\{寘@պmIKasI%gLňḑeurXϝN(˝.46s0K]3L" k%+}']9T""W'k]@e5P`V6)@ʊ{y3DX(gؒ)%n ~Ifqsa9Wky^GcىQsFykJiFPuXC9d#) !Lt$3P,+)i< 5#M=pݚ5j*A$_cj>ep[Ô_0s52 @=;m. g&B73=ƑZhq0$ AXKK .n W&>1ca\\4nF' CS|`<5?2]C8ԑ\{xrLh9kPN>fMqXhѹ;Km\@" ;ʲfBz] &m]p͝YYĨjoI(8-7(tbPH&RC1,@K*-G,Y8we&^B;%:BEo$"㋜~i$Mb>e,5J>|e`_aH%S/XbM(vhp^`KVK[34KtG úT\a#3^ "i#(fЬc9.@MR L 8/8-iJ`jUQ\} 5cy(|"W/K RMKCe"ё±錻Db+)V3ɾ+(>+1f9.p0;Dn=q$s1ZfT-*'-'/K,Δoeie.;q&Ljak{2^PԪ&`i9oQ =-|n2Y>Es%աEsDDL|\FCI$ KܝTj%S%wGE#p+.uV&%W.JCFzz , \]} 11~GWqYпLLn&g=J;^oJ^Y¯RT6G<+a$fNdKv%1X[®E`-+eO !gQ &R $šR84er&8eLYJeʫ~EKEgNXtmr0^T&ZB4\4Y0e&pi,.}\Կ>`W?y/`}L*ɚiIPQ[.wCV \%"6&S{^E''VIEl#awܤJNұGG&C`ҞK@euD{(!+Y,ڑr"MAKUYsT+Fdԉ-Z:eVtFmbOMm*,œYT[T(@pYvJYn@5}2eY)8C ڢVJP+r@__O<4';3CnY&-ꠌqJ)[X$#>EH'(VR'ףʂ( S|loYPVQEs%Ũ{&BQR Y, Z*X͕_hR|&NC?T Q(p-zю \`&e~&46${֭dVSc tE=ttqҊ'ib5~TT;?JaY#&d$h09v(v_Sk2=%L?7`].4®K@럹OsdAQJj+AK(2UdG5^WG}o ?}ځ~aEi譮nrו/b-}^C*Kѡy'@W*dAt*^Mz*sɖC5>j"e꺎qhA"k[~,{StեL6'" $?Z*dhl%,j+7!I $PI& Y% kM=FCʁj\=Fo)k[Ie2lӁ<lj";ˡc9>=2?O{3:ir5L 4)E4I-@%ZgGP.XkTd},8 jYjWYbO|_ߟTb@S[5?_c-֬rZA#FrjS>& iEL i(K,E4,'U,듀^cا+TO(+%%@٥VP2LX!{Nן4.Ϻ,B_tOQ 엷05 N;G)F% RS}P*K|%k,TSX/X<ڕX,ZӘnJNMvNC4eՁǿ`W0?5_b+ 8|IENDB`PK!ezword/media/image6.emf=dKgV;+FЎ@cbZlH2ʑQ YƽF!Hy^㤐 Ĥ\ ZH3YI!C9%-z'[YI8qO9_/˟Տ..+~q?_Uv}O_^߸o^\!Gf_?|Կߖ-U?^.[}:j[o͋O~|T_;.oiv԰VЎs} S{vV?1\JLu@=b:jwUp_Q~?/qz.O\^?n.O*}Tp}\<:uL:S/u{@_Vlˀ/WU}s4Uݼ xZii{y_22ı/r k_辅5IOtK\}8`b@~}pࢺ,>>/OQ>/c@٩w}w <@w~UUĿJ{v{@H_۫Jӻ៧ $woX~7T߽a OUS]?s_ h5@@i߹Ҿ#Ҿsÿy+|=euv%|](@΅zwnWօREiUg_kڷ%%R}߾WK??+h7@}_7i߮y5jU}_/_|QWտ9oU[TշκVƹ/{r?實^9Pڋ4|~k?տTC 4L=Uð>|MJj)?\^dHrwߋ1NϟG<8y#pG<8y#pG<8y#pG<vr>=XV|OZϗIF@,,<1ݍݾ{îOr<%Cb brw{w^իQGOϗm@%泩 qͫP$^ջջ3u|^Xb6oo/@kLj=얳t||6o|{,IoH`H@|zWKy|ntsc_ݹlj_b6#b0PXx$f[A"z߬'H#a |x<p%޾|3ﶋYD&Ɛm͞fe#H" NYXQ]_%(XԐH,1O,]`g[5;CG@btgHdx# Xb9őHKWtj6X OE)x#"P 1ZN/1Oc%)ic pKFחOz7 p "ЫxhznDܱ^ȷ왌!0Ө^,S0;=bϭ>4,1nEPX"Ch!!Tdu\1n|9!!!AJ@r>$JN7aA5' p: HehvFZ,n|h)lV,4M5:gzc $m8^Y-,y*0_b%ᱚH,ӳ񉀛Xb6#h&8%"Ou _[`Al0ՈkDfٔ@ɛDac^1(Ah79gl"ѭ'8EK$#Lx$Ze m083u|sx8sbT1@aW \hX $>vcl7.6z:&\0ALmXbegBp겂ďoǚG({\ʒPQXb+o.m&떃e`-f9+y|B=A'G~}=Yzh8`NJIw1 Q2IeH8 T PBjOs5HPXTc6NXL}w92a3X0$MiM1*_ *m܇DۯfBD @b9Zt^ m:4u\u _,1e4eHXpD%Vv/!2 >%:0‚]1Xzh5}Ьlh,<:{~Hphe@" WMLYʷV]ʩH,a&f~bcأf 8@#ka M Ո-:Dظu< DrPgGx"! -`.fWa0=ug | epN'dZO` $ I* ̳^%"{a;[ġmS'bP43 a|zhH50ϰ1 q5K!%޷Pi3 q  ϒ0"?SZwKt`H DQ1bkS"g#6:q u`+<.c }<:fNnࡹu&@@9901_6 6t{T@b:`Ox#< |L8fO솓K"+7B7K@x K$GMiގʕ1$=?PKH-VqDl@{*`b,6-Y-: =:|+^GG{^Lm:#dA4f%ߠ a,Z І%:{# D_r& oP!F GΤ čbrlT.k2;pb/3 &ѱj $J*Lr7TO*L~cTHfur$bM]jqi+#ggu KSԌqa6@\L-g#!HPYG9 J8{9>Ur{Rallz?V~Fev#dd 1:,k\%BslM.Gl |# 49@B uƒx=3 z 5 6TlyILudlq!l; aq9 Fb Ii}٣jh7܏e!ᤨ $8DߐSJ 6W=0h|IC=?I߁Hq C]*0K%aeH?m:'%БZ\Jx@a_"EDʂ/`6̊{0 9sq3Fd5gn ,M>uU$ؠ#rQk*}o.LRAqU.L#BK#c<&Á)fG.EcF͌"9bl=I-U n;*k8 ~ LmwE- -$[}f8B)&ftύ`pEg2IH1ҒTk,@֪K),\ sed%AǔC1L=KT7d}weֆ57u4iHb# 6a­$e6!²hQgY.Lݩ!O"/9 ZNJ!c)+;[Onw7>n D+"rWYKDfrD {hU1덁OOy]x wmP`:i|pk*O`;H!)D[ m᧲2+Ђt2ͧZ+b\8B%F$`Hg'pŭLq,l_݁ױn3:ut![עy\izX֣C|8%GL;OЀf 8<8D`pKAW7@&YV N(x){ 'uR1=&M(d#x{?U9&dp&_b@-~/xЌnwvSug1y3*A)n0L:إLGO[ljU:TB/ 0H5u"[vˌmi_30c$.lbF2Zx; f $谋J>jt%[J5xLE`=SJ€<,H<죚IX2"`}fcn NfP T \P 茙)};K; -b/^ ! #055,xb9K;{8-b? N+By)՜]NY|I­6&6%Zm7է22.,A|;LDcqS}Ϟ*ɠC2pFѶ,C(fea f!!O|Epe]+##LL24h":BXWQk&9T_TP `m]_Z+T4|?6 0"N 5Mw!q!LI(=֪\fGdW5,z3?O|uM#2CNr:_f`N0cxo15ymCr_+ k!@c_ȡx/#̍MX]WWġ-7Pē:s!m=@vve(K$okl-)WP8UƟQe*<<]>WZexu)MAJGu~A'%*G .V;lAP1kr=+(/|ps Hpw$*o1+sRsG aADm7|A2B/Y( nk<*>Q]笈!ۓHԳ!D!Z6a ӼƢAu#GkD:-~F bI&ql}ȅ8E&޺\<Q01% 0F&O=8J1 +x0 1im BY+#!M3&v*UhC5:0iԻyCB~^8~Xs|PB{faDxr<іˡU7#IXL #&YDOBfrBŽ rb%t\Pp貃 I2d%*em:7 !}Kr7G$t_YKo$>̶X .3v˪=1m *h`B! T43eB.TCdEd [IYMPY:; wU&F0hܣȖznv/^` [qO:L[=b_۪m!p"Hqd%F>KVt!"M'TǹW DC$"Ū3{B@*Aj #aY:x:C=Dߚ=$EʾDGwxP!'_d^Rw|&+!G_:#8M H:]nh3 q.z 21yn8ʷ$30;:W!z*k,oHCO|`x6JW l0$_rH n0"\dckeWc S:$lb6U\VwH9VIgoiuxIKRs5F= lനGj|w, fO|.u/щj=-Ҍi8i"ɨhw]BJٻI-/!^E(tBJ'P@ȁE 5_) ockצ$m]9g7Xh蔵jx~? [=\J2Uqa6]-lj"| $-x&'GVh`(HSД`o30kpObJCӭ)DM΃WC\ @j 8X%,r׉U")1r=P|;;/~JO@.ZA@FE5c /y IxcAHٌpQ1b~ ?d I ^T!J$C&~\0l-2(Ƕ5@W lXNJ=.txxY,XZL,eO"՟<,Ye>x@-mE^E8C2 Dڎz@ aR`bb )s@)$ WMdZH#s0RbR7Kcyq\yO|mX a|Ws_Zh+&fc`@ 0 $ˮ;e?Y!oRIzt,Gl,Q JyxcieBD \= \7(XYZ/*깧 y9PLŌ)獨Inj YXIXtI&F\]X4c]/B%6 hA-(W_'pTp3Z8 +E#Z!!HPC?ߝ΋jǮD=n,S^PuxX񦼔pKV|ۀ ꣄"SFT)$ 0^򈜄7l|cH ~vȔ*q{ehxY\қw?{@DSb $=ҤJ~٩*@2a!V)4 [X@n""懢jRf" :GŁ1;n7{p6Ƈ͒kfUʔSϽ7.ՎnGF(  Ylʚt, @!hKbXCkQsWG<>DUB%kW&qw#:ziЪ*H:u=di/FV7FЋN̶,XQ/PNj*y(3# K H.$$ rQR=2 ">*%0WOl>LE ~Cҹr4CYb35oe^2:Ҟo 鱇&\#MlHkLY/f.(l>+"PCQRs:3Cr#ӳY!2/!Z]aʠcery#^q]_&|Y2< -6~`:uDuTXXvGQ $r'}r3?X[MZ`AXCDJj8c!a&gr"p8EaNMs72d#e#b2~ҎqP(6XauSdK s. 1*<8=T\ `8A}9bn~H IR>dV8Jv$=%f^Aɴa@۔cުBږ CHh<]f-)k~GzC,Q>Fj8S=դvV:LޘE5jÂXUKKȡ!^p2g`>V)7rX& v{p ;$F)#N6+e4O'L;۠2ᗲ M'K;8b͞L#@eCvŚc c3]5W ?eٞFuG܎o2w8^G W`ρ=m[F D`Ueic7R#Ht(UJȬ;3 ю3W _Γ+)KrOR Y1FfWSY2~'ԹݜX41NK7HBC_(@ <\zbaɸRl `9! @i&g0!p]~3I&<1KȊ@ 旰 ۭ295"* 1: q~5ڪ7妠i#Ly3PJ5ϡ^3i4[`Ie jb2%(oI>$'L!IlCLL>W&i|lfܾ}S5TYC>s Wt^X8 {2Hz&M7ZوuRĘ% }"Nk\Cn,+BaYof2m>9Ѻ-{Fk8VjxDrAOm+[U$\fm7hk⍵L16CR^ьI+bVƕSlc6ޣ OEz cEaA ۪/h5)gD}=T_ˇګ~k.xys^qom)ކ)RFkxg~3ϫ<Ay*˂em]G`2 b (q3X(m@``A+*7A(alH;Uy7j_Rz6Fa-y;˨d,=t4ʈotp1 x-d| 4 #/@WQLru 6*+<^:Z>zhJ0KQ2&;gr~CkY {E2 xD=j0o<҆q%!DE|U2KAZXhC3PfM˯Y v\9ea6yЬ`wX%H1|~Qc>}0F2q9,1X!Ѐ 2ʀ`# P^ ^K`5u]3ΞW2TzA >'~!C\oPj>3ƧAB~6 ս.Z_<1:FyUyTAkBI2K;R{$nO\^e NmCivD`QF^ӒE I.jnA.?ϗ5?w磷j9\|eK^VZ 0($ {0rc&!i-NCm?gԽ>gl&1Eg|C0`,;F9` *Ci%[:y':M>n I+/%GU?Fz~?C ڮb0raN-n&ZVf޺mzlo}t׸ #KޘII||VI֐fX4E>MaW ZGw٪03لD1 Qn1DHAQs{}ms ^S$9'xt<&@is0 4\Ul~-7(? A008`怡\:Ⱦ كHyث?!tuj9 q4GF-A/c4eYq )b,8(XCY\"Cu+Z,]stdQ}oODfKx/|Χx6I1i-\Ϗ)?{5Cm`@pَKXP1nExAO7A&8Btݙ3  fc8?;`` WLcp窾`'UF呜DRX }2;:Ԛ{y X(`ư1 ψo,S6v^3x%@fp8'qH%w1J#3|:ϾN輎i3wӁ6?TyTUյuJUiץ7U(U8]>{ퟷ_wt@T߾ft@ψ"o;JNP"Яw/wMw?y EGj#!f? 毦1tM%_EK*MXzo, n%_Pпog8nw%}W~_M;6B%0J`(QF %0J`(QF %0J`(QF %0J`vFxG* /g\oi_n} %օ':f뷯Yz1^I7?|닗0<)1K3IĻ7W_^ o^M.N/\U}v~.,ϧח^ @+Lb֋|zr?^K% U Xl (b~}[o˻MR^\]3I)*% @b1$녁ۮvjqsute?:,o9N'@"ě7^O-7"A"ΐ8; GɔyO$`a Tys(GĪDbeboxf%o_q{[>\]C"ī_n(D*tX"m6)X̦G OE)x#"P 1X/L%)ic pK&0RK*Kn8OՆGFznDܱ]ɷ<2}`QcZ`v~jwvK Kfӛ+8c!Ȑ )$,aHٽ~by|DWL|/K^2D.kAT| Kf"!F_g6X$ Aٍ jD@bG,юSmx1X`H ]216/cv,XHJ<\KS}/,u|&&X,7 `S]*Bb$— X05L5!"ϟI:_ev]Y/9P QMp@X؛.IJ85<8z=-?g:~ K(\{5^D@;„W@^?/PmE7o_>(,oy*CK^)YbZI/?ZF;tĚ:p3// bT1@a RhXs:1;rt;rk: uf㽰 KlLN]V5T(&nKG57{ۀeoخrJrvK78IQn4qOs'ƒq RRḿByEG?-HܣC0ľd87K~ k c, 00|튻 %6%kC£)MxN`}jƨD{\Onzr$w[х{Q0yXc\.|ĜIДͶ#sb  ؽ{?l3X ,RcLlX 1 O6{ʎx:1qw'_O  HD*FS-Ur*KXXY.CD5@0EqX`'{SB5co6nDuQ\/DgQ,14nK(ԁDLxy<&~"|)?:vESH@?&W *jJ7-۹!?* Kp qM&_@UW I]wTCDC#Zq,Al PB|im5W7k:@UB"傢/Dz%fZbw\D́w(8`dDbl8 H%j{,9E ?aAt/C ->@}{鏌#K06"/ Gt'z7< [12'>0#MX"CBc,QsHSϩ`C\G ں]oǕGj{\3 `G݈'zӛDb5 SZr)eά4Tr5d5d>%Q ]-/6)a 7EzHO VfD ٤* $ ?I* ,KE,y(16]3_AAoimucmٞ)[%Xug.pS0_ hb s x܈*^ )o v$@"GB3`Xܱbprs{sn6Nngn啥m:^GP]{k|w^]Wy} VJ-y*)P_I~eacCx)5 TID x ౞^Kaf|)\QG%;6Be u>$ri$u׷1qv*g 1?Gx%OE@c#I 1$uf"Ѹ΋T%#!ݝQJ019{ s'1#2 aM.ěՑK @ $n/ 6jn 2%LNRA6{3A25Dy<2FZ2`W _al@i$.!͒g2PGw Can|E@ EIzufr@`8PKM@EqJOiӃ (s K5 W`ױY5PFg 7[ ,Kd!FR}\{Of8tπa 8V\^01Oj NZ#':+pJ#X|[| s{P r uMݲ (rCltGDr$0-v\=Lr  F*N hO1@WL`%+%Q5Ca\Go|~^ W=r6¬$r9EVo5}$ڰASt$HKΤ!Pba#3iub#1N0\ C^-K$+, j8{abl83kIFMg:D4HOUw1o[0b2SaY݁Çxzdz,r\PƐ lїRSUyG<rJđ?~*;!-hϦ\kEKWBBĈ LtN)5{:Ȇȏ*<x>^G]@x/Hς:>!00^qx cLbY gu?Cg<*VS$ת)uCBV<~O,VS 6Ǥ uo P QcmPMg,/.R/ vzc7Up30726- W3~>B=^)Yc_0{ &PJ%%.[unٖu9j00@~t$~ ^h ko3_@IDa|1 < A}Ԩ'[J5xLE`=SJ˂w,H<죚IX"cQecfcn NfP T \P 肙9v`#w )[L 4^< CF`ajэK,xbƒ^Nk.X°dž|wJ5vSaV_QVhu 6ޛS S1KjA|(>뾤e@z1ϸ>jtgOpJa|ɠC2pEѶ,}(fea fyG>Ϣ  #1BVQk&/m*0Ҷ/e-* AN>9>6 0"N 5Mw!u!LI(=֪D3O{؃zM)1#ga]GLiS*Η4Z 1)5y4`m/ }FN`@^ B{an lºg%b%7F߄b A&Om--/:,j)?le[RIc9CVns_0c(8?vs[|Q]^ >1DDh,H&:Q::<@d fauHIݡq[RAepՖ%~Qn̊ҐK(2B._+yY2q<:䔦 :\yA'%*YxqcÃlVBZa& =_ Jsڴk\ou9\Vw+A;&u2? ;gEl}腽8E&c<Q01%mDpH^ɓ,G)fbE:GK;Um# Nz$B8=0^[G"&s y)TA?bǔre֯L;;P de NU~%Cx) ) 05Uem5'LT!]a&,dÀo{Fga\Xؠn3q]1 M9ٔ+ [eKՋۛ)/">tT8ɥ1$?Rtf/ vKք< Ja|WC38if. ЋV`l2{pEY9o+8 xpRmUxlQb押@xWje"]DMG!p+d2"$<욨|c6W=7?iKjCi B}Brv\خ eB"woxR{kƨˌ5ߟe"P<cOAEbAeZ7x Y6-3d C<*f'ATy(wv'"n A.A({F_!!zW. 㭁Ѫa/ʹGK/ƈ 1زa?–SQ~|a1&M˙7T !C1 =r<i*`#I,@X&24ÈI2* q'\ΣfrBŽ rbĨ:D.L QIq\e8`!;qBR YDIJvYԾSve٣fNY_YwzY|miK2<\Fv˪-CgbQeBBboGAHJ𔲲0_DeB.TCdEd p|6Bex4U #)sB#[R>l7O xɛ΂=G+l9[aؒΞjo2 #d=0|b2ݭ ?1 (6I\+RJ<%!D4E(V  T Te ˂Aa\$}kao^賠: ULn}-FqQ:D ^, $/Vx1IiV8|{M_0_Gb\Hso-ݐ4jxtZ5MNQ <?dȟ ୊QH[iqP{$S%{"Hl)+VY= ' 7 r`^Pn@Hx,LgrZkBU|e. ' ظ toCS1}(7@*۲h+a-i??ZO.[þG2@ Nc{xi\7 xxWc /u ).!.oCE^R$!LL2d A(dSPoG9Y%9eǚtQq[c dje)r>6zg?GfWoyl;,Z"tFYP_:$ J'p`V,V)&&9#eNP!*z?ts9'42#͒|<<;+㑯 P=jK M $ã7&AJ8>XM5T.ɢ&H_IVhI ^*)PO|(u"ę7u&Ks-Z9..%ߣ0߼AcRjFo+WyT=exb*Fܦ1oDMrS20j.Ĉ HX˩}I BFE+^SR[8*-$OY4ZN*;-H<=&xTq[{eA 0l=fUoK k HQY>J(r{;UnDM #%IxΧ8*0:znLVGjK^}Я%=u6LRn=F\?BHHW,Ɨ $c! jHG`:Bd 7i CjRf" :GŁ]1ۿ7{p6CnMYu|s2gzos!EkD=hVjti6eMt, @!hKbZc2_9WQ/]2iיK6-Vq'9!GpH$p]$Ko~yhRz9z ٖ+=I@2ex$@pY %%h쳐.)Aq*DiyᄇB)Ȭ"#n_t er@vT 6&Ш.!Zu91XbPCusg‚>|C.i4L-ّ֘>_c<zF_y"0?Hb:h)7":=*y ֶpQ0 s=T}-WHMs1z}S1.Dq^Gѝp9fqH +=b>nӨ5C(9G+jdhdIIb/mH*38b`@&XT`/8< Q`UQ$@R#oPx5ݶ X a` dnZS-5'U"s7BQf, =S ?YcDV}EyR7P}\?&Z:ۖ!窼jR\G'|[أ;wȐV9f-~e+ю*K $  |FCtH*pxO"by@J + H4B[^U  .# <#؃$Y KѝT*F`P`r0G=!4!ѝǸu6;!4gʐW:RcUEP2drN*ش9Ţ?C2'*2.K:6ٰ492FgأF]J`a! إ=~0j6RJ`Z)Q܈dUH fT!sH%0#a]DDO2`5sEePxNu6ʢaQ]=7XCS޵f$*hR\2#KNCYITcG[hFGceV ?H)l2 $A$Cï-7p+6_{ )sfʦ&nDzM}edU44Bdz^=^@ǢFK[FGӠk)$Pmd9v[UIXkQ0#SDf›{mzE S,KFlf'O=1Ob x J&4!c >1m?4 IR>dV8Jv$=%f^Aɴa@۔cU5-.#xh{fj8Î!~)۠4dNcfAlh |Ͳt}^)E1 ӱOXAf+2G}Qoyu%Nia)AJ`){bD-RB;be,jd(t؍ԯH@2 l$28ΌJUBByǗ$ De*6x;fy×cP0@`nb̮dNsq9j}ibnq jG4eXr!3Kƕb[lmC BH5>!]R$ L-xb&בN|Sc9i PYbg_7lh\RXSh+sc/4:ax;ߚVgx:[n :d<țlV*a>b{2lE[ޫ&%;(1Ey;LL!>ae Hb\j`,(6Hc39US *KKx8 =7pE5ukaX!i$fm@6"yfD21޳}yG>2"EX*qJ lVz{ʴDG C6_iFH-T!Ire[80mf)+C{6__ӋzL)/hd 1i>XL'BGƓ@T{AVDVt{YGl@9M9G $P}ݦ.W\z}qomu6&Sh3 IS <̨V xKBT> 6"$$mc7g2߬0CO^/a &uS-vIwG08pلFOx0(6C =v@9="sm38ϒ-CP!uTtG –wBa(lmشXef<^/[x B:y]Ðy?QLI^ًj? ${j `d yM`q1w$C#bDݰxc WĖ7&_m>0I" -u?ˏ-Y',=+H4>B3?T =0B7Q0+QQ7H c60#901NE3$rkۤ2]ѣX,S檨akwZoo V"kyRtQ-xCx)i{韢Ma " yA@|A !C:-[P{[bwHf],l8m?%&!8cU žKGB{z'.F^4x RqD `ؓ1wZ'd[79G_Ɓ`XwrX@T֥PJ:!_6u(߻=I\G~)9b1OrG !CQ/`(ÜZܻM UMilV{~|l Z57HȒ7fR0&_TR% =ԁuӘ$_) D]j !gvUXRO6+C Rjc6zCD ߱;犲ʀL!1GJAKkMb6<+jt t;t;?Z/? c|غ?3z;M c&m\8ͱ6λ~Bap1 xz$  H@$  H@$  H@$  H@$  H@ \6MsjYt2Y6 %)ElYB~PK!AKword/settings.xml[Ǒ VUe ˃:`1,޵ɖnJ}kE=1^I*+o7_ptp͋͋n_=7/O_==ܿyp͋>_>>?gO_o_}w/oo~woo_~{w7w{s_|z7/?޿_{wݽ-3rx7~x>OC~G7ǶGs|x|] =>}zb޾ooŃ>ԿfGѼm>O=z2g4^}wxՏmⷬxxxՏ/>bXMK<|-<޼e}՛ۛp|â{۷ۯ_޽^oonps{~XݛG RΦ}?n޼'^}燷bkz~᏾6?>~5?w?^z;Know?7_>OW/>?ǟû?~Y臻/?{ÇO3xx{5c}xOo(gz-~?nϏo>?C6#㣾7n=zo^>]?W?++3 7E|G򻇇?<^ǵvi~yO/_??g ?j/ۏ3l[kkG*ja˱?ŇG~Nǻ׷Ut2Gz+8>+Vr~onۛO/7wwQ1՗D~N,_^GVihztEQia|E6<+en6}Z(_<| 9SrMӦ3mvsn'i$vlOvj$iv:;Wf|n,1H}:7_oHv?зq|J.IRO_!l~]ov_eOǰ>}3=7klNvw3חn/KBfWok~NǺlS;LCOgXC3HFҡ;bط\{0^$C :qw0ƾMjlgnlѵa%`lصSA$ق& EWX3A?O9$9)3Nsjjg{jju6}gjƿgjW >4c3544j4.TO_Us>ssS܎Gh֠)涞>?0yO_3<<Ҍgi`[.i>KasZJN{8e>su3lGgaJ\9H ʟ6ͶlVrntm-׮iv7_k7W[U3h=96 atj;UװOgpoC;ch|b ޷Y{6v몭ѭ=&_7Ɓz=n}#Ӳ׍[7K1؛}Ccsk OCC3ùm}}!arzOѣÍv9|(vΖ[}VJup룤=pcsr `4-:?S6 ϵ%W%=HwVN )6Xd+ja~G2mqd[[Umw\rK2VfBw-pբmyB;NKv|1WB5[5Hđ?m׵nu"Yn纲Us]9Nnlp-Mڿ-|Bi'6hS;ߧ!wB ߍeaY72ʴ9fbJ,e7chӷW7"Z݃}z#9=ZG{ZPCGh?awKۏv%Xd0}HhӖpqq 0t}=ٱv(5^$a 78F4c€dml` +v|m:Ʈ> c IL9)=CY8Ǒo^Om̃냩nY|@'j16Wm%aN2\\[NcFGt=dCz0-zoMӹ~k~;duNyc 6~nnF{Ss}muo~q^e;x#J`h)qs鳰Ӧ#XGׄ{э&?C,9J샣_> ]r {Rhq;>qܾ>3gZ$(5g õ ǿT㑾t%a n a%BrcJ=w+X0itlعMu 0OP:y:ꦲjToP u;k{=MCP[8`':wo݌Oµܝa I;}8am}LmFX{HwtO$m깎`m!=OTGZęJH1(]2 ʹFvj!ZO= YHXڷwI_V? GqJ# zh:a `~#CGl HBL/k3G`{cA1nY+rXގc;)e*$X&$w+K@ius ;>t3:%cM6x{0;#!U=# XGiMqt0}=v `r/63=UEvȐ/q1HOcgxlmiȾ;sAV^ija~~15O!s sӌ|A+&'I |N6g Q:nHN4o,Hf ,\׫3l΀rxD"7=;Hn ٝj9ݣ;*T?E3Hh$k$5})kTGjUAB>(U>DHFGjrCsAd!Yз&g:1lNL_:L,=\1®G6! ] Vthn O| /HvGIUBߐ=)7Ȗ]?Cz$mBDȵ=q0}ϑٙq$8Hv: KM}iAK}.slፎB=(+qDp On%P i}YA9g{[\ڐ K&R{p~nx\S̅XAZK0ΑS$AiX=.BrN2~ 9s|g!@%W/hS>]𜅾צwaL̰謤 !Z(yX&kQgsup_ ^ӑzLW6J죯2hJ$ć!G憭7jȄ l[$01aEǚaN7 ̸Sau7!Ygvr>%f5؉D /s;F:H!:V/,PQB,\T_k0;Gq0\Bp,9},_2 K\6۰p:-ܙ%ut1sv}s%@U[Hv HBL" h}N0azd).8$ Y$eroH҈ٹ}EVx\ʮ!q?y³U> Y=nفv^g%fqmIѼ.HưK7H>~c!;{f}A&!Dr=l(tHRۣKNpI6x_?B OG 1pP{Maɡ0`Яo<\#sC9)#aaDrx\aÿ2x%KB}ƿo~DŽH:yzɑn#!'qlhdD]g4JC RCJ=oyj,$%h)3^c7 l>9CF$,Rڭg!G;-YBjv_(O#7~)H8AİQ)ҟFV9(Ya1>RR\cjfj)ꕛB$sаd =}q dH﬙"Fp|Ԭ0ttXn8M }4wゅo#G0bUBĵG+޵KLwg|$kX@B}ZSC`+kv[p vz&NЛhy?  :ەēOA M09í`8]ev)`ǝl>:  "9" V2bo\&tc`~΁Aڀ)_QC$G1RyIF75٦GX X|پ{>:WQG؂l $ľ'I> g*Ƽsގ9 9=uz/>9?=0mK$ƀ񪯧6*.E%:g6c(UW"XL{Uu ,-n^pfx4UN${%qvDQmHNwiKw OMJGa#J-눂&:L6K蝯nj-0a@j =T2p_(+`c]-;~۵ } X%}9rA +-~"qδU ln$[St9怄4LB pFp^A|d=ތ8\#d%`aUp e"v9:|NG!{ӽ$ԛFzj?@9!X\Hܧ#q r67$aU]5D["&16 g0(sIw:RB }CR HM{a9oN:e㑶H3:lz<-}D2췅W~,T`s$hK=O=tUJ I; ):ˆ^v`X4Hjצ^|zKȄ20GqƑTG~%]s sYHk#~;xIgkMDE Ga-֩87miKi$# [B$/@ꌁ ~2@2kcn.*׌ۖUw|HBV$[ד)'E]mÝ{EGgp O;R^Og&|׆d 7Kv":F}a63CH[_sE#swB *iA|Iu9yw;~%K{;K数k1zQaݱ] &k28i-'><O5d +\ sg͠yCFr 0\nRyڽ Z2WZ:2ά_sM$I?ɸٚz:']U3 J?}6|`a oqF!W68=Tsu#Βӱ$J![G¥FMH;u}S$ 6g61bzy O ꀻ+eU߹}DQg$A8s>ӳ DilH婽&j% FPÀW|S$RjS78cvsR89{"5`iХ!\O&$,D@Bx4.Ar(;>= \Ǡmw i|[nȺB yt%^Iv{@n+9Q --2FBmL!գY]-(7"tD6JYr&N= MPƟ紣Œ\GhϮ rM$P▩7 ySQƧkJlȥw *zr+`uou9Bqcgsm\ܪlһr-ֿAOUWd[`rBT ɰ*;-o`L墥ù\^V…ұ $P5,=>k!sla!]ڰ-w/2}$t( qUEz]AǏ)r'aǬR3h>y&kS{nv+djK e/ _JC8K(rv¡2{c=aiFD[ 5 1!h"B -XxM1.*^d:yCڙch8 `_SzqOdwRnQYa_9, vn].3w |`!q}Y䌎֫8/O@Np2!IwZJ:~:#qֲu-yY%O"G/+3+yݾ^)e73cS&d96Gh{-=ޑY0Z#$|iC=\9h:aNc wۊmSGg-Sa= #Ydh7avF"CQzgpهCc`L/;k0jK㷗$-h.[#Aؒу$9I1? 31 O#Rwu&B瀘!q !R1KHB}${cp!94-XDy 6xtpQ;x󕸂s ve>XЃw= A\ fW ``:gneF=*w z?c`>ĉ+K9Ц6{U|EOFq]XJ0:0JO*k*;{lȇO"}lWQN,jn4X:6$nz`a]os-F`R'XvTPv$xE3$bfgM NQvOs{@훀`}mHB6W]w 9|+F~AF ?{BzU }A%~P,a (Qֳ!P\ǚZ>[2LʱiOPW\#PL>o.~ˡ fh* W9`E}ǭ4$Jtw*you)G#t)oϞaYkص~J0HyZ;RA2GQK]!=RIȅXvd3սcSg֭u =wH&g!!˴[iC DFrma%u|qH6$ >Rm HA6D l+FgX 2iߐxu>e%/[(H6GHԅ}J>B!LJ$KϬ !˚+(ACy1HnOI4Ⱥ~2 oYwK E{3=@$D"R#%=š8E<{pSQ:Y Be'2Y6_w gg} mBul{˾A}o9\vzr>mv#(3d+W98RyGICcot}sOk$9gg<1v*t~š$!b9{O$woC4V~`>m:o7b&*>X}7.|7r2RCu{gť;OKz3_L,K<.$Bz =3K-k܍̮CyRQWU>kvg3AtOd% |[zvEfz9=Սˡ?w}R}3p8zfkJ?TOI+ŮU j8U_ƀB~n:SR0X@rG;)3GN\r >L񴮑NsI$*Y~$YE",+LLדY+MKx?W=ҳ6ZA-{%$!O[= O# AB u*<-ʞqw.%5ds[qtw,J& Z5GBm[(ߨ[! % Hnqc٨ZTT V]HB9$1U$㣤̞L{ix5~+-0WboxKQ YqFШ/[Hv?7Zh"cfP?Wj-s$ە-615ȩ,*#Ć=a/G!`qrރCQ>eԃdGȎ?_ݿ@rp{nHJy !k~cL]R:\Bz?FކlMX#+@z"F oL%NJQMT! Օ7ۃVn;P6d]`M)bq&=$XvD *NÎdu>ƲIڤHCAuF nF ߍ3787 mj{ $(f]o -YJ@erI9ڷs ك!tsnHi6![FO r]b~Z@]B޵rTVG[zT ^D:K璸tPѺ!?+O&" sУ5eLV9\Qrx$;WWg qmWuxp50} 2X t9 )u{I+ـR꾍2@F!,n2 VW sY9h\qF!>o>>ƜKt-cd`u.,K،,5(x C[R;9?#)nف_ iL [s{W+6 nفf2*>ަLnRjOBθw]ڄj/HOǎ56!qah* >5`BIνR HSNroH gOW#G",QW-pA>EpV ģp }x @ں[ 4U#Hs; UȥD+Bflس½MQZf?t +&i  %s `OUjA}( -(dыj qBθ˪c,z> A gA%xW[w@͠cR%(d8˺Ry$!åY|5r "B6GR|Ԅ 5=&Q:= $Lk؃{(?̖44ЦzDOPpz^_g3jF{+U8T'| =[Y- Psp_@VXQdыkh һg@)kS G?O#ss ZYˮQG U=4]xpisL! m>um6^!Bîy% uAQT?I ~opNuMMXa+A0J{,U#;۠MO7@[nF&'=~5,!]AbMqMsdskR-Գ.@z@|ǨG =1)B)~dz"$0L)bݷA@+0xuX 8&Pp;üQG$er4$1 7j㚘hwH3 3¬">wX]Gfq[R}$u@N?љu5T*`q)g ^F}g-,ۦֹgQܽ -\U b9[6X +٧a/ѻ}a(U=ct(z9<by~ڭh:y q \2:ӵ{5!smî 0 w#TAVjŀLDՖ!ϯ6"ۑqȆT=:%w~5*hUfx2p@MtUѰ;' $ԓɸ$e%)Gi,U9EB,0+)U iuɊ}\ dZ$0 >Bz*:r!5̮q_Yft\H m0wȞ3C+p>zV1[3jOA֮!Y+>rM^C:va@ti4YZAi^m%P4wd}hF; u3M~xdhl:ܭj+替9s}Cߡ.H)0 r6ߜF$\2ǷACGZ? '2+.#0!q~Ê J#c2t7xݻBTB)zF~2v)~ %vUw&} 0|\C!6m25$^p5ކ6 g; :BMBn#(!H1#EPfpH[6.+sTvH#8Q<m=DlڌRrgs@鱜4n{Q/USz~x<ކlVn ;CKPĹ$txn&ThZG= Z -%0l0\M2t'G6*7M`7*ox}[̐JfҜږXG~jkҫ%"~D$Ahzs5"G&,3 {ڒ4nPQ=;Q`r u^]e'E 5G([65^9\~#z_>wF~xo7C;nnހe7~}׺ݝvǿ^yno?7+;}O߿F?wv7/_hw>_W7w>n/_<<;?9hq?ן߰ fx2 o6ylgfuoug_>쎇ݯg9|pmG绛vh<|wuڜ_ak<Nx/|blݟ><>췷/Ƥ W>ݜ6g/;5><_lw7{FO2 \j9nN76\iw:PK!Z]word/_rels/settings.xml.relsj@E@a>Z9E+v&IN͠=о3M @anz(9Evs 0.2pnAYBeSQB ĜZ~"|=y Gҏuo47Lun@$0=c (n%Dy$60̎\ݹB¥;RY8ͣsޣ)tPK!s0%$word/styles.xml=rȵKOɃ.ESbi2@0  -{>4@R֍2m}"V'NOZj-狓_ޜMZDi/N?w[-*-'۷!^FO:^}/ ?]Fvf-&%isz:8a`(}2'|W6Sd]phO!О|γy\eJ-d%{e2ϳ"yK-ۧ2=i-^ey4KyOsl>m)&g?/*[mӻ']dZe.eDUa6/ o#h~ҋx[!,Y(s{y Jb]Ҳ`@[EC68Nċɓ,Nner,1o,կE} .̳jsq i~k:U'$xOBC∈KMflAtvD{k!Q(.Q/"(E}7d1 *g qeU[`R#=c.٤1٦քo8Ocnl9CT$`qjեsZk=w?h":8&CyS~Z{4(扱O!Kq.ijպoRQ CaӺ}@V38(:ӆϐi6 :/풿#Ɇ'Zi>sP=`aLg3 0~ }3,ߦeHLHb>.Du9ckoRf}˖[|YP|(A鸡˕O>_iFQo Ǣ:oLM> Ts}X(Xk,%(–Pj j j  ǟBTj ǟVAEQ͗F\D>Dja$bBPM(>DA5TDmA5ATDmA5ATD-A57T?j ǟVAzj!Ts %jB!E j j j 1P|)LTEUPM> *wTs}X(T%(BPM(Q[PMQ[PMQKPՄO!e |,*@j')BLbڮtK}r.bݰ0ǎ%j*oIfiaY7>6oeܺ=.Б&t#OMCji~2qEދu - je=F2t\]bqE 74-=suNN%|Z2{{1:,OeR*YоE&祆8oyꡡc Ye|1W )U =JmlmR1"[:~! OVD`NzuCӪd\~ӕnwلNg|Gx>ŊŌt GtzX`sHJ\ btI{AqE\࿏q.ez?Y^vhIQhg'N/O{cfm]mTRT3{/dĄg y* >ɋn&ZpH-I1a&xmG^:yJw7^O̫  *tz=F 7PMn`q^ۑhñ0׀J}9JY$Ҿ &iG4O6Ndq֡ќ1uLàSN|'6H]Wc]82mp-YCMg[D q ±ZކemOj7Kw.No|[/sYJ"=/m]-F!0>('&[;n%mb{ 1l鞟c'/CE F{Ձ[wpii UI2Gos!I[̷&$OfLJZ0f{AAWVqaw(FiTԺjG~6% imK1 7PVCF%G0e{ ҥfNb1 FS V>!⛴ppJN%cU,ƒCAU,Ѕ1OIEKf/'xb1'u w(ǐ…)WJ$5EepqȤu2S\FS( @1!q+s6jR3CVwı4#Wdn;4Ӕ}XVeNKHE"Leӂ=:Zjw`WGaGHyfiCma<nbLAgxDQtuڼ(3Cj,2: mZlљ`H$z7oSjkQ-rHN>w qXMӘʏ); Ϙ?˭hA =Cl0$?>mIm$wUp23"py`fy@ވR7\tTh{>\Mۮ,`L z5-l zK ]gSmI5y\,3M+^E?2A-^{I&"rMʡ4Z9@Bt:&84Hu?pJ.eEWOOYRk- x(~R^:2Ͳw78`K8yBz._)map23W}uTm#.bG#%BJ*C;ue0#PZ[rYcϬkF̓iqfہr>R{g)=ig#vkg6z5B!M LnF2.*9|Ur\\,Uv8C |[ESiB:kq@V$Yxx{wK I®ݾbp!tXPF1 ;q$L{ 4<"Rnv;Չ1KtjLʞFɊ'.x8Kw@t.|KZ7싕+)ϫ+#or@u8aiOyȭ[r`X?l&W?U,K͜=ށjaT JȈh)_.:(uqot9~ANFj})O%Fi҅ :~7Ƀ(ȶ\'CKV^ BE gX?8 &᰿VDF48L^xy N\ui: 4|*& p_,vsgtkՓ@SӔum[wF$p !S-^u9?7ϊf3Ejѷf,7foG.|q UBqw7Y2x aI'_*DÐSWuC7; "wuGO{nvhwhcУ0]~ B0w{M:ŴOY }P:t<|Po`YceuXZdq Z!ʮ$vWd+wkan)%j`_QG2y h4;ې?ߐBrZU{iLDqQ5LǾUn|1A\ v- ߙ<M @@H)l*%*o8Qw:?]MDd2Ȱ)'C#)8ˆj5@;ʂ!7S7fyA5<9'! ('/jf(5;qLV!|Bjоǻd<=)䂠X?\<ߐ;p<]!Ic59X21|!}xV :Tא@Iw("ŷwر%UzjpX8!;}[O9|37x2R}sdj|[9P(tX8aC?_;tG;Rn${i w,B5H~ IC\u~RN*}[ƫ PQSo_iPbԺފi]ऽ,QeL@Lͪ>3<:~؊ٟ ֎VR:}- Vډv !CW3c98<| iKo p'8uRſۦ]cڥꞋp4OTƖm*l5=htK;$"QQsmC5g=hATn#8 pa_Q ^} !\҆q|vԕ<#Yֳ>KC?Yxf̿*2ps7 oXYKHʃuIٛ"Q>VQ,I *m\U)UgQՔs{v8bgq widMi:Q%&)gp7F8Tε^v G+;17+Nho"SSq!IJU;RJ`Iyi7AߧvUAPn)69u vTjה!qƖS.Vnք/FVH1ߦ)-ҸIo(՗˛x}߰!odUl$U-M;m?{H` pC~HV앱<[L[u21>`*S! hΝL# OZs.r8uMKtj$9Yd[ ]r1Ւ\ٺ՟Yӽ{-~ԟ/B!(bm揣- Qg0&ZfL_M2Z>Ѧ>]wr5P̄))C8Y|tqUγ٪hTSMMqr;tr&7zĀMElqŷ;M\MqX0;==;PC)ҫ+b]͍Њ"—QJJ)bRlpwK9dgopBVi,(Orlbt9}OO-)+SVk&/@dzg)C4)6o!NB!Id\57jB+z!We*TS*98):J"_4Ig9_ͥn!jVWviI.:;]u/) uIGZ1*o=ʓ憗9nE "}ǗĚIo&\{wM]'q#C{ïeǕZdGL/$"/X<@*7{ՆNq$ D,xL*T^PmGgpxc$!Gy ί*OBohKY6DE fJF`OPlv׀/_*܋ґ\VDu5ZC턹|/jtf+T:dzXrَtw؜_ 폝6ޣ Qcm2vtG3ΰkh*ԣ~tn6Weh ^Zդ*j%_?hXk<ݽP/X]}nu͉pH_ e_n7y\3ͱ/2ncr t@~nlB@ :lp~-Tw0^tfp=FЎQ!@;-]S{Nӿ}]|**Ļnj ʻ8qQMhS%)l@1yHାi29EL:?]m!~w~˿4{о:ҼæB° ZF ҈p?L~{-)%feUuX<ܤQMYxp~ZGbfKm:=^u7-G֐ u&[u. F5*f(zIফ[ZU9.`G7/0x:qchhlF3QdPȹYsVL4תWZizO|Nj $]޼ K% ` 45DNⓐ=%7t^YaaSfz&9$>Ӊ`,LJNux P^Z_MmӐnR Vs/,ݶ3$M<9!GJQ 38"Dt}$V.M)cOT.Q՚w{kũZ:);81@Q|PK!t?9z(customXml/_rels/item1.xml.rels (1 ;ܝxxYt23iS(O+,1 ?¬S4T5(zG?)'2=l,D60& +Jd2:Yw#u]otm@aCo J6 wE0X(\|̔6(`x k PK!\(customXml/item1.xml $( I /-JN-VNIM.IM .IUq pԋQR %bJ 9yVIJ%%Vzy@ (]??--39%?475DL?)3)'3?( jUч{Ǝ PK!*5?HdocProps/app.xml (Yk0~0~o#Ee6V>V12wm!JZ4?]|#4'ҧcҲ.x$E1ʹ|DފR.I)tCVT1 &8LrMIO&x}eD.R:[&y],h0}u+MKאUCA(=Zd@^BP=5%*7jI8$ț0RI QM.j!2Y@l8vuY;⥣2j p]} M6m1h8^&s [S~*hKKc\/jAh9C (C~w 躍~`l'?~IN̡+T[|QæPK!k%'word/stylesWithEffects.xml=Ys8[Awtvg:T(ٖD-)I~~pAJr쌦&Aw_/EsI=;ih5*<'ߟ/E7`U~]0|G*O"k*w#\DO0hqyN?"M9ewW'd-E*,;*6(Çt6py6K d|v/d>AHV<1^s("كY]m.Obb'_f**Z—%@<_" ^#-cٞW݇VwrI; =rJh~q{&$9&aPTi=tJ7qcHj ,B3o mmJnluSaw,%vD&c'`6v]noWsOznst0±mSuQS *5m|Hj9Be9K|8ŏbg⛦Po4X:9\@~H>=n`Vw< }"l=_%'%)#Άw;Z> i~_ޓ@A`Og= \R+ |3Ji]po"F!6Hcl;5Kq-[2oE.rDa{`rcqٷQ}ʢ5D tQ'A濷`#+a.P<~p] 7r%{`"H69WRQ|l+d%9Ŗ{>/SGT_f Le#Q|p/s'jQQ!*39DeF5ĨFZjO+CHT us}Z4ɪ1Q>(X%9Q.3G̨2CTfTsʌjQQGTj#Q1ʨ>2*ڋj$Ћ,bdT jDa(2CTfTsʌjQQ!*1ѽSpʨ>CjO+b>cF5a2 F5G0`TsʌjQQ!*39DeF5̨^QQ|)LeTs!TF5ѧQ1}0BQE09JeF5̨2CTfTsJjtŨ(>\29D*C$U!f1UmUzj'ؤ>q}q1 bcOSCU0u$.C_ɺQl w}o q)knɡhH!5X@ /n {yVPD"g@JC+!I%WCU眿Un$$T* hމ kH_3qB)"  `|t [7sIfQdiqZ©qBJE:R KT%4 H؞fe4k( dѠ6 x+|BEbJ*"]s0p9n`n iDY)zx1ߤnl ȇ~t Š`CpQX:V_CM%@ +I^VȊ&fZ#+ABUhW$ODA5E4O+I!䦕QAh zHGFAx8 M¿|DeN!x _;lsQH\vr \jd+pIhI?Ơ5!3 "IML~oW 'D "VF.8苛1!T]hTt:-.jyP G .kSR{ s (|H lEɨS( .Odܳvkf:6@gFLn4 ʜF)xUX!+1HLX3C&dyܢv^ ˫Z͝G٫YCBە EGǢ}}*Gϭc.w__xr7wZ-{GҐY3۩OklCrĢCu 1;zhm5Hc2Sӿ0LQ$f3bxYχdlji&;='+݋xr UZ>- VJ5"S:%nrnv^um{R2 g/qGs>wԗ#Odl;Կӄ|XfϋevCH"Ly=ڠjw@g+!GyfiClf<^(#L@ghHAd[<(#CbUL2:mlщWCYOt2!++E$ )3~/0Ix ٳ\kr`R3CQw,$z̺*!椉3 &q#sHHfqhUlXZV_r՛'djuN$y|ۡT,VhFG[?xcGTfj ݱg\h" G8 P_.SN1h=_LfO JM% 6JIY[T Ψ(FօdULm0*縋)NqVLԤHTy d\itT"h>\Lݮ,-gT z5,l4zK ^XSI5yL45U+>Ѕ?A"nkIƴ< rXM]Sˡ4j9ӀB`t2&8 _:fOp.ja EU*Oϛ,5`mvb^2M/O8`K8yB9z.V_)map23OuUDm #.b#9BJ*A;ue0#PZ[0YcϤnkJif~frޙRzg!=I{-vg֭'FCja pIѭhR$`E% fKkKQnΐq}Bm"ͩ4Vy!ZMå 0 +?,n@fֵ]38L ΅s\'\2sTZh1!I""'cn"{J2hyA՗F&6/4F¸g2ay(h8fAg57x{)7YKoh+ss:Q{/WeY<.Wz0 3=4K T!r`O.R[CI̒1Wt[F%րU!?I$9x/Re}!~Tr;V+|V{ɀV 4*9npaԻ ]j@tIwmEfC)\/TƖ0֮o Z [>LJ3cBG},J)>᎖JU|c.o@d*|KXa o4+v5R돫X CԧVobd-䇞90KckʖfFL bv5JTD `JHbBܿ\sBQ}jD\:| ~IafvaznLl!Zc!FΠ~0vDA6;(~i &C8L\x} N\M}C4Wj~Mk ə/5`r)Js,DŽ4a]Y?<9qT/=N8ףw]7ylͳdv~b-֋+"J=`DnѮ2@Eޠ_bGl2 ˥ Q9p:Ŏ7 ª]ot5wњ[u]ot3{Ae X~  »ހP&F ubZst: Q0ݒW:\v~qNwNȱ4 $gh<^-`aWb+rKwk8TM^BS+PR(&@kZ:@" "XEnK,f ImN4#L)%2psd5{$WڑEKGh]9vW I6~ى2&HrDž&X4"`CrBuD{!a_&d$R3ڟT!fd@76 CJDK^)CP w]NFUet)\yjQ~  t}ȩF*#Y,3 JHZ+.sHo_!dBz@VWOy!ܤfUD 僂bd2+Y0&1:W!Z")Ua,kpU\D'*0*f|!rTC:-1tKE.7<8Wh??_5EV\(Y=G^9Ѻ{}+'y'-(T y;0џ:ࡂ2WxRY:HꎗJ?_J5ycS'X^ 瘎?#;ШIӔ >Lxq!8 *~t^yY ":/˽hV9辿^AGw( nvw;ң^o}/' )ruuœҎf92}rV<}G` u~>vvpRn {r5;z6!j?Xv FP{ۥj݉ox{Jx :8;r~ r: `VL%f 7c`ly uXÚQvmב,Z?^NK.k Fǚēg1āNrquR?G lk/*Uw_ۭpwYܝmK'Ț#B:7/mzwU'nV;DvЪHuATwo5;>- H.A'ԟ EUޭ~^4k wc.i8Άu%OfwXe=14ZVN, )ʹ#гWbg"8,U%)چ:no&DTEt*%P*qJWTFᗫ)2p(Z"3<1TMfSd Mbʭn٩V$KNV`%G&qmVr)2%>tT* JpJ|6kJ(%H܋30E4aĊU)RIJ 7|JFLTC^\ƛ<@~ʚlIU8NU$S6Fex+.x1j7FtI.df#|>:Tئ!1;Wᄝ;Ofw:6JԴ+WiqRlpR8mvS2Ðip2 qPp! p=hNf ph 5&>#2ܪ+2X%`cqU2čŤO:ͷ&Y$eJ\Rr Q|G662ƊbrK[{v6'Tqe:U[6';P;X12 {ƇcaAkKz(AB~[a# })\Ά6;ͩn8)¢yFX*0 c/O T0:Af ^J@Dl D%J@5?*SSFmUavXM+rkh42]N&TJ/x?Dtu{΄y%n#&P Gl"wWȪUGRJ`Z0fOt OS&+uC21gt7BCMf'En ˑl ;#Y5 YT;RBРȫbZ-Qm'= :aR"x](N^mrBBY{*O궜j)rL8J{QIޒ` U)M6Mg%:tI!d.?3Uγ1"ɑ_#IB L,i, CQUG# ZG-ܖjር;X8]R4-jWY{_,U\T f .YIY ht'H$& X eʋ4X+T!=Xn9dNWr_3>':E%zƍ؜t ='ZA2Fi63ֈeeiL -Pqv7% Xߎ!n$ xဳU5uZ?3v50&7owFg`o4Z2G^<) @\I~|.( ؖ bL_ bL\ @8P_`)Ǜd5="MY~D{sr5̀)ICp4P3хl㲘geCx8$A@N5Lmgi;zDElνt~S:Wj|,nso6gg}:fir_s"4e C0)M6p`vRzN(i5X=h ?ê)P\ҹD_ɲkMZ*jKv yrWxX1{1'Xd]}nu pp_ %FYSͱ/n#r-T@~j,Bo$Y=q!x6;jd,>*D ͋YNb"b9(K (R'y!+ujߣiڷV#߃nCBUEh T \@Dlc}n4 ?' & շ?M:g=ɍ|Qbw'tH /fφ4߰>С0u|:Q:0""4G8%,+E0vSdlJ6rW64+B?c5hm(6IMl+E 6KR+vr&KU* ޑ]Ջ4R(OYG;=Q @Wy'2[(r0v;ngy5;qB QPIQZ+VW}5aDf"L)MK,TzgxYAAn7Tz+qmC !YV\P¦(򚼇3sg!,ŢX˴G}~颋eE2:zsWS48(E}/}Ӭfzqq\%-]՛֧.*I]~/b; WEUm 73h9,Wed5W5o>ߋUG)%eM||>8.Ѭ=3!m6{vo˦)b.4O@<yx;eVKS\ٸ3ohܹ9u!tB)G`*0HgH4Th0AaZ64 k*˝F;d:<8yg$Sqp#д iRVA(+˥5VaH -IGaqґ)C:T ̸ --GXdvU`mqV[!53%F4!хhUNEa$rz⏔}N51 YO3"Eo}IٜMpc6>G3fIgBJ'sxx"ÀâXYMp & SghRFIc8j'G\\I]:i"<t,+ >`ur)i [_PK!≪word/fontTable.xmlX]O0}i A!canc-#ۥ:GhD*s뜜suOΞX=}?¹ωN~9Ƃk\X3^4# CQc!UNiq V`M4zDuE$iJ.E:e@2 2ZeYl3!G)Q 6Ô҄V"FS)C(0g,=Oxv0Oy ws6y/00IE8QL4R3ϗQ)v:͖G,YRtS5Do#!y$ښzI6;jhAƔ`룓ȩ]ťnvAΧvSh*wM']v7/8BYJh F ڬԾhW k` ]PV/ZZMM\t(i .I]›3@UC|};;{x\v\{H%lQn6Iכ74O:ɴ]Vm_,K#] {U#'lW$fWKZΩaO+yp%rn-ZR`UC2;-%.2ZhѪTߒ)9(7ks`?ȏ}'ͭ|ԴlmcدiՈm[bveNPK!1wdocProps/core.xml (N0Msh ۜ5;Pxִ߶F(Ż,0pxXd/` ƪRO @R*lQ`ג祆):El"*&J86&mh\0b '.KSpf+. pLZVRjcF  bQ:0B39! -E;U=])~Y?6J] @D & pWT<;̹u _R:`1߉[Ut=4&dd#wvҦMYK7yNo9}IHhHMp:ֿǵaM[ PK!Xpword/numbering.xml]ے6}߈ EԣytXucwR-(VO' !! Rd5jQ$E$3of}Ƈh7*ܮvxxClonG_o}n c8 ={گƣ$ٿ{7&ZŻ.ymUi߾54]ǻUx8}f186Ż~nof~ _AD(֜mvC}%bWąVnz|z؄ۄ8\3춇h ٻA(jf}4zwtw\yX'ce!}:Ӓ~}6daX5GrI]ogA_doU >f]o_oCLZ=9#~54r- O-|Ϧw9k_^Y/xKVОv/aQwӻ8}rMкఊ ?~Æ7P??ǩgFo]t|ߨnz+@%7/7qt#EפMw|t#ȽEpSt&Tq@6 "\MRjÈ]βM@(&+ZƮC1b~G(.g[#_eI10 12'䏵3Y0a :a?ciX"O_˘j&jg<`<$Al*,>N5E1G.M[p_˘Ԉv&d0AĶ%N2&/݂ Nõ   b@m)%oix|拙>w28Nsoհ^_PKpxRD㺌! ȧ D VJGwɁ^j9y0ح{>n"1ֳQ`y(g",z7Mr0 R(=8(l`5wqQٮdW_qM9d_}.e@6p@vn/\dL,]SϟJHBylƶCZ=A42Y:#f9`KYn}JŁ-!e 0[4w^g`(Pw Wr3&ni= #Ј4ElQE 1Nb.IȢ[h"nPIl!8l(Dl7m={{pӆ3w&R"]Jy60 Ȓ͠nZ߯JٺLqeXȦ9vϵقm&jma1[^T -lǯrhffC[3* rmM)"C+qM\Gр,̅7M ,l["L֚/R@V.VV8dk"NيS@V.d0&ᴽEL/: K3^f&dZj lՔse3E' 0 Gt# C "8Qa4"nPQ 7a2܆ĮnU 2'}iKT\,NYl39yzT5r&N.IΒ+]S N"zyPS#C]o˛;RbAZ1 Ȯ,utWH%0zE],DS0mr2)8h<^ިj*)VQ#WJY@c^*GA.I5P/TIED܀F4aXpf>3-+YR'Qf@s4˚l %.IUuUS Ӡ`UU dA Ȳ1wӴ(d;Ϙv=eZX\˔ $Z:-Н/4( vl?C]Bs4ao= Hfu+gM_ {[Wǻ@qIH[_Q@a.OeoCZ]yWXG^R( eo=Kt+e[{aNxȦAtkz zآ/g E45 ]n݃UrK`(g8 73[08"8˔8"8[8آ8ۓ/qEq-مwݒϻebORY/"@ _ЗΖhd3 }-̫=eu6MofE,T+i1LUpeQ0drS W?OW~&PBw<:fu(?;&mx<H$mgג5DddQJiZYnOYIRC fk* EZ0{Քqmlq%P@ 1\@!I +ls:G B:2SJtdXã4n/]mnvl*F~ !j EM+B~#pCf;io$>r8h;B n*g4g3NÙg4k$- wNr5:~wJVA~F[GV=l{4Y r\;$$l;tlnvk3) O9a WΏIΟB(j{\ xw~( L. @ao4G[(\ɲfk2_nGXl*᥾pHNdqu};0Mm$cHdjZYk٭*y)zw+Ӳ NXŋ28~qShdwġUB8]yG#1% !JW»G\[[Pllj "_x\7\)!k.@RB4WC_UJ~e *o[F*#zw S*`¼׫1l(&UUnPBUnUoDh{ OE*% #תrXqrY!e?SƸUn(f;\N:Vnp vuqnc$?&_! 4|sOYfZq"wTځ^% t =3'*].JpS'D-Ueʑ*0[g u=]"1C=-rJ@U誎GR YE̖dw!ʥ|@q\P$zFf3Ȇl@&5ViEq8,öui"n@@uugw"hDFh=$U)FiV:3}{~:jS8n{Ƈ M.͕h {3lPQU{ЖU0m(mEp-S@E{JKN`[uh̛hUb쀠.UZqmlDܠ-" 'J^$lM "i%>YSJ[rW-䏱|I0d8UU%>x *ZDêSѲ1wrc܀lqs4GZk/Dlg!c=/dIXU *Ii&ТY5O0/E,{I>_ܤK :vnM_ ;ֺɮYֶ$ qXk:d=ZV@϶Us)X]+F(u%%e9@3UlV15blc^I&GbWmM)AE)Vnc[ܹ,טҟy-M/HEc]3]@Vn t$┦RnB.v( 4 %EqYnʦ7N%l935pw^KJ leYl}8DSV&8N!{J,J*V1_+-n6 Shn[׳k"""0-v/鵞JzHSSz@ #EXu "8l@M Jz(7s̽@vḚfMmТ zlF ,*`[)`+q D\ su]w2рl9/_XKkYb#NԮi*ic%=YUZ꧐ GDTFK4\j8ll{Ӭ#PuzVٓ]p l:J:/K RVƋ|~;_g~c V1& ʹD_LQ0}OA2Nդ;8x9z`a,eܱ,.ؿL[%]w d[Zlr.(0R{Gœ?N6%mގi)mJ&(mWPi]$=]zk10k=EQgx-m6c/*ua%#8I4nQP%p+p{5OCۻCC ǣ}ۭ7}3D\еыlLʌd·`ΜjxfJI4;dTVd5yZ/ [S?E@V3gf5v$:sUIxGdNIsv!N~1Fzg4_ں>X[g_G !(vmw08 WYiaL7!\C6[ڤz'/fN*>|mtj?]`$ARu z&`v63ȶ$63 N3>iݛRJ S\;& TƇ}:SʫmkЙnӘ;M4NJ8^/![ZnU)y~\}nRm'@n._>ˆD9piٚf>E[ w,g ]E{ĜHLIcpnS p3h'{B5' [b=aqph6EO LI+MDXKr`%8|(!|FRQl7y9mO3DCc|s9]7 1&gsR$v:H%tyknoT|s9s>kHMiDMӕA7mm!jBu*sJ?06gӗgrMVQ@>W|dmD ؆aǠ -_0 MuNv %À2}o<rI*DIz3[sNbIOv8!8˔8:2s95ɮ1Éh"$:WqPQr=Uk ld9]̥eyα͸~i8jZX@׃8|]Sa"n݇Y~*[DVS)r AdSND&ojk .W5iNo#Ze*7=BcDʢ}su)AyzMx݁E= *ZMA`N`q@8&l)Qh"NA`YAD8"n@;_-cUdE ә+]P. voD U6xXSm+m |-ffU+G4 7rasdHY`35m+]l D wk ϰnuB^jhAk٭UliYrO7ZIedZA'ٿqh dW_ш?L3S2@Iv#ԅM'Yi$.S"u&©]KK O]/8_'zTQz){̔.XVtPzq,Tv]Z41 %JK+uĈ+_(.pKitX"BNAT.t* F .8NZQvUUՋ^#T .+6RzqRyTE!̨P8. ,T7iᥪ') c(* _8(6?Xl$`P^n*~PK-!˭ [Content_Types].xmlPK-!N I_rels/.relsPK-!/mword/_rels/document.xml.relsPK-!GP#u word/document.xmlPK-! F]word/footer3.xmlPK-!.sword/header1.xmlPK-!d@word/footer1.xmlPK-!YT *word/header2.xmlPK-!@Jword/endnotes.xmlPK-!H;word/footer2.xmlPK-!׀Q@word/_rels/header1.xml.relsPK-!word/_rels/header2.xml.relsPK-!3 `&word/footnotes.xmlPK-!)0word/embeddings/oleObject1.binPK- !3tjj]word/media/image11.pngPK- !3tjjLword/media/image12.pngPK-!sΖMC;word/media/image10.emfPK- !   word/media/image13.pngPK-!)0word/embeddings/oleObject2.binPK-!Fg]6>word/media/image8.emfPK-!0C)word/theme/theme1.xmlPK-!蒬word/media/image1.emfPK- ![zz}z}nword/media/image2.pngPK-!ezGword/media/image9.emfPK-!蒬\word/media/image3.emfPK-!Fg]6!n word/media/image5.emfPK-!sΖMC word/media/image7.emfPK- ![zz}z}1 word/media/image4.pngPK-!eze word/media/image6.emfPK-!AK word/settings.xmlPK-!Z]T! word/_rels/settings.xml.relsPK-!s0%$t" word/styles.xmlPK-!UG customXml/itemProps1.xmlPK-!t?9z(I customXml/_rels/item1.xml.relsPK-!\K customXml/item1.xmlPK-!*5?HK docProps/app.xmlPK-!k%'pP word/stylesWithEffects.xmlPK-!~XhƐRv word/webSettings.xmlPK-!≪J} word/fontTable.xmlPK-!1w$ docProps/core.xmlPK-!Xp҃ word/numbering.xmlPK)) r libdigidoc-3.10.5/doc/doxygen-license.txt0000664000372000037200000000105313560273131017676 0ustar travistravisDoxygen license Copyright © 1997-2014 by Dimitri van Heesch. Permission to use, copy, modify, and distribute this software and its documentation under the terms of the GNU General Public License is hereby granted. No representations are made about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. See the GNU General Public License for more details. Documents produced by doxygen are derivative works derived from the input used in their production; they are not affected by this license. libdigidoc-3.10.5/doc/openssl-license.txt0000664000372000037200000001432013560273131017705 0ustar travistravisLicense This is a copy of the current LICENSE file inside the CVS repository. LICENSE ISSUES ============== The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the OpenSSL License and the original SSLeay license apply to the toolkit. See below for the actual license texts. Actually both licenses are BSD-style Open Source licenses. In case of any license issues related to OpenSSL please contact openssl-core@openssl.org. OpenSSL License --------------- /* ==================================================================== * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ Original SSLeay License ----------------------- /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ libdigidoc-3.10.5/LICENSE.LGPL0000664000372000037200000006350413560273131015046 0ustar travistravis GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libdigidoc-3.10.5/.gitmodules0000664000372000037200000000015413560273131015451 0ustar travistravis[submodule "etc/certs"] path = etc/certs url = ../certs [submodule "cmake"] path = cmake url = ../cmake libdigidoc-3.10.5/cmake/0000775000372000037200000000000013560273132014355 5ustar travistravislibdigidoc-3.10.5/cmake/README.txt0000664000372000037200000000011713560273132016052 0ustar travistravisInner component, do not use. Contact our support via www.id.ee for assistance. libdigidoc-3.10.5/cmake/modules/0000775000372000037200000000000013560273132016025 5ustar travistravislibdigidoc-3.10.5/cmake/modules/FindLDAP.cmake0000664000372000037200000000125213560273132020350 0ustar travistravis# - Try to find the LDAP client libraries # Once done this will define # # LDAP_FOUND - system has libldap # LDAP_INCLUDE_DIR - the ldap include directory # LDAP_LIBRARIES - libldap + liblber library set(CMAKE_FIND_FRAMEWORK LAST) find_path(LDAP_INCLUDE_DIR ldap.h Winldap.h) find_library(LDAP_LIBRARY NAMES ldap Wldap32) find_library(LBER_LIBRARY NAMES lber) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LDAP DEFAULT_MSG LDAP_LIBRARY) if(LDAP_FOUND) if(LBER_LIBRARY) set(LDAP_LIBRARIES ${LDAP_LIBRARY} ${LBER_LIBRARY}) else() set(LDAP_LIBRARIES ${LDAP_LIBRARY}) endif() endif() mark_as_advanced(LDAP_INCLUDE_DIR LDAP_LIBRARY LBER_LIBRARY) libdigidoc-3.10.5/cmake/modules/FindMiniZip.cmake0000664000372000037200000000163513560273132021214 0ustar travistravis# - Find minizip # Find the native MINIZIP includes and library # # MINIZIP_INCLUDE_DIR - where to find minizip.h, etc. # MINIZIP_LIBRARIES - List of libraries when using minizip. # MINIZIP_FOUND - True if minizip found. IF (MINIZIP_INCLUDE_DIR) # Already in cache, be silent SET(MINIZIP_FIND_QUIETLY TRUE) ENDIF (MINIZIP_INCLUDE_DIR) FIND_PATH(MINIZIP_INCLUDE_DIR zip.h PATH_SUFFIXES minizip) SET(MINIZIP_NAMES minizip) FIND_LIBRARY(MINIZIP_LIBRARY NAMES ${MINIZIP_NAMES} ) # handle the QUIETLY and REQUIRED arguments and set MINIZIP_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(MiniZip DEFAULT_MSG MINIZIP_LIBRARY MINIZIP_INCLUDE_DIR) IF(MINIZIP_FOUND) SET( MINIZIP_LIBRARIES ${MINIZIP_LIBRARY} ) ELSE(MINIZIP_FOUND) SET( MINIZIP_LIBRARIES ) ENDIF(MINIZIP_FOUND) MARK_AS_ADVANCED( MINIZIP_LIBRARY MINIZIP_INCLUDE_DIR ) libdigidoc-3.10.5/cmake/modules/FindPoDoFo.cmake0000664000372000037200000000153413560273132020761 0ustar travistravis# - Find PoDoFo # Find the native PoDoFo includes and library # # PODOFO_INCLUDE_DIR - where to find winscard.h, wintypes.h, etc. # PODOFO_LIBRARIES - List of libraries when using PoDoFo. # PODOFO_FOUND - True if PoDoFo found. IF (PODOFO_INCLUDE_DIR) # Already in cache, be silent SET(PODOFO_FIND_QUIETLY TRUE) ENDIF (PODOFO_INCLUDE_DIR) FIND_PATH(PODOFO_INCLUDE_DIR podofo/podofo.h) FIND_LIBRARY(PODOFO_LIBRARY NAMES podofo) # handle the QUIETLY and REQUIRED arguments and set PODOFO_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PODOFO DEFAULT_MSG PODOFO_LIBRARY PODOFO_INCLUDE_DIR) IF(PODOFO_FOUND) SET( PODOFO_LIBRARIES ${PODOFO_LIBRARY} ) ELSE(PODOFO_FOUND) SET( PODOFO_LIBRARIES ) ENDIF(PODOFO_FOUND) MARK_AS_ADVANCED(PODOFO_LIBRARY PODOFO_INCLUDE_DIR) libdigidoc-3.10.5/cmake/modules/WixUI_Minimal2.wxs0000664000372000037200000000527213560273132021333 0ustar travistravis 1 1 1 1 1 1 Installed AND PATCH Installed AND PATCH Installed AND PATCH NOT Installed libdigidoc-3.10.5/cmake/modules/FindLibDigiDoc.cmake0000664000372000037200000000170713560273132021566 0ustar travistravis# - Find LibDigiDoc # Find the native LibDigiDoc includes and library # # LIBDIGIDOC_INCLUDE_DIR - where to find winscard.h, wintypes.h, etc. # LIBDIGIDOC_LIBRARIES - List of libraries when using LibDigiDoc. # LIBDIGIDOC_FOUND - True if LibDigiDoc found. IF (LIBDIGIDOC_INCLUDE_DIR) # Already in cache, be silent SET(LIBDIGIDOC_FIND_QUIETLY TRUE) ENDIF (LIBDIGIDOC_INCLUDE_DIR) FIND_PATH(LIBDIGIDOC_INCLUDE_DIR libdigidoc/DigiDocDefs.h) FIND_LIBRARY(LIBDIGIDOC_LIBRARY NAMES digidoc) # handle the QUIETLY and REQUIRED arguments and set LIBDIGIDOC_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibDigiDoc DEFAULT_MSG LIBDIGIDOC_LIBRARY LIBDIGIDOC_INCLUDE_DIR) IF(LIBDIGIDOC_FOUND) SET( LIBDIGIDOC_LIBRARIES ${LIBDIGIDOC_LIBRARY} ) ELSE(LIBDIGIDOC_FOUND) SET( LIBDIGIDOC_LIBRARIES ) ENDIF(LIBDIGIDOC_FOUND) MARK_AS_ADVANCED(LIBDIGIDOC_LIBRARY LIBDIGIDOC_INCLUDE_DIR) libdigidoc-3.10.5/cmake/modules/FindXSD.cmake0000664000372000037200000000366413560273132020277 0ustar travistravis# - Find XSD # Find XSD includes and executable # # XSD_INCLUDE_DIR - Where to find xsd include sub-directory. # XSD_EXECUTABLE - XSD compiler. # XSD_FOUND - True if XSD found. IF (XSD_INCLUDE_DIR) # Already in cache, be silent. SET(XSD_FIND_QUIETLY TRUE) ENDIF (XSD_INCLUDE_DIR) FIND_PATH(XSD_INCLUDE_DIR xsd/cxx/parser/elements.hxx) FIND_PROGRAM(XSD_EXECUTABLE NAMES xsdcxx xsdgen xsd) if(XSD_EXECUTABLE) execute_process (COMMAND ${XSD_EXECUTABLE} "--version" OUTPUT_VARIABLE EXEC_OUT) string(REGEX REPLACE ".*compiler ([0-9]+)\\.([0-9]+)\\.([0-9]+).*" "\\1" XSD_VERSION_MAJOR ${EXEC_OUT}) string(REGEX REPLACE ".*compiler ([0-9]+)\\.([0-9]+)\\.([0-9]+).*" "\\2" XSD_VERSION_MINOR ${EXEC_OUT}) string(REGEX REPLACE ".*compiler ([0-9]+)\\.([0-9]+)\\.([0-9]+).*" "\\3" XSD_VERSION_PATCH ${EXEC_OUT}) set(XSD_VERSION "${XSD_VERSION_MAJOR}.${XSD_VERSION_MINOR}.${XSD_VERSION_PATCH}") set(XSD_VERSION_COUNT 3) endif() # Handle the QUIETLY and REQUIRED arguments and set XSD_FOUND to # TRUE if all listed variables are TRUE. INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(XSD REQUIRED_VARS XSD_EXECUTABLE XSD_INCLUDE_DIR VERSION_VAR XSD_VERSION) MARK_AS_ADVANCED( XSD_EXECUTABLE XSD_INCLUDE_DIR ) macro( XSD_SCHEMA SOURCES HEADERS OUTPUT INPUT ) get_filename_component( NAME "${INPUT}" NAME ) get_filename_component( BASE "${NAME}" NAME_WE ) list( APPEND ${SOURCES} ${OUTPUT}/${BASE}.cxx ) list( APPEND ${HEADERS} ${OUTPUT}/${BASE}.hxx ) add_custom_command( OUTPUT ${OUTPUT}/${BASE}.cxx ${OUTPUT}/${BASE}.hxx COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPUT} COMMAND ${XSD_EXECUTABLE} cxx-tree --type-naming ucc --function-naming lcc --generate-serialization --suppress-assignment --std c++11 --output-dir ${OUTPUT} ${ARGN} ${INPUT} DEPENDS ${INPUT} ) endmacro() libdigidoc-3.10.5/cmake/modules/WelcomeDlg2.wxs0000664000372000037200000000751613560273132020705 0ustar travistravis