JFIF     "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777"H !1AQ"2aqB#R3b$Cr4Ss%Tt&c$!1AQ"a#2B ? }XuAo)8^ IƟ`vUp9jY0Ǧ w)E허2jU`SEKw5]kSno!]:?jc\غV7/9N+{t#8zd/޲3F/=ź3GNquV"/4:{z%ۣI'D@ %88^f}VV)S_2ed^Mx"͟?UC62Q%чmO͓ cq0rŖJ\Õ_Sݶ'|G.q޾D U]nP%EF>˲E"d&'f2s6H]4w IS˶4VbaQ+9]XtNx:M0JNxϙ⟟"{nr;|{%vo\z-wc,*|k}-m55o4W9ؓw߱Yzk .=/oϡȴ^9ҧʹamtQԬZ]4?egjrQ}+)MleE]MPEn!`IK2RUEwVIoͷcp;lśe7΄uN ;rПV8|e\׹9Y-V_G.)XԢOv<;_"ڜ]ߙEr݊'K{KuBJ}KI}24|"v)/ʻo5)6-Tjd7.C]Q&lU,Yk1P4~UKZs|$kX6+屷CUq+N(jlGrpG&UB3#k3\9qfg7O8Kim(AJOO~C#e`i0wĦij$cWh<dtQߺ"NOtG+ZǪ]b5%]v5$)u|qZ柡s-rۖu$MKڎCmN_V'/1u,21pvlc>қeNnֺ|bkl=lǷNOʣlz*]»vȎ[)j[fs[]:s#m6Qt6*Q+`};ßj[F_jcv`r#w}|k<ڞ/r53N8>Kh q_-_??@enſEܥ\D\YAEo+ ޟd}IcY7+t{=ɩ>}i\\JfxzVdSzᔢ]Q^CJի\iceitMM5hڦg')^ et#ۯ"ÿfF->4iؤ2ݷ6#p6^-R̫gETj^I.kӽUp~D9[:/>h> \gJ|ۿؘ>ml9jMK =+*2i=0RiͶۗV{"u]IH`9J_˹KƼK$X-|=ve/ bjxw.9i%NqVJcFYKcTtO,F;%67vYb8֝qq0tUt=DvawsS~~Edzr^F-v{c++ݔ\|9Iy #nOavOY=3690Tcrilwa\˓m$?箵S6U c(.~R7suMhqcMOnKoc*ȣȩEd'J ܜk*_q}%M/7c.|;trddbsdcJev85̤iW Ę 8C# .딖e$sk80^\J众2)Nm~|Idj_ O+6ǻ#(MIz4Qo:օY,:q]̌"lK}{F]ζ)h>ʶ ^ue78_G#rqv$wkk[Q c+վ+ĸZΝFB]VzoiJRke&Kgom_7Wef_7,osJɽE%lzBt>mRs)v8'P0ֲtrOg4p_2`GlhYڦDF/ӚKmtm'P2kqU765fJY:y؊.ox%8V_ִ̌ܞjpqwЮQ;iUcNoOoٸcY w*4soӵkqf$?-jy~0{>?DaL8XL/ɞo+'8 {ʸxգj#Dy)wk̘e۩+%}~;ڼ5xek|y-%ڱ-ʜe:EEScÚ5z|r'&I&яF*F7|[nRF =(4ۖ@. n7@xx:N^8Bg%u/ny6&dR{?8U_Q6Z߯-oh.NR]} qi6~H(j7*uF&l&o8ts]/P89:jW*$w׹Ӌ FxpsCJi.7N q4WU_}7*M#qWiصnk'4ݍl*t^ c<'d:~͗enFQRz9v~ddoTZ̚k7X(wUswO̙fոҁՕ[$IAI>WW~ĪEѢNoeutYߑ-Eixιpxq{FnyfRrjqU᫤]>wPU8)Y-7Wbq㛋w:7ܣ].j%K:y4] %9$I%pT(󨪙VqiYٓ4y~5S/XTDZM2lȪ; S~Kx:(Mn0';-{*qV&|W3S+\֔a{R{s=lYmN9Fn&o'}Vi( ?*qV5ѼCNsM饏zߴ$^O69@ ,$y|jE;gW/u|M?3+ZՕN86յw%|QO㏏S\E#ddsgl+Scl3~~CԕQľ?5_ z߿t11OĶ0>oB9E/SOSk+b&Yn>$툧eg) "!܉(1 uBoJ)/t/,:=7M+1ܺ#CmS^Nz 6[u&]+|Dfj:uZ5-Z^TjMtm>cȳ NdT_,M#Ex;pt۴ͮ#!N iKl!zPծ~$1SiO} HI&g Bf)b%Ko̧kumEnص;V?j>nltOMVۆl>.WueYaw2+qK,?uHiqqSM}~gu3xbcWSy/Xc{%sZ]uaUM;7:cb5G97'7þյW,;$ܛyVjl޻y7S;o6gf.Tг[7/i1Z^rE cUF'P1-?%u&q{fw~27ޡ ^w$?SwP[=R3Y73 4x(Kk&rLȫMKn:RjcI?3Al`vض[POĖSYujj6v+-[xҵ=~zNN>\ɲQ/uufo*e6l;31붏.>w6=7#7dFDc%ƶTbd;2/=?Asr! ~ZSS~I"9y]Hn,ĊJ7S}cK"amCg3yP=RQɤW}t;-{F+v+RɔڎB?º{SV묖kۏmK~%.Q;OfEf_Y/F-V-MdD)m.ZՍ8Y*h[g/6ydmCc[rdfʾ䖗gd$^֍^ʅѻL|<[݉\߯RiJUo';œN?B smS ܹkس,mRE^ѣlJ&.ċ԰YO:޼f\Z'HCѯU[ʩ1ff4S-٥YxTIGLiыr }L)edׂ*l|ٚuoxӿnWkTbbVm zT_'"x5Vިxo1ج^Fq6Sd3ws'/ڞ6m?}1OsRGݝ+,~ڬ%^p1ef5c25vq~﹉ă[r-eq] 8+/ESj}?mUE.xYK3"oƔ^Y9I]I ޑ" &*4.Jâ}ټQbXKJ񽼀ncg`+riܭ_'Bֽp%bX'7cB}WPm|zHָLJhj~E>i~Z$297|_hyΕ&s}ZϷ *j]:v.HK<SP8`Pƣ)r ,}8Wk[ArHgn=о7:J]TTP>OOj J_KyB\Ԥrm嬷ȫr{ݙ5R(FRЪ6q}KLmR'eޖz6[YތesYYL5Tr7s\^rؙV͸컬j5d?yk'b S }kra^ߚRH)[sg.fLM\u= vJQ]rVkZuoN}#G?yjO%|i2fKoӰღC P_Ϳ6Zr{e/m$i}9 G2')YG9KY>|1ӫ +v+i;h\Q@˿Lӭn˖ 7ck>Vr.D0)hC<˄4"0[eԬݭe+l2s3ss oX]1r]+VK vI;mZ')R6e5=/i@]H^Z۬՝EW.jƆf{8mXMV~_̝z^VR}T63}}k3+k3:j1Phlpi{欍BȽ}6w73GtUZv>4eUj$ xz$$D/߇ߟI"uk̜aƪ*ke/F:dһ_PE1ݡkp(5ʏ-ɮ{Yllԧg!ܝ g]i-umεŸxOê^=PR ##XeMy%2L~󜺶Hm ݙ2t_ƶz7'\Z4T<"AM-&xaC]a5.huQ۫$cMμ|h;.J.o߸sE-zU{d];|YLSMvSEneNKr1B[]NeonNߪ$4̘FPrkxޱ=0lr7Q%=$KQ;0r*XKdGۃ*]w-npᬶ\tt4>Dc[Ouo3/)-WҴ xs71eԤm*ٖ웗H''.Cnmy]݊Kra[9)Y#2U6d7tf.[R.GdE>#O_.+-K`{KonR_ÕM/)?:F,Xo1ƽRmz8C]lD %(x+d2Ah+\CCLJ!D65x\ȼv)\Nrp*[YُfL*PyVΚuWA K4hyYdwihNIy#ub?4NDϐ'4 :nFe(o%ve@@xl-k%QƭRP&kεMŪ-Ys2u ]T!}8*TQnZ}v =~mԧyDM&8K>2|Bnugܷ.wvCs̼5F^ubES7ݢM&4Ź-~mKx1((sr!M5uy\q)oy|a)ˣ,A?w"T휳2\F}PR-<2%`~4Z5\W"(USkGpT(~Qj>ɰ쏳ǓSKKx's]nEf'.iݙL>Moƹk7ݭ[.г6lk<;?)#E]xFU7'>vF%R;t:Җs}NSBWX=Y8ث}~G)S^^ƽwR[)/Fm-ڞTK~˓Z]U;RQ=M/"NԝP[-Y9t_8V+}P?Ue{M/O&WWKvc#r'KM'p[±vtpRC/W|7K2Rfm;ljm%Z]^T[6}6iTC }L[uxg7(Z}. SRI)jҞzȶ쳢oYRw$ŷ"J\ǭw{u'R taF{;3hHB\RP(*ZQ]y;;k٥nWbGKv-V?NDҞkd9@z LJ}Kc9C*?V-*[*۸-0.|󲝳ߗZK#%_OFGF$kC$[NNJ7Yn[k~Xzc+Sʲuhsw^^4+nElbƮKD,}YLV=i=|p|_=b5mȵ(~,em#Xƥ.sVoEaWXc.lY uG\m';'*\ӆ}|˯UfQBvo}/"zw + qvMrQ[[AdU2ٽCGgjؖS~Ev%9">$_2Sߚ%ѽ7jX(t#21r{̬F]b()?r[Rı)W[O/6]XL9 vuLh-Ȃ9"'7f!Փ䮿Bf}[lag֧]?Pc#D9EmfK7o*})+n!]qIo^FrNVNo!Eƃd#OP?%ۋ(mPu93ۣ{}2&$%cZ߯LҚY);U afԶd,*'6_?B:R~}^̬~mJ+vC}Ѩe"MY+mi :s쥸;iJeYvBddeK|#5/mzR]F2 JHUU )/S{Ic$=: W)>} @0#URsR=w"L{+ɞ)d|*qq2>[nƨDۋ-G[6½J|{Ѿ4MwyG-Σ Ze{ug>2|'zΤ2%xՑ*<Q̥T')uLkjn(zF-JOR}wn~FV5zq2m'^VS=7Y^RdfeO)>EpX붚w*r*w˿^kڴ{J;K۔sRŶU]p\zn@dx6[+yeH[_m_/I&mv|M5&&-G"v۴^{vg8Y(K_~h0e AxfrzڬkhS/Vy1ϯdW3'͹}{'V-:MW(V/ͷ*E7s\EmEW}bUr'k,P{9?B֫ #[uNrB,wo^{fdF(5tRf.2J-/:~ t0M"d_/c^32*q]yLl^2[ݥZc*vtm213r'tSuM-Խ#o/HF+2VEpmǦޟS?Rs+t:u G8n,Ԛf,hY8SX*rKf>+cpruɬ=DMrXgϸ:~ɲ ~]'5'kElw\=ڞAG&')G9R\_̝1K;nPg&T(ի[^Jҟ"qoӸ.W}3mF>'$<\U6-~?x?B~{^xkpv-vlߣe빹j\(ښsuu6lH(qoaYt?x8}Ie '@b%TݲygV.+O9/W4MsCMuFjYzG.{ds.k(>G~K?ni-=R r}r ?s̥%l5Ϛ9IN6~۩RĢWNʾE[|nb.HY—קWkr1ҺշMNDp)^¸R:w;u1 12]T/Uiʹd%2OC2K*r5S]g凫5 UQ.ȫ– /i91njFkQxuJ1rn%XDžy?s˗վuMGƋ/m^J*RsF))uF,'l{=|nFm9:N\%u#tnXE->e2Y0PũjUȨEŭ|'eʹ[o{Ցms%CGg/}t|snzrvm\g}cÊ94Pvg'L}ّg궮ԱߢO^f.W-sT]M˔ېе<^Н'KuNn_Vl8*Kж^ xsuW51-ᅱFzƉT-kY/9wzDޯ/XlW)gypǚjDɨ~{ݤHCim.[>rqE_Uرx/>|L64%aj;fxӱF(K֓J9՞ -K> I_5Enn´&=Oc%o̟IJZF$۲5I9Wݚ n.WTuѲӏ[4U/9.2zX5\j3ĎEsMq4%9.d[7јc9eNa+sjE';%s#ɤ`ףS=WI쫢.Mv:j/[3:rTF_zt:.z%udW%]xܮVz$Vŗ49[^y.խN~M&mx+wGR~_4KC[ʻ:v>03߶v9x-Mȧ$c:lrCWjeg%ֹ_Nh՝Qɏj^ϛr^.>WhlE5yֵ6\W^确]*гc&^NI[oCDn.ߑ!,m&M_/'Mn$s\r^8|uSZZ1|LV<(zq׮xmٚZƏ%.Ԁs^2𱸒O#&,s[mײ9kޖCoSq&俙qxP.N] 2UǎsM2iN.f r[mcQZmFُE{#[TbҔ*sfaSrn^8N<\_'MarJ6 EQғ|F[S'[~q~kmn[_x?B f5Q١X=g(~[Cx}GO ĺo'e)~dq(Ot`sN=~heu ::m'Cjj>~5V柙cyQD%uqEc{[l^U O]b~eŦۑ'W3&' 2V.^D%G S6\wYNO$. O+^ŵG~haEs^=1*bICzFF4O#,Wu3허ekB\I'tWMߩOG3iFz{rgeM9g r] i3gk&u1r/1kVgR-ɿuF .^;3;?3큦bN̂r4ovMkڞ}[:,IVG<};*-2",>K%bK2Ƨ[w!)ˤ;d?4%Ul2ږec4#ōIw^R_/TFX+*FM[F|a'ߚ2SIMeVGn ~&Y Ym(?ԛ],=|сG4yjk"Q^~ԗ^c,qqrg^-:Uc[E8>>k|nS..LBIc>3i|ZEZXAqm nuOm<; X~mrK=~ ƱrSN<U!F΋WS/|t?K)zd} ,C"ovx?bբs3mX3桭X֖˦kFddhg}$ggSo5jL*NdJis$ EQ\v=0HxzyW~FT_Ƶccg,&=_V(%kq+_÷O'[_[Uڽv F $Ξ9n5EN/4Yy/%*} .jΔ`V_6\VͲohzfOgޯzpj}y}v:34WH;+x7ӻu<ݦ"mJ/=>eoD֣c4kXW-[}٬6;t[Na_• _5i5˗sٴ]+e;Joj㼶ۙyLumo5&F)F\ {(sm_M>gzcr)KU̠Ħ=VDd'h;-aŤ9KٰqQܫަazMp4bk9 UX.ͮ]KeS5Uq[¹X0ɦ6]roFjʧ2׏6/C6eQE5KӰmsFnIz&`z팡-ٯ.ixyك?c2//z6M4W[]_"?Õ[? Vfvӳq]I5(d|MʝzcC*mN>B2gD+><e:Gh %UkW%zJ8k_ˠ=KFRfw{sŖ^q\/{v[Ω}gLjT[t_ޕg6G~rkkMcSRKբ54?SAûO1o%[>5/R~CioNdNʛćh>f6H8c/<1xd[ŦCEk.9"ej?w&O6^ژR[vrQ.z㎩f6:V8}hi2z~ s-w]+|I9s_C~>-S&9ZFVLf7-d'pՠplJ#mm؎s(?Ʋ?/A%_sXuGNnR}_dq>1ʍ|У3]NXYZʷ/&ܛ彖LS? 6]"_t5qP5Kq]^m91jW暹U6-5WU澦M0˵f2ӪǮ.P~? _nEJTcTei)ٳrۣ%x %gs}7l9'tb~dXst# r?}Weaq>=+to)7،E*vn\e_,\NFxcivz]tM˼?Oԝ2Zrλs-ĺEtonIIfm/9^[^EBUjOnr6vI& l]%0")2䒶-+R*zyX<> -X9GUo^xYQ8ιvixٔa\t)hv}ьոVU~tK,=_wLLa?TYIo]$`N6cbi?#7;MRt<.~Q-mob\\g5췍 ڌ_?8nfJN/Y͢n3?_sϩ{HiְPo'yS??_jߡWi5q? MWȲ)8a]lLˏ--b[TXlΫRy;o5뜾$HW.mm?շG[Ƀ seo5Q}Le%*،«~uU{R$t\^%!weX:G('6WupTS&~8=jo?2_PϖE[nf6Tٯ;GLW)NM[o*\j%.gb|䭹noOX:1R)UTj74˓]D_bʝkzNI.9|^G`KeQ{mOjX/sR7evdgi7qm}ތW&4=~|YY)?7Oj}xXkF×4c.l?i|b[5Ή5j-[Y\z<茲Z$Ff&o;gErǩݦ̪/q[&[/9uuzi;PS^_/?]=ΕqK~ӛ5'NM[m_Ϲc'[oӯE#g߂vvGNRo϶o5Ǩ[ɉtov2~i<7iSȜN(G5+/ٛMTܣukj鷣/$1˒!Mxr\ߤs1ZuMQȌ^]c$CXrj#N/˦Ķ9]Nzê5zi;W,v!ŧD6zğ7uR5^MW}>igl2U2nXo{}_w]&vte\Z3 MEEe/ 2s㗼S_bIղTI}|[Ye/c]*̪9u/DmyNxSDgi `Z?.RFj۪'~.[KVb޺o濡to?E#[.^y=q4F8ڎ/GX\.YW!Z.ѕtt:?gYYyU%Uw~ri>ȦKhg,5/=>V?TrN4aWO,oӕ7-SRi*"dܽpuaVQÞd-#J2Nr:#``ѧWR-F?I-T -cOT2pr?þזgE\Ij~L9%EMoџUؙt8_eYΧWjU}e9y9z/#TT-2dLt3H=ڼcKb'"uIٓ'[[߱F~\2]r%C]^VCLjm[cJNryf}ջ.[DEoRՒb'>fVy_c6[K4Na5>{ɳaw/Uj.Զ_K~?IeJ7OQx3IgFc*جɊǽ-o3Ӭp / ]7V*ENܜ[r/tOJΉw*ʨ*JFN^.WZeLgUwKi/M9y8dkOᛊHxGĶM*&#h/U|6D(uFyE5hYxiSEVm^D|,ۿCj;<*ouOkYpΔ2{x-L] !k2ا#IM'a7:M}M1Y儭Mnk[/;4Uwkkɫ%aɔoXVV$m;2Z4i9:>\Yů= ?[{t6,~!c`Un+dW.gKyIB]l+3kض(\MZ\}>k\C~閹l[ů]VNtƸr몮X+U>v'nv{y7s[г̭9Ctvt% GqT8=wa(6\Rd柮YWv^Fd^\+緉,+=-^S"k:NVu o[_TIѝ椯bF/G㿏dΙ?T}K-T)W>s?3M)V*,;P\,}B u{rDexڥVFfw}47׋w}]Դ 1dmk1V%/'T:Fǒ_TEe[l/l/ٯc{Ƀ[~`zj⾥r}Vܪ{M8Qv]$mU]8J2MngcxY?鑞.9HjxSy.fS(|]MgcK2$(jRQ3XO|<f:Jq4& fw|$N )A8ת99 mFNM*Dϒ NoIa9i9y?:D⻧߇\7ɧ]mu"-˥5/w̨_ 7DK['[2"(%xzT\*GT"+<,yX.lEJrfo?.4N;l>jmZߣ5FdB3\r,t,./S]Q{tm5lӕT~A [fv7Iہc: ΪN7I]2(|o$NLW"#~Dͭ=v-Mv{-lqn{I3xn'6.=DƟܖަ~deQV;k2Ei\[bӴ1_]OhZl朠&t3xkei+c\'ZԪ'hK梿X@cTԫ#emIz6e^i?8 NBc̆f+MׇdC]YSd%lώ8-c7eι/}_con/no\핍~[WNReXMo+اn ?#Ͷ-AUFN1V4!y,{1a$S﹑;Ǚr"__[o) xk}7EI/riwؙ7mR}`|yrEVdo/B# uٳiNQKQkᑑ^d@/=ˑɒ768fsuor9=7ףܹճpMr-$1uySOZN?đrqզ9F q=.!T?ػ bf{¯q=$^:!ES߿ Fu\OS,8e^UוS^hF4BQƺȪw-kF39@X06 Fv=Q^|ƞ5}2tnmG_|Λ(|%](-5>KȁN$=6lq).12 V6m$ׇlOcҫܸ K{;ľ>+Q?Rx-Keu uMy$i B}G*h$Q -W[-&a"[i\}~Ek$<~c{MffS eS.#\^lMiytު]9S{u4 {DFޅSź}R ]R$y;r/P̙3niXMt;&!rxw\ZFmQ"w\L{^۔K&/gr:m=2%5bwE"^e[\$ɟPi!U_rdS2d?=[!(I.rC QZEim%}|YmzZ_ά<ۡLQM|` ybPȏ}?]Eu[`kҫgFb~F}Q8NP>5lӳ^-K%Q}$sx7SvnfTƸ|Kzd'_ⰽח$4L Y?qy32t j2e ȜrJ{mبhۍUU'p#8y'ѝ=i+Tĩo7WYyČkL5؝M=%"Nt}eXW)N.~sv5pɮ sSQ[+-/}kVk'FEɩ9SE&T=&\緵 --tf.9Ѳ4_##_ɱTFV؞~YTddS&s=䟚Fb1._5}~gM'p#,U hs--XG wtԹTi7M:GYK5'^W?C>_Gq/S&d| k_gO ӊiJeHU G_ Êg#),}-:5>V1emq}t}q?meKU:BqJeiPɗ#\$sI} Z生ƫoo=V=pVcUg"%wEm叡vIdhrȔ~F]p58_.,O|'Ɇ^L!c6OWӷ{x9?Fp?ceOuT+Uɵݹ&gx9i퓃sxGIm}_3Īr#:ԣ?4בc[jö#B7KʌWNo)=+c }YvP{lv^r+5Vxx_:~=̌Q}CTy+Wh鸚f$101뢊F[#--Y\i@l)W8/E>8nlj/ktOľ,q*[sE[]:?ZeQvŔɺ|j(Wx,LW=:S?κq%81c)jJvODLiW,{96vr-2}-EH,}%3k#l5gl~x__W Sڎ 8YJQvA=QIWju6-X9$kWЩCI4UWd'&O/Cf=Pi/#+>n$KYst܅y4ʷD^~%~myj,s_4Q}΍Cή;SW:h=Ff{.B/inȇo=-T͸OY2}hlK}.m7-z?,f-/^b\QWs/_͔/3In[6M;l ygؼ!WUË_)D9YL4_>f}ϵ3hV5Oѣ(l8?L4蹥[-Э=7V{&ʢPʼ*3cMz>u4@[oM gKS[jy"Lھzɵfx)GE`ֿ.=kJ>/iˢ[j-qץQC B@o V(ʯG?Bܻ\I>=K-].(vOE.5׮=/Pf^&$caY9{3މ%YOxZ~6Z;;ԗ.NJzş/YϖĜ%ѿO^tY$ν4|e}2ɶU9A؜h˺LrIm%J.|I]kG|DzU k4'(T\9߱^!z -:mW^ <= <^2*;Seq(6ªsHf5ʸO{Ilr~G uJY^k5X_y;5'59O@ƣ̶>pnCOvNwX4oUUf]Џe%MV9Xm9]x'Q=82z)c/~1\~LSow>ﺍƻUql~Sqo羘sk}VjG71kYؽ]b4qnMӡ; w@̇IL㿗[43)]=v*)EH'a񖳋ҎTkxuXGK& ZIR(M8?:ixJp-dmckpu*%N^-7E3='ceE&';_J'Mw𶥏Y9+d9+>!e_Sn|VX -TZu]Ģ/6\ckr /ޗ/z[y.N:*k$ }Yǭ}GUm^-%dm;K_#ctBsg2:8rz-VE|T w.}w9NEPGnoCe8/&3qT}MJ̙Mۗ~哳,-WI_Bsh+~͛vN{ZdYKݲkr%+lo*re-ه?:vYqFfCsqMXRķ{yqgrx.oǓ\xdڗ_ZC9WomX|KmV_%UJܷr$drȳL~MoKyYLic Jq<1$UuٯTד374s<ĕ96춉r9 pGc9=p^:)ZJb&VӝXٽ 0/X& ۳*_ԙƏ.5J 6<$$6B0d_d?hqd>XCe- wO@pg:.>$.Ϣ~L޲|,{-ɪ2.u/Ds-[ُiVIWK5M#Fܭ3?x.)ۣ,wJ)Ȳڣ-#fbdq&Tͧ8Q,YqQ)/R­?\k˔[p_+ogzP[6r^o}_kT}JiJ;<ivEH8wI@MOPʊ\#+$%PDF-1.7 GIF89;
ANDA PELER
Server IP : 182.253.108.180  /  Your IP : 3.137.183.57
Web Server : Apache
System : Linux sma1wiradesa.sch.id 4.15.0-213-generic #224-Ubuntu SMP Mon Jun 19 13:30:12 UTC 2023 x86_64
User : wijaya ( 1017)
PHP Version : 7.3.33-10+ubuntu18.04.1+deb.sury.org+1
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/dennysolo81/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     

