From 5b27d83c8f80397922242422bc2b549bc9e8efe5 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Mon, 27 Nov 2017 06:24:36 +0300 Subject: [PATCH] version 1.3 coming --- README | 16 +- bin/loperIRCLogBot | Bin 0 -> 192376 bytes defined_values.h | 47 +++++ loperIRCLogBot.c | 467 ++++++++++++++++++++++++--------------------- 4 files changed, 310 insertions(+), 220 deletions(-) create mode 100755 bin/loperIRCLogBot create mode 100644 defined_values.h diff --git a/README b/README index af783c1..fb1c5b5 100644 --- a/README +++ b/README @@ -32,7 +32,7 @@ Is it possible to let this app work with shared libraries of the libircclient th Yes! Will update Makefile sooner or later. Where is the application configuration should be set? How? -At the ./bin/bot.conf file. You could generate template by passing -g option: './loperIRCLogBot -g'. It should stored in same folder with executable file. No other option for this for now. +At the /etc/loperIRCLogBot/bot.conf OR ./bin/bot.conf file. You could generate template by passing -g option: './loperIRCLogBot -g'. Configuration file contains 15 lines, so make sure that you didn't define any sensetive information below these 15 lines. Here is an example: server: irc.example.com @@ -46,6 +46,7 @@ maxNickLength: 30 logPath: 0 link: http://localhost:8080/logs/ reJoin: yes +floodTimeOut: 10 'server' should be set as described. NO "irc://" or stuff like this allowed, no slashes and backslashes. 'channel' is the channel to log. Should be started by '#' symbol @@ -56,16 +57,17 @@ reJoin: yes 'password' is a password for the nick. It goes to server as '/nickserv IDENTIFY [password]'. If '0' then no password needed, 'maxNickLength' is a maximum length of the nick. Various servers restrict the length of the nick. '30' should be enough. '128' is maximum, but I'm not sure that you have to set '128' in here, because if server doesn't support nicknames with such lenght, you could face to unforseen behavior in the application. 'logPath' is a path to 'logs' directory, where all your logs will be stored. If '0' then they will be stored at executable file folder. Pay attention, that logPath should be defined as full path. Not like ~/logs of ../../logs. -'link' is a link, that will be provided to anyone on the channel, who starts his/her message by your nick. If '0' then no link will be shown. +'link' is a link, that will be provided to anyone on the channel, who starts his/her message by your nick. If '0' then smile will be shown. 'reJoin'. If set to 'yes', then bot will be re-connect to channel after kick. If 'no' then it won't. +'floodTimeOut' is a time in seconds before answering on request sent to us. Is there any other options for this application? Yes. When you start application, you could pass next options: - -g, --genconf Create configuration file template. Attention! It will overrite your existing configuration file. - -n, --nomessage Don't print any messages anywhere - -v, --version Application version - --help Help message -Pay attention, that '-n' is just for turning-off messages, there is no stuff like daemon-mode inside. Yet. + -d, --daemon Start application as daemon (experimental) + -g, --genconf Create configuration file template. Attention! It will overrite your existing configuration file. + -s, --silent Silent mode. All program messages stores to the 'output.txt' file + -v, --version Application version + --help Show this message and terminate application Any chance to log more than one channel? Nope. diff --git a/bin/loperIRCLogBot b/bin/loperIRCLogBot new file mode 100755 index 0000000000000000000000000000000000000000..f7fb5867cad3be89e83913b25497bfb1090f724f GIT binary patch literal 192376 zcmb@v3t&{m^*??S5{MDlsHjnCUF=dw<&pRVM9q?2xvLw95EQitA=!|WkfhmN9zHO* zyUKN0OsiCC>$g-}rPeC7ihz=YXYd{IMSVu<<6h%~`T#^F|IcUU-px(OQrrJ;TQhgg zoH=vmoHOT~nLE4O>Yo|dLqpLFFSg|)^X6$+62t0;>2Nlm|`HR+%MQ6{R1_4E#4PT>{3X7m5d~94f(zRazXf&BcV=1uyN zf!~&5T&631>E)*>@V`g_U!Q``gDK!EQo!F#!GB>2xSE2_k5lk@N(wlmZ(nklmxBK0 z6maGpebHH(g8r2$=5=QZ{H_%Eds2*hYzjK7K<79mSLxV22N=lr#9u|(f|Brkz2JjD zpK#^nIRewdSCHS7Go3k43D%X*4}_FpsG+=mi4s^`jpzD?>e^7HQdw6YsAWrS`GR_u z4dqo0%Iw*AstDKPp&FgXkDnb3mY3C5D&=*xwSn>w;FT4Dn$Ya>s`*NFZ6GweHdI%p zRE7dIHA;Or6a?Ld`GQPY`Fvu{t}LrYQ>dyTP*yQ}K{ymxJi7*Lfy-cs90Y1ecftIM z>IS83Ze0V}t*92PRfeh;1bX$Y2!O-7B?@Si)v$eb1Gx{?&6h=uQW>bLRDw%_HFfip zd4W(>T`)9vNo|?HtOOvapeMQ$zeaEn0_uXYASeWCD-;TbeHR241R*^1D6c9LgP;SZ z7HDXwt>YZZLe+J(%G_%7sSE}J^Of={PNL^r!=Q!PVor78kkSw+Unu2PR#DNwA*h(j z@|wC}0HhZNYo&UGd@(u|SXU46Bss>YN?0-rt(FA?R3CV(4+I)GNl+;dEvXO8o=X-v zF8HNF?3AesB){{O%7#F<9hk&0%UX_N%1#jNIj8Dc7*ge;hU!p&6v`?6X`qYB&d*a4_D2 zx`hEj5)zm_n^q6&Eo%tPUQh=60b>-#Vt{D2^A^qA$S8B$=ZM+>{N?!H3x38*K0sZSYnb{3IKEmkoZh z4c=~pBg!T}du(v#F4m{R20zsTqSS5h(`@j4Hn{ze;GhluBOAW*(i~BvjWCz8K3O*S z=@t-Wjt%a#!EPt{V{Gt78$90zUv7gJ*x*ez_*pji zY8(7)8+?roF2ai0w$=te*M`5&20zaR-(Z8EZ-ckm;NxuYT{if58@$~HpJ0RUvB58} z!8>el?#Zo>Zi8QF0a5O=!7sAG58B`t+u(|s|I+>oZSX7`+--yB*x-|F@LU_b$Od=X z;2s-%qz&%1!SikKOKk9QHuz*4ywC<$ZE)2F_u1ejHu$AB_)Hu8G8=r34eqzWt8DOM z8@%2IpJIbAw!x>`;EgtTi4DHo2EW_}Z?eIs+2E^f@aZ=A8XLUS248D~b5Ce}*4f}! zSU{9&s9P&bade}{2A7n z5*Y2GzLj;R0!FK-Z(^M(fU!>0A7!1P-&iB+53Q}SQ5N+%`48ZVdtTQwl9io0I>&LO)F6xt5Kc4kgQJ=v239PRZ^|M%K=rz`e`p;Nr z$TgZo{S4MmV!ct+Pi37U)~FZt<5_2DHRgzVHtP(jMv17Wv(8Xz6pH$x^{6w18u_CB z1?vo*hEvo(W}P9^$Px9utTR*^im1QAIzyzf?|aUFH|tK;J4F2%))^9wc2VETIzyq+ zD(ah9X9zUbiTb0gGxQm2MEyb5hqK-!>i4qF5NI@t`rWKE^cnS{{%h75@{Bp6ejDoy zbw-J(-^@BgoKYz1*RjsfX5@={1M3WFhEvpk!8${kkt6DJS!W0{6j8sLb*9wDzVC$o zS!XCSIz;_a)(co~7xhW3pT&Bss83*>ASwXeP-UzU^`EiM5M?xp`WdXB$9kiv zpUV3Atk;YB@vJix8FNHEn{|dDqeRrxS!d`m3Pt_U`+RsBdDOA;VZF>W{L{ zP+_bQ^#@sJh%lN&{a)4?8jMC!zngW21fyQmf6Y2WfiXwaZ)2Syz$g**n^~vpHws1l zI@am(jeJpWV4besaEkgbSf`6OazuSD>vZjgBI;MOPM2=%J0$eaI$gQZA?la1emU#y zqCSarx^AOY)F-e`mu;*=z2H-y_R_VgwpWe3zptd!*Vfv&x=>Nuwm3!6Hm?Xi_QXpb zbt+#uPKT5>ybgywLml0YLe)M{BL@dBJZ%H02{(OQ3*oc6Iw~EfM+sDBZKId29Anj+ zi7-Q5_L)Us%i(^iwol!nU#zC>R9`wAIx$J@Sc{tDbkG4wjNf?SOOH7fC4AfrjIP&0 z0JC;xHUpG~fzaNP`vMq?T&#pMJMTchB(Z<9Ls$DO<2v-=v%2h)5^Nn+ZS$_K!(H0r z+woV`R&790p~f?Yb4jb3_h3P5TkI_WIh)94VkwT;Kj5&Nb%?0tWBkz6vYrpPe~OI6z>M;f>DA%9Kq*V0fzbf~vLYdx35&1z!7YvUV0`DOP`NXUkg5TJ+XG=_V}X#lcjp<0GVX3#9em%jiN#)+VE8es**jH3Qwa z8o~ES83oZq8FfO`k^ewu5y_kYGBz3CanP<~V>Kk*L(Q4ga`Obtk|NjvY~(eLXm#Is z7vEhd@J2&(5S0#v!?0Muu+F6xp)Azmt7so;`EGT~-hpb`Rxl)RwVkT=x?XpntE<@q zQY{!((di$05es9stMZ14%p#RxX;7gt92rcXV=mh&?6vpMU+u?Oee&4eteTUf|6_7j z)m)t9abh=*otN}UAjN=1=xC$!745F4;KJ)ntxJO$>{xjX5{hn{Gj2te*yoUG?afn7 zo^K$3;CWyqL8p*rTy~UBSD2k9_w1BzoOF~<*P5M<@7XECcrT^e+ndYHPH%JC-Rxx< z4;`gbmDy=+&rUhUqN8;BrP(Rivy;=9bd*llnVl}`*{RSNbd*jJv(qtVC&w}&@UtwCg2wwb2Zg`7V$Ixb?7mihkhVe~$IMuI(GW5I^7WogUY2sD0d zR{kgKZBj92S@}tz5Ni$R_lajMz;+d$-i0Wn5BL%TdXGZavgzip1l@xFM7K?^fd9}k z)6X5I7@t6veRjaIv{qO^68<3!PY1(Sd;x~nG3bQWb+iPIOc~m{886qo`X40KgP6$dW2zJ9i4L!+^tt8jtwEgo_)qJ zv3EU95sccim zD#prGQo!o6JmLVD3A7YCI(tcJ?EzCjKe4hcb8^`*<$}DOnUhc|1~2CvoraKX9Fl$P zGl=91sI*Uf@MbyQ`Esy@ed2X%@)1*$69sx`?0-Q2hlxH&QXklsc|Fb)z`oKsr!BKi zoG;+Hv`;eN&hqfjLsJmNs6O$M+%Y2zLdII=k3hM12$+gQphdWssSpbC@_6QFQ{nwr ztK+vWbi^~?6P2BfL`fMFwu6z*a=Cv=3;#HkCEi1{i4rY6e3s4L1p`0+6bz(@I&;}I zt;uXw3dq^{?2vh(0~GF1LL`o>q|xr7UQQJxu|0XA3113I< zGvt#RpFvp-v1GNpdkE}N#SU-to+n7-@pe(H+9iraD+-SmdkRG_MliDuKsRmUkem(q z=noS!8`R7!p@TO4Tfy8`3!Ydm8lYn_gxFbT0R={!CuesXZ9v-sJxiXpV*lB~A%wW} zlko&2@N!0S6AkUJ2Zf~e3o#>Y^IL+xeL_EE3PsRqMD)cb{5H-jo_Sn=sn9ARnmlmR zu3k6_{5V$r8tw7SLlwgmaDQH(Gu*Tt0x~zyznsTV(gyV8Y&x$5{l5d!i+%?%mYQaA zj+l4nXvtO@tSTOpYRX)Mo^6?7{N+dD^=(zFKDG(ye^a^C&L`5=j?|966e*-BgPvyb zIn7mSv-xQujyC;k$f8?d8Awb`j7^-0DX_-!K2-gzVVg+~&atr2bN@k;c|1oHtFlCq zP*A{lzkBou+!`=w3KK@QDB1i3bSF*z~Y6069Gx@_yfd{PtJ>|L^5G-MLq z{EjKcYvmk9vP)z$3vAyv$wXO941-^H#NhAQ2mcn9f%#E(&7YcN7eU4_=?ej;6xB#8 z-jyKtmBL7@60?ZMIG#`2*Zj5YwgJ;o^!ey(+{e_+B%1!aLQJGhKjXh6dW`HQiJnBF zQ*1;}Fo`~|3r>qHPUGX$#N$FKeKY$F`OUSHei9UnFPR&e{GMf!ZjhuewMYvgjI(Mf z#UVx*Zy(_*j=+2N)(DrIBjm^tuC-`JT5~97yU?@z2syNw#O8WY*k#XmSXUHlTYTEV z=9%^pKcdPb+jET5Y@^1^QSU}0PKIJUK1BGE)MJ9WJgZwG5u)$F33W3A*2EF)APW>P z%<0VBzyJW}CCy}OmOq}JLIJ`$$#IF`cwh5v;74kAoW*X998uWfpG8Lz50QW%0>SbU8n3Ug}x0GEUK14-Xy8kTU3RtX(Xmkk}+K*KcxcI5t|5= z#bXm;n~{TQj@W2cH`C{;ap8es8+4s&TzcntjK12f9poey;NZph)+RN}{~UNHxa=N}k(jBQ-{I&;#>qoM-m#hNkdOtKb-l*{8PevkL3?S_GVt9jQYJM2Sx!xk zqBQ@Xv^@RCpoPFv@`KqJ0ye;{WK;0B>3%^=Xk+TN*z~QFPQw~%n>o}!gy#Q?q5g8< zh@qb89_syB7|Ppos1MDdR5{eNA3UpzI25)ZLI?KAnO3`qgY6L}8#Cv%3CV@hEVIcr z{k3<69Dn$T&+)iCZW4nl?_T6dIEXMdH#2lqEAH@U-nZg6zJ;w)2lg_$8b=e>hH0w%aG1zy^R#=U zb6ky?G$j{GNt0M8+)VUZ3^3j!H!*Hlu48>>VzpD5IDYAXotZb|iRXSq?e;=0FwCuT zOh@pF=;?B|yuhmWQ&&6IM>F-duC9qUgo`XN(30S>OGotu9)Ht`78pc!N*YS%2^J6} zEZ`AL-Tn@k0yD`mZV2Zcf%FR^;Y}MRx%MunvOIbsx$Hc>2jV6q4odSb@e&sKE4l!E z3D6_0Y0ER~@c{I7b)>XP2xi$qig>bOTr?UND$HfD)BA~&y;AQ$=ndi-JS?8 z1Nt(N-EZ4Wq!1>uM+?6K3)uw=X@!Nf_tI{B#w%*V+tEBjT7`^yf9t?;_l>Xo9Sb=; zP>p-{klB}U1|Gk$9p=>v^V+2*!Z0)M9@D&j^<^Kf*xSv_vQOsV?K)rcGR|p_w~Aub z22mu|p@1uX2t_acAb@s2du}?mVXehC6B}!kec_`8rMRSveKUY2X9sYshqRyVNc&%; z=#x7V0yo)qB(9lk6}e>dOmm%-yeWg@YW9rB#Beg?H&t=OJ!o8C-;-sZHOA@ms3?0O-Yd5_W351oW0B!p2w@){d*a8825 zq#-T)Sj$MF{f21dMqVAbpa(zLzx2t^4q}=746HF&EtjddBY#C)Kv>6L@5t(A>~<scZQj-5)k~Xq z&9#`Z+U8wbF3WY|6-S$QgLoy;=4};Qp!qB$7yjN@giJ*;;;9VgU4d{p3zVTZ_Ljgf}hh)|gaox)+1rj6eDd zV9_@CY*4Xy#o=WO-Y6>i#~5i-E}oikp+RX`!G8ULs4v4G&HG*C#_yCRKW_dV;4RqU zo3f!j%Nb<@jW|oQThOZLhuHEsu=RDXa|NL92GneQcVR@?_XXmLUKxPtQ^Bt2@J7!L zcO^UAgATfmKi!Od(i3-n68D!tvoltPI;3=6lT=Z+l-7bzO6kYV1Mcg==;=vX!)4zw zW?!M+(}AqlB>NWj?E5dwMNZNH6^#4E?Na5ZvPV3#-w~vSB}p~*B(*w8it8JF+d!%h zGgt?_=2rH_36rU(p95y*TJ9^{Gu)-qaqp?{Uas%w{tRM>hbZi!Zx1g#y#gThq9SbI zn0gbxOT@+TFV4B@RdnP5`jD1`tdB%py1>!_$u6|ZKM+ydW)f*ed=ciF^&0!PrV-@^ zqU3E;wLQq1I27(!k+F0~ES3iJc#QnX6E4BQ8Gpiv3qb)28`6@`+S*r4H)ym~Qc-fNPZ(uep`F{cI ziX`l2z)X!S9nw<8#_`F<02(2%HM5|h#42j98B7Ts-wnG%)4B&(B#2>8FwX-ANNCW= zldgdv_BtMOri5rS2=hh~Q`079Is$ZmZ^_I=#Ej6v@_{^BF(yxh_dZxCT2sSC*4>?AgXc#mWgxg|Gz-hlgJm%u@Z{x*dJsx+TCmv_wan?lfxEPP8juww9 z9$%LfvbrC0x*wh0k0ZMu$8|pzc0X2iKjwEoHkyxea@%EJ%0sbS*7{!BJ6xue)@+;zS z<_*qxMUv}1?cn+ocsCjP##5Q%g_@+4e4(a4iwR3QE99YC%l%0rcaTVcF0w6l5L0hz z@5je|6c|3D+eUb8%y-o~r~q$Jzr!n3?V$FIwrUTswAfqt+XFA3tJRLzA@JVEU&$)v zeFUoqWE%CTuu3L)Vo<_|PC9yaSOOg{x zBFBjA({`Dv*r^W!L(CYYlq$_(M?Pd3*8&XNc~!E1qQ_w3jOyEo3SJL}ObRZOLRFH& znWS*CP0bU)AiY);8M6)C51UNMMTa+{uE7v9P4eV#O)oQWl)wiUqxLW@&?=#9M}uEw^ui4Egl z4u#d&?vPW(i-Ymo!Y6c|E$?Bg@fE(1XauF?5>+#&Y@)`2Mx#7IIe}q$V2C!Dx13RkGro#8l%0)Or}`dIb*u2 zeXVNW%AMPCavb?Y#msF9jmI^vpw+Jpbm>k?E!OJZgqW^`@Fr>lCtt8%Z7USh_h~!y z8?dZk4yrqTV=iQuss9yX@@t>#_dSb!{U#>BYTWM{2W`l^4Ia!bb~o2yWV^~4Qz7oz zxQ*TjT%};QWP=S20CKm{5#=y<+?Y3B{RJTQ8*N} z&Ev}Dquv1);t|f0+=(rKnh3d^#Bc&Zsnkkc&P`&`12mE#jOo%Jz{Fv)%SXTf*tHoh zO3^Pjp~n&0=5=xm!A|G=Zh05%*4mmm>jIqNfK~l^$^kSQpUZ0InWwh3pjEE~FxG0$ zWeXO@2F};X(C%QXPxC7JXm*NcxCASHZKN?3%;@KX zJyRd?$vNBX_7v$FvY`!&anZ4AIeUKJ@sC2~OMcnFTu-z&7@N1?(;3qXK81Nz^{}m( z1+8kr<2p~(Zg6F(Z5b}kNrlvNt#$HqS61h&B)#TYX!mO$>D!(W#^}>_hJNnP>%fWM zVKs7SsN5>T~w{MufB+6Vf-F{>tD;@Y(4 zYs8rE>U9>)?V*$1jW@W`l<@6Xhx*BY`xEE%>wEw^+;{aXfrc-BY{#z{SkkDrQ!oIAX6uweFUW&;zm(tcEV{Eu-f-bFE81@o94W zDdKYIN9J_>+F|WY{UORC?QP>R5aTyh+-Wf>L}R&fU_90Xq{( z`$*eCiJ5A84LxaoJH40?+{DbJn{dRwqNF3+t9tkdWfM0=d0Ru1BL`=M@?*OpWZ*>( z`W&$X-*xc~iOf-j|cDH=MrmrzNA(O)Ipg0R=^EM!zf9AX> z-t)u`O!w^)+JlD}g66Ie5??jVTL3xHmuNqCjogV;^IghSd%>@L+nI~`tC4N^M#(vE z7h-v+vHgzd8{pfo9nd>L4FTX?^c&)jlR_L6{91*}37Ue8KVIR=?L1X{KgSnoOS?3F z&i6?=$6=OS5BHgLA~%37_Hc%agiUz0gB!mEGn4@b(laBQ>6mP-) zC=B3h%+sfRBK=3>q0=3=J^_eh{WD#z=L`Q{h_AhRU?JPmMCo>{FLkB);3=ZJ!@B`3 zj_nUU=%xYswSAVYb^9~@O{@gjNyV#FNAuSG9(P(+XtRK&CjsF~(ri35Dtw>M(d==h zOEjlI>(`BT9njK^8z39WFMDkoMSf-c13QlBR5ZJn&rmF8ccdAY0wmTO`R_*}oxgq( za*eN~aPbeOQXNV{E9wmGlDY9z@y7n`^1MHfDRx|o;>yU#~vORW2g9DF^Kn%wuWZP7=J}B@_a^d?0rYH0ncs(f@@~X0(KE~)2}<8aveom!|TuwM;v1ih$V$m`IO~| zT_>M%9IgoPI$iHru~F)l${k}uHO4~a&e z&k}sSfoH*&Z^OH+LOAeE7ibVeP{k@d+8))-50B{H3uGbMoLl`Q_q?CMnnZ z!EEIDbPx+&A#^awrUL{121<(pN6KU6KJ=uJHgF+HebNS^H&KPl5p<qRD_KbwA!rXGw7?^N}_L|BWB@<8j!QP z;hM2UQ~gt?iMeD^R#`qIatDon0L{`5*Q0R&Zr${6kq6uzWgr=lQ4o{mnHO`0C* zpoAUKm(WAoaipBZ`inM-Aqt^K%GnWpma3;$8Ecm{a3Q^G1+Hm7Lhp{~6-j)%?v1m7 zD%J(&k@f#?Z9p_xXZl@P?z9)-QjH8DB=9TcQPhV#C_5i=MoL!L^C+BSx_2UH_Twlm zeuE3C_1P1}9@i1Ol>{Q&7h54rY^e&BZuy-Igw*omcbgesEcv|x4X2XdN`Y&aU+6lC z+e3EqfQDto6+;`s+o=yerx>YSN?;h;&Bl!IX+kxz|HH6EcEncT2_E_>LF5|~FDv{o zTf>jD{~uG(XWQ2}i!MqG`5hKSKTqQ4SF{@+K$DRVx(V$NJiQE_I-f~$@ea8NpD)H3 zh0z}d8RRfcSbmWYJ~b}FvWtB1wTYes*9(9#TtGkVjG)P=MMXcbIce|iQh(wBZq~T< z{#N^%soUZ$^n$+=2L`b>!$UeRwZ*&mX=?1v(6|fcXNA9vU(Y@DK>f<*ycSV4SScYij_WP>;dL4e1`8nHL|eRA&3{E0`%5ppV@_T6-B*0ryF+H3lIt=M$L zfA6yR$~Ab1Wv*LQ@a2d;1Q2=qJU)MDycM*mlNCL07(}kF=(%dC#ch z+Z~bBK*5%ECfc|`U4n7q5n}qa{c7T=ex(_Ri(fv;y!L?pJJ9JTT7g^eskU`z^aLUd zN|dDI9f)=ZJMN5%PTBebNQS2k0hHHhx|Ps$&lioGVfc8T(Gw%-pP0n(e1lX@?~PN4 zHGp;!ND?{(<=Tc4SxxtNJa6$Qo)GdCIn?(vAmIa)@axE-av2A+^o7unFMf|H>Cowr zD8ph_cu?ngGClzkI#UWg{3QsupAxgU5rbou=X$h`9t#}@5#>&tDLG<)6}(=b<4;^) zsA};>NDF2p4mq%c(|?aC;sCH-pS}rNz{V*f)Dbxt49$)lJT`Q7H&5Zgoo9-DkhDi~ z*lmw((3N>Umb6EU!#ANnoK@sNWr}e*R)d@m@Q`9aiU;(Kz%XP=MEQDi2FeC=ig&Y_ zXKzBXOhl6_$ftb|`^E_tuHEWqVJ6-DhEAiz%JE*T^BD4dK~+}hC-RCf<@b?Z1hSA^ zmRJ{3c32upyu^u}$KcL+rk(ea`$zh*=!Y{4^fWugi=5cMop0h>OY|{_v$se-(qDj} z3R*k2*z6-Y-;eZlXzk4s-Ng6u2#i09BWAi9w2`?wqJMy(a0=&yP7C(8HL55fC!G3h z)4u|nV5O!l!e@x%*Xa^4Cy6mh0%+hk$0u#cSBzB6N76GNNy&U9 z4e=-lA6k!vu$i)iuXX618=%NoQnZQ9PPFI&K-KOAdn1fm#=oTg*{%1H@groh*OBpQ zf|7Y!{6=UtPm50#r^S1)`f&jo=frP>uyo})G37rK9Ci;LUSS;@i*L<9_;8fh%red* z77vaa#oXk%ajWfI_%W^vaUP5{CBhM2ZBuTxeO=T=IlRW|A1dU=jt1kUv31c^&I{@#1 zez$~iSjM0@s_<8;CWh2+K(#W4v&S8PaO7}7@<%b&VM6c=c%zP2KRAQh#LNII{~$@k zMZB#<*4bYiE`v7Dy$i{?$MHmkt3RtMtMarNn1z)doI_30&j$hAR{+H0h;9Xj{Zw8z zV8O9gEuw;(#iMNp-umqjWBf_Ndz^MJ1{fW7gnkB7fh{P)RK(9sH334OBq7ZrCvHSt zkz{xPS}0?P zIouuBa*j(5cKEww-UlWa?<5l++Tal`8#c8?O7O%36k{ja^{tpwWmDVa9D+oY67lI) z;^Pi1zmD*mR>%5QLc8OMCw?pC?d6#rZ;l@j_}?;oM%SQjt#_aH>I^mUh!eO>M19(G zaLOaaDRu}O^ADi$xL_@EFx?To1Okj4><4*r>B1^AG3$aZy%|FCAzmaRt3gOa4iD0q z2ZX`>qX{sWbvV!9@5jmYEvU3&M&kP6kHHa+m3`W0j_AGQE`EvA7axN$7ro}!zER7k zXZg;YGEyD?($W_(qu8~eM^Q^Ob7}b6F3HD8 ziv9#(YWxoJ;~W2)Bl4`{P8EHT47K8eyBKe>>Qtre?q?p&=5J889vn=pFC7RP6T;jNnb&O zj622gi|GZY0Ru9HiSgR$OTTtRgW36(|y4x*V0Ep&8>}cfnxY!ZiKV+3aUJ^eI#>~clHl z{dmk!2tH3P-YA%c&PDH^(um@>G(tCA`nkUNlpJ?_VV1YxX)n&s1`$zv7r&_}uz45R z2nffbxR?v_&qOCK_z~R$(46=7cb@&-IO%rtlz?i#7Klus7}F zKBw(FrgVqGc{^^;fQ1=^8 zg-|zvAH@`__kxM8r5RprqAUK7T(X~t=YlS*dgXSY;bmsxlCI7ZDw`S)Wivl)O&h<{ zvGOlya;zVcrnNO58WeutJ-&76`;9lGrDccT=E>`AoNzZQ1(Fpx$0N89vm_gim2tQ) zvSQqf2h(mXIeqf*544dC8i-99{kWduw+m%p=>{Q0(!?RRz8W+=+WswvPv7#{sbK6p zis#>Wy{EqXq3@W`4#hkE9G4@(pJViD=eUgX@gOoS57eEsuSXw(ZZ--}54bxb?4qCJ z)^r$(af+}O!sB-d7VzG}0IoHy6UDTSuKuNBN?c;bAJJ9%S6{rpuy65xS04i&gpGS4 zIW!?>;OaF_1-`Tn9Dj{E1coXw2P{5e(5LJ^usgCh8+l%?J`_rlR*x6$$#nqZcX$0p zEDx~)*27v&mxJN5;9JAT8$ZRExb%BGYL4hBs9Z3K=LFZ$d!M8V>MQ@oejwa7Nx1R0 zN#Zm^u>2;@S}L2k-?MU49TpgERkb@^g?Li66)qK}UyHi9Ve{NgO+#A7n^p=+emPoT=K8fy^?i^Yx3c4)qxcN$yLKFLO0V}irJo^B=|3)1+TwSJ zg&ldj-v%*I-luA!7-ux?>i8`|RZTo~0$046n1N&a&-CrEq<(*85AL{i9JsJ`P{Nz8 zMF>rJ(@a>lt^*gRWPEwrME>@m4!QAEMZ`5@8(Q?e4+{O_d<1?;zF*o8O)vXI$7^kb zL16dP#2&zTTj18!7*ExPxXgSbS3e)C#TWkrO&f=0j_5#mUy*6~d8?rFDxT*v#w0*8 zqW8lIGI#81`SrQ_L*RlB+97kXna)r};CXqkFE(VSBgXTp$o0-_+*zV}&66))o5S9p z5$j$-stlyC{W}_^{$Nb>LFVuQ`ip*fvLD_KyZY{{3NGf#zQzUc`SyJ8z7m>A;`$Qz zX6n(K_d#*mcb%u3ep0`Ft(6)d!_+tyCzLBBw(HPCx; z`~j*ZUc{GZ;p024bCTk?3*q|x&lAu4A!sv3w#!AT{r|j2$vw_A8n+k zrP{vctfuE`uSqAJ7b!6#kI4SX)3I0REOXpX9Sd3MUxDkScs>%9|0JGe5Mod9 zoNWBTiVLQEV6%Wo8GX_%qbtB!QbsVyq?l;_u}VQC3brsaYKe^I>X%cnak+osYPcK= zQY2@mK-+G6;;CY*&(#LUc8>Wv;YZlj(6Iq(OQ;|%H!gj(K`@c)hvL26{9GLDL7=!h z@ertP;Ghplovv`DwjF8UMg+zc5sNp$iL`2acMC!F2fOBg+)Tj z?x!#?h+Yk%%w4izQ2zM+G8KJ4e3Eg$NjE9CRRA0zw;zMiq}-B1Gpa@BMvNeNQ4^23 z+EK9>)IS72+)=H>e8`S9$=C*jHHsLkqD$Wg>gGC->!M({h^N+y=+akWf?WT?2N{dd z+5HqZ>Bha_z>{|UM4>5A=lbJY&{2NGNvHlBP^NX|a9L@#VYF|MkMUuaW5V$`= z>50#G^8M;4KO(I&E)LAS+UvM@=NZ2{bh5AfOHbY*_-TLIhx*%~EzjaTc?aE*?=v-V z^zMk=35GCpY<_OT6P?A)DC0#F#}|!r#H#6eg^_)7KV^V*q3^|$%}0>Qo-U%N?K?Wp zk^6#FeqkIN7U zzpYHcLxzyqt?)x)*yzc4N~*v;{$)q(20+?`l*IsN!o9~@mtO8zKfMIWwIiB_d;{sU zBYF^yMomn=9PhI_^Q`@tV?8_{-Xv^ID{MRrq+eiB;|cxd;K{8$=SHrPHhx$5H6eiL z)!4g$Kytq(wRRp@ju&C8mWJ_6w-6f()TGwD+Iz+LRRd@?OPVtsa%fU~`b5)OgIQa?$ypw`0=4Dw8Tcz12t$GKJ1Awm$?%Nd zOSAmSleZVk%Aa;vzl8h=C3x~Wq+*SaMSe(4JEFg*XpVFXCmYWmq`EwC?K0jtq8kA@ z!Y}l{uP@s&62SG9x9~tkkK7BCxOnazrLBzm9Y6{c8R#aCkb-uMH|vrHBkzW3s=UVrG1!ZT_20#(0#4a5YW zo)Ox^0QEBV2DoI8?}EU&JD?eNoACZX6=VxBYnhN8i(z3ENl*4uv`80bE?N=cle(v~ z+x91*@Xh+D12Fe05D;><#8nEuOkQ#215@vnUs*C!;{#oY)&F)xZ-qWZB(Qnk!bY%4 zFU(SJ1XuLJ{I`}Y+6WzmJhdy)Ct>nzb)mHqx8O<;;vN-#DeBsT?rQu_R|iU;cI$G0 zecD|jUrZq9Cp{?|JmFg+a1#1-bFgoLTO7ZA4k;ym?`lUIk90=~EbfCgoQ*3J8`($9 z376~E{vT$-Yo^G8^$Wgal)rs3`nxw=&;!*X0j#jSOBTBL;nEnNr>mSo=eCEba%|AMEP9c%CC@7_a^FMb(fkG?G0?;=tBmNE7* zJp6EL0zl&CeO~MZSH2*Ecn!11{fSGv#Qn&L*`X1>$WB}Y-I3-Q{{_wxfaF;3g+KUm z;-D~m!oQck+jt|668^~yKTZ-DgsNNiE%V+f30FRDw@^)V1b*!cb6eHsPdp^>^fiCz z>YB7OdJa2*_MHN%(g08|Xx+#}4lLnY9*u`4z!8G#@=`=H9kz^{HMpjP7l`{kY8u|K zJQEs@dws=eq8d7d&$x_(CP(Z7tp22bUAFgKP{sX>&|rDKh@+DI%DdqMj`bzD_3$R| zj_$;^7F*$~_7aePGp{T=IbPz`?--R((C#m(cvjwmm) zlA?{=R~XkF`38~TV?3#mompa5&!FPbUhI6BP60EtET50k865taxkHye4B9o9KQ4X3 z`}fE*4E|uW8}|1D4y{hj+Lv0zubF@^SsRw ztzhC4zl;71-yc3%E#H@iFYSD;rhTUW96Cah%BH+M@O^GgJnMJD9I>aI3*OA2Y@~_N zwm=5yxS$3(tk_OPikmT=kcVG;Zv*6~w9Mwx$TP5wRU_YIs*b6<)bUT_-gJ!j8R!<+ zO`K9ZjECk5qKmbA)8}O73EK4dcb1+*bA+8{z#egy$~RHv_->{r4L3=7pLF~?q2r($ zY6$T<^eK8 zob4Zg)jSL{!~u~}Iyr9mKe`)qxvtO`-|u5;p8=3LQuwD{IM884T=`p?m|TGR zAHj`a1skj|bdwOLN@0)xGT7 z#TeUhXKU70N9-6B6Bp3MiNGWjZMjJ%X}FxNcBRLlahR&vonGKY3t=KT*Y1 z8@h;I0x;u1M;~_+%6`~qG&fqO%*ad*{dR*h7VUB1AfV5S|`r~lj_+MPHe(W_! z!T1#x1(gTAwJd@Ds5zP}O*LExmfKBX#J&VyMg{bbg;E0GT3oxyL)sYGg)esq2(Vi% z(K*nBx z1|S#MnTE}soD=6~Y=ob%$VGaSI}zkMEOMuj+zOI2#jv~=x+BJ)?uYd_qQ~RGv^dio zKho=0cUzNbc8R-^X6J~#L+Qt5HsBV%PQ}?F7eBbzXK}F_f;IYs3!!&+{K_1hX7-gr zNpIP{4|?FghKvYegrGw#O5uX$gT#MyL3eF+{JIrA#%;yLXLL5sMK7=@uG`5(#kdMW zg{jNyFa=K=aR@ZIgm1tErP@3cT>Mtun#c2~8yA75%*!I*_1}mPt+XV12{n8+dL6WS z-Njy6qE{oZaVIleJHNJWQ7sm-47bK-`=y3j?f@m}Vz%>3jpJKksD2Pr%(WG}l*FDS zyVy5~E%Nh1MdC=}vK-7CM@D?1!r;@rORj>iFh+kRM#42Ka zlXO9Q(5N2|YWnwg3MFJ&-I|Z=_EECiAJK@f8D(~1{m#KE{#k`YkY+I^ipHNMO*@=4z47;zWof-UJD_#t#vDH;^Wl>VTHd0qhlS!Z$FmvI`aD zU&_X_$9L3_~N zctbk%INsEwpUEl6A&`>jh2n3bA#Eey^-E2*QJDi*Vd!ozG!8>jlkCc|!^@59K^z=A zEsnnivqmL=yoZcm2o z5Gt0Q@LaHB{a-sM*pS<;P0kU1oK9HgPv3(oqS1CnBXgZQqVMk)Y^fGo*OILl0c5VD z7RMjqu%7swtoUM&{+nMj2E8X1*?#)6u2+rwfJ-h4dHn+Oz?VYR1adKo%bXAHo`d$06DsO7o z-)D`(7(L%L0f2W+;wDvk=p1`ruBMR!-~63xM@;;>`?Bq%l6=>M(2H+=so3$XffU@E zbMP1YXTGw+tvKw$_%(ODM8PAQFh!)rAMuOrctQ%!C#qr~c6dnJc-!p3w-J#*f@;bU zTR$}5f|33bl!}Rardw=T@@ zFhd{MC*U0)E>sunFW9}2u2o;ORjjoWw4xj_&Cb6i?Ma-NHm5&a2-SR~Ukee#3;49j z`HpBN`qBuq3iiwIF2@(=>u0Ddpc3*1MN49udg$(zc4l zkR`vQJy7qDK5gDy2pcQqM)M|38Z?5dg)3)12Q-7F|v0nIYq2qp5UgAq1Mzoe@u&re5r{qyT2?a z2Tzy5qn@1j;#@r>r?T9@h|NDoPZIomCHgU`XR7Z{%t?#m%aHmhgu!u%J_qk+p6H10j>$Pv@g!o}re;{|5pX=dZIY=oc5ieH+g z6=OONHbUa!-%wQJUeJ+m?zdAkcGX>m*&U&}OCZq{s{1RND64+p+^#zDbIDL0_Nw@$ zf*s-GI%jfSiui-rNcwa10taFA~5?O(|E%!MirVdNnnByfMTb<)@h z6q{<-iLca>=-FhMQu1&YP=r5v>k6`%oO@@aC(+A66r<7IOJ`95+NOWSTV$9(59hiE z0A6IpNlPM_?fL zh6-XP&kwDmJs9Pj+dxeFCqsNmvtQWD=Kve;P%PNSpf}#oWtc8#AgX*rhawpc3YC^R zQfH_kY`V(8`fp<2c^Xx%@9-k<-n;xsB$0t483sL+&z&Wm#&YWdrIaa%s+1+Hsj6>E;RS;!X5ENBxP6%@{(a{|J{(kj9xWwr-W^?vy{BL1p&! z8yOKe11z59UhpOQ$REiVWrD{5%z61>1|!Yis}L_>AwL{JdR#;KP|VGom@oay9N13J zU#@_Rl0RK>UlU|!{d7f!OK*Ub#K2rHLj;@p6m#_1AdY#s^g);(O>Z3r^J%Rc|4xf< zM8ygO12LutLDMDtJ1$21U1uOmZn5xiH~Q%;w_}&r@x;@jk5_BeU&k=KzkN0RKS}rU z|8I&Ijj!Y5HyP}{|8&{#GdKNyvG$OQ9wI3Ww|24-!C{1ze+&d+%P0ox(=n6e>rfvi zXGZPIZp92y&GJF0`RJnP8wi3tbHJwQ@_pl9aYT2Zk&e@RlPOJlSNhj*G;) zr%NX2tgnORh?}e1@qLKfO#YTz{2AAv*%!|M6EZ+vhPr+W#*lsqUtHMq3Y4chystI? z6A#Ea*Zz}2jZ!w4|9*V03PQk*w3iSb5SjM^%ZLgb^wYk;F61+UehJVK_jB3*1c|ht zNPe@Q-Fw)-Pv6IQhuM$6S1IDH81L9e080B0;|(FwTYF@`qm5_s_aovzWa2juM-8(0 zJ?i$~bCLFdNp;KPXY3d1YaIGzi0&tx)Q^!(hw|{-QWWC9o6l#bi$$kK%DD%B?5F)3 za=nCDr;r7^KJbl4yFM-_(pRtdF;6l6e%Nmhe5PH-_7wQ?qS;q7rklb4djx;R7Cjh+ znPCHbUY@RP^Ci4p?!*kN8XPizgn+I(CgVrQ-q1H=3E&&ILlKXXUjP&9lj~$(1kr0N zwb*?>OOE$-a=ce@*h~?f>>#8kIZG`f8pJeuet&^qMv!kA;Y2d^1;B0-`%5fqJTY+d za}9bm@}ZCU&!N3+f3@%VAG2s+4}K54HjI$u_hI{3pNmN^WYUvMJwi|!K=cO`&<6ey z@`+)qb=P9B85$yOTy#HIbjLonnO(W>wdi&G5562W2Ac35bZy_Clk?SZ8<~D7PCowm zif#S$=m&iv|G{w!u2}AO&w#1(%ag;~&voLTkWP$dIo+R!pDBX8Wxw1get3_(aFlIm;3rLdH%3t!l(B(O`PiDe`apwkT9LnQ-lV$FSnKz$ z@pbB8b?rPS|25_6dEth#P<36cv$DD-;0%W98Uhv0vXJv=1hPvS0+oS=fHN%UgsKA0 zy4t`ft9Ny+GgMU_bXL~YR0J9>c3v6|hMWz7+Oh?}Yj9QsY677EP(&|hWkcNpG1{0h zW8^G;5P!pi*(EiBvS7ejTNlFEeN3jTCRhh}xTeB6*FLooN1NLSXIX89v#M-iz*$v2 zuPV^stZ%5UYp4z_$yO#fkI7c}UrlxGd?i~61{xLy8kF*?vfA1}jZ$CN5K?NZ%jYX$ zv~apgL!hiiJk*y3gNy1KDwG9fi>Cm^AE=!ds#0p|=9QG8YzSOhS6!=A*3{KilvXbY zObv&Wd}T=>s9c5rhF3U;&vg#J$~k<}We8K496=On+LrU3P z<(lE@gyF>#hEJd6REkvhlqp`nGCb&PFn{-3Q}I@Kqt7hU8e z=$hfdSe_|Xp@8TbsuRtZ`HC)s($I0(#EF17=VNZ@I(G>x zg4m+!P!+Ua7Obn4EEG@m2!f-BjZPv310g^T0us9SmZP1(i}?vDZ1gOsEqAHkIWZ zel@hKT;ZKIoysvw(6cXJ=fW`sW6oBlPn|KX$ZHmTqi_(V$nWz`DfLacWGeXWuJqZ% zIodfrTu<|*;L7F&Cpb+WMmgnpqnso<%1PrJoLLR)6h_a*pp037q%PdxEDtxp zPlcS8rxfbUz7k#_;H;=4j&o5N+M)P)f!Y8(CyXGlpuPqV7f;9@S&%2`OU-AGJS(qH zKbk$#o#%AVrMp-}v6zlzg46tDn;yjiWK%U(1vuH1u)S{i8xxjoxgD!+c^|W$pWVX? zO>mx_pKW>~iz)!{aaIju=7T7GR1&l#5X`pwD>M}3^Lj2mMajq_^GZ zASuu8jxb3qrSg#Iiz$u}Z2XV?0}Ty7tbb3LVXeZ=2ZNR2nkC3RMUJ41rD($-Sjb2F7;D+f=lC+zy(UghVCgey2DexpJ9;R2- zEs}aMM-~}5a)<@hwG6nz(MoEd(sOBw{R>vGRC2ecO1i`PvL$FWvw;a%Ym2KFgcmp= zig{J=htd}cw*|jYkdHYxK$38$zFKEFcN^7}A~00c(V@XB!IETVFZ_^@e=`5!Qmhu) zLOulVH`BwUAWbeujNzIKLWp9&G>SuD3pK)WxFh6%rhgidPei&AL)m5X5i${ArbXD2TWV$5> z!#2y7)rAmLuw$%iSRfYDk>)zaNj|YAYb&@9Y;caKtxHO3M7DE;AK8WQy5^)okY^g!Bbin8Tc&q{>2d zXsyEz*qRgcJ0ln_tAQT@KTD|B3TIHnE#yWF@eN2BVb!u5!ZR#q34%5<39)}=63Vz% z2bJ(?j5!*%d_a*l(~umFq>*bkjB=8aG$rhbX)6ek^Mntug5+7_Y{QRHM$c1{UPBpO zfr|7n%IF}T<(gJTFT}IC(1a`N={F}hv5`Q|KQ~;Bt#SUj6V5$i?g?ZvorK^4m=z+U?gb2HGwBc} zXSN8MR&H%!3t-X-*fDz~*=P_0VX1S+Z}lcHD01y2L}CWbe7hSgFzp#Pn*`0IL~t?z zPh#Jnnt8Ph)=Yefr7kRvkiAfgFkgNe?w8D?MbAneHPcn?AdA^~`jxi!_nsz8OgyHJ$AZJ?L!&~C(r z)fqzIMYQ^1y=aMID!q7PBJLYI)rm-3*D%59_f5jd+HCK%X|qec(~5ml@T=_}i^2cc zzxO1OhK0}>{ibwFgC`#57BxgKQtLby?xh@uGPTT0DxB2~<+H&Ke4W@nC|9aHt2rHq zfF~&qMgG31B7SA`LZ#pE{Ie?L-%;Z68rd)$he*L$O0qUfsjU+yR<(6=>nfJuIA;2E zXhq=>3CkJNz0*)S&5N$dast}K(NxLQDU*p^$MWv#nB933gQIj~{5l2As97miW zl}z(pQ9OOJ;wdU}ia$8JDy84UsZdSWIlL+?pwqomJRIAEu`~~~oYuisQE5?0^5kpE z)KVYLO3X8?%Y1&nf)t#COb;Lz1|{16k)$zVO@$(R6HClZvM8!)!-Hw|W>N2bdIJ$$ z0)OS5W){|PPG1G`Nn{oxA(ux&N~$9v@>)bOBpK}`nXtlREFoXPCS`1~Y(9$$wgy@Bt^xV6V9h0fc@S= zY~82V;qWqK;und7W1DkQrXk-){%QIuCb(kzRG~~o6i4c~0PPJ+l&N!n!HCJ8VlRk( z*s%(?pD1W{*@xC+5 zLF)kW$Kch@@CuwiS;>ez{C3s` z7TNret(^fQ$lxaShjqdg;qp#RO<-PG4c}H+Z~KtV$Sq_Dt6eaMKWV4+yPy;oXMK3i zDevl9gXcL_U0wAkufQFuT_|5zi1&{u?^@K=m4$0vhft10`P^c>5=HsxlCG{QluzI) z%5s#C;#KxqlnK1T--Yr`lsd|FxOI}1p(q#PItzan=m}mnLRpJzEmbK0i2FCoQLaU~ z7G){!8tpf&z%<=ll|Sw~s&TfAUKIS1uhl#M7`QMTU$Jly*#{6kk4 zzvbU_e^=K!l+Fi02W8`0T!O=uzxKbNAIjDT!57|0H~qD%i{BS>{taJOK-szuUtU1j zj*?#++J{oXi~iOpARm-#Hi9n7IlD0)a=9jyBT;s|jQOD4_d57Tsl3tEmCG;B;$mVI zN+-%jlygw7M%jdN9m;l;yHG0cc6D{2%ty%|HJF2vzpAtjwMC@QqkY&-CcOBiTO#{YGGIeG41y?!Ujk)gS-fl9Il( ztLsgy#qRdk(yew6+BY|Lbxr9(-u#y^bLqyO?`|39I9 zP^7Etx*q+*$^P2`pNF;nM344IlkM*Vei)Z@&hF7ZCfS~Wc^wDez}vV<{w9gxg??OU zKL{W4ki9+qfh2z(v`5jO|5ie>f4|QJeHTC#XulG7^*T6!rJpG)`z10~WJdb;dwu{Y zjY883;N{}__bYf-CJoM6k?tOxdrQB`gPoC#^hoyLT=bnZILphW>c@Xi0e=_p$D<_v z?dg*S=dSGM9qdeGOd33LMW$zP{w@98gU3Y%ln!o8OTR9A@HqG2eD~mylLkA1iY_3h zlAKrv1K}$-+|kvQL4f(;`rt1&tONXH3y6~APc-o-vqSgzAb!O7mkeH$*6-r z^I1W9@Ui^YA4zW|=ab-kR%C$b|Bt;dkE^O$``-h?KB9=C2I2rH&IpPkCqa*b6DkN! zIHNeBq@*~MV`yfxmZcUM4VIM^b(@EqHd?luB;I|Yq9^Kk?D|uussK~pCDsVG4}3xUOhEhONI*wLj*N;OCZJ)I zgLMw%(rQkfDy(0xkqzqg0_qi7i&2sJ4KO1kiyB~tMoy|P#CCZd_7ZM5b!wE_)4YJa zzqHHfsIk^?)Ebd(kQUM^hQU`jI$``vxDjJ9VAlImw#y~Lj31S9ET1EAFs4f@3P0(Kp{ZA7i{R2W9?ZT)8YlWNjgPHZC-3S97 z5m^w#50~^cdP4LN^km+2>eMB{ekgj-f9$Cy1ahOIMG?&~PJe)Z=gp^1?M9x2?fl!etw2)Jud^^LHr!xj{_g$A#rA2tWo}#IquF5_TM`D z(tk&=|K>%N*i~kf^VGA4UV8bJu~8)(BQ}R$(&*B#%k0Z7JAm3{<~)Tqd=`EC5PHH( zXor{45U)fzgC#&&F!2@ajJWI6srNK5v>nk%+KzcqTN_)qH)uC^d|)2*L_hlMZj7_B zD4?1DX1p05RTFJj+ouiK;7EH%MATkfPivzm;G6?q8GkN;{t*XHol1dv@1Wl|178CC zu>aZb zbpqoq^C%bB@r0MKuTjV0zr=NT)YdTT*9QI#jkFF$?F<_eRTDN9=fU8CF6!G3eaBxu zb?UeOOI~iUt+A)|cSvwt{|NdxM`W{k2lMg|;CBL_?ICd{z9r|Hz$Z7r_XPgfY4~%2 zH!$~X$UhDESl~M~&{GL~8t|d*OuLr=KLYsS4ft;ce#2?_9|L}813dHPb>M4(pG`e= z<5g}j&kLf`DjT%MFn1U+`a-0o&ZSHKMjp*yZ*-&oqao*D(`Una@osX$Y4B@+&jh~V zc(EP$G~k&J-a-BQfbZG>&)7b#`qRl=H-6?tCCrgI0|q^r$9$#sx+&jAYd$FMLH$h- zgAu3kvlH+o4eXLX3;1H-Ied8s@#BFX3w*=8DhGZQ@I5_doXNil_^rS<%pZO|Y%lPk z@yrGPeZcPremeEYI5adk?-|N@&j^m&GHwo!3M@R`pe=U)fSzN}!(qic+5%|V1Zxf8 z#eZbY{Kiqv81Vl0_-_RM8-f2u;J*?0Zv_4uf&WI}zY+Lv1pc=OjBOtfmNY$k{N9|? zJ7dZzM{I0B&fc2f@J_cJCs?d6UM>+R-Ye_5jh>^G&Uq{kZ+?&ep)Nb0R#^d}4cz*W zBQ`Q1XKxO_*K*5PD#)>fYfv2C^w(QMwsO(IzsiP*bBW-%6y_oKJaOhcp9hxWa(MR= zGou4i_VD|gxnf8reFDmVO3Pk6PiT2dR6r&F|DF=G9U594rtLdX z&-3)WLeHD^e6^l$(end(epb&%_56vRf7Ww&oLk@4dhV>}3_TCi^F%$*)AI^FZ`SkG zdcH-^59s+>Js;KcCwl%_&*5#KW zSmqqMqmJ zd4-;h2FIE-V|Y%^nF(Eok)fWNjGehe0@NDN!i&x&Xy%FTPf24X}6z+)}G z8;dwNS0M~7zLz^u&Ob27w)mwMERJ(6s@dXK!qHAQAK?EGj&;g0fVKFIaDsC#s?_3l z!d;!`;d_fe2&XysV=!*cgaf{BC~KH3jPSjPsm60vR3&AbVPoxZUwbeBSn zZxRbVq_EdFgN2?_sP)Zdp_iEgnTLG*Onr+~@om3v303ztzk!{njmG>>6fL_(T#8D@ z#u(dybOs<^F$P=7aQ=-paN#iL1*nWM=!N4HBQ0Dw+GzYGbhNlSViqoHu`Q|@C}$=k zcpX8*IhU^NX2={ToWZ;WC zwE0*jjdd91=4E^EH>xT0w`yfR4!G%T{6QKQGL6qcq+2_e0u#{>Rf;~tnGa3QLR@Fh zXiT)>@SXfKBGJDv39u{_Vl&E6Xtp6XZ~=LrMi6615QJlt-hrRE+sv>gAr)drEd?gx zepEd=Zq##to$CO{jUi|_GYIDk8Wp(_IO_-C;|d5yEQ0o~anpw4@WN`D3bS_09GDGjISs@{E&YJQTYeRd z4aBYP!e7+TXni;GhHa4xGi}rse~Zg=Dx zoSP3uX104nz{kmY>?E-x$@pdzvebyA7es2BMN*s;DMuKQG}+!O+eSoNsEKa(T7RIN z&D8VO)8K$x-GGU1_jM%+p8?VCTQ>%!K(sqSZ!M=8TyOVX4d5_mDuUbYM`1T2S@TU` zRI3q7P;T4qkHb`UE?TtRNmtn)RCY>~`KHmjVbZ}cUp#APn)KB14Fam2C6rjCOD)}d z7Jm}jmv(?v=N<&J{am6AXDhO@{X8+`{7HDeo8@7I7Z7ggTner2%g94@Cy@_lNaA%% zt%ADNn-FBfZ2cj#%4+>S+%>{lC*x9KIIXXN8Y8-O60*lgXuT25Yy?_w#9w1W%gtzM zv*msc9xc~GQCQ0dfN_l2%Cn5j4o(Yr>1@WI4vp!C;p~C~9U=*bITP`>LleS|^C&EK zkg=$VvmDwwL=hkD^nwc=nh|d4w1ER1q6x=30m97*w{=FtqYfN0v%eF0q*LY zk9c-y&4Dq^u&zXxv^%nsT9c5`RvYqL-@sJD&~!K$cO2jXUt-dH)V57&~4hg#}LhNP3ycLWL85E#3FCu*!+QAsU4AA7PW%{zF)@dZ?sVeQ(Z-2G%R$+XF()2DO&GltqH#We zTb!iU)Zmmrb5bnjjW%U-jHEV#m8d4gGpf-JYn;@UHI8-K!}+9ktYce;l}}0{oZw7` z>q#B^<8N2zR@5mec^y=yIZwg8q|S_Ert<~iE`+n3QaF;-jomsREt1rOfgdX^lGKwt zW8D@>>P5nMw?&dtNg40Ne@}C1tZ1>*wsf|U)MpARvjO$|5VcMiPd4ii$O-4o1tHv7 zgum@B$Dj7{hm~wk&)c(#?U{J(DFe=~kg~GjSjYY~B6l|l24iZjq zwj<{{zCpOF!~I4b-zS{r?4aydgfpEvP~7oX!U10@;V_eh5x#PI-AoE&eLhOJmqM}c zYcx~G6e*PW{y-viJW~n_e7BP_N(vReYgrg4g;l%JN@O1<;Y|#N=jU+N8G3p6hpv>ton*!f})N$s_Whjflf6&TK z2MTmDk|W@cJ;x45^b-5Q4SNnj_`zIG{s8r`7u%hJ)Wt&W+#bT#1Zp<}q_Ia@69__* z9W&t`gd;4U$!v2MqU*4f6Zup+ET6)O%~*~66o5v;cDNPRMs@UglVnw2l zNFGl&-}Q^ZP_p76l(iN6!dnmHJ1Gib|Hl?f)9;PQP}8wC!CJ#M0s-~JIU`X2r^>WaBAIWOUd{v(%B;4;JscrG)Mgj_m=J5-mj z0lqkS1nnralG_#X*cGG=oIF-1QF=uldqpBgTqlpbP%#N6QcDqhtnsMB%mdzaXkr*0 z>b|&i0g0?ox6z1?!baESz(f^GHS9`CvGswdg_>^3a2K$|KH)sNm`(NetzdLr%&v1W zyUxXIx8tUDL#sB;b7S>bYM3ysdimUrP_5Z<-&cK0KVQf`Fno_ zg9@kr6Q+86o8)0_@qrSq#uS3 z7q!tvrGG=Mtf=pN@l%4Mu#t}Y6Uu*!%iq(b?-gDIj!WSVV3Mi%DI>Kd)9ijXHrc?t zHNIbBW2Ek5bA9M8`R$r9ji5>x7J?J?TXrk*Gm7^jWjT_VYp8v&FU;oK382a5gQ$ z;48p1<#MI-lN`%dvfr77ST-e=<9ZdbQo2A4cq3L)Zwj}+N1VfWrF@K0M8VD|N1RL9 z9&6Dw{T*Mkm_e}YjM(!0&GIk1R82x6z4e#dR>)_;JR$qq)78wgc;*qf& zz)S)g0K5vIKd-rSMg;&O_vA06vL1%_8GS)YL$hR-DgEQCz|f!9s!J7vB$dO=`GFGM zL0Sk2{}oFA4iaaY6YOQjFmwzcYdHMLx&+p50-w>p32eOHP+4(+PRD}8ElU13mHwwH zTd@<3+n>{oh|vM+3_jE`hn-8w-$2So*!)eD?z`G`LnJfTslHagW`C@O1ZDYwcl6Sh zpdw}?i$OMXTWjwFf=Sf9tb#PoH@lh07Qn*@w}(ZQ>CVL&;G2lAMI8WBO&`g>2#dKk z@FBFlImJrvMgm@$G|V_r+Ed0RGsWU60S%5}W`$u66(fM5*oB#TRMdGF6j^fNG3P;- z+gcm}}P$kU8h0o+dDT>w60cE;xb z768cl2>{;_8f3!MPSqT^55}srz+v5NZu#(}E8}V4ny>Y^tHSJuQ0Bp>8pU^q9UkT&>o%y#m;%~#7|*?58RkInDm9Sq z2EzYB2#tpOLMdmn?z!=PK-abDd^q}qnYZi60pU0pF`a3Iw_H%0m*aI9| zdMaT*5atAH2c4G{b1+l)p&~|tzhKdsZ@>@FS%4}En@0< zxDNP_J$zS;oND4i;EmxOP_6K8vjJ8p9vw*zvpT5_7LL4JhIiv2V@@!JH*bPcD#!l~ z%8s;B_Hkez`34xnQ>kw<>SHAHv-%OK_9dVtb_OCMl{eE8)JIFt!u3)37N8dIgaZRkK;QU8+*0}ytPw3tN-ahV22@}Ky|Dwn z#(pU@Mzk}xA#C=xt?Nf$iaJHKmr2rDXw?D7!Pp*)l-_b->>`BGa=monR!G;;GpMAi z%#P1NIly(xQ(Embn2hLSz88-aahe&%5zz99%!)zjHEqqnFuP`8mS}IL72VrZ1C>;j5d?H2ZoPjt~RSD9JOhP8bG1i@>x~ z+wD~gl&l^`PCjkSC&;EU1K-6G(vDO0$&_cP& z9cL8=m?mN?+9yJ(Xs@F7E9z^9cthppou2Z^jkf)`ZaW&#ztRhj>r>daU)P00&T>*= zoQwI_3S1%nM~#RC^BfxA4gAYAekFka5ZD5sH~NkL3uS+zULCD9CdM{#sR&g?k_4dc zdM1f1GCP_nsO)H2WxDV}C^Lq19_t!MlgnWv$gaeo5D6E40TKlb1xBBT8BxR_ll`YV z@^tiD@D}CSP`4Rn<~2Mi_&dE|%O_K)uGTU2bx@y37ZBWoC|p{Tp4+fGwX)p}Lx5Vi2lp3d+!BpsCZ*ciq_Kg!tvc4}vY9 zOs=jR@yl-Q>B@2YFv`%C2DbHoqiZkN^2rpc>rew---<4OthVpVSG!}p+arATkJ=4j zt^}IeCqP>Sk9=eQ_-xNGr~o*zZZc$j|Vo7)o9kG{O-(~n66=*PJL z{H4nNS3kz`lH!rG#V9mRFf*0|UrQwm0lY?FCV<}o6f|Vd+5k#NT>lDrS8%vunH9# z&NNzGYJN+ztits)%PJfpz$&!DFQ07U_5_r~?Mi-kicsNlK|u0R3rCcrG5))50~n!#hwrxZH&xMivrYP$Sfk< z83cx=gHTTX8iRbqY;!3PiL$Dk&8xh7?Jupn_LmZCB=5nWh-~vfkUP7Mdte>+K*8R| ztK^_D5J{Xtxk0=dcf@B86f}x5O`uoHb@YTfC@-*r+pNB(qhX9I!k7aNO1_GqjprEj zqq5d8x@*mhZ-E=e%k4)176Qm8CF?hoo<}LG5yqOY3Ghw!^Ko^{iU;7s_?^`Wzybm( z0LVPx1Vk%fIm-{sN{nDxxc~|}z@^OP;{rG#aS>vFhw*NK@kUEH%e+{FA^9ixi>~w| z6uD8&uZvSbU7QL8JDbd7B~B$lu!qE{h!szHih&$QW$sO$uugiDXOL0UloOrvB!ngE zk-W1DUbFhyG%tkbNeFu+Aj28LIm(*GN!dp8A@E5UF9L&v@ks#rq)Hegk--wi(MbRp z#!m<^j5je>4CD3502sz&n9CJ1pSzUxGO}Dm6&zXa1%P7$Z9h6GAO#qdBO+Jq9w9I7{z-s#le@!iLvFD<1{AToUv+tt z0=0WK=wf#l03L<8sQs_%WGy53!Ex4e9?*}Gc`ATuJphaa@CN{i`Qga{5l_RUI%3HI zG=;>xx+eg}yh#cG#=M*WV}6JLW1iIu0As!nz(m&jHC48i%G^4)#mq|Td;oK#wmVK#xBq zK#zy_0YHx*BtVb5q^rmMR9PC8xgPHTO+1e13xFQ41dvY-@%U4eq-6ps+n{BJ_k$R{ zUIKuJcwM5*6*N?q(iJ@P`U*1B>n{k<>x>Ni=yeqVdi@pwdflhLdR?l@YU;ec2sH8f z0|NB=%uEh!p4V5PBwm-RYy+>~16{lh_q$$CWRKjc%=|)1M7em}4RrDNJOcFiB?9y~ z?o0sm_-q37_;~=58CR;JXkReSi37mI-f#{9di*MYd~!&fyJe}zJ5TTNa?r)&>j20h zf%ZO*6riP>TQKt(=>6nopbgA3#O(k9y1j}3-F}Dw-ToCoArpG;gn($Spt6y>x`ECC zBy%7Dx?Vznu5SU5PcCu279|PxVwFeur;vlruugTcrc-$j6_@f!igc-RmCjPY&)jPcI^BsHE=W&Fy#cES7{ zFfqQj5MZ580>~$a)N^7kWI1RYQrQy9x`W1zph+EH0Kh{$KB0_T$vAHxhe2k=*JP&0 zLx%#O$J+?d<97+r<9@>c(Bn%1h{r#vGVbqDk3S|8JrG^)*Y6OZ*Ih>fpx2cI==C82^tw}?dfic# zrBRtX)U5$cyndYkz3w@RaR!HYy$L1py65S=J`B2e{VM<-GH8rd<`SsUK_h-N80qmc z0`&L^0`xd?3;=puN`M|e3P9pKP8HQqk?V0xKA0HiMFi;aQvmYGAs)vUsK?Vz@9})l z#pBBX$T8qJWJltfBonxMftCqem$7hyGs>um0pa7vm?B=w_!m%rfR^zbfU^q$JOR8K0_+3MFCHl&Cg5hGhrA=_s*c*OUM2+;R?0TeWpkb1lY zinP`Ds?YKCxpg^76>O`{lZ7A`o+~E>q|jitIua~m_iO^Ry9+=;LvFEq02HyiQ*}kv zxBD?w&~DQyE+Kc|1lK56L${%-ToJAJRz#W4D3uE*TyAfh>N3k>w5VMKmMW$4psZF2 zRb<0qR%c*}H%=Y_m&%i~G#DHw&w)!VJ_x=7B^w9|PC|AfIem;W21!l(L!uNSLP22luNcFY;#GE-K@5gJSUb4=UYz zZmqpfG{c@O#ty3^Kl#j78 z|D!~Cgf*5{A{ts*YKfUYXr|fe%oOn-TAQ~>yaUQ0Usr-Tv-*|3Uc7IScz2lY#rqbC z_rMt_bL$8+oU{z%A1J%=-y0hLTvco!am>Beh;)trxidBX_Yz?Io0lN|WRv($K}q8O z0DwY1xG7RiCDatxii#NfZ$S6YRGJt2wFbI9qmni~01#&ixp6-*3j*1S_u@_geL(bt z>Iyd3qgIt?>`%%**TC2cN^;WT5n78f7<}A%hLRj{6J`ToN67);e^*ru+refZZ>@ub zJY)J&30vv!lh&^gAIfJ;{+Rj>yAQz!vx*)i=lFYbt?yG!+~IA;ebox-Ud+qLk)k`WkS`#j~Fhf|1i~r%<-iyl_(p&BUB5QBnnM^|5Q=^-$*9Q07`b zvBQ{Kl35-vqAiD+vWe`>tf9=Rp{!g%LoTUg{vs&iEI~7Ahnj7eN!5xE&7`vwS3?)m z?UM{FGwE#T%w4WTR_$|8I5eVq{(D34iZkT$e^3d*IQ4RKblw2n z-&SefE}dmH-Y%W~6z!s9*pS0F@*7V)`Yed|YAC+5IhROju)GT5eUxm_sUo@M#K*Za zAu3O*HWA>Hs#^gVxxZ=+xf5d$DumeCjTiW2(S@fhs!aE7$y2j%hdT$8XGTK*6muzL z7owgv7` ziD1vjI_!D(A$T&Ym0suFe#Lm+nK_MVhu%3A@a`FhDCWffXZm%q=+x`I?Z;avl!x5vM zv!Ohoboo>!%4YRH2YcDFliBhW42|SVPrhB8Qjasb5)#Swf<%D0C55KvsD#gE8W$nAeCRCNhepSYN+x%)4D1pw~;n@r$1fVBYp7by2> zcmEY~+uSzg*h+ohy-j`GF?R!`b8k=@cg#Hp3Wp$X$J|39G~#iElDXSwibqSx;R`qO z0=O`7?lzS3wxOJ}$$YKRTo7=0!>Y9)6^P8nigxE~f2uy6uQ45T!Zu((Ty8oT|ATx1 z^5bphr@igh#Z#WOQImIPL$ST>$Hh~g1mJt`XgG@-mQ0n+@&A5Wm}{5F_`FCB@&fAn z>TUQSI~txt2xNSYSP6jRa{z$fX97*D#9oVFmx?sr^s>T zN4(@PtEUdZLqECBw2*E5=7ec7aKy;tU32_288=$W_XW(tX) zkXilmXyoH|kS<3)W^i_Y(<%V_0NCdM;0Eh00P+(M1SvH=SLtO0DDeyd>i7bHY&OkT zJ6^lt>k==ct}^faay7Dhsxo-g(}mwu!V8?4b&AF~nRy&MnWvOqH(ls7KVa}clE`7^_-TjJg%2R%@1}I` z`n^uxA}E1J_&-JNbRoV9l9{cPk<*3TaxL(Zem3|xd~lc;SQZc~#9vs4_a~Lt;g#1I zPy-|7!(pTaV!0AV`tudLTU9mkMGo`g=ELCdeIVTlo{YT!4il&b@G}A46l${(b$LKV zcgUDH!Cv>eyQi1~V`C!>)5_81t{+#Z@~rkST?W}gE-DL@dYJ98Z8ps^uWq33IZD&K z(q@!5BsM4sy;BZz`*jp$2E0kpi?>BzM7I zSjYvxCz3{ylz578NtUn4qWCrs$4=o06@&CUnFgf0dk z3H_N$)Ft#`)`$sx19&pOR(f4Rw^$GmXB)|1*vV;3J51ltm>Gc!31|GEopUi(x zfzQaal~EFUniiP2L%^p=>fgP{wMM*`xP=_$H>kjIR`rgD>B99uPu&b)JAicrE&^}^ zfPy!)UwBSu-2uwep!nZW%B^nB$_9BuEWE82qFckli}54X!ndA<78j_6{s0O*?s^uc zfZ{){dg@zXzPC`@0a|#ah!&Xd=ToY!(i-GD#l|YBvDX4CFZD!kr|6W^i*le`rzE7O z9OjyX6lGU=g`!)O-k_^cbgz;s=J|ch~?IXh#8=;rB*;)_M(883B8QS>rhXq zKrr(k$)`frzWWvkKBx51t4Mz~`>BPl##GS@Pwu^sf^7OR5R|5`Ai$=-3P6D;QLkYh z0>vMu-qmXuu`*66{X8oVwHc*WKJ=`FU#M2P0Vwb!>RA~LioaNOc~&q?qwldUN0oA> zXXW4q&q@^}r7n92ur3Dy6nGN#tb7TI|LsKq(c)P_^wBO=^IR-n+1LTyXcr6?GrTNd zGs$>jX4e}_2GhILg|2KLYQo|B-Rv-0gV6dSbtcaeN~y~91^ufLEx!A!imp==D7)=n-`I5!E!17#u#slDwFAu{wJp z0Xn-6K!L|z&)HW%@jr1oXYrsXk4wYn?b*m=B?&`HtAvkAc@# zG+qgShM~WJA>%9jiMSNN`v6h^_>IM`%)P-;3{!nxbGd%P8(>_K@Opu@|9DxE{JLDH zf}SKimBV+;ev=kCB$QIMqpH0=j9HrdSgBYExLCWA@7qZTf;?8*Oz-$u={Bk;S5EgC z{dhd-fm_xJ6Ej1OXG@iQf))P6E~XNW1fNoNrxLx9K+IFBMhQX3-?6XoB->pE$-SqM z%>1V!FGP7(BRJP zKi~_qDRJRY{3$cVo#hK?q$hz*-l#SsOjmF;Fz&mMktT0}^ya(SW)qWI`p5#IsjRe& z^cg|fE-HH$W%+u#*-d!l&1{8TS;hZ>e8h9BF>t46?>jiT8YizH^ga>+c)So$iTyzf zdt3|d``hNNA=+Ko)$YQ0w$J~8U{$fUX78~GrM$~r6+k0(WWrljH-Y57Ph6D(FojNA zn<(I}f~+lsp=lXH5IImZl|qw2#l|ZWk!zEcVSUrI&>QqEd)xt@7p)C*n#`tPDC?{zV%t= zLA}RDfj3&7JoheT?^ih6#Z!0hHzR>>F3-1npF!OUZzSA8G^Q69f{`!p_!e6<+?y}& zD2y9GLF(oZstX(GTS(1m3jT|&X1vm;-xB2C8N%UAMh7dFyA2vTnhp}Me< zZWMWb-Wo!6VI#eLkosT<)rF1ptRVHV5UL9s=~IH#10hrwHq!AQ;EdkqS*YVPLhaf6 zndT_GWW^)GsPWFA^iLtuE^MSf6qNoYRQiK0Qx51K4|RTR-rX1uXoE?D7&{=Or!5^q@Hh9n7IkaZf|0& zM1e}&Pan(*W8!t&h>irjq$bj_RIq*c+M{ny*ccj~`6&D_pSR3*5Uh= z<%#%bA(Ss%iqVf>!`QFG@q@AS6$Yv=Sc=hqAV>j>;TgQ-{&+cni2$~2<2D5VxXZRI zXR!;c4DibPo$5(A1M$eR{iP6j68Pp<0C*5UKLYyzybBvFDiM+gJfr2R+UJ`_U|39i+vETwgtOn@p?J873jqS`m z)X3{~ODM^`SBdoYvU(bismA*Ckmr((SGvY(s4>wjLbYTeoDYri9QvPLR<>JM1V`-6O<;GEQMp>nJk6Ls7v9YD_sYoh{544h4U1zOX1vw zTDt=~FmHfCPIC}?x%IlY!YJ`VvqNZzjD66c49il2~0voK%DKSE}JRl#9}zybSwq| zFlAT(t|IUYxL*WN&`=~R7A%c+p-vtpR+aq+eh%vd>I81S@Tj;v$zg5DOjhf1Bj1=X z1YDVlYU*)q&R7QY0O-$H0AMD8=>Vz-6am-+z&}*Q4xxs;U(F4jg)(IA=3Hf{-+kon=T0SgGe`3(^JU7i3w=Y`8f7?5NAXA-;?O2no2w^7 zjt}r-t^vS1Mi~I|Ne%5No>VQRQVJ-?msqu%pyanq1ORoHA!Fxi5P3_g#7mR+p_nUW**zrb7`*LPa*is+`;FwOH{6K8WC$3!GuH&f zQSLHJa9R1Zr{o;P4?exPk$L4tSMUosZ4CKd-NThwj@1y$`UjfwW>hfqccsdxG$5f3 zZe*7r4G(~BPR)7=r{}u5kgM<-WvXROzcqiLx6IPd;X&>tN@SKk35ql& zYn$76xf>u--U+4ncZ5)a{BE!C)OjPH`HPu4UF~JoAhNqc?1`*g+huTiP)WhT=|AQo z%Cc8Xr|c8T5Ns89UckHA9w|B=b^P6oodG!xPF0YT!D$bGd{RRPCr@fDrBc44F%C`# zDa66)D*_yxn%w|ta>?M-2PGMt$f$$UPwE@`oE+ZZ^qb;!aFPajMX%%=X!bdCES+V8 zOn_eh7fNg}Y;fK0kpQ|j4w{#EvX@f!mxi)#+A`gnR|Z5TI9$D89;7UTdoN|?`J2%5u2+1F|w)W#0&Z!__(f{&6be z4OeR*Dtq=WQbMo}@0*uU7h`t=CATZXX=3M*g0df&2R+$mDZ9I&tkglKh>t3%mhJVC zxx556nOtAeZC?4Ju*%OTH8iFF2Tb`+Kc%I=oAJkHB8tFDi^3nht47mcD zR{Si~iOum(IPXtYhWgEsAKey#`X-+%2P_!=1K>l}ISixopqusK%sLgt{Q^16AI_p` zKAiancrq_ky41WsKSuYoVmf#dUw%i4(I6dzM8;qM{PuiC27vDf^Z+pH78vBj?ud$e z_e8B#M4PLD*%o{xdfOf^8w_OOA_TGlq6BesELxI13<$>>7#f}6nPLaW>r8! z6&y|ee3PcxdUryje~QxUx1Kz9T&|?xNPVhhDMUGz{EMP%m0o`=nc<1axbH4L>Q5@* z&yZQV?13&h=0bDUQ_XR4h33q&l+r;n;WHbaY;21y?_m- zx0Id+if^A?F$Zq91b#7u^NGw!K*=0CmY4by%ABIEG+l4XW&UO`%Vqv80=&#e--gS4 zLw32$j|OE(6O9K{%P|IK>n`&iHA1P@&dla2pqKeDEqa%Eeno?y7vYYaG?9{V`hE4+ zQANHx?AuvEwo4WK@PDoh+AekP9b~G3pyd7bN0ekT?4e{p88jJONsjMNuL+1XZ+!PX zVW%PDGQJ;#q>S&r+W~NV&ja9pT}8a{eFYTA&gyrSP{GD|(%mh47A3w?La22-#0Oj1 z0yNor#1%{7ikypG;Ov|o0@PIG+$6x>iUB9UTnoptYJs^4N;9jqN|H*0SD~g!=eTug zFExS>lkCq}7j9#HmQ~;fSH2*?ZBo&9fGv<0jXx@v072g@J9Qp7<^!Jrj*O`QrUCFz zSFR>9cuau9E4hSkY?#o%54)Bt!&s`BZ||U*YkBw8Ks>)D%jbp<|5mkueKWRQ(GAXXloh(|BL@;TLXf&q)uO| z;0D&I(q81*S?}4o!?W`$?IfM+diuZDDJN)0n(p=UTtN)!a`-0LH_;ZG?njzn)5YEi zfK4|Lfcqq;q$(i%!StPN|BG^bL1+%y`6TBOvge-AeCdyPe-9ouUda8I+$gOo@6WVA zTDtTKw1&N{rozbe!p?n7X+qbP7+TKAJ*Lv6<~OAJQ#CH6dY5E=WeE2aY7yCUmSQ~N z2f~NFk3WNNMYCn9#004xf`7ifrwsLZ2()`qpMr)AIZuOP7LMf&m0}f6QQ@Z3O}UwJ zgc0G*lwS$(W=i~BP}PuKZl(+dWr#~?*s6kr()jC6!()%967x)(+Kdf$<@l2hKYmk8vEL_ zq2yWM!|w+02!L(?@=4A47fS55S?>Y(20U55E_82=X0--z z);~Z>0?_6@0KEVd-Ou}|(0bEZz|1T{rzWN%0hgU}h?fHcTT3Ook8TV|3vHyO)tG+e?A$Y@D z2>Thg0U!M!fa?J4Ca?{_>j3h}mUBN!@NZep0ReVa^Zra^l=y@SDK00K1F;etAY57#q@t-hfKM=GNjoT~-7*48t~x;49;uZ6JoH)gC*RJubsegq%m}NJGDCqc1&99= zCAz!u8DL}@!X+~Q5Y3`44o_MI*h^_`*Wjp z_Q!gkucEA7N5wN4yxO^YuWHYA4doc_;k(lQ7=p6*su1lYd#@@16g1?Ny;r+H!9d=IrNuuE;C%oC0T^SsaJoh1FnyE5cfBo(rcz-A!*K#! zG?o4nRe4<5b;x@ zTcBE=G`~)OPnr{+zzmH~nuqZzbN00=%SY(QCcZ$0K)QRW3UMmLOy>M>Wd38aQ>Iqg zhncP|v-+k=Z*$mV@>WDS^ba@;Pp<-DQYBslde$6b%W$=J4Bs;FJ!kU2ZrI!QuN}iz z4eHA4#>hYCI4G9vZTr>^FgoHJWXo_*t%8CtyPI`p*1^V*ky`@d32<`UALM=|gxiIU z0H4cmREYp|``$6*;HCuTMK~^@GWP>u@cIMDCtF>-{I{yK#>-ul$zX?FU-V!wZ#ErN zu13V*@EtL8U?=k>#mllkcb=B`dcv$FsrX!t?dR5?wL4izxP&trhOAQ4xv0w_EBWo z+($9^0Lp6}(a7@iEX!N_nKs|rKlCKZ@^O$%o4Ut8g>9>R|IIwp))(N`PU7wjbAbFu z4tv}7wPWI9K+m$dc?5&_+A-1SL3QPI?#C^%<;`f!jn>Y_mW_ep%~?<5V=l6XY>?FN z9h66NNp1#gEJ2LU&)|~A*Cq#E6hP7atfX0De~vbiedBwx+zg(~Jf*w0CflRAmn#PGmcz^$LJ4`R6B7P&mG12uU%?k4_&IFia4{Dx%+T zqXqC&goEFLnxGsNF2~oNr)$A6lpllgZ~TjwYcb-<{}RB8NxW>`z{@~Ow3jDWOU*0n zHLGAd8~EFxIioj#sOJGB1IPtXaG9EE1K)WF@3~|l@ADq-R{;EbmDgMS%OK#hQ-W^P zT|?JF)nNWZnOc>>`brLSrQPftXrBjKvljqN0WgC=K7jK86f_k18(#l2r*~<iXJUlwe=G6%zh_O8;wL^C*sIYuKlhWM4Z@$!wLZ*Vht~vELbN($~5jf~fSh z3gr#zDo$r@+1JholYf=c>-DuZij=;#K?|XME%)II1L7Q4&6}W*i7B&x{3+u9yr|pd zymPIQ`+>5r$5r7rVdp0cAmp>HyIf61ZrDXGbTOFtx?E6aA0xB1(sqEB+dG8un^49y zBli!b@!nVzMt3N|@)R8h_rA8nljhp=H-X+$=<12(OfxdQ;e$)=+}pL{9GxdBtGiRb zw~_mj5~-)MzMfPg^SDxZdGntN(c@h?abJ`#cNR3pq$(L{A2}}iQn&WaaLM9fR$s9J zZ*6bHx!USg=rg9Yd+CNj?FCtVw)_0dS!<2!MaBvIo~B``4fW zb^6ZO9%_@P4MX%I&7zfrlx&rqDm``ERrnj(?&mp>cA0MmX2{&44&s1ywfxI z8Vw#-iT~Z;9Iqo9{rR81JV8`mj>ttjXsQ~dpJ`z$fVTf)-2e;$P|#4~Z+H>jgwEJQ zxgIZz@y*=Gm3%W7Z(ppQayC=?T>c|oyw1HQuQ6&Jc`m!cT-Ye2XCG>nN}wTf{YdB# zOItt}uMQBPSDymNC)eN5{lBO-?~=x;Du$)e8VwmZ_Hzc1d$Xn$U*su)RkRfQ?^+ zL-IMrT$S0%U@Yl_ILUmc7Z_x|GX;QuxiSUkJK}=OBwRl*;aO4V$Cd_u%!XFikL7iK z2zVv^@L%bL5P=CMwa=b;X8=?lnH@CkIUZuzW9t?*YKB2>r8OIv1SS8b$!1pX*@8(r z$3Ady@Ou!3+)r_>lz(>B`gPD{(!WwRPd~u2O!8M+oaFa7g0f8VS6ZCp*P!f9^3Rcf zcg1UhJIO!S;%gptll;}Pd%bRwA1tq%E!(Kq$TsR$N3r2rruA#31_53Ow`(=_qbizUEa07e6oPYv=Pu&Pj!|A6(D>X!e2 z^^_J)&`@)$Nfnel-4wUK!0rE+67}0UVcWK><-a@O<5~H3;D<_Y#FoKfPO}D40jDyp zkHOo|ltHF4@-MKWw+4hYp$phsT3gA^k6;V{yL<$rgaAK+u?c`bS=mqf5sU$2p=8uX z+`!U*d$o4RIOQKAMldTRHNG`lrDm<%zbsac4RoNF^&=hN{mZ?y%lnsy2=M;p2>^!w zQsvLNni=WM08G>(*E5z6Qhyj?XmF>$kdqeP*GA`*e|vSas^A7<^7KRaxP9rE;vIF? zEU?ap8kwDSdlR;gD}y&XTLDJdZ1sr}YFUX1)}xf-JZv~9Ns*PQn~vs4-jYY z%S3#O8l5ZTe?*;7Dko;&xl}Gy{GNv#r`R3WbcG7}FFWaK9>{2M zEnOL}T*1-eudAbbf`f&uc07q_STe7&&ZAzgc3y`%*Yaf58E`q?^eq44S?>52EMNE+ z%YRw%JQ1`!U;}j7=X)!%tK?0HX;9;?$lUUJlnq%GdAe)q!4B&R2+B(5W^l+#$M-e> zu8IZ$D7Z{rX#;s4!n>R-Topa-@qP-xzgKy^OUVCaRkTlK(BtJWcUsAtp`ELu#_s^& zs%SC+u8P(GC}=41H@yA>r+4XZS4H2d%yCBO8f(D?FwRxc_4Iy(YT3rzk&V+6-l5>FEToLsGx4)~>bVVd17Ywo2 zc_hcRW0=E!qbQd|^C+68qM@B`z*yL5idx8$=t8i$OQI6x4eBZ$#;UR_K0#dzlpfj@ zGd;g$NmQX6-jZkyRLf1A3ze{ewcBbf+ycD};RnzwAq;;H07KXffP`?DiqwVhC3?dU zjs{QWZl%|S@BzitN(jSfgCRT{-2Ug4cA5}+q+qp&WmA+Pyp5u-s%U5khrFxEt{V4g z5Rq^mf{2mnxx%Ozxk=jETzg#v#=4PL)?S(3@Wa(rW}7PmqEn^>Mc;-aW4^R!1C^kJ zSRo^h)txTX$pAPw8L`GD%l4w`={X#P7fUrF=098iMhKS#NE(cE*q@}}e1u`w;go!g;+ zL$`a&+Gl@I=aPH>x=8L{XD<%hoV~rCkvgY-{)?^SCTukkTeT`w7nBczwwj2o2ZOenh^?L29D0f{@@-Oy+ z(ncID_|OYV8*%hnl(WOOyE+>tPs_j9+JTnyesRH#$10p1MS>MXW?3)<=|wx)fA zAoLBf^*97VgV3&lz3ki&W~qI$av&G}jm-6>iYsH4EhXs6v`f5dr;01D!n917AtAR9 zKK8=kme-)1U0%;xU2b%*@0Qm#M$t`8;lcoMVS~yJ54zCyQqP3};=ujfAhM}30kz1ftrX1fB;BDN(&oLKhtP-u&TcOl~BD{YPp!A3@;8I)V zZJ694cWoJtpi4$S-U3Qfso845tUgJfc+=-RXqDSQ#|iKW{-7^$S>U7k-30ik{&fIy z2WW=sIo=JSUL5u!lnmvgdb#`4?kfPi`!f!Jf0?qnpD6I|%W*+oC_Bt@$0!3I&wma@ zNCtVdbgo)KGMH*xeBJPgs!~Uf+O0s@(h=t#V%g z{%@7ttFn6&%YCZ03|{0ut_-a5J5a_d%luOAbiJZfugaW=^y5u;d0A#mS-i8?!GQDh&QM_-H_7|Vx zwm~cJ)bu$4fOnME5#T+hcL5Zf+0Z9avc6N^Ed(h2I)Loa|ASAVH*)G{IsY?#iApsM z#wiCrO@9C+bHel|c^YrbeK7`&d2?8WG9yXkFss*r+5OVq%`!xo6Xx-I;o!Xq91tx! zw-H2dm*R%Mh~FI)zg@+Rxx1nvP#d;YnbU)|nq9$!Y%Ww@-J5=o@+~emho8wPXWpq| zoSFLX*8;baxLpMuqJk0+haFZLdZip@^;tpv4~sK{W%IQyb_kCa&?W><4UiwUeRbzo8}YVF>sXa+>72H2@9ww=A?3%)eC~6 zM^tp2h#rxlAn`}A74bhA``&gh$Eu)iy3~BT*LZJ>f+-Mj=a6qp)n8$GlBw$MmTyi1N4PBx>dP*25VX!bo2{x^m{nsI`)M) zI{s%kc1MVj4G=iJW9~&Z`>_z_dLF@*D|!9>L0s9dY{@}aoU6Q;{UEM957Xn8HWdlR zsMRk>kJsyIue;t3xHBM%>Sl>|w}9kHv2{X)Qi8Tt2W_1cTb0o5&Q(rIwfECj#70ah=_YZ zIKBVr({vAt^UsLDD|C1K3!3N8A-Ip=f@EmsuhkrL!OBQ{Nf5tIKUfR+Ka%+C6mBml z!PvoHr{ArzpP-+=<|h^;#9+;ZU*kjOf+sL0Gs4 zfx8yJ7=ut*5rV{D_daD$Id$@B-9%Eq*Zu zp#`1shrh;OnPoAs&0q56WwAi5e`lq|m(1 z5Z=h>jM~M7i6?>@Eje-Hgy9ND4 zrXz4_5aR}K+9dZv-RMG>xCDuF=Q;#+(O{QeK}`v8vun^^qfmR@)SiU5yBd;0kG>&R zdqyJbQh*7jL$9DdIN{k$4IG=NBLf@fX?tQEU$2ttVToNxv$ zW%X4h*)HQ%L*mFgu(4ZLwA7%+;AoEe2WX}Uaxl|~vV%kH3SvkkOtpw0El2diQm*F! zu|w%HHW8AD}gcPAFpH;`y z-}MzU(9l|7@f%W031(5yOKHJ+UXH6vA6gn8B8$jP2+@oboESnyagsWXc4rNX>ynSE zCI_t|HuY>y(dw|WkejM%v^XuqBT%PHjsTe9HUqxLQkRZyVwJcQHqR^UlHA6_K=|in&3*5v_Wh^Fk^J{qyUpF(@u8&M+4AG6*b=l1_&3mDNKaVhigd z7Go%0RENUVB?IY=?VEKtj1i5*erajys?3a;8GTbKN>j?q7B63wGJo;%)PBAC_Db^<)RPr$ zsg>tc%&o68b=f%$5R2zlmf>gg>UDZWvzAuOLM2K|dzHd#W7(3@MRO~cxrK@)ODkvL zzJZb|mzFJ_pWbT$>o)tG%DKx{&Z=-rc$mCosS1@YDG$QSD(93f>ErUCqGd}3HMv*v_aM$~4_nX?ph#Kx_F!iWIsD|IYej598dXpT8rZO_zMpulpy7%ea`6I?cT z*|M@F6vV++62Rq~Id=tOxeO>Us#7SSHbD>I?Yz>(m8^tTQW>NzUAUALaY3}>Vup>C z5DskxW)RSrl`NAuc#R{;GE?Otgn5WHc2t0XVf)Sb0}|$kS$4a;>6kIhs@yhhX_#%d zuR>v7@l?YKGasMgRNGC8Cj%W{3H1Ep?2-1e;=AVCD|Q3dk+_+~cGE}fdu*rDnS5QI zGk;3<+zim3T0`Qab}zustl0pAALSd?(5a8?;!%^bOTxnK z7gj$KlYJ;=(1g^x!y@cw%zYaNr1i|Rmw#_Z7EiI4RoMyqCg10b%C-+0M{Dka!B^I1 zf$?5zE8v#}e#n|<-?To@DYTzAs_a+SezfV#fgqka4}2qc+mBmWDE+oJkHup9Wi#up zEA3X!Q6P7$qpr`*kAm=5X7Rx4DKD^9>^9CLINRYz!|${k&l|V`OrMIuYsB~`gvYC` zUSbOz{RJw1+}>qC|h;g#X`BB#YC{Vzzf16EhliLnPcN9_QTA;x~jcqGiRzh3(Y zT)5hD4pPc)yxWsos{zvwU#`oLo8O|eik9qc<^^bgE_jk7151U)JN++hD??1t&QE3UL3UT-Ct z_4umnR40K<2MlMcb3>Wa6CT-3tL(*F?d#STZ$srrvF`m4dk^*(+mk-BdluW{v#jiv zL6c6E9qAnOv{Ptg)&Jw|O8~1XuKsUw13nfl0xnfl6qmZNiWC$zh>Aqi>;?@yLh=GB zNnXr*0fIm*xV0_~?yZ%F)>c|k`Lu3m-C7kDEmf;_vC{9EeBz!R_p{#d@t10V`FDpEv;NRA#BNgu69WI>AmQ*z|Fgh{0>DI6+F_Pq)^tw_8RZZ4{!j`rsZv)q!eEy~j6m8z3|y=cWjqiOc93tyuvGz%9E z5Bt@G$5OPmFDVJH?!&ZCUC3Scv7*Te=9YPHS54tzL&NSqHBT0f_%fmICX%8{>B=vP z5;ZixUkQAdB~k@_lMs0rH=Z1+zt>{jy? zVbfNc{!C5tbu;P7w7RY%`~ITr+q#5VzT0PVH!*BoA_hL1XrSpEv^NxlH}qlK-&?}X z`R+b7;nxx+o6kC(V)E*eY*clnSP!84+Dpu#R`zN#aYn6mIl!QC_ z)U3RRF8p!{U%9K#im-(>zq5o@kr@PURfOLqReP@vcXXD7SN3I5KU2m%sz`pONGOtz zCXS&?+R&#+Shj?AN7@U+?Va1J&6OwntQgHHzjVoK9`opG*!da}KckFbF-uBj7xfE2 z>CA>hYQmP);gFK^ZXkkzS;Dq+r1#iJP`2hw0tYa%gHjkamk_jHHb-EJkq0FP-xg-p zaZ_QtM%{c*xL{*AW_#Gw{m6Opzi^M5Fq^%L{(e03JTh+f>RH5jFmL8{EaPa-2sJt0 zh!0S4?Qtw%sx+X1>G!TX{mq`IBy?W?#^ER8fEG_le;o z?Cg@F{^7XE1f7!@HS0X`cx4yQJ`cE^T-?>D;d5usJMZ`zWcpv0Gv>~M#9*5Ia``AV zX(aef1>ask-GOGmmD#8<9kfo?br9@1zI3zsgwIMtH8ur@|F5-&1 zc-cDQxGdy#wQ^a43$k^^nxb$C0ZXV7XBQQm8y-lVd++XWM)%{>rp)|%csd`K4p^bi zXDjl~XH7L9pO@H1i3pF`uS$SOkIuyl3dSBB0b)O%qG&40LbUlK3Rhep3y-gQ?MHdfI#FM%&HkO9lf~|=Q`1*6KpLuD| z9yR5woxdPOKML8t?qyV#Vc5Vi7{*Psfe*OD8LFm(40qkt;io}1yp&FV^QBE~;4GfI zfrQ+!TVi-&c5q_cH67tTHDPn%F}$<>V=?FLirrQd{PAL5SC{R!Lg9J!U$)!EL@CWa zTFkK|rTxMW`>vouytcEjw18$G_oY0A;i^t9{cU|Gb1(l^C*k^qJNmL^S9Y@e_xi5r zphH;r>~cChQL$w?_UkUBhTboHRqZz$mT=48PG40PhF5oS0qvmGOY1qDUlT4`9Ui## ztnib7&g|i1%U3_TGCaI+biu0d(85y+7E+mgYdM`yUJ9~B1H;>BEfMC|0q=Qt6_i|h z#{Bd6R^s91+&qvHKP=#V;)X8TBKw7#`m7F5+(pd|cKW4LB{WB4w;dE}<$ld0zN zHJ;lY{-z*N^7JKP|Ba`0lG0yO^C}<%I6N;dPw`}T0j3aZ%O1qoj2Iu*|-LpG=ozf`#T^>E#fQFz86lJQNtCkex~%PEot;ok~YKYDHAhNcsihMlWVo^(q6U87GpF-6xu zP!et_Tur9mzl@JKFBMXCc6V(LSJ27o(!v@#gHJ9TVTF#8^Ygy1g(Ij0!&#HV5skD9 z4iD=_6&}71-N?L3M;+=(R5QEN4G6c=8>#B4O4g|=p@rCY^~#HhB8pFXQVQV&V zez>FHwUu{qIG3&_^-uD7{OsdTT9r7FjC`0%qF?xE(K?d+#bS=rrMuDQ5Qg`5avOT7 zFE8(VRm@(d)>RPRPDfzg?KjX7dq%kDhQi{Z;kv@DB>1Mz?2N>Z7Sh#sDMlpk7S;dW z>6_RX{($PJf4G6#M8EL$!mZ&2HGKEdKm3sHj~O#LJYZe8XLtB!Na0V6czr6dKf8#{ zd6*t3FwC(8%(2-(y=~3X?!qxcS0*l@d#>%_CaR6=3J>4!qwt5+d@h+D_OA&$Yc3q~ zXyFlq!X;b7w}XvzPE96C-dU44GdzeoJxwnwq;7HJGWLe=nFc4WNt~5B3oqGv4 zgYK0V-$joQ=peX}&A5h6mYr;;qbJYYq| zj^od(PTWUS6BDcVT9Y_0{1$z-`R^BYZ%>S-rZb!l#)ZexL8yExQw zuqM2Nx?VWHBpgOPkWO@J)qOkEkFTg#QQCjBj9b|og~iIU6jS{VMavnKp{-|gYsy;^uto`qlZSAM*&g%#dt_im;FC0~nSa|$N<1eNV=tq(C_))VExKVRt2${T5ydeBN-GWd#t20$yH=hmZv|13(<(M4U zombU-8;h!blD3h1FI+u8Z0@GBVGSJP+ly5Z3}RGchL7Ipp?4W#@H6Zl9T0w)9)kl#ti1IyZOz%yAU( z=NEB%dVq?BVcr<1`eu@FdMuW`rh3hJ$Def8#SL_E!y@i%&nUtTif~h6#k}>){JPfGRC7SDyd>-E znw#g=)i1~-vq7e5Ns1ra2icb7{B%bV1wBPGKEc>m&zs=rrPWWGhLgXpyDusf8RxN=jq8gG^~7 zvOEvyRiIRRYhAN)C1`A-cjMNzq&R*QdGcS|+0u~ArrVl`5nd?+bTXS-7jn+^q&1yw zs!x#udc#YqonIPiNjIbdBsn0FZ7J5+LPS&sO%&OT32c2wJ1425r8S^5W%;eabLXk7 zHBp+AbNQvcayu3%0zv-1tp?Q z?obv={nk^tk~2xl2fdb-tZQzn%Wz$hz-&OMW~EbJ=yK{wA=s3rHhM`a%QDk#I)+*o z=O{xJK}Dk~;nb;9OQj}GJ&UWpDbtY2a@f@Ce56=~yrr&v0Yy{GXlrj;sB0rLF3GM_ z{S%I=w;|oa0adGtQr5}~1{3B0T%WCPOVUpxbx^eg^PA?)S8G7M%BE>l5XeyVA|C~# zwS$&SCYY}S-a*SdNv3g?bdcVOCmG$ zlVeQNogt}mqC!-0T3P9osb`*6Np@h}wI~xZToU{$DlN^HR7*>GVamA3mS)sU*Rfj5 zTr-A3fv)zzMs#n50S~E@aT2l?fsW#i`LZ+>$HNzR@K(k+JJvP=ir)dGIbWUC+QqA5d_Oiivnn^L9Q(Z~|mO{xfLD8$AkMQvq5GE<*!OC_nq5d|)O zQcf?n*C!X&>9yHXx41E)pyk8F+@bj0(PU`!qNmhJUI;78Pn&WU6J@xf=h13WX-T%# zWipG>?QCFM*0f1>v#mW{PwDTGBhE3m73q#l#?EmB76!s01+M(W(^ zWo>#5TVLf@i_I>;rIb_*tg4P9rFtsA=1aB)6NMM6liG`>)~0OG*p^H;HgcvKv#Dm;v1n~w&_Nef z@|0!Cwlr5G`$%afC-^M}I^C>V+H%mWwgxmqsw<-B42piXq8?rB;vh$^wcvGj8 zQs2wwZR@;xRMn}ilhriW(dj`}y)vhsw#t0vx>Ha#TGH8+K3^m|xED8!3nQ96xK52>HOfa<)7C3Q?tzD*>sem)(hTIUT{ z|L~SZC!eucCRCLR88L>_-NKC_+umM3pK5D*MMqm3Z8NmDa~tLhjePV|3CY_4)Q(76 z*y7||t|8{7ccQeD9h4t+detX3YBc<=6D7f%aeK_NL0t&wtB+kdMH@f|* z1{2IPy+t>n{JP1e^ND zh*c74H=u@u9tuzKJMF2VeRxRTpG<%a-u)frXO7H9dNM zx+OKbnfB~<{qOYhsWZ~^PDy7+o_*T6qcwwmN7=}+qb7~c(4n4+PSpx+>e1O%6mwOw zD^WB&rv1a`o<~Q>G8?h`YLh(ihbB#jB{Ht~2WP zyp!v0q7SFj%K6kVy`rwUZGN3;$?j*`OGxPAx*&$hpmRt$fEr{fFq_vkD6) zR2S{~WT~8L?P!tGCMeZTw>KhP@Bdg-J&>}1SfZTcxFUGUp`e{nZQ$x|jl#Q#!%Mm{ zZFE2kv{;x-0mx7fBdSiO(s{v01=wsp+4oo^bgRefNiE5wx<60_j&(#uBTGS5jV!&E zx&|;bXKQUUbuvD3NSl%?oD;H)nmyg@;4WU(_0$>XoK|z%RAieIhnpewu0*m} zFIhUGcQjKEnO;F{fwmXLEjJ^Sw|OmD@{Fl7+_dPx$2aU8C!~q?-E@21JnEwy$>F>V z#BJWw>ES@$`jNeb?hV`P79mu2|5n{wMDY2yhX6XJrWVi{lS)VDvq$x`Q6(-^_a|7q zbkL?c;}f=uk#0epYKbH&S{<4x6|MDjuHXj_NxDr<*H4;6j@Q?<_H0~KUiEFAx&ry$ zMpdg=ED7R-P$<-M2fa{r$|lGPA-w?|DY;5@#V8`pY;01C4r_^$u_R4Tm#7Xo{MrUp z8|uWx#X)yIyp^F9ESjHg;uE`^J;qK@ce2Nhlh(m%8dB85NoZ0%6`_*=Kg7}QuoBu? zT98ij_F-+L+TiM28aSf7fpZ1vlNhh|6x~?rdg##~xjCtmDc!hcxMtK72vQTRZ?o5_ z@J0s~+{a)6c^-a{L+ZJMYVnP2Dh|@%aAHw7yqs#||IasLp&N$-XSz z5U1NmQZ>;rk7L-7YNjN;U)45gM_)VZQc6w1$Yh#-44%8XHg&x@PErL4c z@D88h;{w-O2UZsXVUF#pA|0Mh3?g{lf5bg;%skH!jNaR#U<2+9C<3sFH(3ou`NnMZuBEtft% zr~V)_46^&?Fc~fv!yvP7PGB?Ole$v`Ly-n}ilB;u%o~FoMz}cFFqQ#aY*3}}*6=shJmc#+v*n`l>5nu}t z>P_qXX^kp=(>wol8B_(pZwN{kCuaOfQvNFl5Jx?yf42zqnT%AN0PBtTYJd=^D-pA+ z=?(k*R}fSKghoxMFGv4w5%3_Rp$uR?W0_M1E@L?uFE_H10AU{+QJ%vL8VZ7BWRZqk z@ih>CsS!ULAOy1b8jtwdy^Eg-@ykVgVX!Cw4EbTO>Y^@8U_BGsf5Sz{RAXx?KqRmr zm<35gO;OCU1)b~&s)C?Xro&OF|VKCOI23t^JFwUXb zB1#5HjTQ#QyFfE0mS%^@D+*Sv>B?aS>9l(6Sk4i}OJwwhmiUjB0Kl^ZMLFrpVe(D-B$CkG zCEzuplUVh&=wF{km|7#^d94C&Gq^E1z{`zgr2uae&CCiI){y60mSZwoOk+a8bBwvA z01-7`+t`^4@0kQt1N^|Cs{Sfqr*WVf4(wr~SPgKnK~)VAFp70G9ExJ?R2(w7&R9?i z@EL=u-A#6>@F0V#1$cx(l>!`PP_^)ezr%t5Xr;^%)8`v+YGL}f=@WB81@L1* zsUD6=Ka-zYfYSt}=rBP(Noz{3N6~SXETVItgo0}y@Ixj%r2uyr)a-uZ-2pN(Ct$>> zAefC{M4r!v=cUH;*#Ixwx#zQOCza=}o6aVR#RYeX@7?8?L}gF`|Dx1YAa&m}sjGkk z6~=)IfO!sF-sPsQ!sEc@T}T<$o9Dy@Td{aJ+QdS^;AatvKeft#Czym9hp^U2ylp6)n4seA*nZ+~1bP{Ksz|&&@*)KtKvk-B@ z0N-vHy9#pm%LLLq0XsuTU~WP1A6jk;Vxu6m))UU(MUi$a3xr*CxlY+bR+ zvXc$azAQX?g<$rcVCnt~AcShdsB|^rj1`UPFVz<<%-evZc={kD+O@f9Gr!(eH_F7Q>^eEyj57yt1enpR;jA&1qErOr64 zb*vu7*=v?@T3Yn)YgTjNy9UU@f@a*ul1waJ#<}v{I}Teu)wnI5P_}eJ*}@4GS*@Yp zi0xZt>>DIbX$ywsF#oII`vpyl3f*zDE zO^%Ib$1s1`bnh~B@7*Ln11SdZc32KrWRfCrOD~p+9*y4fxZ!s$mo3;Oah_#@1b3?R zL;_&mO{*>V6X~nCCnfXFkmSK~kHv*TlE-BWc1awIL4sRkvKV0A-LfqhI;V;aoN;36#tWjAyS-{8&=gImAAsKJDlKILRc1fJue%ut{0Sz7V za8}3|!A@vxE=0g)1>QEy!>=Oa;rB)iPZ6d|dC?t=%}OX+>v*9qF0eFUW+#bNf(h!9{Oc~#8+%lkk?DV&V?G72~S!qEIlXXV?tk(t1(`dVhm?Dmp zL4Z+6YvI`>BfA#h*~SLCDZyk;L*FCI}}reSkp}i?xCYaeP+0h( zFb(S|^!NiW2#kh9a-f0>2inw2`8#%C(IL)R3Vxj|+6D%B;&Z?vedItvp12$wcp$Ph z|GH%>sE|CewI_9t=pB*+9l}HOd&_PRYTv~CNk9k2h#W8YFVWKy9}xt;2j243h;e{ss^~tph^LTCdAc!1U$r` zN&y~eP}Km(8&oO4X$Dmd5UKFAP&*U(0c05#&YlQ+vHq3$z2rs=_2Jlc5!%~2VI5kFqk@3#U zY&$a^){!JwHOClQ+a%!c>AN$v?X>{k7nFL&g~{0_NwokgOp=x^&SBCW(E+?ZpAM5_ zOfqW$whM|wyG-CHjM&O_4 z;eI19RvJYZAXb_x4_uL(#uGTQrZEn9z&Kn0#hpcRs+s8n=iJlY>p| zpAQiAOD{8QS&jy}LE)BIw?rxBgZp8ZDNSEqGBeDYgF7SUThF{@(<1Y-x=WN}K z>y3}>YdzF&x5DoN|3xwU3cm~dsTh8RxA~X3aref@L+AC!L+7>IrYj7Nbz*y|*miYP z6JFbFI?w5P!7i4OhtBJ!htBJ!P3J8kv2D4Gu_bQNdE7(?+#E$rnUBtcvjVCVOB3w~ zc(f(-B;e6;(6oU^+rbhC-mW%}eJX4o`xM?|pTc|WQ+SVk3h%K`;djA4wQ4-}DZIx% zh4AXZ&!bPp-Q%Cad;C*)PdvT(^XU6O&7ZB0Po}nSjI;e> zob8kERQrLnoPS2G$GgsLI#26C%b6Ip9(8YsQx+avP)R5}+<@u8+bzbH%WcAz$v9h{ zubsHE#(QK%A%<yQgf5ab(Id+} zOxd!q%sl?8^04g#eQ*9^nR(=@^6<#@mW{{W9?KH`lRky_$n`GEsgiFy?`Xq$a#eoM zk;8s(dH2XwarDSlc#mA~vh>JR@$$%3c#m9fd~LbB+-#YQv*r1g;$6DnUnjxAt=>%miy$L-;F}>1SOLnc;be=YcwBY?ZR8HzHy-U)A_Xz-xGQ|@B z;BD2mTwZRr%=~2udA?=o${Od9HO?%{NS6Cl&Xz^?t1_@{1K#7Ww`@FeRT+5XD!fOo zw`@Fe)iU$Q?XfHo1MV3*CY3TCBC*?K2_K;V4Us0 z@APrEEXT*9W$BHPP3KvbSdO1WqSTX&q%6z1(Qc{mx6Ax-3vVw=TP`m*TPEXddA?=o z${O#HHQpo3eHVo-3(L>84S3r=;Cu6z=v3Kw{ZLmBUj-)a=pv)70LIm z<{j<%@m})ok*k)a$6kf^$n~~8kKCQc*CW>(Ut2COH``Xm+46kL^0yMx_pG&K*NRQ& zS(Zpk-r--}Lc=s1mZ;1W9*3B`ZtT6~w&mt8OUPuLEzh?sU0D-N=ptDYJ+j;<1PZHs4EAEcbV=%Z%xhn96}EG)xtv8^FODM1HMRF9BBbK#Gp!Dr<~8L z?&PhX-!gIB`CC70M4@_@Cl(Cer{aCD}5K%c@Moop;1%jmyUjY1i55m#XUs5t^ zcFa(ip3iPTFT|k~AP}s;$Jw37uTt*e_m)DbxB<7Q-~mFUT2A=<0PG<;+m!i^C=;yq z9>MCJu?jYT(bJC)kQOjjMk<#5;)(^dc;`5k1wgR-%K}&PRx{GDxq4T=wq4T%HXNYapGRBp- zP3LiQjvV$gGExTv*kw=^0G}3AQLyyg)*NPkFj(LBUqZtoBd!wQPYtRX;4^u$Dsz~< z6%hi=S6b=p;%&lki;VmMeh7Ob4`(lG@WDd*7Ab%bMIRZpB@xON1g{ayoyQfjbzE)n z{_iM2PM$EasQ}}zB9v_x9E3)`2?tvg825u~;6u)-lmLQ#H~#w55%hJ_K>XgAQ40`R zGqkpS{}bK^Mc?C*UR(S&xzuM*eTC8j@D~PE3-A>|(O1t>xnuU4!E(7{_EE$R@MA;B z?3jIGu*{CxK7(OUEx<1eN^8e#n87kTW|Jd!fF~J3){fZ}gJt%(@a$onsRTILpsE4F zb*|4!6Nq;sLV)>7-L;CGKoflv55QjreC`5g*310;w`qc;dLU*`8!Y!g%x)f{!%4}q;|isnMnfgQM-8ePAO!05 zh*>1w$%!kz4C3!I;*$U&P`4}0-i!zVZWUBvkQoGcsW_>bF^g@Eu@{+Jiv&{N#WNmd#HOMbbFb^R{)$VDEf+u;v6RM z*YoLgcme}_y$UpNk?aPD!lW-T0SMzvp8z7V!dbZAcYJh6P#b%QgT9{-uxUJB$!3#y ze;@@qrkVIUmG6=`i37<nnChIo=S za_K%pQU&mHgPH~K3qkR!uF7FHR({)t8XCZHg3^STeJdga*xiHBUfi(mC&rXYfS(vt zH9*+IN-K?ZBaPB(fUrjsVs=GD2r%C|_dI#OnDD-gzSaX8m`$w*AlN)b1iz6ATEYM$ zE~l=Z7CT-wp{W4)wn3F5N{1SEOA&!d2328a0)9ZfuknBe4wBUXKQ;Pm0ivepu7hsn zFoSib9RV@g*j5V=#ik`-24{=}Ag+oe07MmP378@4MuHs-L=&#iAr>I~=*25rVn4C% z2xFs@fdk~yVTPpkJOSrMC|mGixpYxH3Ea&Yk}81v@1^BYi2@uZD7~^V8xs)%9NU8s zv*{5bz>*$>m{mrEwohxt&=-usr2zLbToo{FbcBKtxJ+s49Rj2})N9W`8k+)&GXZ&y5id*B}vikc{*zWE&x0&&5PM8!O}ql;PGObCd91F7+ebwK4`+YD8Y7m zyao`4(;eJ9t(d@cq5}vc6&)rpljs1#5JlI!9p$zi>_BGnQnQ$cEzL}1FPe_QKHlZp7_?)1^psgT>$?JyB z*$KZTW}a?HoP*gWxwI20TZN=Z7N75K*rjprKW!R%&3{eWaeoidf@o4tK-`dWLLt?t zTteC9Y70`!%@(DQwlMF)JY4KLSw`9yJiE0`<-4nLY242+Oc5>3JJq(oEa8J>91ye( zy{;%R{LsYk!*f86H|xC24iWfA2np5IzI`zPUt!Q@^95l1iZD_tZ%^ki11Ie?0FUcI zXv=#7Cho7V5MzOW%ZC9~0q`n=ssec20fq|Tn}X^WtXkXExBpFvVL6~qJkU@Bd{9t% z)Ii;Okf8=Rakxh1Q3F*WmuRO1xWT0c>gt2FAkV&vnDjR>sRW2XP@S&t!UUn9tq~xk zD>|(x`q!0TX3M9R>Pjzz^fye*X8}ZjxdWD&aKjAGBV*Tya@UAj*NAc$@tQHB7GS;+ zYPfl z)u~Fd6)L2yQXy@n3TdlVNIUYjV#+quqW%a45U%GH0PI2i5j8+WC65}0qR8?t0fl1Q zwYrP4T4DQ30&H(frM}utoy`Wg+@PufMx{0zF&TIOifA^#BMhn<;8O;bbi*^-4iDWV z*kK`*8;;qC%myi6q5>F&VYV9v=h^>x;wv1b`}s?NGFy8!eEzEOrrPzU+O@OVHLBV* z%IN{ei3O8oq&Eu#j1rNAQ3y4~z%|MfJWr&Ou2D(5U``cd&WMZxI9*V*tk!nfe7DKP zBPE>tECzP|UE;~O4U)>=$mn}!W6Ppf-)vEYvL$(bXuuUz;R>p71v$&;N8;UsGKRtO zeVyBgSLNaxGSZO};I9NlFL!%>(ELww^)tg*25_jU&Qe&u#Z+e*!1oQxd9u?e0y-i= zsDdHpBpi2^16s{evPWCN`Dt<^(k7iZTiky^#U4$b>3@kxC}C4I3bC zMedaWY>`V;!R`y=E?*V+hDLmD<&Tkz$M1~jG`VsXAzO{LjUMgu1hNL3(w%LKq6KYB@~m+Pf>GqJE2zR15lXW58zn_<*e4rZ`Zd?*)$FfQK1q%bY^|z&6Ax=GDoU84P#Cu$GOn=_0ovTCb>trKQ~gG=-MRS=z<7V zd91NXb`srixV95j?5RVS#HmAp1X%Pv)GYrZxt5h!4#FMnirF#rX6~JE_R1)AX57&XGX7O$slRigiBt3)p zB(0xM12sx6>8itQ&tvkWU@~2hc~XG-R4!>Ln4K^(PYNdIjdpASYPYfal9qzmY{4pz zF!^2&Qq1njC&lE(3HeenyF;)_Dkjxm%_qg|D#0pJOpchGPpaYQU*zl|lb}j~2t1u= z0V3*p#bJin5+OhYRuf`|@DU-v_r^rlRpu~5@Q4r~BBv!{hR_iqzyWzttju9{oM4F% z;Ke-%F++rj5MaN&U{~faJ3_ET2oQPDHe!ZE5Fx<)oVag7baPUMoQ#k~P#7!<03!{Q z^(|>ko*t#+%7lRbC^$uk2~1%^`|oNgighyXj0P6cD=h%uk`+#l!z`>&LZK+I+z4ea zBtm%-Z7&R>@`O6h7jz`r;sBx}(TM~g`jJ{mn82UBwqpCG=xxsw()LXuZSNG)_D>;g z4;9k(@d?Qj45b@Q+dx9u<`K#^j!?E~gt84Ilx-HFY@>cGMxiR`fdIgVnj@5CL^EC?mk-MP)3ZiP4L~yA1gA7WmF2mSRZvw*NXEjD-`EN!hz-Nwf`xx^&c{N z9)!3gm7s=)B>G(^G~oM-i1xW`)9ge&#L&{Ulkl7saL-}&uad-%WTb^}y_;2l6Dj=;3ddOAF&k*2|>>4%4bQB&eJV^D5}^BlY!P$;fno!=v;ya`F-Z z|64{T8zp--b|l8xOM-D)Nc1mEE66hqaAfXrIl$)%9hq^PfIrA%-I-U1=9vo@ux8ja zd!6s93lBQxN}qYu8@G#R|htY$61%eIfsK}hiIfvXvsT~ zqKZQ$9VKPs?N4XO#nPP-ohKJBk~R_HBDn**m<`^ZWHmB$<`F!Tr_L5ny}S_Pp1PBbTeS{|63YLN8SHM^JWlFB4h zqAO8QTtQAoVEfvIx3Y z0UHUZ1h~d9EX`wx6Ax-nfnz85ky&ldZu`DmI@=t-ljwNwnU0wpBhhRzd31{8Wf63Y z2;$@bo@{U@HpUGE6^M#1~YUDIP2%^qHFaEi*oR$PxU{o8E&F9^%_7d#} z87oR{K2IC5lc>V7Ui#t&85I)wnI?ho1`uXX7bA$sJxI@!i|L&ab;`vb%IL8jBpVHh zQ@0@bu8{bO#irSbCW!H@Mo5W_adLZwEV*x+rB?;;JA(4Y3m5N*h}_bBQZBv_5xJ4a z#otFnuB7d9@e>)jHFlZS2yCI$hNm?`z(0+E3#HR7rPc^+B*3}VfPj8RhZD==<u!f!yhTP&`ayzq;YmM8xPJ%jsd4#zAsFQ&6q`l35t zWK5FL+aztn=zZC1+l*DT_jklbb$ZpL14g0yKo%iSe$df~mI0p@t_aFOBu(MuO@ zFFZ^xA~D{cfJaUH%F-SfbZw;XY>^jUfgNTRzH{KjL;q4kQhwrbI`^l@==o~SZwvK{ zhAW91gC=t$;q2{e9Ije$)f+CSH@dp2U9M`oTy3r*4ouEw)L5JM$71Ib#=BCR(Nh}V z6l!SpblG=>WSbG}98I$lh)x-M-sS+i(uAwbHXZ`Hi~!u`ETp|0*hqj=zYuVR(cuL5 zM!9seA*lk0!@kG+X;RQ<%IJAm__AEuCZq3zSvC!|>4z?G+M`R=b@`qSRVc5j>@Fj} z%djApYM@Y&;Q%AXRqGcyj7JK?88XsW${u@HvC3Glw0=`;iJoWnRif;|Na+c2N^M%d zQk%-7^hr_na-?)>oKlGcsE1C6fIv5tCYJ3drMK6;7YC#aDv$blh_XN zsx&d$uSOHfe%+Z+_AAVU!i!InCK`=X1;lH*L}h!|SG+pkcsC1R)}TrOt}&=`fIl^; zQh-qy$`OVQrmL3&d`eJZ(B73pY;H5*ng#Itf+D)5IZW0Yy7EEewNFE2q+J5wQ3h2C zaJfOvLh!3iK4u~KW%5=4I;H@u7LZjtzXKsb%lsyA`Ruou(ojo#uS+wM4!_%`Q>slga(L!|I7D5)f3(KHtsp`3NP}26F;N-sx=-GvOzEVxzsj6Un0+z`LZh3TWI5%-1`GFy+1PHD$SmqwRUA`)tk55f!Fd#u7 z=nYW-BQ9r&xm+fa;NtplW7Z)3v|C0p8XHU#7GO{c5c`a$qk|-CxE$9&k})Ke0Kv5z zzc|`=gxf$}-Wr?N@8Ef|JicdEX_=iko5Z`?LDV5~cu4|YYGhXcyh>2?e7GQYolGJd zDr_6}m69tpwOiRcNv~48o>Ys9Suzd`vh+e5-hlw@oV=?Ua~0UR=IRCXzJKrn+bmZ- zFVWe`_aN2!DK9Qf?uer&DBb>Jfvl>oCbEOs1W0_eR#8Z%k5mB>ha6yTYH z;&)hA7GpVG1%lqQXaGJsbYpJoH>78ENj z%V7pnJbS2XN4d|Aa$`q>v7;Q|0VgB2wE(Xd6x&gr!|bJq5a8{_npYEI_J&|-0|VHW z=UI6UGx$w}0B`9*h*=Z@rzqVJ)c8VBV?t14LQn$`%IQG}Km?yXtMQ~_mUcY)*R^A& z&yJbKjt`6-)c_G`Ryxzf{W=rQYJiBeCdBNA5h1`SdEuOy!>mED^l%j*QlcedhG-BW zK%_(yViqN+Itqz~o|Ljd&CuZoAl#w+yQbB`h^5Bb(q#g|7|-diNy6G;!dnV(k)Zgu z4gjx;$ZW%3luNHhBmnD;3kXg*#1ETekLQm2H5BBVnvmU zqy5wvQ3Vj}d{|%ZFz%rR2E$~eMFeo1pnRYIf>6-ViSD*#wo#D1pOHP&Cc&j+g@kmK7|$WCF0G2Vr3SK^&+&!E;F*qp*XGk=$`lvo|Zo zb<1_MQ(y11Wl>kNMG?xDqDkJqifNu-R-}`VC z1xcO8HM7<=)9FWFh?;>CWV+V`INYF0A$y)dl>uxsD5o7lK%S9-^@mf%4kM)s;2o!E zT1pbYO@iW+NmUNB=cgJ%fIkJK!~FZ+Oj+^pZ-hy9ANA!1=qJs zJvu7_)cXt9e)O4@!TK{RiLSkeYG~wF3WB|d246Kri1;uLm4IqwoSiGs{8R$r>-#Rvq+aFFapdwJ7b|VO z()u66+gd$OZ7#3^K}s9q&OkP;U#U&yQHrQvE6O=X%N!qlR7-oM^6ZuKB{5%*FZjdc z(nuM#MVO5lIO?V-l@Du7`3haH|o zhKzR%*(^f$K2^tq&I16CGpGuHCksmNa+p0o4ZKb>aK%?bJh)j_We&5mjnYbh-xL(z zKmfig&ydO-W}EXU0mC@0#!k9xUzyLoGGpKQ#=bIuPaF4V1I$^X*%Gb_S~MHDgj+1BfY1wdxy76#P_H=!P zHjw{{+dx1Y3N7_`fJK5L>pf3(4wI{2F^n~~9k?_}NXU-I&yjEtp9$4EFC;=}$s<0V7PcK}q3YW{- zUQZHB;KIM@kZn4|<(b|)iDOi)7*&@Sre!(I+5}6FegIz3gV5FpaiH=9&n0n;Le2)s zX6 zJ1`;ycu)^Q%tl6p_IiZU-3&=3Kq#kY8~~wNAFMFjFX9CVdx#exjM2Q9MW#9Lv4ClX zMtm7S*h6gxAdF%0WjV}-M7#i@SrcLw*->VPXpG31YGhRbJXKIEt15?CRYVvk>tsVx z2@oBEjAwQMtm7S*h3`*5XP|hvK(eBBVK^etO+rT>~KnG zjmWsq$f^SPV?nX3svKrdM}&5`A?qGPQV9?;DP#a4P=^e&NW2rW%_8=XMtl{(t%A~~ zV)ju)2yjOaLfZjoc*`(W0)!@V03g(82QYg-;suzm)NQW8bZy4|GE#E|I80F5EzCwn zgth~awT~gG1PGbr06+-T4qz6EcQOF+gN^tyfRIT=3lIWXd|3{&NW4>vV?=DJ5nlzc zOi(%!m@SM50WRu6XvYT{W*EjwfY3w^0E8MHAI#b#UVuPMObP}-2-K;OSNC1RD9SO`L@lGT* zh*-!ZQvpI|tav*TkOlYYsRzJFR!k(~WJQcI8L}C-h(n*7cvS%$RicUMs1NX1LFsH` zc1lDTC;kH?z7pUV!&M6q0(G`Ai^Myxio4dA!TNDV{49VFsI!e(B;I*>?F+HG$jB-M z*U1se_8HXuBNBl78&pNHfRTFV)(F&x7_LfyBMi#9;dHsGTrMY)r6RD|2(AM7O@pcc zxL#1Y4(tFx)@;LA3Gg0+nguXlmb$us~X^HLD2`93v!s`D{!}#E@8RR zNGk>SBZG48wKH;Qks&Dsc$YyrL5AR*A#nt|B)cHRDO|Yxf>BfjaFd{P>M(mVBDAv! zSUJZ(3?O7uY5_tZi!aMz7KwLK`<{q}OfnT9WX6iOBLP`(pHd4jk`)t)I9U;6 zOonX6V#!oRlrex87*qwojG%P3<7Cwu#!7(g22~9(UzXd0FA|1t8pbMsYYnOb;131m zx9e)Tdaa@I{d)O&x%z^PRJ#B-8AkQqGMT*@5!#V}tY-~LB|ymJRV!EX#aHGqi^Mxc z4)ISJ@nrxZllzxPJoPWZM&g|!-zFs6jrdA{e-l&@eV}c)^LR9vp#!nMjC><5;4m3= zhAFt2`v^G=NVa50M8c`%c{y@wjd$|*xZBA zP69Mk8^%h2&_tdBgc==4%u*3Azkj;KhQ{ZeezPL})tzSzU&t5+Gz! zB>;p#?Eq$xc&8H9h}Z{=_$q)83QC)b*^3dOZ7O8lYe*^qLME9C5CXNSm__0pQ*k_8 zEPAh(alLJa%*PdIV7!bc%Xq4cHe0vgzc1q*GTs?OzeDg}$hcdfmN-;KTmEka|CWsZ zlrao#N)lQRCh{PzprPh$9M1%IWCWxd!tOs-Fq z@kANHXWO?@;(m>c*UR`F8EyJo1b>H&>ty_|7<$yp!;;rP{MaqVU(h`!^l!`f0r)M0 zK=+JXM_xaVkq^3`3q9($RpMlc4}kBK>)((uuHK)q*3+I67p$im(Th5__5Dux|69iQ zWZWjBO2Dq>Q6w93MjuyQhdBr^$Ghj990c82<4>cap_lB6Him z+aG$r-Tl6trR^r{r83LZW-6hxU2k|h5iE>Zx=mx#^`&+qQ9dT z`atqz=c`fp5a)?8@eVEixxxqj@xm9!e}&Xdx76hmGCn6G`s^I>3wEN<*?rQE|6`W? zze*j)$+P)43IBE(|1RU_GTQV5#O^^d4w3N^8DaldByOW+gg>^tPsQFt#Q(!(JX%JZ zeyrf(AM_j}dTjdRg}y|_vn_s`-p&*H2=+yrey-%dNyauAZ;^4cjBm(j^Y0M+XEGM< zsVVx%*k8s;GH#Lak21b1P9$T&bo+rB2jKPKbTGJYOIU%a=LuvW&GWc-Vaw*0RPevL)H zC5Ha#eYJ$=WZWdi-u{*-7;=EK+iYJ__B;| z%6Rp`wk3Lg^!|GMcjY~Cpype9kRIO~uE)=1jMFz+^qnl@sWMKNQA>&by-o1L#ZUMX zi2f%;-*04$I5qSq;U8-8|54)dj*Nej(dI7|KE$Ut|NbR*6iK|lB;(MS_#ZF$DKefW zV_f{==<8zSqdo?Te-p*N8W|BcZ zJs{)5GX6wHoBk=m$JM`0Un6?w$oRI@@B1>^^m7i;n6JrrfsCCpUMl0YGTtfUdKqnb zhm6pe!(^N);~6sA^tTFrt&HnreCu#ciC=x%^B6tH&lweu)N}jCdGRwS_{M1bLC zNBn*z;$-L7&S!7=!w>c1_o40Iy0z_%qhEZOP1)04{IV;4))l{7^qmQs4)teC!Ow-> zC-we-jE~FMTb%5Ax8?sz?EbBc_`Og3xTj5zU%4DB`t6_R#Bb>#Z}_dt$&$ZQWW?{0 z+Vb&BmiXCI{1{}M|GUcnU9s1u?~-+Qv5eQth+m4d=@&>nw#(QdBmCY~di*S*O^<$7 zafH4yUq*Bj(ZAv}Ik9n;UzHiI;qKx3jubtUat`fQ3GU6Ar;`Cu3!H)vrM+eY%@FNH4 zJA>r=|MA;0wtmQ)A^TH>jMXyQ^!UN8PvpA&!&o-`uu&RwsEqdSQrYx33*Fr^J}D!9 zFUqF3Pu7X|*)_$`(5&i|Ia-yN^>Rd9kHVIO|I z!p<+~@PiENg)h#ZpGw|ek?}V&;s*f z|CZoyK2~2r{op(Fe4GBo$r^M1iF#ZtmTV;Gl#=pw=4;gKK``fi|>P4UZHLv)B zP<)r@b;Vl4?K0Z>@TH~p7mR}6rholpjd@E(`&&nCdVKR|P^_=?mvIjnH8$^G!S|7I z9~t+PF|htXXUnzuj*a05zDBO&8wK&TpO(7dhe9`IioSyHFT|G>b_*U~DQWY6A^gK* z_-*>X2pztKZ}Tad0$*``_ia>34`-14J&qWD9z2diyJR)}N{=@D(jKeMYV? zmJwf|vqI)J{S$)!rHrr3i0{O)>3=8JYfsZxnq};e(WXxbeoq;XmT_VX{SAWuwu}$U z80YUF<@%px#COi%ds%FIfbVy@zJjlK!FR;i^q|{A=!eQUTt@KWdsJ-xI6mmL=^+PS zg>sYV$;oKb13!G4zJl-3m?U$2Z^Y9wxA~tIxzEdpF9^XGe%SQ*mXAR(`fPgGagxy6 z-@;+jHwxVX8S!l!`1TB&evcB387kxcGUDT1HvKo{dbf->%7_mX+4Q~6!=NCTSXk`P zg+XCZ>BWb^VlTcZSnI|23HBXO9N2#$y|eCe&#n~)y9LEx^3f-PC%pK6!Nfs6`u@Sb z`}*($f-zqFz~G_-eDu2qn{V>r_XxIl@m~st-|wRz6fAzwhuj@L%=?eyzPQ7#NhES*$L-Dg;Lfe#{JwpH!$X@R_23 z-bu3MK8;_i(LtHuiv@qV;G1Y<`Gc-1R+uk|oQnnjM61R>xUae#{D=mhosST{AlNq; z{>mIpxL6O*1Ak_nLJU1a<9{Le;%haYDnR{hp?_IUjo=d+9lS62If5?|d?5vn>E~PY zdn^1t!N!;8D9TXi4W!YrXV|BV*>lf}hqzMJ}2|Ks!bM8&tKvo6jid_myW z|G7eMudlBuyt_`9DLL-CxR&sP$^MIEy(@My^Lv8dk}6h4@2*V`)(if@V>G^A@Q*9J zO!9``FurhL&@J+DFZ2hIv;KT7XNB-=kC9VEbu>6nF2KDNeqb=>1}$f#TsTtjn@`aA zs|5em7&+$%{Rc;D`sajxW(<9s&_8jbraw&Rm&MR`$KdZ4Ih)1)BSp?n1iwwT#Z$6T-DFjwq6 zAx6$QLSHI(o3LlL;I~wB9qRZusx&7<&G21=o3YO0lB*Na*j3p?{3< z9M5gC-Vx7V#L&M<@(%IT`JWX1z~J>0wcZCs@84qN45YyN;(w6B4-EDjspY(^ya<9( zg5Q0##&dtO?ue<^<5 zDEQaKp3nMfNw+DyhV%b@BnJO;k+ZQ_%U>r&-1E%eW9a!!`dkllq@H&d z`THw;zJ(ed6@xDkIqR=2R)mN%f4IPx$FIfU`9lmo`cp}&>d$9u`THm>L9jeV&aE+c z{xFA6{!0o!Ft|(dc(%y@RSf-yG59`|XP^B2V(^c~PSBGjb!6U#+-sLzGY!rN8?MH74eoL}gN%)z_*{1L^ z$s3BO9(X<4=hZ!9>f|di_{j=CFjyn?Gfm=99YeoB=r>#ac~K1gsu=taL{9PCV&&Cp z>UaEiZw&p@G5FUBKU{J4{O6q*`hUdWcc%uvXW>4<6IOrQkMO>_9m({3?v-(?>#AH?8y>*tTdAu;#~G5G1^#~|8&+vFTB<^&~*eqgYEj`sIT@wdOq zdvu>G@7V}u3;i}LU(GRkyM%sAvzGrmk$i~mwLy)=%F36h5Axp+1m7+FQ(oH%9*L3j^BDZQBBxmL zj(z!K!EY-sR{BzsmoE+Q$LHV}{Bbe(5``ZaEId%lUn~cU>KOX8(2tRQ4eNBd-~-7! z;(V3hx6Rh_w<#}z;FcKq_r~CV7K8s)4E}w>bN}3I_0NAO`hmglZ)tlzl|J8hpw4fx z_$BEL_7VI=l3(~cLgB@kykSBN{#Dg~+~;7`G4%W)24DRzjlq9627f={`Mw~K=MrRw z`g<;herpW=6NMibTzzt};y+gEFlcU?+tglP-`tdH&5o*=gO}A%8wbiv}M~w@b(`~8t>E%;rr01QIW>XuR znp0ES+v_?$Kz^+)PD>IY<)l7YpXo?8l6)1O`gCh6#brX!)=pt#LzRz2n`u?3 z#$^5c1;xeFW=ub2YI5ADV@HkWYuUQ2V&^0QHaV|R%hK`n0dsBTtqU!51srr_-o{aVFsk&_H)TVYySAAVGC!;3;B)2xzF9_=9 zrrWbUuP2jKMy=^2vuCO7dR}GjhNg@}L%G(JNy;?Uz-F~NHf6F6=?+T`%xIy)grUiH zS6L>-#kyE&qAbp%DgURe=NPngx;z}Xrq+c`*_2KlO&85iH)VpB1r1Fe9h{uH`ubE` zHfZa}W_k*2sH2tGdRDq2#fhtH=y{b~YqCN_7H87+3({?t$1QaWQkAI|T9#xNOKNUv z%_|tLgU0&SY;#WqdCQf`K#Cwg{HjXk*HLvgCtKLcrdEzmHeJ_KP%_m}m#xzQQ5}MW zEKId$la1}^mShX%BjBJ?71y=SO9c%bEp17qJfL{DrMOYprPNs8oX%L~m7$){npNQ< zzWM1)c5Wwg+PS6N5n)dgxh6QdWR_}p_4A!{sU@YXT##(6Ysw4Oc$4dFx{VhIwS%7G zxm@O3>2J%<=TszHI84gPAWIoe&FyIH zDX%5fLYI2tsIsWJTHzoCt+WPvQgU@QS&m^Xb!1ZQx&}B*?F}7PZ(usTp|mz|??$6j z?J?O>XIF9~CBs?`P}SU&(T$DE?}Cn|XrgwOcHQH3N>oQOyBIYkTJSxcN+!8Bxm!}3 zR`pxg&|qbXvu8IuWlfJ_&Zc!KljT&%mIxT%l9@-YQy!>$^h_&v?MB_sds?V9sVyLA z%%+tZFfkDf6wmBHG*Hn+lZ!+_F%dCQE^_@|z4!HW*Yu!Zu`^Zm`h8Wes$RWU zUGvzQ;`xo6X2B}Q@d#!^hZM)|V44)cX2*caENBN4QDiZ8AiSGX0atRIhDX_b9!KS45;Qd z#VfmM%Sx+GxA-l1a#+o?XXB#SOJ=pneB2d>1>|hXF8UYl7caN^*h<^{xy$^W+MxtDKFX!I-thX6FvKm+Vg#vWfa~Z1TD*d&tjO%~gpFtXArhcwJ2V zV$Ce{CoT4BxbDB96>>6cPKS(Q^8wBcTa8PZwaf)JUds{C%MY>jJVN`dKC>x_m<(vf zy0hR)c-!bJe&a$RCi9vPO3G}~Y*99TsJb$qb)Cpy$l=w7lacr=nfG=v;F@u;!7x|r zVy8=yOOI+ekI!)0Y_kRFauVz$^T$oOhgWi(K$^5TzIfq${Pc5A!6dLR*eR96#L80& zhC%qVPqCk-fhlk9M%ix7j)qwtEH0)Ie@(7tD{VV^uRNTmabHe@E9fKeeFIp96-8}~ z&DOd}6^#g89!@hjd%l>KCEf{&-J-xt0e;;m4ySlsK@RKa^D#^QZDsBvEL9pkd2aXN zG8wsOG&_jKNilZO;BW@8=4Gx=sHvXKDlwkr>3$*rE6w*y7kQf%;TV9jKlVp?=8sHK zI);ME8D=~HmNiA_yN4oJet8dUXg!(Y91@K(G>EUr_o6MrVz_88o674MSaC=g0W1eE z(6u_54KtRLem_qata;5eE=*2E&d`}+ttEX?{h!|w;UKT7cKubw*PJmz80o;*T6X&Y z3UakY{Kc&vY7X%@K672os&C#8kZ>A>zmAVH;+I=J|7dB19bc1}0!@5Bx2k&r1zcHF z{lCA}L(L(+$7gPC0Q}71$4NZz_s@eaR~+o0@jo4D6e+X&53Ok%EKB|@KF2lr87K7m z?aK9$W|jQxhxto*{&x+}cq0DunX85mKXvrBa^U*4kwW?3z*E6<{`vdDkB09B8>ri8&AGP% zJmaytA1fpG5n*Bf?*(|qZ7n}h!~pkF^~Cif?E@4tVRt zZzkfI-w5zkoZ6A%u2C_p8RD4#6yW*$;I;1*z&H_uSNo6kUr~^@IDW>9d}a7Iuai^r zZnNrsLtVzd6VQq0JvATObb5@?{=|ng@<@Ku`VZR;d2aJMCaYas0F+S`D?ZYci5 Xi8^(C{qEd=fAAN@OT1h?1y%PCK^t8H literal 0 HcmV?d00001 diff --git a/defined_values.h b/defined_values.h new file mode 100644 index 0000000..3665af7 --- /dev/null +++ b/defined_values.h @@ -0,0 +1,47 @@ +// Define period before sending PING to server (5 min - 300). +#define TIME_TO_SEND_PING 300 // how often we send pings to server +#define TIME_TO_WAIT_PING 180 // after we sent request to server, how much time should we wait for response before re-connect? + +// Set if you want to turn mode +x on while connecting +#define X_MODE + +// Current version of the program +#define __CUR_VER__ "1.3" + +#define NPING_DEBUG +#define NDEBUG +#define NDEBUG_LOG + +#ifndef __TIME__ +#define __TIME__ "-" +#endif +#ifndef __DATE__ +#define __DATE__ "-" +#endif + +#define DEF_HELP_MSG \ +"Avaliable options:\n\n \ + -d, --daemon Start application as daemon (experimental)\n \ + -g, --genconf Create configuration file template. Attention! It will overrite your existing configuration file.\n \ + -s, --silent Silent mode. All program messages stores to the 'output.txt' file\n \ + -v, --version Application version\n\n \ + --help Show this message and terminate application\n\n \ +Configuration stores at the ./bot.conf. Please pay attention: maximum lenght of the file is 10 strings. In case if you don't use password for your nickname set it to 0.\n \ +Log files stores at the './logs' folder, if in 'bot.conf' you defined '0' for this setting, otherwise it's stores at 'YOUR_PATH/logs'. Files have next format: YYY-MM-DD.txt\n \ +Password for the nickname is taken form the configuration file. '0' stands for 'no password'\n \ +'Link' is the link that returns when someone says 'bot_name something-something'. '0' stands for no link\n \ +Be smart! Don't use too long nicknames. Usually they used should 30 characters long but may vary from server to server. Don't worry if your nickname shorter, but don't let it be greater then 128 characters.\n" + +#define DEF_DEFAULT_TEMPLATE \ +"server: \n\ +channel: \n\ +port: \n\ +nick: \n\ +username: \n\ +realname: \n\ +password: 0\n\ +maxNickLength: 30\n\ +logPath: 0\n\ +link: 0\n\ +reJoin: yes\n\ +floodTimeOut: 10\n" diff --git a/loperIRCLogBot.c b/loperIRCLogBot.c index 71b3270..9b99f11 100644 --- a/loperIRCLogBot.c +++ b/loperIRCLogBot.c @@ -1,7 +1,7 @@ /*********************************************************************************** * Author: Dmitry Isaenko * * License: GNU GPL v.3 * - * Version: 1.2.2 * + * Version: 1.3 * * Site: https://developersu.blogspot.com/ * * 2017, Russia * ***********************************************************************************/ @@ -13,32 +13,14 @@ #include #include #include -// only to get PATH_MAX -#include -// for using setsid -#include +#include // only to get PATH_MAX +#include // for using setsid +#include // Use syslog -//define period before sending PING to server (5 min - 300). -#define TIME_TO_PING 300 - -// set if you want to turn mode +x on while connecting -#define X_MODE - -// Current version of the program -#define __CUR_VER__ "1.2.2" - -#define NPING_DEBUG -#define NDEBUG -#define NDEBUG_LOG - -#ifndef __TIME__ -#define __TIME__ "-" -#endif -#ifndef __DATE__ -#define __DATE__ "-" -#endif +#include "defined_values.h" +// TODO after implementing signals set closelog(); // TODO normal deamon-mode functionality // TODO make it multi-channel // TODO-feachure make an ability to define log path for the bot.conf? Or move it to /etc/ @@ -56,6 +38,7 @@ typedef struct conf_sruct { char logPath[PATH_MAX]; char link[2048]; // should be enough to store link int reJoin; // 1 - yes, 0 - no + int floodTimeOut; } configuration; @@ -78,18 +61,40 @@ configuration load_config(int run, char * nick_or_path) { int checksum = 0; - if (run == 0) { - // the first call - strcpy(confFilePath, nick_or_path); - strcat(confFilePath, "bot.conf"); // add bot.conf to path-to-executable + if (run == 0) { // the first time call + + if ( (conf = fopen("/etc/loperIRCLogBot/bot.conf","r")) != NULL){ + printf("Using configuration file stored at /etc/loperIRCLogBot/bot.conf\n" + "Prefere using the one, stored in this folder? Just rename or delete the one from /etc...\n"); - if ( (conf = fopen(confFilePath,"r")) != NULL) { for (i=0;(!feof(conf));i++){ fgets(fileArray[i], sizeof(fileArray[i]), conf); - if (i>=14) // 15 lines is max size for config file - break; + if (i>=14){ // 15 lines is max size for config file + C.status = -2; + return C; + } } - + } + else { + strcpy(confFilePath, nick_or_path); + strcat(confFilePath, "bot.conf"); // add bot.conf to path-to-executable + + printf("Using configuration file stored at %s\n" + "Please note, configuration file also could be stored at '/etc/loperIRCLogBot/bot.conf' and have higher priority\n", confFilePath); + if ( (conf = fopen(confFilePath,"r")) != NULL) { + for (i=0;(!feof(conf));i++){ + fgets(fileArray[i], sizeof(fileArray[i]), conf); + if (i>=14){ // 15 lines is max size for config file + C.status = -2; + return C; + } + } + } + else { + C.status = -2; //unable to open file or it's too big = -2 + return C; + } + } fclose(conf); #ifdef DEBUG_LOG @@ -107,7 +112,7 @@ configuration load_config(int run, char * nick_or_path) { if (st != NULL){ strcpy(sta[i][0],st); - st = strtok(NULL, ": \t\n"); + st = strtok(NULL, " \t\n"); // if we see anything before 'space' \t or \n if (st == NULL){ // if we had a first parameter in string, (no matter was it set before ":" or after) and don't have the second one, C.status = -1; // then we ruin the chain and returning error. 'Status' of incorrect config-file = "-1" @@ -115,20 +120,19 @@ configuration load_config(int run, char * nick_or_path) { } else { strcpy(sta[i][1], st); - - st = strtok(NULL, ": \t\n"); // generally to parse links - while (st != NULL){ - strcat(sta[i][1], ":"); - strcat(sta[i][1], st); - st = strtok(NULL, ": \t\n"); + if ( strstr(sta[i][0], "link") != NULL ){ // if it's 'link', then add here everything user wrote + st = strtok(NULL, "\n"); + while (st != NULL){ + strcat(sta[i][1], st); + st = strtok(NULL, "\n"); + } } } } } } - for (i=0;i<15;i++){ if ( strstr(sta[i][0], "server") != NULL ) checksum |= 1<<0; @@ -152,10 +156,12 @@ configuration load_config(int run, char * nick_or_path) { checksum |= 1<<9; else if ( strstr(sta[i][0], "reJoin") != NULL ) checksum |= 1<<10; + else if ( strstr(sta[i][0], "floodTimeOut") != NULL ) + checksum |= 1<<11; } - if (checksum != 0b11111111111){ + if (checksum != 0b111111111111){ C.status = checksum; // incorrect number of settings defined return C; } @@ -201,8 +207,10 @@ configuration load_config(int run, char * nick_or_path) { } } else if ( (strcmp(sta[i][0], "link")) == 0){ - strcpy(C.link, "Logs: "); - strcat(C.link, sta[i][1]); + if (strcmp(sta[i][1], "0") == 0) + strcpy(C.link, ";)"); + else + strcpy(C.link, sta[i][1]); } else if ( (strcmp(sta[i][0], "reJoin")) == 0){ if (strcmp(sta[i][1], "yes") == 0 || strcmp(sta[i][1], "Yes") == 0 ) @@ -210,19 +218,14 @@ configuration load_config(int run, char * nick_or_path) { else C.reJoin = 0; } + else if ( (strcmp(sta[i][0], "floodTimeOut")) == 0) + C.floodTimeOut = atoi(sta[i][1]); } if (strlen(C.nick) > C.maxNickLength) C.nick[C.maxNickLength] = '\0'; // yeah, they will love it, before set nick name longer then 128 char =( } // ++++++++++++++++++++++++++++++++++++++++++++++ - } - else { - - C.status = -2; //unable to open file = -2 - return C; - } - #ifdef DEBUG_LOG printf("___Recieved keys from the file___\n"); for (i=0;i<15; i++){ @@ -242,25 +245,28 @@ configuration load_config(int run, char * nick_or_path) { } } -int set_log_dir(char * logdir){ +int createDir(char * logdir, char * newDirName){ struct stat st = {0}; - strcat(logdir, "logs"); + char dir[PATH_MAX]; + + strcpy(dir, logdir); + strcat(dir, newDirName); // add bot.conf to path-to-executable - if (stat(logdir, &st) == -1) { - if (mkdir(logdir, 0777) != 0 ) + if (stat(dir, &st) == -1) { + if (mkdir(dir, 0777) != 0 ) return 1; } return 0; } // Function to print time stamps when writing to console -void printTimeStamp(){ - char timeStamp[22]; +const char * printTimeStamp(){ // const function, static array.. one say this function should be replaced to something better. It's make me sad. + static char timeStamp[22]; time_t now = time(NULL); - strftime(timeStamp, 22, "%d %b %Y %X ", localtime(&now)); - printf("%s", timeStamp); + strftime(timeStamp, 22, "%d %b %Y %X", localtime(&now)); + return timeStamp; } // Mainly used to update is_alive @@ -283,7 +289,6 @@ void event_ctcp_rep(irc_session_t *session, const char *event, const char *orig returns 1 - not OK */ int is_alive( int state, time_t timeGot, irc_session_t * session){ // in future, it should be stand-alone thread - static int defaultTimeout = TIME_TO_PING; static time_t timeSav; static int pingRequestSent = 0; // 0 - not sent, 1 - already sent configuration C = load_config(1, ""); //load config to get current nickname @@ -293,7 +298,7 @@ int is_alive( int state, time_t timeGot, irc_session_t * session){ // in futu #endif if (state == 0) { - if ( ((long) timeGot - timeSav) > defaultTimeout ) { // ok, it's time to send PING to yourself or probably we have problems + if ( ( timeGot - timeSav) > TIME_TO_SEND_PING ) { // ok, it's time to send PING to yourself or probably we have problems if (pingRequestSent == 0){ // if we didn't sent PING request before, let's do it and change pingRequestSent #ifdef PING_DEBUG printf("PANIC - Request sent\n"); @@ -305,7 +310,7 @@ int is_alive( int state, time_t timeGot, irc_session_t * session){ // in futu return 0; } else{ // we already sent PING - if (((long) timeGot - timeSav) > (defaultTimeout+180)){ // we know, that the time is greater than stored one, so we add 3min(180) and if it's greater, then re-connect + if (( timeGot - timeSav) > (TIME_TO_SEND_PING+TIME_TO_WAIT_PING)){ // we know, that the time is greater than stored one, so we add 3min(180) and if it's greater, then re-connect #ifdef PING_DEBUG printf("Now we have problems\n"); #endif @@ -321,7 +326,7 @@ int is_alive( int state, time_t timeGot, irc_session_t * session){ // in futu pingRequestSent = 0; // reset pingRequestSent #ifdef PING_DEBUG printf("\n1-WRITE event\nTime Saved (re-written) = %ld\n", timeSav); //debug - printf("defaultTimeout = %d\n", defaultTimeout); //debug + printf("TIME_TO_SEND_PING = %d\n", TIME_TO_SEND_PING); //debug #endif return 0; } @@ -331,11 +336,10 @@ void event_connect (irc_session_t * session, const char * event, const char * or { is_alive(1, time(NULL), session ); // this time really 'initial' timestamp written into the watchdog function -// dump_event (session, event, origin, params, count); - configuration C = load_config(1, ""); -#ifdef X_MODE + configuration C = load_config(1, ""); // dump_event (session, event, origin, params, count); + #ifdef X_MODE irc_cmd_user_mode (session, "+x"); // TODO clarify this shit -#endif + #endif irc_cmd_join (session, C.channel, 0); } @@ -344,22 +348,9 @@ void dump_event (irc_session_t * session, const char * event, const char * origi #ifdef DEBUG char buf[512]; int cnt; -#endif - char nowTime[20]; - char nickBuf[128]; - char hostBuf[1024]; - - time_t now = time(NULL); - -#ifdef DEBUG buf[0] = '\0'; -#endif - FILE * fp; // set FD for the file for logs - - configuration C = load_config(1, ""); -#ifdef DEBUG for ( cnt = 0; cnt < count; cnt++ ) { if ( cnt ) strcat (buf, "|"); @@ -367,6 +358,20 @@ void dump_event (irc_session_t * session, const char * event, const char * origi } #endif + + static time_t floodTrackTime = 0; + + char nowTime[20]; + + char nickBuf[128]; + char hostBuf[1024]; + + time_t now = time(NULL); + + FILE * fp; // set FD for the file for logs + + configuration C = load_config(1, ""); + // Set name for the log file irc_target_get_nick (origin, nickBuf, 128); @@ -396,9 +401,13 @@ void dump_event (irc_session_t * session, const char * event, const char * origi event_connect (session, event, origin, params, count); } } - else if (!strcmp(event, "CHANNEL")) + else if (!strcmp(event, "CHANNEL")) // works like shit. Should be separated thread if (strncmp(params[1], C.nick, strlen(C.nick)) == 0 ) - strlen(C.link) == 7 ? irc_cmd_msg(session, params[0], ";)") : irc_cmd_msg(session, params[0], C.link); + if ((now - floodTrackTime) >= C.floodTimeOut){ + irc_cmd_msg(session, params[0], C.link); + floodTrackTime = now; + fprintf(fp,"%s <%s>: %s\n",nowTime, C.nick, C.link); + } fclose (fp); } @@ -492,7 +501,6 @@ static void event_notice (irc_session_t * session, const char * event, const cha dump_event (session, event, origin, params, count); - if ( !origin ) return; else @@ -508,32 +516,59 @@ static void event_notice (irc_session_t * session, const char * event, const cha } -int make_template(char * folder){ +int makeTemplate(char * folder){ FILE * templ; strcat (folder, "bot.conf"); - if ( (templ = fopen(folder,"w")) != NULL) { - fprintf(templ, "server: \n"); - fprintf(templ, "channel: \n"); - fprintf(templ, "port: \n"); - fprintf(templ, "nick: \n"); - fprintf(templ, "username: \n"); - fprintf(templ, "realname: \n"); - fprintf(templ, "password: 0\n"); - fprintf(templ, "maxNickLength: 30\n"); - fprintf(templ, "logPath: 0\n"); - fprintf(templ, "link: 0\n"); - fprintf(templ, "reJoin: yes\n"); - fclose(templ); - printf("Configuratation template created.\n"); - return 0; - } - else { - printf("Unable to create configuration template file\nCheck folder permissions\n"); - return 1; - } -} + printf("Attention! This action will remove your current bot.conf file\n" + "Where do you want to generate template?:\n" + "(1) This folder\n" + "(2) /etc/loperIRCLogBot/\n" + "(A) Abort\n"); + do{ + switch (getchar()){ + case '1': + if ( (templ = fopen(folder,"w")) != NULL) { + fprintf(templ, DEF_DEFAULT_TEMPLATE); + fclose(templ); + printf("Configuratation template created.\n"); + return 0; + } + else { + printf("Unable to create configuration template file\n" + "Check folder permissions\n"); + return 1; + } + case '2': + if (createDir("/etc/loperIRCLogBot/","") != 0){ + printf("Unable to create diretory /etc/loperIRCLogBot\n" + "Make sure that you have permissions to write there\n"); + return 1; + } + if ( (templ = fopen("/etc/loperIRCLogBot/bot.conf","w")) != NULL) { + fprintf(templ, DEF_DEFAULT_TEMPLATE); + fclose(templ); + printf("Configuratation template created.\n"); + return 0; + } + else { + printf("Unable to create configuration template file\n" + "Check folder permissions\n"); + return 1; + } + case 'A': case 'a': + printf("No changes applied\n"); + return 0; + case '\n': // ,__o + break; // _-\_<, + default: // (*)/'(*) + while ( getchar() != '\n' ); + } + + printf("\033[A\033[2K"); // VT100 escape codes + } while(1); +} void reportSettingsIssues(int sum){ char *setLst[] = {"server", @@ -546,7 +581,8 @@ void reportSettingsIssues(int sum){ "maxNickLenght", "logPath", "link", - "reJoin"}; + "reJoin", + "floodTimeOut"}; int i; switch (sum){ @@ -554,26 +590,99 @@ void reportSettingsIssues(int sum){ printf("Configuration file issue: value or attribute missed or redundant\n"); break; case -2: - printf ("Unable to open configuration file\n"); + printf ("Unable to open configuration files. Please make sure that they exist at one of the next folders\n" + "/etc/loperIRCLogBot/bot.conf\n" + "./bot.conf\n" + "Please note, that configuration file shouldn't be lager then 15 lines.\n" + "If files exists, please check that user have read permissions for configuraion file\n"); break; case -3: printf("Configuration file issue: 'logPath' is not defined as absolute path\n"); break; default: printf("Configuration file issue. Next field(s) not found:\n"); - for (i=0; i<11; i++) + for (i=0; i<12; i++) if ((sum & (1< 0) // Exit parent process. pid of is not 0, then it's parent. pid = 0 then it's child. + exit(EXIT_SUCCESS); // report to log? + if (chdir("/") < 0) { // change working directory of the process to / + syslog(LOG_ERR, "Failed to change process dir to /"); + exit(EXIT_FAILURE); // it's safe to replace to 'return' statement + } + umask(0); // set umask for using filesystem as we want + if (setsid() < 0) { // set SID + syslog(LOG_ERR, "Failed to set SID"); + exit(EXIT_FAILURE); // report to log + } + // PERFORM SECOND FORK + pid = fork(); + if (pid < 0){ + syslog(LOG_ERR, "Failed to make second fork"); + exit(EXIT_FAILURE); // report to log + } + if (pid > 0) + exit(EXIT_SUCCESS); // report to log? + //doing it using guidelines form man daemon + if (freopen("/dev/null", "rb", stdin) == NULL ){ + syslog(LOG_ERR, "Failed to close 'stdin'"); + exit(EXIT_FAILURE); + } + if (freopen("/var/log/loperIRCLogBot.log", "a", stdout) == NULL ){ + syslog(LOG_ERR, "Failed to redirect 'stdout' to /var/log/loperIRCLogBot.log"); + exit(EXIT_FAILURE); + } + setlinebuf(stdout); // line buffer + if (freopen("/var/log/loperIRCLogBot.log", "a", stderr) == NULL ){ + syslog(LOG_ERR, "Failed to redirect 'stderr' to /var/log/loperIRCLogBot.log"); + exit(EXIT_FAILURE); + } + setvbuf(stderr, NULL, _IONBF, 0); // no buffering for srderr + + syslog(LOG_NOTICE, "loperIRCLogBot successfuly started"); +} int main(int argc, char *argv[]) { configuration config; irc_callbacks_t callbacks; // The IRC callbacks structure - irc_session_t * session; - struct timeval tv; fd_set in_set, out_set; int maxfd = 0; @@ -593,85 +702,21 @@ int main(int argc, char *argv[]) { // end detection if (argc == 2){ if ( strcmp("--help", argv[1]) == 0 ){ - printf("Avaliable options:\n\n" - " -d, --daemon Start application as daemon (experimental)\n" - " -g, --genconf Create configuration file template. Attention! It will overrite your existing configuration file.\n" - " -s, --silent Silent mode. All program messages stores to the 'output.txt' file\n" - " -n, --nomessage Don't print any messages anywhere\n" - " -v, --version Application version\n\n" - " --help Show this message and terminate application\n\n" - "Configuration stores at the ./bot.conf. Please pay attention: maximum lenght of the file is 10 strings. In case if you don't use password for your nickname set it to 0.\n" - "Log files stores at the \"./logs\" folder, if in \"bot.conf\" you defined '0' for this setting, otherwise it's stores at \"YOUR_PATH/logs\". Files have next format: YYY-MM-DD.txt\n" - "Password for the nickname is taken form the configuration file. '0' stands for 'no password'\n" - "'Link' is the link that returns when someone says \"bot_name something-something\". '0' stands for no link\n" - "Be smart! Don't use too long nicknames. Usually they used should 30 characters long but may vary from server to server. Don't worry if your nickname shorter, but don't let it be greater then 128 characters.\n"); + printf(DEF_HELP_MSG); return 0; } + else if( (strcmp("-g", argv[1]) == 0) || (strcmp("--genconf", argv[1]) == 0)) { + return makeTemplate(dest); + } // deamon mode here else if( (strcmp("-d", argv[1]) == 0) || (strcmp("--daemon", argv[1]) == 0)) { - pid_t pid, sid; - // fork - pid = fork(); - if (pid < 0) - // TODO implement notices to syslog to track failure - exit(EXIT_FAILURE); // report to log - // Exit parent process. pid of is not 0, then it's parent. pid = 0 then it's child. - if (pid > 0) - exit(EXIT_SUCCESS); // report to log - // set umask for using filesystem as we want - umask(0); - // create sid - sid = setsid(); - if (sid < 0) - exit(EXIT_FAILURE); // report to log - // change working directory of the process to / - if (chdir("/") < 0) - exit(EXIT_FAILURE); // it's safe to replace to 'return' statement - - freopen("/dev/null", "rb", stdout); //doing it using guidelines form man daemon - freopen("/dev/null", "rb", stdin); - freopen("/dev/null", "rb", stderr); - } - else if( (strcmp("-g", argv[1]) == 0) || (strcmp("--genconf", argv[1]) == 0)) { - printf("Attention! This action will remove your current bot.conf file\nDo you really want to generate template? (Y/N):\n"); - do{ - switch (getchar()){ - case 'y': case 'Y': - return make_template(dest); - case 'n': case 'N': - printf("No changes applied\n"); - return 0; - case '\n': // ,__o - break; // _-\_<, - default: // (*)/'(*) - while ( getchar() != '\n' ); - } - - printf("\033[A\033[2K"); // VT100 escape codes - - } while(1); - return 0; + daemonMode(); } else if( (strcmp("-s", argv[1]) == 0) || (strcmp("--silent", argv[1]) == 0)) { - // close stdin, redirect stdout & stderr - if ( (freopen ("output.txt", "a", stdout)) == NULL ){ // todo - add validation for errno? Write to syslog? - return 1; - } - setlinebuf(stdout); // line buffer - - if ( (freopen ("output.txt", "a", stderr)) == NULL ){ // todo - add validation for errno? - return 1; - } - setvbuf(stderr, NULL, _IONBF, 0); // no buffering for srderr - freopen("/dev/null", "rb", stdin); - } - else if( (strcmp("-n", argv[1]) == 0) || (strcmp("--nomessage", argv[1]) == 0)) { - freopen("/dev/null", "rb", stdout); //doing it using guidelines form man daemon - freopen("/dev/null", "rb", stdin); - freopen("/dev/null", "rb", stderr); + silentMode(); } else if ( (strcmp("-v", argv[1]) == 0) || (strcmp("--version", argv[1]) == 0)) { - printf("loperIRCLogBot: "__CUR_VER__" - build %s %s\n", __TIME__, __DATE__); + printf("loperIRCLogBot: "__CUR_VER__" - build "__TIME__" "__DATE__"\n"); return 0; } else { @@ -679,19 +724,19 @@ int main(int argc, char *argv[]) { "Use --help for information.\n"); return 0; } - } else if (argc > 2){ printf("Too many arguments.\n" "Use --help for information.\n"); return 0; } -// -================================================================================================- +// -================================================================================================- config = load_config(0, dest); if (config.status == 0) { - printf("\t--------\n" - "\tSETTINGS\n" - "\t--------\n" + printf("\t--------------------\n" + "\t%s\n" + "\t\tSETTINGS\n" + "\t--------------------\n" "server - %s\n" "channel - %s\n" "port - %d\n" @@ -703,7 +748,9 @@ int main(int argc, char *argv[]) { "logPath - %s\n" "link - %s\n" "reJoin - %s\n" + "floodTimeOut - %d\n" "\t--------\n", + printTimeStamp(), config.server, config.channel, config.port, @@ -714,9 +761,9 @@ int main(int argc, char *argv[]) { config.maxNickLength, config.logPath, config.link, - config.reJoin == 0?"No":"Yes"); - - if ( set_log_dir(config.logPath) != 0){ // set logs directory + config.reJoin == 0?"No":"Yes", + config.floodTimeOut); + if ( createDir(config.logPath, "logs") != 0){ // set logs directory printf ("Unable to create directory for log files (%s)\n" "Please make sure that you have premissions to write in this directory\n", config.logPath); @@ -735,8 +782,9 @@ int main(int argc, char *argv[]) { callbacks.event_ctcp_req = event_ctcp_req; callbacks.event_notice = event_notice; - callbacks.event_ctcp_rep = event_ctcp_rep; // & dump_event? Now no need to dump. This event is triggered upon receipt of an CTCP response. Thus if you generate the CTCP message and the remote user responded, this event handler will be called. -// callbacks.event_unknown = event_unknown; // this event will be triggered when app recieve PING request from server. And any other unknown event, and this is buggy moment, and should be fixed. + callbacks.event_ctcp_rep = event_ctcp_rep; // & dump_event? Now no need to dump. This event is triggered upon receipt of an CTCP response. + //Thus if you generate the CTCP message and the remote user responded, this event handler will be called. + //callbacks.event_unknown = event_unknown; // this event will be triggered when app recieve unknown request from server. callbacks.event_channel = dump_event; callbacks.event_nick = dump_event; @@ -749,16 +797,13 @@ int main(int argc, char *argv[]) { callbacks.event_umode = dump_event; callbacks.event_ctcp_action = dump_event; // "ACTION" handler - // Now create the session while (1) { - printTimeStamp(); - printf("Connecting...\n"); + printf("%s Connecting...\n", printTimeStamp()); session = irc_create_session( &callbacks ); if ( !session ){ - printTimeStamp(); - printf("Unable to create session\n"); + printf("%s Unable to create session\n", printTimeStamp()); // return 1; // give a try once again } else { @@ -766,16 +811,15 @@ int main(int argc, char *argv[]) { // Connect to a regular IRC server if ( irc_connect (session, config.server, config.port, 0, config.nick, config.username, config.realname ) ){ - printTimeStamp(); - printf ("Could not connect: %s\n", irc_strerror (irc_errno(session))); + + printf ("%s Could not connect: %s\n", printTimeStamp(), irc_strerror (irc_errno(session))); // return 1; //give a try once again // TODO add a counter for few reply and die / do something with this } else { is_alive(1, time(NULL), session); //initialize is_alive internal start time - printTimeStamp(); - printf("Connection established\n"); + printf("%s Connection established\n", printTimeStamp()); ///////////////////// irc_run() replacement /////////////////// while ( irc_is_connected(session) ) @@ -789,10 +833,10 @@ int main(int argc, char *argv[]) { // +1 chk if ( is_alive(0, time(NULL), session) != 0 ){ - printf("\n\t-----------------------------------\n\t"); - printTimeStamp(); - printf("PING timeout\n" - "\t-----------------------------------\n"); + printf("\n\t-----------------------------------\n\t" + "%s PING timeout\n" + "\t-----------------------------------\n", + printTimeStamp()); break; // 1 } // end +1 chk @@ -802,34 +846,31 @@ int main(int argc, char *argv[]) { if ( select (maxfd + 1, &in_set, &out_set, 0, &tv) < 0 ) { - printTimeStamp(); - printf ("Could not connect or I/O error: LIBIRC_ERR_TERMINATED\n"); + printf ("%s Could not connect or I/O error: LIBIRC_ERR_TERMINATED\n", printTimeStamp()); break; // 1 } if ( irc_process_select_descriptors (session, &in_set, &out_set) ){ - printTimeStamp(); - printf ("Could not connect or I/O error\n" ); + printf ("%s Could not connect or I/O error\n", printTimeStamp()); break; // 1 } } irc_disconnect(session); - printTimeStamp(); - printf("Disconnected after successful connection\n"); + printf("%s Connection lost\n", printTimeStamp()); //return 0; //////////////////////////////////////////////////////////////////////////// } } - printTimeStamp(); - printf ("Not connected: will retry in 5 sec\n"); + printf ("%s Not connected: will retry in 5 sec\n", printTimeStamp()); sleep (5); } // while end } return 0; // never happens } - else + else { reportSettingsIssues(config.status); - + return 1; + } return 0; }