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-php80/root/usr/share/pear/PEAR/Command
Viewing File: /opt/cpanel/ea-php80/root/usr/share/pear/PEAR/Command/Channels.php
<?php // /* vim: set expandtab tabstop=4 shiftwidth=4: */ /** * PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add, * channel-update, channel-info, channel-alias, channel-discover commands) * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Stig Bakken <ssb@php.net> * @author Greg Beaver <cellog@php.net> * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500); /** * PEAR commands for managing channels. * * @category pear * @package PEAR * @author Greg Beaver <cellog@php.net> * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.18 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Command_Channels extends PEAR_Command_Common { var $commands = array( 'list-channels' => array( 'summary' => 'List Available Channels', 'function' => 'doList', 'shortcut' => 'lc', 'options' => array(), 'doc' => ' List all available channels for installation. ', ), 'update-channels' => array( 'summary' => 'Update the Channel List', 'function' => 'doUpdateAll', 'shortcut' => 'uc', 'options' => array(), 'doc' => ' List all installed packages in all channels. ' ), 'channel-delete' => array( 'summary' => 'Remove a Channel From the List', 'function' => 'doDelete', 'shortcut' => 'cde', 'options' => array(), 'doc' => '<channel name> Delete a channel from the registry. You may not remove any channel that has installed packages. ' ), 'channel-add' => array( 'summary' => 'Add a Channel', 'function' => 'doAdd', 'shortcut' => 'ca', 'options' => array(), 'doc' => '<channel.xml> Add a private channel to the channel list. Note that all public channels should be synced using "update-channels". Parameter may be either a local file or remote URL to a channel.xml. ' ), 'channel-update' => array( 'summary' => 'Update an Existing Channel', 'function' => 'doUpdate', 'shortcut' => 'cu', 'options' => array( 'force' => array( 'shortopt' => 'f', 'doc' => 'will force download of new channel.xml if an existing channel name is used', ), 'channel' => array( 'shortopt' => 'c', 'arg' => 'CHANNEL', 'doc' => 'will force download of new channel.xml if an existing channel name is used', ), ), 'doc' => '[<channel.xml>|<channel name>] Update a channel in the channel list directly. Note that all public channels can be synced using "update-channels". Parameter may be a local or remote channel.xml, or the name of an existing channel. ' ), 'channel-info' => array( 'summary' => 'Retrieve Information on a Channel', 'function' => 'doInfo', 'shortcut' => 'ci', 'options' => array(), 'doc' => '<package> List the files in an installed package. ' ), 'channel-alias' => array( 'summary' => 'Specify an alias to a channel name', 'function' => 'doAlias', 'shortcut' => 'cha', 'options' => array(), 'doc' => '<channel> <alias> Specify a specific alias to use for a channel name. The alias may not be an existing channel name or alias. ' ), 'channel-discover' => array( 'summary' => 'Initialize a Channel from its server', 'function' => 'doDiscover', 'shortcut' => 'di', 'options' => array(), 'doc' => '[<channel.xml>|<channel name>] Initialize a channel from its server and create a local channel.xml. If <channel name> is in the format "<username>:<password>@<channel>" then <username> and <password> will be set as the login username/password for <channel>. Use caution when passing the username/password in this way, as it may allow other users on your computer to briefly view your username/ password via the system\'s process list. ' ), 'channel-login' => array( 'summary' => 'Connects and authenticates to remote channel server', 'shortcut' => 'cli', 'function' => 'doLogin', 'options' => array(), 'doc' => '<channel name> Log in to a remote channel server. If <channel name> is not supplied, the default channel is used. To use remote functions in the installer that require any kind of privileges, you need to log in first. The username and password you enter here will be stored in your per-user PEAR configuration (~/.pearrc on Unix-like systems). After logging in, your username and password will be sent along in subsequent operations on the remote server.', ), 'channel-logout' => array( 'summary' => 'Logs out from the remote channel server', 'shortcut' => 'clo', 'function' => 'doLogout', 'options' => array(), 'doc' => '<channel name> Logs out from a remote channel server. If <channel name> is not supplied, the default channel is used. This command does not actually connect to the remote server, it only deletes the stored username and password from your user configuration.', ), ); /** * PEAR_Command_Registry constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } function _sortChannels($a, $b) { return strnatcasecmp($a->getName(), $b->getName()); } function doList($command, $options, $params) { $reg = &$this->config->getRegistry(); $registered = $reg->getChannels(); usort($registered, array(&$this, '_sortchannels')); $i = $j = 0; $data = array( 'caption' => 'Registered Channels:', 'border' => true, 'headline' => array('Channel', 'Alias', 'Summary') ); foreach ($registered as $channel) { $data['data'][] = array($channel->getName(), $channel->getAlias(), $channel->getSummary()); } if (count($registered) === 0) { $data = '(no registered channels)'; } $this->ui->outputData($data, $command); return true; } function doUpdateAll($command, $options, $params) { $reg = &$this->config->getRegistry(); $channels = $reg->getChannels(); $success = true; foreach ($channels as $channel) { if ($channel->getName() != '__uri') { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = $this->doUpdate('channel-update', $options, array($channel->getName())); if (PEAR::isError($err)) { $this->ui->outputData($err->getMessage(), $command); $success = false; } else { $success &= $err; } } } return $success; } function doInfo($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError("No channel specified"); } $reg = &$this->config->getRegistry(); $channel = strtolower($params[0]); if ($reg->channelExists($channel)) { $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $this->raiseError($chan); } } else { if (strpos($channel, '://')) { $downloader = &$this->getDownloader(); $tmpdir = $this->config->get('temp_dir'); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir); PEAR::staticPopErrorHandling(); if (PEAR::isError($loc)) { return $this->raiseError('Cannot open "' . $channel . '" (' . $loc->getMessage() . ')'); } else { $contents = implode('', file($loc)); } } else { if (!file_exists($params[0])) { return $this->raiseError('Unknown channel "' . $channel . '"'); } $fp = fopen($params[0], 'r'); if (!$fp) { return $this->raiseError('Cannot open "' . $params[0] . '"'); } $contents = ''; while (!feof($fp)) { $contents .= fread($fp, 1024); } fclose($fp); } if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $chan = new PEAR_ChannelFile; $chan->fromXmlString($contents); $chan->validate(); if ($errs = $chan->getErrors(true)) { foreach ($errs as $err) { $this->ui->outputData($err['level'] . ': ' . $err['message']); } return $this->raiseError('Channel file "' . $params[0] . '" is not valid'); } } if (!$chan) { return $this->raiseError('Serious error: Channel "' . $params[0] . '" has a corrupted registry entry'); } $channel = $chan->getName(); $caption = 'Channel ' . $channel . ' Information:'; $data1 = array( 'caption' => $caption, 'border' => true); $data1['data']['server'] = array('Name and Server', $chan->getName()); if ($chan->getAlias() != $chan->getName()) { $data1['data']['alias'] = array('Alias', $chan->getAlias()); } $data1['data']['summary'] = array('Summary', $chan->getSummary()); $validate = $chan->getValidationPackage(); $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']); $data1['data']['vpackageversion'] = array('Validation Package Version', $validate['attribs']['version']); $d = array(); $d['main'] = $data1; $data['data'] = array(); $data['caption'] = 'Server Capabilities'; $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base'); if ($chan->supportsREST()) { if ($chan->supportsREST()) { $funcs = $chan->getFunctions('rest'); if (!isset($funcs[0])) { $funcs = array($funcs); } foreach ($funcs as $protocol) { $data['data'][] = array('rest', $protocol['attribs']['type'], $protocol['_content']); } } } else { $data['data'][] = array('No supported protocols'); } $d['protocols'] = $data; $data['data'] = array(); $mirrors = $chan->getMirrors(); if ($mirrors) { $data['caption'] = 'Channel ' . $channel . ' Mirrors:'; unset($data['headline']); foreach ($mirrors as $mirror) { $data['data'][] = array($mirror['attribs']['host']); $d['mirrors'] = $data; } foreach ($mirrors as $i => $mirror) { $data['data'] = array(); $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities'; $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base'); if ($chan->supportsREST($mirror['attribs']['host'])) { if ($chan->supportsREST($mirror['attribs']['host'])) { $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']); if (!isset($funcs[0])) { $funcs = array($funcs); } foreach ($funcs as $protocol) { $data['data'][] = array('rest', $protocol['attribs']['type'], $protocol['_content']); } } } else { $data['data'][] = array('No supported protocols'); } $d['mirrorprotocols' . $i] = $data; } } $this->ui->outputData($d, 'channel-info'); } // }}} function doDelete($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError('channel-delete: no channel specified'); } $reg = &$this->config->getRegistry(); if (!$reg->channelExists($params[0])) { return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist'); } $channel = $reg->channelName($params[0]); if ($channel == 'pear.php.net') { return $this->raiseError('Cannot delete the pear.php.net channel'); } if ($channel == 'pecl.php.net') { return $this->raiseError('Cannot delete the pecl.php.net channel'); } if ($channel == 'doc.php.net') { return $this->raiseError('Cannot delete the doc.php.net channel'); } if ($channel == '__uri') { return $this->raiseError('Cannot delete the __uri pseudo-channel'); } if (PEAR::isError($err = $reg->listPackages($channel))) { return $err; } if (count($err)) { return $this->raiseError('Channel "' . $channel . '" has installed packages, cannot delete'); } if (!$reg->deleteChannel($channel)) { return $this->raiseError('Channel "' . $channel . '" deletion failed'); } else { $this->config->deleteChannel($channel); $this->ui->outputData('Channel "' . $channel . '" deleted', $command); } } function doAdd($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError('channel-add: no channel file specified'); } if (strpos($params[0], '://')) { $downloader = &$this->getDownloader(); $tmpdir = $this->config->get('temp_dir'); if (!file_exists($tmpdir)) { require_once 'System.php'; PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = System::mkdir(array('-p', $tmpdir)); PEAR::staticPopErrorHandling(); if (PEAR::isError($err)) { return $this->raiseError('channel-add: temp_dir does not exist: "' . $tmpdir . '" - You can change this location with "pear config-set temp_dir"'); } } if (!is_writable($tmpdir)) { return $this->raiseError('channel-add: temp_dir is not writable: "' . $tmpdir . '" - You can change this location with "pear config-set temp_dir"'); } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false); PEAR::staticPopErrorHandling(); if (PEAR::isError($loc)) { return $this->raiseError('channel-add: Cannot open "' . $params[0] . '" (' . $loc->getMessage() . ')'); } list($loc, $lastmodified) = $loc; $contents = implode('', file($loc)); } else { $lastmodified = $fp = false; if (file_exists($params[0])) { $fp = fopen($params[0], 'r'); } if (!$fp) { return $this->raiseError('channel-add: cannot open "' . $params[0] . '"'); } $contents = ''; while (!feof($fp)) { $contents .= fread($fp, 1024); } fclose($fp); } if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $channel = new PEAR_ChannelFile; PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $result = $channel->fromXmlString($contents); PEAR::staticPopErrorHandling(); if (!$result) { $exit = false; if (count($errors = $channel->getErrors(true))) { foreach ($errors as $error) { $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message'])); if (!$exit) { $exit = $error['level'] == 'error' ? true : false; } } if ($exit) { return $this->raiseError('channel-add: invalid channel.xml file'); } } } $reg = &$this->config->getRegistry(); if ($reg->channelExists($channel->getName())) { return $this->raiseError('channel-add: Channel "' . $channel->getName() . '" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS); } $ret = $reg->addChannel($channel, $lastmodified); if (PEAR::isError($ret)) { return $ret; } if (!$ret) { return $this->raiseError('channel-add: adding Channel "' . $channel->getName() . '" to registry failed'); } $this->config->setChannels($reg->listChannels()); $this->config->writeConfigFile(); $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command); } function doUpdate($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError("No channel file specified"); } $tmpdir = $this->config->get('temp_dir'); if (!file_exists($tmpdir)) { require_once 'System.php'; PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = System::mkdir(array('-p', $tmpdir)); PEAR::staticPopErrorHandling(); if (PEAR::isError($err)) { return $this->raiseError('channel-add: temp_dir does not exist: "' . $tmpdir . '" - You can change this location with "pear config-set temp_dir"'); } } if (!is_writable($tmpdir)) { return $this->raiseError('channel-add: temp_dir is not writable: "' . $tmpdir . '" - You can change this location with "pear config-set temp_dir"'); } $reg = &$this->config->getRegistry(); $lastmodified = false; if ((!file_exists($params[0]) || is_dir($params[0])) && $reg->channelExists(strtolower($params[0]))) { $c = $reg->getChannel(strtolower($params[0])); if (PEAR::isError($c)) { return $this->raiseError($c); } $this->ui->outputData("Updating channel \"$params[0]\"", $command); $dl = &$this->getDownloader(array()); // if force is specified, use a timestamp of "1" to force retrieval $lastmodified = isset($options['force']) ? false : $c->lastModified(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml', $this->ui, $tmpdir, null, $lastmodified); PEAR::staticPopErrorHandling(); if (PEAR::isError($contents)) { // Attempt to fall back to http $this->ui->outputData("Channel \"$params[0]\" is not responding over https://, failed with message: " . $contents->getMessage()); $this->ui->outputData("Trying channel \"$params[0]\" over http:// instead"); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml', $this->ui, $tmpdir, null, $lastmodified); PEAR::staticPopErrorHandling(); if (PEAR::isError($contents)) { return $this->raiseError('Cannot retrieve channel.xml for channel "' . $c->getName() . '" (' . $contents->getMessage() . ')'); } } if (is_array($contents)) { list($contents, $lastmodified) = $contents; } if (!$contents) { $this->ui->outputData("Channel \"$params[0]\" is up to date"); return; } $contents = implode('', file($contents)); if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $channel = new PEAR_ChannelFile; $channel->fromXmlString($contents); if (!$channel->getErrors()) { // security check: is the downloaded file for the channel we got it from? if (strtolower($channel->getName()) != strtolower($c->getName())) { if (!isset($options['force'])) { return $this->raiseError('ERROR: downloaded channel definition file' . ' for channel "' . $channel->getName() . '" from channel "' . strtolower($c->getName()) . '"'); } $this->ui->log(0, 'WARNING: downloaded channel definition file' . ' for channel "' . $channel->getName() . '" from channel "' . strtolower($c->getName()) . '"'); } } } else { if (strpos($params[0], '://')) { $dl = &$this->getDownloader(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $loc = $dl->downloadHttp($params[0], $this->ui, $tmpdir, null, $lastmodified); PEAR::staticPopErrorHandling(); if (PEAR::isError($loc)) { return $this->raiseError("Cannot open " . $params[0] . ' (' . $loc->getMessage() . ')'); } list($loc, $lastmodified) = $loc; $contents = implode('', file($loc)); } else { $fp = false; if (file_exists($params[0])) { $fp = fopen($params[0], 'r'); } if (!$fp) { return $this->raiseError("Cannot open " . $params[0]); } $contents = ''; while (!feof($fp)) { $contents .= fread($fp, 1024); } fclose($fp); } if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $channel = new PEAR_ChannelFile; $channel->fromXmlString($contents); } $exit = false; if (count($errors = $channel->getErrors(true))) { foreach ($errors as $error) { $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message'])); if (!$exit) { $exit = $error['level'] == 'error' ? true : false; } } if ($exit) { return $this->raiseError('Invalid channel.xml file'); } } if (!$reg->channelExists($channel->getName())) { return $this->raiseError('Error: Channel "' . $channel->getName() . '" does not exist, use channel-add to add an entry'); } $ret = $reg->updateChannel($channel, $lastmodified); if (PEAR::isError($ret)) { return $ret; } if (!$ret) { return $this->raiseError('Updating Channel "' . $channel->getName() . '" in registry failed'); } $this->config->setChannels($reg->listChannels()); $this->config->writeConfigFile(); $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded'); } function &getDownloader() { if (!class_exists('PEAR_Downloader')) { require_once 'PEAR/Downloader.php'; } $a = new PEAR_Downloader($this->ui, array(), $this->config); return $a; } function doAlias($command, $options, $params) { if (count($params) === 1) { return $this->raiseError('No channel alias specified'); } if (count($params) !== 2 || (!empty($params[1]) && $params[1][0] == '-')) { return $this->raiseError( 'Invalid format, correct is: channel-alias channel alias'); } $reg = &$this->config->getRegistry(); if (!$reg->channelExists($params[0], true)) { $extra = ''; if ($reg->isAlias($params[0])) { $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' . strtolower($params[1]) . '")'; } return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra); } if ($reg->isAlias($params[1])) { return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' . 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias'); } $chan = $reg->getChannel($params[0]); if (PEAR::isError($chan)) { return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] . '" information (' . $chan->getMessage() . ')'); } // make it a local alias if (!$chan->setAlias(strtolower($params[1]), true)) { return $this->raiseError('Alias "' . strtolower($params[1]) . '" is not a valid channel alias'); } $reg->updateChannel($chan); $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' . strtolower($params[1]) . '"'); } /** * The channel-discover command * * @param string $command command name * @param array $options option_name => value * @param array $params list of additional parameters. * $params[0] should contain a string with either: * - <channel name> or * - <username>:<password>@<channel name> * @return null|PEAR_Error */ function doDiscover($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError("No channel server specified"); } // Look for the possible input format "<username>:<password>@<channel>" if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) { $username = $matches[1]; $password = $matches[2]; $channel = $matches[3]; } else { $channel = $params[0]; } $reg = &$this->config->getRegistry(); if ($reg->channelExists($channel)) { if (!$reg->isAlias($channel)) { return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS); } return $this->raiseError("A channel alias named \"$channel\" " . 'already exists, aliasing channel "' . $reg->channelName($channel) . '"'); } $this->pushErrorHandling(PEAR_ERROR_RETURN); $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml')); $this->popErrorHandling(); if (PEAR::isError($err)) { if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) { return $this->raiseError("Discovery of channel \"$channel\" failed (" . $err->getMessage() . ')'); } // Attempt fetch via https $this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage()); $this->ui->outputData("Trying to discover channel $channel over https:// instead"); $this->pushErrorHandling(PEAR_ERROR_RETURN); $err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml')); $this->popErrorHandling(); if (PEAR::isError($err)) { return $this->raiseError("Discovery of channel \"$channel\" failed (" . $err->getMessage() . ')'); } } // Store username/password if they were given // Arguably we should do a logintest on the channel here, but since // that's awkward on a REST-based channel (even "pear login" doesn't // do it for those), and XML-RPC is deprecated, it's fairly pointless. if (isset($username)) { $this->config->set('username', $username, 'user', $channel); $this->config->set('password', $password, 'user', $channel); $this->config->store(); $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command); } $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command); } /** * Execute the 'login' command. * * @param string $command command name * @param array $options option_name => value * @param array $params list of additional parameters * * @return bool TRUE on success or * a PEAR error on failure * * @access public */ function doLogin($command, $options, $params) { $reg = &$this->config->getRegistry(); // If a parameter is supplied, use that as the channel to log in to $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel'); $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $this->raiseError($chan); } $server = $this->config->get('preferred_mirror', null, $channel); $username = $this->config->get('username', null, $channel); if (empty($username)) { $username = isset($_ENV['USER']) ? $_ENV['USER'] : null; } $this->ui->outputData("Logging in to $server.", $command); list($username, $password) = $this->ui->userDialog( $command, array('Username', 'Password'), array('text', 'password'), array($username, '') ); $username = trim($username); $password = trim($password); $ourfile = $this->config->getConfFile('user'); if (!$ourfile) { $ourfile = $this->config->getConfFile('system'); } $this->config->set('username', $username, 'user', $channel); $this->config->set('password', $password, 'user', $channel); if ($chan->supportsREST()) { $ok = true; } if ($ok !== true) { return $this->raiseError('Login failed!'); } $this->ui->outputData("Logged in.", $command); // avoid changing any temporary settings changed with -d $ourconfig = new PEAR_Config($ourfile, $ourfile); $ourconfig->set('username', $username, 'user', $channel); $ourconfig->set('password', $password, 'user', $channel); $ourconfig->store(); return true; } /** * Execute the 'logout' command. * * @param string $command command name * @param array $options option_name => value * @param array $params list of additional parameters * * @return bool TRUE on success or * a PEAR error on failure * * @access public */ function doLogout($command, $options, $params) { $reg = &$this->config->getRegistry(); // If a parameter is supplied, use that as the channel to log in to $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel'); $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $this->raiseError($chan); } $server = $this->config->get('preferred_mirror', null, $channel); $this->ui->outputData("Logging out from $server.", $command); $this->config->remove('username', 'user', $channel); $this->config->remove('password', 'user', $channel); $this->config->store(); return true; } }