Current File : /home/dennysolo81/install.sh
#!/bin/sh
# shellcheck disable=SC2059 disable=SC2181 disable=SC2154
# virtualmin-install.sh
# Copyright 2005-2019 Virtualmin, Inc.
# Simple script to grab the virtualmin-release and virtualmin-base packages.
# The packages do most of the hard work, so this script can be small-ish and
# lazy-ish.

# WARNING: Anything not listed in the currently supported systems list is not
# going to work, despite the fact that you might see code that detects your
# OS and acts on it.  If it isn't in the list, the code is not complete and
# will not work.  More importantly, the repos that this script uses do not
# exist, if the OS isn't listed.  Don't even bother trying it.
#
# A manual install might work for you though.
# See here: https://www.virtualmin.com/documentation/installation/manual/

# License and version
SERIAL=GPL
KEY=GPL
VER=6.2.2
vm_version=6

# Currently supported systems:
supported="    CentOS/RHEL Linux 7, and 8 on x86_64
    Debian 9, and 10 on i386 and amd64
    Ubuntu 16.04 LTS, 18.04 LTS, and 20.04 LTS on i386 and amd64"

log=/root/virtualmin-install.log
skipyesno=0

# Print usage info, if --help, set mode, etc.
# Temporary colors
RED="$(tput setaf 1)"
YELLOW="$(tput setaf 3)"
CYAN="$(tput setaf 6)"
NORMAL="$(tput sgr0)"

