From 4bc8d80ace6b978aba08879cb5717cc250edc935 Mon Sep 17 00:00:00 2001 From: vados-dev Date: Mon, 2 Mar 2026 23:00:03 +0300 Subject: [PATCH] Backup for MikroNUC sucessfully creatd at Mar 02 23:00:03. --- .../20260302/20260302230001-Binary.backup | Bin 0 -> 307886 bytes MikroNUC/20260302/20260302230001-Config.rsc | 2770 +++++++++++++++++ .../20260302/20260302230001-Diff-Config.rsc | 4 + 3 files changed, 2774 insertions(+) create mode 100644 MikroNUC/20260302/20260302230001-Binary.backup create mode 100644 MikroNUC/20260302/20260302230001-Config.rsc create mode 100644 MikroNUC/history/20260302/20260302230001-Diff-Config.rsc diff --git a/MikroNUC/20260302/20260302230001-Binary.backup b/MikroNUC/20260302/20260302230001-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..699b4772f48f3b059bc58881d6389ded817d19b2 GIT binary patch literal 307886 zcmeEv2{=_<`}aBn&M{;RrHsi?*k?XRDYFzQQz3LlWXu#vBBV(w8l^%>8Yn6nRT?x< zG#V;O%FuuY!gsB64ymV}r}zIo@B2RA_wQV;z1P|H+I#JL-^1_z-D~fYa%gYSkz-gO z4gd(H7)5eJ!~BASCIA3X002A?d@v*0A|u)={I)$21ppp}|3gCz01(6tH;N49DGQHe zB3us)4i3r++p_@xCcvJE0pI`%hy!~f762Ro0F43wB?bmi;$Q%vzyKbIfC1d#;NT!0 z3}^ruFra}AWcmfk^3Obgg9jCXyU7c#CNwxA+%L$-D1zk^V#Mb8ND42@Sa@Q%HU{=Y zDKLPNhyCC=P~*XXp3;bo@HAo^E{_=z5I(XkA-p;cH`0&I4RaPAJWzOWGytGq*oN|( z0tE^Hm^fm4F#zC%aG#P9`;-9yt_ruiivkb`?1{brh2oD71yFc9G(h1cB>@T#roe?L zKxv=@f^h()XKGJ`;^F`l4&KDq7=TA9VF4bchy{3{j0Jd+F<5|`i~<0Q1q4ySXOgOFE^AR15g@rY$}JzpwK7=G%AB-KqfQk z2taAb@(^Ph#hAh|CUA`@JYzZ;|HG|tF9|Q+C;em0II+bH9!^KqC;{DqW?DiWSBl zxW)o|B8>U0Fm7n%Pz3#c2e_Rb$PDu1G1*);&j*Hk81G=PgC7_S)r4&;{&qotMGFEv zU)_blP2hL<0bUK*6JgIGp9%MXm;jIA{~JbmjxRgJh#la^4GQ-T4hi=Q4hn<3R^f(AfC4vFINCg@t&*;>tZ_O^7f zwbUEN9a4gG`fOG5p^xr85e!oW@g zgZvZWN1TNh5fDHXbl{J8cw|`Ep`Oi;v^dSo5q(5iOtybS2tA zSX%>oVh{kR#Q=aXAaJ!XQu{;D2xA`?031#X03Q4TgDwo-cvJ{nEP@gs5J_ZsQhX0X;u^mDQ zpa2)py1;1I(tryzT)?{zQGy}>8fYnTJdFMj0$>7yeTFqcG>{t@92%YWZy6El+YzCD zX+&6#Uzq>DXFTX{$AkX0@o?F`!T+8+hWU0pm|q%?Xec)@IGnrt+dBq?It1hZ-xK@~ zbqM?Ih_F8x(Wpo!CpgTMzcdVu_=84?a08is0nmh?)r3X_aKnD&-G)3Jw3DGWw3DIs zkat4^m{p(vNI~&!4cZA#h{Lf%st!_G_P^oSGRD1YHhv9UP%sfNPG>$HH4F4PeS5bm}mTfQ|x>=4TK?!4@WW0OpT? z08cLzfFuAKIKQB9ZfFoUd^qL}CBZ{O2xTrA@~<1<H(mHCEtv!7Tt#ssNzW06=L9v4b7}D187>2GA>_1b3Ff&)NZ) z0sw%X6jBP)007eg0Hy$-V62D!-Ua~FOaQ1^_fw=m}{6;Kk@r z27FKL4gd~`0Kh}I_J#lPgZUMTpUdG__`@$)0AS|D2^9KAn1R7eG#CKfb8UX6hc|`k zm@3S~_%W^2IiJECnhqHQ^%Z84&4KB8?uqHQ;#Z9Aep zV?d%}pe)`<2fAx*P5f*ZjNj}GC6MG5W3S;)vh-SrfI5@}>w)+ML2RXtvq(<1ncK_huV1Tdv1Mf^HfZfP-?@ z#0dVcg%SK80;6rl0BB21FnN# z*26_A2H?du!PaKDFhBwPR6}@;M({ci6u>JGP=e8Bz#Wn>U$qW`k|Ceu`M1jy{l8YG zGJIAqh#PJoWIg|W;bQ)I!o~h)6jo-5UnrMP0|_1PqnE#A$<-?+b*uJ5` zLBSDWL-Jklx64=LpC{k{kn&3V28V}*1P?m~*54sp)QCuigR%9WCti{NjQYxjuooLd zgaiaLIYZjZ`8yR~rhm1$!F@BNkpC@Cn|BM#P2L}a2 z8~8FqIZK$KTmwGt4*1(e3<35(PsF1C84-^Qj0gz#6NuK}-;UP!b@hLqtiQ`J#Q#kh zhLjMe8H5Eg1NfX&NN{MlcR(=Pf2hh4CrpE3B01C^;J59G>ikI!D!`to3bST4xWECR zAr9va7=?#NJ0Wlu1tdfu6(wNcMPUoFw`e{o!6$2AM$czIS7`I=DH=c%rsd<{LJKZn zIs{n?4Y4q8s2?)`iTkC~6MpIR=zsb21W0;^GC7ePBYstAh^_Jx3Jb2ifIV@Dh#MlX zr2wDL;BzGN(R?x+kAVUirn4dCFCeq{G(Dfsl7m}@NiCShj6BUzJr6&fV71Mj^`H|2wgGcGa|ycp+i(^s_?8(I74l?&qm>P z$axHvAEu+>KK4Wz01gPsdgB1#Uo^ik!@oZg!b%Rj7ic{Ia2Is&K!5ngK%!AlxYGcD zps}QAv$futFE<-k=qhUJ$N4Nsz0RJ9RPxi<5=4_N8iiu&v(eU zMq3-J0rgvi$qDoe`qxKu-3dE98dwn-IT|!`c~Y9pXimiiBWns}sa3hD=O0gygrmXP`}v0k&vvnZ)rP;iS+I&We6zk8kO&+Q_UnLRPRJyyEbo6t zbF*9UngdLDy_*ju>2{x(;UFg#U8ml{5fg zD4Pxm4d(d;@SP0&JQb=iTt5Z&L`6RL4=o2yDH}6v`2#3zp_xH7#z8fPl|R0V{_17~ z1}1Pc^1`_}UrT1tGoqD+h6#yQXc~CPvI^ZjWL41<;8*^&@SQc^cWXcsRUN)-_O=$X zaLXvTkb(=y!$Z~4fbl^C%0mMRW|;Nj-yrBLV7-fD5EjTXfD#^ZwLkJxL$&n1(m)Vb z_{Z2I%`fZ?Xo&bkaKpl(WWOFV%$FHD?7l68l7(vvU{5?F0g24h{3SfL(4C`7B>*Us z5Kx+Ym&iZQDG8u~H42Gf!HIO3kO&qmUxr18g>wU8*&cojg=ID~6t9~{OGUNTzXQBnM=#*lqT0(;_Q0C20f?el|$ zCjLYMSj!(ekCyPc)P}xys11GZP#emKC_E0Vy$rRFpx{1mA_agEfIo=>Mhm_I zL$m>l(So86tOwyyqu^I~Glsgs645u^U;*a)Zs_4|DB;=u&<*{AZm`xYI2-zB-7w#F zL-PaLa5v1)x?z9N4LjTo`?GE$Kjbb#k;32NttU9D{?y z)!nQT`H*9>Kq|002v!QP7as}1(iuoP=_>{RE>6=m70%ZXU@$oIF=ZS8a8lz!ZK(ec zOrv213zGx@ZZ9mp0D!xJ24EH3$e-K`Pio+1B@N?|1OP|_3Q0gcLK095_h8T{G+Gwq zqW!bq1T0gp#V+^a?%%uu5f{bjC(pQTg2iAELxKc?7sa?>Mdi^hP6R1L0)7#f$HJ>3 z$RMNOSByOWH0o|vh^mqlk%BM~62kwuD@l>zS0a%_VNe+E|MKx75gAc2{%FuBQISdU zSfGhv0qj({!GdRpD;6y-^zFlq*IM#+cYTcHU0cS67j|u|yPuI#`DGo-mPv%3_Sp}v z&A(sxK|{SS?h@%>1uZhTbIgSLv+5>v_GFQs*_PC%Abt}1ax%a(#aYrowaB4IA_U!ZND$*2V zMFXU3Op1YNPD!fQ$x~=#j8{wcvZN>H>OWngWbd;-?$w^qS<#cQ{UW->9z0_Q2=PDGsy^%%3>0^JSv;UCL$a%LZ)#kTq=c0WsvB|Vu0C>}6=zpO* zML~C}Iy3^o0O0v8%naF~;f5jHKyPH&%O1xd37Dfu0(z^!%gW%UJatVow=UWnvFN(n z#;Y?CDN($B@{Ht!77r9&{U&O2-fZNg(?^TTeqi3NruCW)t3*vfJpT4=m6hk8 z+?ul3y6Haes>tz39mNeXS*jVaohN7H;2z&Ux>S-O%8i@psdh%`Q^C1T-3Q@uOQW{C zCHV#|&?3${Kl?(fdth_O`6V*vzo0%OJvv}1GoP3rp?vR7_Bop-okiU{NS|zR3)j|q z7aJ#@-+OSTUF@_f2k(GLuRXJ98?)*)TLNz@j7?p1W8l_t1&-2H54|kn`S+c@H4^5v z1t-mjk0op0e2Tw!dj0(AB`U49y4fL*3D|~@#}wb&iO&{0&@t1*t0XQb?b1;lG<-xO zhmA15i#^GI7JD#_b11HN>`wFE<}|6OT-tif%$k&V!Jzcs)q(DEwfQ$r1!gV{f4NPsK(?eg zWY6APb}8F8uiF^XR3JU>+~)j2_Pys~3u|)D@AAOEyO-MR)Sb%iot{@$%zMJ(-M@1k;{ff=+xyWA6&nw=j=B|e$Wn=J zWc&D;)inK5s#BHm9MO-4t(WK71~4_0?_m!|O`UAK!auL==xBvk4_B9$(gT_{2CNz6 zlrGVphg?vZkn^nm)f1a#CB+kPB1pTzS&8#j=jW8>ceQOp$sN9ya%CIYd%gJ7E3fWl zWCS+C*a;oPaO^C1f^)n1vGcb<3*7T}KIOMT|2F7fscrOfW{xfJcLr;KmsA8+9C0` zLMj{LFF>kAtc4I#4N4QjMnWnKgj5!z_>c<61mMCSQ59~FAXOa!tc-?Gi@?Fy5S{Iu z9G%RZW|$EvR3bt|EX)W7gdZTSn^+_Pdksmz6bg}+WY1aANv`PbrKjdh*1GwYH!{*m z{0ESh4UwM&6A+Rx2NobLghXTvCBbgL1olV>L4fG=hh#J4eQk*9&UQ}fj!tIk0s*N* z38`C{5&qI4-~1@Ua@c>G9o&)T=von|6SGv#bJ2d#lQ+$n^#j``ljHSC~e0ktcD`(d?THmj;8i>{EPivhk zraCvryTjJnIc{=FMYnwB*3nZjt$P{uev-uUql)wF(rwI_WnasTZK<_)K5D-GKsol} zlFa)vp5K;zs=s3UTZ@pY>5=|->}(4rcwLlA=(j#l5U}|s%h5by)2AK1US7uvnJ?7T zO5^a`T1|Ra#@YDo6(FnxR05KKT8_vKXY@Ek6onc@qrixyK0Il~1>V&sw8pBldbER> z@#i{jDSZR1W@|dDD`&Jc2enA|_LjR2j5MkGY>3zKJ{lKTVDC`3$D z#3x=7g+g$mqOgJf+CmR+!+d9$dV|H2250u{(SKN&arnC7%qb7@J_M)eeL<#ANIZS%WXxu<$wycD zN0K^#i{ml3tmmcGT~A(04>WwbTq+Y9kH>mfZOt+yMx<8ln16R3VL1&Ie~cHXH@1j} z54;nU)?M0bgi@$j;L1Tgid}Vp?zDTYr*+_hD>{kswaeG7%h~Dp@=8iOZJB=GTNihF zsLVqkUu73ocaTOopcn6#8F{8rIVP>Pvg(ZwrXTCBp;$Eddis<4gr2r;w@q476ZA8* z?JDptH*n`pXQY#W52(4h`P&_ygh^A72o-=2<0`R(a`dpe`v zp6>qxPxlp@v*`$t!ej8*R0@y7V>2i$5}Qe9vuSiHjm2P6=rk6ENTV@mBnE}XAkfHE z5|2$MkT?j7N~ACud~E)sSk1@gKZ?-;Y|iFUSR8~(WKpOHkw>O6S#%0QWD`kjHV>gv zAvXUPkk`+UdAgA76cv)4c;IAW7V5V&IEX0;>`a{4!QtUy9A*Gl3OJb91Y0sWoM^~* zVu5WC+i((OJ#B*3`J07wCpR?QkLSl`hI7@;BEo%xL;b>|)eU|PvvV?M@(W8!t#KnU zI}T#@0No$fmLLuK1HeAnCfI;KDgy{A3`UH~V0cspHpK6E(d&>Gtw0jchXrUI1-?T8 zNc_rg!LhK!gp(H&N{t|o$UBJZXk;>PX4q(%#ST7?=bpf8{we^01)OE7T zCu@$4TUbo*MX$SE(_k&uC_b&tbJ?|JeT9>payPO3=4y*D$6Cg(o1Aa4MeE5SXzw%T)k(GsrGj6|2SJPk$`k_??pSq3ZTJ&**!fx4QXYnD3TP5hX+z>{U;7;I1nExIgpE!&gSt zb?%*2;p@VR>E@3`Vm_fGPWA6AdT`{!gGTuqPBP2aSl`*&d(v={Y(ZL~&Wg{iyWL;W zb{9N<5^y|8X_v{P2@cU4DfhjxZ7Wt5>_8io$aFtUyNV4n?FiN0lfSz?tH4)o`@Aa~ zrBSJsKR=XTY2;+Wr&IY*^|zV-ozCdDng2HP z|C*V9#c5;;fsC+7L^6%bVzAkCHibpzAsiZuLP8h>9t{#)2%W*Daw$wIiA$uB85|CY z$!0PL3_6#?F8#d0}LXgB9uJBXHOpJAx*nF7Rn%ekv(~4x$bBk&svYb9oIN z3?o10r&8lXFggJt5(z|vMxwbZNf8+kf(gI=*T?r)Ub(q1HYc>~;@j&At9txVv!4Z- zij@WGc*cG7FgWghb*^_oE^$9|)rlbK!$~P^Y$t;JQs1Iub|uxO(o2vFT0Dq zJ4?4!-Fu2y_D%b+x~?M*S6%P9=WSWt+g0FOtCj4gQ-#+#b0{cu)^J_pJWq zQWtEAOwM|pMu`M=b!Vd_E!xaO^H|{yvjzJ@p4L_`xuI19o(8xYJ@b>2dUWu-M*N&d zqWcaEX3(k+4m2I_*=}H!xaNg9{y{j}=;P{#+h3j0skK>OCS^TtNtHtGxYAt0~)GhqNqm_VziL)_($$1D;=|Z%{-wL4?zX}R1 zUciZcgUkN9h`nMAZx){ryE`Z##AF07pb>}2>xIrwk=M{<>k$>~Ny9@jaC9;oL5TSU z2Ysc)z5`-SB1nQrBa(o*BCKAc`U8nD2f*buqu@VfC$?*RedF|mV`7_}{fJQ(N;z*8+jt~g+ zVUFydGt>n1ALkvS;k-k%I64810xRUWO4L!8>Tt)a56zQ`?6{>B>&BdCa(S#&}Gz_x`i7yK>m(CnDeHPnopwQ&Vtt zyP|p;ep*v&_;uytjkPRJU0janyAvHcOdH76JBC_brfQW>X7KC*m@FArt;5;fb}X(wsn$Mkbfw6rjb zF5)GpH+2UG!e{$k^ZhTzT`9PgAS>uA3eSHFn24JO&$IgdNhF zVgSxlT*C3T4{hg0nw{8rn>trx4hxpt!U%sKJL8qY21ReeOonr-JwhE+K3zVWGQyJ(!sV~f$dv(PT{ zwkW)FoT{@bUAIHc7)8sD{Ngm{LgLOV{- zkz3%}>A1dYcdU*okLIMwNr&kgRy0kR{bhdp+it4?&EsuGsdpb)F-6L^1|NtF-LQ5Y z_2_vik=u*cx9ksA3)sJyRq?QTWvJvkAKBHCneuj_j-mEY2RSlRmDB**x)daE_0*hG$E|cnL#a zl_?2F+gJJ|)oz;`UR1h$#p=Phs4)woXD&3{WO~Gora$@mRo1mpo*$_ml~1*`QN;~o z#WI(G>DBf3+D&SEPfx#@bU!#Q-{46p`eV=59VL{QswG|Nr*?{}uoLHJ#(q7$i1>g%EihI+IBtaft*ri9jUMnQS%-p%VxUDw)Khkr`|{ zgU+CmS#YughfHOYIAk`9L*%D(Kf)!$>6|)3;BlxN62fCMNo*#Cz@!scEH;&la7h$| zMC8C(4Znu(VMh1kOaT(?BQp!gu#ZSTgd{st^zWULO#16=?t*>qT$s(7Qu<&vCwOjF zf}hH13R1c69`XA5bF<@z=G+PJb6#-b0{lV|e*I4j;U|ymHsn1zz2=lepG2I- z-M8n?g>{iU$DSd-ZoIPdOm)VGw>PUL%9tK=t(RvR?CwluODeUCh4fS<8k(-mY@Kcv zIOT9nu7VpiY8S?$Q${`@wDCwv-d_I_i`zc+T7#HzIZe}krOux`0^c96o00o@Z^gqS zRI{71Y(JLXnORpx-YtwTK)7fEIDF=Pz;wBpcMKSp#PM6hx>Km@QglwYq^zHll*j&@ zMQr44mVS4$2*05rprF@3ZVwt^@H{SZ)}P9nQ-9!|ZFa}i`a8C9N~lxUk~hp=mon+V zj{G$hcfi?C&P_XBcq}`vqXYpWRM{ai7pn0PK>V#>p~KVO`A>V=kbW!Jzp7wgBM^ze z$B_(hKKbpO|yFj>$?p|0$LcB zelX2$!?!%*FHW=5MzjPR;<({~eIroej5{KN2&hE8ue<$)SpRy;-9K)`e^n$p+fk1B z@?palbWyO!?ir7EMK@)i#4ufzFWH=UP-#LjTy61juiwtbHDmkb)iaB2mk{+_`%Bx` zHE8yR*6T30c7AYAY!4b!x_WYbqQ|}PK7a3u)%#=|S6jPupNbgQ68GHs$gEE;q4UsV zJ}E7BYg5$~3$NHU<6J;-cWz-9hZeo*Lc6tB+_OL@JJ!)#Y7*?z#=H8yM1yV2@T!Rk zrtGd`p^L^yZLh2y6>*c+w{~^8+dEdA_i=A7@+t46eWbf;q!;-@>lWATYmUE-%e{5B zo=8}>vFfR}>?i+&whQiTPrsAh%=W-XmbkK>%?cmCrFLR14(nFEZPcii#xIxJ)zaR5 zW!3&bll^@9-7-m{THYfh?sBYe4(q_)+XZ4CIwM&%3H~$VC?M! zmw}mRXt8T1;lrpB$JvOC zSijBxxB36q%>OH-BeJ;!HVa|#7#t#x!6hI>27|<7aft*9fkI@HSVRs7VKZ4AE`d#@ zb15VOgGDDX2oy4h#iH>jd`R~ruR9FsgwyhVJ(ff2;7)ApsE1CQ5&QE?!vb}!uMtc!iSOhFQMhXH|re_bVfI?HB?Tof#in3y?Jn407g4%9wyTzF{@m%I&kN23n^>LbO zrW6O%=)8Y;%(%NnZAM(n;^5OBX0;2IbK_rHGEcM&Po|we zXCJ(w^w=ENYI34)TYfP#kCmXhV=6m6^3e-rEj&4~rqW@q`aYLrqn^&Ol5ab!u3+?< z+yeGj5^*#0+nNVF4W2IXp6Q{qrgYDWo?Vm8mSiiOBrV&LP4KzvF>M)pGPl@tysTKU z&a->ZMokfytX<8JuDCPz)2kZ2G23kS*T0j!JE5&^&6!70CWllWbPg;Zm}MMyT){}% z_SJin}S;%o^?U5=->t6gzHjl^$?j zY3`Z1c&efP(J0dnp4U=Kz3!Q1>n|BLgx_$$b(O}Cx$hMh*89wIkU&6y%+_f6< zhLi*KyC1wf^|~_U&@El70yE{jrw&IvPQJIdI?=4NliRAa zV3KRPp{w%2X#W~dth@d6r|U~{(R1|9g;{oC3~HA5xo@uRdS&+deQxlJRlAbB?}(0$ zziu&CWR5Iv>kYBAX6drTXx42enVgG8%PZafy$kT~fd+Pc}m}L&T7>boITm znc`-5vKiGSQCk%wt)*sJZj3bZ=_;X(qppl2+24D6(@e{q@Gvy8FExkdpj~~JbK3s! zRyz?->((a*?Q%8B{Z+}DA>oS-DPGJucy*gta&BGWqkO5n-iQx3UrY6CRF;e}3<)kj z5rc}kx^~yT%OR6Ox5aGH47p;>0yE~1>XDk0Gw4X%`^Cbxw9W%h=k^d6Jm2>?>O`>N zq6ZSoUYb-5z_c?_S1g9($I1FLYWj2<;P9}#)%lG1l+ zJje8=<8#j%YS{UpyYq;OoK?)%r_MgX`(@SJ($6lsYkTt;e&5c!ul$$qJ=IWU=W1Y< z&>il$VIlL_^tI`AyWDrFp4_^x`B7K%g4#Rn3;Sf$FEq)G$~ZZD`nleRTH^ytKhN8p zn~#q^NtSx{EYtqu zy~m~FBchh*<;6ze4u|b3n()aeFgQy_M0Z(W&w@#F826Hl`fZC^at^wy794wDLLtqn z*RaT4Jh$*D>(KVN_Q&a`pZS2q^v4nz3+q0XAS*Pi4?CYSH=^|#RFBp!=Q$M=rWaF< z_J|!VY%|P9K7AB5Q+lURsHGZH<7mz8_gawgY{N8(w7OcWX_w zx$ww@owvu`*2;EP$ul0}onm)=b7uF`kYrO$>Ir1HS7FyqU@vY z9+(iK-MUtbpEDg97$#bUzh}mOWa+o1{I(R-FuU---BLFEM!LU|?r)^~8|nT(fpqyV zy(N+m9-U04a(Qermw+%ibQ+z(VNnTGDw)DTAm72J6Szbw7oiY|WD=W+u&7iLlgTA< zDO{4EwDlt-HOzy^Al5{48kI&N5X^}*3o|mml=Ty?;PLka2K=d-#61g~HG{z9%g5u(CD8=NfxOcOBI^RX+>gOT$-Zt}PiOafev$K41oL;S^#cEkfgk9MkL*gmT=sYp6efHt8oQeZs z>#UU|4{yH2jB~sFR$oslWK9-k=LWjFzl{?qbwasK-~3s!I87DfBI4?E<+1nb7TB0> zdHbFhX+1V(1L~Oa3J0w-bNZRdURNe2n>tjrog_>P9dv8?ywdgk#4dev@vYIZO1bYo zAChB6jUtJyU>#33OH+)h+wS#7=VjAXvbMHpxg#HWUkI);`C8_@0S@} zSV!7F$X!wcT35S=UEEx-s5I|t)B4m&<+uyzsp?WUJTG_N$dhRdC%#8aBpC|Qg`NvT zAFao4S^Ta$|P0JX9;QnIe6FQn;>GG;ZJO*K*UxM(kqWR*l@) zD)&(TI@(*yL(wS6Q`TY2i%B;u6)0l4NANqwT$=o$_pAq946ErdzTeK9=kA z=3F~mgWH$aDylV+iARf{G`z8*t>{8b>1>hM$fr*7Pwob+_;Bw|SW;br#EY#Ails-j zn4>|YqS^BFiJGSqX4&2Fx{|d8RhA#MZ~rz0-sEVxj)MqCUGH8l>A{_*y>B0F-KVQO zV`8y|&NY4Qm+f<<@)8&ApY7GLNACTH>Y#ShW(JrOp80G+o7aPLhbG?fetd3Q^}G$I zS!cNS4zyzJ^9ExTNXS<4F>Spl^GPMN^bY4MW4EpI=oxplhd6YA+jpI=5vxeiiA|{OL6Y{;S%e zH|QpvsqeUwb~98fPNVB$!^&B{r@f}|xW>6h%}b-}x1_3^*s145^L$|{Vf7xf?&7WO zOD~LHe#Yln!mW)ptg&=W?5* zmOroc>FnSBS?2l{)%o>B_6=T?oo*}kvM-u#-gn&Zl(XxXgIR0V@Pd6C`eM{1$3(KX z&nXtmS3FU9aIRcx)X`wVvI31O3&*Xtez$w9&M^=9_NpuqweZXP8WejCCrmpc875=t zQY}4}pcxzQ<=pX+U845L$vJbH^$E!{h$dOA#eKcJ-tN$y;|c>Cv|X!xQc}0xXQ#4w z^$F^3#>scR(mFn2&#N7dj@Z#0zcF>;#TSHvH`9ALM~^yia|W0j#RIMxO>?G*rRYxD zbZLq0=VzCWOr@B3LcU@Q!#&;-Eu`o!qlFe%R}irCct( zwd%QLy03du^|G{q%6XwH9Zh|AojbA7EBnsN^CrveJxkj)KLXqVP`%{}N4IO^nEyF)3@8?#3px~*Q{ zHu!S(^LKH{lWqkZTyx;@$4LfOCl{S+atm9UETxcu^1hO}_I5=X<`EGp zi@;!$SwtS0PUTVQ2#pG#>qjUA773x!Xlyo(L*sF|6b6ONqce$gGMT}qaY_6M9Y2Cy zkjVHU+=B1Jlp)X%B0@E{W)Q8+ElFfPx$#3-yj1MFsTuzYvmyPjGaE7%W^)V(bZbi* znQBF$6Uf8AvNIZH3$jQ8>a#FgSngeAeZ!6E_#J-yTe1a}puEI{yPom31*1X=%ZnMHO4glsM=sq+ODz9nwaRSvL;t2dvc(}z#j)4# zl!jOzzaUq)KD~R{ww>iGj?C~6opjl9Ldf9{-jlU5I-_S~sv12kF@I+@)qAP94%6mM z%&%k$73I;nb004<$hwwsf5-d>i&atiL(@+?7xStkeMmALwDtp%?r|&Dx`}z)D-nv6zZ0kTR2OqXL%G+_u?*Z zOMEbyg5RCNt)GG3@!|)S_fozw&*iCWgH(YzYB7jZ8 z9?7mohc3M@(j6!(*(z(_AGlxj(u+Qh=NOmkMAngp{bn1V$#I-w7hc(IdM~KLni^2? z#%ASqjT6UgKRBiv#8j*1_8XWd4b+WSuW-nyBA!h*oN-28w8~}h_=bC$mvdju54oFf ztjtQBJ9nTu&NZWES894gM@P8)jov3|N*?KHW9yuXoPH(p8naHvKiIrIeD5*q%HTSm zlOLT6d;dp~H|N>npzGJ$j;WtyyuPbS3o^cWuB&Uy2hs7b>W;j6pBSHFoqjxj*#Y&7 zOWUlfI#f;e`gMA&T)BF7?xVR515aAKpI=C*-kD+5+~V47oabtDJ(bNfH9qF4;(a@i=&P~m zhVsR(EOSQJsfTwQGDG6dK2tbTL0f$DCiYVo(PiV6{Jw&1IS1~}xEq}qw%WSREk*ic z>=k@ToI z{BXsq7z+SSTvb&(4*o2x@Q1vIl3&tZ~rW)Vb zknext-6Qf*`;wPu_sLz>r`W%`EPW_*a9Y3zCEtQsb#hXgR^HW9iZ6RS>#jYLSd=^3 zc*Z;T1zoQD3f_*7byy@78}HV2X|YPF>5ganj()Dxj!D67zVh}HrlX?sm5V-P_(*<^Ilb~?Qe)_#`3w)) zLo31t%i8uX>kVq19*Tsy%(J15b`H!x*6`r9)JlsT4JyeSb9=Yjj+@l6)v4Jkn@My|%f+O`U)YiZ?&Q8mdvRC_bx5|NKj%hGvMpOX;%00b`VQ^Va^BQ@ zw)6~}k}g(Cta(N^8!`S><3eQf?|ObJz98|Jclb8GWsdgjw+k=m}dPL-KvIv0st*ixX+$y>Fe zw#F|c+{?WHK+0EpBJWv}RPd}-Z z5l(-cWTTItebJ>cU8AXZ&&#N?(QbZ-tP_w4OIm6^4p@#ZoY_1(z}6^Qt|i3d@Stbn z&BQ*&UB_mT$_MJ#J{oM_8?h&VS%337Z^2Sd#+rA|mut2n;&(?aJhDKd8>~CM#O2_H zioF4CMu9sSk78clY|2k7Th+(2l!#Henq_*w%rPqd1WFPW%T#1w9tED@0q?+{$8s}5m(h@d$mNYJ{vwYHYMYZ1L7(GibTeSK<=P^Bgb>Wg!)k#k7&Ki$&F288e zJD0H0+U)(_hPSWAi+4)vj*HmR|E1CD+F*g5_XlTQS9zyt#sFCRt}W3nkY@9_Jhr`Q z%7f4AKiTFuE45F4kuv7A^M_YdRl5%pmR{Uw=i2_M6)EEt$Ypz$`nF(N+B2RaDRK9& zCK7tj8BsspaOiA08mA&%zr^T+^se#~ilmJ@SErZJqFX13Tvj}pyEn$mbeXd#H~(_- zg+w*m3wbdi%QpJlK2>`3P5$CUs}E}XR^8jF=y0_aFYB>*?{TO3I@d>uskJEPNP!)D z*D%C4bRc%=8D}oOZQk2{^7i4RHJg@hc-*3Y<3{uHGL8lIb!nf*3a4(o)3k{4;z^sc zbOyyY9I`1Zw(oj0J$vn)_om3UO_GmW6zg#vwCs~tpF6%=xL^0IZ!|MRtl~hW_iM#X zkIx~=dM3PA6RNV(=i{5Z6;8dK!)bXDzf{E0CU?dTr8300U-IO8l}Y)7Gc)Kh`4W}O z@w1w`J}mL_(cU2@*SJM=tI6$gExTuXuE=|l(RV}c;3QEC{MfSXwF1j`XmxX-pD$RRSY)-NWBHwz34=Z12afkQh;NTO|>hu)fr zksRq_|1!TghKp)$)p+V$e!0Zttusr?Is3EKm#4RUby?$=&ScPym8ikWVOnv@rJ3UE z_FA7hHo9e^Vfx)&_=d^5jDk{fC+r$?;mB(_CyywT!02qdEXsA|$+4S{Rxg-_Y|^XB z;BjRMPx723xn|ij_LUp@oT}(kFWIK*!46!%+iPc8opE;44D9KHN7Cr;J%H2aiI0)SOpwcP0{5lU7c3CXKmQM zmP?FC!VO(Gw z%kT2bQw{qvo^fyfbt=MtzFZdmh~p|O49wrD6Mz0d$P3&tarNFyu7~xfuU+%>mRxY~ z%gwuW)Lv9BuxO4_GRriQ>F+t!+>mfz`gn3l;L9tj_Pwf!HAz<+8>k%Bj+1?+&eVaK z)`=RE%aE5^*+&Ld&biRKofpV~D{1xmQ$7C=d+!1!Np_V7-t5OrSI@L&G&6c5>2`EV zT{Tl#l~vW%kE+R*s-M%EuI{F*dq$$GH4~K?RTZkth*U&mRhMRZ7-4LLcu5BFF!)1& z1p=crdVnp!yR5;>!`?L@Y|JjO7!208hDD1pHji&+zyF;3ipa>Sn$`feQGWepXGPq{ zx#ym9?z!ijd+u+1+aF%|m(TsmeeZwjh2Q<%?|j$uQ%_x3{^k#V*AIR4lefSBtxH$a z&%F1|pZJlf^&kDt=G!jre*FJ=%hOYDI{%&T{tvb9`Ov3+`hh?B^w;kCjr&i3bo!}3 z{m93se&&tu{b>7VUiZlHZ~U&KfAnqN`i}4a|Nh|Hex>!f{U80xWaSm#@;l3K`L!Rq z{qa9;JpQwv{EIUm`;Xsn?KS`GHUIv_H+=1Luekdw=AV97>zj_<`pmDbUqAc3)8G9M zfAe#H|8qaJ`TTt!XcVo2P)l@{nJ@9>m-te1=$H8Nua+-4K;cVD{FjvYFDda~QsVy` zSK=u^;rQg#vF3^C>0|X)bID&i(mLw5{E47-E#nACXO_xr>AigWAdnf%s(>G zI<|adq8>~%>&KQRPw+)hWs2U`hMMW)lhen~9iNy!ac=I!>C<#Ur>m+XdDyNC*N|Jn zs`!+Q^3ug2F+VAU7`po&Aw;*^9q%Uba@Y=D3k^sJ@qehJpf9}m;)}nge*eI3JfEL@ zmB9UW57M_M#7BiVAVg(Z2(coBSQA1-LWoQV(Gx;!2q89w5bqO0JTHX!8bKAs*9sv% zD1`VrA;i}UA-+Kf@r^==ZxTX$NC@#^A;jMmLNtUBb3%wy0{y&DnN;SaY4!gx_5Td= zTRw`flS1qR+;3C=zg>uZ&wqJERKyEI0>?%wyHIR5zV61?etf+~wewo_|LfHMZ-7nf z%hVrl!XIx|e;g8G==rJ;L;K&Np1c(e4dZJBUk~GJ3|~Xyg@dAki?>?AvfpcGM}#;i zrtozizFvW^M+9zL;LoV@`;~ZkKfYd#uMi^7DUZtvx}Q8{@a*X&`}z7y0vE9>GYy73xo7tMJ;rHx)AjL(_((| z4MKdpBHke8Ctm|neRT<)fbZ@S0tsfse(?fmc1S#guUFygUeMP)_}VMP!MnP>rFPgP zl7C1D(OPYG$I~EL50ddDCL|pNEdPmFls<10LcC4PPokqeLR2c^g?)Hm5n|}_E+Gyc zs1BdLc;W1&YfsJ3ogSgK?-wr|+}~`6L6kk!@tdzMbj3YAl?E9G3=wunAz+sf;;{O? zTL|%1^?Q%N5csp#DSwyq8yL{->=OdqO`qWkp3hHKg!lj?4d0qlF@WB6Wn#KM9Ubl~ zvda|NkJNzK#c(;8cxzv=-KN-(Pu7|sJofZ`JDt#s~5+w!<{Tq=(&Z9JfKM0PJA}4E}#u%un7U#0PeX{cn2Hx9)$_n|_YK zx)b!rgcj5id&LXnn4yZV zq$y;Pisr!Y0KB=pQdfY#-2wc(`VIbhPW{I0e3knBH5DP=F6Jk9JuQaruG}w%D!cC& zL*f6=#^Ly?W2luY~tvEfe>hH7l-!Pz&UAac4sgb*> zk?ED^#QfyGr^N?$i!c0fRos92Eu#M6w}?H@i^|^TMFnl|%7e8FVC_bW-OAHqpS&al z4P!UP@@l|+*VAI(kL(c)&VKa=hOo?Wm`p*wtlOj#zsvk9%SK4YaXPn8bIg?3O77Ia> zIjf#S80z033;i3yQ2&N7)NKwq&mY)@=R5-ynt{D)tot!cp;1Ys;G%NRfTFvG!NpTdaD-=@le0xawVfRgc(S zL0N;V-rZOAxSbrZhOXK_Ir~r*L=S9Xa*o+f!BB&14!Je=PM)t#Okmfs(QdZ7ezw|N zUeU5&uf&l3dX>FEEA;%NVOR(!@w^z?4M6U>mDbMqnSaI4R}j z29RsIS12F&pjYfR@Of4#Btufsi&Q*U*(D*&q>@>8-AZcne!B@WXoiq7=ufV=8$i~BNR$C6+S&-;;;R!4P z3V%zY{`yP6+XB z6(PR8BE)x8g!p?EA-=OB#CKJMc!Ln)UkD+-yCTF#D?)rvMTqaM2=RRtA^t%{h>ul- z`2LCzKTshJTl`>!wdWtI2=T)eAwE$N;(w|L@sBD({76NJPgaEZR7HqSSA_UXMTmb` z5#q-xLj2>35dWki#Aho){CGu(pQs4&lNBL;`EDUTcefD#OGSvEstEDFR)qM)yM_4a ziV#0j5#pa$g!rYqh4|Tu5WjM_5ICb?Y9dtG)bH~C&bXJ zP6@GZv?9c5A%=F7vT_FX&w}pGquyiqx`3~D;OlWA_I+lr5ci4~hVH&dn`}EyU1^A%6XQMGT2wsEDB#--|yJd~M+C7NFR~ulL~# z$tA$~LjnOUh*?2E3$kGiL9rPUUyZN7jjz9huMY?@^p%!x?h#_>E>Zyx;O#5X_yfQg zSp*&tVyHE$+Pw%gU&7aAd>t0z;NCFm_A-(jH7K@k!WV7d=kd$K7s5@k01F|m>=6fH zOEEdSp4>e@$vnjT#Jt6P_9d?R>*Xq%>6ekKc9nD0?!Vz&MZ$|%i@3_=4q_LFeTbci zv53Wp*@*3k0l|-V#l5WC%c8&8i&f=s(qgr{l&xqX_#4hyCF|AQ%W<;dCoM3{gQw$8 zCx|i`FUxE-kV&r{+|eS|XN7EVt%#9(=O^Ft;tNAU;)^&RN;9-vztu`oZLxWj zmt5K)=-<$7_3zKnZ#KN_;ZWEYp;PaMV_`R`K@}AtyNmxvbqBQ?-gR-7uG89A}I?HpnT;izq!`y%CqZ1 zvMHYog0)&j96UUpZl+n#8Bd!@*v;fKGU-K)n>01+((@vJeOFVMXO z3`*Vv)I$Tt!{uO97lN$Um3;Y`JR7ZtNgNT)FUN^wC{jRnsuVH~u~T=aosOgBaAlT2 z&b>I-i<%1P2i1#(AmcvIM(f|z4>)Pt2KGnFVfPq!XZ%fhdNpXS$#Zcc8AWn|@JEo# znU!|D}x4EHD4S)^PEdS{1Xqw61H~K}vIH_S| zxB;dCVOCblo&xFzOJ01UA7Y0LYUN<=m<(ph$zZ;W1oT5^`tO^Y&rN*^u=%MUD~ET7 zQ-6nOeKnvY0?JJU?1eroEZXV-|1CcFe~x_x6$nsR9}Ylby#ks44(x*{fC=IicZ1T# zvrcz89dG*GwBtv$uHRhqSArC_qopKltpwdT$x;YmSOz|(`hZd7qv|(y=-;P)!#eOi z>NhMBko5Tc-Cd|VKMDKBeL~QR1MADHgs8kmh{|h)fcLP1cCkxFo3K8>JP!*5vKXRm zc#g1>hP46XBH>SaLiopqcu$D!;Qj}(F(mI9#NO+$AC}};_D~L9W%wJ0uvQE`4=?pw zNm_sOWdic00QY(T_lB*2+xJQ#*oXCfe+}@xLHjVa1aX%J@q1n-5cjd0k{9V6%&`O- zU%wTML!VJA^86&qz7FQ}W{_m#&BQpMU{Asa|9`A9KY6!!0Up_*2lffE@At`cC-!~a zZ+$YnM~HpD6n$%Wud+6P%*bW7dyfzYCswnpJ2Q@!r^Z_0N{D{OnsH}bU-8Kc4(=yA zKRMP++II<27nN`RceEuu1e=d99n-Blq{r@!iiqHPmy~}^`?C%f1eev|OUkHEV z2mjs2zvs~T#rUg7zVlyQ_<^_l&u_f>=11P}nP1+2>IZIoE{Os`1_cnjy8~^tI_MeZv{^CFQ?mY*PE##7SO}_RczxO-Q@7?!j zfA-l2{@||HeA9`&c(JADie(TJ)efaBV59mougAD4calu1o z;Di6)%<_ zIEZFE3b-K=PRGGsCB(sd+ku}3HCB*@5CIeQnr9w6eTC>9D@D-pL!xnfwEqzQ!*zyp zVvp|<1{#*5yU@^s%^>R5R@)n$T6Z;BsjbEVbwKY1f;1(^@X>3^gLabu=84n4v8d_aaEI#O z7^nUX1D^g351Rh{b-VDJ{K~Y@V1dEx$RT$U_6xCZ`Pp`Omk_V5lKI(wVEup9>5G@I zpE-AN?&{gvg)6nWRtu05vbSw~m)rPT@6tYA{(P~GV?8vG5AXi37Hq*jr7s5ZJ#ORG zy+8W0HoiCC`1`-u#^2~p=v{8(58w6eKjpUm#p3*KxAD>Y{z&hb>9bAa_hIK9q;VT@ zJ5AcLXmt+Zdidb~ujja-4?rP89MJL%Pl01y{igw%uYM z;+3#i!FzE)ITav@S_m|H2ujmKP?}l~39;`350Y+1fl8z(QCAcmmjgM?{48t&WN3TX z+2Vu$A7YmoMUQFy0gR|NabGQj_-eRM_H&hQs0eW{7#J?O-9r4i3etPuZXrI1bs8?9 z-9r5SgZ%pgdxSWl`uo~FLVV%#{QQG^gt)Gj@UPp$*u&@R_XzPG_#P1ixkrdD&;_UG zsfzgL`{62k@uL-Sj{56!gWrr%Z@Dg@BT8*=77@lu4JH)jv*R|SGw-G!uS|2`MC0~F6c zfg{#FITI#$AU#&)J-kty%qRUYI~ONt#d&&R`Pym_oo%Ohcwqm`a-0Nyb5%hn!>BQQ zLl(AH%VE@#8>>MQNWlD@r?;rIo5g1PVNc#1k*&D#j2R7YTb}USve@4EN|5QDB#qzH z32t>2eumXf^9jFQJL#cUZ-mMox={d*8UyOsPJyC?(^k;-H|1o?!%Txr;a3(L=q6#5 zIm2t9HGqL;3Y`rsJ9}XNp&K*ZUe?!q0lqZuCC%U_fk?#(_M};anIP5_AT>ysNDKup zXx@jbngYgTRTm$jF@x?_#i&;LS&SAH2(m%_EF{gv=&5Z#L~7_EjFw|G zzi9fG4SCr7ad<#M0>8mP<2Q=sL4GEWd?Fi0U!yRGOi`8y6q09eGa{5!`@2- z%)n*9@(yy?x#MFz3}z%$gB>Dxk~5uh!6Ak^YBixiltpkni=4FI#;_ic23 zNaBMa_r@@RN>e;0y|E;1F4pTF=yIkNODiOniQW54Q_(|;ho`{9hsM#c^jj^Sq$*WK zgTzHMS)68xG~7hIOEthQTv#^aC<~%2Z75FFtmp6^^;LC5r>Z-9VE;ByDoJx&#!)Ru zk~mSaa7EHz;E=OduU@_?nNP~d|Mr3XhjM)n?6Nq=Oi;zyqZuXq^i$5P1aln9vlv8V zoIp4$t1nHanalnPBTh_xBH5#drOl=Ngb11Qz&#B;6#Eink<_u;WF`JxC637ScXFQAJ_V{v; zHCJV?+m8KKV>3u)FKIW1tL${RPLHoAZ3voi&s_#d^l&$rY6H6Lr9slj*H42)cKtNn zh?7?S)fGQYWtuc=2&F3uw)`NZq{W%N51ngDmt`^(+!4HuZ`^@J)L|QDAZn!nRrCf#G3l(+(I_$^y*p)Bo zMNlT52oiZ?hSmnd3fRd&v!S7`2T2;n(M{18MF&R4S*GTF1s3Ak|_}onY+Rmwu8Nz-1MMZ%Vy%R3~X2Fs08%EvKoe zd{dWt9ex@0IS7-ZPp(Ncg~t6PyLnp%?KHq@rRbMN z&eK~ZV9+YjDU)cSJt|Un3f(@ieihGw_O={ zqndA*3V>wt^z{iCQzEoj6y-l+4&+pf=@XNF;tWVU`%61_NGv!ZnW#bS0&Id_0e#@Wy zEs~8eLO?cF%4OrLN*jc%+_?XcT0|wf3eB$n02>0-&fNH$uLhlXJ&;+_3uX%ovU~>q z_S}kmHc}Oo?xxh^38=?2hg92F11yu=gKC)MuX;V#VGSt7is`{ok8lsd@lf+GbEXci1zBJp6Ob&R-8Dltq=zZ-E(G`wKq$ntX2Z%r@N>yy*R zrY7q3qfOsGGUZQ9PWY3Pt>eLoWA*y-k>#Zm&E@0Mlgsr<|5*LF?@za;j~+d0(44cR zxSWE0i~F~(p%ot5&!nU>t53gmE?n^#clhLABO(G#^4{Hfy>RZ@mD&YT47)18v@sRfkJ;4UU6JiQP3HRu@R?q-W~) zrC>we)b>Ti2PI}sWnfGlNrewvOH{N43}>p`*ch#)RHlD;2@CQZ=@D6~+J@pv>ROYA z+Nm<0s#+*&q`)rg?1zTEJY8VtqZ&{q7jHyzh;0KK9_gpGb;wb9vv$&J`I*nVFZC&z zFEbf4S=>z8%klt zGjl3&ZOPj_GwUhWlAw>5`-R1|^R-iPR{r8rtX8=&j@W(?i8mNBn)j2YR=LQ<4bKL%vR%GR%<5hmq!K>p^!bRYV}7fNmYmA z@n;%f2{?NzOd-|{7Y}$`%G`%YayT`V@HnK*(x%b!+Omw8`%Gz$yNnV0ocHcS2a~i3 zZRiOcyk1P+wiq3PZW2UU1I{xI2N)+OOLpWy>#ueJPMI5$x79ff+AOE+TGLQy_nHF$ z>z&F%&+^oD$I%?PyYFFg0y(uB(i@Y`1FnJ%r*TVh9d4Xp<~sHP)seI_bxrHosgk)I ztL$u*mdx2|H*SZ`&Dm-zj<6e}_ zR(Ymot6{Y6x5L(KRn5+9bqs%vMZv9%ezXD~fBQ>ukH~O#I9PAXamoL+V$}1aRwMsh zxml?*7$13nv#q#Lj+PNub9lmU&(gBppbof~Txd2dZc(qZWSbos8BqoMngfn=?LGRI zx0F-K$+E{Iv%|HMS_1%SDlCnZc4S-4ii zNtz&uQx%bylIaH{S_m@f%T|~K%`8qfCHx84ZLWtcXghSQhecLPrd_`opwe8cC4Jcm zn@PNIMmGJVWdPX-*TON~Ey05)5Ee0t+dn63c?i8B;*z`~bT=jLm8F4sd} z9v*Ln=^AMW*=9FrP#lS*?^?&dRZGM71&zu2yiD71)=2!$VPmv!g^BbA#E?S~WJ4&1 zt>{jY(=%L_dYq%=on@&lvsgy31BA=6mjWY)d)<}9Zv{03s2^6#(SiNrVUz{Qvfm8G zH^Svmhp*EXQ-!dzL8J-*bsOAC13e(D15MUCel*_kBY!1GUQ+EtdTB}hPEb?M4)#y* zHo%%~wJBReMms2y=WLTumE{dbX&?#dX*%+5a`1sX6Tr78<91876kF5GvWF?Z1Er}{ z$e{L~^Hh{Slnpg8SOtM+vL_oJ(-0jSo0uAvtt7+)I)f9pTR|c>!X#)1X-amUqxJKT zy-%76Nu{3<*>>S+QD@cCpz9}o7D!K5g{g^-8jQ(ntFQ!xDFNbPJ~#aJVA7P3t9~k% zf*_Kua6N1VEzoipWwC5grDmqvN@uu!?Y+&o;}LY!9{pYOo8B0znqi)792=XMgmFm| zBM4AY3w~n!R7ErXa-8%!d4^jLgN-cihRw0=YWHnfW3oPZWO9n^tvap>Ihn#NXlAf^ zg;C=f>G??~XL2d|pv=)D?ry68?QD~+7OP2w0W&1$8iYzd zdA#np@YcgYt4vu6R;hGy4FFqaoINN%FbhCc52k9_4@bwU?i4uH$(SP9x!j3cL4zim zJjLn*KeMrsYo5zffJWK4?Q~oNQnSx$IUvTO?waRzWNo;RSvzdN?$TYwSYhQXd3!X> zdVPWAcT8T6q%V)ukBq|A1pBR@(dwh|*YP)%6DmwILLt_sv>PSw!v4ZYEj3M%B}CcQXlBRx>%=9Fddt`gCowK6#Y4 zagqbw->zLJC)v$|dP=CIM&OKU!3w!^B3GmptcT5@1{xe?dgONU8$sHK6#_>|KL}xX zQL4BfwbB_?8)pz18}vvUt}X=|3LhT7eG2Q12UoHw!^S2qwvDGq$FQgLuoiqcE5dz!IYsD^#spehR=4?lPAZomOZ2jOtq(R!L;*BSY3 z%tm3qW~?!qMiqkiL}IUdr|2=FD(BAAogfI$+krutB9`^)r6?tg?!?NGGix9WLT&HL z?D!ly4C_MyS#a|7& zcC9;fz|1{&V6!b5=yF8~G-VLSqM*P!9V8j@7sL_CFyn^fx(qtXmnP z#!2dpC|`M+1ub%yBhJozwrPYM-`G|!pHzMEq)*JvgB*k47My*ET znrUIh(q3X3xI?b+Z=IC&5q-P?qf<^oa;HPLa**oy2^kgc5?8u_d8nOo=%UL8BUUZU zJvWX##c6IB2!P8?ai7aS-xNX~i!Og15P^`j0_vPis_O<|8(NB3UuB|3YGOqhc=r6ScG!DiZ zomRoUM&p3W{tU_mcGBZKL1(c{D|OjwKH7H&Z)1iIEl+#96g+?L+KIleNjkA{z@78nrdcVn~m} zFkP-$Pum|FRh`T$g$1?-snwvLy)K(l*Zp>5s*b3*T7a2pRMiwI`XSBQ(GYogS&S|m zUPnx06vzO%oM??5B}-@&Z^#RWJ2DHCpfxr&Mt`&ee?5#=#ulS%bhdLNY`5hS0{GPG zvJ|xAjZr3^5DQ7t@!NKtQidPBC~FoaO1v2RWOc$xg>a>p_!KmV(7@$h)WjclL6B_e z0~u>UV0Ri!P&?a&a|;Z>B?6Y|A0jpjpso4Ire6F4C&QFp2vakw4gk)kz%GUMz1a$t zzReLJ3pv+X$4|^oiL7?>>5AM5{&=X8e1S&)m+)GjWv3EbcW|nTgtA6dbf$c?;Lo zz;A6D#R}$%#c|9Mi3J(7LKQ)-K}Ga7?0Xzdr_FqDThLAlz<1&_12?yV4ix3qzhnpXGpW=_{JIA=oK91=6BSZJfyYNVkIVQHflE&2GJ09=EGIn&gJzWNx~Km zV;Qm}m2RXT92})UKbNyr1YEM5lf&?^j!H_yGD;E&ZoEXMy)NRhM`Y8FFjKu0#`RQg z1no9?o-W81e4?350;biL@{9(})mYY0LG3UY59D_Y{FWTnKC2{cjs+WW(iv+7Igd2OIbT!SwS*LEM(-~N*lcBjq-km2iE8WojBQKzo*(U zXqWwU_T1(U87SXcx&H*Kscz&9-De^_bC(ES+Se3!d_IVR#BX1V)yV{7gZF0b@d3Bw z=_ZpWrbp?NxkUvopz+8FWvpdEJ6K8lj_vuHdU7pZ3!)1x=^dXsQ9pk4_|)W)nYp?1 zQ%|)fR+pc+Iyrx|dwy=^%;QJDVtw^;aO52)jzybscf%c{ZtC=^pP{ANM7=(BbZTO% zexiPK3WM;DOdmN?pE`168ubpz>nU6{*wn@{4I(-xWWw?3sjq!BO`bKd{7Mq{x|myy zT;1`t)g+?YB9(r-9dDp1s!Mx*_I;!>4LiMd=0`!?OWT`c{WxbtrPoyNv~oHq z!a`a^B0rm+m^^ai_~h~WF@7*nKYr}Q(c{M_$-N2%`w*&5Po6k(Z2H*L5yD1!|7sZC zu-|Tv5YmcR1(a^7XIJA+@NB%i95w^0VHmCzmNpvo2!cKNG;KeW8m4 zNN4!YHS2*0yX!|RqsQy3xl=`M)pLHkjo@Wl*YAd7VK-df9E+0`s&`=jp+h>IraJI7 zCa=V48p6&)(G=+n*2<-JFe=+|v{HlnWmMu2YZ$GJg3N+;+(o#h9RURz2kNMt^te9o z43gj_rh-~p7wVPu>~ zv;(FU>GA?El=CQJyO@<#_s#6c7&PcZGETXS1tDCP{<eQyAPYEs z#{K0iK-3HwT86`wC{BV@KD`_#&45o_KTRB-{~*XGR|Z@Ts>1(%d&A#MRfoF2QS4D7 z5(05AQyp@olERU!l{Z`3oQxyh^Z;dciq8b=2nM_mHQT*baN&w3W6igPe71yLJ0b3> z;~=2C5u6jp>2c{@3DPw`nI^eSq;&4u71fh`LRlwM3nRmD)sI?n=L{vSsXL2d@szul zE>m(rzBNUrhs)K}iB41-6 zh+3z@2pg(`^x$ss{w!yc82H}mzv0T@QYFeC@2Vtk;t|v!HQ6HA5zAP(ETfn=L;a}k zT%?3d3NB0$KVZn=vyU@mR#Jg_MPyN7D#KP_Ei%sX9fhiyVlDmF>2)E9(l86x5g4?L z{VHveL!D;14{(%s>(it%l8e33E2pcAVKa!*K$Ye-8#}wxk6j(*jei=pg9r!m(zUQV zQfyDxceUw-g~#OM!Dc_0=_($(-8;6h0RW@Kz$%)zicnD{dfBqt9fn?;=div3ouSCQ zALT}aNVGG()*$%kl{#Cr@(bQOL*uvM6!{f4cQa&|;ns}B4#2Ki5DUP~Hkiy0X zW}zs({Csy2SeIvTz;+Pru%5)dY%B?vN1Z?8b__0H+)o=)e~3h}#&a&Boe&yZ zt|w`L$%%ql80S2rW`6T78r3UhJ5#z7rj6Y(a@h~tL2HJ6)@Kv4LpiY&1c%Ne)(X~X z9d5{~`U(2#D|3}|k*H$oFO)3t&}>Cq>;vgLqN6M=SFc~9!#XyWr62vE<}H!0$X#P! z{h32P&M`6y2}gYZ55Vh2*veLA$4}ORL@s&`(B(L%5Cb}Ebx5Y+3c|)V0+K!04Q?v) zhh3N1E~OXnja4kQ+KCNw8NWa1`XiJ%c)DKiq}Z^)miQ32n76Qf;q%&X_)wqW5H#_cbJf<#WsP#o@3x(!Sc*N_ z5b6|k4Vu?t=LPRv%)KmFKeZhrj9@J?k_y^B9pIG_lGM8XIEx1+OPg=TzL^iB@Qj}Y z*TPP)kog@10D|z<4qG|bQt24bNe^`X)&_Ok=*4)2?Cq+pGZYU^r$J$;P#ywX{6b2; z1@+tk4rv<)ygDCbS9(hq7+j6t^FcP3;G*xaN!=BiD!#K2DB4E=rEaSgXdT2L-+i@o zHCPXIZZkE#sIs&WB%$BFMCUgP%`H6Wq5Bi3>xk$Yb!{wkoj59#eTDwBtfJcI+mDiFT8BztnRsyLZI+kX#MAZNG`p_Pv_#wX?9>b|F0*!hLkv?e!d42QG$mculuqMl@MRPjjFmr;GDR z0CLx*Z9*02;r!e?-M=m%LPb}2tk>})EO9Uya?|$Zh4fsn-QGMMM^VtkS!(yynM(^- zDY1DN!LO_vypWRA*o-L0wPFJM@U)Kziqi5|gEYu4WqIxew-4xv^0y9x4=+mqnO{2- zx+uTeDgKRFcfiA+=L1*FUys6DlV@U=DXu5&vr&`9u^uu(*O!=^x#MEobXNvg(X_|L z>Do2qLlGh0f%6{K+%j9dnsnchJK$WL45~}-PiQtVosr}?Yu0Ifde=hQfdETR|vWF;V@P4NxP9dj!| zlr3Z~6*z_~5`*9cr>gT>pF=Bu3tXuPFii$VIyfT0VU`HK>Ff#Lg~mR-nj<_Chs89R z`DN0?imClWn9>4UI4xkqTAVf6J}fFK_Dx|;kg}>9P#)@P9l0K=s#_Jk&VP-lG?pqR zi1?`W_KN2G1C$ws@V)i67hd{=Zx zS#{OOH+EY}3Q2BEVY@3k{;kHelK>j~U-VOo4ERhKvQ)P&vv{Tet_oS>SSuPOqlvYj ztfp~i&Xdt3^N1p zK;i*5d)T8DLJ*|Lu}Z}$B5xQnmu5ZcV%Tg2@{=~sQLM{xg7jqM>C%~Nx;~;COc*`V zVc{-|Uh0id9&@>qNiD_Jq63&BaRaFu4j(iz;5Vd)d}aF3b(mT&o!-mRh+Y0-dyF~W zR8oNL)J!x30L?Y1V0E9l;3}ro2U(C7F;})E9`%drRY&x4)?D9J(Q{c;iG`IOkt-#K zpSi6=-4yv3-+O65%ceK;jJFnSdNUq^w#k=Fzi-c)7F3+$Ar*u_puyWCIv%nhR8&M! z4gh3e3)a;R#v740Zb)@YfQh&*kn>8AdGhAX+e+S$d96?0FZJ!5g{r9+YUZ9U1XZZYg-_*x^Z2{dlwT zMt()$ODA3$cDP9kvm>J0kX%_GX50fIptoKUX|01SVp=WIqgE zRA%2BvRW)asisNT&rA|GeulLY!z zj_F9*VKcN4&b*Wp&kLHfwnV5Rs3Xk^wrndmP+cg=F92@IRP3bHw`J2 z`8UXs6cl~{-@0SV2;Jn$6Yk_r>sfsrz*Cn2><4+QuOleX=bLSh+Nl&<%;F5 zDd$YS4l4mrx|zZ(>mua2w`J^14k%!!N*6#Uh8Apn&A3`tnj*G^YTg{2gH}1?x5pjH zeWg)8b|2@}g4~;e1HmdxSHh)s*yI4+AcaN< z-0Qm5yryT|eXAXY`G@Y+fwrZbZQ6=meF=(rvi;)u64p*tbRp_=Nd`onE?IlbklpNZUJLOo&TdwjC3|9eW?W6}o3{17i zwaTYWO}d0)hlnvm(HU<*^)Xy1Mh%VWR<`LKx1aesO<>S}i~9r@m_TjDp&pIN3+%}hW!@=(|^U;nJ( zZkVw`DNHV-Xs7MFEZo;eA87!GT*DxuuvqB+84^9l@(~VK6<^}AsW!socR-y0K~)2h zcvO#2QP!MAi29|i^L?aZB@9MQ<{!7gmlr(MS`j)$5d{ID7dXA|H|wQ(U~q2dywC!0 zrhK0P$luxImsmi`+biG)Ssr8LRboL02~#i^a2^gXis>w{S4faz>-9rGhV#Mg8ontC zE)3InN^+wtfvrT66sWYINjv(u=cMN_&`4RR(5KMSxbo_GztU&E^vF<(+xS3 zL@iwN*$$$WY_)MiR&_zV%=k9833*da*5yqKU2S-Cr%sSwKwL4MVeQ%Oxz4eV-oA0YnOimq{K6>o<2~PXLcu|HZ zC#(*>K8(qEWQW3T7Zoc<-~n`dDV=K0@%yqG!su5)wD1S(-$iR%PUWRNi3!p}$X{8~ zw)ezKZiF63oSNhyoQ0l7ga)kZO$GO&HU*;Mt+HV_=0Qy{!+2ji>2-a?gAnC6q!+ea zI@z-QTsD@mu+=DO@uu2@@xD?QfJEe^RPA^rgnk73qDB;U0f^@_CR5%MNlo~eO6y{^ zGpT0EzGCmIN`B*}rK{%3@RduFFRp8lPl- zwMw{gCfiUG`_e8Od41lvn9X>YW-mmoAj*^~tU)w-{FNlYVefv5HYMn~E=aH$zLgi? zQqQIY56T&kzF*M-ZARp{$FaER$%JI?D}$^0pfV879+s0z{!%)jssemWdbN|Rw-KQ1 zC}RHM@n75Q2A6T&ji%@-PfTueaWRMhj#5*~N+<+kMRO6#L@KMQ7X_?po7{uy4bqz7 z&`8b@Vp#m~U~`la9Yzh+y`3v%NKp4LVxeLuLH{~ID@`6i_`_uN@nF-S@)6|n(rTqu zaTozbqGzb|EIdN9puKT~=7Qm*Fy=H%awC2zL+M9$JHUE}$E!LpbMxSVpJ@sX+pK*=?qf%XyIj27b#V)9|Ydxeeocm9WaMx zL<55YB{vHPF<_-L=B;ovWKB$4QB@z+vul-}8#{v0@-_R&lk#}oQNL*Sqpm{bS*goo z$Cwf+M!?oAPA^j$ZS1v!jCnwd<3sY`!GjdBt%GAZ$qmviAREWQgHEariXM6_%eoXb zqxnq9i+R6E!lHbEcVdK$Vw{)5>Ac^hLxt_lxmG8P!ZZsK3Wc-c&~b|yDVj^KfMe4g zzquYntvE^PJ^&87&9EX<)I+Czu9J(m6Wh1>-Cw#k4KE z=f2D&D5ms!5qHQyFv;c|*V-LtxXv;~dDK14zS7y;5>Dj3TO`L>#!AmLLNVjWaFC-T z^%4|Pbvv+u{|Jfi4=?kVnmT@Cf?_u&9bXcsty;n5zsTM0-BzUNu-Tw#Og6z6l%fMU z8DzHy%dfm}MWu^rsq_qKkRa4uO$QS=i%~--M7C~790`1jh61-B&rA*3JmXfwqY#zt z$(1_ZhKF<<7JWFvZn`YM&Wa267q~~E!vTd&DUm6n>|H;t$tX0K;vTY+7-@WFfG?t*oUBk1iQT=DocAOw9yxXzCl~Zy+)lE);~dQ|U>%fZk}#XQLL= z6}>Fb)umpCUlP$B(UZsh7?8EL%X4z6*MTOh62}tS(2Q62c*IGL^edI9r zS~EF64*N4+`;*9?0I9}SH#MWIp74+js-Ba>-n)l6W5~0l zg*;0u@3Y7bF|t_o@_G0PU#4WDBr8!4jG$IE#`p zyytdTrCWAGu*?`Fe^Il!I7V5x&!z-qCNtlB$vxF1eDW2SAmYqd;-F zxT>Bx2U0Y{0^`=x;YMl7&Nqs)WR(Zxob6=NxP=6 z;W9>+msXwb$)LI(=SR=k5@qugvBC(@ySbu>iF=|qg07!Nc)j9%#^Mg7~99Bz{kws(D zJ4`vVOkzW8sZ!9o7D+8}*mX2#^gYTRqLkXblhb1vBiH?@;qNM+$0s-5&sUvh%1%jVUk>E@~*Ms(1zoSH-AZ*9h%F0OhVm2_`8 zZo(ysFd%~P?S$$L$pB(EwYDX7;}W7R!A?nG3uF^1Faza@&bq@LZN!o`}5;&Zd zV=0inJf|!aUvj$gToDHj=cu-|G*j9KyvfxfuTbISxUEyFxLnm~1Z=r{J^;2rml2Xi z5FK8PT9WT}!e8#%yffjTXqJQ&S9Jf92P3ocQeqyaQ0jC|H=gE|l#} zz+^UF4g6M+)Rx1b-D(U!1AVOzpI8-c%G-`dP-h>rQw^Yi0Ck0y8Ar+OXgu-m#agCx z!DCW&CPkW3Owf+ezPOU*R4`?~)f&_tOq7Xh^A2+&z9i_zX^88?4@za2H73R^mYp>q z0(q0|0qWc|8CgO4SwYGVSjN2z3s=vx1Mi&^*va*&a`;$+Rl6rBp*kHyjzH-qk*sXd z#z#vEtK#89LIj_`GCGqsA+^Qo_zI<+&w_D}X&5dt+)K%aZo>B=-*MwTX&lMnXL77_ z8`dy0ozl75Z4d>@t!NM*wHEUA-xQW*n!=^+1Ez`PPl2TQQ{pi-nC~ZgcgkO8viA;K zmA{-Kv}y+a+vdJIgOuD|cX@u#pI9x!5edp2DIZ&?Mnw%c2l=2YzMdQQ-c8HD8OWIQ zp1M)5ow)f3>>+A5GjKYbm2GEhgG@7A1k{U+T5V^epF4SZ*Z0MuGZlE~tVyn9LBhK2 zhh%gBnbT_Y(p;2WME%sagMEdV9qS*a@q+#_?`KF^XM)*`;X@lW^jeuy4f2b>)vn3d zFaS5h4)l#G_Zuhqs}{{uN{Y*Wk|J7n>}lE*PbldlJ1eSle0wRD9SpU&PA$j1$cd~N zL;@wIqTD#QnxkAn*rOS88Y1*sjp3X~RXdG=nx#&@rQ-*S^SY&5A@2(?4k}0hGPIk$ ztnS~-8T^%fUOS|a+2jJpBTrz3pe8_OuJPT8rh+SAdzT5TK)HNs)M!aiiJBdyG(p@G zJ@a9BOVK=smx2v!yV)0}94XQUaca6Z7he@lmT@QQWV}i*YL(qPICthqu<`(^{sdFS z{;al`W6~XL475!EC+h>S&EhpB~7)ET;WJZZ8YP zpzL0@L|+Ck`$`dny^BdtIM(^XrQ*;MN$?*^- zB(8NeK%RH5>!|7KEgz7@VLL3+3Zuo7)GWG1aL&bnQpQSS3c4A7av@R*3}^N}&|0Y*}m8T{^c_u9QH=uLc zT?4YLt9?U09C7=-w6m#r>D%g^#9|o*)7=9&ILRpyXOje$YHYqK&AX<$!E9-%M4d8m zwxLYxeYx4)WbB4Cn5&-f+Ya5S7D@F`f`Cb{P>WOH$!fpwg{QuW)Y)vqR4nFb-HP58 zDBH)S0LfPr#cG|{UdUQFk)!Vmbq1_&{CsZMTU=ZsG`ihGA;Lp?i5;aCWzL9HyG2y! z?i4oEp9UdH8s_@z#_h1V$!F%wFc=f+m1~^E$FfR}EUuuTFu;Y|%gX^@s>+k2Y@4N{ zJWTn2anr87j+ITJ1z-$bavMjxc~vuFvW^r6i|L11mo7Wf=L!dp%n3*FGhB#`xIR_Fpm!(MUJ{K%;^wMxQDTJGC#S5v=J+z z^2?zvt8jxj;94)?!@&(%r%Ta!;VhKwCGA>D_dybcsU2>X+O|s>EDxw%tifh%#kq3n(3velMcV6-0e%NF#`~cl9hF2HxGUGO z^%J_;*p-_%XXf%#SdK48wV{C(ZlR`Lwo9Ai(skJv#^n%T-+JxHFw^AqMBhrfMWZ=d?Q2%uYN}TZd~(`_hI&jN z&}7MIgb{MflL$AkxXd;H??$a~=~Lsv>0kuQfU*h?P&o{^SA(?Ih6nGZSx<93`?Bg5 zMk~_7jUlv&IH5x<;~>mxppT7O8K;yfv*hw#mV||A2ZmX&lhcz9s7D00yKW9-0cF1@ z7TTeVcTYN4fZ1#S)dQ=AQ*&M@}$QV~ksZ0TsoaAivi%@`2HI#6ikA>S54-gPo;Fefp)HcIEb2SrdW8n3c4@W1CsDv2Xh}!`I;bI)G zrLrBa1&+1IY<2AR)2J4QwHI|AN%!Tj4irgOgC#%0rD%t%>i6Lhsdp*Xk3*wj-L=or zniCD={tqI@@Hb%Np;aSgD8yA2(7a#^)kKa&*Tdf8aX3oCVAD!DC|%B4Y~ z3CA1L0JjQ3Y+5rMBUV#!iB1(K8Z=Z?ir7-z+8otrC!Ywy`k_~qqj&HsXM%$@rs?BK z;yi4|=s=@~)F|vEcnD6hgAEkvhR7Y_q7TGN)`r|uZ^paH$MlWgh%Jej#GCf!L55R( zEG0YKdiECXGetm(@*e<|J5yxCv}{_;m`HXNWf4#eZ_xmBy_`5OtIJly2Z8I64@2`G z1lSlTe&@JZ^>ICO5J?}3L!OICoekP)(8!b1faO}v>`Umpuuv3KzAdQSk)Z^nK3Yr9 zHR-F>-MBR_FANI68z@Z7b$Z$-GD`9U!FehVuHAMiCaaqMR1zk{8M*sJTj277^y*`E zY@ta~4&F*zj>wt5ND7e*FC%bwW$qhDJ~o>_ImpJOH!3$)LrA!kLSZ{WCYLtlX52%@ z%rx`ctg4R-5Tx-my>%hjVTS>c2QxW_e*aBqCn%xwHn5f?u{+lgBv z<6|Y;IzA}rI6re{U&YipCmB7XFCKEvb=q&hw?u87$Xo?vqyhx=@f;>^!~rks8^G-1 zTyAgGF$Q*TJnUNml_w?n3@(s1*g>kmaAg)buCMm0NxTo@>jwzDx9HYCd_ ze27IP4)R)`)D~PPt)VM6ENFcKG>=n#8BZ%{CV`*gj?5(P;Q7|#@60q2#Ns9 zNXDUP0@4{u4tm?YT}-8SV4>gX#K%TcIE-hi6#bTAvbjA$z7oG{z4p{=w%at3oJ zIcTieH@T*-w6Qoz+!PXQkRqVWpR6dp{}?H%H-bh-4Df zu!QG|Shb;qW^(C&b0_yLYt#0{N*1-clu9e;P^B0z>j$V^j20u+;EZE?_{$M{+)+;E zslK<8cy}jK?_Hb&j zMifYCFM%4%nDoZk>pToM zemXNg?st%5a%|mi#pzhm8=sXOKa9qwj!c{wp9+GB6UUC%M~L5O%6LX#%h&3H8a5~8 zB*U^z_QZUvxK$Or;%8ZqM2;097gP^@g0tBh6E!zo)fIIf)(|mBfI{Q)2B(5{6c5#< z@<9~RhZfqWdn0a|HL9Skn8MUnA1o#(tcHck>GcJ2fd^rX@%*PX!}H$?22#?r37+3* zz;46J*A5z}NzzuoMzj!T9%Q+l&5Q)U!nIa z@rJuaQ;rOqTAO`0>Tl@SsyX9lyVmJWQ1&fkfO%L>)az&-&6bp$l*3i3Fph#w2?Fj~ zr#mT60%tmnm7*o8G>P>_0Wv15r^3i?gZc`3V~|o-|4|wtIid&vjYsP9CUFAMGrhbi zYsCU4@pP`u0z7KOG;=v&Zx0TYiY>c|DUki(<2ytQeOy?}XLnF!jT1=dgNM%~;7nzo zs3FhX7kys=Wu)tumfB!QVp4Zas8@p}=b~Z=-cw);t`igDqigYaR5gPO(+nYlOzSl* zsonONUkEo|&2trXVkCay-R3-KQYWe6TDni&8EZm`y5m+;qk5Z@gXY$WOTErg;4J#3 zf=tU&x^M!5kK*%{Ah2n!a$-{+nLKgi#L;7uC#HdYR|sGAqgLEG6SV!lLul8+4pau` z?g}DiMM2l2FmtGMN7A=2Qf^L-a(?ce{5SJG`tCc(M&@=Ff_#rF@&U}xy;Dw*i>%N* z&3_h0X`oVIXJ~Y|N^K*3vc*=FM&luRAFh|1ER68sKapxIEvOu4)281I&c(^qVCC$s z9dj{n-194C-$1uKvBwJ&h!Nh8caPn;xmX<@dG_H)-uBGx#YL^!IJTF+1i_#@^#p_B zYQ>*eC5cgROn~%4{H5hGy&l9WH2*xkipq2BLUqsH3NyZRuOK$@;_~ATMHb{HWsFez z0;gZpdN1RX8+GazGx-%&2SvB}lX6773KYbN`t4L-md;Yn?uA(Ja5_5Bv2C9Smn9iN zU6;5wrXf8#Q|+ua9<1DSYnxQjNW2I0RD2HArdZtIR+t4Uq?0->tc8XC4-R8<5-0LG z>AidSSxDPw+1JHs?uPYtjY^Hs+Nv%u$Srd7VHBS6vj8l&kog^}qf2AcZ?||G@JlNg`YrJ>y~VHM+g7~1>|Cep)klwvPLCcNJw7^7*EhZDrsn5K4N%DD zZilPXMD66{i2Xe^Qs{;%Qa7Z0&d;0oL;~E@bCkk*d<_4_#`*$WiJ<%7JvKTqF*-3i zHF{+9sDYQ(IItG?JFF6Bdbe)*QLyAE-NfJQMZI=!CFnM@cs*#&T{?Se?&_7RbMLx- z>H5X%=g(d_eeLoSXHR=3ljhdLm9+_o!AY&b5Ck-~`I8fq4zth8;p#kA)=ACe7FZX( z!_WgCk=6MTIU%Psx`^G)d~9xRZVrO4?o7u-aXMNp@OJq;9&sv87b`yYm|Kx3t1jiF z22YV(r_)zzN=lQHSd~g~df5O$Z5@^JxM@qPt~aU}C$^$DKsfY&tHu96_89-)>G1z) z>fC+>0&tVR6hxrO!eErgzVp+lZP#@Iv2W=n%@l22@iV?*Tg$rAEtOfg0i6Q^AC1@T z*sLCTvCEo=UdMB5vVnCH_PPm5f(?>9!6fN!s*?bT;f*3$l6QpG79vbF3yy8UceCe?ETaT48#Nexe(rhT? zs&PFmrz}I~mRS<*Ih_>Kb{^t4=GZMo;m-6rHWlhp(}+W#{G1h@@}xzwj;YPXQRw+` zbUj|6(KpTwYGB=~vh_PX9dwS+0IL|VWHPmyq3Y*QaJ6$Lbd+%h;!K#(qG~wIsu@Zj zKvU;~d`8fmj$kza$9ZIrG=xdeL=vSL>5a*%>Q7O;fq~CY64;m}T}-nUiRm*T70V&F zwC}O8F%_uQiUSVS3T}ldMe&=Bi`{U!t=CSf8>1*2tOi{zbhb04>fmVd8C^)JC>o)p zrD*S%G)=+&Z(v}OV5*8EZWJe1o?(7hS!#5XTRQzaF&`k=3L18FIWE?6Nb>T;nzvLo zqnFM>UnB)BhizP=F=i!hj(QZSL)5B{Y{4A;=z=dN0YL|5`cbVL0zx)nJsF%)xU@vN zmeZn2NemSgb>XK~f(>~AMJ1F)(B%k=b@n`Y={AWDcS2<7trVVZ35)<5L|^l3CGrVN z_7=iv@Y0S^6~z`wz^#RQ=_ZK9)co4DPIoyq3@~to(2L8pPWK!o$8Ck_n!BQ=?Ko>> z)EEr$>Zg+GYJD-Lx^ujuOyo?Mst~tKivxFN!VR$qLB!>1xqfo%sD}HMfeCSDoZ}To zWf1vG?cy<9?vP#ulKUil;zP4LNF!mwv*c~NKb-_Vh3)}MI7$MPFhGv8lov0L;ADHY z9N-&g5RurU9L>~3t>fRSA#)q-i#ix9=R?Zk%x~8^K_^adhs3y?vKxoo+MkDs`G-gA zqB|Fsu*Hx|ct|&<8OQ1i2Iu;f(E*v$puj2yDk`t^SSdQRy3zxri*+fcyj?qs&VoPh zuOaBn$UL>opxKb`C+8wot*8s0uxaRM@tVu_x-5 zvR)FIG;AbP+}5pZF*D7;G5M$@)@Z)qn^r@}HHJ+nRCMd1R>aA$T#2#nDx+>`eND^| zk^Sad<496<>+tqr9Ue1a02z8kpjK4TVpTXQQ@&4Fd4RfYzsU%{Nynz>v8ru+&=`)! zlk0-va_HD9<~b#(NC3ppcG8RySt&Y2`XRjN$zW;lob<-WmFT09@?-ZtCQW?&2F0Z} z?#Y{KZ^M!@FIP#b=9<-zI^uT%kQ09B<;^Wx)CLS)(t5_W>!d!Qt^!^QDL{}zyJO!r zOs7WbglAywNO}Qn0caX<28J)Ib~QB9&19k5sa&7hU}bw$^JszL8PtF9D*p7~3>iC?xf_c2d?;x3xnu!(|y8ak7?DJS5N&_z^;Nd&vIM z4znQf+cJ)H@_oMAd^Jde)a8moU&emrB41gm)L?R$EICdOX-Pmt7Ods??RHJB=vore^nWOyON`#|(~CyVBj!|K(~hZuWd>p#7_XfK z7$fSoHnkAhF!z$O)YXUuf@e_+CT^99n=0$0dgj2To(DDYDpJk$4Vq;^lg4{{Augq{ z3r9gEc+yYkN_MA&(FX>Iq|&XmdZ+^Auf>;o9V@^N0%ZykIPMk~TaPR*j^V%IVZYs7 z^`Bh|GXL46`RwB2*a)6K+jno3)qfqU-KAKa<~KM}2T_#1tGhKTyh3(S>1Cl%b-{;* zpkRjhxlwp)x0_wRx#q6~;~Ys$yLfeqG-%cIxtPL{a3)nkzFt_|J;}fwC*4p47iquL zp4L17mupIU?iFoNurrn^4plWk$%5R6+ z=E#84w-#}@`ar6fYetVfh^?4v(2S^wQafS2kH}3>fgLzl$WnTN7bvB%tlyfT@CkOK z7&al5S3OgtT&__;0O*b=fPl6oMsMO*i0JZ0&23p)9$!E*!)K)Tz95OcS?Lkw;|GWz z|0hi^x8>VeZ`BKO7`=_*7fv^u%n&SJboVR)!-zt$GQAiu#5YItSG*|1d zw3-gd;FT}M^P`F>iA;oI6nOwRMF4Km49)I#txRv%O48i6jbnv26o+X>V;Q&AbPO7# zT2v9HNthoQG250VHa23+PqiK{d|JvdDK5CUBo5C5w~k;M?NGs?J)OS1l;J zMsDh9(z#>LIA zILx7S?QJoujApDI)eEf=;DbTT z&*o0%<$~F(44M-~$bCp9^I@;c!*bl4nuxX%4O>f0jkG(!Sbh!D>{==u-L08B#%-}S zQe4FfooYpamCvwk?jVLTuV2|RM71}MrbhP7&zYuy$Gx;-?PVhxVY500dH3`m&b6n_*(PX4>CfneI; zMa{x-5=qrc0Cf4H6jk$a63C1cfK+Cyex%`1FssaGx+h?76uISs3_fTFb8N90#IFwN z*uY;$VJW*{s;Ig2Ez$Fvicyf_DaiOFgQJ1Uqe@ak{HmgQAXQztsOesavLIRaaYKV9 z*>O3k53=#d17v8mM%{GqXXvM zop{541e60`jR&BItT%Q#oDjp*?;PYSZrI5{u+Zl2lO8yZozQP?HS5D1L5M54U>>*P zS(Q_7weVBs4iylvla?*_I8J;eQ~LQj&HM!M_8np`uvHv2>3Rf33%7CDa1!zSCzYSQ|5ouzrm2vC%VO+Vqna_A9w$0J@N? z2ISKPm=Z|trcP_1$q}*|mcmgxx#*FZ$t{mrUPQD>u8w9)Gs|>H|J3I7C`6J93Vkc0 z#n-30=oE~x-YLvzj~TVBALim$^+WC}J$oxld@jw>Q9YN#O1t*_CBNBAy@t1VuD*EU z+~VA^#W{7zR>C^xC!HD{0zr|plZ(gCEuO0Dpe6We;tjf{UcH_>y?Fds;dQU;ygX`N zHvM)Gwfw~PePU|y__XsrY1I&(S6hm2Ifafb9-p#>R{bQasf0_gFPMR#u@i-ID%(b1 zx#PB6JMOg_al)8=*HC)uj){rKs{<7dpvQ)F`Sl%0i@fU$ITa`D96;t4ydRrIQ%J>j;x8m_F?*5h{OuLQL; zT+#FM|Ficd@Nr$${rJ^lTawq<+1Dr8iR{FqU9vQZNk-C0npj&jk{u^bCU0h*G%uQ& zH-7JpWMzZ2ENP(-mO@G?2}>YQmQr>?8fbuo?N`G7FQH{=DU_W;ftH{B` zvK7(a?~enTnfLB~&;8zW&OPVczR0nN>=RxYZRY1fMt;G_S_QR{oyQ__Sir)~&SB&* zR$Xt`v3}W*tZvU4A`NSCJTI@aGM#tcA78IZ1HeUh#K zUqf(zSIErIhYAKZiqdai*RkFqQ3#m4DTQ<%>ywj`vywnug^ZO~8{2uTUk(rtpy8n^ zIq6QybR5gZK&{8cHvenRg0?k;;UUdNylW z>Ns~CizvNu1%*ZikM+sfW@cJ`5>ygECEN$=e5BU~F$v zS`FK3bm&-rFRW>pa_?3;WZCK-EjQBuM#2FbCsu=J`=rl2yRzqfkTHs9n^#K)9h_8P z@j>wMliUobgPU}qmQVP-La!kZaTC}a0qrv?XO>;c)u4u+%CPnW^MeX$c{3*t2XbRU zHeqbEJ^khnwOgnhv*fEzhm{{13xgLpqH?&`I!=D+=>pG0by+f&4yZXGKVV5Q z2|&V9^3#PftARSfV`U!jDs^!8MfCHLFGRQW(!2*ryo`E)u{0P0VKBB60eOMD* z)d_(spcV{pcDFp_7EMvDCKO@#u%6{{jnC8+8V51v435Vk;8d2nYH?3QFcu4g??HCK z(3*PPwcT(V&_XP`kQG(^?#^3%z@TWC#XO(X9jw?tiH(%3_}o6+MKHiBhxvJ0tjVLD6s zRK~XQ<{c$haWN9|_LUD4MKIsk!9#4h*bZk3c-$?yJ&(srk-ja5Aab<$P|`Mgk1A=8 znd&_t%O2VWoCVoDATjm^lz0L8uF*Q#&4av`l+xG;Lm*ksmNo5Z)4-=G?-n#VL!g%C zVTX<^$oJ@oCL#vLfZP19PR$iN$9zZsDU}Q>z#%Qdqr~y3D+arhEyWkm3@FioyBD0EVTw~M{ zEQB-+%caaZt*4AxKygrpVp+U&))@2v*sXz!6BtRm4tUS$8VW(^q{+NsFdX41 zs2jj3QmXbin}+8%RE;LMNVW}AjstJygIk`(dlpZEy+_jkxH(=XVDT{20_Z)}yoRpQ z8paGaW2I#oEF1+Z1AD>TB$|r(v@vVujWiAnLOR>nP+bn4p(DngmPDfTybU^R@g(pI zG^|uFcfuZ`8>=UGsoN=arS>F(!-*lwh8g15y;I)INU@>yM%1A<;^Ckxae12ZR+HAW zWH_kAu!?RdWoNlT;chGuCzIV7?upT}N4^2q8pPM8ePTNHHo-j=2a%r=Dfe;v8?|gU zjX{OeSHZ>Ot(Q4WagZsDX+1O(*B9SH2?yt#k|%e$-%DLFF|sFkr@+Apk~KRs!S5`p z59eyA(=m6kM@Ue(8oIm4qY}k}m|a*2p@^CHDvNVaD&%8ONj$Cy34tK+7wzo9y($eu-;sdf5KJj9xV2W=@V7N!?O{#6 z=B>f>QK1h0l}sU>0(2;3_s%PmqU3`xnK!HNI8V8ozEUSoVu@Bdw92sJkkZ66c6Ohn z-Mu1!!M?TVK5eQh9CD~o5L$^a(apm6l(Hk5wugnx5G}-|A=qAtD~i;~a3yUm=J`b) z;zkV7eVqCbjZzHPcCd1pmpsQ4_LOrCei&kMU72o`#If;Xq0(mHwlOFKZ?$@jhquxE zhBGH)Eo#Mr^zbj&N(q*6^A1oI1jItpz?0vrr1ok4Xeozv8w+6u``o^PKL%q!KxIf% zVsB8Y5QNA9(Cb!Yz^vI>$8Zmd!cv)Hex8OH=L$G1z;w956a;KB3|Jn=u(V@M zC?uf(VCV3b1&HKh@cV}hW$+es+k~sc9LZpa!N)+<6tihVP(q-W0P;xlbp2A|lKtn` z*~lks);T3~i{IRuZ$XFa?hf9}g;{3yq_(wSn|W7|I901Jlbm&W@16zS4n3!-#Y~Ia zT1uP2=E^_4oXHbY?NRFq-9W$u4O)4{y{P<{dhnCUUSPV5*Fu>m_?$VQgeqnYdus#k zc5nl=X4$Pg8Et_~#-uw&nG^Zw0xXp#?{H~%dT)a&e?^pbH;6>6G=2kRQ`~Ti1zxqf zBtcV6ClJG`uuY-FjFEMz#F7#2a*i9W7*+5O1F>4MB9tBBg+OQv3@TTen_rs7?@Yzu za4;YT_wbQHQzTRZ9K^3hQ0al*lkR7w)j@civNchYQeK@z{nBDU8Y^3jXz*#Z1tQ?# ztRvUQd%F6@@N&dp(bnunGNrf3acka{sI*LKq%9Z;J{wJZJyHOP(Q7bi?yI$9Oi1uP z7KI4%j4l}Vk~XL>QB{IAWZB*poIY`)a>G-935}M{wUm-DyFEDh!>(ZR=5{1(9Ra(qUiWH|8i8Td3MSNC`$D((e_e7bP`wJcY;9 zTrZ+reF3SPD9^UFp;T7mv_RniFlx%s(=>u3@Cgvok})E_B(T3qbsjev-pk;cX~<|O zKaA*u!Orf!8u)bJR}Ru(nh@v`_A6jNz<@{3YKsQmje?mxoCVmTVe7ay4aqu6gDx`# zn@<2jCt3=Ye7C{j_YHm8Sm+0ZDxaETdG2J)oQu=O!a&jHcY@)ulsd?sRPcf(;ddah z*Ze0ijjJ>|yqa!arMWQpF}v4=hD+w5pKsQ}w_8cHX}E>o^Rin5t)>eXe-~3J!*OPd zSq)?s4B`ckapCOOEF13Jql}3;tC=nfas|YXpv|a3ObJ)+f~hTkDX59R~l#Iw%GPnY@JXLEXj&l?A_I16l4NO5tn}wm%YCds3UzU1L#SqQ8facq{0) z&GeiB?W5m9gA-_SrZkcz@idjSRB1~R3-YywmkzXQ7T_furC=gYD@7HeZ?v_Z{IEM> zw^>yM%XYCS`rDhsUs4R)03(Ex4c}(XIb_moJr@F7&VvVfddD=|m@^&MUJ8K%3D*;> zJpQn~C2ghV4ZFp(ATVIsv=2JEtG5HGZAEAyg&Iz2yEvt#bbH<~3WlAuT$RkeJ@G~) z{nveglG&dzGOGklJg--t|ELPe8SB_c$RmVoA}2`$IayUpNIj{8KMjP`pS_uo`i*D7&nj}V zzN(s#`g3aNPtsU3>lSv9llZyHlB%JkNmk38{Nm9U-zX z$H`z}j+06F3!@#}03~i(uGo!G?9FE>#co<$Tnsr*7K-NIOWL~p_-%qh&u>x+twt=!OlaO%a?WRT^cO%(gdiQgk$u0qhLFFg8td2z z6TXp4Ud%{bZo|)vKzUyP-#|Qh4jOcwsqixss9T*-R z%*~E=xS11EM&Eo}=U5>gIao_b;||-=p%I~uwvL{*_V)G~!A@2Y(hhBDI}h5j30iAA zIw7Q{3dp{yio9X!b$gnAHXUwkarH|cd-}@{pSUEnEw%WG=fC`!%ijOui#IgB>=kdm z^^bq^(vN-rZO7ht{SE)T^PVfV_W$`Ww|~9y&bhb0aQ{tL{MGc;@A;$G%x{YCHn=MVJ0;>$OFwC=`7A9(A_pZI9b z{O2nVy#80$Y0umD;K=8{^qN20_4j|axc>#e{=m!buIc^yuU>L?XVX7ExqocqNiBcq zJ@${^-gW*B@9yZ?`|bzQ`+B;r`ss6rj`?5S_TGo@zTq|R>zRM*x6l1paps}_wdb*)hNJp@<2!$G-b?TOyK`Ul zqqn@Q{l>c=eq+$YY!DMutxil&Hj?Uz$7j2b_nw%&YWS-D$8H>$JiNGY zA{B|u&Mr;rdKXU2If89gS!S4>dhurE8G7BHeCIn0Uw`bDecQGl-!r%Oq21qp;r{b) z{rTVM&-vG-+#RN&5tF%d)>d>`Lpqd9_c&qzYksg;eF}<{phD}c=V6n`0C&O z^K&y}?H9cJU7`NhjokJ8w|}wzH`ji@di!PD*fN{7>_y#%Yv;ExApQv;G$Hu;liIP4 z&4k=X*Broj4Iuy?xY_`JYhY5z7Fc&%;SVgwng&AJ-UG!1t&Jxi|Iug2H5)FztY+z> zpR_OT{ofbVM|SMqntt?^li&Q@6`i49{OG2KzZv`dhc0fLYWbS6GhrTl=~wRf&)MJJ z@T-p&yM8d=-JYuc>L1U4^ZHQL_kR7hPoI7Mds=(`y5{OvjL#f?(l~n2gAH$u{cPlU zHJ_UN@{_%P^7bPytNGoDNBe&C{-=NXnZLWYp|SPlv4<}B)(`5Qx$hMhok~2oVIukH zH(&CFJsmJcTl;hG*B@+s=6kOku6x4||7uhJ z>+gB`s=Y@q{$(ulAG7D~`rz-jrGED}10NjUaDL*@Mc=Qk-JPCt_f?Jj@jsm3@z~4$ z=JFpNx&55#rykT>?tSI?|BHO~qD}XFD0cs655m@{Kls>PZytS5_)XpKdDGwh%f$m5 zPCetC+*zZ}{2wg2z)Klt&Nwtv6>@^9XI@=Lc~ecOh| z7M}Y1A7Aj9PuK11zVy-I{Xe^;`0$UM`=@ScpSid8lHu=eI;nr)iO#1Ju>-$r>igKI z?tSiUe=>9Te|+|;j!kd7^8)`^y`jZoBY1fAPReiZ6Und*dbJPYh07H_-Zz zh08A;{At%GU;Ws3-}2~7cmGGvNe!+>qy5MDh^XX@X4$OAG z>YT5>^!|JQ`JW#D+70#bxIX#57e05O_8o8k_y05uLdf&Z>3DbFZCt82_#1sGeZ|}PL z4bQyuZ$EnTj?Y~6+0Tq#RrM!N{v`j{aQoEB=gu`Aefr=3__uA5dz`<2(Z3JW|Iz(d zKl+yEKKiBu-{?LtcIo}!zUfuBe&#P{U-*mfxUbp!?OX=9t>-O0`Pq9v_0n%1J$3xQ zE}DAD$1;!p`m=x4@eiLr{?5#upTF_MJ+FA~ci!TNe{<^mi+*tV4?p~Qa?636KKR#HZzA8{_`$De;d@^6 zMeX%_x93X&ubq(ShvUe?3ce@_vWW>S^VsW@A|@z-d}s=mb;#cChxiE6?L!q;gyT`Z~pn4 zZ{7aY&fBI`(#gDw>@!Rs} zrVl-N=~d>}dOKfpYt6R1KJkGYuD|u#pIq|srt7=Dap3WfG!Q}-v#HeVoL$Ts*D&Ve zHinCUe*Ak4Aq1ul{sGSM=O<5{I&~I%{^}}tKGv~wlH5ngwn=hd4cSQuIhzmyX|~|= z24H9>Nqx;`_=8-_cKEh|oUE@tYmzjQ9q?!CBx$Vf7$%dX9hhbUpnI~hqC2+>CR0s%jHCRkw|tB%8^px|65s$wlN;ebo+fs=j(7IaOc3i<|=XnEg9- zs^QX0lMUn)(|AH5dBbf@8w;R=fL@+ONOd<$4xim*tfQI$ZB`L-Up2I?x`vSIt>h$% zSukXf2l@Wd$T$)l5U^4%T(gigY~Bi}2HvLJoCPPTTn^mL58VRdV55Ys4q!1B&l_0-NJ5>X7hzG_Oh57EXK4` zoh(T;`NS?lKDmoBK0GNfKs&aLc4S&voKUMGtq*@&GVj*A1@j7>~I^lB%E&&3PbQQ3CK%mEqW@_Fs zkeFb`o@VLc^Jy~HVG{C46=|S3>l!Y-^oCs}PcA0dc7#13_`MWBG4%$5pA8L!!0LvD zfS+mh++e?F>F*onpcfhVvxPo+^;Y`%)NXhPJw^E)NDV4zxW9@t*5Nhs<1+(S5z+|b z(!TL$#ak{-yx@HJeIEQd7ydxwY%6EwLAePd1k1Ob^%y?e$yi4%&dOGD62^(^Ca4Oc ziZ=EXi2G?=Ixxd}q3}5vPC`g-D=iFiUI@ducF}pnx|+ zxeP)cW#6Ik-(qC~q&x!&8MM5P<%K?dm8F5E+yzri2oMi>jHLmp`Y0GK)K`vruM0xJiw;5OF& zi(stS^NR@~ON?|cA%yg>=a&*fUckOzMhN*J`>qi}9$Cbmyp<60N%p*r5VDJX2l~5^^`(Ol@=^92F!Td#47&&+qfjtHJt0@J z@$Z3oVQCH!LM~!?d!bBLZyzD#ZR~j%(12}zR}(@8SvkNSJ;};BNC^25<9nV%2nn-t zu7$B<OHD`pRmO+X^QQCm$lPsvg2E{1F0_cpm|pePjcGn-WNQwvv*cy4-TET2{l&wpDZuD9HC*$D`fY9?@wla}q?0{Fb0 zJdeGfhC`NcYpcu|?rm%D*&q10n?HtgQzM@a_qOpTv$mCY;ZbK>TO0ObAU-ven4X%6 zPe%t66H~F_*mxZElPq&1Ye6j->OqbTgVFw(VKvFsEXi4VI%npuGfwEaLe^+WSvg3* zbMX4e`0zv`GB_3+PejKeu~9X12g|$xGed@RJQ*e<@%WL6slnCcnTbcI#v@}n3?jl@Cuf*u3$OtoNa)Pv2o+%@W@1bTCJgrrvt;&r0(Eo zZJwNnPY+K;waF?L6&QCDg!}Faz=YcCsc5j$f%A$N%jLQdp#x0qK&m~ z6`5fu0_)}Dac&?9^*|FECTIFbV*~#22$gAZLp(Y#6`f8TiXK&mrHv0uEI(`JO?L^3 z-rhekcr+1@-4soX#>Qeej&*!W824MIY27&dlv1G{kxh^x>ye~>I-ayM@#xgy=oIgh z$h;GeFwP?6k!k`A=I4P;`7GEbv_gP@)|`*@mC!?ujiC4j9sgzQ?F4;W_o2=7Fn}glG?F_A zd8CF+Vlpa=RYSXB5ZdN4DL9sGbqqb9v+S&~)ZX2yHYLPIEvvhR zan2>A?sun7ojQ-bL4KaH`Sf2sA=<#khLr9ab9irS!M4)Hlxr@S?ovZ@+L+bh7K@Z^ zq>a35>RG2btTiJhhVgH6L)vgsc35kU;1*Q0jZte3jGuMQwegH?bF;=@`)L7y|iS~DymIMY`XwdjRHbAw~p z3uel2!dio-abkh*nrc|ho@iQg(Eb8l3x*xOPkHybN;kA-=1Ph?R2XgF*^_3^o`Rc@ z7+-b6;w5;~a|CXNQOlY6z(V<^<4>e+D@w=3s(_uCS4%gQupm=jk%05T{^l?Q5yJhY z!h|(n7L*kP9%p4`9l>vfN5rrIDK8SXd z#^7H_YX){F+}jq`3noor8)zLG)|!j?tl>Bz$F&LtBTe5fSlMEZQ7J1yrDclQVFlYE zo0yYj=-Ib%HHS66ud(T%J5xCd@21VuwC0liNEvcIBE5_6p>OLTY*mvc#;MlA ztu#<;?c{I_1&?~#l5~10AkB3yzl3!MG5t=z-Ts&1+89Fbey%S;K(iac94lHuZvGYjhWK_S2ZS#awQQ z28D1fxID?uYkCr5AJGk!?0S9i2rF_qb;%@rZ81zfGy#265^SDGP~+wbpcN4%oXt##>6&S^Q&}r7%iBnQ zdpC)b+`=7NwyLs4;-=*ET>Cg87L2F&4T`6=^Vr*#Zg^-OIOFifK{ZV_O6YCbk!*D z>2f#-%Y#1U+eBrwK=YJr6n(vYy19BUJ>>i@-Jml!HR) zdX`*jSYfyWW_bgCuLxdiD}vVts}v?YZ@9p+n)x}QHXMNI*E*=iuwX43_G~e`Uo+tB zs$iRr5kh~?{hC!U@;r(frFM`eD9GwX*MjitDQ#qWdNQsp+NSFodCkmg!&VE2RqR?> zOvSfUL;)7r2cdL`r~;-GtLWQ~GO*O!1{xv(NeBmBU7g{sE~Wzu&%Fs zr2XY8r2OaS*VeH&YomNoAP*x3Ya*X<=Q1NKHHrN1&*N(X0_5+t}HNH(Km zV}ursq{4u0RvuRb5*sQ4i65yTp(>EdGGdC}sJ)|8a$`CMo`IFmJPxVYZd;3Rtp!~F zq=RUVOc;+~1iy`b7+kFgsnCP@gy~?cw*jOPLuj`-m^3RR(Oec(6d_Vofl%mW^oL{Y zgBwrj40eDEp&pP4I4VKyHf<%I3H%g7x)=d)sYHfQ*?-;%vjKvQ@-{I{={B3u82U=Ftj77)zOUZ6k5f9hX z&I4O#>1FRUiifAR74H(L2T;jYY@8S~Cz1eZs*ic>ZXb5~;7}K%bYv3VkgTc* zSPuzlsj;=_*sV@Rw~f~PoS8q-nsIYk#)hK$O(1~h;DImy*O%Ixh~*DTy^`gB2|wG# z0niHt`bA-5HsG6za9~qK49ra`4!}WVG0*H8grGB~yS90PM=77RQk2&y*k(?*&Fm6{ z^KnctQQNPJloHLOXR<~EL=XV{*>w^@ zs<;P70-uDVCf|bSH7nG^;Wb(>nd8I8Fhs!J2f|78o>J< zP+CCn#*S;#*q{BHuBCM&XXW9VSywYo6fDPZVC^pGuAy<`BhAg&R&g$afs&L`jP#r# zwGcStIIME@@)B@mDk<1X6{Zc%Xpr%bQ2xO5gtg|jFl$PH9K@L}`bmpMeKf8xdhSIRpM>$v3Z25@mrNI*1r&*b zDOHF>Q)^GDe$0Dj(-|C01+ZpTK3z1S$LoOaTL_omHnp|je^BxEfr;_Knb>q9GB`LD zjZ+U8+Ad+wPzwPpA@OA*@#yHpk;K4Abl^~8XksccGdUQUj(Re4rx20(d~fEV=wNgz zG98;hR*+ZO!&N=J$_u@@rlP~K_;hJL?y7<|VcU2fX=cI8=UyY5Y%4YIq?6Dq(J(lb z?vKQy2{@;Yj#JMYHWpFVFzMisLuo6--nT+Y=kSU}Nt2Q35g;O7Oqdl@(@qWT#E6bX zZiMCz%uG#1$EOoh(Hmx>@oCS9_OiTn9c}cVr}0n#%Z2VGYOQ2AZ_0NpSw*{rB4`Wj43KLV&&6Cx_}7UAii z+}5cGAPob-Hxitb&pSVGCx%E;B_euA(eU6*@rm-zo3bJEZd9}xH&nD4UsR(UO?qTY zDHR|F;H6@^kj`gyhl=L5k;O3WVBhDW6kyo&3=^zDmb9B`Z*Jk68|$QG`+aT=?0t*v z_@#E*47Q^MDchR)6f&fMjfVjVM|qhf7$2Gy{UCTqaOlC*5)hV6rXoO@gml^S-C3zf zEK9b)o5LEz0k-jqCW(}=fT5?tEZIvwttDMAvyh>Tc4@>YD)KK|NXOTAN!hSkAptDo zl9$S&gf#vIT$0|m5+RRw-O?Ofg|n*VM6(8Q6un_+JaQD`Sh!T{vXkpaCB1q@yP>sN zHY!NI?o3Wr0{8X>W4#Vns`2OpPf+;AxdrSL61cRYxRceTENGE?Vw&v+?fR&dpNr(v zaU*3LF1-wG#xc^wN6V`OJT8G0;Z<+EmZaR6x?f#uy;5PRfY!|GAa_)wO)g*)gaZe0JqiEMnK?b1wNfE^`q1K7 zE#niDQG}S$!NlZLbaWy@eNa-^T-#mZ*4Xp}dB^0@>5+-?neqOap`qv$MLC&R1tg!@ zve&0MNcR)pPEiOx19U&v2BFX;a*Gr#Zq-u?hbbFZ5f*K!2#db2DtwwDf^#UR=XLO? z&%4bHR1T+VU+_Xt&CUsxFX~yOH`~p0U~XZ|kfzb!;-{WUIbrcj)9l4uI;>sEo`AO` z2AP)m=@}-SV6IqdD65DHN-fdSErJtEHfJGcyacK(Glhp%mZsDD!l<}H?e%QKDdymU zBdu6~TLhd|Zi^#LaF)=@k7=bOyu#YB-SP)t%G&R1YipO2U4pKxBst!*CYuTBnJLDS zUfmkz6C|FyaLp=sdfw5>=8nQ)Ab&1b4Zv{)YmJtrY5sL2kJL+M8Brb3FQ8|D{V*oUJrw4%f>>wf&8l>Bv zZ6X6ummqLg-I{8X(pD;Gt=DP6CIXhoFmjt{y*LT}pdZ!gB-iNdj89KZj1MOU`-QhQ zOj~fYkLq-?IiUE`=pNPSB*dS9b~H{!Cr2X#(ZrG1^hjb9>XMGyiIM0O-CH7)lM4IF z8_!i2mjV@e!_6=+aEwg@E#3qr@JK1F?*-O|QSQciJR5EW8$5ukaB0u4YwtLKI=J?5 zcUNZzPkAleqmui^g-VGspw!V?$0Q<#Tq=T z6@0qXY{^b|+4fE8WCE;yL60c1ohA6DR_0nD*nB=Z%i64C`>|NB9Pr8I zT;M)9h&{Hp+AbrjJMMa&WT`$@Rk#y~-RKg<*o(F)pshjiK4oU=-lm0nTiOq_VDP1_o;E)x zsI<%EM#D>+H?F1%&+wJqm{_Wol;xAyJlV@G zem?Bp)N~Rl5R@psyL;N&!}v$YLU<u|CvvNE=Ny8kpo=S+rm^mN{QzqtasH>XuHI z*RS0KAlJd_`PmvT+!NrQwr&fThv;bF@)iy2Q8zv@7)?aS4?|BIXq(cuz9=Q_DvTo{ zn3S_xt%BQ{x6%gOAqVoa5SayIQYD-do}_}X8Vpl7C&Yr*w!&}7#wcGEkydGKMeBP< zMeF-{>iXtmh2b8#DKz&oTFjWPfj0`HS+p~6xZrj)r)BhfIs}85*Rtlk0a1?TY(@5z z9V@?}kvO1?00~sSTxMN|v}QiF2YELvW(8fkm}Qa5*A=B02s>24T1N3VK)#?{fuEe@ z(l3!RFzPMni)3@TpdnX(-)YZ}ZwcJBwo(SDedpHe+)9-)stG84!~(tqtwG?n4%#Bu zvRiGVU^%91*)q5TJy-%wmB@KvKu%`kFEC&ed*IcFy^8Jf_XqFtfl+Veb)-r|MUxqA zhH}NMYl4gflUFZZR|E)WRRjo6sen*=L{&i$SdRzxtZf)HT0@8)ob30Uo`d|MgndP1 z!4ok67U-UXBE+nfO&hi&ye34)%OZ+MQOYEUS7ljmkwShenSipJelK`J1p@=E`m`5(h^X*i>Xg7shO_6O1LP2d=8X*=RD&(Tv*FTb3dx9DuuF)G zA`54fR-V){=-1iS-VUnXc3_hz@z9iI1t08TGnyTk?oz@kxY8ChgfBos3>Wig8|fwgH%|Iip33>dunpTH>YxP|9Sj zMJ=a8xSYJ6PZ|3))75S-IQwA-zuWW#8+yz_?lG4NX=_mYtBI#i-m*{ z&WuXX86I^aW6otl)Tf1MZPmk|_`sO9H_igVXagAQsc2JUgfU^#xKDGI9M{Nk#V#F? zW$*%MCgh}Yfsg?&%gSt}Q&489_x1Jl`6RS}g-wYh%!o%W?(#|++Be>KSm1m03I|^p zwM{=8gRhXHwzdJDXKiy%U$1+{WVi~C&-*z;Q?cR5bTlzF9iJ4ICKTAPd4^;!Ds({y z(`CVfY@-H^t*kHsBRn`O;0TS_43gA+yC{ypr(imOAK{|bW_B_SpCW-2wLnmWa&Bi{ zbnq#X)j}5`wm+npXDQ%Qq}X`GNKQ=;luL6KT+hVPP@yg`PX86$zCW4O=Z$1mPt7|S zL$~=DgdG>Gb=5Jh2;WjGku&vdkcVT09_0gO*d&(g3v;EknOi+L@h+i8e% zMUS!ZaZ1k_wvHkFAsRn;_+<@!!Juz5R!&CtU<6Yh>?n1%U>E)D5q-BDdlX3a%|7>Z z&J8Xea8Rm(FAFwEKsd^io_HfP?6WtOqA`uhT~;ImLf4D0CVK=H35>^Mx}zq}$VfRUsUqK5z#z~M+_xGCCVi8X#PQUux% zeJmqHURn7(NK(3NZN1j!OgF1z#D;Y-(>cu4Ojk|KOpGiZHz%jsGdC>tFJ`Yl8a-@G zciz-DY0piKFZQ?f^&IFteq?ZRE{3A%aBO-s(w~@`n3(qPjvHwQBC%4R-e zSv@K6gdv3|vgvj@_0}9ro0_;5WU+vxa6ar$3N%FJRUQSgf0-zVfmZX4(ujzb&OSmZ zL($W-ZdZgW=T(F&Z7Mfc39bOjg;z0+((7yvAjc}&DMJG#kS0%gHSpC{Fej@gmjj)w zj@KfUqE1%l#_**YdpfFR752?Rlm-f{Rdp4P12|8&;)Ip~yWY08j$lIu<$Th^Yjt$@ zu!yVy_~t{ftgfohfX12Cy;uPX`blh*R9_wdg_$EAYHkYAwpxl2()ML5Pz<0WTM^D0 z!=t4y>gyGZwHjS&q1V;jcx!Xr;CNgp;WyH@a2Kvx2;~XTxaCN+KOUQo`V&e>toB19 z##Tj5kRK8~XOaOy1_Z*<$kU*>?*_$vH?U49wbrEb4%~t6eMRrRNar2ScCqNN_$k>g zVS@#(V~ig5A#ig59$ii;~BUowYVrp6PY-=#v2yX-28 zyirB>KR6!uxZHx>h2X|eBdDk0YTgt?J;sv&$T4eXUBfnIJT^KE%V8(KQqD7yek8@g zWDJ}LW+|nxP$;cC88kJMU;(i*%A#vXYvwe4uv=Uu8`7FpB0dPDO$#i=P)~c=%$EVs z?#^&`CrYPjux3a9V5o~e2cg#coCU}2>yq;Gs<}vxvT}(j6;l}Hkvk-S`p!5tF0v|4 z(VlJtKe>;^vZngt$E(rP1x9ECjwb->g~LPO z%sMj_n?9O|435RdJsjsI+CUxdb@ygGw=^R-$iYzYOcIoG;4BpJQHR^l4Q;`6ih9<(gC21Btkwi)Nr$*RJks|8Ca&zwa{9hfB2c_4k;oVl z1*8-=Y4dBrOYyJ#olEXvw3mpIjq2#Q=5)mh*%18ky1>Orhum&@y z66S4d8!s{gVV*H6?>b1pn+ROh2(TeyN}WG2Hb_HC(VOI1FgA)CHF}{i#d36U=hAR% zD{Zuu5}{@N&hI<{%vJ-`FxbzX)}hR9R_1xib?mBhh0HcF7KvdrNyx@y9&VV`vkrzY z+zw^WOpQVSJ8n|~DMi?0wITjU26aGna0w$1SnN443XWnR@^CGtr-ssC1|q$L-fF*( zK5t_yjS$2S!T;BEM~yB0HJCQ z5z9@3H@E?xPQJ~Gx5_@urLdATYzOv~!ADARP+|&|RYb?B%+?AZS3atNut+K~S`gOX zyg@*tWz@;x(_bop9s)-%Tw8t~&RRpikHe)B`=Vf#hZme5Wga2$8K9RK2?FQFATwO( zw(dBlwGvlju*u6Uc(k5%@%nO4JY)&vwR$7Kh&l#f_BL)^*<7u$#n zq@L~I@}A);4KMEHXvC3WMFJ=TqP^`MonibVPV55!gzFUO zr$meGzNrSLO}HhL^r#GKoL_Fv0TX;QyR>CZV{4hYoS8z$_;ujC&laAh8)dya2K!}H zVjg*$z2|We>qQVK7~jo<{fUu@__QxE+(`^veI4H!cv`;az-Y39!RQAi0Ekir={7<5 zE*3MKr72q;>`%VBxgtW1K!46yWMCvV9!-o!BU9tC@nLMV(g-1jbhfpjuDLXauSq-y zjT3o(Nd-qHrVd4E@Nw1&2rCO6t!eMTu_wCSZ(exgQQI zJ0JmbDh$Ph06KWuWJ|^LtZkA!E6gl+Sot z`WRXzq_hSWp2IX`@*S*b8o0wW9FI5Y%5q&j%b!kqc?Ymb2DMzEZE{VS<6ds@gZ`y1Us}+D!zeW;tmnwpWXPQy57MiK`#vusaSZmn!Tn)|MQ@{VC`Q%_b`>6}XKhsyW_~tXJOSNW2f;&id8#JuDsysPD>pZ!ElMXl z148O~xDy)d0?ue;mO{2TXXYh;vxz5lDObI4ixckyuB_15H~-I^W&k)7pyI6+^(nQjrDS( zqGqfp0`tpfHb-WrC)llU(9cb@LGCg!E6S(faW7a3DVJ5~dgZa(Z;V~el>s> zh5m}URl#Qf3iStyA3^Fh)^J5g;(e(Ij4rJRj68-5H1Lb(9ta+KD>50=;>7|iP_)rP z7o=Hz!9pByE!#HouIAc6L2yeLJ(yx$C@WAX=0DdX?YaEZCt&cgpb|z<7>Z_vcD#pE zl`zSiby#^G$^cbgd;5Vf{t=OO0=wQg4Nae!8HaUBb!}Xzl+ED4UOp2;0fUm<9N~a(b3VPLtr3POlD0dW2EDF zKkST+e${ofwPs$07mpv$GWQ01Oi@eJLyEJHywdO?#^S(d0JsDim0lc3)Huo}Js0CY zD#De^Dmt<0P>o7gt=AX|ij0G$Fw@az|1MxYCM72|{KcA|(C~r-4(a);wfI zTIsN1JEoOC*bB;8XkW?oB(#bANP+%>gxkiB#%~xE2UyrbY!e8Xz&dXAv`5LpRUR@6 zHwfDTP8z%ikYg9Eq{Q)x*2EiCFUA1!G|)VtG?6vPJ)nlbk(E%-;g?Bq_3P6H+%0mZ)kotqLD{nbtwJuSA0OmFi&8S-H53 zmWzKo!g@hZWvD+NKJmwxyet%AF+V^_XX|rDh=p!9^LdM2uDnZ1ij)R>sR0vgIkuh#=|isH6#9%oJ5JanQ&dk)^Tp)k`hW+7d31&q@J8? zyy@9n)N=EET3b^S6i~FS+bsoq3Ab~uSu)T<iY&kT4o# zGJdI_w9FZ1y2OeqzKK=5jZ-s4JfNWSMq~X`(ebf(B0fGgnHZQD8=D!AO&_gzXvSFC z(mP?7DDp@&GCdNV8jDO;T--4}Mpw3WYgf|$pq&>76q<++j6?@#Mv)1xXdtfVrQ1f% za*c$ZPE+1_bYeIWn@k*zAn#mJS;MR>F(=!`A~z;t~0abvW5$n3Ww9fcbYO}8(lhOa-IiuNCFI~+YeInJ63w^*(kzxcJF<*eT- zniSq=xp!=fN8|C>#Q17=53XmRCW$-avBBs-WGW#s4CYqBF1}7`+9`E!pP7XFuoJLa zRz;S4om4c~+Yd)Z4@Hl9Mw?$h|ElnK)W|MIk%AJW_(*`E$h0u zoNi{}JQ3!Qrsfn(Q*#@^ZIHJmAUP)~nw*;+)+BYL;;q;Kl`3dDZn0X^-FrY*&FvFu z8qPSdzR;rL(~+s^=~1dY!T#{WDweDcYxJbxsu-4HCr^N!X8i-CI4*423Yhkc2 zIwpK4q-ppFQX)Bv6AA1w(^HX2+~4X2XTob|x1o#FN8_Ut!{fs+F?F1Iks6KKmBS%} z!KzR}1jS1}^8{X{#Sl|kTo8eiu4{XI3%VKB#09b?v@l^KiHn(DZs}_R+8VFag^hGD1MlWl zDoxq?9ZNa=L~9P$nM9DlQ;(G@l?x)!9dV`XVu@6wi)yS$7j^wk)fRMRC-MOI7VwHm zn@-AFz+f5L}*i!t4(Gd7&rFnP{#q7iv7MIglS-lcZ5TIHT_w!1{#qWE`EvFe- zMlfv-!=mtNHTXri&0#r6<H(N&16t&Q_3zD7Y$>gWk7Egu@JIW+*K(GLbe{J!K22zK?4A9N@O+2Dtj)P3lf^& z>Qx9aUSUh=5d}0p93s7xq&)7VniiBq$VJdHMUD~!DWx4qp~ylag;$h;RH{L5vnrs# zOORYdUccOdxjTCK`(SHeDH=d>DLL?5&0by~68R(oB_*)gz;w}?{bW>PR@}T2_wFmY zjN!4$P5bGZvow-=ux+AXA5V-g`H+^XDfyxlUuZc2_N-J5%oV?MKlEvGo7QeiZbG^Z zRQmdN?{KA~UfO%#P7i&jyY>IGpz{YPVJZx|p#T33C2Il|0amSTU^&sIT;aGPoFLD; z+@cerb#qv=LqP)fn2c^I28YguJjB%h3caK%;f%MITD)ojuq5bF1g$ce3{XZ*ja24wMuQ+uI%Y zmIyVmv}FauNK3u>szUVekm?_$@zVnDZV!ylb9s=7w``8$LZURXBF$w}MViZ3lyPa} z-Xp>?ccNhAwK$E89*2?ArVYn!(Z(%pD62b}{qXI2eL=@BM~tLnflCtp>Mv%qPR4Y_ zoqw`}%WErfN&@tiGC$j=N?aYr>vEyGqB){jN+gC(YO5xlOVkw) z|3cXKSyQ?)mqP&I$|n29F+jS5jIZsC`Ig5eYmEqL-Nxg+bwC8KvumSz=CzUD)g#Pp zsTuoeczOJUU8n`00bU+pCR`Ff@xoy8f{}sI-$NRl}`?IpENMd)PQR42Me4_v&<#pUZC< zGt#C`FRnyT^9MDmPA6|dEA1x&?&`rEFFV4 z(%)WVg@NUa6{<04atWrNBTw9UZ^G>d7`;pf?E>9Aq)JXdk+$r-nV&OkiU2vh3f22V zVGP-bSF}Owsc3_^x>h;P4sb0l7qyYvVjCy)Tp??KEl?PrNY@H=fxr%uv(knwLpegI z1KL^Yr96EYcaNO4U>eBK>Go2K7IPu18Xh5OXgb`~lhsp34!oJcA0uw%b=%&rP3Zu~ z`?ZM$!*&eA-mlH%3+U`@W9ip}uN=IB^SY_)wBU;=Ezb9Y4xK2Lg|+4tfRArPGV;tIM6OY*Z^r%cz>f}uON;NZu zb4ly?&K+uAx; zdu-v8O(d?;I#6(-aLIf`=?^Kr1iH8H4{&cUOU1yroL2@^xUNGxze=6sKcGrlI?qIU;|8tLaW-er@XNvmiEV!a{`BtU`Lk&lMEDGl z&jRhyE|XA^H!KHAr8Oy67}L5c+JY~yXbXO)s+XzglJ>Nbv%>I4ZnqJ(!R|*7#t^;N zZoenI;C$X%%)%`bY~#i46E>{8<$@(8UgcEC>MmSyEH_=)U<lxTh72=rqBZn7h;-G2M~>Y* zFcKLbj*dl{=lrg**m!KB)T3*`>jeoPLLu*W#T5hG5#t!cfl4m&RDfEDV68jV$H$RvK=KHbIQ!YgXKZKfN3p*c70&Qf`9Y^v$jQ^t`DyE1Uiu@xN7HWJjtT= zbV8ZEiA@tw-!{$#(!mBeJezk%oqK_d*PZFyOWHnpCWr>X8lX|z7YrA}8HaL~bG*1- z;X_m|sM^Z~ZEvM5aa{`sUa&!UEv83FvQ0^vwWOY;CTro16V(JfVE}(_-bC3Y_!IzD zn>+5h;GP310GS}JvE9O5|oEl{E{F!3NWHEk(UiFZxvxDm7PxO80q# z9663Y2baFlur`#_XcqM*;4zN{3%3~>c{i-x#a3q4bX+5E*jjsUZzp@EXS3E~LeE?I zr5rFu;@(M(T9s-t7pydvt6*EMm9nyMH5@%X=d*3`x;-Ep61i#8 z-7>VKZOt3D06(6nJOJ_(0S9m5oxnmkx#FxD;0NoA#%@s#myDxG;Oh3A;erS(N@YQP z<%1R+ddyPF+m)l5GJps36UIM4z`PwH4G^zgARZfd`ua41Pxc3ZP^l?v&4rb>SxdPw zqn^%}nMbYaIRYWo*#MxFM}3!9H1U9Zat(dyOwdm#j0O7Td)MnW%vu!A0DDEy$;-!k z#}m=f>%K6Dlf66j{!i+_7d`B#Mel}|@D%myHva%?DrmTD(jve8y;X;ARoxqWq zDH&;}Ip3RaE{k+@5PZ5)%);O;kZG%k>b!w0F^`Yb0#bO$%kRPBqa@TF!bLig;3&}e zaMC}~G*O9$u)F6#Zy5h9C;L*q&R478@EYVKdzd`h1eAHj91G5_@3iNblWfg}YkKUM zH{7JPUIDmU3Am2JV65`kQCw@nk!quCxBu8tq`mdoIeZl5^SBY(^bNyflkVd2bjOKQ z+j#o++~Co{<6}qr56#@J4|PUSq7FWm6lL+fM(J1Sv7|`7Mo#ad1Gje`>2@5au$Xqo zXNEeL%sb+TZ#SoslXJ(%hWc(m`VR7)Z$RIn6ogUZ=drcZb`gc1a|R}+;)#i=*l=u| zU8))x#W;WL1P_>WAO&y01vTIdOSp$6RK`XPD8o`gykaP>qS^3=j9I=Wt^r}GxPLu$ zOy4@#pEweUO(zDU{WIv5&XV!ae>*6tUWZW+GnRvKZyTZz^-#nN@Rdw&KB7suqzvny zB?C(x=xTLGHy{ryiw6NJ;~DY3MCUN`jibkQ5J&Ka4QiAN7bqmyvGS8RMbI(0arwuE25 zbw27)DLwEHJh8xO9E%RdBB-WQMw<_g?C*U$Wi>xI@jwgH*8cuVaKK8?#4E9UEs`di+pq5=J<2I64&@!mvTC1Re&aBFOP{ zAYdKvv8nCpr1y1s+U{EqJh5#1cD3zZ(&6DasxUYdyMruX2szz&htL-^hIJi64#29F z4Y-sxpn_pr72pS5nMPL{Uy$X3#`u!Sme$jjdI!m19XiN`H@#rCD981-QLr3F<{?lc z7W1aN#OdBPvWD(Z1L?D-qNCABJW5@v`0d!NHE`7yjN5h7xgq!PhHsiUvd|WrA6^>l$)@!FAzWnf=)hET z8o)|fWPBQBhqoaK$7d#^Q$F+;o2Gr^V5)oR(CB1(aZ#V{&^r!0H^t+fxxS^t!;3wA z6HwhQQ9>dz8B0u09E#!%-mGhIi#2p@2R-#oTRGj#^Qbc0WnM(ip!Q-usA!u^>;p`G zkSWvdlxde+RQ$4o9Y>=5BNG#cf&fPfcAL)3?g=Qf+))DMGSC(QCaPSr?UEV6w9s*p zc4w>Mra0+Qy_b+RnZcAN5^hH6gf1&>#VnEO#4lr)RelyE9 zuCSI{htTxra(X@;UOo^88<5igo7D}-O7eN2D$Eb4%MS<&@xD=^Oye?3vpG=4Zw_mq z1mH`q!stETb?S@VQ}KEl>T^rEB@~90PBzN)@-2QrVo-4v4X$^J=T&@si1+uhnk*v#!+P)pb?v9Y?JG%-vUDzkQYjGf`lZEyv>*gF zhc!&e@kW-UOr|G=U(!=oc_}+Wq0-Og(#D|B!*&j|v*~T??eJZN8?ZN1$t+wdtnn^} zn1e=mCGZGA2s7G>fTZk|QYw?Kf)cY=%E^ypvqAP2j;eG(IHwCIK${hA8w7oHSMNS8 zZX2ZsT0>&X8Xp0ja8r06&pMbXZao9fGp@?0&tr?NB3_H*KmVyuCs~yHXV3dgs4<;^ zLp@8G`Rg-dM`9y~W_pKv9J8Z)w0rVs=7!t5I?!G`_~=JAQ|Mtm-6}o)kvUeS4h%ZD zp@KCx7?rA_^T(q%P7jPu%nT;*>J)(#itNgpD|4Og&*f8@am{DL&3Y<({D>Qj4?PsXTqZ<}f7c?lm zUZGiK%4M2m{#tHVv|>q=H|+ZG&hfLP&7Bqvu4&%F2`&xYdE58DbjQ# zZe(XeaJXosJ^mBYnPD+wrZVtu!Au(tb!T8VD?3K2XdBvWF^_KT4r+m*J(`ozZ8JZ& zAD!Oyq-E=_xnSTW%=^*vA!peJx3v@SwTvo=jcb6@!?WqMCtJ3@YM_;N2hM*4sDao( zVS`IqFQGR3gC;1@55^M>l#X%$w;7}fT3P2IcP;N0>1Vh7>6nJk!*I(qz8w(Qe7Ree z(h2&amM81-vY$|ZDl))Y(Www?%U2(;i$Ygd+JVIYsQH=31x_C5`_gqHMu-79O&27b z^oDzvk6J^G!QlEXzIjT4V7m{zfng9Pt)dM8dS!)zyMCVt4&0sOKJTbmTk*n5vC9(I zLA+312C9gU^C>zuI`+a;igP@L^WlC-uU+m?tt!}U@=}F+zz(<455=^9BYjd42XR$J z9K@h%a|*qJ;Q7K(e%uPdg$|Mha5K8AxkWn<)}u=zgJ$MkOVb1Pc&DJJwt}&jRQ564_KlBqg8g9_O~R#5 zYrXQ)hK-$B_m$^~KH_r?+zK}13EM~~V7$HO**7v59QX_{@`hX6O3t$z)ujhLPNR`< z$Trk~a+{!5+o&v>-2RG|U$46Sq&2WufTPwTTY;Sz+=nAdGucfv;jG27?g|Ux=fn+Mbk+CpZ4AbNRs3{53AYN%Z3*F8{kNIRz1wXD{eRX1E>r%naz=R;qIm7Nn;_0k zH^%giT|@&iuWxOwo9j2WP#!9`iC2qQoTM{6Y3=o%-brh3Jl@V-)j+D4*XmL(5t}xN z#h8%PMEU-xI37I&z*Ma^b2rU6$9+6rOv;VCW;z5=949RNNoy}%eREdzhmckbMI(lCbZ+_`h-al;rk9x{xF4e=Q^4D%mnga|_1 z^|ZwCw(ALNH{bLxT%5g>+T&IUEgm+q%OgWd!r^l2yB!XaV^#um5uAVZVCPCx@A^%Q=M;a3{)!S8XAUe*7KBR-C&f}ilcd#@r z`-OL+JQVNJ2O;x!AC!82*pR0%L-N^ltkF-ctuL;=vUp|V)tog8-5%x`Hly3{jRn25 zGoO4xdFGQAQcm>rp7Dvz3k_V6Xe_S2oUJ@P4;e6UgF)#vkI>5Exy`CVM5#6<+xEXL zw(a;X5idCIDeN6yNOhDqZn7j{k(V}BX>~nM+rXz?>r38L`;s@mr^}nja@?S&yy2FA zIee+Gv82|q%bMc-yf|njyH>{ zaH3(wbbDSZHT#kk^6GSUu$8cyy!XM*&bCMY5(}{b18(!6#Y0fh8!@vZmNafM+Jv13 zzsxO>pN+WRA!lsY)rAbM0x2PLhD?G@gr@YJyP5`nitmKV{p|+~JPBWrF(WdzAy}ib z%bHzR`&q}G4}FNbZeP-+)|YhoHeI?{ZcovoZYrlzz{a1;4BJ%-r(w+AEE@t*yEF>nn?^TaAUaS61=1IEBVI#*tH3iuv*nTnFdY zm2M)S6S-yud9 z!A>qLUY)zKywzBq<8NdOFzM@aYOxyyA*)_tk>^s0hh+&k6u-WQs8kRirlC`U_;DhSJY1`G!|cX$ zP$b|LWL4&wY?-jz^jw>J5i3pcBu{P7UM{0wK9((wvpuJ&${li=Su2=07AkRw88C4B zydd~Ls417tBno`jj;o+T#c57xdZnODUt)ivFR||&)?7>ail@odjgQ*f%)UucpDY(q zp1h#V-9e;o_OWz<5In&*xvA=@B9@4#n6QeW(>!De>}7$^{Dk6XI;QKJ49_VLbxhlh z?5>+y$vDgOvxo>}ckRKG?a!W~ zFf#^=tjiCrgwxEyaY>Ob<%KY) z=Svp#at_6+e!lO?r?vr~dKV`jlmj7>e)?cH3!%Fmcn`|raY#Lhb=dOAz4_^@TgwPX z-f;Z5!2{X3etRWw_!%t64ndJY=8T!-Iaw01>R7bHqJ|Z^4Ji~k#i(=X@|JTyI6=m5 z4y4u?arGGM%wgkcT0@NCnM3%KS}+_xE@quMVi;$UCEYduv!3pnclTJ}Sc$L9!bE-Q zYhjw~Yhn6ReLo^Dk|GpguQwJx>IW2O84;B~R$}^C<#$mlyRO5`Imf)>1vV;_8xh`t zo(o9mR=|N8W- z#188Yj*_{rW5pEdT_>MDTbs=u?%ea)t~AHuay>_M^!R8u@+zT~Y-0tel4wgMNW1#O#F$X?_gI`Jn9WS_MpOK4H%vfLM!b6=aF(Xv1~i& z`pGzO8Bcbqwr9B=0JK@c4=rWNO*j_deA9{(X1a;FEj&SvuP-mY+L&LSTUr6Fj-aYk zW*vH$9t!)mZ{#OG_)Z0zitId7raeDZcEA9172bWxr76gzKfBwh&wrDRkh5y z-D9_ShI&Gl)$083erI2_MXhIV z!4@Av%Sl*NsDcuv=V0pmT#&Md`RH%{#o%2vrf5P*{G6jSA_@2aIvbI`c4XlyH70da3l@lOlmU0CAyAm3dT^k#`(! zrMHv@ou={`Oy3pwSz(j^>WSRq0v82D?H(NBs}H`h`jGBC=(7aDRuQuMaJlcn)9Hp) z;48nuu5uKvmMvZ%N{jNrsroH&qEl~rjNu);3Z5aMdPEMGw_rkgM5`x=lXk>}*GbFi z&t5d$ms#23F+6<9i)X#w9333at(U=9roNWw9^ZgN)CvhX}_Q^Q#7jU+z6)@Fy zrEZR7goJ#%44*ejOUAK>2tsvp#BpP*=`p>CX(n!m#kS=!+yvvXC-h+wL`=DF9If=^ zzRxP8M=akD5_+319;s^?ra1y5z)0Qvlmf;lEy_P5&93VuOa4gRoEXbMn&wE#0lB(G zS&Z~Z-5e2PJ(91$G)KCw1Bgn+yv7#;vr@^D#xy^dFE_$`A|cnR3c1^^gJu!Kt&j&T zaX#>Z2(3o#ru9N?%$%H<7&9klX2#5k^93YFps)dYE+wV;A#=`SQ4$xSWuMi|%l77T z8Vx_Aerr7(VUC-W_HLx*f<<0qRmDR;!~f|DhMr~d6cS<%QMCP!>$Oh?*uQ>O;TCP1IhC_@};QaGtzRI=giZ~1SKpu zB4l2k^#yy{f)DaMPc>tp1f3FODA)4bHs;a@Jmw2T z;1w{>TjRpMM=fSbWU59RDfubE%rr+_KMt9VNw0^uNk1i}Mmkm)x_&#)DDtDzCo5m% zM^VyhQtXG~*yA%2CoIhKUHT~-A}S`waHJhE=9f~G;C3vpi}9?L5UX?`@wt1e5p(X| z=4_8fOHfHgg8by63S%@9?64@py=I!rnM!lOBkjm_)`K#>8i6F4n#@iw(;V3yshgA2 zh2+~=;le*7dj$gL5y%T6d`5(7Q^G$Zm<-pM+ujD#j>Me;u}4}#kT6K|;$V%C!Du7c zMb*Ud`F=@J#r5Fp9bOb=^l*MS|Uwot_;_h z&?pX+2?}`K4k>r}apj+~LPVm_imVPxSX9On>8DqDszWZ?oG>Mrryr#k$Vdz8vi;%= zlApZnlb@0q#y^Ed%IhxSD|~u&^*~95``6%|zao|xvyzX_S5BP#6{$*SBtD8%#8-bs zte%q?A4ROJkp9cVUnPuCDho&2QP2&qU~RkCRRIoiQG$}a#G$tO#|a|jlndF?<(q$$ zn3iak^vf)j{^h;(+>VRIex|5s=Si0RcdojT#7#WXD>j2}WHYn!F>`^%iR+UECC4YK z7hJ{A`j9rFH82uJ3|@Uw4NO&%k=Wj59V=DgruA)lVih)DBMIx^p=QuNJ5GHXb?9P* z3xlGj-B33gSkk%H;`&^Ras$7?F&rn5*!;Br%Js#KMNxw1nU|$^(Wp7Mx}ev#y!7It zIZ7JP&ZWllqo4NIHWn5)%qy>HP&wk#Zq@d>4x96!f|aW8Bc9b{q@Zn)#Uv%E;4`V8 zq}o>zCf$ALh7eJ~EukSw4e&1-jUv{9d7{)h7qK?OKCP&4D$eEI(>OOf>(b4nrZJ7c zR+(ozTnR=~ez04)u$>|DND_#gw4r=;p=;mdo49<=n}JUgvKa-tF^jaC)5*HZP0V`U z4mVbVF4LlWpCgN^IB(#OO$rZ}g7yBaD00@khUY#l4@>3`N6dyBQ49rq*d| z81s8jG~M$(;G0L7*W2+e>9&(r01G&*=fIC1;0yeHDvNJ<4TNFK7~zo!qjtvpj>Ho4 zJCez*%&D6h`?{pJ{1!bEWa}a_TOfTpC6Lu_N33lntZpV&d(8H%I39~5yV0@iF(*#w zd&jeUO0;51vp5KPLI0*7D1;%P6#9|aVav1H@ff}1I+g_S7!ElkbjqgOXC$VCfT+b*6?-m9Av9j$;!ZA3xWcY;={Zg#e{Y-*~Glaho4Z0Gsc^0`7t z*G=xNLK&HCNZR%*9uiHn%o27?>{z9Pml3 zws{4Qp=}ZP>W$@PQ@Gyh=4%r!JaOD`9drKr+{OzN7tR;qN6k@P&UY*u+bMkG?eh}& zT3!8DDCxw>eUt>(n0N1t6%%HCb=-;xm%d>6ZrgNymXvjOoc_ynm76K zlR!bpyMrcn*r17HZm!HNFWgGez#NP3cafi;{i*sXpuOXtew~MGor`_TIn8ZKY;vZ9E=4iXkGp4Bk^KFa&duGfW zjgwJ@?+X{k%+bW=nX_Z&C=&%QQH?x(;^LS&+I7S~0M+TnaHMLaN7}YZ5CAraoEzxaS1iV zVdN&P5`{L^dI_~yw=0t~{GXgUqKQjXr{aQ%8W<+@eOIe=q6VO)bzCN*DkgAxJ?e(H zE3PkbotQw$ok$=zF#$?>lVa#5CaKlfMNcF{OiZCjY)hCaAlkA=<+NB^HF1And1-#j zr0HTVtU+pBUs}DEo5$BS=2o{%ZZsbg^JmPwvA!_3wK!%jEG{o@EuubMV=*ziNH39< z^;-)U4O;P@4)y%13HQoYfsuHlCe&O9?mv+26b_KtNf42wHk~H9vc?w0Hxg$araIy` zcigyZdG4E}hf4Q*QL{YAPT!`cBc0G{GwpE)jzx(tzGy7ns$d@?{)MA~{U3u}e0hl81eM7aD-jyqQFKU4vi2VdcC6I+U57O;6b%v88CcZf$(86@Sz(ws# z^{HBI|BGXy4)QGI7riu>Mbs>|n)kqenJsn?(u*BP8E6?_Wi}@JS6Kut5-{6()+@0G zHL>}w;}2aW5gfr`N8=<28|}!lStDeT8{lFKzYz&%G(ovCMyY7QuNSUd=4i?O>6u`P zeX=EYUCwNpc||3?7rvA{zwGipcQj4eL6*3sh5eOY@2*dmSybeqRFJ{xy7Uc@mpIG; zid?vop60bm8Svp_2kT261-l+SRs4X%k_{O55p3*_p65=#_%69}f@^*SZ`=2m`t?({ zBMPH3B>&OZ)svaNd~bj2on1W<*zsG~uJ5qhEHXQmZ?##31?~2pN&bsw;Nx0}83tk3 zvm(=qA`@$EHDZ>Xyb%*CVv}Ou#El}?Pgpy`3jx@t@ykU!R^$fV*j#^k15r!kaZ|M( zcSDlCW-~~(&8;Acn4g$i5q6mozuR(yhe2E7D8}RF5_aRFmDr4#)$v#ydwaaa&A_*! zXw2NO9Qs~%`8V#j$`j1N0>(X3Uaq zNC6t%h&kp9yUcU~+?ldG@BH|?AFNICRPknw7~9^rWCTD-$TpcJM6VQq`!P5dhJ{7+ z(uGSG>hx#7t1I#*VDG?ekI7qX5;YkQy%^NQv<4Jsxv^=Y|vb44GQe$xy#@mI) z`tpryORJlWt4qri_+&^HPj9st2JUAcHB51xom)wARy6XJ5nctp6~s|M#PV9pM?@?5Rv?1_sqDtM)-qsxqHLA> zK&nQ|&eo^3r)P*WWKLfT-G#muy8kJ&&;>r6*l_n-94wKf8kOzJQR``g|CEB{iydVC zSekY#(f+l|nhm6UX1w>txQ+03WGuoj6b2PL)X6ICQ_ZpadrIe>%*LA1#Oro?;|_0KNzRG_ql81 zyksAmFbC`*aW2kYoUPLzC00rd2mM{)R#GCpudNA)v?Dz(Z7&?eKxz#7%)!PlkC@}R z4=Mnl{^AeU)CSZ;KHs_jLp~oV(~jPMt84Ay@pRq`@udgF;Te5R>e;>~^`rWv7VqiW z+@FIE@DOP$a(A#9Z$*KhRPb^E-Vxbgj^ifgZsaBj^ASsJqZ_B{1`R{c38RIe<&c#i zYKx!w2}CvJCeVI#>M@08YqJ;oeZWUeky9CpV8J;jcar;c0aM3N3+mXt5RlId>hljB z@S+J%O8Y%nH2IuRx9oE-@{|PA{)Cu1_)b?tD|GqBVySHEXz>ntN9jw1;?ri(DV{4b z`kF|W`kF|~`VIqLL{^(+winxp^sORYxZw515v!k@+&fpBId`+&ef{c{g}v2_^RKza`A3Qd1uJ3RmPPO`;tAm+xLl04l0*v!G2W0+*;(}PLkDW>CpWtXC8$o* zd%~d5FmJcpBwFW#nVe9$PE$tx&6X&JHPOo;%oJJ~vbQb2%{tUbd0-R0*sLgal)MDN z1dng5-B?|izj0-8Wo~J?v2dla_1Zd_k4`BRJC^I=Z6q|P*H&I0FJ|&Vg?}Rmfbufh z`H`9FDMT_UX;{83ooyIFa*OmVqAi2JWJ`a%j80D%`Yey!ig@?i{Oa6F3Dsn;2bpKd zzgkwtrnYI6?i`p$6mc!bvsr#&Tf;#0(RRV;4|5JWbD&&@{QZ1>Yw9S^rdnWZ!a)ARzq6EdqAB*>#W+H2t9 z-PkRuHLFx5D*O03D{9BGN_^y3|w9zByE2}U=N&CU6ZrS&a3gMdgh&pCnJg+aRk@|}~w+?SJxtal3^mtPdh*4uyQ zKWu(_{Dn8d_FHd+to>HoZM_xx?YHbWe(R0+E!Pg-y4~^K+6`JQ`ZIaHNG5hWbR!m< zQ#B`#8xLR9@PalDZ1r3@AfM~4G&4 zf$mzCXmRP%R8K%nNfB-2HJkm5QUlW$W;j&Ip0D49m{)Mm`@7xU-E1&-)T0{ZYqT;B z+||!iTS3*Ll65U52=a;;cVzrIe)EnB+--7T9uZ)XQgV88oVj+wD=oNiOw}e}cS{Y| z@0@J)DA>27f0V13_WW<|Hj`1k-$ zyABzMDG5@10A#FJtDoX)=+gRU>f+~m5G9|fVkhwM=HlGOtE<-<^t{B4jb#wx7+1)k zo1&hl={%NqqFs$yf_u~CQj8iNmo;oIZfz~CUfXP}&uv}Ts?oO)QpGo*;^*v$Cw46F zCfg&o>r7P7lY0AVCvaLIRN)=~c%nvaGWgqn{1sUNrpld^rzIFuvG-DWLR%CByj~48`O2jBKn(Md6%x%lQiRB}In@2NFu7RFphbLK^&l@hs~j^#UbbM#)ug$uo+fGi&%4t>u8P#~n4 z2an5Lk3hamff16Iji4<06H4a@^EM{x7m-;=V zp{1$BiYgiu6Pv&GEYf86DyD+sM8%^jnfacsFUL^U-o^wRkqb+22FsrOjMK?a-~0`! zHz-j3rGxc~i#x$h7NQdmU=2B9$k)q`RFe+1Iy^r&e|@pButesiVU7+SKoN@sJzBHR zVxtPsvU7Z8ZgXpKLoPUJbt9s>BNMe+4ZS_Ger<`rC#z~Gfw_@~Nf(_%2A*S3OT(aW zGF9ur!>V49gXhx}cy5h4odT!JhkQikyZ3oSr8Lg-xiW`Z)q*C|)4um5)<4>pSYOq} zy5>?2-!!e{ljAi%lJQ@Ef%Vx z{ba6UbCQ)wM|p>hrYzfs99C^9i3~o*8?&{Vdg}{pn@N((P(OUpQvhF@d}rEviaOV< z>f&3My>dus7UWO7a?We&0g_(Bloh$3f3NwDwgRe$Up;f6M`N+?hK!!>d;ns6ltdp? z_(9$-c~zfYd2REh<%WDTj@GP>6}gtvlsgAAdhyNqThoiL2lLZ6!b`Qa>2S5>&Q3Yk zZ!{M#tWE4fGK+eo#X_$~`c#`&lbvAlmF_3K*Vnz>OAFU-&E2XwZ_c)EfAZp+!AncG zP|u?rpN+M(txRPP38cmZ?($hny)VakS$PsA`+@BPx_y))$WSBv`MoQ1^Do|5Z}1zm ze6^+lN#v6~X^Dq<36QC=eq-ZW23$U#kb)26-M)pzD>ts`)k>U?%V!h=+6L;+h05-1 z2%M*Ik@muL{pS3Y$#3vF^HFyzxVAboYv0=WWYD?z#?(#bv|e3`{97-EmpVH)CRgms z=pof9UM`k(%2oU*^D8$t0d*W`F0akcafkIh;Ncrv^8h;uF!`pR-XZzG*>n5rp$Z|f zqm=DPdJJ}x)@-LaO(-o~X&}77<{}+pN>H3OVGJJ;ppCBYB3fy~rs;DMrPh|0=eCyC z=rm83`>-7Q&R%?rcBrQabai!cz89=43v^B_T*=N2!6A736Zi~OyKz))^5;*1#lnr1 zb+zZsL#sDfAC{1tFD|V&HaBUbEurNb8^aTm7b*G(J$gU5a7CRhO2~PEMPD-%UCB&O z(G}bQKv#}TP1P>YPyujlBSU}rH0%+-%OAiS2GGXh)umT;hA0KwT$_I}JDPG-Bnpz! zn7Q&GSLR9d4z=m=km043xoeA!<)tfnyYfi$xRoT9y^Zq@)cFLRspBEb#^TDA#f8So z;@0&wE}TT~XGHJu3iu~-C%mVrIAYE=<`x!6)s@A@<@j$xVpNv4(3}RJ?}Z%GL0I9o z12O;%Q}yz^Sk^3O=@A%1i7*6)Km0IP0?OH=hU63hmJP8QmWkRV9r^O6^Mfp@SVoI8 zRQbl@`toaAYXx#ll#wG_Bu^13mDQYhj9S=Q-fXE*etMLI#-d~I`Uaiy`awE3dWZFSMx zlT@m~pZX+zTfcE-d1-#Xviepe^LYGebr?dTO6^DnohI#SGtUjD&*2C*R^Zw*kOOKj zGS_o2a>&4-7i>#UrN`M~-K|edj8BhWBr=GkQmd49BZyGre=BaHZD1tz``W%-?rZz< zBZJyGwYGhcFUC~#qrSRX=FyIq(&YsmD~=gLS>fs{go)aHaQ&d?-b3W$Rc<@zFJi{A~B+)}|Mm@p?dVEH57Vr5sx^J-iNZMMj%z?P!p+mnLMe#jn>T@Tl0G3H#Yj%!>YPc z{S560bu5!B^)M}8Q`fSfQV#?BLqn5zX=+!Fq455+re>iLse|cNlO86utNi=bT$4gk zrDEx2?`sALr3sZnk;>FZdeUg!gz}{IkSj*Tbh)Axd#;q9(Yo1|-ms&za2B*2ydA5w zA=xT{Dvbun=JXzgcM6G>8<0}f$$~(CA>l=OO{N`G!39Dm2{Snwg>{-xo6t&VXlj$< zXx9{7)U}VhqAr2=$3CZSv>dB?)EhYB)UCl@BgLFLK@kkR!L zK3b_5*5zPP3{!4?&E{2W<8$VrC!|eY0E(3qMxo-} z{W})(TB`&E41uwHXcL;Q!x4{JvGF!p%7O%S_-_V5=P99n3ZULHEnTP zhD!mg*OS{+HLT>gO9eHpIEyaf#xVZucNZ`{*Fufy^wEy9o>WsO+u5u^^+Wwp6_ba? z`uT&swS@PIqxWL&yjxd&pB2*!-zC$l|Es>7GNAi0{bUnr)n~W6F_~ZXTVns7@D%#?%mqia#Nz5sVTskfcLLwSJD0q*DQ&eqO6~V02tLu5 zAb3}oMk{dYZj2y5m3mJ26zW1_h2vN-D(^N+?Cov{cR;i}ZpS+ygk~bP{3P(>PLhGgpq$hz=t}_3^(6qmJ);Sw zfup3G%SP9Sj^hT7izfjfp;%%PGA5LG;m9(kyjVov_^oP+j_CR(kCzhdutk1QHKm195ajIbna@3LLM-Tp?`CO1K?W$oCcPa z#146kHJr1R!Jau{7-t_M*jruK=D;|Y1n>tpc*Xce#RUAAj*mVS8%G)~RL~Zh7o&FMJ8Dn$sdsZ-|&6j^`ZHf)9n)#{de+XQqF(=dnb?-+J zPu}|}u>^nm-Q-ZL0O~){!a&vg*kYNnZD2aL4@#A9FF-Try@en{)sO;M$$!HspQxiFj61Up{g5rt| zM&)>#)0f^<{C zW{eu$WKX$Lr?l%SIa3hYDm#8$%_*TNgbpt;s$lzQA-ENNwvF;Uk|Z%sdj0iPJfhGE7=-LW~`U6tfofg^eZK<(g2{( zC`m<=kh2!=YId`HrZDid+trKx`8zo}FUE84hOuuwsGDoLSQyA&H$DlYb~WU0vnY8` za(@0j!nprk<;H#Zf)iM=2mxR7x{DR|)K4)YTBqMMAF*8(!fuLroPb;XL+rC#2{ z1E0H^El8v7jd0Vq^5!u?aDI|6wUT`XrpMHstzCl2{n9%LdB9EX8pEZNR#Hgl7-jKD z3mxsDY+OB<5!4toIq12MXEomwTX<%DAEu$epzJsCf0Bn18~WOb()E3zY~pLDdS1|V zW6$bTyVUE-&2Go4Pk^{5w3NO?z}3EXE$g}n&`jI+-~v5In~4ezu9&0ML3cW(on}-+ zzxOd42O3AO$3vFnb`6<2a#J+jIFysH$2^^?)h6*k+dDrR!#o9ZXp=N0C%9L6+T=Rf zV_rVHFIn>(@n0RR8s3c%{q+IOxxN^UZ8CwMYneD229b#Y5Bk4S3Y&bi$U zR(U*KB|DDse`9w*2G}1QFc3bnpcQ;5bTK|t?dTIhx*W`&sqrUK)3iBvKWv#GJ{Egf*6EP+cL@=GXrc3oLzua435pi-#PQjHo925as~xX=IMGhQyep#?wJQ zSaiCcT2FU=k6Taiov|6nBdV?dz_$W;h>uZ4o=4*{A&#ha1u(u9@JRtoKH%IGaqZru z5uenWG#Zjr=t~S;?@J8*uVrHB9#j=>rl<x);LuxJ+iYC#S>51t&|EsJAblQWoDax6u=U7COV1Sw- zs2K@Gym6mGNb*0wf+ahwwI>)~iYd*W+P9o4IpA45kO9xiFHZfzgOy)9R@X}?B*Fu> zd-nY|- z+OFkkRq&aojpo@&&xBOR7Rt{tm?Q^z!Q<&*@ZjJ^cW zC;JjWf1(SZ)Fhxp5Q1yNX*o_RtkuF>XgiF%D>EzJt0X}M0ZS3QS}vkybI*L4IK{PA zc(=w)X~r8f!(f+1t*&Rrfk$Dn)J`kY#oqfY2_{HZa@LWnNk|t&dgsv-<@ns|*m0p# z+^`ilN;w?Wzx845A;KN1X!8 zG8%2OBCh%F^87=zZ5)8UMR*9mID=l5r{ZdQM7_ z&&fm|(nhqe37m%|E6BXQWX_9y$(;BuGRLAg{Y9x0+m=URSGP77u0W*;e5S;Z!$L0* z7cEkMkW>_iE*^|rk(CM2@{UA8mi9fQ!Yrf${ZUfk?h{|soVyWm-*bQd0LBHAyTDps zKG(Xy%*EX zCiCPO(-@CvUqNx3RmPY(@o5_yTf8!Ors4VDPFL2-()N_ zE#G8&bR@nPbR%;+=&&)q6J&5_w){OaNVZvoJLxu~N_H(jL3yDiDxW(s7Cm={A|IZv zp4-|Rx5E6fwjAJIQG{d*^ps1-YO}hjS*3fkN-tqLJ3EU9t!GnVIvQ_x8nOE(Vit`~ z)F!7p;!TVaDJ!s1bGWX4@%G4$rGVtLt*4W_1T3AYb?tWvpf)+{`aeoQd-~K6cSAmE zdLKk)W{7$m{QcYiKXN)&Eh%!ocCdTuUCZ;V2lW{6fUz#l5c`O3`Sj*%D_7T6Uuz)B zQ=_r4wlcT0stzZIIO103&P-mtwIUdos}i)tJppH{YF+vu1^>vD*k#Qs1ul#6UR|4| zi`+5(Z@%bA^WQJ-WBx;6$-?>NNV?)EEaeYvy-~gGYr$FRYr*+HbS+qh(Asg6z255% z@ru>1%OC0GWNlWO5wo0%n^X{@BZ8-sC!R}|J8fCKr^J>3CC8XDtEc9R$o#z+2f`J` zwcb(Gxfmo83${kmh)ixVor)?o^R8=_ep)M zNlTUXMp+tUhxk1s6V!mK`^3-pHQ!y5QiW_K1s-l(U%RnE@kP@Tk_x$)&%;-j=Qdx&YLP`x5;zSdeS$-(VA5&T zGWzecLQK%99(=bl5Bq?MC$Da-t!^!@F31SX_f-iZ49dqxvRKPdw1+0?m4;J@wt8cI zd2Mc?u|jcr)Al3<(-a_Bc%D~rr}jLrN+ZU|JaY$h^fEH4ZqBi)n)?+Av)o0mSHJFkS8;sc*90k%F{?t|G;A$98HY z>#Omcq6=k$yjwc3XGE(}78y6o$_P(}=1o)j;A zNQJGxdCPGqC~dQ~OEd3GX%nK0pYBS@hSoIp+DCE4{pYpKt!o>Ln~jAlrJSYmd$Nv# z=)pRYRQm}gPM~|%S*3&{5uAn-mdUsH^VR!kqR&fBbYFqc!!q#kcPOs1%kK{z@HU$@ zli)#J(c!*vP~)^<6XF4~UuRsX^8Lr~kD+=?YTT5H~Q40Z+F6{+(UT*tQ zi@J90na2aesrS#7T?T-gQia%nA1Rfts%OitjPZ_Xn`VLKS;H_+8^*v9!!V8;Zx5J; zF>q9bco;&6hXLd5;kCY2)ju3KK5BJw<{UbRTPZ_X+g8HbL9~~KqNaVc^Z=ftH_uIY zI69^ZQ7(VM5BSxq^NXg#;+shj>Zdv8j%$%ERJ@OjMY}6pS<5a_tM%_@?5`r zn>+DT`Sh>w!uchZhFq?%3Sk*jT{H+|Xz}2Q7PvklI}jW()Md_LT;@pWbk_myA;YI? z6E$^Xf%6fEEU}~ZvQHK^$YUj9sV6P7=hZL2J7W)7CD?mq@L;#qLF9zA8+ZV&c0;ry zfE*g;?Xoz=Mx^8cr9%#dr|AhRS36MVkkgd=*i&)PVVSynJ%)71Y04KavdH9KK++I7 z#7zKaURm2%Sl?LO#Hy{{9ucpE%2zzHb!Ll5n}8@HH(J>uk7ruZyL%5UNsEFgq6_fM zQQJNbXO!%({^36RD?hg@nyFMo^qC6cG~lIpn|2G8(CfBc|1yQFZ}{YK*pN{W!4%J> z8jF1OVWKvEVSKvM!b2ls;LC%g=@WeY^{%?*VQEh-32 zPY5XK_crub0i$jr+ptt6~6=!w>E4F$dH{>*FvXpx1ya4hfu_%@(w?4gvH7+5rRGhKKZ*7D z%G}1%+`^UYJO#<+dq)VBUqt!z!j(M6$N8KA%F_I+9#_-ACBhoGjF)gM9gPzGLMyN& za57h|&dunPyAyA`{*tpcb$w;k4w~%?b8lRYu6wmNUls3@WkePFrd5SIi|Afo)as>~ zX!T){Mtxdea_Wf&oUZPtjf^$*eH505lS6zph#{PDM{U`TQwlv1jd%>o6#JxlcS2Oq z37oE{9gLph1w}FjSe1P=UzTa13OSEem~Usy#JyCJV@?y6UfgX}^}nB9t-+fZ0yoQJ zQ4-sc8)`01k8)P3=$S9-)qEgdjf{|&ujvU?iY;<>_@=R3g$d?p2TG3+n_E zLk)^$jDBm-;Peo^sjtC3W%e z6lxJ&DRsAdA;lwG34}Z!go>&N_a*w$&|m6HL;sz7eB5r%>9~HKqnVzNET&JW%zIWG zn`?ORZZqgcHZxawlsj`pg+!JbI?x!~9mU?m~lMkM9E!H%3p!8j+ z+Kd1ws>Io`Asl+zR4A7(8v86V5|xT63JBSks>-5GkzRmjzFmN2KE2B%75IIW>r$-* zw7Q#4!|^CmsK+eoNhQ8?r9HTZjX_p3Dj(n!Mviah^|Zp1hk_k@zIb>yJxC5uuSdH2 zBdgl>i7kkRRgvOZp45d7N2cU(XBImVeJ?^LNT|KFI{&M&w#u8Jyoow*qUVST40M&E zo?nLaOi41lg+!adybe()ozpRj6{tCc*ON6Js5pmYiZEBO%IZ5HQOeO{`>a1TII$M_nfscfkkA$QB<5oyBbf&*(S4D~1V zWgQzUdMu-QkIOpgIlSUihGDp2%xp|MX1CfW4FfutF(G1z;~O^NQ^wl^CkzAe#fJ~! z1Zv*|sPAONZgp9lRN%({sH!z&ENX;N5C*a3q3+{`VSGl^jqlHhx(E4**DxJ* zeg35Z;~0**aNadEY#75wj*Anp6G%QOkHL-)7{>5PL>oSI*f55Ud;-CD-ab1hOtxr@ z_YQcV`M2-fx$~H49^a1%eG}g@4J2kikC&vCbQEM1SjHCoVDN8z=CyBV)94~FI|9s(8piPFF*vipkywE? z6+?r3LqHr!YP%eTVZ$&GoWn}&?Mbu&{`z^*2EKpZSed+R7=MeOcT%q(F^r)amYarP7Swih%l&&=c(3zSxVV}0Z!#|`8B@s&yQ&f7!BpL_0Q z%nd&Y#nK*sRCIG%bQ7F&Mf^Uj{l+1$Oh2mq{^)>V;9>G3f+;|2P7E;nG3>mK6Ga9x zXuO0d+J!Q>rkyYI)XL^sj)y_ujr$3OVJfZR@IEz6^i{)=eQKEOtA?Zd z)G(E=VaPCyZrF}2htGR_P7C_u`?Rq#dE79D2OvObBH&F=5ke+DXBfth8-_6_O5l}+ zkBHxYe&^1ePl(??O)x8yzhM|(G>l)TzrRe3{F{a`@T-O~@N0%K{NrHaAII+eC|u3= zASjMsiCm}6Dhq4#u)geD0fj_|7yue-lYiK=d^j7F7BxiMswl8lMTdA0AKl$cc|K?x){eS$iH~-Gh&V1-w|IsTG zx86jPJTy;bd-t!2S#l8)LCDt;@f)+`^WryV$yxCmvt&yAK4uuk?+bJXwci;1V*=)1 z4;jYA0UGTuQfRing}G?_`#X33?9Pz!HZ5o;NX(oNOUxLqXr?uNNQ!`UT z{O82<#57JG-oIbV&!!A*~zJk6LVLpi&v^ESIqULrB|oTrAl??wd|~d|Iv$?Fy>92c;I=7Fz<0e7Mc+%4Ir@J59pc}c z{3o>DXX#%XubnNY|B(XyuPFLo9G@zi%4HlnH^06lC_Kq2d;rxb8cxVbEqV0pU2*75 zrDJ?O$r9+|_|%jl&=~`g?~8W~z&rI`z@U5SXuSO zj)|s@2__#f4jZx4%q&(zh2CA|rAir6(zUGlG29uzRp8i+ohB{s2UOKj43f|x?wbk| zP=KN!#y(!Ea^EL(BYc0Ku`+qoFn;i;@r1E5iS0IgS`9>V5_-=g;uOd*P7R8*!7S|L zF_C^u!Va}2cv@@Xn1nqd>cfuwH~;;tgU#Ym>{HB@NxV&ljqbCCG4PyW419q0H?+4o zGyG9lBltQ8^Pds_|az2MIA9K4%0BzRwsdlmFL%Vf?!R!}!wy<18hrav`(5 zpzZp4r4CDcmQ-Sv;4PyVox%q@GWm@stH5Jt4C4@Z7~kMae1qrk4XmAQJLE=eQJ6?X zsXSia1(^;@ke1%ykw0UV5BAgYWigc;G0)ml(5h`pmcZaus)LU}wdwkf>nno7=%i zIgdZjYm|Bt2~XkA6F`^HAZyz{J4g;Bn<{Lp_sW5T2g-qDBYF;ubjWzHe0Vr^npsvf zdUK%^h2TOcGzZ9lMqeyu+y@hV)A)GRVLPtP;_CA1tDCQFZmra7HU9g`jZOT2vTGHp+?%Is9@Vr90)X6(re(-W;GtKzD6t(sU- znzR)uz3ZF+%yvl=^1@bS^uN~{TDX8J|U{2d3$%=ax$hYpmP{{o29P0dJNhwiUI-M*@c&OU~KBCyPGDE9B>Ut^}_1K-r z_WY#k`q?dp-H8fmc=Q&J+sbO8Sj)6ZgdC-b^A_oi+&Ibi$YYh5+_;pY1%kD$IE(_+ zC+ml{){d+YPkfV-NdW?6E)>CRZZo)@RtY^hn{9{P4(rI`#r$n%dC7L~d>0Yf6w1Z& zx4NvG=0C2tPs5i(Ak#Yz;8=VIX|jaa*DMG8ac z&ThLChEZ^Pui9oli!3!IsGQ2A8YGUOMw-=WDYk}j!VPiGsCE^Yy8MjXb#SdJQClUP z5%HXxOeKOfc_KQG?F(%XWy?4&a-&=FpXk6%*Aa&sVhxs==zx}~6BBdHn@mEn1(GFj z0Oc`9wFZ)U%&F$FpyDivnQupXp<+DrzGK;;w%-E|9m`Ibr}nzCF?7Gf;%)K?lZmLp zx00|Es@X=|#xmnf(xghh>EiToM5|QE$3?`CTGpS_k6c{;~ z(Q*-RU)GKO%N#$Qc)%3NZkSximB?guEWe$KDiB$f(rU}3N7k-vT;l77J@7>aZvrk8 zI3N71C<}iKuna!fM}C(4G2Z^7feip04vcRfFb0NflbZOojV4oF?{S#4jV)3M-Afz!x%PSmM#-?jQ^9;lLK3k z!B!CAK?0aeaM&w6QijRvMvwtikf_7M03RLo6~izP-01y;dLC_H@Hm}x;v_xO_^~*$ zeJk0wZH>~By*z7=MHj;;NCL&EGLJtbnH8UMgeWzMn3|EGGWr%oiga5;j!oEmQo)lIsOWD$Z zMHq%vhzJq8L_%XygkcyUrb$E^zs$jeLm?hyN~Qw2FbOl-47G@~)T)OW6(TKbxC66B zGu2M$#nmX@39F%%F0-)sL^IVW=t4wR`4p|jx|)KORs#v*uvN99)D($DC7+*>^kBmR zfFCE8Z>v!)gYlW$-fpJ$p|XY|%Wtbna+r3T?T}PGNyqnP5fPn*jj`)%Ysv>o!Psp$ zf9F6EfI;h;sL{h7s|cJ!PXMRp+VZhz>0^PFO=}MwjKZ7B$ep928@n-SkvgSeIo7HW zFbRvGUP(&jNFBPJxRcRGbF~P7mR(6Yp<4Y*YiY)jTIzEY;kDT5vQnBKr}>y;T3_rS zR5}3EJ1wha`H2;)TuhZ{rrPd=l{bRastoa<6-w2x9NqJ4c@7VK#BxI-CR!!Ip}eGa zuJ*_cGqld}1!dC8$REnTek- z$T>bGx8M&|G0zXWO7Q8Ti(1xsG@qH-i{&$^yOJD&H&naX-5PWTDK8Nbt*jKu(F`_N z%Va6aO}eTiwgQpmxLrk3qBf;eUEdBmnzl#HTh5MC4I|caZ_DP1%9JiVR%Hf^15wZk zRC8DwV&84GQe_Jm#4Ji|rLmE7Ri_zmTT!}lVxfsUO=!6aRcOm`N1achHTa(^{U05V zrXpf)G1bTLDB@$Z864$>u&)oOXct~eNwlmIF! ziyOLBH!u$=&$TOjlad5cuKY+T46XD@C1ITqVP92^I0Pux7+JeLOGq3tD8xy`td6P` zQ?*!YM!#1SaP5k?wkat9=1HR3g-ha42>-_CW$pWAV`cJB2k`jlza5}M6d0EWh75yz zsfWe!z#ktr$ZvZX+RD&ppCxtZECi?UVj^)z?LPTm=6GKgsc97nZo>jCHCz{a? zLleX0GR_=@ql0dcR6Dnlq}q&vo0^1!Iv#|~heYAK3fUAWFLQKLBK9Dvwz%8mvrs>J zhpJf)QH_|boE3mpGl^PpCGIxGbr9J&1aCXtx?mWn#=vQIV;Um~N#+rBj%US8DOfV6 znaHyRSq2Lv$~2Q|$Ran~*3C8`vBFZP*2R*1{ccrq{3J#d*9L{>Ek!c?GRY$%oQc2q@R07~~+;^xdSs08{R>nfEQ zizTJEm2m)rq9TKd*yw0Yzli}Fl-!fJgAS%;nZFa)g#F-Sf;14< zkoy>)B;1p~jevKvlarGz9BFQDUZ+b)a2q~jTM=HJU{Nzj8fcJAvB)>+=@pwyy8fVs_j*LDx@Woc4p_ash-am%kx|SH-9hkBQ&lASwJY z?w=It7+ajb;)Awc62JfC5b9i+{52khkJJ2DF;GI1(hdEms&t%IRpTWyvps5X;mb!c zU+Xbms}`%FSgXj))hbenHxRi)$90I;ih%4%hn_Betbl9M2~p!Ig?%IGgjAcCtL->y z%WxYm6Pzv7DEe6)7iMi#|4dqaKAYMKb8VeKTaVCf>~K4roy6a9*LTsP*|S9fga)53 zHYjqby-()aJBjv=RIRWFm8>vNB`f4qdNWtkY1H(X2+OctjpJ=cbQ!px>xsJt2>hQd z;;%taA709}{4iP`rqRZc5t@6v&>V75|LL@TBvFOgX~xG1(*&Qc_T4pBCZ`6Bfyn{m z>@nWL#DH=3)U{Tp)0vrhwcQ?{+^r25XOH6$ltmSX?NkShvnQ(QapCxYaaP6fk63%0 zd`iZnZe@V*pwEoV=0Ji)m_a8 zGMm%snG^NQLH{HsFjb|9BB#RIbkvbpigfQU0=d3`iZp*v=yg3R)4{OQ%Yk()yFy`7 zC0(W-S8>LgJ3*nLI0Kz z*%tUURhb9IPjO75u76WzNnVw_O!%uA0(v8R%iCAT{%-|4M{>G7t7hx2u(VRe;(2ZA8( z#JM>Q6|viyk$CWb%B!MO8N89n4FIMb35Ujob8*K@*&LHrCdW~jH$LREod58DsW-d$r7tx3H6Q^lc>ACsQ?^;E?^pSYD3DFJeL9WYel5k)Ix&u$@q0Ck&tRRD}*AbPo?;s9c+Kr_*RF-is$I zPBT4ZCwsweHVrd~(!#LP41y#^AgKy2XGADce7vm>-_up z8-_7__&+p^;Xx06vTs65;`%!&1yv{5_33es+pvIz*dJ-xJ`!ESNW&{zVHhiCRd}ve z@y0V!s}T!>@ja{KVUt8uh4T+ZRFUMv#6zNX%>mqpByn@O`bMBkv={>|OI89Nl6UK6 z8pN6~x?pz2Ozweb#JDBV4;*%m?$;Z%{NV#DFxD1)AkgG*)F*#~Ke1fm16eMA<6FYu z{7n9a^;P~J)!<<m{dL2j<57HmR_o)>Y4#e127f$95Gwfe+j%BrpAj2LI1B_}>&x`uM=*Lc;&H2LC%6 z{O@Y;zo)_D#<;}i4>b5c)ZqVx2LH+++M?T2h!^lS4;la`3UZx(O3%VQCm!oyK&Br- zky9#A$T;#zz$>uF@wWtOas5PKhLJB=c$bqdgdyYs`3BmI36 zp0L7Q`{5@jJ=6LqnlKOX)>RQ|;yj9cXQl~CuOj`skbYh^LFsr5YWNGq^jW0iN?(d9 z!G8qlV@RLP)PsN+!xP2y%Sitx#d_wD{uQKO&eU@a=|5dezmD{uFQzXc{f~?Fzld}g ziH4Ul^)Dm+LJ@uy>9a^*&cJ^U(rto&PG_VqAe|xodyXLZ!9=Fi_agTL#a6x#=@_`- z@6Et}Khn=3{rfWMKY;ZAxLD5*A^lsB{sS4t_!1c7A;EjutRF_!BO>cdnNnXy)_)?h z1~OScf~tBeh zuTa^^Oxd3R0HQ|_Su$B)MHUnrWc@@Y>ubpRR?(4csh>jD-w|0~!%HTrBVPxdTd3^| zIC?uYF)o>a=IzfS8;=+cf1NV{uD+o#<^CLUw^i=oqEA5qG6VecfO&&p5W!P5{0oGW z=*f?Xwk3_J_Fn|Vw+V<};LSg;H~&ij_;wxOsOyK_Btw>82GHM=Kp7N%rHI007KLBc zQTP>(!l;hIujwcdfb^ovAo1%u62Fo`;x~#&Ol6Vy=Q=ER9_WpTjFQ#kxSR8H&7Zlo@cV*h~;zK8jJWQzSI)Yh)= UWHv%vnI$Vtt3qCdqP+3{0=n<3!~g&Q literal 0 HcmV?d00001 diff --git a/MikroNUC/20260302/20260302230001-Config.rsc b/MikroNUC/20260302/20260302230001-Config.rsc new file mode 100644 index 0000000..9be17c4 --- /dev/null +++ b/MikroNUC/20260302/20260302230001-Config.rsc @@ -0,0 +1,2770 @@ +# 2026-03-02 23:00:01 by RouterOS 7.21.1 +# system id = NmJcEM+8XAP +# +/caps-man channel +add band=2ghz-g/n extension-channel=disabled frequency=2422 name=2G-3 \ + reselect-interval=20m save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXX frequency=5660 name=5G-5660 \ + save-selected=yes +add band=5ghz-a/n/ac extension-channel=XXXXXXXX frequency=5160,5200,5280 \ + name=5G-5160-5280 reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5180 name=5G-36 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5200 name=5G-40 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5220 name=5G-44 \ + reselect-interval=30m save-selected=yes +add band=5ghz-n/ac extension-channel=XXXX frequency=5240 name=5G-48 \ + reselect-interval=30m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2442 name=2G-7 \ + reselect-interval=20m save-selected=yes +add band=2ghz-g/n extension-channel=disabled frequency=2462 name=2G-11 \ + reselect-interval=20m save-selected=yes +/interface bridge +add name=Bridge-DOC +add name=Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] disable-running-check=no name=ether2 +/interface veth +add address=172.18.20.6/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.18.20.5 gateway6="" name=docker-xray-vless-veth +add address=10.10.10.10/24 container-mac-address=5C:26:FE:05:6F:12 dhcp=no \ + gateway=10.10.10.1 gateway6="" mac-address=5C:26:FE:05:6F:11 name=veth1 +/caps-man datapath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=xs-DataPath +add bridge=Bridge-LAN client-to-client-forwarding=yes local-forwarding=yes \ + name=DataPath +/caps-man security +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=xs-Sec +add authentication-types=wpa2-psk encryption=aes-ccm group-encryption=aes-ccm \ + group-key-update=30m name=WPA2 +/caps-man configuration +add channel.band=2ghz-b/g/n country=no_country_set datapath=xs-DataPath mode=\ + ap name=xs-2G rx-chains=0,1,2,3 security=xs-Sec ssid=vados tx-chains=\ + 0,1,2,3 +add channel.band=5ghz-a/n/ac country=no_country_set datapath=xs-DataPath \ + installation=any mode=ap name=xs-5G rx-chains=0,1,2,3 security=xs-Sec \ + ssid=vados5g tx-chains=0,1,2,3 +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX .frequency=2422,2442,2462 .reselect-interval=20m country=belarus \ + datapath=DataPath datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes hw-protection-mode=rts-cts installation=any name=2G \ + rx-chains=0,1,2,3 security=WPA2 ssid=vados tx-chains=0,1,2,3 +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX .frequency=5180,5200,5220,5240,5260 .reselect-interval=20m \ + .skip-dfs-channels=yes country=belarus datapath=DataPath \ + datapath.client-to-client-forwarding=yes .local-forwarding=yes \ + hw-protection-mode=rts-cts installation=any name=5G security=WPA2 ssid=\ + vados5g +/disk +add slot=ramstorage tmpfs-max-size=100000000 type=tmpfs +add slot=tmpfs tmpfs-max-size=715827882 type=tmpfs +/interface list +add include=dynamic,static name=LAN +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroMIC +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=P1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/app settings +set auto-update=yes disk=sata1 lan-bridge=Bridge-LAN registry-mirrors="https:/\ + /reg.vados.ru:5000/:https://reg.vados.ru/,https://registry-1.docker.io" +/caps-man aaa +set called-format=ssid +/caps-man access-list +add action=reject allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-120..-80 ssid-regexp="" +add action=accept allow-signal-out-of-range=10s disabled=no interface=all \ + signal-range=-79..120 ssid-regexp="" +/caps-man manager +# bad package path +set ca-certificate=CAPsMAN-CA-A2A7DF3D5EE6 certificate=CAPsMAN-A2A7DF3D5EE6 \ + enabled=yes package-path=/tmpfs/capsman-packages +/caps-man manager interface +set [ find default=yes ] forbid=yes +add disabled=no interface=Bridge-LAN +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=g,gn,b \ + master-configuration=2G name-format=prefix-identity name-prefix=2G +add action=create-dynamic-enabled hw-supported-modes=an,ac,a \ + master-configuration=5G name-format=prefix-identity name-prefix=5G +add action=create-dynamic-enabled disabled=yes hw-supported-modes=ac,an,a \ + master-configuration=2G name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled disabled=yes hw-supported-modes=an \ + master-configuration=5G name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/container config +set layer-dir=/sata1 registry-url=https://reg.vados.ru tmpdir=/ramstorage \ + username=amster-dev +/container envs +add key=ENV list=carkeeperbot_envs value=/root/.ashrc +add key=PATH list=carkeeperbot_envs value=\ + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +add key=PORT list=carkeeperbot_envs value="\${SSH_PORT}" +add key=SSH_PORT list=carkeeperbot_envs value=8222 +/container mounts +add dst=/app list=carkeeper_app src=/sata1/carkeeper/app +add dst=/configs list=carkeeper_configs src=/sata1/carkeeper/configs +add dst=/root/.ashrc list=carkeeper_configs/.profile src=\ + /sata1/carkeeper/configs/.profile +add dst=/etc/php82/php.ini list=carkeeper_configs/php.ini src=\ + /sata1/carkeeper/configs/php.ini +add dst=/etc/ssh/sshd_config list=carkeeper_configs/sshd_config src=\ + /sata1/carkeeper/configs/sshd_config +add dst=/scripts list=carkeeper_scripts src=/sata1/carkeeper/scripts +add dst=/var/sync list=carkeeper_sync src=/sata1/carkeeper/sync +add dst=/var/tmp list=carkeeper_tmp src=/sata1/carkeeper/tmp +/interface bridge port +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-DOC interface=veth1 +add bridge=Bridge-LAN interface=LAN +add bridge=Bridge-LAN interface=dynamic +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes +/interface detect-internet +set detect-interface-list=LAN internet-interface-list=LAN lan-interface-list=\ + LAN wan-interface-list=LAN +/interface wifi capsman +set package-path=/tmpfs/capsman-packages upgrade-policy=none +/ip address +add address=10.30.30.10/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.10.10.1/24 interface=Bridge-DOC network=10.10.10.0 +add address=172.18.20.5/30 interface=docker-xray-vless-veth network=\ + 172.18.20.4 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set disabled=yes interface=Bridge-LAN \ + lease-script=lease-script lease-time=10m name=nucDHCP server-address=\ + 10.30.30.10 +/ip dns +set doh-max-concurrent-queries=100 doh-max-server-connections=20 servers=\ + 10.30.30.81 verify-doh-cert=yes +/ip firewall filter +add action=accept chain=input +add action=accept chain=output +add action=accept chain=forward comment="Comment of the rule" disabled=yes +/ip firewall mangle +# docker-xray-vless-veth not ready +add action=change-mss chain=forward new-mss=1360 out-interface=\ + docker-xray-vless-veth protocol=tcp tcp-flags=syn tcp-mss=1420-65535 +/ip firewall nat +# docker-xray-vless-veth not ready +add action=masquerade chain=srcnat out-interface=docker-xray-vless-veth +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip route +add disabled=no dst-address=0.0.0.0/0 gateway=10.30.30.81 routing-table=main +/ip service +set ftp disabled=yes +set www disabled=yes +set ssh port=2222 +set www-ssl port=4443 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set allow-disable-external-interface=yes enabled=yes +/ipv6 firewall address-list +add address=2400:cb00::/32 list=CLOUDFLARE-IP-Address +add address=2606:4700::/32 list=CLOUDFLARE-IP-Address +add address=2803:f800::/32 list=CLOUDFLARE-IP-Address +add address=2405:b500::/32 list=CLOUDFLARE-IP-Address +add address=2405:8100::/32 list=CLOUDFLARE-IP-Address +add address=2a06:98c0::/29 list=CLOUDFLARE-IP-Address +add address=2c0f:f248::/32 list=CLOUDFLARE-IP-Address +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroNUC +/system note +set show-at-login=no +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes +/system ntp client servers +add address=10.30.30.81 +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +/system scheduler +add comment="Backup Every Week" interval=1w name=BackupEveryWeek on-event=\ + "/system/script { run BackupAndUpdate; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=04:41:27 +add comment="Setup Global Environment for scripts" name=Amster-SetGlobalEnv \ + on-event=\ + "/system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + Amster-GetInstallUpdate on-event=":global getInstUpd; \$getInstUpd;" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add dont-require-permissions=no name=test owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n#:local ScriptName [ :jobname ];\r\ + \n:local expSrc;\r\ + \n:local FileName;\r\ + \n:local FilePath;\r\ + \n:local DirPath \"tmpfs/\";\r\ + \n:global WaitForFile;\r\ + \n:global IfThenElse;\r\ + \n\r\ + \n:foreach Script in=([ /system/script find where name~\"Amster-GlobalConf\ + *\" ]) do={\r\ + \n:local ScriptVal [ /system/script/get \$Script ];\r\ + \n\r\ + \n:local expName [ (\$ScriptVal->\"name\") ];\r\ + \n#[/system/script get \$expScript name];\r\ + \n:delay 2s;\r\ + \n\r\ + \n:set expSrc [/system/script print where name=\$expName];\r\ + \n/system/script print where name=\$expName;\r\ + \n#[:put [/system/script get \$expScript source]];\r\ + \n:put [\$expSrc];\r\ + \n:delay 2s;\r\ + \n:set FileName \$expName;\r\ + \n:set FilePath (\$DirPath . \$FileName);\r\ + \n\r\ + \n#:log warning \"\\n----------------------\\n\\\$expSrc = \$expSrc\\n____\ + ______________________________\";\r\ + \n:log info \"\\n\\\$FileName = '\$FileName'\";\r\ + \n:log info \"\\n\\\$FilePath = \$FilePath\";\r\ + \n#:log warning {/system/script/get source=[/system/script/get \$expScript\ + \_source];};\r\ + \n\r\ + \n#\$[/system script get [/system script find name=\"\$FileName\"] source]\ + \r\ + \n\r\ + \n#:local gettingScript \"\$FileName\";\r\ + \n#:execute script=\"[[:parse \\\"[:parse { :put (\"\$[/system script get \ + [/system script find name=\$FileName] source]\"); } \\\"]]\"; \\\r\ + \n\r\ + \n#:execute script={:put \"[:parse \\\"[:parse [/system/script get [/syste\ + m/script find name=\$gettingScript] source];\\\"]]\";} \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n:do {\r\ + \n:local fName (\$FilePath . \".rsc\");\r\ + \n#:delay 3s;\r\ + \n#/file add name=\$fName;\r\ + \n:put [:tostr [\$expSrc]];\r\ + \n/file set \$fName contents=[:put [\$expSrc]];\r\ + \n:delay 3s;\r\ + \n\$WaitForFile \$fName;\r\ + \n(\$FilePath . \".rsc\");\r\ + \n#:delay 2s;\r\ + \n\r\ + \n} on-error={\r\ + \n:log error \"\\nERROR \\\$FilePath = \$FilePath\";\r\ + \n}\r\ + \n#\$WaitForFile (\$FilePath . \".rsc\");\r\ + \n#:execute script={ :put [/system/script get [:put \$FileName] source]; }\ + ;\r\ + \n#/system/script export \$Sscript file=\$FilePath;\r\ + \n#/system/script/export [:put [/system/script/get \$expScript source]] fi\ + le=\$FilePath;\r\ + \n#:execute script={ :put [/system/script/get \$expScript source]; } \\\r\ + \n\r\ + \n#:log warning \"\\n\\\$expScript = \$expScript\";\r\ + \n# \\\r\ + \n# file=(\$FilePath . \".rsc\\00\");\r\ + \n#script={:put [/system/script/get \$FileName source];} file=(\$FilePath\ + \_. \".rsc\\00\");\r\ + \n#/system script export \$src file=(\$FilePath . \$FileName);\r\ + \n}\r\ + \n\r\ + \n:log warning \"\\nComplete!\";\r\ + \n\r\ + \n # :execute script={ :put [ /system/script/get Amster-GlobalConfig sou\ + rce ]; } \\\r\ + \n # file=(\$FilePath . \".conf\\00\");\r\ + \n # \$WaitForFile (\$FilePath . \".conf\");\r\ + \n # :onerror Err {\r\ + \n # /tool/fetch upload=yes url=(\$BackupUploadUrl . \"/\" . \$FileName\ + \_. \".conf\") \\\r\ + \n # user=\$BackupUploadUser password=\$BackupUploadPass src-path=(\ + \$FilePath . \".conf\");\r\ + \n # :set ConfigFile [ /file/get (\$FilePath . \".conf\") ];\r\ + \n # :set (\$ConfigFile->\"name\") (\$FileName . \".conf\");\r\ + \n " +add dont-require-permissions=no name=test1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#:local runningVer [:find [/system/resource/get version] \"(\"];\r\ + \n\r\ + \n:local runningChannel;\r\ + \n:local runningVersion;\r\ + \n:local ParseCustom;\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n \r\ + \n:global runningChannel [\$ParseCustom [/system/resource/get version] \"(\ + \" \")\" 1];\r\ + \n:log warning [\$runningChannel];\r\ + \n:set runningVersion [\$ParseCustom [/system/resource/get version] \" \" \ + \")\" 2];\r\ + \n:log warning [\$runningVersion];\r\ + \n\r\ + \n\r\ + \n\r\ + \n# :if ([:len \$open] = 0) do={\r\ + \n# :log error \"\$SMP Could not extract installed OS channel from vers\ + ion string: `\$runningOsAndChannel`.\";\r\ + \n# :error \"\$SMP error, check logs\";\r\ + \n# }\r\ + \n# :local rest [:pick \$runningOsAndChannel (\$open+1) [:len \$runningOs\ + AndChannel]];\r\ + \n# :local close [:find \$rest \")\"];\r\ + \n# :local channel [:pick \$rest 0 \$close];\r\ + \n# :return \$channel;\r\ + \n#}" +add dont-require-permissions=no name=01-Amster-Init-Script owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# Amster Initial Script\r\ + \n#\r\ + \n#:global GlobalEnvRemove true; /system/script {run Amster-GlobalEnvRemov\ + e; };\r\ + \n#:delay 1s;\r\ + \n:#global ReloadGlobal true; \r\ + \n\r\ + \n:global AmScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global defOwner \"vados\";\r\ + \n:global AmFirstRun;\r\ + \n\r\ + \n:set AmFirstRun do={\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n #:global ParseKeyValueStore;\r\ + \n #:local AmUpdCRLF true;\r\ + \n #:local IfThenElse;\r\ + \n #:set IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1\ + \_] = true) do={:return \$2}; :return \$3}\r\ + \n #/certificate/settings/set builtin-trust-store=fetch;\r\ + \n #/tool/fetch \"\$scriptsUrl/certs/Root-YE.pem\" dst-path=\"root-ye.p\ + em\";\r\ + \n #/certificate/import file-name=\"root-ye.pem\" passphrase=\"\";\r\ + \n # For basic verification we rename the certificate and print it by f\ + ingerprint. Make sure exactly this one certificate (\"Root-YE\") is shown.\ + \r\ + \n #/certificate/set name=\"Root-YE\" [ find where common-name=\"Root Y\ + E\" ];\r\ + \n #/certificate/print proplist=name,fingerprint where fingerprint=\"e1\ + 4ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666\";\r\ + \n #:log info \"\\nAmScriptsUrl = \$AmScriptsUrl\";\r\ + \n :local Scripts {\r\ + \n \"Amster-GlobalConfig\"\r\ + \n \"Amster-GlobalFunc\";\r\ + \n# \"Amster-SFTP-backup\"\r\ + \n# \"Amster-BkpEmail-and-upd\";\r\ + \n };\r\ + \n# /system/script/set owner=(\$ScriptVal->\"name\") \\\r\ + \n# source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRLF \$S\ + ourceNew ] \$Script;\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n /system/script { run Amster-GlobalConfig; run Amster-GlobalFunc; }\r\ + \n}\r\ + \n:global AmUpdRun;\r\ + \n:set AmUpdRun do={\r\ + \n #:local UpdScript [ :tostr \$1 ];\r\ + \n #:global ParseKeyValueStore;\r\ + \n :global AmScriptsUrl;\r\ + \n :global defOwner;\r\ + \n :local Scripts {\r\ + \n# \"Amster-GlobalConfig\"\r\ + \n# \"Amster-GlobalFunc\"\r\ + \n# \"Amster-GlobalRemove\"\r\ + \n \"Amster-backup-SFTP\"\r\ + \n \"Amster-SFTP-backup\"\r\ + \n \"Amster-BkpEmail-and-upd\"\r\ + \n \"Amster-TG-Bot\"\r\ + \n \"Amster-TG-Notification\";\r\ + \n };\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :put \"updating \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$defOwner source=([ /too\ + l/fetch (\"\$AmScriptsUrl\" . \$Script . \".rsc\") output=user as-value ]-\ + >\"data\");\r\ + \n /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$\ + Script;\r\ + \n };\r\ + \n# /system/script/add name=\$Script owner=\$AmOwner source=([ /tool/fe\ + tch check-certificate=yes-without-crl (\"\$AmScriptsUrl\" . \$Script . \".\ + rsc\") output=user as-value ]->\"data\"); };\r\ + \n}\r\ + \n\r\ + \n\$AmFirstRun;\r\ + \n#\$AmUpdRun;\r\ + \n\r\ + \n#\$setUpdExist;\r\ + \n#:global setUpdExist;\r\ + \n#:global ParseKeyValueStore;\r\ + \n#:set setUpdExist do={\r\ + \n#:do {\r\ + \n#:global ParseKeyValueStore;\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\\r\?\\n#comment=*\" ] do={\r\ + \n# :local ScriptVal [ /system/script/get \$Script ];\r\ + \n# :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"#comment\"\ + ) ];\r\ + \n# :local scriptName (\$ScriptVal->\"name\");\r\ + \n#:log warning (\"\\n\\\$scriptName = \". \$scriptName);\r\ + \n#: log warning (\"\\n\\\$ScriptInfo = \". \$ScriptInfo);\r\ + \n# }\r\ + \n#} on-error={}\r\ + \n#}\r\ + \n#\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run\ + -count;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;\r\ + \n#;(evl / (evl /docommand=;(evl / (evl /foreachcounter=\$Script;do=;(evl \ + / (evl /localname=\$ScriptVal;value=(evl (evl /system/script/getnumber=\$S\ + cript))) (evl /localname=\$ScriptInfo;value=(evl (<%% \$ParseKeyValueStore\ + \_(> \$ParseKeyValueStore);(-> \$ScriptVal comment)))) (evl /localname=\$s\ + criptName) (evl /setname=\$scriptName;value=(-> #\$ScriptVal name)) (evl /\ + log/errormessage=(. \r\ + \n# \$ ScriptInfo = \$ScriptInfo)));in=(evl (evl /system/script/findwhere\ + =\$name;\$owner;\$policy;\$dont-require-permissions;\$last-started;\$run-c\ + ount;\$source;\$invalid;\$comment;\$.id;\$.nextid;\$.dead;\$.about;(~ \$so\ + urce (. ^#!rsc by Vados \r\ + \n# \? \r\ + \n#));5))));on-error=;(evl /)))\r\ + \n" +add dont-require-permissions=no name="Download cAP's Packages" owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# +------------------------------+\r\ + \n# | |\r\ + \n# | Mikrotik RouterOS Scripts |\r\ + \n# | _Download cAP's Packages_ |\r\ + \n# | |\r\ + \n# +------------------------------+\r\ + \n# https://github.com/sebastian13/mikrotik-routeros-scripts\r\ + \n#\r\ + \n\r\ + \n# Set a directory path providing the required space\r\ + \n# Add a microSD card https://wiki.mikrotik.com/wiki/Manual:System/Disks\ + \r\ + \n# or setup a RAM-Disk via '/disk/add type=tmpfs tmpfs-max-size=20M slot=\ + ram'\r\ + \n:local dir \"/tmpfs/capsman-packages\";\r\ + \n\r\ + \n\r\ + \n# Set Package Path if required, set policy to none if using 'upgrade-cap\ + s' script\r\ + \n/interface/wifi/capsman/set package-path=\$dir upgrade-policy=none;\r\ + \n/caps-man/manager/set package-path=\$dir upgrade-policy=none;\r\ + \n#require-same-version;\r\ + \n\r\ + \n:local installed [/system package get value-name=version [find where nam\ + e=\"routeros\"]]\r\ + \n\r\ + \n# Delete old downloads\r\ + \n# /file/remove [ find type=package name~\"capsman*\" ]\r\ + \n\r\ + \n# Starting from RouterOS version 7.13, drivers for older wireless and 60\ + GHz interfaces are\r\ + \n# part of the separate \"wireless\" package. The existing \"wifiwave2\" \ + package has been divided\r\ + \n# into distinct packages: \"wifi-qcom\" and \"wifi-qcom-ac\".\r\ + \n# RouterOS >=7.12 is required to upgrade to 7.13.\r\ + \n# https://forum.mikrotik.com/viewtopic.php\?t=202423\r\ + \n\r\ + \n:foreach architecture in={ \"arm\";\r\ + \n# \"arm64\";\r\ + \n \"x86_64\";\r\ + \n \"mipsbe\"} do={\r\ + \n :foreach package in={ \"routeros\";\r\ + \n# \"wifi-qcom-ac\";\r\ + \n# \"wifi-qcom\";\r\ + \n \"wireless\"} do={ :do {\r\ + \n :put \"\"\r\ + \n :put \"Download \$package \$installed for \$architecture\"\r\ + \n /tool fetch mode=https \\\r\ + \n url=\"https://download.mikrotik.com/routeros/\$installed/\$packa\ + ge-\$installed-\$architecture.npk\" \\\r\ + \n dst-path=\"\$dir/\$package-\$installed-\$architecture.npk\"\r\ + \n } on-error={ :put \"Error downloading the file. On a 404, note t\ + hat the package may not exist for the specified architecture!\" }\r\ + \n }\r\ + \n}\r\ + \n" +add comment="Script for setup routeros scrypt system" \ + dont-require-permissions=no name=AM-setup owner=AM-setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros scrypt system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:global NewScript \"script_name\"; \r\ + \n#:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n#/system/script/add name=\$NewScript owner=\$NewScript source=([/tool/fe\ + tch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptAdd . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n#:global NewScript (a);\r\ + \n#:global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n#\r\ + \n# For run from terminal:\r\ + \n#/system/script/add name=AM-setup owner=AM-Setup source=([/tool/fetch ch\ + eck-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" outp\ + ut=user as-value ]->\"data\");\r\ + \n#\r\ + \n#:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados\ + \" ] do={\r\ + \n# if (\$ScriptUpdatesCRLF = true) do={\r\ + \n# /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$Scri\ + pt;\r\ + \n# } else={\r\ + \n# /system/script/set source=[ :tolf [ get \$Script source ] ] \$Script\ + ;\r\ + \n# }\r\ + \n#}\r\ + \n# /import verbose=no \$ScriptName\r\ + \n:global SetupScript [ :jobname ];\r\ + \n:global RemoveMe;\r\ + \n:global InitSetup true;\r\ + \n:global tmpfs true;\r\ + \n\r\ + \n{\r\ + \n :local RmMe [:tobool \$1];\r\ + \n\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global SetupScript;\r\ + \n :global RemoveMe;\r\ + \n :global InitSetup;\r\ + \n :global tmpfs;\r\ + \n \r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :if (\$SetupScript = false) do={\r\ + \n :global SetupScript \"AM-setup\";\r\ + \n }\r\ + \n :if (\$RemoveMe != false) do={\r\ + \n :set RemoveMe true;\r\ + \n }\r\ + \n\r\ + \n :log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n \r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n \r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Thr tmpfs variable is true. Checking for tmpfs/scripts director\ + y...\";\r\ + \n :if (\$tmpfs = true && [/file find name=\"tmpfs/scripts\"] != \"\") do\ + ={\r\ + \n :log debug (\$0 . \"Directory tmpfs/scripts exsist.\");\r\ + \n :return \$true;\r\ + \n } else={\r\ + \n :log error (\$0 . \"Directory tmpfs/scripts does not exsist. Remove \ + global variable tmpfs!\");\r\ + \n :global tmpfs (a);\r\ + \n return false;\r\ + \n}\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n \r\ + \n /system/script run \$Script;\r\ + \n :delay 2s;\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :if (\$RemoveMe = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :local OnEvent (\":delay 30s;\\n\" . \"/system/script/remove [ find \ + where name=\\\"\$SetupScript\\\" ];\\n\" . \\\r\ + \n \":delay 2s;\\n\" . \"/system/scheduler/remove [ find where name=\\\ + \"_RemoveSetup\\\" ];\\n\" . \\\r\ + \n \":delay 2s;\\n\" . \":global RemoveMe (a);\\n\");\r\ + \n :local Comment \"_RemoveSetup tmp scheduler for remove setup script.\ + \";\r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-\ + time=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$0 . \"\\nI've done everything, and now I'm tired..\ + . I'm leaving.\\nThere will be an error below, this is normal.\");\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :put \"Normal removing temporary global environment variables.\";\ + \r\ + \n :global SetupScript (a);\r\ + \n :global InitSetup (a);\r\ + \n :global RemoveMe (a);\r\ + \n } on-error={\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$0 . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n}\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n\r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add dont-require-permissions=yes name=MkTmpfs owner=vados policy=\ + ftp,read,write,policy,test,sniff,sensitive source=\ + ":global MkDir;\r\ + \n\r\ + \n\$MkDir /usb1/tmpfs;" +add dont-require-permissions=no name=CreateContainer owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local contIF \"veth1\";\r\ + \n:local contIP \"10.10.10.10/24\";\r\ + \n:local contGW \"10.10.10.1\";\r\ + \n#/interface/veth/add name=\$contIF address=\$contIP gateway=\$contGW;\r\ + \n:local contBridgeIF \"Bridge-DOC\";\r\ + \n:local contBridgeIP \"10.10.10.1/24\";\r\ + \n/interface/bridge/add name=\$contBridgeIF;\r\ + \n/ip/address/add address=\$contBridgeIP interface=\$contBridgeIF;\r\ + \n/interface/bridge/port/add bridge=\$contBridgeIF interface=\$contIF;\r\ + \n/container/config/set ram-high=768M registry-url=https://registry-1.dock\ + er.io tmpdir=sata1/tmp\r\ + \n" +add dont-require-permissions=no name=carkeeperbot owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + container/mounts/add list=carkeeper_configs/.profile src=sata1/carkeeper/c\ + onfigs/.profile dst=/root/.ashrc;\r\ + \n/container/mounts/add list=carkeeper_configs/php.ini src=sata1/carkeeper\ + /configs/php.ini dst=/etc/php82/php.ini;\r\ + \n#/container/mounts/add list=carkeeper_configs src=sata1/carkeeper/config\ + s dst=/configs;\r\ + \n/container/mounts/add list=carkeeper_app src=sata1/carkeeper/app dst=/ap\ + p;\r\ + \n/container/mounts/add list=carkeeper_scripts src=sata1/carkeeper/scripts\ + \_dst=/scripts;\r\ + \n/container/mounts/add list=carkeeper_configs/sshd_config src=sata1/carke\ + eper/configs/sshd_config dst=/etc/ssh/sshd_config;\r\ + \n\r\ + \n/container/mounts/add list=carkeeper_tmp src=sata1/carkeeper/tmp dst=/va\ + r/tmp;\r\ + \n/container/mounts/add list=carkeeper_sync src=sata1/carkeeper/sync dst=/\ + var/sync;\r\ + \n" +/tool e-mail +set certificate-verification=no from=MikroNUC port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add disabled=yes down-script=\ + ":local msg \"Host MikroYellow is DOWN\";\r\ + \n\$TGSendMessage \$msg;" host=10.30.30.86 http-codes="" interval=10s \ + test-script="" type=simple up-script=\ + ":global TGSendMessage;\r\ + \n\$TGSendMessage \"Host MikroYellow is UP\";" +/user aaa +set accounting=no diff --git a/MikroNUC/history/20260302/20260302230001-Diff-Config.rsc b/MikroNUC/history/20260302/20260302230001-Diff-Config.rsc new file mode 100644 index 0000000..bca875e --- /dev/null +++ b/MikroNUC/history/20260302/20260302230001-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 23:00:01 by RouterOS 7.21.1 +--- +> # 2026-03-02 22:40:01 by RouterOS 7.21.1 -- 2.52.0