$
z4G{bJ8pem1_P(wv9<)pW*HWeluuLd~-@z&H#V+~G-PXO4c_XD^VwboA{>X6X%bPAZ
zfbEP9Lvb9!X>!Y;Bba{y9saywDTJ_+E<5yidP_hUaZZ6`2rCc#kiT9Xu$DB*lr<&p
za|AbWq5*72EbU}Sizq(88NaDR2rv`e#U0aA9|m7&6a~);#jjMemk8q&o}{%jj-p_=
zr;<+Pb?=NGU+uhfJY7jPASFT?tvzp(&QVm|wDXL=sK?HryT1Pp&
zqnU^!ykZ(@1{08$3B~26gJ5A%1vg{+p|e_=*YsvzQP`qiKd;ow<0_j9A>h)WuUouc
zxPHtL`*mtyw9woHa_?8@61LCmG9{P2j9F^O^%jo?+RPe+c4|>|!yQ_3OmcdzmshAl
zj=6#Ws4TnT=z{tdw#5UW#IevmRm;N{sD26Z4gdn;P_c5}5OQ3lHL%e#d
zTJG63iP!1yqa4CnxTh{eU()5_4MEt6T(%U2QiRkc_jJc;C|jC^6YjNXI18OYADZ*pzSH$3H`HXN-E)?!{EWsku53?H)`#G
zEn#^=jDu6_Yu3^>Z#3NR$q&hIO0>-lH5TykNBhM;GiypLVH8ODMzQDQ1>B7(iG-0r
zS~n9ppN~H}oIO<~l9ykf+L|*fn>-RP;RLSAnL;SD5o9a+Rjs)1cSSV*pcnLN5j4N=
z?Wcd4EhCNs_iAAgf>oYHJfsIjtjwET>v1|v2AK783F{vRH#_0os$|rND8PYqsUiXw
z2rp$5S|IA{sm|zMQ;sp5p%?WC9Pbs>imXwK^2a{rk9nXG){hWhZ9cDoM|oc4RWO@w
zpdLB&V0$7^6Z_~4jIR3u(d|n%=?f%yC`C;o-pg*^
zH6NHV-kvqTr9dB!v7)NWI%mnQ&Sgfd%&a0IFdx6wM}?&*;Gwgs#
zu2%%U&?{RGFVw|fT}H8-G4_S&AUn-kYP1ll&NhGAEdspOa+mx&8!LJ{m4qf<1hWzv
zOC9Sl(q*UF?X$?h&vQ-@%7oWv#J4Y234eTqZu&F)4UG9Z%K|gx$9P1!D7<$q9tm%U
z9$JpW2uF$?%elg0VMrJJ7z1-}K>KwTJ@M1KQ(uBsO}u(*d61_E8daway#EB~
zR9|hPXbXjCff?SK`WX-QN<4zcD=K)`Q4fj8y_Ygn!dJwY`^Q;@pj!>29seujjISC%
ziyNK2qHf7fYifEXbSHT%H=M()R41Z&vMS`m9Xs5;f_
zVtG@h=iR(#mJg_(cyI5}I~h$QvP!qCnaUOdIIH&HtE6UTDeRBr$=_){w}8o~C8Xxk
z;!C+AV1rJPOzRGeP7P|nmp3HrCOcZ2ZF#cQcuj9eJzqti;7ibW^rMJ*r*<<-A*9K|
zC2hu42^HvWJH*X7m4#>o&_Y_)RLAx-K}A?P{=yNGNRE92f(bx0SsdpS{id@52qE)03B56pfxVjoev3w
ztZ}~0&MD~Ly+R@o*V6NcjuD5e^S56>WI8{$iQE6EBYeB{SJ~(HUa$oouWCNM2C`hO
z{lrCFN&gV@!TP;ISUF%+UaNT@%PO*aUF@nsWXg$LJ&p(=>rAwwt(CdZxD#GLT*jL^
zNb({DJI{EvWqCWo32NHxzRO4+t_TOkA`k0`!0?RbhMJb<^s{(lu|yKp(kWzrGcA<^
zZv*5Uc+nHY#WAW;y@AAMsy2Y%yeA)wPzr^W*|E6AE4o+PT@>t>VhHV{%#^%vKZxM2
zwQo}swE;*i#a^RcDZQIwG!p8&GJGt(Cz%`<6h18fkVBg86L;i|-1Jt5)wuWTTY4OD
z8fRrLiCZS2&PtQhN&Z9&7_nnic$iD*4{j!pl1`kA&yT$J()5*;f=|ef?WYpndODr`YJ$eE
zZ4=rbXA)TL4t0}SZSCH(Y@^P$5m{`bhJKG>9(-TxY_rE+hnQY$-GVz{a(iJkY(s_C
zbA?yQ_>G^PsVqPLXYz!_H?`f^{WvRE|Ll93HCOD`TJ_#)3915n)}6JShwku*xao;M
zz0CFB{lE1vBjo3*sb8=wsJ~rfJDbfL#IKEN;jAavT5cCmVnk*olxZAne@fgz(^WLg
zPy?UhWcAVo$Dd^*RSv^gt}CoOuia
zCa=4*&Na>=G7N;*(QhrMVp-0Dm;aFo&zsk_Gm~GKN~)=+oK@A*UZ!Yb=&Gz*HU}M}
z>CTQ@^R2qRz@75eG=Ff`u$osUh;)Kl#z
zx8C`Q0h)6$&lv2WNrU2K5^A{%&Um{{pq%9e|I`m1cwfsH+va%cD4lU94tpjT)H6x>
z@?|J!DX2DL9V1Ph(!a%_-%*+~WnU&}Nha~qL}W-YEmuWWE&a>r^u`f6uPJ>iF{@JH
za^)J<_YM+7#kP?Ob!_{6mWAtkXR>Dpt$gn~Ge#Ot&4+
zZz3u;vO>ivnPS@mdZENArF&nxhQ(^ls2GKy;n<70u?ZUV16qEstPnf^7sd~(T#^l@UofCi<}
z$bXh7$j?gNf6v6Dn>A&nkMxWxqyL({5-*LVRzejpi|sU+xDzcUve~+9meLhHHRIzL
zyhbbecC&aMI_q9cZDdJQw`RJEDZOzyrW_<;TwEfQbLg|-sWbjz)z3J{L*&m2b)&LP
zN?jXtsq;_-W1bBSan7??@;^%WM_UoyX6YHF5G(>|hsAL2b^r5EA)FZ=BG`>aHduY;
zDUSVn+~C!7tfpD2&_PB13cZKs(rMya$MBw1WNKFSO$R~$ItP?fPlz#Gd{=Yhwl1x^
zd`QO>UVH&%61v$9-U#b-6xrW-TtnbmSY&}p=^ECqZJ$!|<(^Wy4xNofoENovPIfsNAZmdZ2pIysiVOx>1r=y5!DTawuyg
zY3^5iTtllfDqci2b189bHy~=3rnm^yp>Fc|Eg#Bc2{1HtR%2~M&x_|G!;amfeLfz&
z=g{~KU)s!Iv4JUH^?dSh6o70>^4AE7h77yp7eAO2>D2Q+|Hed&GGGLFv%T{LVQT`;
zg5Sj7^tO=)`X*&J|{+S$J3f*aAtDaus9R#@~oGKI$S1aJK)jYZBi
z+*Ov~0~o_DHW6Jas0mHw>*~$Wty~OL{BjT7*)k}u`!6qVH)NST?_qhXg!pev2`5kdkNj^q^S@zwWi+UR!6Gst4;i>Bf|pXG
zyko_lodW=4x{q-nvZOj0g|}ef-ZYG;Cx1bJ9#ISma0)fYfjSOCaCYS(>y>olv0vmx
ze*67dZrjWfou1`I^rwOEl<}I*@}JH147xRa9Zkz6%)ioq>>HnrUOo5y-l=0Hv9e44
z*fZc+v1|HO~zoz=k9PH!xiSjpPPA*7T
z{mKEgL>u|lk&0q32{i%BN?SQ}m#Hea$(3)8HNg?3W5y(vs1n;e66foeFvi>BOOnlc
zxO~RuOM2wPygJ^@s#Wwis26K}NidXSPgC_z|4AzjrB_IrsG11lB3LO#DS!o4#`4Lg
z#4IGa4I0t|Vdvd790G6ZowHhx+F#YGs$(A1%0+xsIN8m5TT|xH#GAFvc=sACc%X>d
z*J?FkWLqI&V$?&0K0JF)(xdo;kbdM2E2GX{qx!}W11hWM{d&U=u)=a(-}1rVpG?3gJkF&8QNgM_#A1W!gj2TPxGF4z9mmn
zbw|`l$DZ38`($Hgu~+|QHuv~35LGi|gFAz=0j4>6z85Vzri!ZYs>@mwu3xW5
z8JP`{k3#_c){LEwOAKz-2q(dWvM$B4)#uBMw-flmZRE>+vjt>B5Nb7^aiy9kwn{Pi
zkKfgr!3IS7Dg8v$p}x~~N$grSJ3MJN^XEPMVFU-9a*(>!uTf55{~`FcOKTv4gW6au
zl8v;4ef06k{(^@Dz~057t|hNqjxZ8Zn5$BE^;h{2X>cyw3Z{aBmV
z+T5FFqYUtKFSdx>ZGe-Ydj?6DK6FF%g%^A|#^6~ZyY<}P-$5&@*J7iDKik7mL&6TR
z6NYv7rs~PcI1e%g{PesB>tSu=pIxkCunvxV9~NF~v4zO5keqmKTXYG#5y65nZ)_C%
zv=-27bS(=VQN%}9#V%OKgP8jnpWI87GIc7=;i2-vK^452lnpc`T9bz21Dk
z15(CAymZ+&u0;5M8S8UdUkL6C!rh@h)n>4tCNinl-9E_SWDZ9rdPm#`@0~svMvlS%
z&x4B52T0Q3fP|UQ3A}f;9}&E-ByFhnq(3yNSg?tL{^;E+8yGTNKkY!Gj;R~Dch~H8
z#widT@Z?@@(P))!ymfuyI_P|mquS1Z0{8{E5U90EH#3c&TkK9-Os7K2;gI4@>s?A+
z!+ni79^NMSNDY>)1r6WtzbSx|ZZ1tED-S2+S&QLBl!r4oQ64o+?W_}8b2=)WuXjd^
z#OUVl%AnR-h!H!#EjHBRY!M<{b+u;yT*-%yyu_24O3b;QduU4^)KscIpT}j
zRFomT1Z1*-fw0MPmMUYYYR0X9Gs0wNkoUPYi1qk&@qz$22pmm0y7r8o(W`115l3gN(WZc~;^Y&lL&
z;!Y^p4sCxG6BmWMn~jtZyqfu~^b<1UCa*8cpyRZ02y17p+q=(XzE*Od0*NJp#K(jX
zS1BQNh(hDS(#U89cO_OOa`}oakt+_?)vV@_~?3On8b
z=nB2xr+iUkoXfjZ3I5JS^p3E=3z&US{c^hiWWBN2Lo9nHdAB%?DIt{wcV!Iy{Mswg
znSK7ss&67r3Nt3i{MZqm(R{TQqw7!52kV5lBEoYY49W@EoDJWjGlYo`M&7h^3ThUoGsR8bTmK4v
zi@I=LJ82AUX-tMq8vY6ZYlU9Gwajr?u?a*KMaIRxrmAjW8l0X3@Z-rr%L^^HMAhc!
zcbAyz*-?F*7*-{i9@_|r{aylGa()
zj&2`(*~O;`xJT&kChw$QDb`+yDD`ZX)O~n4QNw{#b$a_AA}WTui2Mzu!G(`Ks9yH&
z*252Ed*$B)pKqV(J8K#krS&UxIK4%fmk4e=HbPj%U!YIw{6@f#j#L(cINnGmIKSI4
zKs=4(w{(tFHV_RWrK40`uYdwW?c(L}@75knTV1t@KmwyR?
z9CA(4Ipc83*YdrLF`d~^+OY1BUUgjWKAA9#Bg_xvl1W2n67>wtI^UG7<-d*LC9;K0
zz1d@6CyeY~I4?xd98?I&M?O+9JbCiSQf-$0(31RhVGU7q$YV*aZ#qo(?xZsZ@XTOcSphqH`Y}rD#sVT
zIY^j$Dsgb@>wkFVtrsIF+r+?pwt3Ly6AJ`ezdmk($Ip(_5~=H>T=M|7HrLi4$A4i^
z(&>hgP{~Z-E?TF;0lk0&n#)EcGrghrs%F~y`@BExaIS`IYguI0T!=_^OR9~#ZLsUL
zu?gI`z8qEshi1lSUl8{{9>|Z(vCQDpLWkC=ryeVhH!aQU?O|ED#5SDYF@p#SOWX>5
z9=9ehNj}?dV)@G7!}}h-cOZrI3tmw7!fOwyElQ>`h1UT8Ek~=VoZc|sX=D9EBO9&WIPxCSH#Zj
zB1ATGx}_xiKfCDx6e1hzD{0UXTQ^VNudh+qOXskc?8G+KoF%k~h?Vct83T{
zrpSzukcVJc7?YZD$?Dor2M!|lkjs%A!M7)EMJ0
z-}xl-h}zBSH9nx*kZW&qR;TL5qEQ3z)wkB`mDhFK(Z}xr;FeFLpDNh7kv_+}SI{F-
znsxq}2RfvsmlyBVyR*|skv@kXgb?7n|A(xYnCBu_xXXOpoCp=MO)?ZISDGT^p-^>I69>ZYD;5oDM`J?XgIR
zpqc65dPUYKe?&7?tx-uxREEB31|vIv`|3<9daqyC3?ed{>QrVmZ6oJ|Ni7@Uv1cE?
zmCXcN>e{kkvcDD=<21lOX=$?R-S0l_Ts&^*7$vB#
z?^pNynI2kDO?iI|qhQQJUi`GVf-A9q3CS@kSTWB=0ti$g;r5~O=jeWu+_s?2oJ?6^P?L!n!akQPkBs+<2#Be~8@wHt?@QS7lOd@IOGq&5mV$B#GV5bG+
zm?pUvR#89$jz;zgdHSEMK%h6*7>Svl5749v`JH`l0JnP|ziu&9SR&Wro#_J%sY2v!
zLs43t1mNhOR{Xf4NOqJsV-dVxGKLoN^@Sw-w&`5@RSw0l`R2>yOJYWQmk;V7#p`n+
z-Em@XsDbB!%)S$ktz9nD5yid$D{c+)JZ38^1}2(PawJk5j#tR|kG{z;wy!CIyctw9
zQe@o{?_Bpg2UHs&<(;j_Fy!-G#fbX{URA8VhTO*)XP0RD5-&Ia_#~ZvtcS2^t2RR2
zHivBtnW$`-LEYt0h?z6R_-WigKcnU4Ta-ER=Ytn#UgqJ#HH{mJ#_{-(g9tdGWDOyt
z@=b|D6(90uVrTRhnGa^Ix5!k=6$t&TZ_0fGOPWEMBAF4d($vtYYJv^fCi}QJt
zZ32092{n_eGHu-NDcefneS4{?$?R=hwJd+}Q(4r9=L+v$${DNFyV1e!6RUf
z_u-AVzbKYIk`WE}M$7Pq-ni=f0YWV-pScVkP`|Cg$jUZ-cWwGsJvT*R7?lbTONMdC
zb9wpG8z->3*DXz*KY1TKHYj`xasz?7tW9LPi-pL6x;W>rUhqx9v&iyOv-LMVS+r(?
zX}uqIc&988F$qzq2rCeT(FI!D0t=c!sHZt{I$>Uq$H2P~J|U$$c1U3}XjE7zc6i(7
zQQJcs@rr((5KF&}YT{9>6RI#f6&d>U(a;Ztinem}TboNzM#YhXM3Sb(YqN@fm!+$l
zhJ;O%WAKl>ATK)WEo;OolD{qR-4oQO(G|paC98g{$?
zr|}s7*V=nVHPJIak`}bLI{>(ntE~m_dFf;q?tCfduPGhx(!f8&H9d`(leD~<_
z#IH!~_Yj_Ob3FovYBEDkw3xQ;p=cjZ@8{Xy^D3Z1&}(2BxUTB7kk!x%-G6Zs$Fgz0
zfTbFIbj~>u=i)a%c)mlsH{*rZV|mE=CG>P@_m~Jsi>48csJ#jP0xSixhjMh>Q-Beu8uhWfQ~02V9>v$QlHQ47u|ANDm$FY!1XR1+w`NHEgW17SQZ75f`c?
z*{YwqW^F1sHA1f0o^@O0W=~8-L&|8c#nA9S=#P6z0Xq=P8~>W7zD>9A(-qkMh%k?T
z>r~1UthwBtlU!FoQ$l+Hp?r}bob3q
zIiQr=H(5GMcWBxRZ8x;S(|xuV&IOdq70h!Dm`XW27X+6f`Of%nTIaa#CW?uC#PnSP9%Bx43C$e9lZSO#X;=^<
zY^`{WtAUS4d^!>4l~2agHR`It5yEaNQhIG783PotiSPp@l758;m%0^+s*lddFADOS
z5bOld1-+85wwQI^!mj&tf!J~XaT9Zn;KUxFHBZ;4@F2oqP$Q5nrPji?NO=%kNr3jm
z(b+Hynga
z=Ew-i@^I=xqZtt0AywDDDf;D8ub#o9y-)h?^
z*%PL~N8sr(k%5TZg7MAn0cA}VlHJ+o9v>5)Cz6dKM=P2FMv4}wun7A^*vSpnSWNL0>zjsK}bBc$7_Hpcn2T_(gfiKtRREc1i6ka*lVK(B^}j)+xp
zRjwea)Df8IXfkAkT#mIo>rJwq_A*DT
z5-%x~@o->qp`?KZX2(3mkEx+lxrrSf&CD*X34(t>D{~UAv2MoFDk4?ZP{iQAmSU|l
z-JBiJu;RVvJMrrPgaaW$kJsNV5Z60QCUA^^Eos?J<2>nL1=I6&EGTNR<=^?tQ
z_v)jJVEpSFz^6zJRsB^ALo=nJ19-ZGSt+kmIyiyfbIY)_5em!+4G_*kl`<-5{wAVi
z4#*PI8HkE<%_CkC9C7WfNHFdyn2oznW^6zUOarktJ>7$3QyS0uv9vQnNs
zeWx#!UC-X?a4q?DQAk=YgdA@m!}_BlFt&c;b;f<7KuKxJK^GH{sw=(
zk~&K!ZUh{QJW^Vz!i
z%`O3@8|TX}k&9Dmze^6?fnpwf`DFBREpzavJ~f$+u~9%x6Kf{IT`6gPB=_-`Gxs@f
zjU>?NG^J#bi10|eoy3r}i+(ku_A-zdB@e9(U1+w0os93xa=ngz5`Tr}b2|z8RW49r
zZ$tU2>3SQbWSgj-+L67zH(>8D_+aop84ha)(7PBINwN#|bocPc0H^$|SDL
z^uBQIxhMC4y3h!Q31|@^4rM#!^j=ew-j9aFdrcL&t6`Y@LfKTd^qgMsIzC~=%7N>0
z-??et&UWbrVj)DM?v~Y*2z8;}35Rf_gw+6;4yfFFAJOq-Xze{UbfiT6@$3RyRe6t8
zC>wNS0eK}AmW+s8Lf}|&K2|*91zTP(Tk|U7-8CMPAXy;h
zeL&h>TiHm2uAR1bSIpLrV$t8a{?A#l#5A_`AZnjwpg2k-IiV4hOEa1Dnv)780j<^y>>y-vl%`TW$x23W)
z{X`}VrMQXh6&`&O-Bub6p@nKNLa%b4@L5M*IgSuOIUHF81ld*7-A=(d7AIqx8khSX
zQKmn2g(q?Z6-q%fz~br5Cvr;Z_b3=fuVM(L57bc
zE*tqO<(To>mmTtfF9rLU)zks~9xM
zdvuq#l2_C&%a~YnCdP*eaObu?`yam-{xjNgTxoxW0SyGEXHiiK7qh-K7VAhyFd;D<
zJBQg+Z1&!Se
z-N2FMX^1I(1?iL)Mksuk(z#*GXujHu?v4UB0fE`Kmg69$qI9lnS$o4Tb-4wQ%_4ET
ze>SyH=Mmj`yLFsWm)X5VL}l^V^@H_V)#OChzqLUpWlv#7^s$O8qK?ru7E4Y?eiZMC
zKgydNa+7!$q{iAp$+>tn1Pg9S+*W#{ZZUb*Frv(K($;Lo8c6#oEJ6Xy
z6bh&NyE);8qR6+Z=fyd8sXE_B-adNqCN_AU)BFq8Tt+lwI-!M+()h&~P(h}FQN_Eb
z_)})W6DqcFCCcup5Oa?ENjPF8Ca!3?hJkX8Z;X>%doQGU%M{L2$(8$%A$q}w#A5#I
z%%p_2lLWrJd(Z^&N$-hF-9hIHjFB{=HkLX9a==wdOZz&V`bNURDgcT6#+NKx96?K7i
zhfze8&9|AjvZV>!BSeIy{p6|*(AP%6Z2hL%0}V{nA1RELW;9srSiSv+RSs#}V{Vri
zzCv%LhE-@1h$@fkr-vX$b7`J&hR0p^`?Osjged*RY&+>ROY?4Kp*
z&%+~{D@~}GQzG%~Nl*H*m0dFW^LZ}onJravi@{X2*iyk=B3YRfzE^*KgDl!Tntt2<
znNiQB30)U>2F!M{>R2zZlbUL|%5yzE^mdK);=_U89vfRLBQ*Z{?98^uZ_*~16*W8p
za-t&Hh9g!pzI452ayZYeyB=J;SW+@|s-<7QZ&GP8e8yn+r(r(tX$@k>VWk&HEU?jG
zy-rjas%Ii0<^B6&^~x>0UV-x-?Fj`j<`3}gmi8;>Pp*SWI9JD#?<^lge|ot*5el$^
zKeu^Ukjm-+s`&fq$sWC|I=J=Y1^L11U7ukKDGd7xAm}!b5twAY$JNdK;&ntr93l4P
z5|<~C+&YHKFD+@fa6GtgPWL2A@RVjF=G5X|ffNOT1u+>@s5oA^BsUmIZn*@_UGyVbsVCxctxJe1
zL6SozVb-Cq^{P6o55(I#R*K#<+Qp}9rd)aOg$l)_ph0)Kk&+r7Y;z$yJjjtqcI)hr
zn{uu`nF_@q%qrC+^*HsYza`?g{f)?zSE4smu7-_%2mszPbG#CoS4b<7JdvtC`TH!u
zW6L1#&C8$ZB8nOj3os(B*n~KCF##&B@$iRVNFqGyg-&B;3uB%q`uTpAwDq8#6eOJ*lRm2S1G17>
zY)h5RqRnm6W*09L)nlt?C$6aeHkR4U;=#U9S6AgWm33{SFYTsrc=_7FX!%oKbse?(
z+z`Z3MO~HuRbftAWgX|zD}HvpRZ-!K!k?3EzrJtu{HGN&mDO^~VGX=~(v|JqRKFG%+>THaV(am`f9lnRsi
z&v~5hdJx}thrbJa%gDv)6VF7lOh)Y+bV+|20euQxL~XMi;%!IwPsQ_S{JFK4ZR?Gt
zC?D349MYvVT#Uq3zkQYMu+91B-mIu_Wm$nB~=5xd#X{$?S3bD=w
zEF>v}T~%puzH0thRL92T8BMUANfL$fxdLCE+pG+Ifg-Eh-vd%^`os01(X5{HL?z#c
zqU555QoQpX8bkMV+6miCE?EZ6jh(fBwn@&i#6g{~l?vt>IOyLDQ)eerdMCw%cPDjY
zeGfcEaoF+{pX&KfFpe{V>q6;+fETT0xa+*$Kah7H{OyNHTmhp71!NZ5|7I{}8_!}C
z(ywkTy20@`?=7OoJ@<;k8g)p
zEWp@WP0_h6Y3=8VF@gCqjBc`j@ekvU(shAEIHMs0?LO+8Si@#?E_dAVc+*3+DH2^4
z`J_JT6H>J7{(qj9Z!W#eyK(tXV>o)~
z-Y^%6qy24S!Ab=EJ_Wb{<&rIcb@MY~hGdi1xWH`OKyxanR~@<>_|RXsRTBm?6b2)&PoY)~Cy^>G
zQk2V{;!z8ysC*%k|tKE@U;eU9Q)qA`MW=7FL}O{cD&xeVG5S^#@Cm>i!!*
z0wosGQ*e{n)avFj_3|itX%#M!OgjAfsb`EgSkt*_jV0pyXd!Lbv-!Xc!L0Q0Io$qF
zlCBdm>aS}NNFW+yVotL=OZc=zP!zjy5O_rvep%po=|1z}QTEd1XMjG2Ow=%L{c7lZ
zV=C7$ok1HVQFTqW=E36u3oHY{87$bX3}=+*J<7-pug+ob`jp~U`AcHpdA2UZJnjiI
zTDc5QxLf6CPNkQpThQXdG3EWNt^aY#0e|%mrF-pX2{DR>FTj1+HxgFS$T&NfE3HKR
z@;Og_F$d%lkLvV1uP*f1CW$1Hef=CQXfxx9+m&co-%Ex4xp_^3>|)d=Kvo2I`0iSw
zA#HkII=7R{F^dCrRlzj}hG^+PF3YoW*Q;1p9F+X)-2PP+Bi8JE0lRxF*XFL9kG6ai
zdp-H#NN5E#*u4`O%NAI`Xy^Lw9lel?5~KEfq4e!vjqaVb6^XY+Z1S#RgTWxz!Z0y@
zhTD10dYD&31!+{P8tMn%{>a)mxr{y^4xB>RhH$biW$cM3qLap?M4!9w-}du)s$w~?
zg~1p4tPAC-z=j%I9P(VlH*Ukn>g=ZCnV=Ynl7rpC7FPD@CvvYy@@;(NRMH|K
z>z=^7KgIMhXvf8C0N?UJn)SdPBSJIAWap$wU;K|T5-M4Qg7Gb1+&tD%5z6gW_-Qss
zse1x9rT>|Jcn2HL
z+d_GWvxqjN6;C)7iAXq3sIkx|Mk_7K;b9M>4UOv?F=DLITXk1f+J!BNP^|PZFE{uk
z5xicqbAnsR#N+G_M?X5UBk9OgZXY=#b;_G6>`WinO6gUEmIy{ekkn)OOGH}3BKZPE5$WF;3D7^B8g9V@wosc&?N*YVG^Lz~wo~3h$I^1S#XMItqwI1505fR}r_6
zXw-f*k*?SGh1X%~cn+U92v?mb&yg0L=X~q6nxt6^u8HqApoh^Au8B%`s7|68!DuqU
zA=d0%7^I95*r6EtQAfAgr)N&8nQ7hXemjFiGt(H52j`ld0acHk+!fySD6qL4s*Iz2
ztPcdg9{|*=q3U^e9`do@kgKtbzV_sbaB_$E(u@bOYiKCl=99L;nz)vnM#jWDO<}k<
z?a)Udt5017A2JFiwB1YQGxg#M_pdi=3Y$Ox7Qw45+j3C#ni^4}XZN?U1Rn)?pSCxo
z!5`U%wQNNU>E8|6eV7%fo8xG$fMZ2kzbDZ%&byDKF`0kE5f;M#8dc6qJ(2~>URyMc
zU}emqW&sjr^*?XUjNFTU=OG4IEypO*E*G{`%{Oz)*ZsUo>RG$@>SybY8IbGqn1!lY
zM7kR1eAhmpVdmH9mI=@VPI*g->AFn%H`~4Gp#y^poOm^%rXO-jAPwTJ>nqwGm(RHI
ziFSvn*mYOv#lN7#CpwvDRcov$emvT1fsVZ*Xv-C?7u}SE
zAsD-3oLEG9O{+n?R0b~U*jW|VTW3nWvukUS!JNeARBo{*QfTh!iss*SkJszZ<-54i
zw^y&bl-
z+&LK4K|CBcc8dlJYvLwhS@8JS@M2cs@HN|?S7K?T=D0V3zS%O^?Rgu>nU%M!y@v~5
zRnEc-F$2;qowvSkAf_(;am0@GAtUjFqUFHj83x%;QiS?n*J?+B?JiIg_=={$OnpDZjgqX#{4EOW8
zM6dOR2C7d~O{jm9#gZA}qhg*OVpnzDe^nL692eVI{Yr6)%ABA4%ak_`xT`_Pxy$TI
zZB>Lyc>+c$6R8zmlIZJ-3a_6|XC%$$l_)
zxp78THom}sie@#Z-SanAS4e)J9{}Z-SIm_A;Ls*$c)hAOlKtPXObDMxsW~)vRO`G-
z#5Li6jMwIM?hU*nHsmA2Ak`>EC{21*Dyakhc(##W(&64LUHAzHcy@;p7lzW~P}@_e
z$S{+!=D6g5Pvh5J^)_tkO?-yL9Xb+DO!B0GZEynbs~U+(cXL*#=)%htkGkZ=ryhQ@
zI&}*D{@cI0wXy%vcA_Hc^n-&0_;!<6RBMj81ou@hI;zr63J_L@kgwdQNOk4Zt!n;a
z8~#5Cyh&OMycr`EnFxsnw|*c0q3bax;3cPKV$;D|CF*R#BOrjfp1ojv%)j
z>_j^9dgNC5+lKsa%*P#nWG8gMTV7TcbK&nY@13_IFEScc+hCY9<+ya6`6HFe%T>{i
zs031+U<`#wmfpj=&%a*vN7utJ^bU*9KRdH0VyK-Cln}Bx28HxfINI4H51Jhad!>!?
zAQ+?MP9QJsTt!=4?oAuTLTgLer_Me<9uT8WO=-B(o
z3jC#Qk|rCDWMAq2O4_mNLk8Hu_LDy9q8^{_Z0HA9FZgl*?TC4nM1i7*{O=T(^KO3J
z!{17DhVpRv4}TJz3j5M22O#Fpx)wR+WN6jw0RAp$YQHD%Zy!nCIXt)S3ySw*tz>0O
zWQE1D8GIzxMU(FwuXkW!BX;MhcbtEnmj`E`U7q;yZ074woG4z#T)Irg^5Js|t}&(1
zD4)dq-pj3(ef*dYi&e~`^*0dcnOZbj7D40lB$56G!U^_yPCSp`(@Xk`{89U)vE>a6
zJ0+Pz{_xgo3_b#?U$|1o#NAHlW`3!|f`^HN-uu&OSA1owX@5U^Lk&w!kLa85;;mV{
ze-hzN6~T?yY-CD#(|?DzrupmeS;_Synk70&&=1)x4O;S1OVL#ZpV^66cBw$V&3vme
zChM9c3p}aVT1w-NR;XD@cWAAYH3Yg(zoqF2*tvZiV~4eGs8G$A@Uizu-Q4SG3q2}r
zNe0Mb=ylS4&u*b3Q&RQzxmDlJeK}+HnnM(#wPvbBJ(x%AAK8ia1uh9P
zA%waEY~{_4mC6eU0VmABGoQ#5`*|2~{ifVcBiCPEfV@s*O4K|t@lcfF2?AdHtSk@Smaym&$+>c0j+`1XUtoF^(VE7M|E^Z#7=t
zMuot0)gx1Wl+lJW894DR=6KzOV;@X_(X`SJ&o^6+TM>h=&pCjhRf4pWG2ey$?|Xlx
zr(Tb4XHblfjC49z
z^F_UdKCAy#wGnbeq{4LiaGR~o*64vh~GSknzE%(6BP
zYNj4rnHN)F(L@)1LQ@iAl9elKa#OGSsYQTD;!}|+Buf@@wQZKudvilj;|BC?q0erSM_&0DKD+VaAjQsgzPv&zpt%>
zpJ(^yj+hr{Ai0D*fHA$PHSuqbH7bt;73~kVJPkT(<@CO6tTgW8fhd5{?0Hvqm6P^|y=*#)cV6Si*VB_}
zYz2QYq=R^SHQ#!}0aeR4&v(bpUv|&s-k37d*xEudrr+dzZnmeT8V`Ngi`Z`N;yka~
z`Q7gQU`Qza2Qy$j+(KUVEH=PA5|LzFp-WEwpHSU@0s)9o5;}ubqM`t?t&LHm$O)JN>j!-`v9AE&pO7XQ
zx8(qUfRjxp^{;&n5@l2pVbdR3TI8TLJtHG#_vSRZMyn;#sDr1G=9IrtVp;+3feEMwtlfaLn&TMl8sN@i2!)XxM1SgoN*
z=ox{UBZdoC@Mu9#5_9;e4T^1#!jO?;YuS;6)G8=m=rNdbq
zp(LcD2MYWqvlkKtsQO5!)5w9{j2xJtC;;6OnSNu00X9VtuW`V%%a{f3t|9|4Vu94L
zgW$Z}>A*0El4`UaL}})oDo>mp3W0T=DudD-yD(O5n<&SBySWxrfq8#Hwn(u9!4_oL
zMA|`+^&44$J!`o+d-BrQsll60pW0?{{wNx0H+KkEQ}!R_J6=~Um)03
zixkKIOFNQhqnvLCIohx=wA&>@-wlV$QjiylcSLbF+Clu+Eet>5fY8}+cr1v%x*=AW
z0@|)x7<%ne1Mf~5CZt8N))!=dm-`nv*d!4|%JgP&BnWn>^n_ry7`AyK)?Z<`?|7cqWfo>~PxM}+@)#1K<=g&KI_mrP^?4(m>q_v5CUCq(#yJjDh(BqB<1n*s)l
zA$~HSZro|+12=rtZ~N`Ynt^Ti0-bqIMwXMzhL!)ZXE?V;fX4HPldb1n1B~=f7$zFO
z0Z)*0SId4L*DCYk`%sF&4&>5Tu8tq
znS2N_E(jo#}&QM7X9~1!iOKO6avx5p23Ti}qVt@n1K@vL|
zZ~-bn0KIbnS(3eVuqRQn9(r0E^r?Xcs?4m>ClBe2y;<_Y#4quR_&lDW2_P$s6v4*j
z%FFj>&D`VNXp`F*zXgzlyZ|@5-n&l@Xr6{tyuR`&VN1q~1UNjR;oCtY8e(_J>
z_kR3yX9JE+a1K#~p#n(C`a%^yjyxm9>QpwWGJk=g8B~d4Mh!@@D{Fhm{`Gu7a97Ox
zv26?nD80iJiv^GBPbrZpNb*AVGX}NEK~gMtWul7Jo)^3jIAe$jya(yk4~KUikAqjy
z50Szg3qUH>2BIR0ZC$g#BFRzWXAFn03giH(6dOo2*Ay}Sem*s{de)c7w&0Us2Q-{5
zAJ~%JBQUO5k}gQ;8e6krEc)24kf
z0Ey@n3zj3n4rcpC`3fwMbP$2RQmcg6HSeaudi_A*Y*I)eYs#p4D}LCtZ7YYoubw>g
z(6mw-_!0w<_C@2b7jZx^(x4D~Tb}69;2;#)RJiF3{7oT=^iWYGI?VAkT6%BzIR^NF
zN_lx3fue@K1$(`91#BkWMjXBqm&Tf^h|xhGv35Ym$c`y|9{lZr7?XEPK<1}GWABtk
zI=oj{@B&q<=A^-4_u|5wJOZr2v*3wDV*DIawfnA?KTw{ce?K;cpQts%U*wteOpc$}
zYOPq{174rPnGNYXpknk>bhh#!(!H??WBxoBpy*R`NY_AT%N}9yU1W)>KO9Oy0Kv?y
z0B91*t&!-OB^@59n~S_VC<*c3N4fy_85^V_{f_5PS*!xeU0jHR&5PuyI=!u6P
zX@f_%P=4%wJgA6uG63#L+CbLzswqaE3l0GjwhPi|@jCTLo!gQ`{+*BDrfbh33byUg
zaw)bN>_%2Kc3a7q*fr~mJUVuRhe)O$yxA0DuE9Ek8ut$$p|g&lX~RAzw&xy&=HeY|
z!r(C}uQ^bN?+i%wf>;b1(O*l1;CZTuK7Ks`QA=&)D0E*DLFLOF01Ry17HGAQbEv6%
zKL=XtPiq9k-O-XBA=*KW-JW&^q8^Hopv^LrAHmg5UV_Pc@zq%VH88m^#*4U+ChS%O
zHI@vtvMk=EnppD6fw=12s)R2YSAg2<$!`HGtq&Zo#*1Wlb-DGxLL)aZz(PK4E;4T2
z0wSNcgBp={3R?2q8G*=%J%ukRRYl`(G|@r7Nru7aV~s?Ycq=-F@J~x>9sz#`1CUKw
z7r%jv^c|FsYS-^b&VOYOQ50A^`5dDG&(W}IHkWUy}=!|
zH7rX^DKF*j#^8M`qw#Jtq>&C3ATTg1L}cpB0UN5?l17_NDFcdJhUpO`kelkD&^KWX
z1d}bxF=7||#M_~#WBwn2-SImlknjXm$aLp81t9+ME#N7$CB_Bpg0OI*wgwJ-tV$vGK?Bk5Hx;hK!AdWZGHxnq{EJlv
zv@F-63wCBwIT-ig6F(!=h*@JWZ4@mbK_iN{z0>eLlkMe9%%CToL7w6ReFn~3^WRKlAk;m^)WBa3%FMU0LUHwIDwF_c1I%07Up}3Vo(Tu-CLi1+!YA!RjJ4g{J@7
z+MCO9fW@sb
zpkMPc!kj?-PDd^Ya^QL?F*dhU+g@4p2N?=0<4uB$ZG|F=*&@VISg(CnpxE_O0eNq3
zD>VK!2QMS|MY(Z5MgoZ)^|yw=Y2lQ#vr@BBK9)9}jnmOSS%T^bGS6v4&T76Y!dWAv
zeVm8usl5R!{cGNM?W=jiBG^Rt$CUB~o0-u-<`l&+rF>?mnGv?a<95xG+KPie$QT8y
zlEb@U*kOX2o0$mq`!(_i!;HWLe35fvG_dX#hhSHqp)xGL+o7=pd=A8>#_A`*AI?o#
zgP^=5Qo$gokM1)iG-=&nibE)9Dh^r?vw
zs!Wd_kF-rpZzwEM7DJ{lAHBT}%@y?9;(tPilRRG(YIpuSWL+u(EE*eiher}^7vJ3j
zT5E*sx}ch4x)wldhZHYMVl?yY5|ay{UtE^s8_ASoeCUY8K6q>2i0`*zBVhsL`C>(_
z)!uSoO+-|)8H0<3-rj?xL<$EMkSj%ZqW~769hrByilV0)7QouZRH%&|Cnz~qP!Qko
z^mYxHh4khsGv;hRtpf0<#Jyk%1Q1j{O(k-X*MLdy{Tx#$kUM2$?_#C;cAb6_smtxZMk42sa0;i`Dy<>eVJ)k&k%#a<<@A0aS
z0r0G@%(zij)%QHy-a`tswL4B*KmB7mMSG(Q06ty2{h*5NvA|sj
zzK?=yqj`^g%-kyq@Gw*rrn`_&sfg@
zSebW3i1!b*dFuAnet8EhktW#fV5F}V34IgiWhU0Y}3EqvHWWs)1AKGzrfb7
zF;heV_%FWZwwV2^#X
z9~SYshTRFp{dj-^4lm<`1|-vewRW&q$*wbdMgsWZ9qpa0XLT8~4fYLUO}+_)o@EzoqVHU&aamtGac^c9)t!peVBGdoX$jMdm;QsVQ&iJVjzE$Jpd-l9-zhL`+3bA6Qq8I#lmBpLvhJy*
z9|Mio_KZ<|nv!BSJ@CK$;QOzzBmVO}>yV2o|KEQI|BvE~U13l8Hy*_A%Vy3Z=>Kk7
Z1F+}O*)YkvJ?4M@+UojhRVubo{~xdJ_5=U`
literal 0
HcmV?d00001
diff --git a/sunshine/nvhttp.cpp b/sunshine/nvhttp.cpp
index f167778a..28ecb8ea 100644
--- a/sunshine/nvhttp.cpp
+++ b/sunshine/nvhttp.cpp
@@ -761,12 +761,39 @@ void cancel(resp_https_t response, req_https_t request) {
}
}
+#define CHECK_EXPECTED_EXTENTIONS(extention) (extention == "png" || extention == "jpg" || extention == "jpeg")
+
void appasset(resp_https_t response, req_https_t request) {
print_req(request);
- std::ifstream in(SUNSHINE_ASSETS_DIR "/box.png");
- response->write(SimpleWeb::StatusCode::success_ok, in);
+ auto args = request->parse_query_string();
+ auto appid = util::from_view(args.at("appid")) - 1;
+ auto app_image = proc::proc.get_app_image(appid);
+
+ BOOST_LOG(debug) << "/appasset: ["sv << app_image << "] -- image"sv;
+
+ if (app_image.empty()) {
+ app_image = "steam.png";
+ }
+ auto file_path = SUNSHINE_ASSETS_DIR "/" + app_image;
+
+ BOOST_LOG(debug) << "/appasset: ["sv << file_path << "] -- image path"sv;
+ // check if files exists
+ std::error_code code;
+ auto image_extention = std::filesystem::path(file_path).extension().string();
+ image_extention = image_extention.substr(1, image_extention.length() - 1);
+ if (!std::filesystem::exists(file_path, code) || !CHECK_EXPECTED_EXTENTIONS(image_extention)) {
+ BOOST_LOG(debug) << "/appasset: ["sv << file_path << "] [extention="sv << image_extention << "] -- file not found"sv;
+ response->write(SimpleWeb::StatusCode::client_error_not_found);
+ return;
+ }
+
+ SimpleWeb::CaseInsensitiveMultimap header;
+ header.emplace("Content-Type", "image/" + image_extention);
+ std::ifstream in(file_path);
+ response->write(SimpleWeb::StatusCode::success_ok, in, header);
response->close_connection_after_response = true;
+ BOOST_LOG(debug) << "/appasset: ["sv << file_path << "] [extention="sv << image_extention << "] -- sent"sv;
}
void start() {
diff --git a/sunshine/process.cpp b/sunshine/process.cpp
index f68593c0..2215fa5b 100644
--- a/sunshine/process.cpp
+++ b/sunshine/process.cpp
@@ -189,6 +189,14 @@ std::vector &proc_t::get_apps() {
return _apps;
}
+std::string proc_t::get_app_image(int app_id) {
+ if(app_id < 0 || app_id >= _apps.size()) {
+ BOOST_LOG(error) << "Couldn't find app with ID ["sv << app_id << ']';
+ return {};
+ }
+ return _apps[app_id].image;
+}
+
proc_t::~proc_t() {
terminate();
}
@@ -279,6 +287,7 @@ std::optional parse(const std::string &file_name) {
auto output = app_node.get_optional("output"s);
auto name = parse_env_val(this_env, app_node.get("name"s));
auto cmd = app_node.get_optional("cmd"s);
+ auto image = app_node.get_optional("image"s);
auto working_dir = app_node.get_optional("working-dir"s);
std::vector prep_cmds;
@@ -321,6 +330,10 @@ std::optional parse(const std::string &file_name) {
ctx.working_dir = parse_env_val(this_env, *working_dir);
}
+ if (image) {
+ ctx.image = parse_env_val(this_env, *image);
+ }
+
ctx.name = std::move(name);
ctx.prep_cmds = std::move(prep_cmds);
ctx.detached = std::move(detached);
diff --git a/sunshine/process.h b/sunshine/process.h
index 86016b64..b45e0c04 100644
--- a/sunshine/process.h
+++ b/sunshine/process.h
@@ -55,6 +55,7 @@ struct ctx_t {
std::string cmd;
std::string working_dir;
std::string output;
+ std::string image;
};
class proc_t {
@@ -78,6 +79,7 @@ public:
const std::vector &get_apps() const;
std::vector &get_apps();
+ std::string get_app_image(int app_id);
void terminate();
From dd7736e806d26615900f7b0502a4be574c71cee4 Mon Sep 17 00:00:00 2001
From: Elia Zammuto
Date: Wed, 19 Jan 2022 21:27:17 +0100
Subject: [PATCH 04/35] UI Web Fixes
---
assets/web/config.html | 17 +++++++++++++++--
assets/web/header.html | 11 +++++++++++
assets/web/pin.html | 4 ++--
assets/web/welcome.html | 5 ++---
4 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/assets/web/config.html b/assets/web/config.html
index 9c33df77..39a2f58f 100644
--- a/assets/web/config.html
+++ b/assets/web/config.html
@@ -85,7 +85,7 @@
- Automatically configure port forwarding
+ Choose which type of gamepad to Emulate on the host
@@ -186,7 +186,8 @@
The display modes advertised by Sunshine