# Set defaults
bundle='LAMP' # Other option is LEMP
mode='full' # Other option is minimal

usage () {
  # shellcheck disable=SC2046
  printf "Usage: %s %s [options]\\n" "${CYAN}" $(basename "$0")
  echo
  echo "  If called without arguments, installs Virtualmin."
  echo
  printf "  ${YELLOW}--uninstall|-u${NORMAL} - Removes all Virtualmin packages (do not use on a production system)\\n"
  printf "  ${YELLOW}--help|-h${NORMAL} - This message\\n"
  printf "  ${YELLOW}--force|-f${NORMAL} - Skip confirmation message\\n"
  printf "  ${YELLOW}--hostname|-n${NORMAL} - Set fully qualified hostname\\n"
  printf "  ${YELLOW}--verbose|-v${NORMAL} - Verbose\\n"
  printf "  ${YELLOW}--setup|-s${NORMAL} - Setup software repositories and exit (no installation or configuration)\\n"
  printf "  ${YELLOW}--minimal|-m${NORMAL} - Install a smaller subset of packages for low-memory/low-resource systems\\n"
  printf "  ${YELLOW}--bundle|-b <name>${NORMAL} - Choose bundle to install (LAMP or LEMP, defaults to LAMP)\\n"
  printf "  ${YELLOW}--disable <feature>${NORMAL} - Disable feature [SCL]\\n"
  echo
}

