usr/bin/ftp000075500000253000147207246730006660 0ustar00ELF>,@@N@8 @@@@@@88@8@@@D)D) --a-a) --a-aTT@T@DDPtdAAQtdRtd--a-a  /lib64/ld-linux-x86-64.so.2GNU GNU-A1pD*yHtPq(A Pquz(BEje]|fUa qX9Q*l ViZW]5&c'Goa@oB;>|L7xP. G;!/`*4 Kd= URhe-Q s/EaqEaN"@WbEa!@xEa| @Fa@kFalibreadline.so.6_ITM_deregisterTMCloneTable__gmon_start___Jv_RegisterClasses_ITM_registerTMCloneTablerl_terminal_name_initreadline_finiadd_historylibncurses.so.5libtinfo.so.5libc.so.6socket__stpcpy_chkfflushstrcpy__printf_chkexitexecl_IO_putcsetlocalegai_strerrorstrncmpstrrchrwait__longjmp_chk__strdupperrorconnectgetpwuid__fdelt_chkclosedirsignalstrncpyputsfork__stack_chk_failunlinkputcharlistenselectstdinpopenchmodrewindgmtimestrtolisattyfeoffgetsgetpwnamstrlensendgetaddrinfo__errno_locationbindfseekchdirreadgetnameinfo__fxstat64shutdownpoll__fprintf_chk__sigsetjmpstdoutmemcpyfclosesetsockoptmallocgetpassstrcatumaskstrcasecmp__strncpy_chkopendir__xstat64__ctype_b_locgetenvsscanfgetservbynamestderr__snprintf_chkgetuid__strncat_chkstrncasecmpfilenopclosegethostnamegetcwdfwritegettimeofdaymkstemp64__memcpy_chklseek64strchrgetsocknamerindex__vfprintf_chkfdopenreaddir64acceptsleep__strcpy_chkfreeaddrinfo__sprintf_chkmemmovefopen64access_IO_getc__strcat_chkstrcmp__libc_start_maindirfdferrorstpcpysysconffree_edata__bss_start_endGLIBC_2.3GLIBC_2.11GLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.2.5GLIBC_2.3.4ii ii ui ti /a9EaqEauFa{Fay0a 0a(0a00a80a@0aH0aP0aX0a `0a h0a p0a x0a0a0a0a0a0a0av0a0a0a0a0a0a0a0a0a0a1a1a1a 1a! 1as(1a"01a#81a$@1a%H1a&P1a'X1a(`1a)h1a*p1a+x1a,1a-1a.1a/1a01a11a21a31a41a51a61a71a81a91a:1a;1a<2a=2a>2a?2a@ 2aA(2aB02aC82aD@2aEH2aFP2aGX2aH`2aIh2aJp2aKx2aL2aM2aN2aO2aP2aQ2aR2aS2aT2aU2aV2aW2aX2aZ2a[2a\2a]3a^3a_3a`3aa 3ab(3ac03ad83af@3agH3ahP3aiX3aj`3akh3alp3amx3an3ao3apHH5!HtH5"!%$!@%"!h%!h%!h% !h%!h%!h%!h%!hp%!h`%!h P%!h @%!h 0%!h %!h %!h%!h%!h%!h%!h%!h%!h%z!h%r!h%j!hp%b!h`%Z!hP%R!h@%J!h0%B!h %:!h%2!h%*!h%"!h %!h!%!h"% !h#%!h$%!h%%!h&%!h'p%!h(`%!h)P%!h*@%!h+0%!h, %!h-%!h.%!h/%!h0%!h1%!h2%!h3%!h4%z!h5%r!h6%j!h7p%b!h8`%Z!h9P%R!h:@%J!h;0%B!h< %:!h=%2!h>%*!h?%"!h@%!hA%!hB% !hC%!hD% !hE% !hF% !hGp% !hH`% !hIP% !hJ@% !hK0% !hL % !hM% !hN% !hO% !hP% !hQ% !hR% !hS% !hT%z !hU%r !hV%j !hWp%b !hX`%Z !hYP%R !hZ@%J !h[0%B !h\ %: !h]%2 !h^%* !h_%" !h`% !ha% !hb% !hc% !hd% !he% !hf% !hgp% !hh`% !hiP% !hj@% !hk0% !hl % !hm% !hnATUSH0 !|$ H4$ AdH%(H$(1m Aq A"H@/'!]"c!%!")"H$H8Hiu AjHc!D$ D$ H$HH$D$ H$H8-H$HHP@tH5w$$ A,/"HtH5vH=!Ⱥ A1!"m!-!E "돿 A9z A/ A%0 A AX A A A A A A K1z!3." ;!0!"H ! AH=!sl!t-"!!}!'."Ht%H\$ Hp HƄ$H!D$ ~Ubvt1H$@#@ H4$|$ Hb!YH5! 5!t+ ,"h A1'H=P!HL!`FbUHt`Fb H!%tDHJHDHH`FbHc€`Fb Ht$H|$踰\$Ią)H8qHH4H;xt!HEHLЋA!t }H}@@@ rDtƀ`FbA AHHt6Hƿ`Fb|+";tHHBHE H1@AVH5y!of.H@&[@ A @H=(!k uH|$U(1I^HHPTI@H@H&@f.EaUH-EaHHw]øHt]EaEaUH-EaHHHH?HHu]úHt]HƿEa=!uUH~]v!@H=H!tHtU-aH]{s=I!!bE1fHA@t A8u7@D))"A@faEt3D8tOH@t@8HHt9H@WbAuIABH7@uA@fa1E1fE9} bIABA@fa@faAE1UfUHSHH5 !Hts3a@H H3Ht\H !y[ "t !uC "1 waH5!!!u !HAVIAUATI`FbUHSHdH%(HD$1Q=HHk@1lAH!I`Fb)Lƀ`Fb HLt E`Fb tBH|$1FT$1A9$A$IHL$dH3 %(u\H[]A\A]A^ƀ`FbH !!@1ޙ&f1əZ@kf.AWAVIAUAATU1SHdH %(H$1Ƀ|$!t!(!cD5!1E[@qH=8%!@@HD1SAWAVAUATUSH8dH %(H$(1Ƀ|$Ht$HD$;@H!H$! waHD$fD5!H|$HH}u!f.Dq!EtD !HD$EH8D"Et7]HHHHHDAtI="5r!jLRPHcʅMt A/~IL1MdAfD/HL9t.u1҃HL9uALzHH9AH@Hƿ5@cO!!&@@!!t!!T@1>Ht$!H$(dH3%(KH8[]A\A]A^A_fDH7LIL8IhH=a @MD@1TC!C!1DHD$ \$ H@HDqt HHۈuLl$ DHt$H|$@HD$@H1ky"@!!Z 2!E1AD$ Ll$ _USH=Ⱥ!<H!+@15!?A`"bA FbWbb`@14 A@D^!D!Iً!IHHھ@ELDELDŅ!HDͅHD1Tn"HHھ@Z"HDͅHD1%!Hپc@&"HDͅHD1H" b@Wb@1D !Eb`b@1!5:!4 A@HٿHHDͅ@HD1i=!@HD1HID!E~@@3!~,3b1fH1h AH 9! !H[]@@7f@H  =@5S!J K!u+H M@1J@HI!8@1@@f.H:!1@Һ4 A!@HD1!!HHFu!1@Һ4 A(u!@HD1u!!HHֶ! $!1ɉ!tZuK@1 @U!_!t(&@1/AH!e!t4 Af.H !1!uM@1A@m!!tW@1AH!u4 A!t4 Af.H!1m@Һ4 A!@HD1(!4!HH!1@Һ4 A!@HD1!!HH!1@Һ4 A!@HD1!!HH&!1@Һ4 A!@HD18!D!HS~jH~H 1xqɉ !u7%!@1@l!1[!D U!4 Af5B!1Ʌɉ 3!tHKH= @1![H|$ H4$~OH$@Hp10tHÐ=>!u!uZH$@Hp1f0HÐH|$ @H.uH$@H1!fDH  ( @SHdH%(H$1tptCH"@iw!H$dH3%(H[!H^Hu/!DAHx?HHt}H=@1!kf.k8DH= IHٺ@1!(HHJ8"t$???mf.HfD$A fH|$ H4$~H$l@Hp1[.HfDH|$ @HuH$U@H1!fDSH |$Ht$!HD$;@H!H! waHD$ DH|$1HH;u!5z!tƋ !HD$H8u|1H޿l@]-O!u!tt@@!!t!!\@Ht$!!H [ÐHH(oHt$H|$@HD$@H1CQ!H|$ H4$~&H$@Hp1b,tMHH|$ @HuH$@H1!HH$@Hp1+HH|$ |@H|$ WUSHH~tHvfDHFHC3a3aH@8n@HE<-tP Ү!uv<-<|t!!urHsHSHH[]E1@U@~tHP@1!H[]HHHHCtn@@.|t!H[]DHxHHHCDЀ~*AAUATUSH8|$HcHt$aHD$HDHHHT$(HD$(8-xHD$@;@H@zlH!!HEHD$  waHD$$ !t]|$~VA@HD$Ht$(H|$ @IDE1H()T{!!Ht$~L!H8[]A\A]fHD$(8| D!HD$(EEHHD$(t%=!Ht$(@V!H8[]A\A]fڋD$H9FHD$@D-?!5!H0}!t r!D-!uHt$H|$@,tHc|$fDHD$x@H1迾!H8[]A\A]f.Ht$H|$@tHc|$}fDHf.AUIATUSH8dH%(HD$(1贼I袼H~UD1ѿ9uLpHc!HD$(dH3%(uBH8[]A\A]fDL+Hu@?!b߃Vu11ٻ@蟸HHø@HDؾ/H裺HhHH|$($-HDH}su }hu}t$+=!tHH= OMt4E1L@HH1bHj!ƽ1HH17DSHpdH %(HL$h1Ƀ|$ H4$H$v>H@1JX!HD$hdH3%(HHp[fDHp@1p%t+un|$ uH$@Hp1K%f|$ H$ @Hp1!%u|$ ~eH$Hp1@%XH A轼8H|$ @H|$ D@1?H=h H\$螺H_ PHjH$D$ HHXXDH$@bD$ HC迷Df.S1'@:!0!$t ![fD=!uH (@蹻&@1#뽐f.H|$ H4$~OH$U@Hp1#tHÐ=>!u!uZH$T@Hp1f#HÐH|$ +@H.uH$:@H1ҹ!fDH  (@H|$ H4$~OH$]@Hp1"tHÐ=~!u!uZH$\@Hp1"HÐH|$ +@HnuH$:@H1 !fDH Q (0@%HH4$|$ ~H$ AHf.H|$ d@Ht t$ @H$y@H1x!ff.HH4$|$ ~H$@/Hf.H|$ @H^t t$ @H$y@H1!ff.H|$ H4$~g~"H$@HPHp1!HDH|$ @HuH$@H1z!HH|$ AH|$ {S!@Hv@HE!H1p ![Sn! @Hv@HER!H10 B![S.!@Hv@HE!H1![H:!tM5!!t41mf.!u@ f.HHH=j #@1aAUATUSHdH%(H$1GH$ILdHLDHAAD! tH3L€DHAHDHHL)H)ʹȶL9uL1@H$dH3%(u HĘ[]A\A],@膵Hff.SH |$Ht$ HD$HxhHHD$H|$HD$x@vaRt!H [fD6@H3HD$xHD$HPHHD$HpD$xҋ!11!o3H޿蒲H [@l@H=' b!H [fHt$H|$@ HD$5@H1諳!@ V!-@耯H= 12H޿HD$H@ Ht HD$1P(@H@&H=O 芲D$(!w[@H=' b!OH!1@Һ4 A!@HD1訲!!HH!1`@Һ4 AȞ!@HD1X!d!HUSHts=!HHv@@Wb#!%!ح!t$Hu@ b蹭!H[]A!H[]f.@!謭!!H[]fSH|$ H4$H=! +!i!HË!uOH5!`bή!H; tH޿bͬ%!H[H; tH߾ H0!胮HfDH|$ @H=H$@H1薰!딿@K!v@!!oDHz!1@Һ4 A\!@HD1(F!4!HH&!1@Һ4 A!@HD1د!!HH1@t HfD=!u!u@1Hf.H )@蕰t @AHH~ 1,@Hp!H¾(@1HY@1T@ATUSH=!|$ H4$|$ o¿!R-p!H$HcHpHL3bLaƃ3bHcHH3bHHEbI\$umDHHEbt[H=| 迭< u֋!HcHH93b{HHEbuf.H=! d t?up@Щ!H[]A\DH!5b5bXH=  uDP@~-!H[]A\@^H|$ ?@HwH$J@H1'5!RH3b!!3H!!H3b@̨!f.H!1`@Һ4 A!@HD1x!!HH|$ H4$~H$@Hp1HfDH|$ r@H^uH${@H1!fDSHPdH %(HL$H1Ƀ|$,Ht$ [!5!tIHD$ @Hp1t? a蕧!HD$HdH3%(HP[D!@HD$DLL$蠣IIE He@`Fb趢wHD$DEbHHD$h@JA)ufHD$ƀEb6f.A5fH=){!贞=!== H=z!臞AAH=GZ! A1AH=*Z!EfDH!A1蠞= !H5 誛H= ޝEw!L$9ED$!DH=)z!贝AA(fDt$|1]QH=VY!Ht\HAY! c!tAݙH= A!H([]A\A]A^A_H#X!룐ATIUHSHdH%(H$1HH$H^HT$01HƄ$HlF!HHfF!HcF!HHL$ LVF!D$0D$8詝 H\$ H{ HT$`11HHHL$(D$hD$`H{ _La蕗H\$ B!LAH!aHuGfKA]H[(Ht,Cu܋svdH[(G0AHuH|$ _!B1HD$ aHp H|$(LH{H$E1E1$@ݘHD$ Hx(t H= H$mA1S s{˜yK8RSHs贛x:SHsaT$H|$ VHT$pa5tf=5D!@@Hv!H=u!HQU!H d!HT$( bD$(軚4u!ftf u 1f!u!1HHL$`A D$`諕sHd!H$dH3 %(H[]A\fH{(t*H= H${A1y A这?AnfDDŽ$???3ANfDH$D!YAfA EH1趚HT$0HHHB!HB!HHB!B!HHL$ LD$0D$8șƄ$Ƅ$ H!H$A1!A蘘pH 4 AH=s!HtH=R!Ht!m1fDLa>v>!HT!aHL$1AD$_A͗ f$dH=U L$H$IL\A1:!1]Ao!苓f.USHHt$(HT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1Hƒ!0=!H=`Q!k@{HH$H=9Q!HHHD$HD$ $D$0HD$[H Q! AH=P!H?!@@@Ëv!FH$ Ht  A譃H=F>! A1Hl$ ;H=$>!?1HHH=^!AρHcH=^!ILl 賁H={^! L?)HHL JL 芁HAtKHzHcHILl bH ?)ILL JL @A9A~LD$11HHD$ HD$0Ht.HHcHHl Ѓ?)HrD1Mtx1AH$ dH3%(Hĸ []A\A]A^A_H舀H$ tHDH`A!=>!(x1l@u@(!t !1C4H=<}H#-tHU A1wHT$HtI A1wD-%d!E=c!9=!t1CaHD$0HD$8HD$@HD$X@xu1D%c!Eu= xtԕ HD$8HtHt$8KuHD$@HtHt$@ 2u!H$(!dH3%(+ H8![]A\A]HT$Ht$H|$ ¾@@tHD$8HD$<-uzHD$xuwHp HD$ Ht$8tHD$@HtHt$@ ~tHD$0!H>HD$0H|$ -D<|H|$@tHD$ HD$ H_HD$0!@H|$ tH$ƿsx$%=1HL$H= ` A1vHt$8sH|$ qwfav#HR HtiHt$@tHt$@uCH|$ 1HxtH5 1w A H uYHD$X@HT$Ht$Hu1@uHt$8rHD$@HtHt$@ rHD$0HP rHD$@HD$@HXHtHD$ HD$ HHD$0"@H|$p1jqHt$8KrHD$@HtHt$@ 2rd`!HD$(Ht H|$(o=z xaqg 1HD$0y!HtHD$ Ht HD$0H|$ HD$HH!Ht$H}HL$pHT$` Ad1Y@`H|$XMHD$(HD$(HH|$`1^p ?qHD$@8!DnE1IH|$ qH$  pHT$HHH$ HHD$HfH|$(VqHcӉHynA~ )HcHՅ֋-_!R^!rHT$HHD$PH9_HT$H A1qH= 5qHT$HHD$PH9*fHD$PH(HD$PHT$HHD$PH9}D]!EtHT$HHD$PH9H|$(smHt$( |nHD$HHHD$HHt$(bnHD$HHHD$HH|$ p uD ^!EnHD$HHT$PH9~ZfDHL$HHT$PH9AH5 #mH= pHT$P=I^!HHT$PuH5 #mHD$PHHD$PHT$HHD$PH9}H= oGD]!EtEHD$HH~;HD$HH=H5U #KmH5D :mH=3 noDG\!EEyA<$ t ApHD$HH|$p1KmHD$0Ht HD$0H|$ H|$(k!1y $Ht$8mHD$@HHt$@ mj8pHL$H= I@1{pHt$8m!Uj8pHL$H== I@11pHD$0H H HT$H A1nH=Ə nHT$HHD$PH9HD$PH(HD$PHT$HHD$PH9}5[!t0HT$HHD$PH9H5f \kH=U m jZ!oH|$ j,H|$(j'i8  =!S=|Z!F=۠!9H=I!H)lH=}I!lH$$fDŽ$pm1 AmHmHt$8kHt$@ k!SHT$H A1lH= Ilh8XnHL$H= I@1nHT$H A1lH= kjH5 #i)AiA<$mHL$H= I@1mM1H x 2HALmAVHAUATUSH0Ht$H|$HdH%(H$(1HL$HD$@5@D$4H$HD$`HD$hD$,D$,t5! $X!t D$,W!1HD$HHD$XHD$PaD$0luf1W!u= xh։ HD$XHtHt$XMi۝!H$(dH3%( H0[]A\A]A^@D$,REHD$Ht HD$8-tHT$U A1MjH$HI A1/j@hHD$XHD$8-xD$,2=o!t 1͌aqk5D$,t!H5 Ht1w AH<$H$Ht$1@Ht$XgHt$H$H|$uHD$8|$H|$iD5$!EHt$@H|$:HHD$="U!9=8!1藋Ht$1Y@!@HD$@HD$@HHD$8-pxfH| HD$8H|$8]gH$ƿfxH$HۉuHDŽ$ ; !v6H= !Ht WcH$(gHH !  !H|$p1Fe4!eYH޺ H0c1IDD-a !HR !H|$@xfHLkeHA1H-& !H|$8LcIfHLlc9؉HD$`ILl$`D-T!EtVD$,tNHD$`HT$hH93fH5 #cHT$hHHT$hHL$`HT$hH9}H=؇ fR!%HT$`HD$hH9D$,HT$` A1`fH= eHT$`HD$hH9HD$hH(HD$hHT$`HD$hH9}H|$/fHa8Hà H\H|$E[fE/Z!]; [a84gHL$H= I@1fH$1cHD$PHtHt$P ccQ!M!=R!tED$,t=HT$`HD$hH9}H58 #.bH5' bH= Qd5+Q!t*D$,t"HT$` A1dH= dD$4H|$@`t>`8 t A/eHD$`H|$8|`t,`8eHL$H= I@1eHD$HHt HD$HH|$8Ht$XbHD$PHtHt$P ~bH$1aH|$@E`1ɂ tHD$`HD$, ,!Ht$`H$HT$p APH|$@HD$H!HtHD$8Ht HD$HH|$8HD$@Ht H|$@_=- xa HD$`H!Ht$`H$HT$p AHD$8|H|$Ht$aHD$8HD$8H HD$H!@hH= oH|$@b\  tOfDHT$`HD$hH9|AD$,t9H5 #x_H=q aHD$hHHD$hD O!EuDiN!Et$HT$`HD$hH9|D$,fHD$`HHD$`H|$@Xa u1D$0u)Ht$8^HD$`HHD$` f.H|$8]^Ht$8 ^tfHT$` A1UaH=~ `HD$`HT$hH9FfDHD$hH(HD$hHT$`HD$hH9}DN!Et8HD$`H~.HD$`H=H5 ^H= 8`DM!Et D$,EED9bHL$H= A1a8D$4D$4; ]H|$l`^!8p ^HD$PH|$@H`HD$8HD$8HHD$H"@jaHL$H=& I@1aHt$X+^!H|$8^1Hމ`H([8aHL$H= I@1`HD$HHHD$HH|$8oH|$8111^-j yfD^tS E9H|$8|1^<[A<$ t At_HD$`T$4A1^AZA_A<$;HT$` A1U^H=~ ]@^(!H5T #J[0ZH|$H^yf.AUATUSHHl$dH%(H$1HHAH=9!\HcZH=9!H\I\H=y9! L?)HHH JL\x11IHH$HD$\x?u%H$dH3%(ucHĨ[]A\A]@1豻P@]1!5H=.!Ht4YH!Yf AH@8t u@1@{f !@AWAVAUATUSHHc!H!L=!L4IFI9HD$sTMIDMoLHI9v+J#I/ItHZ~HHIHkI9wIL;l$MrL5H!H[]A\A]A^A_ÐAUATUHSHHXHIXD- !EdE9|H7! AH[]A\A]f1I\=(}!9~H!E)!HHD-!HLlXHIWI|}ZHItEHLWHHVMeH[]A\A]1[*H)ʃef! A趤@AWAVAUATIUSHHH5!dH%(H$1H=!H~>f AfH8t0uHH9H96!/ A @I9HH5c!sG/HFu!HH{/HHSHL9uKH !HL/t?{H !@Ht8HE4VHIH0XHƿWxD$%=@$ULfWHS5!A A:fFHc!H5l!uEH=i! A?H-P!EH$dH3%(xHĨ[]A\A]A^A_H$!HHDUx AH!뛀x.D5!LhL=!HELL-!L=!D5!tH=!L!LXHtoH8tH;5!tkL~H=c!HH?{HZH5N!?1H;.uN!~LUH;5!sHF~FH!HH=!I\$H ʃ߃Av_t QЀ v-uFHH9w$Hl3!/ A ʃ߃AwHH9v܈@HH<3!/ A뉀/Hp!t HHd!LjI9~LUHtLp LSITH9!wmH2!Z AL-!MuLSHPLLWLH>uH5! H=!H5Jv HzRH`SHPLLUDf.AWAVAUIATUSH( Ld$dH%(H$ 1L{tfHHS{uGLLtF1)f.<}X<[EHUHՄt<{uEHUHՄuHELE1HD$I9vvE;M HI)LL $AUL $Ht$ LB PM]LLpEfIwII9wA{,[AGIW<]tt H<]uI<I6UHE]t+t'Hh@<]Hf.H}tK=u EIf1H$ dH3 %(u{H( []A\A]A^A_fEAIqf.AIZH1 LH$H$H rPf.ATHUHSHZHM dH%(H$1fDE@HECfDHP/@Hn 2HZ;u AL6W :H2-MAU1ATIUSHH8 f dH%(H$( 1HH|$HD$Hl$tJf<~e<{-HtDHCuH]HHuf= *HD$ 1H7,!D$ Hs Hd H$ HM P=(PU5ISOHr1HHJ H; - P=('A<${  uAD$<}H L H  txqS}u{@Hf t H1OPLA|$m ALr4 H-E u & H]LeH*L1fDHHxuHcHMH#HLH1ɐHHHHHHZH)HuHH H$( dH34%(0H8 []A\A]IHHHcMHIML1fHHKH|LHSHEHuIDLs1xN*H)HcH<1)! AHD$YHD$u! AHD$@H]HD$1{! A!5H}HHtHHH;HuHHHl 1ISHH?HHtHWHH{Hu[f.fHbLf.Hj9!tPH=!HtK%I=ok xI=[k FJLk 9!9!t'H=!HtMKH8!I!1HRfHI\ HDE1E1E1۸5aD:HJEt\H @tKH2H@:qt@uH)IcH9~2AIAH0HHuA~:HDfDH0AHHqDHE1L@f.AWAVAUATUHSHt~?HLeLHtLHt3L@H 1d AJH[]A\A]A^A_LJ AJL. A1J끿x AFD%Z IcL,@II5aI5a15aH;G9LH0L9rPADECD&AOHcЃH$5aH@LkI}Ha,ALIuH'A t,H= AHT$ ƿ@x D$8? HD$H8a H!%tDHJHDHHazOAHt$HHfH=1c aOA1#CVfDH= @HT$ ƿ?x D$8?7HD$H8a H!%tDHJHDHHazz@Ht$HHaH<AD  Hc-!HH3bH3b3bfDH= $@AtBBHIcDH u HD{H9uA u bf t[H= ?uAPb@9SH ^ -HA>H ^ 0A>H ^ -HA>H ^ 1xAr>:AWAAVIAUIATL%8F UH-8F SL)1HH7HtLLDAHH9uH[]A\A]A^A_Ðf.fHHTYPE %s %sTYPE %s%s: unknown mode nmap: unbalanced bracketsIncredible pattern: %s ../aNLSTfdopen failed, oops %s %s? Continue withmallocQUITsorry, arguments too long (%s) remote-filelocal-filelocal: %s: %s MDTM %s%*s %04d%02d%02d%02d%02d%02dRETRtousage: %s host-name [port] SYSTRemote system type is %s. 215 UNIX Type: L8215 TOPS20usage: %s [ ]%s%s | sizebinaryasciitenexSTORAPPESTOUlocal-filesusage: %s local-files mputr+wremote-filesusage: %s remote-files mgetConnected to %s. Not connected. No proxy connection. Case: %s; CR stripping: %s Ntrans: (in) %s (out) %s Ntrans: offNmap: (in) %s (out) %s Nmap: offTick counter printing: %s Macros:Bell mode %s. Packet tracing %s. Tick counter printing %s (%d bytes/tick increment)Hash mark printing %s (%d bytes/hash mark)Verbose mode %s. Use of PORT cmds %s. Interactive mode %s. Globbing %s. %s: bad debugging value. Debugging %s (debug=%d). remote-directoryusage: %s remote-directory XCWD %susage: %s local-directory Local directory now %s usage: %s remote-file DELE %smdeletefrom-name%s from-name to-name to-nameRNFR %sRNTO %sLISToutput to local-file:/bin/shSHELL-cTry again laterusernameUSER %sPassword: PASS %sAccount: ACCT %sXPWDdirectory-nameusage: %s directory-name XMKD %sXRMD %scommand line to sendusage: %s line-to-send arguments to SITE commandSITE usage: %s mode file-name file-nameSITE CHMOD %s %sSITE UMASKSITE UMASK %sSITE IDLESITE IDLE %sHELPHELP %sftp: %s Account:usage: %s command ?Ambiguous command?Invalid command?Invalid proxy commandNot connectedCase mapping %s. Ntrans off.Nmap off.mapoutUsage: %s [mapin mapout] Store unique %s. Receive unique %s. CDUPXCUPrestart: offset not specifiedrestarting at %ld. %s macro nameUsage: %s macro_name Passive mode %s. filenameusage: %s filename SIZE %sSTAT %sSTATAIimageebcdicExtremely long filename from server: %sFilename provided by server doesn't match pattern `%s': %s Error creating temporary file, oops Refusing to handle insecure file list usage: %s remote-file [ local-file ] Already connected to %s, use close first. Using %s mode to transfer files. Remember to set tenex mode when transfering binary files from this machine. ftp: internal error: unknown type %d We only support %s mode, sorry. We only support %s format, sorry. We only support %s structure, sorry. usage: %s local-file remote-file Warning: embedded .. in %.*s (changing to !!) Connected for proxy commands to %s. Mode: %s; Type: %s; Form: %s; Structure: %s Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s Store unique: %s; Receive unique: %s Hash mark printing: %s; Use of PORT cmds: %s CWD command not recognized, trying XCWD usage: %s remote-directory local-file usage: %s remote-files local-file usage: %s username [password] [account] PWD command not recognized, trying XPWD MKD command not recognized, trying XMKD RMD command not recognized, trying XRMD Carriage Return stripping %s. CDUP command not recognized, trying XCUP execute get, put or append to initiate transferLimit of 16 macros have already been definedEnter macro line by line, terminating it with a null linemacdef:end of file encounteredMacro not defined - 4k buffer exceeded%s %02d/%02d/%04d %02d:%02d:%02d GMT Local file "%s" is newer than remote file "%s" !$accountappendbellbyecasecdupchmodcrdebugdisconnectexitformglobhashidlelcdmacdefmkdirmlsmodtimenewernmapnlistntransopenpromptpassiveproxysendportpwdquitquoterecvregetrstatusrhelprenameresetrestartrmdirruniquesitestructsystemsuniqueticktracetypeuserumaskverbosetoggle verbose modesend new user informationget (set) umask on remote sideset file transfer typetoggle packet tracingtoggle printing byte counter during transfersset tenex file transfer typeshow remote system typetoggle store unique on remote machineset file transfer structureshow current statusshow size of remote fileescape to the shellsend site specific command to remote server Try "rhelp site" or "site help" for more informationsend one fileclear queued command repliestoggle store unique for local filesshow status of remote machineremove directory on the remote machinerestart file transfer at bytecountrename fileget help from remote serverget file restarting at end of local filereceive filesend arbitrary ftp commandterminate ftp session and exitprint working directory on remote machineissue command on alternate connectionforce interactive prompting on multiple commandstoggle use of PORT cmd for each data connectionenter passive transfer modeset translation table for default file name mappingset templates for default file name mappingnlist contents of remote directoryget file if remote file is newer than local file send multiple filesset file transfer modeshow last modification time of remote filelist contents of multiple remote directoriesmake directory on the remote machineget multiple fileslist contents of multiple remote directoriesdelete multiple filesdefine a macrolist contents of remote directorychange local working directoryget (set) idle timer on remote sideprint local help informationtoggle printing `#' for each buffer transferredtoggle metacharacter expansion of local file namesset file transfer formatexecute macroterminate ftp sessionlist contents of remote directorytoggle/set debugging modedelete remote filetoggle carriage return stripping on ascii getsconnect to remote ftpchange file permissions of remote filechange remote working directory to parent directorychange remote working directorytoggle mget upper/lower case id mappingset binary transfer typebeep when command completedset ascii transfer typeappend to a filesend account command to remote serverUsage: %s macro_name. '%s' macro not found. Not connected. send aborted waiting for remote to finish abort receive aborted waiting for remote to finish abortrunique: can't find unique file name.%lld bytes %s in %.3g secs (%.2f Kbytes/sec) 421 Service not available, remote server has closed connectionftp: mismatch struct sockaddr sizeNo control connection for commanduse of scoped address can be troublesome wrong server: return code must be 229 %u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%uPassive mode address scan failure. Shouldn't happen! wrong server: return code must be %d ftp: setsockopt (reuse address)LPRT 6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,2,%d,%dPassive mode AF mismatch. Shouldn't happen! proxy server does not support third party transfers.ftp: no answer from ftp-server (more than 5 sec). WARNING! %d bare linefeeds received in ASCII mode File may not have transferred correctly.ftp: acceptftp: setsockopt TOS (ignored)%c%c%c%s:ftp: mismatch address familyftp: socketftp: connectftp: unknown%dftp: %s%s%s: %s Trying %s... ftp: connect to address %sftp: getsocknameftp: fdopen failed. Connected to %s (%s). ftp: setsockopt---> PASS PASS XXXXName (%s:%s): Name (%s): Login failed. Password:initPASVLPSVftp: closeftp multihome bindftp: setsockopt (ignored)EPSV 2Passive mode refused.%u,%u,%u,%u,%u,%u,%u,%u,%uEPSV%c%c%c%u%cftp: setsockopt failed ftp: bindftp: listenEPRT |%d|%s|%s|PORT %u,%u,%u,%u,%u,%uabort%cABOR No primary connectionPORT %slocal: %s remote: %s local: %s %s: not a plain file. REST %ld Bytes transferred: %lld Bytes transferred: %lld netoutftp: pollsentnetin%s: short write received?.A@@`{[*?Arguments too longOut of memoryPathname too longBad directory componentsUnknown user name after ~Commands may be abbreviated. Commands are: ftp: ftp/tcp: unknown service Usage: { ftp | pftp } [-Apinegvtd] [hostname] -p: enable passive mode (default for ftp and pftp) -i: turn off prompting during mget -e: disable readline support, if present -g: disable filename globbing -m: don't force data channel interface to the same as control channel -t: enable packet tracing [nonfunctional]?Ambiguous help command %s ?Invalid help command %s %-*s %s tcpftpTERM -A: enable active mode -n: inhibit auto-login -v: verbose mode -d: enable debuggingftp: %c: unknown option ftp> sorry, input line too long)@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@ )@(@(@(@m(@a(@(@(@(@U(@I(@(@=(@(@(@(@4(@(@'@Warning: .netrc token too long, will be trunctated to %zd characters Error: `password' must follow `login' in .netrc Error - .netrc file not correct permissions. Remove password or correct mode (should be 600). Remove account or correct mode (should be 600). Macro definition missing null line terminator.HOME%s/.netrcanonymousMissing macdef name argument.Unknown .netrc keyword %s 4K macro buffer exceededdefaultpasswordpasswdmachine;t<<\8, 4l#%<&&L)*\++L,,-t|2L66D7,9<9L9\9 9$9<9T < B B 7zXZִF!t/]?Eh=ڊ̓NI B&(4N q'# /|1x=;1i)f6K qԦ*O[ +ϟC臇|/_V5Xq`"dNG!5IM,HHMLSUHR,Nf(yс /d[W''*fF ѤaH0zwꃩ-C;um` rhڱJ\9fA(?_۩?>R0/V,>X7ٙGF S$ks3ϊYWqHl+ "ܺ/ u +S E=(8`g!"ҨWɨ*LMymH~ʁ4Z Mp &O]Օ ckj㬬smZIӖ?mKܤH~!21-οcp˜VM=Xcp[*xsiV+f?L07A9g[ga ,^F&9 &oIhJIbq-(ư7pQAN bC;V7SvQ랲f[)⎘ =4ILwޤC+GTΈ1E@;z8N;tN%NqYi&,֠&u ^ OG@e!Mp{(x:ʹ/H, dRǣJ; )drZ {jz*v0{J s*"oUNudDe1!N,?m3F⬧Z诚C b6oduSe ۸ChFOW`4 o" BuaweaT]* Ͻb'~5vu"Jζ۱#iZl-Cbnb+ TAN! 4O(_Q _0D@aS0YLyP! Vu0nʳ=3 "pO=clL =Tʩaj-~de0-ԃz#5w,?6\/tДG]*#rE}64KF~pm]nTq(I;xz~N鋇R\>sJ-]iU3_Х@0Eb>gXN=1NnyawxG^('dC)QMfmbYCƑv2Oђ/ 2z4}j(YN }8zAbl' BIޟTĸ\w'`֯jgIW+^p:y1Yz%.J)20[aGi@.*ASnyv_M%:bـgM bȗ-pBBOB9x#u*!P6ǽ| kuInN-Lq:Cazy|\'q\q VUf pDw5*t(ߞ|m1ҥ-+3#=٨fE32tխC !u#T&5@Ysnyz˃ܷJԕ6CyVWq0Eql$=T{}Ʊн+9^-رgYZ.shstrtab.interp.note.ABI-tag.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.jcr.dynamic.got.got.plt.data.bss.gnu_debuglink.gnu_debugdata 8@8T@T !t@t$4o@P> @ F@No^@^[oX@Xj@xtBP@Ph  ~@y@&@&$@  @ ( APAP-a--a--a--a-/a/0a03a3< EaE EEM php_ftp.c000064400000111556147577111130006370 0ustar00/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrew Skalski | | Stefan Esser (resume functions) | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #if defined(NETWARE) && defined(USE_WINSOCK) #include #endif #if HAVE_OPENSSL_EXT # include #endif #if HAVE_FTP #include "ext/standard/info.h" #include "ext/standard/file.h" #include "php_ftp.h" #include "ftp.h" static int le_ftpbuf; #define le_ftpbuf_name "FTP Buffer" /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_connect, 0, 0, 1) ZEND_ARG_INFO(0, host) ZEND_ARG_INFO(0, port) ZEND_ARG_INFO(0, timeout) ZEND_END_ARG_INFO() #if HAVE_OPENSSL_EXT ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_ssl_connect, 0, 0, 1) ZEND_ARG_INFO(0, host) ZEND_ARG_INFO(0, port) ZEND_ARG_INFO(0, timeout) ZEND_END_ARG_INFO() #endif ZEND_BEGIN_ARG_INFO(arginfo_ftp_login, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, username) ZEND_ARG_INFO(0, password) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_pwd, 0) ZEND_ARG_INFO(0, ftp) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_cdup, 0) ZEND_ARG_INFO(0, ftp) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_chdir, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, directory) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_exec, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, command) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_raw, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, command) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_mkdir, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, directory) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_rmdir, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, directory) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_chmod, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_alloc, 0, 0, 2) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, size) ZEND_ARG_INFO(1, response) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_nlist, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, directory) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_rawlist, 0, 0, 2) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, directory) ZEND_ARG_INFO(0, recursive) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_systype, 0) ZEND_ARG_INFO(0, ftp) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_fget, 0, 0, 4) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, fp) ZEND_ARG_INFO(0, remote_file) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, resumepos) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_fget, 0, 0, 4) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, fp) ZEND_ARG_INFO(0, remote_file) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, resumepos) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_pasv, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, pasv) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_get, 0, 0, 4) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, local_file) ZEND_ARG_INFO(0, remote_file) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, resume_pos) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_get, 0, 0, 4) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, local_file) ZEND_ARG_INFO(0, remote_file) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, resume_pos) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_nb_continue, 0) ZEND_ARG_INFO(0, ftp) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_fput, 0, 0, 4) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, remote_file) ZEND_ARG_INFO(0, fp) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, startpos) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_fput, 0, 0, 4) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, remote_file) ZEND_ARG_INFO(0, fp) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, startpos) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_put, 0, 0, 4) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, remote_file) ZEND_ARG_INFO(0, local_file) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, startpos) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_put, 0, 0, 4) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, remote_file) ZEND_ARG_INFO(0, local_file) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, startpos) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_size, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_mdtm, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_rename, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, src) ZEND_ARG_INFO(0, dest) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_delete, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, file) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_site, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, cmd) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_close, 0) ZEND_ARG_INFO(0, ftp) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_set_option, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, option) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_ftp_get_option, 0) ZEND_ARG_INFO(0, ftp) ZEND_ARG_INFO(0, option) ZEND_END_ARG_INFO() /* }}} */ const zend_function_entry php_ftp_functions[] = { PHP_FE(ftp_connect, arginfo_ftp_connect) #if HAVE_OPENSSL_EXT PHP_FE(ftp_ssl_connect, arginfo_ftp_ssl_connect) #endif PHP_FE(ftp_login, arginfo_ftp_login) PHP_FE(ftp_pwd, arginfo_ftp_pwd) PHP_FE(ftp_cdup, arginfo_ftp_cdup) PHP_FE(ftp_chdir, arginfo_ftp_chdir) PHP_FE(ftp_exec, arginfo_ftp_exec) PHP_FE(ftp_raw, arginfo_ftp_raw) PHP_FE(ftp_mkdir, arginfo_ftp_mkdir) PHP_FE(ftp_rmdir, arginfo_ftp_rmdir) PHP_FE(ftp_chmod, arginfo_ftp_chmod) PHP_FE(ftp_alloc, arginfo_ftp_alloc) PHP_FE(ftp_nlist, arginfo_ftp_nlist) PHP_FE(ftp_rawlist, arginfo_ftp_rawlist) PHP_FE(ftp_systype, arginfo_ftp_systype) PHP_FE(ftp_pasv, arginfo_ftp_pasv) PHP_FE(ftp_get, arginfo_ftp_get) PHP_FE(ftp_fget, arginfo_ftp_fget) PHP_FE(ftp_put, arginfo_ftp_put) PHP_FE(ftp_fput, arginfo_ftp_fput) PHP_FE(ftp_size, arginfo_ftp_size) PHP_FE(ftp_mdtm, arginfo_ftp_mdtm) PHP_FE(ftp_rename, arginfo_ftp_rename) PHP_FE(ftp_delete, arginfo_ftp_delete) PHP_FE(ftp_site, arginfo_ftp_site) PHP_FE(ftp_close, arginfo_ftp_close) PHP_FE(ftp_set_option, arginfo_ftp_set_option) PHP_FE(ftp_get_option, arginfo_ftp_get_option) PHP_FE(ftp_nb_fget, arginfo_ftp_nb_fget) PHP_FE(ftp_nb_get, arginfo_ftp_nb_get) PHP_FE(ftp_nb_continue, arginfo_ftp_nb_continue) PHP_FE(ftp_nb_put, arginfo_ftp_nb_put) PHP_FE(ftp_nb_fput, arginfo_ftp_nb_fput) PHP_FALIAS(ftp_quit, ftp_close, arginfo_ftp_close) PHP_FE_END }; zend_module_entry php_ftp_module_entry = { STANDARD_MODULE_HEADER, "ftp", php_ftp_functions, PHP_MINIT(ftp), NULL, NULL, NULL, PHP_MINFO(ftp), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; #if COMPILE_DL_FTP ZEND_GET_MODULE(php_ftp) #endif static void ftp_destructor_ftpbuf(zend_rsrc_list_entry *rsrc TSRMLS_DC) { ftpbuf_t *ftp = (ftpbuf_t *)rsrc->ptr; ftp_close(ftp); } PHP_MINIT_FUNCTION(ftp) { #ifdef HAVE_OPENSSL_EXT SSL_library_init(); OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); #endif le_ftpbuf = zend_register_list_destructors_ex(ftp_destructor_ftpbuf, NULL, le_ftpbuf_name, module_number); REGISTER_LONG_CONSTANT("FTP_ASCII", FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_TEXT", FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_BINARY", FTPTYPE_IMAGE, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_IMAGE", FTPTYPE_IMAGE, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_AUTORESUME", PHP_FTP_AUTORESUME, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_TIMEOUT_SEC", PHP_FTP_OPT_TIMEOUT_SEC, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_AUTOSEEK", PHP_FTP_OPT_AUTOSEEK, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_USEPASVADDRESS", PHP_FTP_OPT_USEPASVADDRESS, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_FAILED", PHP_FTP_FAILED, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_FINISHED", PHP_FTP_FINISHED, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("FTP_MOREDATA", PHP_FTP_MOREDATA, CONST_PERSISTENT | CONST_CS); return SUCCESS; } PHP_MINFO_FUNCTION(ftp) { php_info_print_table_start(); php_info_print_table_row(2, "FTP support", "enabled"); php_info_print_table_end(); } #define XTYPE(xtype, mode) { \ if (mode != FTPTYPE_ASCII && mode != FTPTYPE_IMAGE) { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Mode must be FTP_ASCII or FTP_BINARY"); \ RETURN_FALSE; \ } \ xtype = mode; \ } /* {{{ proto resource ftp_connect(string host [, int port [, int timeout]]) Opens a FTP stream */ PHP_FUNCTION(ftp_connect) { ftpbuf_t *ftp; char *host; int host_len; long port = 0; long timeout_sec = FTP_DEFAULT_TIMEOUT; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &host, &host_len, &port, &timeout_sec) == FAILURE) { return; } if (timeout_sec <= 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Timeout has to be greater than 0"); RETURN_FALSE; } /* connect */ if (!(ftp = ftp_open(host, (short)port, timeout_sec TSRMLS_CC))) { RETURN_FALSE; } /* autoseek for resuming */ ftp->autoseek = FTP_DEFAULT_AUTOSEEK; ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS; #if HAVE_OPENSSL_EXT /* disable ssl */ ftp->use_ssl = 0; #endif ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf); } /* }}} */ #if HAVE_OPENSSL_EXT /* {{{ proto resource ftp_ssl_connect(string host [, int port [, int timeout]]) Opens a FTP-SSL stream */ PHP_FUNCTION(ftp_ssl_connect) { ftpbuf_t *ftp; char *host; int host_len; long port = 0; long timeout_sec = FTP_DEFAULT_TIMEOUT; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &host, &host_len, &port, &timeout_sec) == FAILURE) { return; } if (timeout_sec <= 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Timeout has to be greater than 0"); RETURN_FALSE; } /* connect */ if (!(ftp = ftp_open(host, (short)port, timeout_sec TSRMLS_CC))) { RETURN_FALSE; } /* autoseek for resuming */ ftp->autoseek = FTP_DEFAULT_AUTOSEEK; ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS; /* enable ssl */ ftp->use_ssl = 1; ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf); } /* }}} */ #endif /* {{{ proto bool ftp_login(resource stream, string username, string password) Logs into the FTP server */ PHP_FUNCTION(ftp_login) { zval *z_ftp; ftpbuf_t *ftp; char *user, *pass; int user_len, pass_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &z_ftp, &user, &user_len, &pass, &pass_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* log in */ if (!ftp_login(ftp, user, pass TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto string ftp_pwd(resource stream) Returns the present working directory */ PHP_FUNCTION(ftp_pwd) { zval *z_ftp; ftpbuf_t *ftp; const char *pwd; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); if (!(pwd = ftp_pwd(ftp))) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_STRING((char*) pwd, 1); } /* }}} */ /* {{{ proto bool ftp_cdup(resource stream) Changes to the parent directory */ PHP_FUNCTION(ftp_cdup) { zval *z_ftp; ftpbuf_t *ftp; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); if (!ftp_cdup(ftp)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto bool ftp_chdir(resource stream, string directory) Changes directories */ PHP_FUNCTION(ftp_chdir) { zval *z_ftp; ftpbuf_t *ftp; char *dir; int dir_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &dir, &dir_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* change directories */ if (!ftp_chdir(ftp, dir)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto bool ftp_exec(resource stream, string command) Requests execution of a program on the FTP server */ PHP_FUNCTION(ftp_exec) { zval *z_ftp; ftpbuf_t *ftp; char *cmd; int cmd_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* execute serverside command */ if (!ftp_exec(ftp, cmd)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto array ftp_raw(resource stream, string command) Sends a literal command to the FTP server */ PHP_FUNCTION(ftp_raw) { zval *z_ftp; ftpbuf_t *ftp; char *cmd; int cmd_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* execute arbitrary ftp command */ ftp_raw(ftp, cmd, return_value); } /* }}} */ /* {{{ proto string ftp_mkdir(resource stream, string directory) Creates a directory and returns the absolute path for the new directory or false on error */ PHP_FUNCTION(ftp_mkdir) { zval *z_ftp; ftpbuf_t *ftp; char *dir, *tmp; int dir_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &dir, &dir_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* create directorie */ if (NULL == (tmp = ftp_mkdir(ftp, dir))) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_STRING(tmp, 0); } /* }}} */ /* {{{ proto bool ftp_rmdir(resource stream, string directory) Removes a directory */ PHP_FUNCTION(ftp_rmdir) { zval *z_ftp; ftpbuf_t *ftp; char *dir; int dir_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &dir, &dir_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* remove directorie */ if (!ftp_rmdir(ftp, dir)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto int ftp_chmod(resource stream, int mode, string filename) Sets permissions on a file */ PHP_FUNCTION(ftp_chmod) { zval *z_ftp; ftpbuf_t *ftp; char *filename; int filename_len; long mode; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlp", &z_ftp, &mode, &filename, &filename_len) == FAILURE) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); if (!ftp_chmod(ftp, mode, filename, filename_len)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_LONG(mode); } /* }}} */ /* {{{ proto bool ftp_alloc(resource stream, int size[, &response]) Attempt to allocate space on the remote FTP server */ PHP_FUNCTION(ftp_alloc) { zval *z_ftp, *zresponse = NULL; ftpbuf_t *ftp; long size, ret; char *response = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|z", &z_ftp, &size, &zresponse) == FAILURE) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); ret = ftp_alloc(ftp, size, zresponse ? &response : NULL); if (response) { zval_dtor(zresponse); ZVAL_STRING(zresponse, response, 0); } if (!ret) { RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto array ftp_nlist(resource stream, string directory) Returns an array of filenames in the given directory */ PHP_FUNCTION(ftp_nlist) { zval *z_ftp; ftpbuf_t *ftp; char **nlist, **ptr, *dir; int dir_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &z_ftp, &dir, &dir_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* get list of files */ if (NULL == (nlist = ftp_nlist(ftp, dir TSRMLS_CC))) { RETURN_FALSE; } array_init(return_value); for (ptr = nlist; *ptr; ptr++) { add_next_index_string(return_value, *ptr, 1); } efree(nlist); } /* }}} */ /* {{{ proto array ftp_rawlist(resource stream, string directory [, bool recursive]) Returns a detailed listing of a directory as an array of output lines */ PHP_FUNCTION(ftp_rawlist) { zval *z_ftp; ftpbuf_t *ftp; char **llist, **ptr, *dir; int dir_len; zend_bool recursive = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|b", &z_ftp, &dir, &dir_len, &recursive) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* get raw directory listing */ if (NULL == (llist = ftp_list(ftp, dir, recursive TSRMLS_CC))) { RETURN_FALSE; } array_init(return_value); for (ptr = llist; *ptr; ptr++) { add_next_index_string(return_value, *ptr, 1); } efree(llist); } /* }}} */ /* {{{ proto string ftp_systype(resource stream) Returns the system type identifier */ PHP_FUNCTION(ftp_systype) { zval *z_ftp; ftpbuf_t *ftp; const char *syst; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); if (NULL == (syst = ftp_syst(ftp))) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_STRING((char*) syst, 1); } /* }}} */ /* {{{ proto bool ftp_fget(resource stream, resource fp, string remote_file, int mode[, int resumepos]) Retrieves a file from the FTP server and writes it to an open file */ PHP_FUNCTION(ftp_fget) { zval *z_ftp, *z_file; ftpbuf_t *ftp; ftptype_t xtype; php_stream *stream; char *file; int file_len; long mode, resumepos=0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrsl|l", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); php_stream_from_zval(stream, &z_file); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) { resumepos = 0; } if (ftp->autoseek && resumepos) { /* if autoresume is wanted seek to end */ if (resumepos == PHP_FTP_AUTORESUME) { php_stream_seek(stream, 0, SEEK_END); resumepos = php_stream_tell(stream); } else { php_stream_seek(stream, resumepos, SEEK_SET); } } if (!ftp_get(ftp, stream, file, xtype, resumepos TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto int ftp_nb_fget(resource stream, resource fp, string remote_file, int mode[, int resumepos]) Retrieves a file from the FTP server asynchronly and writes it to an open file */ PHP_FUNCTION(ftp_nb_fget) { zval *z_ftp, *z_file; ftpbuf_t *ftp; ftptype_t xtype; php_stream *stream; char *file; int file_len; long mode, resumepos=0, ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrsl|l", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); php_stream_from_zval(stream, &z_file); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) { resumepos = 0; } if (ftp->autoseek && resumepos) { /* if autoresume is wanted seek to end */ if (resumepos == PHP_FTP_AUTORESUME) { php_stream_seek(stream, 0, SEEK_END); resumepos = php_stream_tell(stream); } else { php_stream_seek(stream, resumepos, SEEK_SET); } } /* configuration */ ftp->direction = 0; /* recv */ ftp->closestream = 0; /* do not close */ if ((ret = ftp_nb_get(ftp, stream, file, xtype, resumepos TSRMLS_CC)) == PHP_FTP_FAILED) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_LONG(ret); } RETURN_LONG(ret); } /* }}} */ /* {{{ proto bool ftp_pasv(resource stream, bool pasv) Turns passive mode on or off */ PHP_FUNCTION(ftp_pasv) { zval *z_ftp; ftpbuf_t *ftp; zend_bool pasv; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rb", &z_ftp, &pasv) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); if (!ftp_pasv(ftp, pasv ? 1 : 0)) { RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto bool ftp_get(resource stream, string local_file, string remote_file, int mode[, int resume_pos]) Retrieves a file from the FTP server and writes it to a local file */ PHP_FUNCTION(ftp_get) { zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; php_stream *outstream; char *local, *remote; int local_len, remote_len; long mode, resumepos=0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) { resumepos = 0; } #ifdef PHP_WIN32 mode = FTPTYPE_IMAGE; #endif if (ftp->autoseek && resumepos) { outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL); if (outstream == NULL) { outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); } if (outstream != NULL) { /* if autoresume is wanted seek to end */ if (resumepos == PHP_FTP_AUTORESUME) { php_stream_seek(outstream, 0, SEEK_END); resumepos = php_stream_tell(outstream); } else { php_stream_seek(outstream, resumepos, SEEK_SET); } } } else { outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); } if (outstream == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error opening %s", local); RETURN_FALSE; } if (!ftp_get(ftp, outstream, remote, xtype, resumepos TSRMLS_CC)) { php_stream_close(outstream); VCWD_UNLINK(local); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } php_stream_close(outstream); RETURN_TRUE; } /* }}} */ /* {{{ proto int ftp_nb_get(resource stream, string local_file, string remote_file, int mode[, int resume_pos]) Retrieves a file from the FTP server nbhronly and writes it to a local file */ PHP_FUNCTION(ftp_nb_get) { zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; php_stream *outstream; char *local, *remote; int local_len, remote_len, ret; long mode, resumepos=0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) { resumepos = 0; } #ifdef PHP_WIN32 mode = FTPTYPE_IMAGE; #endif if (ftp->autoseek && resumepos) { outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL); if (outstream == NULL) { outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); } if (outstream != NULL) { /* if autoresume is wanted seek to end */ if (resumepos == PHP_FTP_AUTORESUME) { php_stream_seek(outstream, 0, SEEK_END); resumepos = php_stream_tell(outstream); } else { php_stream_seek(outstream, resumepos, SEEK_SET); } } } else { outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); } if (outstream == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error opening %s", local); RETURN_FALSE; } /* configuration */ ftp->direction = 0; /* recv */ ftp->closestream = 1; /* do close */ if ((ret = ftp_nb_get(ftp, outstream, remote, xtype, resumepos TSRMLS_CC)) == PHP_FTP_FAILED) { php_stream_close(outstream); ftp->stream = NULL; VCWD_UNLINK(local); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_LONG(PHP_FTP_FAILED); } if (ret == PHP_FTP_FINISHED){ php_stream_close(outstream); ftp->stream = NULL; } RETURN_LONG(ret); } /* }}} */ /* {{{ proto int ftp_nb_continue(resource stream) Continues retrieving/sending a file nbronously */ PHP_FUNCTION(ftp_nb_continue) { zval *z_ftp; ftpbuf_t *ftp; long ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); if (!ftp->nb) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "no nbronous transfer to continue."); RETURN_LONG(PHP_FTP_FAILED); } if (ftp->direction) { ret=ftp_nb_continue_write(ftp TSRMLS_CC); } else { ret=ftp_nb_continue_read(ftp TSRMLS_CC); } if (ret != PHP_FTP_MOREDATA && ftp->closestream) { php_stream_close(ftp->stream); ftp->stream = NULL; } if (ret == PHP_FTP_FAILED) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); } RETURN_LONG(ret); } /* }}} */ /* {{{ proto bool ftp_fput(resource stream, string remote_file, resource fp, int mode[, int startpos]) Stores a file from an open file to the FTP server */ PHP_FUNCTION(ftp_fput) { zval *z_ftp, *z_file; ftpbuf_t *ftp; ftptype_t xtype; int remote_len; long mode, startpos=0; php_stream *stream; char *remote; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrl|l", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); php_stream_from_zval(stream, &z_file); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) { startpos = 0; } if (ftp->autoseek && startpos) { /* if autoresume is wanted ask for remote size */ if (startpos == PHP_FTP_AUTORESUME) { startpos = ftp_size(ftp, remote); if (startpos < 0) { startpos = 0; } } if (startpos) { php_stream_seek(stream, startpos, SEEK_SET); } } if (!ftp_put(ftp, remote, stream, xtype, startpos TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto int ftp_nb_fput(resource stream, string remote_file, resource fp, int mode[, int startpos]) Stores a file from an open file to the FTP server nbronly */ PHP_FUNCTION(ftp_nb_fput) { zval *z_ftp, *z_file; ftpbuf_t *ftp; ftptype_t xtype; int remote_len, ret; long mode, startpos=0; php_stream *stream; char *remote; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrl|l", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); php_stream_from_zval(stream, &z_file); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) { startpos = 0; } if (ftp->autoseek && startpos) { /* if autoresume is wanted ask for remote size */ if (startpos == PHP_FTP_AUTORESUME) { startpos = ftp_size(ftp, remote); if (startpos < 0) { startpos = 0; } } if (startpos) { php_stream_seek(stream, startpos, SEEK_SET); } } /* configuration */ ftp->direction = 1; /* send */ ftp->closestream = 0; /* do not close */ if (((ret = ftp_nb_put(ftp, remote, stream, xtype, startpos TSRMLS_CC)) == PHP_FTP_FAILED)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_LONG(ret); } RETURN_LONG(ret); } /* }}} */ /* {{{ proto bool ftp_put(resource stream, string remote_file, string local_file, int mode[, int startpos]) Stores a file on the FTP server */ PHP_FUNCTION(ftp_put) { zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; char *remote, *local; long remote_len, local_len; long mode, startpos=0; php_stream *instream; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); XTYPE(xtype, mode); if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) { RETURN_FALSE; } /* ignore autoresume if autoseek is switched off */ if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) { startpos = 0; } if (ftp->autoseek && startpos) { /* if autoresume is wanted ask for remote size */ if (startpos == PHP_FTP_AUTORESUME) { startpos = ftp_size(ftp, remote); if (startpos < 0) { startpos = 0; } } if (startpos) { php_stream_seek(instream, startpos, SEEK_SET); } } if (!ftp_put(ftp, remote, instream, xtype, startpos TSRMLS_CC)) { php_stream_close(instream); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } php_stream_close(instream); RETURN_TRUE; } /* }}} */ /* {{{ proto int ftp_nb_put(resource stream, string remote_file, string local_file, int mode[, int startpos]) Stores a file on the FTP server */ PHP_FUNCTION(ftp_nb_put) { zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; char *remote, *local; int remote_len, local_len; long mode, startpos=0, ret; php_stream *instream; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); XTYPE(xtype, mode); if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) { RETURN_FALSE; } /* ignore autoresume if autoseek is switched off */ if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) { startpos = 0; } if (ftp->autoseek && startpos) { /* if autoresume is wanted ask for remote size */ if (startpos == PHP_FTP_AUTORESUME) { startpos = ftp_size(ftp, remote); if (startpos < 0) { startpos = 0; } } if (startpos) { php_stream_seek(instream, startpos, SEEK_SET); } } /* configuration */ ftp->direction = 1; /* send */ ftp->closestream = 1; /* do close */ ret = ftp_nb_put(ftp, remote, instream, xtype, startpos TSRMLS_CC); if (ret != PHP_FTP_MOREDATA) { php_stream_close(instream); ftp->stream = NULL; } if (ret == PHP_FTP_FAILED) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); } RETURN_LONG(ret); } /* }}} */ /* {{{ proto int ftp_size(resource stream, string filename) Returns the size of the file, or -1 on error */ PHP_FUNCTION(ftp_size) { zval *z_ftp; ftpbuf_t *ftp; char *file; int file_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &z_ftp, &file, &file_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* get file size */ RETURN_LONG(ftp_size(ftp, file)); } /* }}} */ /* {{{ proto int ftp_mdtm(resource stream, string filename) Returns the last modification time of the file, or -1 on error */ PHP_FUNCTION(ftp_mdtm) { zval *z_ftp; ftpbuf_t *ftp; char *file; int file_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &z_ftp, &file, &file_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* get file mod time */ RETURN_LONG(ftp_mdtm(ftp, file)); } /* }}} */ /* {{{ proto bool ftp_rename(resource stream, string src, string dest) Renames the given file to a new path */ PHP_FUNCTION(ftp_rename) { zval *z_ftp; ftpbuf_t *ftp; char *src, *dest; int src_len, dest_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &z_ftp, &src, &src_len, &dest, &dest_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* rename the file */ if (!ftp_rename(ftp, src, dest)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto bool ftp_delete(resource stream, string file) Deletes a file */ PHP_FUNCTION(ftp_delete) { zval *z_ftp; ftpbuf_t *ftp; char *file; int file_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &file, &file_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* delete the file */ if (!ftp_delete(ftp, file)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto bool ftp_site(resource stream, string cmd) Sends a SITE command to the server */ PHP_FUNCTION(ftp_site) { zval *z_ftp; ftpbuf_t *ftp; char *cmd; int cmd_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); /* send the site command */ if (!ftp_site(ftp, cmd)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto bool ftp_close(resource stream) Closes the FTP stream */ PHP_FUNCTION(ftp_close) { zval *z_ftp; ftpbuf_t *ftp; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); ftp_quit(ftp); RETURN_BOOL(zend_list_delete(Z_LVAL_P(z_ftp)) == SUCCESS); } /* }}} */ /* {{{ proto bool ftp_set_option(resource stream, int option, mixed value) Sets an FTP option */ PHP_FUNCTION(ftp_set_option) { zval *z_ftp, *z_value; long option; ftpbuf_t *ftp; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &z_ftp, &option, &z_value) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); switch (option) { case PHP_FTP_OPT_TIMEOUT_SEC: if (Z_TYPE_P(z_value) != IS_LONG) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option TIMEOUT_SEC expects value of type long, %s given", zend_zval_type_name(z_value)); RETURN_FALSE; } if (Z_LVAL_P(z_value) <= 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Timeout has to be greater than 0"); RETURN_FALSE; } ftp->timeout_sec = Z_LVAL_P(z_value); RETURN_TRUE; break; case PHP_FTP_OPT_AUTOSEEK: if (Z_TYPE_P(z_value) != IS_BOOL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option AUTOSEEK expects value of type boolean, %s given", zend_zval_type_name(z_value)); RETURN_FALSE; } ftp->autoseek = Z_LVAL_P(z_value); RETURN_TRUE; break; case PHP_FTP_OPT_USEPASVADDRESS: if (Z_TYPE_P(z_value) != IS_BOOL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option USEPASVADDRESS expects value of type boolean, %s given", zend_zval_type_name(z_value)); RETURN_FALSE; } ftp->usepasvaddress = Z_LVAL_P(z_value); RETURN_TRUE; break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option '%ld'", option); RETURN_FALSE; break; } } /* }}} */ /* {{{ proto mixed ftp_get_option(resource stream, int option) Gets an FTP option */ PHP_FUNCTION(ftp_get_option) { zval *z_ftp; long option; ftpbuf_t *ftp; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &z_ftp, &option) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); switch (option) { case PHP_FTP_OPT_TIMEOUT_SEC: RETURN_LONG(ftp->timeout_sec); break; case PHP_FTP_OPT_AUTOSEEK: RETURN_BOOL(ftp->autoseek); break; case PHP_FTP_OPT_USEPASVADDRESS: RETURN_BOOL(ftp->usepasvaddress); break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option '%ld'", option); RETURN_FALSE; break; } } /* }}} */ #endif /* HAVE_FTP */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * indent-tabs-mode: t * End: */ ftp.c000064400000107756147577111130005530 0ustar00/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrew Skalski | | Stefan Esser (resume functions) | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #if HAVE_FTP #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #ifdef PHP_WIN32 #include #elif defined(NETWARE) #ifdef USE_WINSOCK /* Modified to use Winsock (NOVSOCK2.H), at least for now */ #include #else #include #include #include #endif #else #ifdef HAVE_SYS_TYPES_H #include #endif #include #include #include #include #endif #include #if HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #if HAVE_OPENSSL_EXT #include #endif #include "ftp.h" #include "ext/standard/fsock.h" /* Additional headers for NetWare */ #if defined(NETWARE) && !defined(USE_WINSOCK) #include #endif /* sends an ftp command, returns true on success, false on error. * it sends the string "cmd args\r\n" if args is non-null, or * "cmd\r\n" if args is null */ static int ftp_putcmd( ftpbuf_t *ftp, const char *cmd, const char *args); /* wrapper around send/recv to handle timeouts */ static int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len); static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len); static int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen); /* reads a line the socket , returns true on success, false on error */ static int ftp_readline(ftpbuf_t *ftp); /* reads an ftp response, returns true on success, false on error */ static int ftp_getresp(ftpbuf_t *ftp); /* sets the ftp transfer type */ static int ftp_type(ftpbuf_t *ftp, ftptype_t type); /* opens up a data stream */ static databuf_t* ftp_getdata(ftpbuf_t *ftp TSRMLS_DC); /* accepts the data connection, returns updated data buffer */ static databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp TSRMLS_DC); /* closes the data connection, returns NULL */ static databuf_t* data_close(ftpbuf_t *ftp, databuf_t *data); /* generic file lister */ static char** ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC); /* IP and port conversion box */ union ipbox { struct in_addr ia[2]; unsigned short s[4]; unsigned char c[8]; }; /* {{{ ftp_open */ ftpbuf_t* ftp_open(const char *host, short port, long timeout_sec TSRMLS_DC) { ftpbuf_t *ftp; socklen_t size; struct timeval tv; /* alloc the ftp structure */ ftp = ecalloc(1, sizeof(*ftp)); tv.tv_sec = timeout_sec; tv.tv_usec = 0; ftp->fd = php_network_connect_socket_to_host(host, (unsigned short) (port ? port : 21), SOCK_STREAM, 0, &tv, NULL, NULL, NULL, 0 TSRMLS_CC); if (ftp->fd == -1) { goto bail; } /* Default Settings */ ftp->timeout_sec = timeout_sec; ftp->nb = 0; size = sizeof(ftp->localaddr); memset(&ftp->localaddr, 0, size); if (getsockname(ftp->fd, (struct sockaddr*) &ftp->localaddr, &size) != 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "getsockname failed: %s (%d)", strerror(errno), errno); goto bail; } if (!ftp_getresp(ftp) || ftp->resp != 220) { goto bail; } return ftp; bail: if (ftp->fd != -1) { closesocket(ftp->fd); } efree(ftp); return NULL; } /* }}} */ /* {{{ ftp_close */ ftpbuf_t* ftp_close(ftpbuf_t *ftp) { if (ftp == NULL) { return NULL; } if (ftp->data) { data_close(ftp, ftp->data); } if (ftp->stream && ftp->closestream) { TSRMLS_FETCH(); php_stream_close(ftp->stream); } if (ftp->fd != -1) { #if HAVE_OPENSSL_EXT if (ftp->ssl_active) { SSL_shutdown(ftp->ssl_handle); SSL_free(ftp->ssl_handle); } #endif closesocket(ftp->fd); } ftp_gc(ftp); efree(ftp); return NULL; } /* }}} */ /* {{{ ftp_gc */ void ftp_gc(ftpbuf_t *ftp) { if (ftp == NULL) { return; } if (ftp->pwd) { efree(ftp->pwd); ftp->pwd = NULL; } if (ftp->syst) { efree(ftp->syst); ftp->syst = NULL; } } /* }}} */ /* {{{ ftp_quit */ int ftp_quit(ftpbuf_t *ftp) { if (ftp == NULL) { return 0; } if (!ftp_putcmd(ftp, "QUIT", NULL)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 221) { return 0; } if (ftp->pwd) { efree(ftp->pwd); ftp->pwd = NULL; } return 1; } /* }}} */ /* {{{ ftp_login */ int ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC) { #if HAVE_OPENSSL_EXT SSL_CTX *ctx = NULL; long ssl_ctx_options = SSL_OP_ALL; #endif if (ftp == NULL) { return 0; } #if HAVE_OPENSSL_EXT if (ftp->use_ssl && !ftp->ssl_active) { if (!ftp_putcmd(ftp, "AUTH", "TLS")) { return 0; } if (!ftp_getresp(ftp)) { return 0; } if (ftp->resp != 234) { if (!ftp_putcmd(ftp, "AUTH", "SSL")) { return 0; } if (!ftp_getresp(ftp)) { return 0; } if (ftp->resp != 334) { return 0; } else { ftp->old_ssl = 1; ftp->use_ssl_for_data = 1; } } ctx = SSL_CTX_new(SSLv23_client_method()); if (ctx == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create the SSL context"); return 0; } #if OPENSSL_VERSION_NUMBER >= 0x0090605fL ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; #endif SSL_CTX_set_options(ctx, ssl_ctx_options); /* allow SSL to re-use sessions */ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH); ftp->ssl_handle = SSL_new(ctx); if (ftp->ssl_handle == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create the SSL handle"); SSL_CTX_free(ctx); return 0; } SSL_set_fd(ftp->ssl_handle, ftp->fd); if (SSL_connect(ftp->ssl_handle) <= 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS handshake failed"); SSL_shutdown(ftp->ssl_handle); SSL_free(ftp->ssl_handle); return 0; } ftp->ssl_active = 1; if (!ftp->old_ssl) { /* set protection buffersize to zero */ if (!ftp_putcmd(ftp, "PBSZ", "0")) { return 0; } if (!ftp_getresp(ftp)) { return 0; } /* enable data conn encryption */ if (!ftp_putcmd(ftp, "PROT", "P")) { return 0; } if (!ftp_getresp(ftp)) { return 0; } ftp->use_ssl_for_data = (ftp->resp >= 200 && ftp->resp <=299); } } #endif if (!ftp_putcmd(ftp, "USER", user)) { return 0; } if (!ftp_getresp(ftp)) { return 0; } if (ftp->resp == 230) { return 1; } if (ftp->resp != 331) { return 0; } if (!ftp_putcmd(ftp, "PASS", pass)) { return 0; } if (!ftp_getresp(ftp)) { return 0; } return (ftp->resp == 230); } /* }}} */ /* {{{ ftp_reinit */ int ftp_reinit(ftpbuf_t *ftp) { if (ftp == NULL) { return 0; } ftp_gc(ftp); ftp->nb = 0; if (!ftp_putcmd(ftp, "REIN", NULL)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 220) { return 0; } return 1; } /* }}} */ /* {{{ ftp_syst */ const char* ftp_syst(ftpbuf_t *ftp) { char *syst, *end; if (ftp == NULL) { return NULL; } /* default to cached value */ if (ftp->syst) { return ftp->syst; } if (!ftp_putcmd(ftp, "SYST", NULL)) { return NULL; } if (!ftp_getresp(ftp) || ftp->resp != 215) { return NULL; } syst = ftp->inbuf; while (*syst == ' ') { syst++; } if ((end = strchr(syst, ' '))) { *end = 0; } ftp->syst = estrdup(syst); if (end) { *end = ' '; } return ftp->syst; } /* }}} */ /* {{{ ftp_pwd */ const char* ftp_pwd(ftpbuf_t *ftp) { char *pwd, *end; if (ftp == NULL) { return NULL; } /* default to cached value */ if (ftp->pwd) { return ftp->pwd; } if (!ftp_putcmd(ftp, "PWD", NULL)) { return NULL; } if (!ftp_getresp(ftp) || ftp->resp != 257) { return NULL; } /* copy out the pwd from response */ if ((pwd = strchr(ftp->inbuf, '"')) == NULL) { return NULL; } if ((end = strrchr(++pwd, '"')) == NULL) { return NULL; } ftp->pwd = estrndup(pwd, end - pwd); return ftp->pwd; } /* }}} */ /* {{{ ftp_exec */ int ftp_exec(ftpbuf_t *ftp, const char *cmd) { if (ftp == NULL) { return 0; } if (!ftp_putcmd(ftp, "SITE EXEC", cmd)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 200) { return 0; } return 1; } /* }}} */ /* {{{ ftp_raw */ void ftp_raw(ftpbuf_t *ftp, const char *cmd, zval *return_value) { if (ftp == NULL || cmd == NULL) { RETURN_NULL(); } if (!ftp_putcmd(ftp, cmd, NULL)) { RETURN_NULL(); } array_init(return_value); while (ftp_readline(ftp)) { add_next_index_string(return_value, ftp->inbuf, 1); if (isdigit(ftp->inbuf[0]) && isdigit(ftp->inbuf[1]) && isdigit(ftp->inbuf[2]) && ftp->inbuf[3] == ' ') { return; } } } /* }}} */ /* {{{ ftp_chdir */ int ftp_chdir(ftpbuf_t *ftp, const char *dir) { if (ftp == NULL) { return 0; } if (ftp->pwd) { efree(ftp->pwd); ftp->pwd = NULL; } if (!ftp_putcmd(ftp, "CWD", dir)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 250) { return 0; } return 1; } /* }}} */ /* {{{ ftp_cdup */ int ftp_cdup(ftpbuf_t *ftp) { if (ftp == NULL) { return 0; } if (ftp->pwd) { efree(ftp->pwd); ftp->pwd = NULL; } if (!ftp_putcmd(ftp, "CDUP", NULL)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 250) { return 0; } return 1; } /* }}} */ /* {{{ ftp_mkdir */ char* ftp_mkdir(ftpbuf_t *ftp, const char *dir) { char *mkd, *end; if (ftp == NULL) { return NULL; } if (!ftp_putcmd(ftp, "MKD", dir)) { return NULL; } if (!ftp_getresp(ftp) || ftp->resp != 257) { return NULL; } /* copy out the dir from response */ if ((mkd = strchr(ftp->inbuf, '"')) == NULL) { mkd = estrdup(dir); return mkd; } if ((end = strrchr(++mkd, '"')) == NULL) { return NULL; } *end = 0; mkd = estrdup(mkd); *end = '"'; return mkd; } /* }}} */ /* {{{ ftp_rmdir */ int ftp_rmdir(ftpbuf_t *ftp, const char *dir) { if (ftp == NULL) { return 0; } if (!ftp_putcmd(ftp, "RMD", dir)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 250) { return 0; } return 1; } /* }}} */ /* {{{ ftp_chmod */ int ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len) { char *buffer; if (ftp == NULL || filename_len <= 0) { return 0; } spprintf(&buffer, 0, "CHMOD %o %s", mode, filename); if (!ftp_putcmd(ftp, "SITE", buffer)) { efree(buffer); return 0; } efree(buffer); if (!ftp_getresp(ftp) || ftp->resp != 200) { return 0; } return 1; } /* }}} */ /* {{{ ftp_alloc */ int ftp_alloc(ftpbuf_t *ftp, const long size, char **response) { char buffer[64]; if (ftp == NULL || size <= 0) { return 0; } snprintf(buffer, sizeof(buffer) - 1, "%ld", size); if (!ftp_putcmd(ftp, "ALLO", buffer)) { return 0; } if (!ftp_getresp(ftp)) { return 0; } if (response) { *response = estrdup(ftp->inbuf); } if (ftp->resp < 200 || ftp->resp >= 300) { return 0; } return 1; } /* }}} */ /* {{{ ftp_nlist */ char** ftp_nlist(ftpbuf_t *ftp, const char *path TSRMLS_DC) { return ftp_genlist(ftp, "NLST", path TSRMLS_CC); } /* }}} */ /* {{{ ftp_list */ char** ftp_list(ftpbuf_t *ftp, const char *path, int recursive TSRMLS_DC) { return ftp_genlist(ftp, ((recursive) ? "LIST -R" : "LIST"), path TSRMLS_CC); } /* }}} */ /* {{{ ftp_type */ int ftp_type(ftpbuf_t *ftp, ftptype_t type) { char typechar[2] = "?"; if (ftp == NULL) { return 0; } if (type == ftp->type) { return 1; } if (type == FTPTYPE_ASCII) { typechar[0] = 'A'; } else if (type == FTPTYPE_IMAGE) { typechar[0] = 'I'; } else { return 0; } if (!ftp_putcmd(ftp, "TYPE", typechar)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 200) { return 0; } ftp->type = type; return 1; } /* }}} */ /* {{{ ftp_pasv */ int ftp_pasv(ftpbuf_t *ftp, int pasv) { char *ptr; union ipbox ipbox; unsigned long b[6]; socklen_t n; struct sockaddr *sa; struct sockaddr_in *sin; if (ftp == NULL) { return 0; } if (pasv && ftp->pasv == 2) { return 1; } ftp->pasv = 0; if (!pasv) { return 1; } n = sizeof(ftp->pasvaddr); memset(&ftp->pasvaddr, 0, n); sa = (struct sockaddr *) &ftp->pasvaddr; if (getpeername(ftp->fd, sa, &n) < 0) { return 0; } #if HAVE_IPV6 if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; char *endptr, delimiter; /* try EPSV first */ if (!ftp_putcmd(ftp, "EPSV", NULL)) { return 0; } if (!ftp_getresp(ftp)) { return 0; } if (ftp->resp == 229) { /* parse out the port */ for (ptr = ftp->inbuf; *ptr && *ptr != '('; ptr++); if (!*ptr) { return 0; } delimiter = *++ptr; for (n = 0; *ptr && n < 3; ptr++) { if (*ptr == delimiter) { n++; } } sin6->sin6_port = htons((unsigned short) strtoul(ptr, &endptr, 10)); if (ptr == endptr || *endptr != delimiter) { return 0; } ftp->pasv = 2; return 1; } } /* fall back to PASV */ #endif if (!ftp_putcmd(ftp, "PASV", NULL)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 227) { return 0; } /* parse out the IP and port */ for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++); n = sscanf(ptr, "%lu,%lu,%lu,%lu,%lu,%lu", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5]); if (n != 6) { return 0; } for (n = 0; n < 6; n++) { ipbox.c[n] = (unsigned char) b[n]; } sin = (struct sockaddr_in *) sa; if (ftp->usepasvaddress) { sin->sin_addr = ipbox.ia[0]; } sin->sin_port = ipbox.s[2]; ftp->pasv = 2; return 1; } /* }}} */ /* {{{ ftp_get */ int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC) { databuf_t *data = NULL; size_t rcvd; char arg[11]; if (ftp == NULL) { return 0; } if (!ftp_type(ftp, type)) { goto bail; } if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) { goto bail; } ftp->data = data; if (resumepos > 0) { snprintf(arg, sizeof(arg), "%ld", resumepos); if (!ftp_putcmd(ftp, "REST", arg)) { goto bail; } if (!ftp_getresp(ftp) || (ftp->resp != 350)) { goto bail; } } if (!ftp_putcmd(ftp, "RETR", path)) { goto bail; } if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) { goto bail; } if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) { goto bail; } while ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) { if (rcvd == -1) { goto bail; } if (type == FTPTYPE_ASCII) { #ifndef PHP_WIN32 char *s; #endif char *ptr = data->buf; char *e = ptr + rcvd; /* logic depends on the OS EOL * Win32 -> \r\n * Everything Else \n */ #ifdef PHP_WIN32 php_stream_write(outstream, ptr, (e - ptr)); ptr = e; #else while (e > ptr && (s = memchr(ptr, '\r', (e - ptr)))) { php_stream_write(outstream, ptr, (s - ptr)); if (*(s + 1) == '\n') { s++; php_stream_putc(outstream, '\n'); } ptr = s + 1; } #endif if (ptr < e) { php_stream_write(outstream, ptr, (e - ptr)); } } else if (rcvd != php_stream_write(outstream, data->buf, rcvd)) { goto bail; } } ftp->data = data = data_close(ftp, data); if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) { goto bail; } return 1; bail: ftp->data = data_close(ftp, data); return 0; } /* }}} */ /* {{{ ftp_put */ int ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC) { databuf_t *data = NULL; long size; char *ptr; int ch; char arg[11]; if (ftp == NULL) { return 0; } if (!ftp_type(ftp, type)) { goto bail; } if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) { goto bail; } ftp->data = data; if (startpos > 0) { snprintf(arg, sizeof(arg), "%ld", startpos); if (!ftp_putcmd(ftp, "REST", arg)) { goto bail; } if (!ftp_getresp(ftp) || (ftp->resp != 350)) { goto bail; } } if (!ftp_putcmd(ftp, "STOR", path)) { goto bail; } if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) { goto bail; } if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) { goto bail; } size = 0; ptr = data->buf; while (!php_stream_eof(instream) && (ch = php_stream_getc(instream))!=EOF) { /* flush if necessary */ if (FTP_BUFSIZE - size < 2) { if (my_send(ftp, data->fd, data->buf, size) != size) { goto bail; } ptr = data->buf; size = 0; } if (ch == '\n' && type == FTPTYPE_ASCII) { *ptr++ = '\r'; size++; } *ptr++ = ch; size++; } if (size && my_send(ftp, data->fd, data->buf, size) != size) { goto bail; } ftp->data = data = data_close(ftp, data); if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250 && ftp->resp != 200)) { goto bail; } return 1; bail: ftp->data = data_close(ftp, data); return 0; } /* }}} */ /* {{{ ftp_size */ long ftp_size(ftpbuf_t *ftp, const char *path) { if (ftp == NULL) { return -1; } if (!ftp_type(ftp, FTPTYPE_IMAGE)) { return -1; } if (!ftp_putcmd(ftp, "SIZE", path)) { return -1; } if (!ftp_getresp(ftp) || ftp->resp != 213) { return -1; } return atol(ftp->inbuf); } /* }}} */ /* {{{ ftp_mdtm */ time_t ftp_mdtm(ftpbuf_t *ftp, const char *path) { time_t stamp; struct tm *gmt, tmbuf; struct tm tm; char *ptr; int n; if (ftp == NULL) { return -1; } if (!ftp_putcmd(ftp, "MDTM", path)) { return -1; } if (!ftp_getresp(ftp) || ftp->resp != 213) { return -1; } /* parse out the timestamp */ for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++); n = sscanf(ptr, "%4u%2u%2u%2u%2u%2u", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); if (n != 6) { return -1; } tm.tm_year -= 1900; tm.tm_mon--; tm.tm_isdst = -1; /* figure out the GMT offset */ stamp = time(NULL); gmt = php_gmtime_r(&stamp, &tmbuf); if (!gmt) { return -1; } gmt->tm_isdst = -1; /* apply the GMT offset */ tm.tm_sec += stamp - mktime(gmt); tm.tm_isdst = gmt->tm_isdst; stamp = mktime(&tm); return stamp; } /* }}} */ /* {{{ ftp_delete */ int ftp_delete(ftpbuf_t *ftp, const char *path) { if (ftp == NULL) { return 0; } if (!ftp_putcmd(ftp, "DELE", path)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 250) { return 0; } return 1; } /* }}} */ /* {{{ ftp_rename */ int ftp_rename(ftpbuf_t *ftp, const char *src, const char *dest) { if (ftp == NULL) { return 0; } if (!ftp_putcmd(ftp, "RNFR", src)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 350) { return 0; } if (!ftp_putcmd(ftp, "RNTO", dest)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp != 250) { return 0; } return 1; } /* }}} */ /* {{{ ftp_site */ int ftp_site(ftpbuf_t *ftp, const char *cmd) { if (ftp == NULL) { return 0; } if (!ftp_putcmd(ftp, "SITE", cmd)) { return 0; } if (!ftp_getresp(ftp) || ftp->resp < 200 || ftp->resp >= 300) { return 0; } return 1; } /* }}} */ /* static functions */ /* {{{ ftp_putcmd */ int ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const char *args) { int size; char *data; if (strpbrk(cmd, "\r\n")) { return 0; } /* build the output buffer */ if (args && args[0]) { /* "cmd args\r\n\0" */ if (strlen(cmd) + strlen(args) + 4 > FTP_BUFSIZE) { return 0; } if (strpbrk(args, "\r\n")) { return 0; } size = slprintf(ftp->outbuf, sizeof(ftp->outbuf), "%s %s\r\n", cmd, args); } else { /* "cmd\r\n\0" */ if (strlen(cmd) + 3 > FTP_BUFSIZE) { return 0; } size = slprintf(ftp->outbuf, sizeof(ftp->outbuf), "%s\r\n", cmd); } data = ftp->outbuf; /* Clear the extra-lines buffer */ ftp->extra = NULL; if (my_send(ftp, ftp->fd, data, size) != size) { return 0; } return 1; } /* }}} */ /* {{{ ftp_readline */ int ftp_readline(ftpbuf_t *ftp) { long size, rcvd; char *data, *eol; /* shift the extra to the front */ size = FTP_BUFSIZE; rcvd = 0; if (ftp->extra) { memmove(ftp->inbuf, ftp->extra, ftp->extralen); rcvd = ftp->extralen; } data = ftp->inbuf; do { size -= rcvd; for (eol = data; rcvd; rcvd--, eol++) { if (*eol == '\r') { *eol = 0; ftp->extra = eol + 1; if (rcvd > 1 && *(eol + 1) == '\n') { ftp->extra++; rcvd--; } if ((ftp->extralen = --rcvd) == 0) { ftp->extra = NULL; } return 1; } else if (*eol == '\n') { *eol = 0; ftp->extra = eol + 1; if ((ftp->extralen = --rcvd) == 0) { ftp->extra = NULL; } return 1; } } data = eol; if ((rcvd = my_recv(ftp, ftp->fd, data, size)) < 1) { return 0; } } while (size); return 0; } /* }}} */ /* {{{ ftp_getresp */ int ftp_getresp(ftpbuf_t *ftp) { if (ftp == NULL) { return 0; } ftp->resp = 0; while (1) { if (!ftp_readline(ftp)) { return 0; } /* Break out when the end-tag is found */ if (isdigit(ftp->inbuf[0]) && isdigit(ftp->inbuf[1]) && isdigit(ftp->inbuf[2]) && ftp->inbuf[3] == ' ') { break; } } /* translate the tag */ if (!isdigit(ftp->inbuf[0]) || !isdigit(ftp->inbuf[1]) || !isdigit(ftp->inbuf[2])) { return 0; } ftp->resp = 100 * (ftp->inbuf[0] - '0') + 10 * (ftp->inbuf[1] - '0') + (ftp->inbuf[2] - '0'); memmove(ftp->inbuf, ftp->inbuf + 4, FTP_BUFSIZE - 4); if (ftp->extra) { ftp->extra -= 4; } return 1; } /* }}} */ /* {{{ my_send */ int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { long size, sent; int n; size = len; while (size) { n = php_pollfd_for_ms(s, POLLOUT, ftp->timeout_sec * 1000); if (n < 1) { #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK)) if (n == 0) { errno = ETIMEDOUT; } #endif return -1; } #if HAVE_OPENSSL_EXT if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) { sent = SSL_write(ftp->ssl_handle, buf, size); } else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) { sent = SSL_write(ftp->data->ssl_handle, buf, size); } else { #endif sent = send(s, buf, size, 0); #if HAVE_OPENSSL_EXT } #endif if (sent == -1) { return -1; } buf = (char*) buf + sent; size -= sent; } return len; } /* }}} */ /* {{{ my_recv */ int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { int n, nr_bytes; n = php_pollfd_for_ms(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000); if (n < 1) { #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK)) if (n == 0) { errno = ETIMEDOUT; } #endif return -1; } #if HAVE_OPENSSL_EXT if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) { nr_bytes = SSL_read(ftp->ssl_handle, buf, len); } else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) { nr_bytes = SSL_read(ftp->data->ssl_handle, buf, len); } else { #endif nr_bytes = recv(s, buf, len, 0); #if HAVE_OPENSSL_EXT } #endif return (nr_bytes); } /* }}} */ /* {{{ data_available */ int data_available(ftpbuf_t *ftp, php_socket_t s) { int n; n = php_pollfd_for_ms(s, PHP_POLLREADABLE, 1000); if (n < 1) { #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK)) if (n == 0) { errno = ETIMEDOUT; } #endif return 0; } return 1; } /* }}} */ /* {{{ data_writeable */ int data_writeable(ftpbuf_t *ftp, php_socket_t s) { int n; n = php_pollfd_for_ms(s, POLLOUT, 1000); if (n < 1) { #ifndef PHP_WIN32 if (n == 0) { errno = ETIMEDOUT; } #endif return 0; } return 1; } /* }}} */ /* {{{ my_accept */ int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen) { int n; n = php_pollfd_for_ms(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000); if (n < 1) { #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK)) if (n == 0) { errno = ETIMEDOUT; } #endif return -1; } return accept(s, addr, addrlen); } /* }}} */ /* {{{ ftp_getdata */ databuf_t* ftp_getdata(ftpbuf_t *ftp TSRMLS_DC) { int fd = -1; databuf_t *data; php_sockaddr_storage addr; struct sockaddr *sa; socklen_t size; union ipbox ipbox; char arg[sizeof("255, 255, 255, 255, 255, 255")]; struct timeval tv; /* ask for a passive connection if we need one */ if (ftp->pasv && !ftp_pasv(ftp, 1)) { return NULL; } /* alloc the data structure */ data = ecalloc(1, sizeof(*data)); data->listener = -1; data->fd = -1; data->type = ftp->type; sa = (struct sockaddr *) &ftp->localaddr; /* bind/listen */ if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == SOCK_ERR) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "socket() failed: %s (%d)", strerror(errno), errno); goto bail; } /* passive connection handler */ if (ftp->pasv) { /* clear the ready status */ ftp->pasv = 1; /* connect */ /* Win 95/98 seems not to like size > sizeof(sockaddr_in) */ size = php_sockaddr_size(&ftp->pasvaddr); tv.tv_sec = ftp->timeout_sec; tv.tv_usec = 0; if (php_connect_nonb(fd, (struct sockaddr*) &ftp->pasvaddr, size, &tv) == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_connect_nonb() failed: %s (%d)", strerror(errno), errno); goto bail; } data->fd = fd; ftp->data = data; return data; } /* active (normal) connection */ /* bind to a local address */ php_any_addr(sa->sa_family, &addr, 0); size = php_sockaddr_size(&addr); if (bind(fd, (struct sockaddr*) &addr, size) != 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "bind() failed: %s (%d)", strerror(errno), errno); goto bail; } if (getsockname(fd, (struct sockaddr*) &addr, &size) != 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "getsockname() failed: %s (%d)", strerror(errno), errno); goto bail; } if (listen(fd, 5) != 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "listen() failed: %s (%d)", strerror(errno), errno); goto bail; } data->listener = fd; #if HAVE_IPV6 && HAVE_INET_NTOP if (sa->sa_family == AF_INET6) { /* need to use EPRT */ char eprtarg[INET6_ADDRSTRLEN + sizeof("|x||xxxxx|")]; char out[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &((struct sockaddr_in6*) sa)->sin6_addr, out, sizeof(out)); snprintf(eprtarg, sizeof(eprtarg), "|2|%s|%hu|", out, ntohs(((struct sockaddr_in6 *) &addr)->sin6_port)); if (!ftp_putcmd(ftp, "EPRT", eprtarg)) { goto bail; } if (!ftp_getresp(ftp) || ftp->resp != 200) { goto bail; } ftp->data = data; return data; } #endif /* send the PORT */ ipbox.ia[0] = ((struct sockaddr_in*) sa)->sin_addr; ipbox.s[2] = ((struct sockaddr_in*) &addr)->sin_port; snprintf(arg, sizeof(arg), "%u,%u,%u,%u,%u,%u", ipbox.c[0], ipbox.c[1], ipbox.c[2], ipbox.c[3], ipbox.c[4], ipbox.c[5]); if (!ftp_putcmd(ftp, "PORT", arg)) { goto bail; } if (!ftp_getresp(ftp) || ftp->resp != 200) { goto bail; } ftp->data = data; return data; bail: if (fd != -1) { closesocket(fd); } efree(data); return NULL; } /* }}} */ /* {{{ data_accept */ databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp TSRMLS_DC) { php_sockaddr_storage addr; socklen_t size; #if HAVE_OPENSSL_EXT SSL_CTX *ctx; SSL_SESSION *session; int result; #endif if (data->fd != -1) { goto data_accepted; } size = sizeof(addr); data->fd = my_accept(ftp, data->listener, (struct sockaddr*) &addr, &size); closesocket(data->listener); data->listener = -1; if (data->fd == -1) { efree(data); return NULL; } data_accepted: #if HAVE_OPENSSL_EXT /* now enable ssl if we need to */ if (ftp->use_ssl && ftp->use_ssl_for_data) { ctx = SSL_get_SSL_CTX(ftp->ssl_handle); if (ctx == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to retreive the existing SSL context"); return 0; } data->ssl_handle = SSL_new(ctx); if (data->ssl_handle == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to create the SSL handle"); return 0; } SSL_set_fd(data->ssl_handle, data->fd); if (ftp->old_ssl) { SSL_copy_session_id(data->ssl_handle, ftp->ssl_handle); } /* get the session from the control connection so we can re-use it */ session = SSL_get_session(ftp->ssl_handle); if (session == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to retreive the existing SSL session"); SSL_free(data->ssl_handle); return 0; } /* and set it on the data connection */ result = SSL_set_session(data->ssl_handle, session); if (result == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to set the existing SSL session"); SSL_free(data->ssl_handle); return 0; } if (SSL_connect(data->ssl_handle) <= 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: SSL/TLS handshake failed"); SSL_shutdown(data->ssl_handle); SSL_free(data->ssl_handle); return 0; } data->ssl_active = 1; } #endif return data; } /* }}} */ /* {{{ data_close */ databuf_t* data_close(ftpbuf_t *ftp, databuf_t *data) { #if HAVE_OPENSSL_EXT SSL_CTX *ctx; #endif if (data == NULL) { return NULL; } if (data->listener != -1) { #if HAVE_OPENSSL_EXT if (data->ssl_active) { /* don't free the data context, it's the same as the control */ SSL_shutdown(data->ssl_handle); SSL_free(data->ssl_handle); data->ssl_active = 0; } #endif closesocket(data->listener); } if (data->fd != -1) { #if HAVE_OPENSSL_EXT if (data->ssl_active) { /* don't free the data context, it's the same as the control */ SSL_shutdown(data->ssl_handle); SSL_free(data->ssl_handle); data->ssl_active = 0; } #endif closesocket(data->fd); } if (ftp) { ftp->data = NULL; } efree(data); return NULL; } /* }}} */ /* {{{ ftp_genlist */ char** ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC) { php_stream *tmpstream = NULL; databuf_t *data = NULL; char *ptr; int ch, lastch; size_t size, rcvd; size_t lines; char **ret = NULL; char **entry; char *text; if ((tmpstream = php_stream_fopen_tmpfile()) == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create temporary file. Check permissions in temporary files directory."); return NULL; } if (!ftp_type(ftp, FTPTYPE_ASCII)) { goto bail; } if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) { goto bail; } ftp->data = data; if (!ftp_putcmd(ftp, cmd, path)) { goto bail; } if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125 && ftp->resp != 226)) { goto bail; } /* some servers don't open a ftp-data connection if the directory is empty */ if (ftp->resp == 226) { ftp->data = data_close(ftp, data); php_stream_close(tmpstream); return ecalloc(1, sizeof(char*)); } /* pull data buffer into tmpfile */ if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) { goto bail; } size = 0; lines = 0; lastch = 0; while ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) { if (rcvd == -1 || rcvd > ((size_t)(-1))-size) { goto bail; } php_stream_write(tmpstream, data->buf, rcvd); size += rcvd; for (ptr = data->buf; rcvd; rcvd--, ptr++) { if (*ptr == '\n' && lastch == '\r') { lines++; } lastch = *ptr; } } ftp->data = data_close(ftp, data); php_stream_rewind(tmpstream); ret = safe_emalloc((lines + 1), sizeof(char*), size); entry = ret; text = (char*) (ret + lines + 1); *entry = text; lastch = 0; while ((ch = php_stream_getc(tmpstream)) != EOF) { if (ch == '\n' && lastch == '\r') { *(text - 1) = 0; *++entry = text; } else { *text++ = ch; } lastch = ch; } *entry = NULL; php_stream_close(tmpstream); if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) { efree(ret); return NULL; } return ret; bail: ftp->data = data_close(ftp, data); php_stream_close(tmpstream); if (ret) efree(ret); return NULL; } /* }}} */ /* {{{ ftp_nb_get */ int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC) { databuf_t *data = NULL; char arg[11]; if (ftp == NULL) { return PHP_FTP_FAILED; } if (!ftp_type(ftp, type)) { goto bail; } if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) { goto bail; } if (resumepos>0) { snprintf(arg, sizeof(arg), "%ld", resumepos); if (!ftp_putcmd(ftp, "REST", arg)) { goto bail; } if (!ftp_getresp(ftp) || (ftp->resp != 350)) { goto bail; } } if (!ftp_putcmd(ftp, "RETR", path)) { goto bail; } if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) { goto bail; } if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) { goto bail; } ftp->data = data; ftp->stream = outstream; ftp->lastch = 0; ftp->nb = 1; return (ftp_nb_continue_read(ftp TSRMLS_CC)); bail: ftp->data = data_close(ftp, data); return PHP_FTP_FAILED; } /* }}} */ /* {{{ ftp_nb_continue_read */ int ftp_nb_continue_read(ftpbuf_t *ftp TSRMLS_DC) { databuf_t *data = NULL; char *ptr; int lastch; size_t rcvd; ftptype_t type; data = ftp->data; /* check if there is already more data */ if (!data_available(ftp, data->fd)) { return PHP_FTP_MOREDATA; } type = ftp->type; lastch = ftp->lastch; if ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) { if (rcvd == -1) { goto bail; } if (type == FTPTYPE_ASCII) { for (ptr = data->buf; rcvd; rcvd--, ptr++) { if (lastch == '\r' && *ptr != '\n') { php_stream_putc(ftp->stream, '\r'); } if (*ptr != '\r') { php_stream_putc(ftp->stream, *ptr); } lastch = *ptr; } } else if (rcvd != php_stream_write(ftp->stream, data->buf, rcvd)) { goto bail; } ftp->lastch = lastch; return PHP_FTP_MOREDATA; } if (type == FTPTYPE_ASCII && lastch == '\r') { php_stream_putc(ftp->stream, '\r'); } ftp->data = data = data_close(ftp, data); if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) { goto bail; } ftp->nb = 0; return PHP_FTP_FINISHED; bail: ftp->nb = 0; ftp->data = data_close(ftp, data); return PHP_FTP_FAILED; } /* }}} */ /* {{{ ftp_nb_put */ int ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC) { databuf_t *data = NULL; char arg[11]; if (ftp == NULL) { return 0; } if (!ftp_type(ftp, type)) { goto bail; } if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) { goto bail; } if (startpos > 0) { snprintf(arg, sizeof(arg), "%ld", startpos); if (!ftp_putcmd(ftp, "REST", arg)) { goto bail; } if (!ftp_getresp(ftp) || (ftp->resp != 350)) { goto bail; } } if (!ftp_putcmd(ftp, "STOR", path)) { goto bail; } if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) { goto bail; } if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) { goto bail; } ftp->data = data; ftp->stream = instream; ftp->lastch = 0; ftp->nb = 1; return (ftp_nb_continue_write(ftp TSRMLS_CC)); bail: ftp->data = data_close(ftp, data); return PHP_FTP_FAILED; } /* }}} */ /* {{{ ftp_nb_continue_write */ int ftp_nb_continue_write(ftpbuf_t *ftp TSRMLS_DC) { long size; char *ptr; int ch; /* check if we can write more data */ if (!data_writeable(ftp, ftp->data->fd)) { return PHP_FTP_MOREDATA; } size = 0; ptr = ftp->data->buf; while (!php_stream_eof(ftp->stream) && (ch = php_stream_getc(ftp->stream)) != EOF) { if (ch == '\n' && ftp->type == FTPTYPE_ASCII) { *ptr++ = '\r'; size++; } *ptr++ = ch; size++; /* flush if necessary */ if (FTP_BUFSIZE - size < 2) { if (my_send(ftp, ftp->data->fd, ftp->data->buf, size) != size) { goto bail; } return PHP_FTP_MOREDATA; } } if (size && my_send(ftp, ftp->data->fd, ftp->data->buf, size) != size) { goto bail; } ftp->data = data_close(ftp, ftp->data); if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) { goto bail; } ftp->nb = 0; return PHP_FTP_FINISHED; bail: ftp->data = data_close(ftp, ftp->data); ftp->nb = 0; return PHP_FTP_FAILED; } /* }}} */ #endif /* HAVE_FTP */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */ ftp.h000064400000017444147577111130005527 0ustar00/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrew Skalski | | Stefan Esser (resume functions) | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifndef FTP_H #define FTP_H #include "php_network.h" #include #ifdef HAVE_NETINET_IN_H #include #endif #define FTP_DEFAULT_TIMEOUT 90 #define FTP_DEFAULT_AUTOSEEK 1 #define FTP_DEFAULT_USEPASVADDRESS 1 #define PHP_FTP_FAILED 0 #define PHP_FTP_FINISHED 1 #define PHP_FTP_MOREDATA 2 /* XXX this should be configurable at runtime XXX */ #define FTP_BUFSIZE 4096 typedef enum ftptype { FTPTYPE_ASCII=1, FTPTYPE_IMAGE } ftptype_t; typedef struct databuf { int listener; /* listener socket */ php_socket_t fd; /* data connection */ ftptype_t type; /* transfer type */ char buf[FTP_BUFSIZE]; /* data buffer */ #if HAVE_OPENSSL_EXT SSL *ssl_handle; /* ssl handle */ int ssl_active; /* flag if ssl is active or not */ #endif } databuf_t; typedef struct ftpbuf { php_socket_t fd; /* control connection */ php_sockaddr_storage localaddr; /* local address */ int resp; /* last response code */ char inbuf[FTP_BUFSIZE]; /* last response text */ char *extra; /* extra characters */ int extralen; /* number of extra chars */ char outbuf[FTP_BUFSIZE]; /* command output buffer */ char *pwd; /* cached pwd */ char *syst; /* cached system type */ ftptype_t type; /* current transfer type */ int pasv; /* 0=off; 1=pasv; 2=ready */ php_sockaddr_storage pasvaddr; /* passive mode address */ long timeout_sec; /* User configurable timeout (seconds) */ int autoseek; /* User configurable autoseek flag */ int usepasvaddress; /* Use the address returned by the pasv command */ int nb; /* "nonblocking" transfer in progress */ databuf_t *data; /* Data connection for "nonblocking" transfers */ php_stream *stream; /* output stream for "nonblocking" transfers */ int lastch; /* last char of previous call */ int direction; /* recv = 0 / send = 1 */ int closestream;/* close or not close stream */ #if HAVE_OPENSSL_EXT int use_ssl; /* enable(1) or disable(0) ssl */ int use_ssl_for_data; /* en/disable ssl for the dataconnection */ int old_ssl; /* old mode = forced data encryption */ SSL *ssl_handle; /* handle for control connection */ int ssl_active; /* ssl active on control conn */ #endif } ftpbuf_t; /* open a FTP connection, returns ftpbuf (NULL on error) * port is the ftp port in network byte order, or 0 for the default */ ftpbuf_t* ftp_open(const char *host, short port, long timeout_sec TSRMLS_DC); /* quits from the ftp session (it still needs to be closed) * return true on success, false on error */ int ftp_quit(ftpbuf_t *ftp); /* frees up any cached data held in the ftp buffer */ void ftp_gc(ftpbuf_t *ftp); /* close the FTP connection and return NULL */ ftpbuf_t* ftp_close(ftpbuf_t *ftp); /* logs into the FTP server, returns true on success, false on error */ int ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC); /* reinitializes the connection, returns true on success, false on error */ int ftp_reinit(ftpbuf_t *ftp); /* returns the remote system type (NULL on error) */ const char* ftp_syst(ftpbuf_t *ftp); /* returns the present working directory (NULL on error) */ const char* ftp_pwd(ftpbuf_t *ftp); /* exec a command [special features], return true on success, false on error */ int ftp_exec(ftpbuf_t *ftp, const char *cmd); /* send a raw ftp command, return response as a hashtable, NULL on error */ void ftp_raw(ftpbuf_t *ftp, const char *cmd, zval *return_value); /* changes directories, return true on success, false on error */ int ftp_chdir(ftpbuf_t *ftp, const char *dir); /* changes to parent directory, return true on success, false on error */ int ftp_cdup(ftpbuf_t *ftp); /* creates a directory, return the directory name on success, NULL on error. * the return value must be freed */ char* ftp_mkdir(ftpbuf_t *ftp, const char *dir); /* removes a directory, return true on success, false on error */ int ftp_rmdir(ftpbuf_t *ftp, const char *dir); /* Set permissions on a file */ int ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len); /* Allocate space on remote server with ALLO command * Many servers will respond with 202 Allocation not necessary, * however some servers will not accept STOR or APPE until ALLO is confirmed. * If response is passed, it is estrdup()ed from ftp->inbuf and must be freed * or assigned to a zval returned to the user */ int ftp_alloc(ftpbuf_t *ftp, const long size, char **response); /* returns a NULL-terminated array of filenames in the given path * or NULL on error. the return array must be freed (but don't * free the array elements) */ char** ftp_nlist(ftpbuf_t *ftp, const char *path TSRMLS_DC); /* returns a NULL-terminated array of lines returned by the ftp * LIST command for the given path or NULL on error. the return * array must be freed (but don't * free the array elements) */ char** ftp_list(ftpbuf_t *ftp, const char *path, int recursive TSRMLS_DC); /* switches passive mode on or off * returns true on success, false on error */ int ftp_pasv(ftpbuf_t *ftp, int pasv); /* retrieves a file and saves its contents to outfp * returns true on success, false on error */ int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC); /* stores the data from a file, socket, or process as a file on the remote server * returns true on success, false on error */ int ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC); /* returns the size of the given file, or -1 on error */ long ftp_size(ftpbuf_t *ftp, const char *path); /* returns the last modified time of the given file, or -1 on error */ time_t ftp_mdtm(ftpbuf_t *ftp, const char *path); /* renames a file on the server */ int ftp_rename(ftpbuf_t *ftp, const char *src, const char *dest); /* deletes the file from the server */ int ftp_delete(ftpbuf_t *ftp, const char *path); /* sends a SITE command to the server */ int ftp_site(ftpbuf_t *ftp, const char *cmd); /* retrieves part of a file and saves its contents to outfp * returns true on success, false on error */ int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC); /* stores the data from a file, socket, or process as a file on the remote server * returns true on success, false on error */ int ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC); /* continues a previous nb_(f)get command */ int ftp_nb_continue_read(ftpbuf_t *ftp TSRMLS_DC); /* continues a previous nb_(f)put command */ int ftp_nb_continue_write(ftpbuf_t *ftp TSRMLS_DC); #endif