Skip to content
Snippets Groups Projects
0003-add-gluon-hoodselector-Integrate-VPN-Mode.patch 443 KiB
Newer Older
7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332
zV0+YIQdtz?)7t};&erYT>tb{WDgzW49=l4yM1b%a<bG=bv}nKtJdhv>UbHfs{_(HC
zjbqRj&0TXGV}K(Su&$6x9pP5M2+;VVC-P@CID=c4?_#hUlWG_gn$<Kz_#DDB2q%90
ztdt+~32borA)>9~sTIu=G6&`|9L@)tZjS+}m)%c3a=}Dl0B%ri4UGv*Pl-?g4Pt^Q
z&&bQlFpeR#+N!Xg<=&70EETQN&v}pB3=3Kcf=zaIvnL@OZ?JWu2k0&8k|4)@jBSqh
zMEVO(5QAq)P2LG6pl@o(xdA^kXZFxaVdFOzrDVC<H4yf}M<&#f&SVk*tOBfGzRCdn
zLRiUV*&*y$Yk)|R097yzU4UTSfeTceUuA~gvq#>?vax!q?7Nw!S0E{?$eUW+kj%{T
zL1=-CkppJ>3~#_d-)IBO0aI8Urc=CMsVu!yoE;G&U70pCud|o3uq^56K`ZdlS~r+s
z`jW3miRANW0|{yp5gK%k5C>>14U2pbU1^Yxg08e8(G*JBi6CK~;zvLzZ9_Is68``n
zp?S9W%+M3MJfu-4Ti`^l@nMG2lIU4{ta=u3L>2&n`ul5I`v7=o@Dhim^)e|~jl&hN
zm)D=pQn3neKVLsp`r>#54;wg;5bpk&zrg{j!ihf-o0zyjhdXTnFk95-w>QELhJs=k
zAIxc9XMv^k%jU~8MLmJ?ootF~Q<mYr(;@W<*IL=Uoa8}<Y5<Wnds%K20PTG52zBfg
zEBFvj4pmqpd3I%};vj&KWu{=$#&ZS{w`<#IKb5Hb>oM2g<uph-ylyf&qSCzL6FLWP
z)fzn(9uUrN*gKZ+1u7OEn1k43@2*WYB<?-52tAi;`s@7R>I6X>rioS6H%P>UmJyUN
zyrZmSm>87+^Qvb2JO-4uXI#+Wf`5Yt?@yS(fN9DGX?Nd0kuTbSEmH++N|hzW6`%~Z
z@HMyVzUUiP2L8>+QQtFt*cRJlKqjX=&N_jFssMvjBkPX9U4QA^XPN>APJ?y2*<9}#
z7-HF81qZ5u@@%1&36ntz;3k%b*Q|yX6xw7p@&ueHGWg>g2KG+?YhF39>^TCQx?sqy
zAuTtQcN5uwG|yre5rtDUh0t8Ij!_@To1!S1h@5b4uVJ>ELjnok)vUA;y20hZrsma!
zhDZle;RY>90HA)Z^*zAv@DL>V@{aLi>MDw{H>du2yqMsnTwL#BP`V)~%zwWzPuS8X
z_W{}#cOZmE>M*g;aEgSY8Yh!BbKNrYeMV@v1jp{!oVrpJdqsKxK7(CatMzU@hyMT=
zX(3YAc3tRknL(D{90uwS7-yuzdAvbr-uG`mXA}kinlNKdy_u{q8J@=BfbAyoZ|PKp
z<e;e?+n5lVG0Y-Z(<~^6CZLx>+<S^FsNC7kkg8et4ZEv#hp(XyANH+{lg!5Ogf2ch
zO2a}_eFRJrS4Mup7({kFpec<qC$h!~ayvo`9pX1FYS*wt5&*_d`A_mq=RS!AuT;C}
zHLls?1Pk)lL4tdJV&c4VR~R4t^u|nxC^Qm4qkL94`)HwoLgmx3{{Uwd?Sv!_^>>{V
z@*LzqBRim03PZfcaAPb(dx8P~0C>Mt0cmj}c0==nG6-52&}ypk5@$I;M>C?dRA&I?
z1EUN#O#(Ht2Fsi0ARW8&-Mh_`S@J<Y6Qn_mIySdq0M%Xs1WlJ&^xtTp+P~)6%s0On
zBE1KftYM~Cu>$Q@u?|0c#adw{%|`Ysrrm<1B@nIC3n5~_nFl%$oJZs1?%*)alTbk%
zRIIwa?s^)4!%1qS`!1X|N{J554tctV+!45-v<}mDgA;3zu5DJ{u{Qn7w2UevlVK1Y
z>$nm65Z8a-5@_=^BkT*&A;;(R!Ak)PV8Vpec<v}A81okVIxY5$`3AgBG*V1iuX39h
z{YYT_m9)G#A_#ibKTkNY0Ki4QM(j%qUWupZJ>^Ed_W}DPHF=6Ebp!`adlG;lW{Pm_
zh1QBs5RL_jg*)5iR{Br@g)3F?qWF#tRnQxv_7#VhHr#-aDw+)&ug(ob(Y=6bCg##G
zj%~ga+@dzM)6X46A-2K}lxhmacAH`?P)k-`)I2#b;)w>YZpa|=b&osfma<8()p(;c
zoXIqy30=a%)XRxM4Z&fZ6-%4g%ha$Z^NY%=8!M)z1r%5UG)#`2K*u0Qzs~CYrX5fs
zh*JUwlxuMxc%mI-pkQ-dVlD&=cX_ZnGNFFhP~KCi<m87FiVO~oz#)Ajyz2mwX<7gZ
zX)0yNxDY34;w_a&?hc*;Ua&(_-)(@56@cgVBHe|b+)uRtIx5Ya?h-CNU;uj8X=EhT
z5W~vG7<+6@98kWH-^3uwED(3_s5n9S2Q7hhgLHs1aD>5WBvJVU{P979uz+L)GWvLL
zIW9ysK82}6N7nt3l5!Ys?WX{MtO4&`{JiPyp-<*JD;?;aYh1^p%|kn?si-FP_ZD3!
z1kHfbp9G!N5e;NW&O(<?6F4ENY!~JK00%bLga9F2l_vBK9teoWY4_JR!WbtyffNuZ
z*3A=M>S?Kj_8@BJr{|lLb{k01u}07aVvt+`JF5xZS=@RjDZ(}-#`#=AiU8D?n{<8w
z;A1Oxp|_3%RrzuM00IO6W>0KUXB*^#1zC>R=SI2IePO+lzJITwx&;Z}8r7iw@PtT&
z*5B`b4gwHBQ@aQIoZCzo{AsUs3Fa-~5IJO_Zu6hQ4oaZ$Vi2&l;KbVxPEi6oL`fSC
zaAO_QC^cC99w(-<L0|)WZ>V}*Y?vCTM#r|U-}ZkPN1y?s?xD*a%Qb`6i~+jA_WbX;
zx{N@_Rr9-Y(Rd5vR#6M=1{|glEh+S(+7+^0vZ;j0xedA~$uzCx!3cuzRcz8kO=O-3
znjSAe=-_~={XPExLHI&VW!?0=l$Pd-UJk_)n*M42vZsg&X&0unnoXU*>8nl={^p=R
zx7E@rkdB?|{a`n9-To%)zrj#e&2I#Z0AgztxF*tj8wC&ozgVh<${58x0j={kbHHY<
zfC(?kG+S?a=)>j20RR^7&WA`2Y<n1hJD|IE&M>T&F&{hQ9clKdhQ}~&JIi^i((G6G
z%r?w}5>iR7RmC8<Qiip6)*MO;5I07P6a{|N@aTv7Iufd|HMs;LIIR;#mNfuw%QbMu
zpDaL#{$3hVh#b`vN)@OghHfY#F=YVNPUkbcV}jPwy3PpkArVr)ji`G>x=Kh18n!N#
zvtQ1KpoR+W-snS06vg<Z5Ij74>3_!s0t6O!xImxAS5&~Jt!(d2RBIgy#6Is=!5@s8
z1(YJ0L|1Yie2gtLKrYTW1f5U|K{EiCs>m9{M^|jrfbljZTwn{5jKGLb(H~o_Ah`?u
z!K25DRMDJsPVNFb+)d#`1H}D89&L?)Z%XcMe}(8$iRt|P&54N;P1Y>%DNH`u$P|l>
zO6-9QUtn3XPxKG>mahagq`eOD^Ws!S>?Ga7GFf?oI2FJJgr!I5Gzb(r(GFm>Y>?Dt
zE$I9S91r2V3)F*Pj;jO|Cc9_flwuxvqjl}p0lEN9>G-G)MwY^?7#vTPaIv-pLnvV)
zeX9JHRNh)RWGd10;xEzn1fLKe$MHHoXCQ<^7-;|i6p-rH@CGb1HCR6PlO<>`ITnWZ
z`97XR03I7mp9YKOmUuAN&XVvDQ@M*U!hjAV{{R?Qp!@~S?32y93OY4H9|!P%X?@2x
z*uG5gr2TCEeUQQkx^8qA-sk<GNP{D<?KCW7r~;2^!cjjzuk=LAkd#!QXn=Cyre>yS
zWfx$(k3i3ioCo6C`n!R{ot!WMKK62glf7%N0q!c`0ylmeqDW~y1F&wON&05HAPXU9
zr3n%IaN|M(i>wNFsXW=vm==T0_3OPi)E3agF4bweF?Q->(gqyEq7Xsr6@=t~A=K0W
zU(!=zIRGoYs)7npi-kx4H9PFFx4e~tksQ(iTB_RpR@VpSFsDYdbbXN<Fhc4>wWEDd
zQm$Kp0HZ7^u7tlfVzRVEgh;I@)gLfWP>O95cDynDhTXyug*z_Ins>HiL%Rf~$f%>F
z8iKnsFG@|)2q1LhifL6i<iH!9WbDf)?g6N3Ew`}I46?fds-2`L(j~r)N+cjO97JjA
zdI%L{4hW3uP)ZTr3o-zF=ZB$`G~*Xog}iEEULk&%$m{{qJ}ENsnq2jqm^Xh(_X~$Y
z0u73(3c#`(u>?KXN;fQ+r9BZ0cjBR32b@(lGQO9#;*{FD$hwmx_EqwQu?Mo?%{8G^
z<A}tvbz&k{NXQ|!8xw^d3X~Zj)HaEx`Y|zp=-6XXH2z|xe$aM79jDi#VF<<U!oy8(
z=1Ih9ySvGlx4mFY6L8?WDW2(5h#SInOjM*NHj>A8%zPpcKtiBsh2ElH<QoVd=$J$k
z=mQV;{{V~{PqY=^T3T`Z{Kcqj3c-%6b!B$N+<;Pidm4VB)?y8MQii99?4ADrp#CEO
zfudD!qNkV|Aj7$&S3v5GAZD(x2f7S*{FI*^@i79WGK-}*6iJTx7*gfUsTjzZ=uv7P
z_@}&vwUBNMS!B{nH$kG-f|Ex9#Z*Wq6VZ;2w9yRqAmcWhp1nWq%t$Eke)C`BHkrgS
zZp#QfHG7D~h6CHFlFHP(Fuwz!PMS$hX-dlFO#vKRf`hnp^G=f;A?w&1ak$&Y00d88
zl>J)~@tdFn1kP1NcLCiP3t9;2U#4UoP1IhxfFTJ}Yz@Z7=4x;P`2i?R6MK9|b%7&|
zu#=s-7-C#g*N7sE)Y;7lFK7v+bR~4vCCP`FQ`ElDvf_t%wH+WvvMz78_{Ln!7a8uG
zcfWQf@F-LDArBw(pfWu02n>4+(SQfmopaI+c}oa)pzi_j`4D&hOZb?)b`bM3whdGJ
znQ(-IkT?2MQ%ZLWD>%AZ5n=O3S+EcTbY<c)e;H}40iD4<rO-bZ04xBdD+msZ&{>73
z;160=oO!c7*$^SP;?&!V$7qfTMWSJ^_6QGjJAg%0CC7`8b?({G4y?8-S@xK8?gAuG
zi*>C~ywZ<sCHBDYe(F{S5)OccCp_aO3Y8XzcM;8CI`-DOBmg3?rx2cQDJEdyQ+hix
zGkP2XK&5{9nR*nXTIvJ=J~RYMI~pm6s2E=+fv_`eSio?|C*89BLO(Jd@drBC0VU2c
ziu0*;fljRCpP4Dn!KIntM$HqR9Cn_df@*c?dtTymB7x4Me#^e~b1hH;0T=WV7p9BN
zlOPfF4z1A%w>p6&OjN63Ww3WwHg%v~=R>_apEL5xz<3_@{!E0H2t;K|+z#*VQph__
zDiI;LBiGc*+(YF>kxF)&n3#}+iSt0__^UA7>qE<(`5v<L{{W;M2Rj!{?;iG_S^RL)
z0Dl-`CcEG<3C4JuyO_znqBYdC@q51_O(272W9Tgp@kit*8evm&47y8%BIybVelltM
zjHHNj0VUS+Uhh~FQ(1q&KjQ=*upDuPsX|xgN$)mR0iAyjGr#DFv}VE<1@U--jgl~R
z3{;9|*BTTEZUck(w!fH=_y83kIIFvKADFy=1n?CtL!q7b1P2f#B|o9H*e>RI5)ixW
z-B7OO)<ecaxz-DNt_j?Wa04Jvf-0c7nCom2xXA!t86q(<qJRVL7n7r7QF~tj^n+ih
z%ISPWqBsWm;n6+Zls8C+7@aBLd|_#UA5xdu;WMF~^eFCojo<ZwIt(^Rqz%{Q*EF_>
zTVB%arMid?4{YSUH2T``2j+M<1V3SRlis+HfoiTFnM+_&G?$plQ^sb?cp>RG#wxvJ
zxGDL_>b%$Zz@Pw6=~`3WOFU^oZ~#?ziRpRhqV_@t7PF`oT>*?sFN*EXuzEUAZbQ;A
zm>car#de*S2kIatqkQa-K*)pOXPDimr{~yVTlN5u{b>AX+8~?CA@BHw7{UHvkgx#{
z{w6tJ*vojx9QKam4RIm*f(<nXYU3Q_34^+6zs2Mg0suSstqUkkMcy<32?YXG5*O9L
z9Yb>G-4(nJe>g=*0{a;VY2yvtBGEBr-q1~vUR`TQfTisw_+6>|%SR0T;~GGrtZk^*
zs=K%#eu7wC4Io{LL<X~b!$X?Uy%(cdr8Kal43HfYp|7<k2t1X-#G*ac47-5*w*;Ik
zr@1rE$b;QUvPBy=q;))Da+MG=Z8qHwP~t$=lnPxtSL@+XS_GCA<741H%<<o#ATR_4
zjoh6)Z~|P~+EK^Bl7T5*!lQbEY67tY(|5fHf8~Mz0mBe}KSL&N#J$gdNT+H@n49sC
zDeoCl<qKU}5uXrYguQ|tK!wN*gZKn+e-!mBai$AF)5qWYj#c*%*ealPwwA+KXGj18
zs)n1-m^ofp1l`RPEU9-QG~krGpeXEM)OpH;A+#PkyEgVf5I7N{W}3Yh;+Rccl$(5s
z?BPD+9^i(&TD#+azUP@n05NHJI`AJrjh#4);iw0CEj<#=lW}slqXIc;#sly^1n+e@
z=}!m|K;RkkvQ)<+3<SGAM{KYa7}^*GXu{h&wyiJXo)pc>4e{OA9XJp!hREE{O|^mQ
z0RWN*4q$G+0Do`(nK?QQlr8qVuf9!!a3UC2+Fktj96Cr4$OyO4P}7T&9h5<M&^!ve
zW_8g-9++to&i3~&OAv!c6k!0p?^*iLC?H!CLa&AZJ}`&l0@}M&EmFFL2mug3b&%9B
z>4H%Fs`8pW(9IE&Bfu9_NnEoC!}?(rBMm1tG8bt?g<e<^m$nqipoYBtY=j%Fm_J=2
zI8>_itJUOPjgTMU(uF*$;qx>6P%m}U*#76`3y?4)mv{TkU?33*D5$F@u0uU(rmQr6
zSCd&`)r5()s_QJ%S>q)UFeCP89Mv-IDF;_`F7M0m&8-OsV{WHq+qt2LCqiDkPo(8*
zhQo+VO2i5gBKvTnkSKG35CWgM-TfgBP;RUqsJy52e`XJ&m@h~9SBYKj0$hngvBc?k
z8^-|-f?eOkJ=r+O06|6#_v{7nOO({aJ#@ENf0z;Y<I<vVH~JU<0PA6Q*I2`ixF`Y;
zQ0jCkrB1wHR1ygrBOa?|hORt(HDsp0cnct7Nl<jUmvID|lYn4AQD8B1`RmXrDfewz
z<#sV5isQSb{lP#aPK0(o`}wo);0Rsdwi=hU)SW>OQQbNR_e%U3#C(Zus8)hF=qjR_
zAzj_Ec+i1_5TZoWuur9~K_JlsTIfZS>-i204JYtF_F_og1RNTn{I>r9K^@ovYFi?Z
z@mx{tL6ZKpOS1C@I$*t1-xqoN?gs84+Cu=XX9^N(Dagcjnp`{#btIW01v;ZP4<Afb
z7?=XO-`d!kQHE5CL^djPrMF0j-J@nd+)oNh**AnLP5{&E_&TSGhB<&%?4a0wlELXg
zux)0RYg&^M48f@q0YPsk*c{+N)Y1O{(-=hoBWHiCp>)6jcW(H9IYA---oG9DC~Hh^
z-{t{dUAZ<pmjMM196MG9wN?PAA;W8}1x>*_Fkk`#J`E<~_S&lg%s?0tMc$Fuammz>
zucE<9wspcq4uyl1cizk)mX0q&*VUzXcpAE9paL;CfVpod$rP~!Pf@-fH=(VrkP&rJ
z_fh2Obe8}~9o8)aoq?SqWIhF3U^}7H9sz(Rx5z6ahXE0p1rQR529YMPp21+FS2s7Q
zKPF105Qga;H(E@@#t1hZtu}Wi)r4e#8D`4H@0Bn=qlq>hzO+Kh>rB|C0P|!CRvV7Y
zA`I9Rg5Hn5w^43<QYop5E}!UxYjlg@-qs>fA_&4*03)m2z-x)<%D5mckf0~6JiDE1
z;{|419cCMio`Q6LSw1d5njo9a*LRz}W-OoqNFgOJgur5!49EjWy}R)-di5X%j&TgW
z>}EJ?<E>7^U5kGV3jY8?60i$!h_mK3azJcN(D-oM+;S`c>Ma0`p#Di$8M>4n1aEzv
zO?<@{Lfcb_CLTR?#_AXXemJnBp}8eg0I|>TocsLdw44A#y0;F7Qp~dkBIW>f=FYW^
zg$p|Q&4f!&0uS>5Dz1rrMQE3Nm3;|ODX{YK{NY9r+8tVhr$EoQ5d~r(Mh@Kpcj?75
zZkzppYUG5CkmxV*yo@z{6G!k6zRQd_5)@yW9p9k%U;>c-0jxzu1nG_o20YkAi&;wx
z`p~h!Ql8}1O@2%mA(Y?Xes}v<D!mX7^1$hV3<mCuyW@i&kagzxOFh#jPT(9v+7j5d
z;oW3^&<eFZyWtNwP$ZDr?T<={T^AXl5Lpc|Uq)w2vE`Jb2CJ#2^NEtGkTY*(A&7D2
zSk)iMFaZ!D@*pRAzSTW_>_BdPZt2x^x7<|(p{42CFk~UQv!(!lZW6Dyu3a=bUJyG$
zunivr3SF2-F~Cc}VqRy%e<9+)GBK_Ah#4DD@u}y4V+O-T@za1YwT0|e(kT>1pXA)>
z+$PHx@Zao;Oh`x}zBJ&!^TQV>fIMGfm-Wlkm;~+$LKI7PK*?D{Zsx%H(XN;o-3Teq
z282B><6fr$1b$tv%Nk<%*u~VRwI_z{k#evhqS)T1OI^#UWEdK=DL|wcy9oq_>O?|r
zek?S|86xN=f5Nzm6Cf8p1WdiX>MO!X34gQ|Y8>g35<$jP5U_RL&F+N+!TE0uso)^W
zr>KRkjSyt-xw_Z;h&fYjAOQ37l#{_xzKMbE&DUWFp{T?HYMa%iz#Myfpt4L*DzLLQ
zL7;Cv^ylXB$j`!@<8%#}Z<&0ELT=#$t{AZB&zSyro{BngCg^06hr~hnmj|2%%TLam
z&n(<S?!eN2YHKB+5K?tfk=Nhit~fRo{{St&uJb*mRL<Q@wDpQBfo0J;N#Y?M6CEHP
z8t5$`nrTU%xkv<7hUt2iucdaZz#Uo!*66$*Vn8IaD2XbjPPty-Mz^k;sm?EfMd*e~
z8@NlL&`eBBf{F+Rk*HsgX;XzoHHCGdDCN{-5O2g-)N{vylnH=nMx+o=^K>{e&}c#p
z-JPG~QF`1ML#g9Y<k4%QZ5}9c&TLSBFXMoCTLVhFIc(_l9Dh>+=Gl3|Sz^R^?tb8B
z+&}|aM^3EXJ1Qap0bf-E^~6-dhpcI9jo%pdvtslm8r2VE-Vfk0dw`1HP}OeQlr(w0
zq1fB&*pTdr9-grJqmkni7fGmfp=N_`DRBKcG2qbaPKc9ZiB&QIQvU$688?M!palfn
zQ)P8`z8I+5ij7?#x@8Tg8Z2}q)Tjl~$dJI6SSEvbq<P$=F|4gF`n$`JR@w&!Gc^i3
ztL{*NOMv{r-F9H5{v7hFkk1fN4mI$pTu8)19l1RPD7|oqfDLHYJ^-c%7-iX*T)?%2
zMo>)8p%Vd&kGsRZ1UAbGKvlDNM*`?IO%7RtRuKTy6QlnC?4R~bf)+rw!{*`fzcGw_
z2EMxMu+}bRQxJ1~-2+Q|&@O87gdh|n14Bkgf}$Q;<wqmrRXtFn+D(Ya2J9Qk@6zJI
ziR@E1bZa~q5(Bwz#Rx_D^zZ~Vcc4{I)GT5Xdi@#Tp?cwu!#IY}oR{V8o?xh2Z%xJ$
ztI`{0Ctv{j)o$Y?Ti>__s8j;qH;;EVos1w$RmWc75YWH_l`FSP4jK&`$}PI3f^7iS
zFH`)4!%-vXFTd9FisAug-L*}(2gz880n;aCK@IGfdQ*VMO0NBS$L)JykKiDTSHE1x
zSj-{nDVkpw=(n&0o^?*{_7j+~+8AV+X6XvY@C%LuQt&`YMcg%3RfGYlZMmX&Y%sGC
zf{jm209o6rLVp1EW?T7$%9+uu5ic;Y@+W5)(h&O*v*F9DgA^tL9K0v~`d3UnjBYM8
z1JIC7j6b>nXD=;XU*|S9P82ksaV>nw`v@JV*{?gT59$Ghh{^=T^1GRI;Dhb`5I{b!
za@)ZIg{1WswfJEvaRqk+H%`01=QJ0>FGSG)0Gt(YjSwEi2T%!V&7Ein#J|q-T4WHa
z#KKAc0JJMDh#+Mhmg==#Q!4~jaTW+VO&rvjwGCqEh6i*Ad}zrCMu|!r#$7hS=8Og%
z1ZnSG<gfr3t(NL{rD<9jze_;BiI5@i59H!qCV@|XGj~CQVNtha168rWxI_Uh+NAu7
ziRLb3Ftn|BF0BJ-RuY#S61R8sGtCqMsIs%w;M`-}0>fTdLB2O@kuX3fRXQITo?^&{
z(jgz=?-SD?^#?xo9wU{s$Y&!;3DPFX5*tecqmlU=-s8R4Ap1e7zri;QGhC8ogMp!G
zlfwifZTh`GaxN$bds-6>9`)P;E<xt;S_L6)*0<gSLQ=pSgeeYcw<sR4*ea`Iex?$D
zQ5(13C-Z_s;zCaiDwT+~6zH%(F8T9K2ge~d%y1pIw)~7Ry%2;bE7sFf<E6sVz!dZX
zPTk+)ILIgfgYKS)tmzr9TmZD-EkkN29^z1!D7g$1qY2Zf5LS>hWwO;5E6MsfW10{y
z*DntkQ2DhvZJOb4%meuP8Uwp_9$!hqp4BF<*r8??yA%!ULqDvHPE~bQuGC-*#b7{g
zih*bp=XqlCZw!1*pig}HG9U9GcF|O48lT>2KM3sT(6Ll@jxHOLFs^-SD>kT#%bF-U
z7fT)|qkG?jx)uzt+6bk;Mmc@x1daWq)`>#6RJdY)T1JX3vtH0PCsPR}uY*%3Z4hmT
z?}4Egcxu4I=C8GG`>J5Ef)Odwp>NLdy`w-pMS(UtE>wQlgevDDH)?LJ!L4Kp5wMF3
z@la&XI+6~&*aYug^A_46ORSrWr}zq`DI5bVk0#W*Zt_41Kz2F!%Ws)r{{ZE{fA9Rz
zAW*3l>4X#nKvUNfcLdz1Nbj+GLo}ZfFg@7;tNj(i+@aA($QiIvXSr9V0(WpCh!B5M
z65({#EOkjuJ-J(i1AQ1G4QY5eJz`7J2ZkL;TH$}y1X$_m&D9&#FD0(EJPYl($mho$
zTh8>b(Gs<ggqwElZqq@l?Z>1-A_x~@0ugKg!mMbTUke8BX8p(%Kqr8v5e?KpN{2I*
zN~VW-IdJL3Qn&sINj4?q<H_+TdZ8)0KgJQIz$g`ZMWNh{Rfdm_B6d|rBfHrqB}*U?
zDZ3;GyV-(50vcS41pB7BmlJ?elZ9|XP8SGN3NI!!g%}p0NZ>Sr*R9Q`x;e1p10EkN
z0a^b54r2-e1>HrXAW5u^bVKQ~77U}aSkJgR!14!TbUjoRtiXohhJv;-HG(%!0UJMo
zg52i_5Dox@O92_Z>5_DXuiV<ZVKt{H-Vj_=GS*)=e79fbA({a1li#_1poDq|j;M>*
z+;6CWJ%k^f#FGyH0D$-(LuysECh|-8PIvB=?9DEJy0S2w#2vdKk^caOCiV45gKHHO
z32XtjHkxbtGBG%c$S?}By}YGTLiPoPAKzrmMgUcXnnf$>F-))qV64)34_)BT@(?;0
z=mcQXVORUPJAvOUXgc*qZ_4)>LI?@L2~XD{kP&t~{*M0uc2hc?0B$wVP_=8RGPW>)
zh$gDCDkA<0h=>~RmzTtv&V*1H-hvE%%a&`1DkDJHQB%v%k1*`EWGEow=Fbcu7>FBO
zJgS&u0NhsgS+2XHmlp<{ciCb^*|V&qz6%i|D1im7H$)WDP;_E#^OqEhx3~>CTZo*I
zgr(S?3si*i>y?&()pKzh4>TWuP$8|Vhedat`ITMmQ#k=)g%X%uZ&YH_s(4!ug?YLW
zR_LLHn~-vn&eBA_OqADGj<9ayGy!N+vXq-Ds>bZ|o!*tgJO2PdPgxaFtY<??#Rj5C
zssmOdI69O=0!_K9I%yAjP`#(o;5g~hP;4h|CD5&?f*{DaAZnx(<5`CgU_qfbNXN%F
zv>J5V<XKsed3vi*7rI(lx0~H?iSd&l?oDh5LqDj41iC5>ZP&Pe)0TqF0lb`hn@Q@A
zY6`j&Sum0grGF1>zs?rBAnJmL@sF252Q7r2@;rodu#!U|x=X*G=&kiK8Id0`!~{dB
zy~t}*RPoLeDg=N${KXMeUtNwrzP#plSHKrWUSpsp)j$3I^fvOsucZ^sPNn7*3Lg~K
ze8iRM2`}UTU}g?)CMWnXHIJKey)@z$f)jm!w3b%CpA?*i5#ZlXp9~^G0E1EESZ*){
zlz=nV1i*MK5na8}{keh`*oR)R;K!PMSUC{obO&jp!a%^VfDKD_=EBH~!P@YJMbZ#T
zZZ=3GT@Q>I{^mdKg9Bd@U*yek*bB=BZ-p4yF~-7UUXDXf(K_NA#0bq-c8%D1u6p(Z
zjX}^vp=Jb|0Kbu?dX+HWDgbz!y!Ais*D(TnQtH*Xf=7W*)POB0C3EArL1+N=K#)i^
zD@>6b6eA1ue;bDVaZ<<yPrkJuE9NVsltHbB>;cm%t*i)~kP<7Yn*m@AQwF_fCfg=R
zK&N3g-%QmlUTOiL`oR~z85lI&Sad>aQ6!x*t3j9cH9AgV9B(Z~=Uq`n<z6_E;^s0$
znpnofn^7ZXn5NOV8lNzzv>2%V%lNM#Gz?!IlHU!(B#4y~k@^uS)W-9a`_7m4!^tq5
zDFc9MD7L!}oZ6@MpdDZ)MFSkN!qF3bE@?=JmGiUb-Bs;8sk@cT<tuuKG$8nOtA>1?
zDvDLebiv*Cfbe=tjvSZ3bI03m@Mgk30!kuJn88lwrttPulqE-6$?2*s91tuisVa%H
zAcTC{*sj4tg&@FqP?PkpIA@iHXy)Z%(a|GDn}-a*=E(*L4B`>=%%bBvfrQ+FoisGz
z1PUc;8!CYq`H`j$C5GR*^LdkVV;O|ikLmp6vG68(^Qz9B8BK+uEx@2gB&KTagi#bj
zO1o0kh6qkDUG21>x}Ud82ps~V`8(hE*E=N#A+;p#@EM>Y0p{8z`^M40zZDLcbWhVb
z3KcYcV~q&`p>K-^@EYjB#ir(T+6s%WreF576nc^2)TypSo>0TnmFHR<>zvb4HKhEd
z^S^_TN)!>jfI4L)S9gd4xBmcio1@9No*-Iqbw_E8#a${-*EFr}fHC#aLsq^&f1la8
zH!)4xF4Ti8<C0>4bP&}r7B;gTq=0Veo{SrPiu@pKE{6KMd&O0ExI;Q12oygodw;eD
ztY{6+&~$^k%FhHmBnTZMleDwg00o`lghfPAFfUCQ5?$@~6H(rY6#!I;?416x#%c8=
zIBabaeqdK(7(uXtaTG1*IvA6vEf`iu**Irl2xHF#00GgEg$y89HJhf#I{8v6zwhDq
zId`E!9Y7&I#HM`8=HNx&ML?#l<cfl{Hc?a)lfHUT+6JH(Pc-*dUu6);sc67iuK~ry
zfOVkTW)9N?(}uS-<z7E0y1m^f22w(`1Gea81r0STy#$-fOA9SJRnZl|IGzx`#7s8Y
z%{0Lv7A1Z9%FP@pCb5Y!s^0P`3=LR7Y<XFd98|50V_OHsoo<AORXf7l>Z>8#KB%Le
z043a3x}POK$l|uiZpb>u$@Z*r{%ShXncPY4Z#20PQ4Ve*-PX+B)P&zHX0wU7B+`o4
z>^oMl*tq;H=?`W6K;af5oduO&8z4<FX=yq}H*yjm8SjvYql06gTy;Vj0AvDgTf|<l
zk8R~+2e--kTWCzWpJDkIumi+Sj##=OvhVsfKGI_8(q>xl=^B(18|vYv_1B?Ke(5(f
zDCiSu1P-NPbz}x!I3g>aiWyIogSQ2K2wS=tI(P?%C)<hJe-<PS4y^W#A*|tN`_Zry
z59y)x<}Vwp6?>{xVZ3>TyfA}^QQEef(Z=`42-vE#8C13`nL#xdX(j0!B<_Hkqf5F$
zNJEHgkQKN6zPJ6yqyqywL|rI5=JYw%aWGf3GNIpdn}I+Xn%#s2s-0HVAln4feHaU9
zJD$L!A5fwgYQn2#6wt5OORxUtEr`DjKZm!Q$B+md?hul_+NN9F5x#l}=6uV;z%}>#
z(GKDVfJHrBMUCzI-2A`aI^IMPw-p&+7+i@y6q5{Y?)$fMJlrr2gl<jYpsus<I*2C`
z5>o7PN$?K*WVrHG^<IXcv_d1;yVe+02!+S6MM4JHxY@KA14{#>0xFGH9N`eBvQn5y
zukI#cC}7dLp<CLe`gM>(B+X`MsE@H#n-HT=OL`!i9vET{R5j1QS^@Auq^wqBH3H|5
zz5s<Q3Ae#J!r=@mV>L8>99xHW9)`O=yD%&SZ|*Q++Pz<h=6Vgr8eVrpE5RrZm)5(x
zF>!K&<)2EQH~<C>a3Z@dvV+NTOf%gF^qo!SggSP&l|qXBc$kQIOfy}eFK#Z!a~WOq
z9LM$Y#)D&v3IJa?)(cR=Flh}qA_B2e3gh^g!=Q9~OQ}%>U_BQGjw)8M4g#Dq&E!cC
zgK+`z6_e@4_I4^Biuq^_E!JF~^Inl%oTAlEL}8$s3LnfW(B6p5pDkktKf2m*9{wuh
z8F*!;6YCPtlu+7(Rs7J3Ri@xZalbMR_AU194j1g3LRvCM20wBiy-hff5quc!U}=vf
zz)ImJN3!pC<!>&Ci1Pj8#(WN42Km6UlzKeaZH*9tCj{{I<{<S*I<XMerF%WYGU62T
z^pKkxT+&~ZrkPp*AK;H<J^*#ain~pn)t0pIhxMU)Li%9YE6~j?owh%qZHHs!IiMv9
z>s?~j@*cAX%yjV~hOrH1l4G_8u~l#bpnNGf3Swb@48$G2DnLTND8v{6I7v}^6Bu=N
zC97Xx6-erp04aVciqob40J~fN0J5PoOOOGCtagThN<LibT!edRU*FdBltrM0^WVC1
zECZxF5s~qH4x#wK0w^(lpZa8%-~`K14b5vl>jCR0{sOb>+!knII!1sFw6N{5+ibw-
zQ%OOa6m^c=C@h`tM&W5(>Dz#z;!9j5{O$mYK$=REY>I<MJs3fJ1rguen=+`d5^?ET
z+799?e_0%Whxa09F!0Wkla4fcAKRxO3_1P3%9+tM1gy0!mrLBK79cHtP4>t`)JTee
zCjNlrAX=rdG9gk%;Y519Kr2vKZLn%GaO7M9l0xRxA|n;XJ;btrG=PIeN2CQ@Nb7D7
zP#}Ar_YQL-@YU%S7jkB8F2FWW5a?C6780<4Btqv53YLjlBq@D2fEp2@O_0Xp_B?NI
zw`iDB?T;qgIu>i#BSLB`bhDU)t%BN^T!nTyeo9y2fM#Q>yV>-rt`&H`>YW?VT{xkI
z*bu~zyENeH*gsVO>gc#24AEE-K(4egM)^m85&^@)G+UI=inMuOCXB$F5-GJAU@Zw<
zAHob0eEM3&S1$@J0`Et-`T?FUOsiUE`zj)}u$1H^@dRYm;(g0T3Iqh?+UFDugJ>D8
z6@5M7uviB+od8SAuYuaSWOGy~q!E{rrfeha3wm^W_Pfx~u<jT@kZOJG(^HlL1q4AE
zb#kD-`Ws=OI}3{TeEF1%jQ~BwB_&>;xX7UfWTVmp5h(J|8{pO+ieEeF^WlSX$I<gW
zqH-JqL&MFtDzYeAmw`PV9&;EGlo%to;E2eNxgJP^iPv!x>};<Q<`YhSCJKXlZ=jCb
zJ4dsRuFptUu8v$beIhEd1}|D%e3t2qTcQjj8|78oc3Yae0u2k@`~Ltx95q<n8KdaU
zuou~b)s%O;P0GZcoV&mPZ5>u_saD2Z=*Ust;1frtJC;DVc`Q^rJ_>L(6fO;jC?YR3
z{{XB10Ow&B9@=Nm?=`vNN}K4>>EgH+@*5ipWeVk|$cF$B;4c-ak9f@T!jLaI@A{By
ziTvn6Jg#AuJ1*Gpit+54z@}(3#1g-4ez_)Wc>t`-v?#v#^g84d&Pz%3VapFBjAT(-
zAk#8D;SMuyKHR<%$C5A_H5g*)rEHx*F%Qd_5m4+5l)exq+}hX2onc@qp>g)<YeoBX
zw{cWNRZ>teOZssJOvbJ5f*}z~_89A@E=g3Y6KPAPJZxz9n2;KQe}EAj4}qG9`>s~)
z4uzW~b_MT{TAjq)2#DUK&}AHq>(@vMu8z7n24SW=6J((Z<p%V{Wr%uj(!B6FY!(7(
zqz>Zb9hQ<liGU*Ja(WU1-dUli1IJq+l8b&FwA&d{Lv3znOV(O=5z0L;15ZH|Y-pfG
zIs}-|6T=!1XJNOPGxtHgq$+?4XXxLN5~yzvdKe961tp5aNdh6PHX1rsRLwnCpROiD
z><JAYWO01=qe-sv6Ky^sq$xY0t-w3r8d*)SdvG^2v@RI2!Ei*2xdTQs=}ui`5mmr)
z&2A4Cp^&=hh-jFlXaEGPNQE!ioNDjDOA5Mi$p*K0yX0U5ugqnNA8>;#3lTEcZuEL9
zfzqJ?0I$7y^Z3LX;0+Wut5^JYc~I<1O~ryEVSKo0M2f_bOMKM@Kz?*uhq0DB##UYN
z0Ank+PY7$19v6rv_~I3)(YW=1fTIgHEXRAq0faK2L3&t`37zU0hY(nq)FZ61s&O3g
z-Sz~eTsu_T8`E3M@MbTRU?CN*33g0)N~W08TJVO<W#On0sz!5-4{m-S`-qN>zpLcf
zl4T<$ADv`Uz0)T>Aq!^hp?n8XuLYn1lfI=Nvp@RWd-2RPzkdG!VeXh1>_S)&L5iq9
zt;w<>K;;`|<kp?qTx4w6eQgH%cUAt4;W7p6)27(eaGmlPUAycJQ;#PAf-d!0>F8ty
z3Lb&{Q4~f7%d-LFQMI0oXMFJk$z1l%cOhSZ9qxw2(m7{P03_-=q4wQFksLr{p3g0k
z#4>Qzve$EhqPFQ|$+)B(tfC18<2PeGhVnrXybZusinpMKPB3gc6-R}U5DtyQyp~MU
zAwWS@&b|pEkXW&^xvmtFo7WI1#hZ1Aa!D%&kb0@pmJJ=z<LPHcEzRd+sA(w>4HqgM
zW<7fP3Vtl4Id2qxcu9@|;3C9nfjj>Ivs#^M#<a0^^h@+9_J25?6oq}fTz2e4(8uKU
z!Z3QX0q<_b#mA0S;satPr+CzUA<v&A6vJHJhZPMKdvF|(z<L5<Hi*yI={lIi-{qu@
zh=ad!Gvz>qEK<VlCe+~4H(tkkCJu_p2+%zQN{u*lGcpPQdwa3$e9Hi(0HTyr)5~Yg
zV=_`aDB$miW$Dp^#g)(7MQ2Q`Is!zl)9Ip-t>N)<5aCtW90lO+QgEc~iv-<?y?^`2
zN&-{PY!_ns^b*zB89&!^x|YNw7Cl~j2I|F#Pk9U$Af||qf(R!EIKZ%g<^&0gTj;L0
z?<mIx0N?ko7~$D+1;VFxUJKj}ZYS6gdiaJ*o9k{3%wQ*D%g}^%b5u4-+H8P`n!!Ug
znFu=8R4p)AVUs?<KD5Ml)Y>D0m4G5I)pcw^cBUs7GnXetuU$!nh?qnQJ7mf(Zh5hS
zD>l})j<}{iq(k@Q-J+H^@r=Qk4pFi1aD1Z3=KxirVt4hBVQwbVlJ4egM^IO0(<kHp
zagR|5omfPpaxl~VfezcEuG~8e1B^kI+VM7|4Wjk9LCy|zQ8s-wu8k;?>3R};Mu^Rg
zlMEUc=S^yhu4GDr6UaXXkk@w?au^4vyC!dj-pH3O!a{_Xba}coFSpbj(i+W~2j&Xs
z5ZEl*pearBFz*9T5EtjEt&5b`CK}E3d)$PXwhRCb{WZYVW*m^nA%|2D!f1d=hG|$A
z@y(Pt^!JTz7%dGH1|IaI#CSjk&+#i%sPcu)0DEr6YG1mJa_LhSfEnoL@%RBKH*^-e
z{L&SM2*xgfIcP_j{NcJvtU7o}3*CPh!TAt2Ytm$|=)p;WE7zN>fK7+IOfE(NLd8Kx
zpc5tV76Zsw%~Co98W6g=offDKR(zOug)QdWdk>XE8KO*rd$cp#vjl2#Czb^E9TW?c
z#UMMu2pL4G8Cw*Or67on0E~9v7zEC@BC8@Ojr(a=l9(l0zy-%N`HR)kA=_yMb%=lf
z5A4AgpriG@Q2=P1kc)_N!ySS(L{b5nsGOfK2k&s|h7@8M4deH9*vs_LM-{^|?v7{<
zjuxLT#qx(sy0alVh!Is)fdOFDt}JC(3^+FCo8K=eLkkKTq>xr>hQgC@N9&23sV^fT
z+7bwAbg@K9DTX4N3I)O;6L7Nxuvj*$6`C7^ZA)L^fZfvofe5hXFQgzE!V*#Ger-qk
z2l_HwPK_nb)e?fXlypQJ>yTUkb1ky4)T~^llV}(WR=M44oZ4_;T;DxSjoK{6Da-<W
z;0vY`+djSM1lhOqHk&t!X9O(gT0QMi948R4;>(B{r(M@UI2bU$cx_=bp{E)kRC%2X
zT@x9O>M4Vra0zjiMG?3{O*E^wVoY-V6<p+n)ynr-;@u{GPd|)V5P;O>yQQS1hD!z@
zPrIKR5CuwNivpmwYgOOHnAmU+CF?koY6sSCWD0F4+B7}&(-Miw3RYn$!%BY`qm&Vh
z0E$Mx+askkXd0?@p&Gx25${AJN{#2L8&tT5a0$pL+Bf&{d}W*hqe>06t2VP6veFyZ
zi6U7-%TtM>u@T7mdEaGgh_b{Kd^4WKzQ+nv9Bm7Nnb)#ih=arde0TG^)6L@Z(hI|y
z*`^kMSOscG;nbktnx46|phF11NSa}z0mn3f4JZctQcMX%nDzOqm`iDl%Yi8&odJzO
zUbIzRnG6*dWip4o&J-;Hxgxg+zjmpk909|xS(|-n1x!tZ!>Ng`k?p$79fCapLswKZ
zv=;yf$&_?5GNSFI-cLFZtCkz*9>=Uk+Cn6dekx4`T#8>%Vm|62VbwZ;T#ywy`#{R&
zyvhDaDh{z`wikyjAsBY*QRrlPxg<&fVB2n<&u@-c)L?EAF@7vl3o@Pq8~0{(MR~n~
zncAcs1EO45Xw$dWHw52v%Xb3GG7Pa*(_?T^K_8){_g+3TZ0)X?_6j3_4H(?PfKWEm
z=Y?-`O~YvB$TVhTWcYEo{{Sv#KA3g}rR1Vqvw>pNYvsXw1u8TxHxpvE*>+`aavsi=
z(0?J3gpDTs){raxyvCCvn@j@*+vQEW$7w_##7DZPD1!inAQd7104UbVVExwwH-}3N
zxh5=E)bl1D+I3w}QfQTHuZ}zUh0PR`Ai6qXGN{RqYn>I$XtnfpbHNiK(mLuDgn$@W
zAwf%c8zx6~(J%%DyQ)gmJ(lH?&Ih{rY|=ei6t!MKECH#g`H&grqLuj^ByfZdgcOj_
z8l&+X>@^s)zTvPmodLCEA-XS5=?YOCA6)=BKFBW_OhOm{tw_RJA~xu?{LDjTuzA{R
zNF_S}gnrRI?4(C{FXaHS+5Y?9;Wyh$4b=d6^^@I0as?VbgGwI(Qw{YHqi0J1y6;Au
zrhq|$Hvt;s5=BAgh;6C{?xkydCQ~~hHPx%3_3K9wDkM7Ul>Y#<9xi+bvlA;Vx4?~|
ziQ1(S)^co+pS9(vC;(~Ok4pHqY{dTn>A)vU`x9;*6UGiHo$=e(t|U5O3;afaruUY)
znE*hP9T3Gwv|i`uh$R<=E)#IJh&#YI6JTUs^3LFqf&h~4_o=&6+|k*D_WE24ot|gV
zjtz6g0FkY%AnYjX=?+RwPGqF?_8Htd-~Rw}ZAignq->37n;W@ZkO5&N1l(8>IsIa$
zA3{Oz6yhjIKw@fj@e4wiMgl+pm(?i^-q~L?$sf5J)#<A3!vO695Dwh!<@<A0`~tg7
zg54nn-fQ*(1pNVOC!m@*=pfPi$5;9Jn~F#=jE}yqx>PaAloif)C8sZ1%?XDz-8xKf
znsW{~Kw5%nJ#NK~nMx1>iNzt>gWcgQK@I@5XxhQc4>%!JKB&H;J>;L*4=4mQwSQLI
z&B`5-qd1$<?2M$eP=F<uv3?TJPZLvLTTqcKbjunmmDJ6yb~JwUF`{UhQ{=dL^5UZ4
z!LqJEGU`h-bQFMXJk*dEV(*N{u&4qRCF?=<9Ka8F1L+hrRB{~N&M}@7QG;}mvjP?X
zZ+m_`S`s2rs|!NGQ6N@dJAs$`;9(`%CXqaHjX48NH&AHz`pw!=z%aI~l~8(Fo2h`8
zb>6*$VoEasq!8=XMS8zx030sJC&hNY{xN=%0s!aZHHY!XGqVof;P>=R*A2})0aC_)
zj1S|1I)9<vM1HG~Xh2y&-AvZYlT=#N%^sw)E(yqTFprBy=4Ha1r+kPIn-LQ*F+wv!
zEDIxq<%YgU1XxOcA1PNi!eo0YH9@aP<G2Q>L5yD%L`99p;CFG;1`6Zss_4lMK>P@P
zw{E+efFTWe(;17K@X2RH5EjsiBUFE>1%!suTn$Usw~lKFZ6m*_?F5F`F71R4l`Pl_
z`WNN~9w86S-MVb?P31bX(V8ff{rI0uQkq32?FeW)C+<Y}5uzst$JNh<fxtt4gFk5B
z%und!2orS|Z}i62nUQA2>+C>$Kul14Y2V{Cro<rkDhdh&=CZmn2BJF(oe4F4cH4lg
zH9>~X5>mj@fE2(1XJRyEk$E@)U|tFk1#$}krI`ll)Ftnon88p3*{&n+E#X3{#4(z5
z2Z_GHh0Bm%3t$|ki{CqN@(P;WZ%s|;3Y38xA=D>421#FF&<g$YgMOanWiS_25_ofn
zVmGA#R4>~&(zF4>qd*Sl2$tP#Bij;TC)-6;>-SNQ!ee&zl@NPq(9V>aPqgrFnqHf&
zgM=0Lv0^bMu)<3L;>Rlh1%{E!3XCqnzwHXG%IZQlkG|1}rKcQ#2rKoB&@~6y4Rk`c
zoK*@Wcsm1f5HzFlthjRcf#DFPl5N-Znt6J7fvH-hlV3fzHrETlf?!l<^JCdOh=N=e
z4ZaQS814`t-cP@60kv|UFa$%ns(X|<WDtVki4nv;0oa+o0ZeZPQX*^|9gqi&a4E31
zi)@}sEbSjhKKX8v$^aC#jN)<EyuncG07Me0u$Sa!QkWteR^-Ce^u?8XHKR2jAn{FO
ztJ47+6kzE@o8jM#4UI<t<=cBK6>|U^9{EqI5k=nCzzl&C4f_!g^-lRnY{V0q2>_;W
zYcdF}%lxz~akIt%slXRhL*;IDPCkyI@@O`&q-45-1aiS9s;nca6rf6aco4*q@OP#M
d006pt9ZfrtNd(CVFqn;*C2E>PF8dCD|Jn4?QgQ$Q

literal 0
HcmV?d00001

diff --git a/docs/package/rectangle-example.svg b/docs/package/rectangle-example.svg
new file mode 100644
index 00000000..74d52968
--- /dev/null
+++ b/docs/package/rectangle-example.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
+<svg width="13cm" height="9cm" viewBox="348 138 253 169" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <g>
+    <rect style="fill: #ffffff" x="389" y="164" width="158" height="115"/>
+    <rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="389" y="164" width="158" height="115"/>
+  </g>
+  <text font-size="12.7998" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="348" y="150">
+    <tspan x="348" y="150">53.22,</tspan>
+    <tspan x="348" y="166">8.09 #</tspan>
+  </text>
+  <text font-size="12.7998" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="545" y="288">
+    <tspan x="545" y="288"># 53.36,</tspan>
+    <tspan x="545" y="304">    8.32</tspan>
+  </text>
+</svg>
diff --git a/package/gluon-hoodselector/Makefile b/package/gluon-hoodselector/Makefile
new file mode 100644
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
index 00000000..f1d86728
--- /dev/null
+++ b/package/gluon-hoodselector/Makefile
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
@@ -0,0 +1,23 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gluon-hoodselector
+
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+GLUON_VERSION:=3
+PKG_VERSION:=2
+
+include ../gluon.mk
+
+define Package/gluon-hoodselector
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+  TITLE:=Automatically sortes nodes into network domains.
+  DEPENDS:=+luaposix +libgluonutil +lua-math-polygon +libjson-c +gluon-site +micrond +luabitop @GLUON_MULTIDOMAIN
+  CONFLICTS:=+gluon-config-mode-domain-select
+endef
+
+define Package/gluon-hoodselector/description
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+  The job of the hoodselector is to automatically detect in which domain
+  the node is located based on geo settings. Based on this information
+  the hoodselector will select a domain from a list of known domains
+  and adjust the domain related settings e.g. VPN, wireless ...
+endef
+
+$(eval $(call BuildPackageGluon,gluon-hoodselector))
diff --git a/package/gluon-hoodselector/check_site.lua b/package/gluon-hoodselector/check_site.lua
new file mode 100644
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
index 00000000..d16df082
--- /dev/null
+++ b/package/gluon-hoodselector/check_site.lua
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
@@ -0,0 +1,26 @@
+function check_lat_lon_range(pos,range,label)
+	need({'hoodselector', 'shapes'}, function(err)
+		if (type(pos) ~= "number") then
+			return false
+		end
+		if pos > range or pos < -range then
+			return false
+		end
+		return true
+	end, true, label.." must match a range +/-"..range)
+end
+
+if this_domain() ~= need_string(in_site({'default_domain'})) then
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+	for _,shape in pairs(need_table(in_domain({'hoodselector', 'shapes'}))) do
+		need({'hoodselector', 'shapes'}, function(err)
+			if #shape < 2 then
+				return false
+			end
+			for k,v in ipairs(shape) do
+				check_lat_lon_range(v.lat,90.0,"lat")
+				check_lat_lon_range(v.lon,180.0,"lon")
+			end
+			return true
+		end, true, "needs to have at least 2 coordinates for rectangular shapes.")
+	end
+end
diff --git a/package/gluon-hoodselector/files/usr/lib/micron.d/hoodselector b/package/gluon-hoodselector/files/usr/lib/micron.d/hoodselector
new file mode 100644
index 00000000..6e793151
--- /dev/null
+++ b/package/gluon-hoodselector/files/usr/lib/micron.d/hoodselector
@@ -0,0 +1 @@
+*/2 * * * * /usr/sbin/hoodselector
diff --git a/package/gluon-hoodselector/luasrc/usr/lib/lua/hoodselector/util.lua b/package/gluon-hoodselector/luasrc/usr/lib/lua/hoodselector/util.lua
new file mode 100644
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
index 00000000..5d82a72c
--- /dev/null
+++ b/package/gluon-hoodselector/luasrc/usr/lib/lua/hoodselector/util.lua
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
@@ -0,0 +1,83 @@
+local unistd = require('posix.unistd')
+local util = require 'gluon.util'
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+local math_polygon = require('math-polygon')
+local json = require 'jsonc'
+local uci = require('simple-uci').cursor()
+local site = require 'gluon.site'
+local logger = require('posix.syslog')
+local M = {}
+
+function M.log(msg)
+	io.stdout:write(msg..'\n')
+	logger.openlog(msg, logger.LOG_PID)
+end
+
+function M.get_domains()
+	local list = {}
+	for _, domain_path in ipairs(util.glob('/lib/gluon/domains/*.json')) do
+		table.insert(list, {
+			domain_code = domain_path:match('([^/]+)%.json$'),
+			domain = assert(json.load(domain_path)),
+		})
+	end
+	return list
+end
+
+-- Return the default domain from the domain list.
+-- This method can return the following data:
+-- * default domain
+-- * nil if no default domain has been defined
+function M.get_default_domain(jdomains)
+	for _, domain in pairs(jdomains) do
+		if domain.domain_code == site.default_domain() then
+			return domain
+		end
+	end
+	return nil
+end
+
+-- Get Geoposition.
+-- This method can return the following data:
+-- * table {lat, lon}
+-- * nil for no position
+function M.get_geolocation()
+	return {
+		lat = tonumber(uci:get('gluon-node-info', uci:get_first('gluon-node-info', 'location'), 'latitude')),
+		lon = tonumber(uci:get('gluon-node-info', uci:get_first('gluon-node-info', 'location'), 'longitude'))
+	}
+end
+
+-- Return domain from the domain list based on geo position or nil if no geo based domain could be
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+-- determined.
+function M.get_domain_by_geo(jdomains,geo)
+	for _, domain in pairs(jdomains) do
+		if domain.domain_code ~= site.default_domain() then
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+			-- Keep record of how many nested shapes we are in, e.g. a polyon with holes.
+			local nesting = 1
+			for _, area in pairs(domain.domain.hoodselector.shapes) do
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+				-- Convert rectangle, defined by to points, into polygon
+				if #area == 2 then
+					area = math_polygon.two_point_rec_to_poly(area)
+				end
+				if (math_polygon.point_in_polygon(area,geo) == 1) then
+					nesting = nesting * (-1)
+			if nesting == -1 then return domain end
+		end
+	end
+	return nil
+end
+
+function M.set_domain_config(domain)
+	if uci:get('gluon', 'core', 'domain') ~= domain.domain_code then
+		uci:set('gluon', 'core', 'domain', domain.domain_code)
+		uci:commit('gluon')
+		os.execute('gluon-reconfigure')
+		M.log('Set domain "'..domain.domain.domain_names[domain.domain_code]..'"')
+		return true
+	end
+	return false
+end
+
+return M
diff --git a/package/gluon-hoodselector/luasrc/usr/sbin/hoodselector b/package/gluon-hoodselector/luasrc/usr/sbin/hoodselector
new file mode 100755
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
index 00000000..12125da7
--- /dev/null
+++ b/package/gluon-hoodselector/luasrc/usr/sbin/hoodselector
@@ -0,0 +1,56 @@
+#!/usr/bin/lua
+
+local bit = require('bit')
+local unistd = require('posix.unistd')
+local fcntl = require('posix.fcntl')
+local hoodutil = require('hoodselector.util')
+
+-- PID file to ensure the hoodselector isn't running parallel
+local lockfile = '/var/lock/hoodselector.lock'
+local lockfd, err = fcntl.open(lockfile, bit.bor(fcntl.O_WRONLY, fcntl.O_CREAT), 384) -- mode 0600
+
+if not lockfd then
+	hoodutil.log(err, '\n')
+	os.exit(1)
+end
+
+local ok, _ = fcntl.fcntl(lockfd, fcntl.F_SETLK, {
+	l_start = 0,
+	l_len = 0,
+	l_type = fcntl.F_WRLCK,
+	l_whence = unistd.SEEK_SET,
+})
+
+if not ok then
+	io.stderr:write(string.format(
+		"Unable to lock file %s. Make sure there is no other instance of the hoodselector running.\n",
+		lockfile
+	))
+	os.exit(1)
+end
+
+-- geolocation mode
+-- If we have a location we will try to select the domain corresponding to this location.
+-- If no domain for the location has been defined or if we can't determine the node's location,
+-- we will select the default domain as last fallback instance.
+local geo = hoodutil.get_geolocation()
+if geo.lat ~= nil and geo.lon ~= nil then
+	io.stdout:write('Position found. Enter "geolocation mode" ...\n')
+	local jdomains = hoodutil.get_domains()
+	local geo_base_domain = hoodutil.get_domain_by_geo(jdomains, geo)
+	if geo_base_domain ~= nil then
+		if hoodutil.set_domain_config(geo_base_domain) then
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+			os.execute("gluon-reload")
+			hoodutil.log('Domain set by geolocation mode.\n')
+		end
+		return
+	end
+	io.stdout:write('No domain has been defined for the current position. Continue with default domain mode\n')
+	io.stdout:write('No position found. Continue with default domain mode\n')
+end
+
+-- default domain mode
+if hoodutil.set_domain_config(hoodutil.get_default_domain(hoodutil.get_domains())) then
Jan-Tarek Butt's avatar
Jan-Tarek Butt committed
+	os.execute("gluon-reload")