while [ "$1" != "" ]; do
  case $1 in
    --help|-h)
    usage
    exit 0
    ;;
    --uninstall|-u)
    shift
    mode="uninstall"
    ;;
    --force|-f|--yes|-y)
    shift
    skipyesno=1
    ;;
    --hostname|-n)
    shift
    forcehostname=$1
    shift
    ;;
    --verbose|-v)
    shift
    VERBOSE=1
    ;;
    --setup|-s)
    shift
    setup_only=1
    mode='setup'
    break
    ;;
    --minimal|-m)
    shift
    mode='minimal'
    ;;
    --disable)
    shift
    case "$1" in
      SCL)
      shift
      DISABLE_SCL=1
      ;;
      EPEL)
      shift
      DISABLE_EPEL=1
      ;;
      *)
      printf "Unknown feature ${YELLOW}$1${NORMAL}: exiting\\n"
      exit 1
      ;;
    esac
    ;;
    --bundle|-b)
    shift
    case "$1" in
      LAMP)
      shift
      bundle='LAMP'
      ;;
      LEMP)
      shift
      bundle='LEMP'
      ;;
      *)
      printf "Unknown bundle ${YELLOW}$1${NORMAL}: exiting\\n"
      exit 1
      ;;
    esac
    ;;
    *)
    printf "Unrecognized option: $1\\n\\n"
    usage
    exit 1
    ;;
  esac
done

# Make sure Perl is installed
printf "Checking for Perl..." >> $log
# loop until we've got a Perl or until we can't try any more
while true; do
  perl="$(which perl 2>/dev/null)"
  if [ -z "$perl" ]; then
    if [ -x /usr/bin/perl ]; then
      perl=/usr/bin/perl
      break
    elif [ -x /usr/local/bin/perl ]; then
      perl=/usr/local/bin/perl
      break
    elif [ -x /opt/csw/bin/perl ]; then
      perl=/opt/csw/bin/perl
      break
    elif [ "$perl_attempted" = 1 ] ; then
      printf "${RED}Perl could not be installed - Installation cannot continue.${NORMAL}\\n"
      exit 2
    fi
    # couldn't find Perl, so we need to try to install it
    echo 'Perl was not found on your system - Virtualmin requires it to run.'
    echo 'Attempting to install it now...'
    if [ -x /usr/bin/dnf ]; then
      dnf -y install perl >> $log
    elif [ -x /usr/bin/yum ]; then
      yum -y install perl >> $log
    elif [ -x /usr/bin/apt-get ]; then
      apt-get update >> $log
      apt-get -q -y install perl >> $log
    fi
    perl_attempted=1
    # Loop. Next loop should either break or exit.
  else
    break
  fi
done
printf "found Perl at $perl\\n" >> $log

# Check for wget or curl or fetch
printf "Checking for HTTP client..." >> $log
while true; do
  if [ -x "/usr/bin/wget" ]; then
    download="/usr/bin/wget -nv"
    break
  elif [ -x "/usr/bin/curl" ]; then
    download="/usr/bin/curl -f -s -L -O"
    break
  elif [ -x "/usr/bin/fetch" ]; then
    download="/usr/bin/fetch"
    break
  elif [ "$wget_attempted" = 1 ]; then
    printf "${RED}No HTTP client available. Could not install wget. Cannot continue.${NORMAL}\\n"
    exit 1
  fi

  # Made it here without finding a downloader, so try to install one
  wget_attempted=1
  if [ -x /usr/bin/dnf ]; then
    dnf -y install wget >> $log
  elif [ -x /usr/bin/yum ]; then
    yum -y install wget >> $log
  elif [ -x /usr/bin/apt-get ]; then
    apt-get update >> /dev/null
    apt-get -y -q install wget >> $log
  fi
