PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/cpanel/ea-wappspector
Viewing File: /opt/cpanel/ea-wappspector/composer-installer.php
<?php /* * This file is part of Composer. * * (c) Nils Adermann <naderman@naderman.de> * Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ setupEnvironment(); process(is_array($argv) ? $argv : array()); /** * Initializes various values * * @throws RuntimeException If uopz extension prevents exit calls */ function setupEnvironment() { ini_set('display_errors', 1); if (extension_loaded('uopz') && !(ini_get('uopz.disable') || ini_get('uopz.exit'))) { // uopz works at opcode level and disables exit calls if (function_exists('uopz_allow_exit')) { @uopz_allow_exit(true); } else { throw new RuntimeException('The uopz extension ignores exit calls and breaks this installer.'); } } $installer = 'ComposerInstaller'; if (defined('PHP_WINDOWS_VERSION_MAJOR')) { if ($version = getenv('COMPOSERSETUP')) { $installer = sprintf('Composer-Setup.exe/%s', $version); } } define('COMPOSER_INSTALLER', $installer); } /** * Processes the installer */ function process($argv) { // Determine ANSI output from --ansi and --no-ansi flags setUseAnsi($argv); $help = in_array('--help', $argv) || in_array('-h', $argv); if ($help) { displayHelp(); exit(0); } $check = in_array('--check', $argv); $force = in_array('--force', $argv); $quiet = in_array('--quiet', $argv); $channel = 'stable'; if (in_array('--snapshot', $argv)) { $channel = 'snapshot'; } elseif (in_array('--preview', $argv)) { $channel = 'preview'; } elseif (in_array('--1', $argv)) { $channel = '1'; } elseif (in_array('--2', $argv)) { $channel = '2'; } elseif (in_array('--2.2', $argv)) { $channel = '2.2'; } $disableTls = in_array('--disable-tls', $argv); $installDir = getOptValue('--install-dir', $argv, false); $version = getOptValue('--version', $argv, false); $filename = getOptValue('--filename', $argv, 'composer.phar'); $cafile = getOptValue('--cafile', $argv, false); if (!checkParams($installDir, $version, $cafile)) { exit(1); } $ok = checkPlatform($warnings, $quiet, $disableTls, true); if ($check) { // Only show warnings if we haven't output any errors if ($ok) { showWarnings($warnings); showSecurityWarning($disableTls); } exit($ok ? 0 : 1); } if ($ok || $force) { if ($channel === '1' && !$quiet) { out('Warning: You forced the install of Composer 1.x via --1, but Composer 2.x is the latest stable version. Updating to it via composer self-update --stable is recommended.', 'error'); } $installer = new Installer($quiet, $disableTls, $cafile); if ($installer->run($version, $installDir, $filename, $channel)) { showWarnings($warnings); showSecurityWarning($disableTls); exit(0); } } exit(1); } /** * Displays the help */ function displayHelp() { echo <<<EOF Composer Installer ------------------ Options --help this help --check for checking environment only --force forces the installation --ansi force ANSI color output --no-ansi disable ANSI color output --quiet do not output unimportant messages --install-dir="..." accepts a target installation directory --preview install the latest version from the preview (alpha/beta/rc) channel instead of stable --snapshot install the latest version from the snapshot (dev builds) channel instead of stable --1 install the latest stable Composer 1.x (EOL) version --2 install the latest stable Composer 2.x version --2.2 install the latest stable Composer 2.2.x (LTS) version --version="..." accepts a specific version to install instead of the latest --filename="..." accepts a target filename (default: composer.phar) --disable-tls disable SSL/TLS security for file downloads --cafile="..." accepts a path to a Certificate Authority (CA) certificate file for SSL/TLS verification EOF; } /** * Sets the USE_ANSI define for colorizing output * * @param array $argv Command-line arguments */ function setUseAnsi($argv) { // --no-ansi wins over --ansi if (in_array('--no-ansi', $argv)) { define('USE_ANSI', false); } elseif (in_array('--ansi', $argv)) { define('USE_ANSI', true); } else { define('USE_ANSI', outputSupportsColor()); } } /** * Returns whether color output is supported * * @return bool */ function outputSupportsColor() { if (false !== getenv('NO_COLOR') || !defined('STDOUT')) { return false; } if ('Hyper' === getenv('TERM_PROGRAM')) { return true; } if (defined('PHP_WINDOWS_VERSION_BUILD')) { return (function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); } if (function_exists('stream_isatty')) { return stream_isatty(STDOUT); } if (function_exists('posix_isatty')) { return posix_isatty(STDOUT); } $stat = fstat(STDOUT); // Check if formatted mode is S_IFCHR return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; } /** * Returns the value of a command-line option * * @param string $opt The command-line option to check * @param array $argv Command-line arguments * @param mixed $default Default value to be returned * * @return mixed The command-line value or the default */ function getOptValue($opt, $argv, $default) { $optLength = strlen($opt); foreach ($argv as $key => $value) { $next = $key + 1; if (0 === strpos($value, $opt)) { if ($optLength === strlen($value) && isset($argv[$next])) { return trim($argv[$next]); } else { return trim(substr($value, $optLength + 1)); } } } return $default; } /** * Checks that user-supplied params are valid * * @param mixed $installDir The required istallation directory * @param mixed $version The required composer version to install * @param mixed $cafile Certificate Authority file * * @return bool True if the supplied params are okay */ function checkParams($installDir, $version, $cafile) { $result = true; if (false !== $installDir && !is_dir($installDir)) { out("The defined install dir ({$installDir}) does not exist.", 'info'); $result = false; } if (false !== $version && 1 !== preg_match('/^\d+\.\d+\.\d+(\-(alpha|beta|RC)\d*)*$/', $version)) { out("The defined install version ({$version}) does not match release pattern.", 'info'); $result = false; } if (false !== $cafile && (!file_exists($cafile) || !is_readable($cafile))) { out("The defined Certificate Authority (CA) cert file ({$cafile}) does not exist or is not readable.", 'info'); $result = false; } return $result; } /** * Checks the platform for possible issues running Composer * * Errors are written to the output, warnings are saved for later display. * * @param array $warnings Populated by method, to be shown later * @param bool $quiet Quiet mode * @param bool $disableTls Bypass tls * @param bool $install If we are installing, rather than diagnosing * * @return bool True if there are no errors */ function checkPlatform(&$warnings, $quiet, $disableTls, $install) { getPlatformIssues($errors, $warnings, $install); // Make openssl warning an error if tls has not been specifically disabled if (isset($warnings['openssl']) && !$disableTls) { $errors['openssl'] = $warnings['openssl']; unset($warnings['openssl']); } if (!empty($errors)) { // Composer-Setup.exe uses "Some settings" to flag platform errors out('Some settings on your machine make Composer unable to work properly.', 'error'); out('Make sure that you fix the issues listed below and run this script again:', 'error'); outputIssues($errors); return false; } if (empty($warnings) && !$quiet) { out('All settings correct for using Composer', 'success'); } return true; } /** * Checks platform configuration for common incompatibility issues * * @param array $errors Populated by method * @param array $warnings Populated by method * @param bool $install If we are installing, rather than diagnosing * * @return bool If any errors or warnings have been found */ function getPlatformIssues(&$errors, &$warnings, $install) { $errors = array(); $warnings = array(); if ($iniPath = php_ini_loaded_file()) { $iniMessage = PHP_EOL.'The php.ini used by your command-line PHP is: ' . $iniPath; } else { $iniMessage = PHP_EOL.'A php.ini file does not exist. You will have to create one.'; } $iniMessage .= PHP_EOL.'If you can not modify the ini file, you can also run `php -d option=value` to modify ini values on the fly. You can use -d multiple times.'; if (ini_get('detect_unicode')) { $errors['unicode'] = array( 'The detect_unicode setting must be disabled.', 'Add the following to the end of your `php.ini`:', ' detect_unicode = Off', $iniMessage ); } if (extension_loaded('suhosin')) { $suhosin = ini_get('suhosin.executor.include.whitelist'); $suhosinBlacklist = ini_get('suhosin.executor.include.blacklist'); if (false === stripos($suhosin, 'phar') && (!$suhosinBlacklist || false !== stripos($suhosinBlacklist, 'phar'))) { $errors['suhosin'] = array( 'The suhosin.executor.include.whitelist setting is incorrect.', 'Add the following to the end of your `php.ini` or suhosin.ini (Example path [for Debian]: /etc/php5/cli/conf.d/suhosin.ini):', ' suhosin.executor.include.whitelist = phar '.$suhosin, $iniMessage ); } } if (!function_exists('json_decode')) { $errors['json'] = array( 'The json extension is missing.', 'Install it or recompile php without --disable-json' ); } if (!extension_loaded('Phar')) { $errors['phar'] = array( 'The phar extension is missing.', 'Install it or recompile php without --disable-phar' ); } if (!extension_loaded('filter')) { $errors['filter'] = array( 'The filter extension is missing.', 'Install it or recompile php without --disable-filter' ); } if (!extension_loaded('hash')) { $errors['hash'] = array( 'The hash extension is missing.', 'Install it or recompile php without --disable-hash' ); } if (!extension_loaded('iconv') && !extension_loaded('mbstring')) { $errors['iconv_mbstring'] = array( 'The iconv OR mbstring extension is required and both are missing.', 'Install either of them or recompile php without --disable-iconv' ); } if (!ini_get('allow_url_fopen')) { $errors['allow_url_fopen'] = array( 'The allow_url_fopen setting is incorrect.', 'Add the following to the end of your `php.ini`:', ' allow_url_fopen = On', $iniMessage ); } if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) { $ioncube = ioncube_loader_version(); $errors['ioncube'] = array( 'Your ionCube Loader extension ('.$ioncube.') is incompatible with Phar files.', 'Upgrade to ionCube 4.0.9 or higher or remove this line (path may be different) from your `php.ini` to disable it:', ' zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so', $iniMessage ); } if (version_compare(PHP_VERSION, '5.3.2', '<')) { $errors['php'] = array( 'Your PHP ('.PHP_VERSION.') is too old, you must upgrade to PHP 5.3.2 or higher.' ); } if (version_compare(PHP_VERSION, '5.3.4', '<')) { $warnings['php'] = array( 'Your PHP ('.PHP_VERSION.') is quite old, upgrading to PHP 5.3.4 or higher is recommended.', 'Composer works with 5.3.2+ for most people, but there might be edge case issues.' ); } if (!extension_loaded('openssl')) { $warnings['openssl'] = array( 'The openssl extension is missing, which means that secure HTTPS transfers are impossible.', 'If possible you should enable it or recompile php with --with-openssl' ); } if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) { // Attempt to parse version number out, fallback to whole string value. $opensslVersion = trim(strstr(OPENSSL_VERSION_TEXT, ' ')); $opensslVersion = substr($opensslVersion, 0, strpos($opensslVersion, ' ')); $opensslVersion = $opensslVersion ? $opensslVersion : OPENSSL_VERSION_TEXT; $warnings['openssl_version'] = array( 'The OpenSSL library ('.$opensslVersion.') used by PHP does not support TLSv1.2 or TLSv1.1.', 'If possible you should upgrade OpenSSL to version 1.0.1 or above.' ); } if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) { $warnings['apc_cli'] = array( 'The apc.enable_cli setting is incorrect.', 'Add the following to the end of your `php.ini`:', ' apc.enable_cli = Off', $iniMessage ); } if (!$install && extension_loaded('xdebug')) { $warnings['xdebug_loaded'] = array( 'The xdebug extension is loaded, this can slow down Composer a little.', 'Disabling it when using Composer is recommended.' ); if (ini_get('xdebug.profiler_enabled')) { $warnings['xdebug_profile'] = array( 'The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.', 'Add the following to the end of your `php.ini` to disable it:', ' xdebug.profiler_enabled = 0', $iniMessage ); } } if (!extension_loaded('zlib')) { $warnings['zlib'] = array( 'The zlib extension is not loaded, this can slow down Composer a lot.', 'If possible, install it or recompile php with --with-zlib', $iniMessage ); } if (defined('PHP_WINDOWS_VERSION_BUILD') && (version_compare(PHP_VERSION, '7.2.23', '<') || (version_compare(PHP_VERSION, '7.3.0', '>=') && version_compare(PHP_VERSION, '7.3.10', '<')))) { $warnings['onedrive'] = array( 'The Windows OneDrive folder is not supported on PHP versions below 7.2.23 and 7.3.10.', 'Upgrade your PHP ('.PHP_VERSION.') to use this location with Composer.' ); } if (extension_loaded('uopz') && !(ini_get('uopz.disable') || ini_get('uopz.exit'))) { $warnings['uopz'] = array( 'The uopz extension ignores exit calls and may not work with all Composer commands.', 'Disabling it when using Composer is recommended.' ); } ob_start(); phpinfo(INFO_GENERAL); $phpinfo = ob_get_clean(); if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) { $configure = $match[1]; if (false !== strpos($configure, '--enable-sigchild')) { $warnings['sigchild'] = array( 'PHP was compiled with --enable-sigchild which can cause issues on some platforms.', 'Recompile it without this flag if possible, see also:', ' https://bugs.php.net/bug.php?id=22999' ); } if (false !== strpos($configure, '--with-curlwrappers')) { $warnings['curlwrappers'] = array( 'PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.', 'Recompile it without this flag if possible' ); } } // Stringify the message arrays foreach ($errors as $key => $value) { $errors[$key] = PHP_EOL.implode(PHP_EOL, $value); } foreach ($warnings as $key => $value) { $warnings[$key] = PHP_EOL.implode(PHP_EOL, $value); } return !empty($errors) || !empty($warnings); } /** * Outputs an array of issues * * @param array $issues */ function outputIssues($issues) { foreach ($issues as $issue) { out($issue, 'info'); } out(''); } /** * Outputs any warnings found * * @param array $warnings */ function showWarnings($warnings) { if (!empty($warnings)) { out('Some settings on your machine may cause stability issues with Composer.', 'error'); out('If you encounter issues, try to change the following:', 'error'); outputIssues($warnings); } } /** * Outputs an end of process warning if tls has been bypassed * * @param bool $disableTls Bypass tls */ function showSecurityWarning($disableTls) { if ($disableTls) { out('You have instructed the Installer not to enforce SSL/TLS security on remote HTTPS requests.', 'info'); out('This will leave all downloads during installation vulnerable to Man-In-The-Middle (MITM) attacks', 'info'); } } /** * colorize output */ function out($text, $color = null, $newLine = true) { $styles = array( 'success' => "\033[0;32m%s\033[0m", 'error' => "\033[31;31m%s\033[0m", 'info' => "\033[33;33m%s\033[0m" ); $format = '%s'; if (isset($styles[$color]) && USE_ANSI) { $format = $styles[$color]; } if ($newLine) { $format .= PHP_EOL; } printf($format, $text); } /** * Returns the system-dependent Composer home location, which may not exist * * @return string */ function getHomeDir() { $home = getenv('COMPOSER_HOME'); if ($home) { return $home; } $userDir = getUserDir(); if (defined('PHP_WINDOWS_VERSION_MAJOR')) { return $userDir.'/Composer'; } $dirs = array(); if (useXdg()) { // XDG Base Directory Specifications $xdgConfig = getenv('XDG_CONFIG_HOME'); if (!$xdgConfig) { $xdgConfig = $userDir . '/.config'; } $dirs[] = $xdgConfig . '/composer'; } $dirs[] = $userDir . '/.composer'; // select first dir which exists of: $XDG_CONFIG_HOME/composer or ~/.composer foreach ($dirs as $dir) { if (is_dir($dir)) { return $dir; } } // if none exists, we default to first defined one (XDG one if system uses it, or ~/.composer otherwise) return $dirs[0]; } /** * Returns the location of the user directory from the environment * @throws RuntimeException If the environment value does not exists * * @return string */ function getUserDir() { $userEnv = defined('PHP_WINDOWS_VERSION_MAJOR') ? 'APPDATA' : 'HOME'; $userDir = getenv($userEnv); if (!$userDir) { throw new RuntimeException('The '.$userEnv.' or COMPOSER_HOME environment variable must be set for composer to run correctly'); } return rtrim(strtr($userDir, '\\', '/'), '/'); } /** * @return bool */ function useXdg() { foreach (array_keys($_SERVER) as $key) { if (strpos($key, 'XDG_') === 0) { return true; } } if (is_dir('/etc/xdg')) { return true; } return false; } function validateCaFile($contents) { // assume the CA is valid if php is vulnerable to // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html if ( PHP_VERSION_ID <= 50327 || (PHP_VERSION_ID >= 50400 && PHP_VERSION_ID < 50422) || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50506) ) { return !empty($contents); } return (bool) openssl_x509_parse($contents); } class Installer { private $quiet; private $disableTls; private $cafile; private $displayPath; private $target; private $tmpFile; private $tmpCafile; private $baseUrl; private $algo; private $errHandler; private $httpClient; private $pubKeys = array(); private $installs = array(); /** * Constructor - must not do anything that throws an exception * * @param bool $quiet Quiet mode * @param bool $disableTls Bypass tls * @param mixed $cafile Path to CA bundle, or false */ public function __construct($quiet, $disableTls, $caFile) { if (($this->quiet = $quiet)) { ob_start(); } $this->disableTls = $disableTls; $this->cafile = $caFile; $this->errHandler = new ErrorHandler(); } /** * Runs the installer * * @param mixed $version Specific version to install, or false * @param mixed $installDir Specific installation directory, or false * @param string $filename Specific filename to save to, or composer.phar * @param string $channel Specific version channel to use * @throws Exception If anything other than a RuntimeException is caught * * @return bool If the installation succeeded */ public function run($version, $installDir, $filename, $channel) { try { $this->initTargets($installDir, $filename); $this->initTls(); $this->httpClient = new HttpClient($this->disableTls, $this->cafile); $result = $this->install($version, $channel); // in case --1 or --2 is passed, we leave the default channel for next self-update to stable if (1 === preg_match('{^\d+$}D', $channel)) { $channel = 'stable'; } if ($result && $channel !== 'stable' && !$version && defined('PHP_BINARY')) { $null = (defined('PHP_WINDOWS_VERSION_MAJOR') ? 'NUL' : '/dev/null'); @exec(escapeshellarg(PHP_BINARY) .' '.escapeshellarg($this->target).' self-update --'.$channel.' --set-channel-only -q > '.$null.' 2> '.$null, $output); } } catch (Exception $e) { $result = false; } // Always clean up $this->cleanUp($result); if (isset($e)) { // Rethrow anything that is not a RuntimeException if (!$e instanceof RuntimeException) { throw $e; } out($e->getMessage(), 'error'); } return $result; } /** * Initialization methods to set the required filenames and composer url * * @param mixed $installDir Specific installation directory, or false * @param string $filename Specific filename to save to, or composer.phar * @throws RuntimeException If the installation directory is not writable */ protected function initTargets($installDir, $filename) { $this->displayPath = ($installDir ? rtrim($installDir, '/').'/' : '').$filename; $installDir = $installDir ? realpath($installDir) : getcwd(); if (!is_writeable($installDir)) { throw new RuntimeException('The installation directory "'.$installDir.'" is not writable'); } $this->target = $installDir.DIRECTORY_SEPARATOR.$filename; $this->tmpFile = $installDir.DIRECTORY_SEPARATOR.basename($this->target, '.phar').'-temp.phar'; $uriScheme = $this->disableTls ? 'http' : 'https'; $this->baseUrl = $uriScheme.'://getcomposer.org'; } /** * A wrapper around methods to check tls and write public keys * @throws RuntimeException If SHA384 is not supported */ protected function initTls() { if ($this->disableTls) { return; } if (!in_array('sha384', array_map('strtolower', openssl_get_md_methods()))) { throw new RuntimeException('SHA384 is not supported by your openssl extension'); } $this->algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384'; $home = $this->getComposerHome(); $this->pubKeys = array( 'dev' => $this->installKey(self::getPKDev(), $home, 'keys.dev.pub'), 'tags' => $this->installKey(self::getPKTags(), $home, 'keys.tags.pub') ); if (empty($this->cafile) && !HttpClient::getSystemCaRootBundlePath()) { $this->cafile = $this->tmpCafile = $this->installKey(HttpClient::getPackagedCaFile(), $home, 'cacert-temp.pem'); } } /** * Returns the Composer home directory, creating it if required * @throws RuntimeException If the directory cannot be created * * @return string */ protected function getComposerHome() { $home = getHomeDir(); if (!is_dir($home)) { $this->errHandler->start(); if (!mkdir($home, 0777, true)) { throw new RuntimeException(sprintf( 'Unable to create Composer home directory "%s": %s', $home, $this->errHandler->message )); } $this->installs[] = $home; $this->errHandler->stop(); } return $home; } /** * Writes public key data to disc * * @param string $data The public key(s) in pem format * @param string $path The directory to write to * @param string $filename The name of the file * @throws RuntimeException If the file cannot be written * * @return string The path to the saved data */ protected function installKey($data, $path, $filename) { $this->errHandler->start(); $target = $path.DIRECTORY_SEPARATOR.$filename; $installed = file_exists($target); $write = file_put_contents($target, $data, LOCK_EX); @chmod($target, 0644); $this->errHandler->stop(); if (!$write) { throw new RuntimeException(sprintf('Unable to write %s to: %s', $filename, $path)); } if (!$installed) { $this->installs[] = $target; } return $target; } /** * The main install function * * @param mixed $version Specific version to install, or false * @param string $channel Version channel to use * * @return bool If the installation succeeded */ protected function install($version, $channel) { $retries = 3; $result = false; $infoMsg = 'Downloading...'; $infoType = 'info'; while ($retries--) { if (!$this->quiet) { out($infoMsg, $infoType); $infoMsg = 'Retrying...'; $infoType = 'error'; } if (!$this->getVersion($channel, $version, $url, $error)) { out($error, 'error'); continue; } if (!$this->downloadToTmp($url, $signature, $error)) { out($error, 'error'); continue; } if (!$this->verifyAndSave($version, $signature, $error)) { out($error, 'error'); continue; } $result = true; break; } if (!$this->quiet) { if ($result) { out(PHP_EOL."Composer (version {$version}) successfully installed to: {$this->target}", 'success'); out("Use it: php {$this->displayPath}", 'info'); out(''); } else { out('The download failed repeatedly, aborting.', 'error'); } } return $result; } /** * Sets the version url, downloading version data if required * * @param string $channel Version channel to use * @param false|string $version Version to install, or set by method * @param null|string $url The versioned url, set by method * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function getVersion($channel, &$version, &$url, &$error) { $error = ''; if ($version) { if (empty($url)) { $url = $this->baseUrl."/download/{$version}/composer.phar"; } return true; } $this->errHandler->start(); if ($this->downloadVersionData($data, $error)) { $this->parseVersionData($data, $channel, $version, $url); } $this->errHandler->stop(); return empty($error); } /** * Downloads and json-decodes version data * * @param null|array $data Downloaded version data, set by method * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function downloadVersionData(&$data, &$error) { $url = $this->baseUrl.'/versions'; $errFmt = 'The "%s" file could not be %s: %s'; if (!$json = $this->httpClient->get($url)) { $error = sprintf($errFmt, $url, 'downloaded', $this->errHandler->message); return false; } if (!$data = json_decode($json, true)) { $error = sprintf($errFmt, $url, 'json-decoded', $this->getJsonError()); return false; } return true; } /** * A wrapper around the methods needed to download and save the phar * * @param string $url The versioned download url * @param null|string $signature Set by method on successful download * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function downloadToTmp($url, &$signature, &$error) { $error = ''; $errFmt = 'The "%s" file could not be downloaded: %s'; $sigUrl = $url.'.sig'; $this->errHandler->start(); if (!$fh = fopen($this->tmpFile, 'w')) { $error = sprintf('Could not create file "%s": %s', $this->tmpFile, $this->errHandler->message); } elseif (!$this->getSignature($sigUrl, $signature)) { $error = sprintf($errFmt, $sigUrl, $this->errHandler->message); } elseif (!fwrite($fh, $this->httpClient->get($url))) { $error = sprintf($errFmt, $url, $this->errHandler->message); } if (is_resource($fh)) { fclose($fh); } $this->errHandler->stop(); return empty($error); } /** * Verifies the downloaded file and saves it to the target location * * @param string $version The composer version downloaded * @param string $signature The digital signature to check * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function verifyAndSave($version, $signature, &$error) { $error = ''; if (!$this->validatePhar($this->tmpFile, $pharError)) { $error = 'The download is corrupt: '.$pharError; } elseif (!$this->verifySignature($version, $signature, $this->tmpFile)) { $error = 'Signature mismatch, could not verify the phar file integrity'; } else { $this->errHandler->start(); if (!rename($this->tmpFile, $this->target)) { $error = sprintf('Could not write to file "%s": %s', $this->target, $this->errHandler->message); } chmod($this->target, 0755); $this->errHandler->stop(); } return empty($error); } /** * Parses an array of version data to match the required channel * * @param array $data Downloaded version data * @param mixed $channel Version channel to use * @param false|string $version Set by method * @param mixed $url The versioned url, set by method */ protected function parseVersionData(array $data, $channel, &$version, &$url) { foreach ($data[$channel] as $candidate) { if ($candidate['min-php'] <= PHP_VERSION_ID) { $version = $candidate['version']; $url = $this->baseUrl.$candidate['path']; break; } } if (!$version) { $error = sprintf( 'None of the %d %s version(s) of Composer matches your PHP version (%s / ID: %d)', count($data[$channel]), $channel, PHP_VERSION, PHP_VERSION_ID ); throw new RuntimeException($error); } } /** * Downloads the digital signature of required phar file * * @param string $url The signature url * @param null|string $signature Set by method on success * * @return bool If the download succeeded */ protected function getSignature($url, &$signature) { if (!$result = $this->disableTls) { $signature = $this->httpClient->get($url); if ($signature) { $signature = json_decode($signature, true); $signature = base64_decode($signature['sha384']); $result = true; } } return $result; } /** * Verifies the signature of the downloaded phar * * @param string $version The composer versione * @param string $signature The downloaded digital signature * @param string $file The temp phar file * * @return bool If the operation succeeded */ protected function verifySignature($version, $signature, $file) { if (!$result = $this->disableTls) { $path = preg_match('{^[0-9a-f]{40}$}', $version) ? $this->pubKeys['dev'] : $this->pubKeys['tags']; $pubkeyid = openssl_pkey_get_public('file://'.$path); $result = 1 === openssl_verify( file_get_contents($file), $signature, $pubkeyid, $this->algo ); // PHP 8 automatically frees the key instance and deprecates the function if (PHP_VERSION_ID < 80000) { openssl_free_key($pubkeyid); } } return $result; } /** * Validates the downloaded phar file * * @param string $pharFile The temp phar file * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function validatePhar($pharFile, &$error) { if (ini_get('phar.readonly')) { return true; } try { // Test the phar validity $phar = new Phar($pharFile); // Free the variable to unlock the file unset($phar); $result = true; } catch (Exception $e) { if (!$e instanceof UnexpectedValueException && !$e instanceof PharException) { throw $e; } $error = $e->getMessage(); $result = false; } return $result; } /** * Returns a string representation of the last json error * * @return string The error string or code */ protected function getJsonError() { if (function_exists('json_last_error_msg')) { return json_last_error_msg(); } else { return 'json_last_error = '.json_last_error(); } } /** * Cleans up resources at the end of the installation * * @param bool $result If the installation succeeded */ protected function cleanUp($result) { if (!$result) { // Output buffered errors if ($this->quiet) { $this->outputErrors(); } // Clean up stuff we created $this->uninstall(); } elseif ($this->tmpCafile) { @unlink($this->tmpCafile); } } /** * Outputs unique errors when in quiet mode * */ protected function outputErrors() { $errors = explode(PHP_EOL, ob_get_clean()); $shown = array(); foreach ($errors as $error) { if ($error && !in_array($error, $shown)) { out($error, 'error'); $shown[] = $error; } } } /** * Uninstalls newly-created files and directories on failure * */ protected function uninstall() { foreach (array_reverse($this->installs) as $target) { if (is_file($target)) { @unlink($target); } elseif (is_dir($target)) { @rmdir($target); } } if ($this->tmpFile !== null && file_exists($this->tmpFile)) { @unlink($this->tmpFile); } } public static function getPKDev() { return <<<PKDEV -----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ== -----END PUBLIC KEY----- PKDEV; } public static function getPKTags() { return <<<PKTAGS -----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95 RGv89BPD+2DLnJysngsvVaUCAwEAAQ== -----END PUBLIC KEY----- PKTAGS; } } class ErrorHandler { public $message; protected $active; /** * Handle php errors * * @param mixed $code The error code * @param mixed $msg The error message */ public function handleError($code, $msg) { if ($this->message) { $this->message .= PHP_EOL; } $this->message .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg); } /** * Starts error-handling if not already active * * Any message is cleared */ public function start() { if (!$this->active) { set_error_handler(array($this, 'handleError')); $this->active = true; } $this->message = ''; } /** * Stops error-handling if active * * Any message is preserved until the next call to start() */ public function stop() { if ($this->active) { restore_error_handler(); $this->active = false; } } } class NoProxyPattern { private $composerInNoProxy = false; private $rulePorts = array(); public function __construct($pattern) { $rules = preg_split('{[\s,]+}', $pattern, null, PREG_SPLIT_NO_EMPTY); if ($matches = preg_grep('{getcomposer\.org(?::\d+)?}i', $rules)) { $this->composerInNoProxy = true; foreach ($matches as $match) { if (strpos($match, ':') !== false) { list(, $port) = explode(':', $match); $this->rulePorts[] = (int) $port; } } } } /** * Returns true if NO_PROXY contains getcomposer.org * * @param string $url http(s)://getcomposer.org * * @return bool */ public function test($url) { if (!$this->composerInNoProxy) { return false; } if (empty($this->rulePorts)) { return true; } if (strpos($url, 'http://') === 0) { $port = 80; } else { $port = 443; } return in_array($port, $this->rulePorts); } } class HttpClient { /** @var null|string */ private static $caPath; private $options = array('http' => array()); private $disableTls = false; public function __construct($disableTls = false, $cafile = false) { $this->disableTls = $disableTls; if ($this->disableTls === false) { if (!empty($cafile) && !is_dir($cafile)) { if (!is_readable($cafile) || !validateCaFile(file_get_contents($cafile))) { throw new RuntimeException('The configured cafile (' .$cafile. ') was not valid or could not be read.'); } } $options = $this->getTlsStreamContextDefaults($cafile); $this->options = array_replace_recursive($this->options, $options); } } public function get($url) { $context = $this->getStreamContext($url); $result = file_get_contents($url, false, $context); if ($result && extension_loaded('zlib')) { $decode = false; foreach ($http_response_header as $header) { if (preg_match('{^content-encoding: *gzip *$}i', $header)) { $decode = true; continue; } elseif (preg_match('{^HTTP/}i', $header)) { $decode = false; } } if ($decode) { if (version_compare(PHP_VERSION, '5.4.0', '>=')) { $result = zlib_decode($result); } else { // work around issue with gzuncompress & co that do not work with all gzip checksums $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result)); } if (!$result) { throw new RuntimeException('Failed to decode zlib stream'); } } } return $result; } protected function getStreamContext($url) { if ($this->disableTls === false) { if (PHP_VERSION_ID < 50600) { $this->options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST); } } // Keeping the above mostly isolated from the code copied from Composer. return $this->getMergedStreamContext($url); } protected function getTlsStreamContextDefaults($cafile) { $ciphers = implode(':', array( 'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-ECDSA-AES256-GCM-SHA384', 'DHE-RSA-AES128-GCM-SHA256', 'DHE-DSS-AES128-GCM-SHA256', 'kEDH+AESGCM', 'ECDHE-RSA-AES128-SHA256', 'ECDHE-ECDSA-AES128-SHA256', 'ECDHE-RSA-AES128-SHA', 'ECDHE-ECDSA-AES128-SHA', 'ECDHE-RSA-AES256-SHA384', 'ECDHE-ECDSA-AES256-SHA384', 'ECDHE-RSA-AES256-SHA', 'ECDHE-ECDSA-AES256-SHA', 'DHE-RSA-AES128-SHA256', 'DHE-RSA-AES128-SHA', 'DHE-DSS-AES128-SHA256', 'DHE-RSA-AES256-SHA256', 'DHE-DSS-AES256-SHA', 'DHE-RSA-AES256-SHA', 'AES128-GCM-SHA256', 'AES256-GCM-SHA384', 'AES128-SHA256', 'AES256-SHA256', 'AES128-SHA', 'AES256-SHA', 'AES', 'CAMELLIA', 'DES-CBC3-SHA', '!aNULL', '!eNULL', '!EXPORT', '!DES', '!RC4', '!MD5', '!PSK', '!aECDH', '!EDH-DSS-DES-CBC3-SHA', '!EDH-RSA-DES-CBC3-SHA', '!KRB5-DES-CBC3-SHA', )); /** * CN_match and SNI_server_name are only known once a URL is passed. * They will be set in the getOptionsForUrl() method which receives a URL. * * cafile or capath can be overridden by passing in those options to constructor. */ $options = array( 'ssl' => array( 'ciphers' => $ciphers, 'verify_peer' => true, 'verify_depth' => 7, 'SNI_enabled' => true, ) ); /** * Attempt to find a local cafile or throw an exception. * The user may go download one if this occurs. */ if (!$cafile) { $cafile = self::getSystemCaRootBundlePath(); } if (is_dir($cafile)) { $options['ssl']['capath'] = $cafile; } elseif ($cafile) { $options['ssl']['cafile'] = $cafile; } else { throw new RuntimeException('A valid cafile could not be located automatically.'); } /** * Disable TLS compression to prevent CRIME attacks where supported. */ if (version_compare(PHP_VERSION, '5.4.13') >= 0) { $options['ssl']['disable_compression'] = true; } return $options; } /** * function copied from Composer\Util\StreamContextFactory::initOptions * * Any changes should be applied there as well, or backported here. * * @param string $url URL the context is to be used for * @return resource Default context * @throws \RuntimeException if https proxy required and OpenSSL uninstalled */ protected function getMergedStreamContext($url) { $options = $this->options; // Handle HTTP_PROXY/http_proxy on CLI only for security reasons if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) { $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']); } // Prefer CGI_HTTP_PROXY if available if (!empty($_SERVER['CGI_HTTP_PROXY'])) { $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']); } // Override with HTTPS proxy if present and URL is https if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) { $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']); } // Remove proxy if URL matches no_proxy directive if (!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) { $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']); if ($pattern->test($url)) { unset($proxy); } } if (!empty($proxy)) { $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : ''; $proxyURL .= isset($proxy['host']) ? $proxy['host'] : ''; if (isset($proxy['port'])) { $proxyURL .= ":" . $proxy['port']; } elseif (strpos($proxyURL, 'http://') === 0) { $proxyURL .= ":80"; } elseif (strpos($proxyURL, 'https://') === 0) { $proxyURL .= ":443"; } // check for a secure proxy if (strpos($proxyURL, 'https://') === 0) { if (!extension_loaded('openssl')) { throw new RuntimeException('You must enable the openssl extension to use a secure proxy.'); } if (strpos($url, 'https://') === 0) { throw new RuntimeException('PHP does not support https requests through a secure proxy.'); } } // http(s):// is not supported in proxy $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL); $options['http'] = array( 'proxy' => $proxyURL, ); // add request_fulluri for http requests if ('http' === parse_url($url, PHP_URL_SCHEME)) { $options['http']['request_fulluri'] = true; } // handle proxy auth if present if (isset($proxy['user'])) { $auth = rawurldecode($proxy['user']); if (isset($proxy['pass'])) { $auth .= ':' . rawurldecode($proxy['pass']); } $auth = base64_encode($auth); $options['http']['header'] = "Proxy-Authorization: Basic {$auth}\r\n"; } } if (isset($options['http']['header'])) { $options['http']['header'] .= "Connection: close\r\n"; } else { $options['http']['header'] = "Connection: close\r\n"; } if (extension_loaded('zlib')) { $options['http']['header'] .= "Accept-Encoding: gzip\r\n"; } $options['http']['header'] .= "User-Agent: ".COMPOSER_INSTALLER."\r\n"; $options['http']['protocol_version'] = 1.1; $options['http']['timeout'] = 600; return stream_context_create($options); } /** * This method was adapted from Sslurp. * https://github.com/EvanDotPro/Sslurp * * (c) Evan Coury <me@evancoury.com> * * For the full copyright and license information, please see below: * * Copyright (c) 2013, Evan Coury * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ public static function getSystemCaRootBundlePath() { if (self::$caPath !== null) { return self::$caPath; } // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that. // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. $envCertFile = getenv('SSL_CERT_FILE'); if ($envCertFile && is_readable($envCertFile) && validateCaFile(file_get_contents($envCertFile))) { return self::$caPath = $envCertFile; } // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that. // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. $envCertDir = getenv('SSL_CERT_DIR'); if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) { return self::$caPath = $envCertDir; } $configured = ini_get('openssl.cafile'); if ($configured && strlen($configured) > 0 && is_readable($configured) && validateCaFile(file_get_contents($configured))) { return self::$caPath = $configured; } $configured = ini_get('openssl.capath'); if ($configured && is_dir($configured) && is_readable($configured)) { return self::$caPath = $configured; } $caBundlePaths = array( '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package) '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package) '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package) '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package) '/usr/ssl/certs/ca-bundle.crt', // Cygwin '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option) '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat? '/etc/ssl/cert.pem', // OpenBSD '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x '/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package '/opt/homebrew/etc/openssl@3/cert.pem', // macOS silicon homebrew, openssl@3 package '/opt/homebrew/etc/openssl@1.1/cert.pem', // macOS silicon homebrew, openssl@1.1 package ); foreach ($caBundlePaths as $caBundle) { if (@is_readable($caBundle) && validateCaFile(file_get_contents($caBundle))) { return self::$caPath = $caBundle; } } foreach ($caBundlePaths as $caBundle) { $caBundle = dirname($caBundle); if (is_dir($caBundle) && glob($caBundle.'/*')) { return self::$caPath = $caBundle; } } return self::$caPath = false; } public static function getPackagedCaFile() { return <<<CACERT ## ## Bundle of CA Root Certificates for Let's Encrypt ## ## See https://letsencrypt.org/certificates/#root-certificates ## ## ISRG Root X1 (RSA 4096) expires Jun 04 11:04:38 2035 GMT ## ISRG Root X2 (ECDSA P-384) expires Sep 17 16:00:00 2040 GMT ## ## Both these are self-signed CA root certificates ## ISRG Root X1 ============ -----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= -----END CERTIFICATE----- ISRG Root X2 ============ -----BEGIN CERTIFICATE----- MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW +1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 /q4AaOeMSQ+2b1tbFfLn -----END CERTIFICATE----- CACERT; } }