done
if [ -z "$download" ]; then
  echo "Tried to install downloader, but failed. Do you have working network and DNS?"
fi
printf "found %s\\n" "$download" >> $log

# Check for gpg, debian 10 doesn't install by default!?
if [ -x /usr/bin/apt-get ]; then
  if [ ! -x /usr/bin/gpg ]; then
    printf "gpg not found, attempting to install..." >> $log
    apt-get update >> /dev/null
    apt-get -y -q install gnupg >> $log
  fi
fi

arch="$(uname -m)"
if [ "$arch" = "i686" ]; then
  arch="i386"
fi
if [ "$SERIAL" = "GPL" ]; then
  LOGIN=""
  PRODUCT="GPL"
  repopath="gpl/"
else
  LOGIN="$SERIAL:$KEY@"
  PRODUCT="Professional"
  repopath=""
fi

# Virtualmin-provided packages
vmgroup="'Virtualmin Core'"
debvmpackages="virtualmin-core"
deps=
sclgroup="'Software Collections PHP 7.2 Environment'"

# This has to be installed before anything else, so it can be disabled during
# install, and turned back on after. This is ridiculous.
debpredeps="fail2ban"

if [ "$mode" = 'full' ]; then
  if [ "$bundle" = 'LAMP' ]; then
    rhgroup="'Virtualmin LAMP Stack'"
    debdeps="postfix virtualmin-lamp-stack"
    ubudeps="postfix virtualmin-lamp-stack"
  elif [ "$bundle" = 'LEMP' ]; then
    rhgroup="'Virtualmin LEMP Stack'"
    debdeps="postfix php*-fpm virtualmin-lemp-stack"
    ubudeps="postfix php*-fpm virtualmin-lemp-stack"
  fi
elif [ "$mode" = 'minimal' ]; then
  if [ "$bundle" = 'LAMP' ]; then
    rhgroup="'Virtualmin LAMP Stack Minimal'"
    debdeps="postfix virtualmin-lamp-stack-minimal"
    ubudeps="postfix virtualmin-lamp-stack-minimal"
  elif [ "$bundle" = 'LEMP' ]; then
    rhgroup="'Virtualmin LEMP Stack Minimal'"
    debdeps="postfix php*-fpm virtualmin-lemp-stack-minimal"
    ubudeps="postfix php*-fpm virtualmin-lemp-stack-minimal"
  fi
fi

# Find temp directory
if [ -z "$TMPDIR" ]; then
  TMPDIR=/tmp
fi

# Check whether $TMPDIR is mounted noexec (everything will fail, if so)
# XXX: This check is imperfect. If $TMPDIR is a full path, but the parent dir
# is mounted noexec, this won't catch it.
TMPNOEXEC="$(grep $TMPDIR /etc/mtab | grep noexec)"
if [ -n "$TMPNOEXEC" ]; then
  echo "${RED}Fatal:${NORMAL} $TMPDIR directory is mounted noexec. Installation cannot continue."
  exit 1
fi

if [ -z "$tempdir" ]; then
  tempdir="$TMPDIR/.virtualmin-$$"
  if [ -e "$tempdir" ]; then
    rm -rf "$tempdir"
  fi
  mkdir "$tempdir"
fi

# "files" subdir for libs
mkdir "$tempdir/files"
srcdir="$tempdir/files"
if ! cd "$srcdir"; then
  echo "Failed to cd to $srcdir"
  exit 1
fi

# Download the slib (source: http://github.com/virtualmin/slib)
# Lots of little utility functions.
$download https://software.virtualmin.com/lib/slib.sh
chmod +x slib.sh
# shellcheck disable=SC1091
. ./slib.sh

# Check the serial number and key
serial_ok "$SERIAL" "$KEY"
# Setup slog
# shellcheck disable=SC2034
LOG_PATH="$log"
# Setup run_ok
# shellcheck disable=SC2034
RUN_LOG="$log"
# Exit on any failure during shell stage
# shellcheck disable=SC2034
RUN_ERRORS_FATAL=1

# Console output level; ignore debug level messages.
if [ "$VERBOSE" = "1" ]; then
  # shellcheck disable=SC2034
  LOG_LEVEL_STDOUT="DEBUG"
else
  # shellcheck disable=SC2034
  LOG_LEVEL_STDOUT="INFO"
fi
# Log file output level; catch literally everything.
# shellcheck disable=SC2034
LOG_LEVEL_LOG="DEBUG"

# log_fatal calls log_error
log_fatal() {
  log_error "$1"
}

remove_virtualmin_release () {
  # shellcheck disable=SC2154
  case "$os_type" in
    "fedora" | "centos" | "rhel" | "amazon" )
    run_ok "rpm -e virtualmin-release" "Removing virtualmin-release"
    ;;
    "debian" | "ubuntu" )
    grep -v "virtualmin" /etc/apt/sources.list > "$tempdir"/sources.list
    mv "$tempdir"/sources.list /etc/apt/sources.list
    rm -f /etc/apt/sources.list.d/virtualmin.list
    ;;
  esac
}

fatal () {
  echo
  log_fatal "Fatal Error Occurred: $1"
  printf "${RED}Cannot continue installation.${NORMAL}\\n"
  remove_virtualmin_release
  if [ -x "$tempdir" ]; then
    log_warning "Removing temporary directory and files."
    rm -rf "$tempdir"
  fi
  log_fatal "If you are unsure of what went wrong, you may wish to review the log"
  log_fatal "in $log"
  exit 1
}

success () {
  log_success "$1 Succeeded."
}

# Function to find out if Virtualmin is already installed, so we can get
# rid of some of the warning message. Nobody reads it, and frequently
# folks run the install script on a production system; either to attempt
# to upgrade, or to "fix" something. That's never the right thing.
is_installed () {
  if [ -f /etc/virtualmin-license ]; then
    # looks like it's been installed before
    return 0
  fi
  # XXX Probably not installed? Maybe we should remove license on uninstall, too.
  return 1
}

# This function performs a rough uninstallation of Virtualmin
# It is neither complete, nor correct, but it almost certainly won't break
# anything.  It is primarily useful for cleaning up a botched install, so you
# can run the installer again.
uninstall () {
  # Very destructive, ask first.
  echo
  printf "  ${REDBG}WARNING${NORMAL}\\n"
  echo
  echo "  This operation is very destructive. It removes nearly all of the packages"
  echo "  installed by the Virtualmin installer. Never run this on a production system."
  echo
  printf " Continue? (y/n) "
  if ! yesno; then
    exit
  fi

  # This is a crummy way to detect package manager...but going through
  # half the installer just to get here is even crummier.
  if which rpm 1>/dev/null 2>&1; then package_type=rpm
  elif which dpkg 1>/dev/null 2>&1; then package_type=deb
  fi

case "$package_type" in
  rpm)
  yum groupremove -y --setopt="groupremove_leaf_only=true" "Virtualmin Core"
  yum groupremove -y --setopt="groupremove_leaf_only=true" "Virtualmin LAMP Stack"
  yum groupremove -y --setopt="groupremove_leaf_only=true" "Virtualmin LEMP Stack"
  yum groupremove -y --setopt="groupremove_leaf_only=true" "Virtualmin LAMP Stack Minimal"
  yum groupremove -y --setopt="groupremove_leaf_only=true" "Virtualmin LEMP Stack Minimal"
  yum remove -y virtualmin-base
  yum remove -y wbm-virtual-server wbm-virtualmin-htpasswd wbm-virtualmin-dav wbm-virtualmin-mailman wbm-virtualmin-awstats wbm-php-pear wbm-ruby-gems wbm-virtualmin-registrar wbm-virtualmin-init wbm-jailkit wbm-virtualmin-git wbm-virtualmin-slavedns wbm-virtual-server wbm-virtualmin-sqlite wbm-virtualmin-svn
  yum remove -y wbt-virtual-server-mobile
  yum remove -y virtualmin-config perl-Term-Spinner-Color
  yum remove -y webmin usermin awstats
  yum remove -y nginx
  yum remove -y fail2ban
  yum clean all; yum clean all
  os_type="centos"
  ;;
  deb)
  rm -rf /etc/fail2ban/jail.d/00-firewalld.conf
  rm -f /etc/fail2ban/jail.local
  apt-get remove --assume-yes --purge virtualmin-base virtualmin-core virtualmin-lamp-stack virtualmin-lemp-stack
  apt-get remove --assume-yes --purge virtualmin-lamp-stack-minimal virtualmin-lemp-stack-minimal
  apt-get remove --assume-yes --purge virtualmin-config libterm-spinner-color-perl
  apt-get remove --assume-yes --purge webmin-virtual-server webmin-virtualmin-htpasswd webmin-virtualmin-git webmin-virtualmin-slavedns webmin-virtualmin-dav webmin-virtualmin-mailman webmin-virtualmin-awstats webmin-php-pear webmin-ruby-gems webmin-virtualmin-registrar webmin-virtualmin-init webmin-jailkit webmin-virtual-server webmin-virtualmin-sqlite webmin-virtualmin-svn
  apt-get remove --assume-yes --purge webmin-virtual-server-mobile
  apt-get remove --assume-yes --purge fail2ban
  apt-get remove --assume-yes --purge apache2*
  apt-get remove --assume-yes --purge nginx*
  apt-get remove --assume-yes --purge webmin usermin
  apt-get autoremove --assume-yes
  os_type="debian"
  apt-get clean
  ;;
  *)
  echo "I don't know how to uninstall on this operating system."
  ;;
esac
echo 'Removing nameserver 127.0.0.1 from /etc/resolv.conf'
sed -i '/nameserver 127.0.0.1/g' /etc/resolv.conf
echo 'Removing virtualmin repo configuration'
remove_virtualmin_release
echo "Removing /etc/virtualmin-license, if it exists."
rm /etc/virtualmin-license
echo "Done.  There's probably quite a bit of related packages and such left behind"
echo "but all of the Virtualmin-specific packages have been removed."
exit 0
}
if [ "$mode" = "uninstall" ]; then
  uninstall
fi

# Calculate disk space requirements (this is a guess, for now)
if [ "$mode" = 'minimal' ]; then
  disk_space_required=500
else
  disk_space_required=650
fi

# Message to display in interactive mode
install_msg() {
cat <<EOF

  Welcome to the Virtualmin ${GREEN}$PRODUCT${NORMAL} installer, version ${GREEN}$VER${NORMAL}

  This script must be run on a freshly installed supported OS. It does not
  perform updates or upgrades (use your system package manager) or license
  changes (use the "virtualmin change-license" command).

  The systems currently supported by install.sh are:

EOF
echo "${CYAN}$supported${NORMAL}"
cat <<EOF

  If your OS/version/arch is not listed, installation ${RED}will fail${NORMAL}. More
  details about the systems supported by the script can be found here:

    ${UNDERLINE}https://www.virtualmin.com/os-support${NORMAL}

  The selected package bundle is ${CYAN}${bundle}${NORMAL} and the size of install is
  ${CYAN}${mode}${NORMAL}. It will require up to ${CYAN}${disk_space_required} MB${NORMAL} of disk space.

  Exit and re-run this script with ${CYAN}--help${NORMAL} flag to see available options.

EOF

  printf " Continue? (y/n) "
  if ! yesno; then
    exit
  fi
}
if [ "$skipyesno" -ne 1 ] && [ -z "$setup_only" ]; then
  install_msg
fi

already_installed_msg() {
  # Double check if installed, just in case above error ignored.
  if is_installed; then
cat <<EOF

  ${REDBG}WARNING${NORMAL}

  Virtualmin may already be installed. This can happen if an installation failed,
  and can be ignored in that case.

  But, if Virtualmin has already successfully installed you should not run this
  script again! It will cause breakage to your existing configuration.

  Updates and upgrades can be performed from within Virtualmin. To change
  license details, use the 'virtualmin change-license' command.

  Changing the license never requires re-installation.

EOF
    printf " Really Continue? (y/n) "
    if ! yesno; then
      exit
    fi
  fi
}
if [ "$skipyesno" -ne 1 ] && [ -z "$setup_only" ]; then
  already_installed_msg
fi

# Check memory
if [ "$mode" = "full" ]; then
  minimum_memory=1610613
else
  # minimal mode probably needs less memory to succeed
  minimum_memory=1048576
fi
if ! memory_ok "$minimum_memory"; then
  log_fatal "Too little memory, and unable to create a swap file. Consider adding swap"
  log_fatal "or more RAM to your system."
  exit 1
fi

# Check for localhost in /etc/hosts
if [ -z "$setup_only" ]; then
  grep localhost /etc/hosts >/dev/null
  if [ "$?" != 0 ]; then
    log_warning "There is no localhost entry in /etc/hosts. This is required, so one will be added."
    run_ok "echo 127.0.0.1 localhost >> /etc/hosts" "Editing /etc/hosts"
    if [ "$?" -ne 0 ]; then
      log_error "Failed to configure a localhost entry in /etc/hosts."
      log_error "This may cause problems, but we'll try to continue."
    fi
  fi
fi

# download()
# Use $download to download the provided filename or exit with an error.
download() {
  # XXX Check this to make sure run_ok is doing the right thing.
  # Especially make sure failure gets logged right.
  # awk magic prints the filename, rather than whole URL
  download_file=$(echo "$1" |awk -F/ '{print $NF}')
  run_ok "$download $1" "Downloading $download_file"
  if [ $? -ne 0 ]; then
    fatal "Failed to download $1. Cannot continue. Check your network connection and DNS settings."
  else
    return 0
  fi
}

# Only root can run this
id | grep -i "uid=0(" >/dev/null
if [ "$?" != "0" ]; then
  uname -a | grep -i CYGWIN >/dev/null
  if [ "$?" != "0" ]; then
    fatal "${RED}Fatal:${NORMAL} The Virtualmin install script must be run as root"
  fi
fi

log_info "Started installation log in $log"
echo
if [ -n "$setup_only" ]; then
  log_debug "Phase 1 of 1: Setup"
  printf "${YELLOW}▣${NORMAL} Phase ${YELLOW}1${NORMAL} of ${GREEN}1${NORMAL}: Setup\\n"
else
  log_debug "Phase 1 of 3: Setup"
  printf "${YELLOW}▣${CYAN}□□${NORMAL} Phase ${YELLOW}1${NORMAL} of ${GREEN}3${NORMAL}: Setup\\n"
fi

# Print out some details that we gather before logging existed
log_debug "Install mode: $mode"
log_debug "Product: Virtualmin $PRODUCT"
log_debug "install.sh version: $VER"

# Check for a fully qualified hostname
log_debug "Checking for fully qualified hostname..."
name="$(hostname -f)"
if [ -n "$forcehostname" ]; then set_hostname "$forcehostname"
elif ! is_fully_qualified "$name"; then set_hostname
fi

# Insert the serial number and password into /etc/virtualmin-license
log_debug "Installing serial number and license key into /etc/virtualmin-license"
echo "SerialNumber=$SERIAL" > /etc/virtualmin-license
echo "LicenseKey=$KEY" >> /etc/virtualmin-license
chmod 700 /etc/virtualmin-license
cd ..

# Populate some distro version globals
get_distro
log_debug "Operating system name:    $os_real"
log_debug "Operating system version: $os_version"
log_debug "Operating system type:    $os_type"
log_debug "Operating system major:   $os_major_version"

install_virtualmin_release () {
  # Grab virtualmin-release from the server
  log_debug "Configuring package manager for ${os_real} ${os_version}..."
  case "$os_type" in
    rhel|centos|fedora|amazon)
    case "$os_type" in
      rhel|centos)
      if [ "$os_major_version" -lt 7 ]; then
        printf "${RED}${os_type} ${os_version} is not supported by this installer.${NORMAL}\\n"
        exit 1
      fi
      ;;
      fedora)
      if [ "$os_version" -lt 33 ]; then
        printf "${RED}${os_type} ${os_version} is not supported by this installer.${NORMAL}\\n"
        exit 1
      fi
      ;;
      ubuntu)
      if [ "$os_version" != "16.04" ] && [ "$os_version" != "18.04" ] && [ "$os_version" != "20.04" ]; then
        printf "${RED}${os_type} ${os_version} is not supported by this installer.${NORMAL}\\n"
        exit 1
      fi
      ;;
      debian)
      if [ "$os_major_version" -lt 9 ]; then
        printf "${RED}${os_type} ${os_version} is not supported by this installer.${NORMAL}\\n"
        exit 1
      fi
      ;;
      *)
      printf "${RED}This OS/version is not recognized. Can't continue.${NORMAL}\\n"
      exit 1
      ;;
    esac
    if [ -x /usr/sbin/setenforce ]; then
      log_debug "Disabling SELinux during installation..."
      if /usr/sbin/setenforce 0; then log_debug " setenforce 0 succeeded"
    else log_debug "  setenforce 0 failed: $?"
    fi
  fi
  package_type="rpm"
  if which dnf 1>/dev/null 2>&1; then
    install="dnf -y install"
    install_cmd="dnf"
    install_group="dnf -y --quiet group install --setopt=group_package_types=mandatory,default"
    install_config_manager="dnf config-manager"
    if ! $install_config_manager 1>/dev/null 2>&1; then
      run_ok "$install dnf-plugins-core"
    fi
  else
    install="/usr/bin/yum -y install"
    install_cmd="/usr/bin/yum"
    if [ "$os_major_version" -ge 7 ]; then
      run_ok "yum --quiet groups mark convert" "Updating yum Groups"
    fi
    install_group="yum -y --quiet groupinstall --setopt=group_package_types=mandatory,default"
    install_config_manager="yum-config-manager"
  fi
  download "https://${LOGIN}software.virtualmin.com/vm/${vm_version}/${repopath}${os_type}/${os_major_version}/${arch}/virtualmin-release-latest.noarch.rpm"
  run_ok "rpm -U --replacepkgs --quiet virtualmin-release-latest.noarch.rpm" "Installing virtualmin-release package"
  # XXX This weirdly only seems necessary on CentOS 8, but harmless
  # elsewhere.
  rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-webmin
  ;;
  debian | ubuntu)
  package_type="deb"
  if [ "$os_type" = "ubuntu" ]; then
    deps="$ubudeps"
    case "$os_version" in
      16.04*)
      repos="virtualmin-xenial virtualmin-universal"
      ;;
      18.04*)
      repos="virtualmin-bionic virtualmin-universal"
      ;;
      20.04*)
      repos="virtualmin-focal virtualmin-universal"
      ;;
    esac
  else
    deps="$debdeps"
    case "$os_version" in
      8*)
      run_ok "apt-get install --assume-yes apt-transport-https lsb-release ca-certificates" "Installing extra dependencies for Debian 8"
      download 'https://packages.sury.org/php/apt.gpg'
      run_ok "cp apt.gpg /etc/apt/trusted.gpg.d/php.gpg" "Adding GPG key for PHP7 packages"
      echo "deb http://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
      repos="virtualmin-jessie virtualmin-universal"
      ;;
      9*)
      repos="virtualmin-stretch virtualmin-universal"
      ;;
      10*)
      repos="virtualmin-buster virtualmin-universal"
      ;;
    esac
  fi
  log_debug "apt-get repos: ${repos}"
  if [ -z "$repos" ]; then # Probably unstable with no version number
    log_fatal "No repos available for this OS. Are you running unstable/testing?"
    exit 1
  fi
  # Remove any existing repo config, in case it's a reinstall
  remove_virtualmin_release
  for repo in $repos; do
    printf "deb http://${LOGIN}software.virtualmin.com/vm/${vm_version}/${repopath}apt ${repo} main\\n" >> /etc/apt/sources.list.d/virtualmin.list
  done
  # Install our keys
  log_debug "Installing Webmin and Virtualmin package signing keys..."
  download "https://software.virtualmin.com/lib/RPM-GPG-KEY-virtualmin-6"
  download "https://software.virtualmin.com/lib/RPM-GPG-KEY-webmin"
  run_ok "apt-key add RPM-GPG-KEY-virtualmin-6" "Installing Virtualmin 6 key"
  run_ok "apt-key add RPM-GPG-KEY-webmin" "Installing Webmin key"
  run_ok "apt-get update" "Updating apt metadata"
  run_ok "apt-get update" "Downloading repository metadata"
  # Make sure universe repos are available
  # XXX Test to make sure this run_ok syntax works as expected (with single quotes inside double)
  if [ $os_type = "ubuntu" ]; then
    if [ -x "/bin/add-apt-repository" ] || [ -x "/usr/bin/add-apt-repository" ]; then 
      run_ok "add-apt-repository universe" \
        "Enabling universe repositories, if not already available"
    else
      run_ok "sed -ie '/backports/b; s/#*[ ]*deb \\(.*\\) universe$/deb \\1 universe/' /etc/apt/sources.list" \
        "Enabling universe repositories, if not already available"
    fi
  fi
  # XXX Is this still enabled by default on Debian/Ubuntu systems?
  run_ok "sed -ie 's/^deb cdrom:/#deb cdrom:/' /etc/apt/sources.list" "Disabling cdrom: repositories"
  install="DEBIAN_FRONTEND='noninteractive' /usr/bin/apt-get --quiet --assume-yes --install-recommends -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' -o Dpkg::Pre-Install-Pkgs::='/usr/sbin/dpkg-preconfigure --apt' install"
  #export DEBIAN_FRONTEND=noninteractive
  install_updates="$install $deps"
  run_ok "apt-get clean" "Cleaning out old metadata"
  sed -i "s/\\(deb[[:space:]]file.*\\)/#\\1/" /etc/apt/sources.list
  ;;
  *)
  log_error " Your OS is not currently supported by this installer."
  log_error " You can probably run Virtualmin Professional on your system, anyway,"
  log_error " but you'll have to install it using the manual installation process."
  exit 1
  ;;
esac

return 0
}
if [ -n "$setup_only" ]; then
  if install_virtualmin_release; then
    log_success "Repository configuration successful. You can now install Virtualmin"
    log_success "components using your OS package manager."
  else
    log_error "Errors occurred during setup of Virtualmin software repositories. You may find more"
    log_error "information in ${RUN_LOG}."
  fi
  exit $?
fi

# Install Functions
install_with_apt () {
  # Install Webmin first, because it needs to be already done for the deps
  run_ok "$install webmin" "Installing Webmin"
  run_ok "$install usermin" "Installing Usermin"
  for d in $debpredeps; do
    run_ok "$install $d" "Installing $d"
  done
  if [ $bundle = 'LEMP' ]; then
    # This is bloody awful. I can't believe how fragile dpkg is here.
    for s in fail2ban ipchains apache2; do
      systemctl stop "$s">>${RUN_LOG} 2>&1
      systemctl disable "$s">>${RUN_LOG} 2>&1
    done
    run_ok 'apt-get remove --assume-yes --purge apache2* php*' 'Removing apache2 (if installed) before LEMP installation.'
    run_ok 'apt-get autoremove --assume-yes' 'Removing unneeded packages that could conflict with LEMP stack.'
    run_ok "$install nginx-common" "Installing nginx-common"
    sed -i 's/listen \[::\]:80 default_server;/#listen \[::\]:80 default_server;/' /etc/nginx/sites-available/default
  else
    # This is bloody awful. I can't believe how fragile dpkg is here.
    for s in fail2ban nginx; do
      systemctl stop "$s">>${RUN_LOG} 2>&1
      systemctl disable "$s">>${RUN_LOG} 2>&1
    done
    run_ok 'apt-get remove --assume-yes --purge nginx* php*' 'Removing nginx (if installed) before LAMP installation.'
    run_ok 'apt-get autoremove --assume-yes' 'Removing unneeded packages that could conflict with LAMP stack.'
  fi
  for d in ${deps}; do
    run_ok "$install ${d}" "Installing $d"
  done
  run_ok "$install ${debvmpackages}" "Installing Virtualmin and plugins"
  if [ $? -ne 0 ]; then
    log_warning "apt-get seems to have failed. Are you sure your OS and version is supported?"
    log_warning "https://www.virtualmin.com/os-support"
    fatal "Installation failed: $?"
  fi

  # Make sure the time is set properly
  /usr/sbin/ntpdate-debian 2>/dev/null 2>&1

  return 0
}

install_with_yum () {
  # RHEL 8 specific setup
  if [ "$os_major_version" -ge 8 ] && [ "$os_type" = "rhel" ]; then
    # Important Perl packages are now hidden in CodeReady repo
    run_ok "$install_config_manager --set-enabled codeready-builder-for-rhel-$os_major_version-x86_64-rpms" "Enabling Red Hat CodeReady package repository"
    run_ok "$install https://dl.fedoraproject.org/pub/epel/epel-release-latest-$os_major_version.noarch.rpm" "Installing EPEL $os_major_version release package"
  # RHEL 7 specific setup
  elif [ "$os_major_version" -eq 7 ] && [ "$os_type" = "rhel" ]; then
    run_ok "$install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm" "Installing EPEL 7 release package"
  # install extras from EPEL and SCL
  elif [ "$os_type" = "centos" ]; then
    install_epel_release
    if [ "$os_major_version" -lt 8 ]; then
      # No SCL on CentOS 8
      install_scl_php
    fi
  fi

  # Important Perl packages are now hidden in PowerTools repo
  if [ "$os_major_version" -eq 8 ] && [ "$os_type" = "centos" ]; then
    # Detect PowerTools repo name
    powertools="PowerTools"
    centos_stream=$(dnf repolist all | grep "^powertools")
      if [ ! -z "$centos_stream" ]; then
        powertools="powertools"
      fi
    run_ok "$install_config_manager --set-enabled $powertools" "Enabling PowerTools package repository"
  fi

  # XXX This is so stupid. Why does yum insist on extra commands?
  if [ "$os_major_version" -eq 7 ]; then
    run_ok "yum --quiet groups mark install $rhgroup" "Marking $rhgroup for install"
    run_ok "yum --quiet groups mark install $vmgroup" "Marking $vmgroup for install"
  fi
  run_ok "$install_group $rhgroup" "Installing dependencies and system packages"
  run_ok "$install_group $vmgroup" "Installing Virtualmin and all related packages"
  if [ $? -ne 0 ]; then
    fatal "Installation failed: $?"
  fi

  run_ok "$install_cmd clean all" "Cleaning up software repo metadata"

  return 0
}

install_virtualmin () {
  case "$package_type" in
    rpm)
    install_with_yum
    ;;
    deb)
    install_with_apt
    ;;
    *)
    install_with_tar
    ;;
  esac
  if [ $? -eq 0 ]; then
    return 0
  else
    return $?
  fi
}

install_epel_release () {
  if [ -z "$DISABLE_EPEL" ]; then
    run_ok "$install epel-release" "Installing EPEL release package"
  fi
}

install_scl_php () {
  if [ -z "$DISABLE_SCL" ]; then
    run_ok "$install yum-utils" "Installing yum-utils"
    run_ok "$install_config_manager --enable extras >/dev/null" "Enabling extras repository"
    run_ok "$install scl-utils" "Installing scl-utils"
    if [ "${os_type}" = "centos" ]; then
      run_ok "$install centos-release-scl" "Install Software Collections release package"
    elif [ "${os_type}" = "rhel" ]; then
      run_ok "$install_config_manager --enable rhel-server-rhscl-${os_major_version}-rpms" "Enabling Server Software Collection"
    fi
    run_ok "$install_group $sclgroup" "Installing PHP7"
  fi
}

# virtualmin-release only exists for one platform...but it's as good a function
# name as any, I guess.  Should just be "setup_repositories" or something.
errors=$((0))
install_virtualmin_release
echo
log_debug "Phase 2 of 3: Installation"
printf "${GREEN}▣${YELLOW}▣${CYAN}□${NORMAL} Phase ${YELLOW}2${NORMAL} of ${GREEN}3${NORMAL}: Installation\\n"
install_virtualmin
if [ "$?" != "0" ]; then
  errorlist="${errorlist}  ${YELLOW}◉${NORMAL} Package installation returned an error.\\n"
  errors=$((errors + 1))
fi

# We want to make sure we're running our version of packages if we have
# our own version.  There's no good way to do this, but we'll
run_ok "$install_updates" "Installing updates to Virtualmin-related packages"
if [ "$?" != "0" ]; then
  errorlist="${errorlist}  ${YELLOW}◉${NORMAL} Installing updates returned an error.\\n"
  errors=$((errors + 1))
fi

# Reap any clingy processes (like spinner forks)
# get the parent pids (as those are the problem)
allpids="$(ps -o pid= --ppid $$) $allpids"
for pid in $allpids; do
  kill "$pid" 1>/dev/null 2>&1
done

# Final step is configuration. Wait here for a moment, hopefully letting any
# apt processes disappear before we start, as they're huge and memory is a
# problem. XXX This is hacky. I'm not sure what's really causing random fails.
sleep 1
echo
log_debug "Phase 3 of 3: Configuration"
printf "${GREEN}▣▣${YELLOW}▣${NORMAL} Phase ${YELLOW}3${NORMAL} of ${GREEN}3${NORMAL}: Configuration\\n"
if [ "$mode" = "minimal" ]; then
  bundle="Mini${bundle}"
fi
virtualmin-config-system --bundle "$bundle"
if [ "$?" != "0" ]; then
  errorlist="${errorlist}  ${YELLOW}◉${NORMAL} Postinstall configuration returned an error.\\n"
  errors=$((errors + 1))
fi
config_system_pid=$!

# Functions that are used in the OS specific modifications section
disable_selinux () {
  seconfigfiles="/etc/selinux/config /etc/sysconfig/selinux"
  for i in $seconfigfiles; do
    if [ -e "$i" ]; then
      perl -pi -e 's/^SELINUX=.*/SELINUX=disabled/' "$i"
    fi
  done
}

# Changes that are specific to OS
case "$os_type" in
  "fedora" | "centos" | "rhel" | "amazon" )
  disable_selinux
  ;;
esac


# kill the virtualmin config-system command, if it's still running
kill "$config_system_pid" 1>/dev/null 2>&1
# Make sure the cursor is back (if spinners misbehaved)
tput cnorm


printf "${GREEN}▣▣▣${NORMAL} Cleaning up\\n"
# Cleanup the tmp files
if [ "$tempdir" != "" ] && [ "$tempdir" != "/" ]; then
  log_debug "Cleaning up temporary files in $tempdir."
  find "$tempdir" -delete
else
  log_error "Could not safely clean up temporary files because TMPDIR set to $tempdir."
fi

if [ -n "$QUOTA_FAILED" ]; then
  log_warning "Quotas were not configurable. A reboot may be required. Or, if this is"
  log_warning "a VM, configuration may be required at the host level."
fi
echo
if [ $errors -eq "0" ]; then
  hostname=$(hostname -f)
  detect_ip
  log_success "Installation Complete!"
  log_success "If there were no errors above, Virtualmin should be ready"
  log_success "to configure at https://${hostname}:10000 (or https://${address}:10000)."
  log_success "You'll receive a security warning in your browser on your first visit."
else
  log_warning "The following errors occurred during installation:"
  echo
  printf "${errorlist}"
fi

exit 0

Anon7 - 2022
SCDN GOK