1*0Sstevel@tonic-gate# Net::FTP.pm 2*0Sstevel@tonic-gate# 3*0Sstevel@tonic-gate# Copyright (c) 1995-8 Graham Barr <gbarr@pobox.com>. All rights reserved. 4*0Sstevel@tonic-gate# This program is free software; you can redistribute it and/or 5*0Sstevel@tonic-gate# modify it under the same terms as Perl itself. 6*0Sstevel@tonic-gate# 7*0Sstevel@tonic-gate# Documentation (at end) improved 1996 by Nathan Torkington <gnat@frii.com>. 8*0Sstevel@tonic-gate 9*0Sstevel@tonic-gatepackage Net::FTP; 10*0Sstevel@tonic-gate 11*0Sstevel@tonic-gaterequire 5.001; 12*0Sstevel@tonic-gate 13*0Sstevel@tonic-gateuse strict; 14*0Sstevel@tonic-gateuse vars qw(@ISA $VERSION); 15*0Sstevel@tonic-gateuse Carp; 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gateuse Socket 1.3; 18*0Sstevel@tonic-gateuse IO::Socket; 19*0Sstevel@tonic-gateuse Time::Local; 20*0Sstevel@tonic-gateuse Net::Cmd; 21*0Sstevel@tonic-gateuse Net::Config; 22*0Sstevel@tonic-gateuse Fcntl qw(O_WRONLY O_RDONLY O_APPEND O_CREAT O_TRUNC); 23*0Sstevel@tonic-gate# use AutoLoader qw(AUTOLOAD); 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate$VERSION = "2.72"; # $Id: //depot/libnet/Net/FTP.pm#80 $ 26*0Sstevel@tonic-gate@ISA = qw(Exporter Net::Cmd IO::Socket::INET); 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate# Someday I will "use constant", when I am not bothered to much about 29*0Sstevel@tonic-gate# compatability with older releases of perl 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gateuse vars qw($TELNET_IAC $TELNET_IP $TELNET_DM); 32*0Sstevel@tonic-gate($TELNET_IAC,$TELNET_IP,$TELNET_DM) = (255,244,242); 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate# Name is too long for AutoLoad, it clashes with pasv_xfer 35*0Sstevel@tonic-gatesub pasv_xfer_unique { 36*0Sstevel@tonic-gate my($sftp,$sfile,$dftp,$dfile) = @_; 37*0Sstevel@tonic-gate $sftp->pasv_xfer($sfile,$dftp,$dfile,1); 38*0Sstevel@tonic-gate} 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gateBEGIN { 41*0Sstevel@tonic-gate # make a constant so code is fast'ish 42*0Sstevel@tonic-gate my $is_os390 = $^O eq 'os390'; 43*0Sstevel@tonic-gate *trEBCDIC = sub () { $is_os390 } 44*0Sstevel@tonic-gate} 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate1; 47*0Sstevel@tonic-gate# Having problems with AutoLoader 48*0Sstevel@tonic-gate#__END__ 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gatesub new 51*0Sstevel@tonic-gate{ 52*0Sstevel@tonic-gate my $pkg = shift; 53*0Sstevel@tonic-gate my $peer = shift; 54*0Sstevel@tonic-gate my %arg = @_; 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate my $host = $peer; 57*0Sstevel@tonic-gate my $fire = undef; 58*0Sstevel@tonic-gate my $fire_type = undef; 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate if(exists($arg{Firewall}) || Net::Config->requires_firewall($peer)) 61*0Sstevel@tonic-gate { 62*0Sstevel@tonic-gate $fire = $arg{Firewall} 63*0Sstevel@tonic-gate || $ENV{FTP_FIREWALL} 64*0Sstevel@tonic-gate || $NetConfig{ftp_firewall} 65*0Sstevel@tonic-gate || undef; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate if(defined $fire) 68*0Sstevel@tonic-gate { 69*0Sstevel@tonic-gate $peer = $fire; 70*0Sstevel@tonic-gate delete $arg{Port}; 71*0Sstevel@tonic-gate $fire_type = $arg{FirewallType} 72*0Sstevel@tonic-gate || $ENV{FTP_FIREWALL_TYPE} 73*0Sstevel@tonic-gate || $NetConfig{firewall_type} 74*0Sstevel@tonic-gate || undef; 75*0Sstevel@tonic-gate } 76*0Sstevel@tonic-gate } 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate my $ftp = $pkg->SUPER::new(PeerAddr => $peer, 79*0Sstevel@tonic-gate PeerPort => $arg{Port} || 'ftp(21)', 80*0Sstevel@tonic-gate LocalAddr => $arg{'LocalAddr'}, 81*0Sstevel@tonic-gate Proto => 'tcp', 82*0Sstevel@tonic-gate Timeout => defined $arg{Timeout} 83*0Sstevel@tonic-gate ? $arg{Timeout} 84*0Sstevel@tonic-gate : 120 85*0Sstevel@tonic-gate ) or return undef; 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_host'} = $host; # Remote hostname 88*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_type'} = 'A'; # ASCII/binary/etc mode 89*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_blksize'} = abs($arg{'BlockSize'} || 10240); 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_localaddr'} = $arg{'LocalAddr'}; 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_firewall'} = $fire 94*0Sstevel@tonic-gate if(defined $fire); 95*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_firewall_type'} = $fire_type 96*0Sstevel@tonic-gate if(defined $fire_type); 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_passive'} = int 99*0Sstevel@tonic-gate exists $arg{Passive} 100*0Sstevel@tonic-gate ? $arg{Passive} 101*0Sstevel@tonic-gate : exists $ENV{FTP_PASSIVE} 102*0Sstevel@tonic-gate ? $ENV{FTP_PASSIVE} 103*0Sstevel@tonic-gate : defined $fire 104*0Sstevel@tonic-gate ? $NetConfig{ftp_ext_passive} 105*0Sstevel@tonic-gate : $NetConfig{ftp_int_passive}; # Whew! :-) 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate $ftp->hash(exists $arg{Hash} ? $arg{Hash} : 0, 1024); 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate $ftp->autoflush(1); 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate $ftp->debug(exists $arg{Debug} ? $arg{Debug} : undef); 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate unless ($ftp->response() == CMD_OK) 114*0Sstevel@tonic-gate { 115*0Sstevel@tonic-gate $ftp->close(); 116*0Sstevel@tonic-gate $@ = $ftp->message; 117*0Sstevel@tonic-gate undef $ftp; 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate $ftp; 121*0Sstevel@tonic-gate} 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate## 124*0Sstevel@tonic-gate## User interface methods 125*0Sstevel@tonic-gate## 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gatesub hash { 128*0Sstevel@tonic-gate my $ftp = shift; # self 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate my($h,$b) = @_; 131*0Sstevel@tonic-gate unless($h) { 132*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_hash'}; 133*0Sstevel@tonic-gate return [\*STDERR,0]; 134*0Sstevel@tonic-gate } 135*0Sstevel@tonic-gate ($h,$b) = (ref($h)? $h : \*STDERR, $b || 1024); 136*0Sstevel@tonic-gate select((select($h), $|=1)[0]); 137*0Sstevel@tonic-gate $b = 512 if $b < 512; 138*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_hash'} = [$h, $b]; 139*0Sstevel@tonic-gate} 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gatesub quit 142*0Sstevel@tonic-gate{ 143*0Sstevel@tonic-gate my $ftp = shift; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate $ftp->_QUIT; 146*0Sstevel@tonic-gate $ftp->close; 147*0Sstevel@tonic-gate} 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gatesub DESTROY {} 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gatesub ascii { shift->type('A',@_); } 152*0Sstevel@tonic-gatesub binary { shift->type('I',@_); } 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gatesub ebcdic 155*0Sstevel@tonic-gate{ 156*0Sstevel@tonic-gate carp "TYPE E is unsupported, shall default to I"; 157*0Sstevel@tonic-gate shift->type('E',@_); 158*0Sstevel@tonic-gate} 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gatesub byte 161*0Sstevel@tonic-gate{ 162*0Sstevel@tonic-gate carp "TYPE L is unsupported, shall default to I"; 163*0Sstevel@tonic-gate shift->type('L',@_); 164*0Sstevel@tonic-gate} 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate# Allow the user to send a command directly, BE CAREFUL !! 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gatesub quot 169*0Sstevel@tonic-gate{ 170*0Sstevel@tonic-gate my $ftp = shift; 171*0Sstevel@tonic-gate my $cmd = shift; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate $ftp->command( uc $cmd, @_); 174*0Sstevel@tonic-gate $ftp->response(); 175*0Sstevel@tonic-gate} 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gatesub site 178*0Sstevel@tonic-gate{ 179*0Sstevel@tonic-gate my $ftp = shift; 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate $ftp->command("SITE", @_); 182*0Sstevel@tonic-gate $ftp->response(); 183*0Sstevel@tonic-gate} 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gatesub mdtm 186*0Sstevel@tonic-gate{ 187*0Sstevel@tonic-gate my $ftp = shift; 188*0Sstevel@tonic-gate my $file = shift; 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate # Server Y2K bug workaround 191*0Sstevel@tonic-gate # 192*0Sstevel@tonic-gate # sigh; some idiotic FTP servers use ("19%d",tm.tm_year) instead of 193*0Sstevel@tonic-gate # ("%d",tm.tm_year+1900). This results in an extra digit in the 194*0Sstevel@tonic-gate # string returned. To account for this we allow an optional extra 195*0Sstevel@tonic-gate # digit in the year. Then if the first two digits are 19 we use the 196*0Sstevel@tonic-gate # remainder, otherwise we subtract 1900 from the whole year. 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate $ftp->_MDTM($file) && $ftp->message =~ /((\d\d)(\d\d\d?))(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ 199*0Sstevel@tonic-gate ? timegm($8,$7,$6,$5,$4-1,$2 eq '19' ? $3 : ($1-1900)) 200*0Sstevel@tonic-gate : undef; 201*0Sstevel@tonic-gate} 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gatesub size { 204*0Sstevel@tonic-gate my $ftp = shift; 205*0Sstevel@tonic-gate my $file = shift; 206*0Sstevel@tonic-gate my $io; 207*0Sstevel@tonic-gate if($ftp->supported("SIZE")) { 208*0Sstevel@tonic-gate return $ftp->_SIZE($file) 209*0Sstevel@tonic-gate ? ($ftp->message =~ /(\d+)\s*$/)[0] 210*0Sstevel@tonic-gate : undef; 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate elsif($ftp->supported("STAT")) { 213*0Sstevel@tonic-gate my @msg; 214*0Sstevel@tonic-gate return undef 215*0Sstevel@tonic-gate unless $ftp->_STAT($file) && (@msg = $ftp->message) == 3; 216*0Sstevel@tonic-gate my $line; 217*0Sstevel@tonic-gate foreach $line (@msg) { 218*0Sstevel@tonic-gate return (split(/\s+/,$line))[4] 219*0Sstevel@tonic-gate if $line =~ /^[-rwxSsTt]{10}/ 220*0Sstevel@tonic-gate } 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate else { 223*0Sstevel@tonic-gate my @files = $ftp->dir($file); 224*0Sstevel@tonic-gate if(@files) { 225*0Sstevel@tonic-gate return (split(/\s+/,$1))[4] 226*0Sstevel@tonic-gate if $files[0] =~ /^([-rwxSsTt]{10}.*)$/; 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate } 229*0Sstevel@tonic-gate undef; 230*0Sstevel@tonic-gate} 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gatesub login { 233*0Sstevel@tonic-gate my($ftp,$user,$pass,$acct) = @_; 234*0Sstevel@tonic-gate my($ok,$ruser,$fwtype); 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate unless (defined $user) { 237*0Sstevel@tonic-gate require Net::Netrc; 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_host'}); 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate ($user,$pass,$acct) = $rc->lpa() 242*0Sstevel@tonic-gate if ($rc); 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate $user ||= "anonymous"; 246*0Sstevel@tonic-gate $ruser = $user; 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate $fwtype = ${*$ftp}{'net_ftp_firewall_type'} 249*0Sstevel@tonic-gate || $NetConfig{'ftp_firewall_type'} 250*0Sstevel@tonic-gate || 0; 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate if ($fwtype && defined ${*$ftp}{'net_ftp_firewall'}) { 253*0Sstevel@tonic-gate if ($fwtype == 1 || $fwtype == 7) { 254*0Sstevel@tonic-gate $user .= '@' . ${*$ftp}{'net_ftp_host'}; 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate else { 257*0Sstevel@tonic-gate require Net::Netrc; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}); 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate my($fwuser,$fwpass,$fwacct) = $rc ? $rc->lpa() : (); 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate if ($fwtype == 5) { 264*0Sstevel@tonic-gate $user = join('@',$user,$fwuser,${*$ftp}{'net_ftp_host'}); 265*0Sstevel@tonic-gate $pass = $pass . '@' . $fwpass; 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate else { 268*0Sstevel@tonic-gate if ($fwtype == 2) { 269*0Sstevel@tonic-gate $user .= '@' . ${*$ftp}{'net_ftp_host'}; 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate elsif ($fwtype == 6) { 272*0Sstevel@tonic-gate $fwuser .= '@' . ${*$ftp}{'net_ftp_host'}; 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate $ok = $ftp->_USER($fwuser); 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate return 0 unless $ok == CMD_OK || $ok == CMD_MORE; 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate $ok = $ftp->_PASS($fwpass || ""); 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate return 0 unless $ok == CMD_OK || $ok == CMD_MORE; 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate $ok = $ftp->_ACCT($fwacct) 284*0Sstevel@tonic-gate if defined($fwacct); 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate if ($fwtype == 3) { 287*0Sstevel@tonic-gate $ok = $ftp->command("SITE",${*$ftp}{'net_ftp_host'})->response; 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate elsif ($fwtype == 4) { 290*0Sstevel@tonic-gate $ok = $ftp->command("OPEN",${*$ftp}{'net_ftp_host'})->response; 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate return 0 unless $ok == CMD_OK || $ok == CMD_MORE; 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate $ok = $ftp->_USER($user); 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate # Some dumb firewalls don't prefix the connection messages 301*0Sstevel@tonic-gate $ok = $ftp->response() 302*0Sstevel@tonic-gate if ($ok == CMD_OK && $ftp->code == 220 && $user =~ /\@/); 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate if ($ok == CMD_MORE) { 305*0Sstevel@tonic-gate unless(defined $pass) { 306*0Sstevel@tonic-gate require Net::Netrc; 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_host'}, $ruser); 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate ($ruser,$pass,$acct) = $rc->lpa() 311*0Sstevel@tonic-gate if ($rc); 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate $pass = '-anonymous@' 314*0Sstevel@tonic-gate if (!defined $pass && (!defined($ruser) || $ruser =~ /^anonymous/o)); 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate $ok = $ftp->_PASS($pass || ""); 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate $ok = $ftp->_ACCT($acct) 321*0Sstevel@tonic-gate if (defined($acct) && ($ok == CMD_MORE || $ok == CMD_OK)); 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate if ($fwtype == 7 && $ok == CMD_OK && defined ${*$ftp}{'net_ftp_firewall'}) { 324*0Sstevel@tonic-gate my($f,$auth,$resp) = _auth_id($ftp); 325*0Sstevel@tonic-gate $ftp->authorize($auth,$resp) if defined($resp); 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate $ok == CMD_OK; 329*0Sstevel@tonic-gate} 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gatesub account 332*0Sstevel@tonic-gate{ 333*0Sstevel@tonic-gate @_ == 2 or croak 'usage: $ftp->account( ACCT )'; 334*0Sstevel@tonic-gate my $ftp = shift; 335*0Sstevel@tonic-gate my $acct = shift; 336*0Sstevel@tonic-gate $ftp->_ACCT($acct) == CMD_OK; 337*0Sstevel@tonic-gate} 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gatesub _auth_id { 340*0Sstevel@tonic-gate my($ftp,$auth,$resp) = @_; 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate unless(defined $resp) 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate require Net::Netrc; 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate $auth ||= eval { (getpwuid($>))[0] } || $ENV{NAME}; 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}, $auth) 349*0Sstevel@tonic-gate || Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}); 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate ($auth,$resp) = $rc->lpa() 352*0Sstevel@tonic-gate if ($rc); 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate ($ftp,$auth,$resp); 355*0Sstevel@tonic-gate} 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gatesub authorize 358*0Sstevel@tonic-gate{ 359*0Sstevel@tonic-gate @_ >= 1 || @_ <= 3 or croak 'usage: $ftp->authorize( [AUTH [, RESP]])'; 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate my($ftp,$auth,$resp) = &_auth_id; 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate my $ok = $ftp->_AUTH($auth || ""); 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate $ok = $ftp->_RESP($resp || "") 366*0Sstevel@tonic-gate if ($ok == CMD_MORE); 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate $ok == CMD_OK; 369*0Sstevel@tonic-gate} 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gatesub rename 372*0Sstevel@tonic-gate{ 373*0Sstevel@tonic-gate @_ == 3 or croak 'usage: $ftp->rename(FROM, TO)'; 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate my($ftp,$from,$to) = @_; 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate $ftp->_RNFR($from) 378*0Sstevel@tonic-gate && $ftp->_RNTO($to); 379*0Sstevel@tonic-gate} 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gatesub type 382*0Sstevel@tonic-gate{ 383*0Sstevel@tonic-gate my $ftp = shift; 384*0Sstevel@tonic-gate my $type = shift; 385*0Sstevel@tonic-gate my $oldval = ${*$ftp}{'net_ftp_type'}; 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate return $oldval 388*0Sstevel@tonic-gate unless (defined $type); 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate return undef 391*0Sstevel@tonic-gate unless ($ftp->_TYPE($type,@_)); 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_type'} = join(" ",$type,@_); 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate $oldval; 396*0Sstevel@tonic-gate} 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gatesub alloc 399*0Sstevel@tonic-gate{ 400*0Sstevel@tonic-gate my $ftp = shift; 401*0Sstevel@tonic-gate my $size = shift; 402*0Sstevel@tonic-gate my $oldval = ${*$ftp}{'net_ftp_allo'}; 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate return $oldval 405*0Sstevel@tonic-gate unless (defined $size); 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate return undef 408*0Sstevel@tonic-gate unless ($ftp->_ALLO($size,@_)); 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_allo'} = join(" ",$size,@_); 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate $oldval; 413*0Sstevel@tonic-gate} 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gatesub abort 416*0Sstevel@tonic-gate{ 417*0Sstevel@tonic-gate my $ftp = shift; 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate send($ftp,pack("CCC", $TELNET_IAC, $TELNET_IP, $TELNET_IAC),MSG_OOB); 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate $ftp->command(pack("C",$TELNET_DM) . "ABOR"); 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_dataconn'}->close() 424*0Sstevel@tonic-gate if defined ${*$ftp}{'net_ftp_dataconn'}; 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate $ftp->response(); 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate $ftp->status == CMD_OK; 429*0Sstevel@tonic-gate} 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gatesub get 432*0Sstevel@tonic-gate{ 433*0Sstevel@tonic-gate my($ftp,$remote,$local,$where) = @_; 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate my($loc,$len,$buf,$resp,$data); 436*0Sstevel@tonic-gate local *FD; 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate my $localfd = ref($local) || ref(\$local) eq "GLOB"; 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate ($local = $remote) =~ s#^.*/## 441*0Sstevel@tonic-gate unless(defined $local); 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate croak("Bad remote filename '$remote'\n") 444*0Sstevel@tonic-gate if $remote =~ /[\r\n]/s; 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_rest'} = $where 447*0Sstevel@tonic-gate if ($where); 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_port'}; 450*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_pasv'}; 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate $data = $ftp->retr($remote) or 453*0Sstevel@tonic-gate return undef; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate if($localfd) 456*0Sstevel@tonic-gate { 457*0Sstevel@tonic-gate $loc = $local; 458*0Sstevel@tonic-gate } 459*0Sstevel@tonic-gate else 460*0Sstevel@tonic-gate { 461*0Sstevel@tonic-gate $loc = \*FD; 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate unless(sysopen($loc, $local, O_CREAT | O_WRONLY | ($where ? O_APPEND : O_TRUNC))) 464*0Sstevel@tonic-gate { 465*0Sstevel@tonic-gate carp "Cannot open Local file $local: $!\n"; 466*0Sstevel@tonic-gate $data->abort; 467*0Sstevel@tonic-gate return undef; 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate if($ftp->type eq 'I' && !binmode($loc)) 472*0Sstevel@tonic-gate { 473*0Sstevel@tonic-gate carp "Cannot binmode Local file $local: $!\n"; 474*0Sstevel@tonic-gate $data->abort; 475*0Sstevel@tonic-gate close($loc) unless $localfd; 476*0Sstevel@tonic-gate return undef; 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate $buf = ''; 480*0Sstevel@tonic-gate my($count,$hashh,$hashb,$ref) = (0); 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate ($hashh,$hashb) = @$ref 483*0Sstevel@tonic-gate if($ref = ${*$ftp}{'net_ftp_hash'}); 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate my $blksize = ${*$ftp}{'net_ftp_blksize'}; 486*0Sstevel@tonic-gate local $\; # Just in case 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate while(1) 489*0Sstevel@tonic-gate { 490*0Sstevel@tonic-gate last unless $len = $data->read($buf,$blksize); 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate if (trEBCDIC && $ftp->type ne 'I') 493*0Sstevel@tonic-gate { 494*0Sstevel@tonic-gate $buf = $ftp->toebcdic($buf); 495*0Sstevel@tonic-gate $len = length($buf); 496*0Sstevel@tonic-gate } 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate if($hashh) { 499*0Sstevel@tonic-gate $count += $len; 500*0Sstevel@tonic-gate print $hashh "#" x (int($count / $hashb)); 501*0Sstevel@tonic-gate $count %= $hashb; 502*0Sstevel@tonic-gate } 503*0Sstevel@tonic-gate unless(print $loc $buf) 504*0Sstevel@tonic-gate { 505*0Sstevel@tonic-gate carp "Cannot write to Local file $local: $!\n"; 506*0Sstevel@tonic-gate $data->abort; 507*0Sstevel@tonic-gate close($loc) 508*0Sstevel@tonic-gate unless $localfd; 509*0Sstevel@tonic-gate return undef; 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate print $hashh "\n" if $hashh; 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate unless ($localfd) 516*0Sstevel@tonic-gate { 517*0Sstevel@tonic-gate unless (close($loc)) 518*0Sstevel@tonic-gate { 519*0Sstevel@tonic-gate carp "Cannot close file $local (perhaps disk space) $!\n"; 520*0Sstevel@tonic-gate return undef; 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate unless ($data->close()) # implied $ftp->response 525*0Sstevel@tonic-gate { 526*0Sstevel@tonic-gate carp "Unable to close datastream"; 527*0Sstevel@tonic-gate return undef; 528*0Sstevel@tonic-gate } 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate return $local; 531*0Sstevel@tonic-gate} 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gatesub cwd 534*0Sstevel@tonic-gate{ 535*0Sstevel@tonic-gate @_ == 1 || @_ == 2 or croak 'usage: $ftp->cwd( [ DIR ] )'; 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate my($ftp,$dir) = @_; 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate $dir = "/" unless defined($dir) && $dir =~ /\S/; 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate $dir eq ".." 542*0Sstevel@tonic-gate ? $ftp->_CDUP() 543*0Sstevel@tonic-gate : $ftp->_CWD($dir); 544*0Sstevel@tonic-gate} 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gatesub cdup 547*0Sstevel@tonic-gate{ 548*0Sstevel@tonic-gate @_ == 1 or croak 'usage: $ftp->cdup()'; 549*0Sstevel@tonic-gate $_[0]->_CDUP; 550*0Sstevel@tonic-gate} 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gatesub pwd 553*0Sstevel@tonic-gate{ 554*0Sstevel@tonic-gate @_ == 1 || croak 'usage: $ftp->pwd()'; 555*0Sstevel@tonic-gate my $ftp = shift; 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate $ftp->_PWD(); 558*0Sstevel@tonic-gate $ftp->_extract_path; 559*0Sstevel@tonic-gate} 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate# rmdir( $ftp, $dir, [ $recurse ] ) 562*0Sstevel@tonic-gate# 563*0Sstevel@tonic-gate# Removes $dir on remote host via FTP. 564*0Sstevel@tonic-gate# $ftp is handle for remote host 565*0Sstevel@tonic-gate# 566*0Sstevel@tonic-gate# If $recurse is TRUE, the directory and deleted recursively. 567*0Sstevel@tonic-gate# This means all of its contents and subdirectories. 568*0Sstevel@tonic-gate# 569*0Sstevel@tonic-gate# Initial version contributed by Dinkum Software 570*0Sstevel@tonic-gate# 571*0Sstevel@tonic-gatesub rmdir 572*0Sstevel@tonic-gate{ 573*0Sstevel@tonic-gate @_ == 2 || @_ == 3 or croak('usage: $ftp->rmdir( DIR [, RECURSE ] )'); 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate # Pick off the args 576*0Sstevel@tonic-gate my ($ftp, $dir, $recurse) = @_ ; 577*0Sstevel@tonic-gate my $ok; 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate return $ok 580*0Sstevel@tonic-gate if $ok = $ftp->_RMD( $dir ) or !$recurse; 581*0Sstevel@tonic-gate 582*0Sstevel@tonic-gate # Try to delete the contents 583*0Sstevel@tonic-gate # Get a list of all the files in the directory 584*0Sstevel@tonic-gate my $filelist = $ftp->ls($dir); 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate return undef 587*0Sstevel@tonic-gate unless $filelist && @$filelist; # failed, it is probably not a directory 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate # Go thru and delete each file or the directory 590*0Sstevel@tonic-gate my $file; 591*0Sstevel@tonic-gate foreach $file (map { m,/, ? $_ : "$dir/$_" } @$filelist) 592*0Sstevel@tonic-gate { 593*0Sstevel@tonic-gate next # successfully deleted the file 594*0Sstevel@tonic-gate if $ftp->delete($file); 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate # Failed to delete it, assume its a directory 597*0Sstevel@tonic-gate # Recurse and ignore errors, the final rmdir() will 598*0Sstevel@tonic-gate # fail on any errors here 599*0Sstevel@tonic-gate return $ok 600*0Sstevel@tonic-gate unless $ok = $ftp->rmdir($file, 1) ; 601*0Sstevel@tonic-gate } 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate # Directory should be empty 604*0Sstevel@tonic-gate # Try to remove the directory again 605*0Sstevel@tonic-gate # Pass results directly to caller 606*0Sstevel@tonic-gate # If any of the prior deletes failed, this 607*0Sstevel@tonic-gate # rmdir() will fail because directory is not empty 608*0Sstevel@tonic-gate return $ftp->_RMD($dir) ; 609*0Sstevel@tonic-gate} 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gatesub restart 612*0Sstevel@tonic-gate{ 613*0Sstevel@tonic-gate @_ == 2 || croak 'usage: $ftp->restart( BYTE_OFFSET )'; 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate my($ftp,$where) = @_; 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_rest'} = $where; 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate return undef; 620*0Sstevel@tonic-gate} 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gatesub mkdir 624*0Sstevel@tonic-gate{ 625*0Sstevel@tonic-gate @_ == 2 || @_ == 3 or croak 'usage: $ftp->mkdir( DIR [, RECURSE ] )'; 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate my($ftp,$dir,$recurse) = @_; 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate $ftp->_MKD($dir) || $recurse or 630*0Sstevel@tonic-gate return undef; 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate my $path = $dir; 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate unless($ftp->ok) 635*0Sstevel@tonic-gate { 636*0Sstevel@tonic-gate my @path = split(m#(?=/+)#, $dir); 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate $path = ""; 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate while(@path) 641*0Sstevel@tonic-gate { 642*0Sstevel@tonic-gate $path .= shift @path; 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate $ftp->_MKD($path); 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate $path = $ftp->_extract_path($path); 647*0Sstevel@tonic-gate } 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate # If the creation of the last element was not successful, see if we 650*0Sstevel@tonic-gate # can cd to it, if so then return path 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate unless($ftp->ok) 653*0Sstevel@tonic-gate { 654*0Sstevel@tonic-gate my($status,$message) = ($ftp->status,$ftp->message); 655*0Sstevel@tonic-gate my $pwd = $ftp->pwd; 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate if($pwd && $ftp->cwd($dir)) 658*0Sstevel@tonic-gate { 659*0Sstevel@tonic-gate $path = $dir; 660*0Sstevel@tonic-gate $ftp->cwd($pwd); 661*0Sstevel@tonic-gate } 662*0Sstevel@tonic-gate else 663*0Sstevel@tonic-gate { 664*0Sstevel@tonic-gate undef $path; 665*0Sstevel@tonic-gate } 666*0Sstevel@tonic-gate $ftp->set_status($status,$message); 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate $path; 671*0Sstevel@tonic-gate} 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gatesub delete 674*0Sstevel@tonic-gate{ 675*0Sstevel@tonic-gate @_ == 2 || croak 'usage: $ftp->delete( FILENAME )'; 676*0Sstevel@tonic-gate 677*0Sstevel@tonic-gate $_[0]->_DELE($_[1]); 678*0Sstevel@tonic-gate} 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gatesub put { shift->_store_cmd("stor",@_) } 681*0Sstevel@tonic-gatesub put_unique { shift->_store_cmd("stou",@_) } 682*0Sstevel@tonic-gatesub append { shift->_store_cmd("appe",@_) } 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gatesub nlst { shift->_data_cmd("NLST",@_) } 685*0Sstevel@tonic-gatesub list { shift->_data_cmd("LIST",@_) } 686*0Sstevel@tonic-gatesub retr { shift->_data_cmd("RETR",@_) } 687*0Sstevel@tonic-gatesub stor { shift->_data_cmd("STOR",@_) } 688*0Sstevel@tonic-gatesub stou { shift->_data_cmd("STOU",@_) } 689*0Sstevel@tonic-gatesub appe { shift->_data_cmd("APPE",@_) } 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gatesub _store_cmd 692*0Sstevel@tonic-gate{ 693*0Sstevel@tonic-gate my($ftp,$cmd,$local,$remote) = @_; 694*0Sstevel@tonic-gate my($loc,$sock,$len,$buf); 695*0Sstevel@tonic-gate local *FD; 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate my $localfd = ref($local) || ref(\$local) eq "GLOB"; 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate unless(defined $remote) 700*0Sstevel@tonic-gate { 701*0Sstevel@tonic-gate croak 'Must specify remote filename with stream input' 702*0Sstevel@tonic-gate if $localfd; 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate require File::Basename; 705*0Sstevel@tonic-gate $remote = File::Basename::basename($local); 706*0Sstevel@tonic-gate } 707*0Sstevel@tonic-gate if( defined ${*$ftp}{'net_ftp_allo'} ) 708*0Sstevel@tonic-gate { 709*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_allo'}; 710*0Sstevel@tonic-gate } else 711*0Sstevel@tonic-gate { 712*0Sstevel@tonic-gate # if the user hasn't already invoked the alloc method since the last 713*0Sstevel@tonic-gate # _store_cmd call, figure out if the local file is a regular file(not 714*0Sstevel@tonic-gate # a pipe, or device) and if so get the file size from stat, and send 715*0Sstevel@tonic-gate # an ALLO command before sending the STOR, STOU, or APPE command. 716*0Sstevel@tonic-gate my $size = -f $local && -s _; # no ALLO if sending data from a pipe 717*0Sstevel@tonic-gate $ftp->_ALLO($size) if $size; 718*0Sstevel@tonic-gate } 719*0Sstevel@tonic-gate croak("Bad remote filename '$remote'\n") 720*0Sstevel@tonic-gate if $remote =~ /[\r\n]/s; 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate if($localfd) 723*0Sstevel@tonic-gate { 724*0Sstevel@tonic-gate $loc = $local; 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate else 727*0Sstevel@tonic-gate { 728*0Sstevel@tonic-gate $loc = \*FD; 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate unless(sysopen($loc, $local, O_RDONLY)) 731*0Sstevel@tonic-gate { 732*0Sstevel@tonic-gate carp "Cannot open Local file $local: $!\n"; 733*0Sstevel@tonic-gate return undef; 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate if($ftp->type eq 'I' && !binmode($loc)) 738*0Sstevel@tonic-gate { 739*0Sstevel@tonic-gate carp "Cannot binmode Local file $local: $!\n"; 740*0Sstevel@tonic-gate return undef; 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate 743*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_port'}; 744*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_pasv'}; 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate $sock = $ftp->_data_cmd($cmd, $remote) or 747*0Sstevel@tonic-gate return undef; 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate $remote = ($ftp->message =~ /FILE:\s*(.*)/)[0] 750*0Sstevel@tonic-gate if 'STOU' eq uc $cmd; 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate my $blksize = ${*$ftp}{'net_ftp_blksize'}; 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate my($count,$hashh,$hashb,$ref) = (0); 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate ($hashh,$hashb) = @$ref 757*0Sstevel@tonic-gate if($ref = ${*$ftp}{'net_ftp_hash'}); 758*0Sstevel@tonic-gate 759*0Sstevel@tonic-gate while(1) 760*0Sstevel@tonic-gate { 761*0Sstevel@tonic-gate last unless $len = read($loc,$buf="",$blksize); 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate if (trEBCDIC && $ftp->type ne 'I') 764*0Sstevel@tonic-gate { 765*0Sstevel@tonic-gate $buf = $ftp->toascii($buf); 766*0Sstevel@tonic-gate $len = length($buf); 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate if($hashh) { 770*0Sstevel@tonic-gate $count += $len; 771*0Sstevel@tonic-gate print $hashh "#" x (int($count / $hashb)); 772*0Sstevel@tonic-gate $count %= $hashb; 773*0Sstevel@tonic-gate } 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate my $wlen; 776*0Sstevel@tonic-gate unless(defined($wlen = $sock->write($buf,$len)) && $wlen == $len) 777*0Sstevel@tonic-gate { 778*0Sstevel@tonic-gate $sock->abort; 779*0Sstevel@tonic-gate close($loc) 780*0Sstevel@tonic-gate unless $localfd; 781*0Sstevel@tonic-gate print $hashh "\n" if $hashh; 782*0Sstevel@tonic-gate return undef; 783*0Sstevel@tonic-gate } 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate print $hashh "\n" if $hashh; 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate close($loc) 789*0Sstevel@tonic-gate unless $localfd; 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate $sock->close() or 792*0Sstevel@tonic-gate return undef; 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate if ('STOU' eq uc $cmd and $ftp->message =~ m/unique\s+file\s*name\s*:\s*(.*)\)|"(.*)"/) 795*0Sstevel@tonic-gate { 796*0Sstevel@tonic-gate require File::Basename; 797*0Sstevel@tonic-gate $remote = File::Basename::basename($+) 798*0Sstevel@tonic-gate } 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate return $remote; 801*0Sstevel@tonic-gate} 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gatesub port 804*0Sstevel@tonic-gate{ 805*0Sstevel@tonic-gate @_ == 1 || @_ == 2 or croak 'usage: $ftp->port([PORT])'; 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate my($ftp,$port) = @_; 808*0Sstevel@tonic-gate my $ok; 809*0Sstevel@tonic-gate 810*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_intern_port'}; 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate unless(defined $port) 813*0Sstevel@tonic-gate { 814*0Sstevel@tonic-gate # create a Listen socket at same address as the command socket 815*0Sstevel@tonic-gate 816*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_listen'} ||= IO::Socket::INET->new(Listen => 5, 817*0Sstevel@tonic-gate Proto => 'tcp', 818*0Sstevel@tonic-gate Timeout => $ftp->timeout, 819*0Sstevel@tonic-gate LocalAddr => $ftp->sockhost, 820*0Sstevel@tonic-gate ); 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate my $listen = ${*$ftp}{'net_ftp_listen'}; 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate my($myport, @myaddr) = ($listen->sockport, split(/\./,$listen->sockhost)); 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate $port = join(',', @myaddr, $myport >> 8, $myport & 0xff); 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_intern_port'} = 1; 829*0Sstevel@tonic-gate } 830*0Sstevel@tonic-gate 831*0Sstevel@tonic-gate $ok = $ftp->_PORT($port); 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_port'} = $port; 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate $ok; 836*0Sstevel@tonic-gate} 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gatesub ls { shift->_list_cmd("NLST",@_); } 839*0Sstevel@tonic-gatesub dir { shift->_list_cmd("LIST",@_); } 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gatesub pasv 842*0Sstevel@tonic-gate{ 843*0Sstevel@tonic-gate @_ == 1 or croak 'usage: $ftp->pasv()'; 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gate my $ftp = shift; 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_intern_port'}; 848*0Sstevel@tonic-gate 849*0Sstevel@tonic-gate $ftp->_PASV && $ftp->message =~ /(\d+(,\d+)+)/ 850*0Sstevel@tonic-gate ? ${*$ftp}{'net_ftp_pasv'} = $1 851*0Sstevel@tonic-gate : undef; 852*0Sstevel@tonic-gate} 853*0Sstevel@tonic-gate 854*0Sstevel@tonic-gatesub unique_name 855*0Sstevel@tonic-gate{ 856*0Sstevel@tonic-gate my $ftp = shift; 857*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_unique'} || undef; 858*0Sstevel@tonic-gate} 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gatesub supported { 861*0Sstevel@tonic-gate @_ == 2 or croak 'usage: $ftp->supported( CMD )'; 862*0Sstevel@tonic-gate my $ftp = shift; 863*0Sstevel@tonic-gate my $cmd = uc shift; 864*0Sstevel@tonic-gate my $hash = ${*$ftp}{'net_ftp_supported'} ||= {}; 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate return $hash->{$cmd} 867*0Sstevel@tonic-gate if exists $hash->{$cmd}; 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate return $hash->{$cmd} = 0 870*0Sstevel@tonic-gate unless $ftp->_HELP($cmd); 871*0Sstevel@tonic-gate 872*0Sstevel@tonic-gate my $text = $ftp->message; 873*0Sstevel@tonic-gate if($text =~ /following\s+commands/i) { 874*0Sstevel@tonic-gate $text =~ s/^.*\n//; 875*0Sstevel@tonic-gate while($text =~ /(\*?)(\w+)(\*?)/sg) { 876*0Sstevel@tonic-gate $hash->{"\U$2"} = !length("$1$3"); 877*0Sstevel@tonic-gate } 878*0Sstevel@tonic-gate } 879*0Sstevel@tonic-gate else { 880*0Sstevel@tonic-gate $hash->{$cmd} = $text !~ /unimplemented/i; 881*0Sstevel@tonic-gate } 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate $hash->{$cmd} ||= 0; 884*0Sstevel@tonic-gate} 885*0Sstevel@tonic-gate 886*0Sstevel@tonic-gate## 887*0Sstevel@tonic-gate## Deprecated methods 888*0Sstevel@tonic-gate## 889*0Sstevel@tonic-gate 890*0Sstevel@tonic-gatesub lsl 891*0Sstevel@tonic-gate{ 892*0Sstevel@tonic-gate carp "Use of Net::FTP::lsl deprecated, use 'dir'" 893*0Sstevel@tonic-gate if $^W; 894*0Sstevel@tonic-gate goto &dir; 895*0Sstevel@tonic-gate} 896*0Sstevel@tonic-gate 897*0Sstevel@tonic-gatesub authorise 898*0Sstevel@tonic-gate{ 899*0Sstevel@tonic-gate carp "Use of Net::FTP::authorise deprecated, use 'authorize'" 900*0Sstevel@tonic-gate if $^W; 901*0Sstevel@tonic-gate goto &authorize; 902*0Sstevel@tonic-gate} 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate 905*0Sstevel@tonic-gate## 906*0Sstevel@tonic-gate## Private methods 907*0Sstevel@tonic-gate## 908*0Sstevel@tonic-gate 909*0Sstevel@tonic-gatesub _extract_path 910*0Sstevel@tonic-gate{ 911*0Sstevel@tonic-gate my($ftp, $path) = @_; 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate # This tries to work both with and without the quote doubling 914*0Sstevel@tonic-gate # convention (RFC 959 requires it, but the first 3 servers I checked 915*0Sstevel@tonic-gate # didn't implement it). It will fail on a server which uses a quote in 916*0Sstevel@tonic-gate # the message which isn't a part of or surrounding the path. 917*0Sstevel@tonic-gate $ftp->ok && 918*0Sstevel@tonic-gate $ftp->message =~ /(?:^|\s)\"(.*)\"(?:$|\s)/ && 919*0Sstevel@tonic-gate ($path = $1) =~ s/\"\"/\"/g; 920*0Sstevel@tonic-gate 921*0Sstevel@tonic-gate $path; 922*0Sstevel@tonic-gate} 923*0Sstevel@tonic-gate 924*0Sstevel@tonic-gate## 925*0Sstevel@tonic-gate## Communication methods 926*0Sstevel@tonic-gate## 927*0Sstevel@tonic-gate 928*0Sstevel@tonic-gatesub _dataconn 929*0Sstevel@tonic-gate{ 930*0Sstevel@tonic-gate my $ftp = shift; 931*0Sstevel@tonic-gate my $data = undef; 932*0Sstevel@tonic-gate my $pkg = "Net::FTP::" . $ftp->type; 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate eval "require " . $pkg; 935*0Sstevel@tonic-gate 936*0Sstevel@tonic-gate $pkg =~ s/ /_/g; 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_dataconn'}; 939*0Sstevel@tonic-gate 940*0Sstevel@tonic-gate if(defined ${*$ftp}{'net_ftp_pasv'}) 941*0Sstevel@tonic-gate { 942*0Sstevel@tonic-gate my @port = split(/,/,${*$ftp}{'net_ftp_pasv'}); 943*0Sstevel@tonic-gate 944*0Sstevel@tonic-gate $data = $pkg->new(PeerAddr => join(".",@port[0..3]), 945*0Sstevel@tonic-gate PeerPort => $port[4] * 256 + $port[5], 946*0Sstevel@tonic-gate LocalAddr => ${*$ftp}{'net_ftp_localaddr'}, 947*0Sstevel@tonic-gate Proto => 'tcp' 948*0Sstevel@tonic-gate ); 949*0Sstevel@tonic-gate } 950*0Sstevel@tonic-gate elsif(defined ${*$ftp}{'net_ftp_listen'}) 951*0Sstevel@tonic-gate { 952*0Sstevel@tonic-gate $data = ${*$ftp}{'net_ftp_listen'}->accept($pkg); 953*0Sstevel@tonic-gate close(delete ${*$ftp}{'net_ftp_listen'}); 954*0Sstevel@tonic-gate } 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate if($data) 957*0Sstevel@tonic-gate { 958*0Sstevel@tonic-gate ${*$data} = ""; 959*0Sstevel@tonic-gate $data->timeout($ftp->timeout); 960*0Sstevel@tonic-gate ${*$ftp}{'net_ftp_dataconn'} = $data; 961*0Sstevel@tonic-gate ${*$data}{'net_ftp_cmd'} = $ftp; 962*0Sstevel@tonic-gate ${*$data}{'net_ftp_blksize'} = ${*$ftp}{'net_ftp_blksize'}; 963*0Sstevel@tonic-gate } 964*0Sstevel@tonic-gate 965*0Sstevel@tonic-gate $data; 966*0Sstevel@tonic-gate} 967*0Sstevel@tonic-gate 968*0Sstevel@tonic-gatesub _list_cmd 969*0Sstevel@tonic-gate{ 970*0Sstevel@tonic-gate my $ftp = shift; 971*0Sstevel@tonic-gate my $cmd = uc shift; 972*0Sstevel@tonic-gate 973*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_port'}; 974*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_pasv'}; 975*0Sstevel@tonic-gate 976*0Sstevel@tonic-gate my $data = $ftp->_data_cmd($cmd,@_); 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate return 979*0Sstevel@tonic-gate unless(defined $data); 980*0Sstevel@tonic-gate 981*0Sstevel@tonic-gate require Net::FTP::A; 982*0Sstevel@tonic-gate bless $data, "Net::FTP::A"; # Force ASCII mode 983*0Sstevel@tonic-gate 984*0Sstevel@tonic-gate my $databuf = ''; 985*0Sstevel@tonic-gate my $buf = ''; 986*0Sstevel@tonic-gate my $blksize = ${*$ftp}{'net_ftp_blksize'}; 987*0Sstevel@tonic-gate 988*0Sstevel@tonic-gate while($data->read($databuf,$blksize)) { 989*0Sstevel@tonic-gate $buf .= $databuf; 990*0Sstevel@tonic-gate } 991*0Sstevel@tonic-gate 992*0Sstevel@tonic-gate my $list = [ split(/\n/,$buf) ]; 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate $data->close(); 995*0Sstevel@tonic-gate 996*0Sstevel@tonic-gate if (trEBCDIC) 997*0Sstevel@tonic-gate { 998*0Sstevel@tonic-gate for (@$list) { $_ = $ftp->toebcdic($_) } 999*0Sstevel@tonic-gate } 1000*0Sstevel@tonic-gate 1001*0Sstevel@tonic-gate wantarray ? @{$list} 1002*0Sstevel@tonic-gate : $list; 1003*0Sstevel@tonic-gate} 1004*0Sstevel@tonic-gate 1005*0Sstevel@tonic-gatesub _data_cmd 1006*0Sstevel@tonic-gate{ 1007*0Sstevel@tonic-gate my $ftp = shift; 1008*0Sstevel@tonic-gate my $cmd = uc shift; 1009*0Sstevel@tonic-gate my $ok = 1; 1010*0Sstevel@tonic-gate my $where = delete ${*$ftp}{'net_ftp_rest'} || 0; 1011*0Sstevel@tonic-gate my $arg; 1012*0Sstevel@tonic-gate 1013*0Sstevel@tonic-gate for $arg (@_) { 1014*0Sstevel@tonic-gate croak("Bad argument '$arg'\n") 1015*0Sstevel@tonic-gate if $arg =~ /[\r\n]/s; 1016*0Sstevel@tonic-gate } 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate if(${*$ftp}{'net_ftp_passive'} && 1019*0Sstevel@tonic-gate !defined ${*$ftp}{'net_ftp_pasv'} && 1020*0Sstevel@tonic-gate !defined ${*$ftp}{'net_ftp_port'}) 1021*0Sstevel@tonic-gate { 1022*0Sstevel@tonic-gate my $data = undef; 1023*0Sstevel@tonic-gate 1024*0Sstevel@tonic-gate $ok = defined $ftp->pasv; 1025*0Sstevel@tonic-gate $ok = $ftp->_REST($where) 1026*0Sstevel@tonic-gate if $ok && $where; 1027*0Sstevel@tonic-gate 1028*0Sstevel@tonic-gate if($ok) 1029*0Sstevel@tonic-gate { 1030*0Sstevel@tonic-gate $ftp->command($cmd,@_); 1031*0Sstevel@tonic-gate $data = $ftp->_dataconn(); 1032*0Sstevel@tonic-gate $ok = CMD_INFO == $ftp->response(); 1033*0Sstevel@tonic-gate if($ok) 1034*0Sstevel@tonic-gate { 1035*0Sstevel@tonic-gate $data->reading 1036*0Sstevel@tonic-gate if $data && $cmd =~ /RETR|LIST|NLST/; 1037*0Sstevel@tonic-gate return $data 1038*0Sstevel@tonic-gate } 1039*0Sstevel@tonic-gate $data->_close 1040*0Sstevel@tonic-gate if $data; 1041*0Sstevel@tonic-gate } 1042*0Sstevel@tonic-gate return undef; 1043*0Sstevel@tonic-gate } 1044*0Sstevel@tonic-gate 1045*0Sstevel@tonic-gate $ok = $ftp->port 1046*0Sstevel@tonic-gate unless (defined ${*$ftp}{'net_ftp_port'} || 1047*0Sstevel@tonic-gate defined ${*$ftp}{'net_ftp_pasv'}); 1048*0Sstevel@tonic-gate 1049*0Sstevel@tonic-gate $ok = $ftp->_REST($where) 1050*0Sstevel@tonic-gate if $ok && $where; 1051*0Sstevel@tonic-gate 1052*0Sstevel@tonic-gate return undef 1053*0Sstevel@tonic-gate unless $ok; 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate $ftp->command($cmd,@_); 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate return 1 1058*0Sstevel@tonic-gate if(defined ${*$ftp}{'net_ftp_pasv'}); 1059*0Sstevel@tonic-gate 1060*0Sstevel@tonic-gate $ok = CMD_INFO == $ftp->response(); 1061*0Sstevel@tonic-gate 1062*0Sstevel@tonic-gate return $ok 1063*0Sstevel@tonic-gate unless exists ${*$ftp}{'net_ftp_intern_port'}; 1064*0Sstevel@tonic-gate 1065*0Sstevel@tonic-gate if($ok) { 1066*0Sstevel@tonic-gate my $data = $ftp->_dataconn(); 1067*0Sstevel@tonic-gate 1068*0Sstevel@tonic-gate $data->reading 1069*0Sstevel@tonic-gate if $data && $cmd =~ /RETR|LIST|NLST/; 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate return $data; 1072*0Sstevel@tonic-gate } 1073*0Sstevel@tonic-gate 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate close(delete ${*$ftp}{'net_ftp_listen'}); 1076*0Sstevel@tonic-gate 1077*0Sstevel@tonic-gate return undef; 1078*0Sstevel@tonic-gate} 1079*0Sstevel@tonic-gate 1080*0Sstevel@tonic-gate## 1081*0Sstevel@tonic-gate## Over-ride methods (Net::Cmd) 1082*0Sstevel@tonic-gate## 1083*0Sstevel@tonic-gate 1084*0Sstevel@tonic-gatesub debug_text { $_[2] =~ /^(pass|resp|acct)/i ? "$1 ....\n" : $_[2]; } 1085*0Sstevel@tonic-gate 1086*0Sstevel@tonic-gatesub command 1087*0Sstevel@tonic-gate{ 1088*0Sstevel@tonic-gate my $ftp = shift; 1089*0Sstevel@tonic-gate 1090*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_port'}; 1091*0Sstevel@tonic-gate $ftp->SUPER::command(@_); 1092*0Sstevel@tonic-gate} 1093*0Sstevel@tonic-gate 1094*0Sstevel@tonic-gatesub response 1095*0Sstevel@tonic-gate{ 1096*0Sstevel@tonic-gate my $ftp = shift; 1097*0Sstevel@tonic-gate my $code = $ftp->SUPER::response(); 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate delete ${*$ftp}{'net_ftp_pasv'} 1100*0Sstevel@tonic-gate if ($code != CMD_MORE && $code != CMD_INFO); 1101*0Sstevel@tonic-gate 1102*0Sstevel@tonic-gate $code; 1103*0Sstevel@tonic-gate} 1104*0Sstevel@tonic-gate 1105*0Sstevel@tonic-gatesub parse_response 1106*0Sstevel@tonic-gate{ 1107*0Sstevel@tonic-gate return ($1, $2 eq "-") 1108*0Sstevel@tonic-gate if $_[1] =~ s/^(\d\d\d)(.?)//o; 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate my $ftp = shift; 1111*0Sstevel@tonic-gate 1112*0Sstevel@tonic-gate # Darn MS FTP server is a load of CRAP !!!! 1113*0Sstevel@tonic-gate return () 1114*0Sstevel@tonic-gate unless ${*$ftp}{'net_cmd_code'} + 0; 1115*0Sstevel@tonic-gate 1116*0Sstevel@tonic-gate (${*$ftp}{'net_cmd_code'},1); 1117*0Sstevel@tonic-gate} 1118*0Sstevel@tonic-gate 1119*0Sstevel@tonic-gate## 1120*0Sstevel@tonic-gate## Allow 2 servers to talk directly 1121*0Sstevel@tonic-gate## 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gatesub pasv_xfer { 1124*0Sstevel@tonic-gate my($sftp,$sfile,$dftp,$dfile,$unique) = @_; 1125*0Sstevel@tonic-gate 1126*0Sstevel@tonic-gate ($dfile = $sfile) =~ s#.*/## 1127*0Sstevel@tonic-gate unless(defined $dfile); 1128*0Sstevel@tonic-gate 1129*0Sstevel@tonic-gate my $port = $sftp->pasv or 1130*0Sstevel@tonic-gate return undef; 1131*0Sstevel@tonic-gate 1132*0Sstevel@tonic-gate $dftp->port($port) or 1133*0Sstevel@tonic-gate return undef; 1134*0Sstevel@tonic-gate 1135*0Sstevel@tonic-gate return undef 1136*0Sstevel@tonic-gate unless($unique ? $dftp->stou($dfile) : $dftp->stor($dfile)); 1137*0Sstevel@tonic-gate 1138*0Sstevel@tonic-gate unless($sftp->retr($sfile) && $sftp->response == CMD_INFO) { 1139*0Sstevel@tonic-gate $sftp->retr($sfile); 1140*0Sstevel@tonic-gate $dftp->abort; 1141*0Sstevel@tonic-gate $dftp->response(); 1142*0Sstevel@tonic-gate return undef; 1143*0Sstevel@tonic-gate } 1144*0Sstevel@tonic-gate 1145*0Sstevel@tonic-gate $dftp->pasv_wait($sftp); 1146*0Sstevel@tonic-gate} 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gatesub pasv_wait 1149*0Sstevel@tonic-gate{ 1150*0Sstevel@tonic-gate @_ == 2 or croak 'usage: $ftp->pasv_wait(NON_PASV_FTP)'; 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate my($ftp, $non_pasv) = @_; 1153*0Sstevel@tonic-gate my($file,$rin,$rout); 1154*0Sstevel@tonic-gate 1155*0Sstevel@tonic-gate vec($rin='',fileno($ftp),1) = 1; 1156*0Sstevel@tonic-gate select($rout=$rin, undef, undef, undef); 1157*0Sstevel@tonic-gate 1158*0Sstevel@tonic-gate $ftp->response(); 1159*0Sstevel@tonic-gate $non_pasv->response(); 1160*0Sstevel@tonic-gate 1161*0Sstevel@tonic-gate return undef 1162*0Sstevel@tonic-gate unless $ftp->ok() && $non_pasv->ok(); 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate return $1 1165*0Sstevel@tonic-gate if $ftp->message =~ /unique file name:\s*(\S*)\s*\)/; 1166*0Sstevel@tonic-gate 1167*0Sstevel@tonic-gate return $1 1168*0Sstevel@tonic-gate if $non_pasv->message =~ /unique file name:\s*(\S*)\s*\)/; 1169*0Sstevel@tonic-gate 1170*0Sstevel@tonic-gate return 1; 1171*0Sstevel@tonic-gate} 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gatesub cmd { shift->command(@_)->response() } 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate######################################## 1176*0Sstevel@tonic-gate# 1177*0Sstevel@tonic-gate# RFC959 commands 1178*0Sstevel@tonic-gate# 1179*0Sstevel@tonic-gate 1180*0Sstevel@tonic-gatesub _ABOR { shift->command("ABOR")->response() == CMD_OK } 1181*0Sstevel@tonic-gatesub _ALLO { shift->command("ALLO",@_)->response() == CMD_OK} 1182*0Sstevel@tonic-gatesub _CDUP { shift->command("CDUP")->response() == CMD_OK } 1183*0Sstevel@tonic-gatesub _NOOP { shift->command("NOOP")->response() == CMD_OK } 1184*0Sstevel@tonic-gatesub _PASV { shift->command("PASV")->response() == CMD_OK } 1185*0Sstevel@tonic-gatesub _QUIT { shift->command("QUIT")->response() == CMD_OK } 1186*0Sstevel@tonic-gatesub _DELE { shift->command("DELE",@_)->response() == CMD_OK } 1187*0Sstevel@tonic-gatesub _CWD { shift->command("CWD", @_)->response() == CMD_OK } 1188*0Sstevel@tonic-gatesub _PORT { shift->command("PORT",@_)->response() == CMD_OK } 1189*0Sstevel@tonic-gatesub _RMD { shift->command("RMD", @_)->response() == CMD_OK } 1190*0Sstevel@tonic-gatesub _MKD { shift->command("MKD", @_)->response() == CMD_OK } 1191*0Sstevel@tonic-gatesub _PWD { shift->command("PWD", @_)->response() == CMD_OK } 1192*0Sstevel@tonic-gatesub _TYPE { shift->command("TYPE",@_)->response() == CMD_OK } 1193*0Sstevel@tonic-gatesub _RNTO { shift->command("RNTO",@_)->response() == CMD_OK } 1194*0Sstevel@tonic-gatesub _RESP { shift->command("RESP",@_)->response() == CMD_OK } 1195*0Sstevel@tonic-gatesub _MDTM { shift->command("MDTM",@_)->response() == CMD_OK } 1196*0Sstevel@tonic-gatesub _SIZE { shift->command("SIZE",@_)->response() == CMD_OK } 1197*0Sstevel@tonic-gatesub _HELP { shift->command("HELP",@_)->response() == CMD_OK } 1198*0Sstevel@tonic-gatesub _STAT { shift->command("STAT",@_)->response() == CMD_OK } 1199*0Sstevel@tonic-gatesub _APPE { shift->command("APPE",@_)->response() == CMD_INFO } 1200*0Sstevel@tonic-gatesub _LIST { shift->command("LIST",@_)->response() == CMD_INFO } 1201*0Sstevel@tonic-gatesub _NLST { shift->command("NLST",@_)->response() == CMD_INFO } 1202*0Sstevel@tonic-gatesub _RETR { shift->command("RETR",@_)->response() == CMD_INFO } 1203*0Sstevel@tonic-gatesub _STOR { shift->command("STOR",@_)->response() == CMD_INFO } 1204*0Sstevel@tonic-gatesub _STOU { shift->command("STOU",@_)->response() == CMD_INFO } 1205*0Sstevel@tonic-gatesub _RNFR { shift->command("RNFR",@_)->response() == CMD_MORE } 1206*0Sstevel@tonic-gatesub _REST { shift->command("REST",@_)->response() == CMD_MORE } 1207*0Sstevel@tonic-gatesub _USER { shift->command("user",@_)->response() } # A certain brain dead firewall :-) 1208*0Sstevel@tonic-gatesub _PASS { shift->command("PASS",@_)->response() } 1209*0Sstevel@tonic-gatesub _ACCT { shift->command("ACCT",@_)->response() } 1210*0Sstevel@tonic-gatesub _AUTH { shift->command("AUTH",@_)->response() } 1211*0Sstevel@tonic-gate 1212*0Sstevel@tonic-gatesub _SMNT { shift->unsupported(@_) } 1213*0Sstevel@tonic-gatesub _MODE { shift->unsupported(@_) } 1214*0Sstevel@tonic-gatesub _SYST { shift->unsupported(@_) } 1215*0Sstevel@tonic-gatesub _STRU { shift->unsupported(@_) } 1216*0Sstevel@tonic-gatesub _REIN { shift->unsupported(@_) } 1217*0Sstevel@tonic-gate 1218*0Sstevel@tonic-gate1; 1219*0Sstevel@tonic-gate 1220*0Sstevel@tonic-gate__END__ 1221*0Sstevel@tonic-gate 1222*0Sstevel@tonic-gate=head1 NAME 1223*0Sstevel@tonic-gate 1224*0Sstevel@tonic-gateNet::FTP - FTP Client class 1225*0Sstevel@tonic-gate 1226*0Sstevel@tonic-gate=head1 SYNOPSIS 1227*0Sstevel@tonic-gate 1228*0Sstevel@tonic-gate use Net::FTP; 1229*0Sstevel@tonic-gate 1230*0Sstevel@tonic-gate $ftp = Net::FTP->new("some.host.name", Debug => 0) 1231*0Sstevel@tonic-gate or die "Cannot connect to some.host.name: $@"; 1232*0Sstevel@tonic-gate 1233*0Sstevel@tonic-gate $ftp->login("anonymous",'-anonymous@') 1234*0Sstevel@tonic-gate or die "Cannot login ", $ftp->message; 1235*0Sstevel@tonic-gate 1236*0Sstevel@tonic-gate $ftp->cwd("/pub") 1237*0Sstevel@tonic-gate or die "Cannot change working directory ", $ftp->message; 1238*0Sstevel@tonic-gate 1239*0Sstevel@tonic-gate $ftp->get("that.file") 1240*0Sstevel@tonic-gate or die "get failed ", $ftp->message; 1241*0Sstevel@tonic-gate 1242*0Sstevel@tonic-gate $ftp->quit; 1243*0Sstevel@tonic-gate 1244*0Sstevel@tonic-gate=head1 DESCRIPTION 1245*0Sstevel@tonic-gate 1246*0Sstevel@tonic-gateC<Net::FTP> is a class implementing a simple FTP client in Perl as 1247*0Sstevel@tonic-gatedescribed in RFC959. It provides wrappers for a subset of the RFC959 1248*0Sstevel@tonic-gatecommands. 1249*0Sstevel@tonic-gate 1250*0Sstevel@tonic-gate=head1 OVERVIEW 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gateFTP stands for File Transfer Protocol. It is a way of transferring 1253*0Sstevel@tonic-gatefiles between networked machines. The protocol defines a client 1254*0Sstevel@tonic-gate(whose commands are provided by this module) and a server (not 1255*0Sstevel@tonic-gateimplemented in this module). Communication is always initiated by the 1256*0Sstevel@tonic-gateclient, and the server responds with a message and a status code (and 1257*0Sstevel@tonic-gatesometimes with data). 1258*0Sstevel@tonic-gate 1259*0Sstevel@tonic-gateThe FTP protocol allows files to be sent to or fetched from the 1260*0Sstevel@tonic-gateserver. Each transfer involves a B<local file> (on the client) and a 1261*0Sstevel@tonic-gateB<remote file> (on the server). In this module, the same file name 1262*0Sstevel@tonic-gatewill be used for both local and remote if only one is specified. This 1263*0Sstevel@tonic-gatemeans that transferring remote file C</path/to/file> will try to put 1264*0Sstevel@tonic-gatethat file in C</path/to/file> locally, unless you specify a local file 1265*0Sstevel@tonic-gatename. 1266*0Sstevel@tonic-gate 1267*0Sstevel@tonic-gateThe protocol also defines several standard B<translations> which the 1268*0Sstevel@tonic-gatefile can undergo during transfer. These are ASCII, EBCDIC, binary, 1269*0Sstevel@tonic-gateand byte. ASCII is the default type, and indicates that the sender of 1270*0Sstevel@tonic-gatefiles will translate the ends of lines to a standard representation 1271*0Sstevel@tonic-gatewhich the receiver will then translate back into their local 1272*0Sstevel@tonic-gaterepresentation. EBCDIC indicates the file being transferred is in 1273*0Sstevel@tonic-gateEBCDIC format. Binary (also known as image) format sends the data as 1274*0Sstevel@tonic-gatea contiguous bit stream. Byte format transfers the data as bytes, the 1275*0Sstevel@tonic-gatevalues of which remain the same regardless of differences in byte size 1276*0Sstevel@tonic-gatebetween the two machines (in theory - in practice you should only use 1277*0Sstevel@tonic-gatethis if you really know what you're doing). 1278*0Sstevel@tonic-gate 1279*0Sstevel@tonic-gate=head1 CONSTRUCTOR 1280*0Sstevel@tonic-gate 1281*0Sstevel@tonic-gate=over 4 1282*0Sstevel@tonic-gate 1283*0Sstevel@tonic-gate=item new (HOST [,OPTIONS]) 1284*0Sstevel@tonic-gate 1285*0Sstevel@tonic-gateThis is the constructor for a new Net::FTP object. C<HOST> is the 1286*0Sstevel@tonic-gatename of the remote host to which an FTP connection is required. 1287*0Sstevel@tonic-gate 1288*0Sstevel@tonic-gateC<OPTIONS> are passed in a hash like fashion, using key and value pairs. 1289*0Sstevel@tonic-gatePossible options are: 1290*0Sstevel@tonic-gate 1291*0Sstevel@tonic-gateB<Firewall> - The name of a machine which acts as an FTP firewall. This can be 1292*0Sstevel@tonic-gateoverridden by an environment variable C<FTP_FIREWALL>. If specified, and the 1293*0Sstevel@tonic-gategiven host cannot be directly connected to, then the 1294*0Sstevel@tonic-gateconnection is made to the firewall machine and the string C<@hostname> is 1295*0Sstevel@tonic-gateappended to the login identifier. This kind of setup is also refered to 1296*0Sstevel@tonic-gateas an ftp proxy. 1297*0Sstevel@tonic-gate 1298*0Sstevel@tonic-gateB<FirewallType> - The type of firewall running on the machine indicated by 1299*0Sstevel@tonic-gateB<Firewall>. This can be overridden by an environment variable 1300*0Sstevel@tonic-gateC<FTP_FIREWALL_TYPE>. For a list of permissible types, see the description of 1301*0Sstevel@tonic-gateftp_firewall_type in L<Net::Config>. 1302*0Sstevel@tonic-gate 1303*0Sstevel@tonic-gateB<BlockSize> - This is the block size that Net::FTP will use when doing 1304*0Sstevel@tonic-gatetransfers. (defaults to 10240) 1305*0Sstevel@tonic-gate 1306*0Sstevel@tonic-gateB<Port> - The port number to connect to on the remote machine for the 1307*0Sstevel@tonic-gateFTP connection 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gateB<Timeout> - Set a timeout value (defaults to 120) 1310*0Sstevel@tonic-gate 1311*0Sstevel@tonic-gateB<Debug> - debug level (see the debug method in L<Net::Cmd>) 1312*0Sstevel@tonic-gate 1313*0Sstevel@tonic-gateB<Passive> - If set to a non-zero value then all data transfers will be done 1314*0Sstevel@tonic-gateusing passive mode. This is not usually required except for some I<dumb> 1315*0Sstevel@tonic-gateservers, and some firewall configurations. This can also be set by the 1316*0Sstevel@tonic-gateenvironment variable C<FTP_PASSIVE>. 1317*0Sstevel@tonic-gate 1318*0Sstevel@tonic-gateB<Hash> - If given a reference to a file handle (e.g., C<\*STDERR>), 1319*0Sstevel@tonic-gateprint hash marks (#) on that filehandle every 1024 bytes. This 1320*0Sstevel@tonic-gatesimply invokes the C<hash()> method for you, so that hash marks 1321*0Sstevel@tonic-gateare displayed for all transfers. You can, of course, call C<hash()> 1322*0Sstevel@tonic-gateexplicitly whenever you'd like. 1323*0Sstevel@tonic-gate 1324*0Sstevel@tonic-gateB<LocalAddr> - Local address to use for all socket connections, this 1325*0Sstevel@tonic-gateargument will be passed to L<IO::Socket::INET> 1326*0Sstevel@tonic-gate 1327*0Sstevel@tonic-gateIf the constructor fails undef will be returned and an error message will 1328*0Sstevel@tonic-gatebe in $@ 1329*0Sstevel@tonic-gate 1330*0Sstevel@tonic-gate=back 1331*0Sstevel@tonic-gate 1332*0Sstevel@tonic-gate=head1 METHODS 1333*0Sstevel@tonic-gate 1334*0Sstevel@tonic-gateUnless otherwise stated all methods return either a I<true> or I<false> 1335*0Sstevel@tonic-gatevalue, with I<true> meaning that the operation was a success. When a method 1336*0Sstevel@tonic-gatestates that it returns a value, failure will be returned as I<undef> or an 1337*0Sstevel@tonic-gateempty list. 1338*0Sstevel@tonic-gate 1339*0Sstevel@tonic-gate=over 4 1340*0Sstevel@tonic-gate 1341*0Sstevel@tonic-gate=item login ([LOGIN [,PASSWORD [, ACCOUNT] ] ]) 1342*0Sstevel@tonic-gate 1343*0Sstevel@tonic-gateLog into the remote FTP server with the given login information. If 1344*0Sstevel@tonic-gateno arguments are given then the C<Net::FTP> uses the C<Net::Netrc> 1345*0Sstevel@tonic-gatepackage to lookup the login information for the connected host. 1346*0Sstevel@tonic-gateIf no information is found then a login of I<anonymous> is used. 1347*0Sstevel@tonic-gateIf no password is given and the login is I<anonymous> then I<anonymous@> 1348*0Sstevel@tonic-gatewill be used for password. 1349*0Sstevel@tonic-gate 1350*0Sstevel@tonic-gateIf the connection is via a firewall then the C<authorize> method will 1351*0Sstevel@tonic-gatebe called with no arguments. 1352*0Sstevel@tonic-gate 1353*0Sstevel@tonic-gate=item authorize ( [AUTH [, RESP]]) 1354*0Sstevel@tonic-gate 1355*0Sstevel@tonic-gateThis is a protocol used by some firewall ftp proxies. It is used 1356*0Sstevel@tonic-gateto authorise the user to send data out. If both arguments are not specified 1357*0Sstevel@tonic-gatethen C<authorize> uses C<Net::Netrc> to do a lookup. 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate=item site (ARGS) 1360*0Sstevel@tonic-gate 1361*0Sstevel@tonic-gateSend a SITE command to the remote server and wait for a response. 1362*0Sstevel@tonic-gate 1363*0Sstevel@tonic-gateReturns most significant digit of the response code. 1364*0Sstevel@tonic-gate 1365*0Sstevel@tonic-gate=item ascii 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gateTransfer file in ASCII. CRLF translation will be done if required 1368*0Sstevel@tonic-gate 1369*0Sstevel@tonic-gate=item binary 1370*0Sstevel@tonic-gate 1371*0Sstevel@tonic-gateTransfer file in binary mode. No transformation will be done. 1372*0Sstevel@tonic-gate 1373*0Sstevel@tonic-gateB<Hint>: If both server and client machines use the same line ending for 1374*0Sstevel@tonic-gatetext files, then it will be faster to transfer all files in binary mode. 1375*0Sstevel@tonic-gate 1376*0Sstevel@tonic-gate=item rename ( OLDNAME, NEWNAME ) 1377*0Sstevel@tonic-gate 1378*0Sstevel@tonic-gateRename a file on the remote FTP server from C<OLDNAME> to C<NEWNAME>. This 1379*0Sstevel@tonic-gateis done by sending the RNFR and RNTO commands. 1380*0Sstevel@tonic-gate 1381*0Sstevel@tonic-gate=item delete ( FILENAME ) 1382*0Sstevel@tonic-gate 1383*0Sstevel@tonic-gateSend a request to the server to delete C<FILENAME>. 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate=item cwd ( [ DIR ] ) 1386*0Sstevel@tonic-gate 1387*0Sstevel@tonic-gateAttempt to change directory to the directory given in C<$dir>. If 1388*0Sstevel@tonic-gateC<$dir> is C<"..">, the FTP C<CDUP> command is used to attempt to 1389*0Sstevel@tonic-gatemove up one directory. If no directory is given then an attempt is made 1390*0Sstevel@tonic-gateto change the directory to the root directory. 1391*0Sstevel@tonic-gate 1392*0Sstevel@tonic-gate=item cdup () 1393*0Sstevel@tonic-gate 1394*0Sstevel@tonic-gateChange directory to the parent of the current directory. 1395*0Sstevel@tonic-gate 1396*0Sstevel@tonic-gate=item pwd () 1397*0Sstevel@tonic-gate 1398*0Sstevel@tonic-gateReturns the full pathname of the current directory. 1399*0Sstevel@tonic-gate 1400*0Sstevel@tonic-gate=item restart ( WHERE ) 1401*0Sstevel@tonic-gate 1402*0Sstevel@tonic-gateSet the byte offset at which to begin the next data transfer. Net::FTP simply 1403*0Sstevel@tonic-gaterecords this value and uses it when during the next data transfer. For this 1404*0Sstevel@tonic-gatereason this method will not return an error, but setting it may cause 1405*0Sstevel@tonic-gatea subsequent data transfer to fail. 1406*0Sstevel@tonic-gate 1407*0Sstevel@tonic-gate=item rmdir ( DIR [, RECURSE ]) 1408*0Sstevel@tonic-gate 1409*0Sstevel@tonic-gateRemove the directory with the name C<DIR>. If C<RECURSE> is I<true> then 1410*0Sstevel@tonic-gateC<rmdir> will attempt to delete everything inside the directory. 1411*0Sstevel@tonic-gate 1412*0Sstevel@tonic-gate=item mkdir ( DIR [, RECURSE ]) 1413*0Sstevel@tonic-gate 1414*0Sstevel@tonic-gateCreate a new directory with the name C<DIR>. If C<RECURSE> is I<true> then 1415*0Sstevel@tonic-gateC<mkdir> will attempt to create all the directories in the given path. 1416*0Sstevel@tonic-gate 1417*0Sstevel@tonic-gateReturns the full pathname to the new directory. 1418*0Sstevel@tonic-gate 1419*0Sstevel@tonic-gate=item ls ( [ DIR ] ) 1420*0Sstevel@tonic-gate 1421*0Sstevel@tonic-gate=item alloc ( SIZE [, RECORD_SIZE] ) 1422*0Sstevel@tonic-gate 1423*0Sstevel@tonic-gateThe alloc command allows you to give the ftp server a hint about the size 1424*0Sstevel@tonic-gateof the file about to be transfered using the ALLO ftp command. Some storage 1425*0Sstevel@tonic-gatesystems use this to make intelligent decisions about how to store the file. 1426*0Sstevel@tonic-gateThe C<SIZE> argument represents the size of the file in bytes. The 1427*0Sstevel@tonic-gateC<RECORD_SIZE> argument indicates a mazimum record or page size for files 1428*0Sstevel@tonic-gatesent with a record or page structure. 1429*0Sstevel@tonic-gate 1430*0Sstevel@tonic-gateThe size of the file will be determined, and sent to the server 1431*0Sstevel@tonic-gateautomatically for normal files so that this method need only be called if 1432*0Sstevel@tonic-gateyou are transfering data from a socket, named pipe, or other stream not 1433*0Sstevel@tonic-gateassociated with a normal file. 1434*0Sstevel@tonic-gate 1435*0Sstevel@tonic-gateGet a directory listing of C<DIR>, or the current directory. 1436*0Sstevel@tonic-gate 1437*0Sstevel@tonic-gateIn an array context, returns a list of lines returned from the server. In 1438*0Sstevel@tonic-gatea scalar context, returns a reference to a list. 1439*0Sstevel@tonic-gate 1440*0Sstevel@tonic-gate=item dir ( [ DIR ] ) 1441*0Sstevel@tonic-gate 1442*0Sstevel@tonic-gateGet a directory listing of C<DIR>, or the current directory in long format. 1443*0Sstevel@tonic-gate 1444*0Sstevel@tonic-gateIn an array context, returns a list of lines returned from the server. In 1445*0Sstevel@tonic-gatea scalar context, returns a reference to a list. 1446*0Sstevel@tonic-gate 1447*0Sstevel@tonic-gate=item get ( REMOTE_FILE [, LOCAL_FILE [, WHERE]] ) 1448*0Sstevel@tonic-gate 1449*0Sstevel@tonic-gateGet C<REMOTE_FILE> from the server and store locally. C<LOCAL_FILE> may be 1450*0Sstevel@tonic-gatea filename or a filehandle. If not specified, the file will be stored in 1451*0Sstevel@tonic-gatethe current directory with the same leafname as the remote file. 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gateIf C<WHERE> is given then the first C<WHERE> bytes of the file will 1454*0Sstevel@tonic-gatenot be transfered, and the remaining bytes will be appended to 1455*0Sstevel@tonic-gatethe local file if it already exists. 1456*0Sstevel@tonic-gate 1457*0Sstevel@tonic-gateReturns C<LOCAL_FILE>, or the generated local file name if C<LOCAL_FILE> 1458*0Sstevel@tonic-gateis not given. If an error was encountered undef is returned. 1459*0Sstevel@tonic-gate 1460*0Sstevel@tonic-gate=item put ( LOCAL_FILE [, REMOTE_FILE ] ) 1461*0Sstevel@tonic-gate 1462*0Sstevel@tonic-gatePut a file on the remote server. C<LOCAL_FILE> may be a name or a filehandle. 1463*0Sstevel@tonic-gateIf C<LOCAL_FILE> is a filehandle then C<REMOTE_FILE> must be specified. If 1464*0Sstevel@tonic-gateC<REMOTE_FILE> is not specified then the file will be stored in the current 1465*0Sstevel@tonic-gatedirectory with the same leafname as C<LOCAL_FILE>. 1466*0Sstevel@tonic-gate 1467*0Sstevel@tonic-gateReturns C<REMOTE_FILE>, or the generated remote filename if C<REMOTE_FILE> 1468*0Sstevel@tonic-gateis not given. 1469*0Sstevel@tonic-gate 1470*0Sstevel@tonic-gateB<NOTE>: If for some reason the transfer does not complete and an error is 1471*0Sstevel@tonic-gatereturned then the contents that had been transfered will not be remove 1472*0Sstevel@tonic-gateautomatically. 1473*0Sstevel@tonic-gate 1474*0Sstevel@tonic-gate=item put_unique ( LOCAL_FILE [, REMOTE_FILE ] ) 1475*0Sstevel@tonic-gate 1476*0Sstevel@tonic-gateSame as put but uses the C<STOU> command. 1477*0Sstevel@tonic-gate 1478*0Sstevel@tonic-gateReturns the name of the file on the server. 1479*0Sstevel@tonic-gate 1480*0Sstevel@tonic-gate=item append ( LOCAL_FILE [, REMOTE_FILE ] ) 1481*0Sstevel@tonic-gate 1482*0Sstevel@tonic-gateSame as put but appends to the file on the remote server. 1483*0Sstevel@tonic-gate 1484*0Sstevel@tonic-gateReturns C<REMOTE_FILE>, or the generated remote filename if C<REMOTE_FILE> 1485*0Sstevel@tonic-gateis not given. 1486*0Sstevel@tonic-gate 1487*0Sstevel@tonic-gate=item unique_name () 1488*0Sstevel@tonic-gate 1489*0Sstevel@tonic-gateReturns the name of the last file stored on the server using the 1490*0Sstevel@tonic-gateC<STOU> command. 1491*0Sstevel@tonic-gate 1492*0Sstevel@tonic-gate=item mdtm ( FILE ) 1493*0Sstevel@tonic-gate 1494*0Sstevel@tonic-gateReturns the I<modification time> of the given file 1495*0Sstevel@tonic-gate 1496*0Sstevel@tonic-gate=item size ( FILE ) 1497*0Sstevel@tonic-gate 1498*0Sstevel@tonic-gateReturns the size in bytes for the given file as stored on the remote server. 1499*0Sstevel@tonic-gate 1500*0Sstevel@tonic-gateB<NOTE>: The size reported is the size of the stored file on the remote server. 1501*0Sstevel@tonic-gateIf the file is subsequently transfered from the server in ASCII mode 1502*0Sstevel@tonic-gateand the remote server and local machine have different ideas about 1503*0Sstevel@tonic-gate"End Of Line" then the size of file on the local machine after transfer 1504*0Sstevel@tonic-gatemay be different. 1505*0Sstevel@tonic-gate 1506*0Sstevel@tonic-gate=item supported ( CMD ) 1507*0Sstevel@tonic-gate 1508*0Sstevel@tonic-gateReturns TRUE if the remote server supports the given command. 1509*0Sstevel@tonic-gate 1510*0Sstevel@tonic-gate=item hash ( [FILEHANDLE_GLOB_REF],[ BYTES_PER_HASH_MARK] ) 1511*0Sstevel@tonic-gate 1512*0Sstevel@tonic-gateCalled without parameters, or with the first argument false, hash marks 1513*0Sstevel@tonic-gateare suppressed. If the first argument is true but not a reference to a 1514*0Sstevel@tonic-gatefile handle glob, then \*STDERR is used. The second argument is the number 1515*0Sstevel@tonic-gateof bytes per hash mark printed, and defaults to 1024. In all cases the 1516*0Sstevel@tonic-gatereturn value is a reference to an array of two: the filehandle glob reference 1517*0Sstevel@tonic-gateand the bytes per hash mark. 1518*0Sstevel@tonic-gate 1519*0Sstevel@tonic-gate=back 1520*0Sstevel@tonic-gate 1521*0Sstevel@tonic-gateThe following methods can return different results depending on 1522*0Sstevel@tonic-gatehow they are called. If the user explicitly calls either 1523*0Sstevel@tonic-gateof the C<pasv> or C<port> methods then these methods will 1524*0Sstevel@tonic-gatereturn a I<true> or I<false> value. If the user does not 1525*0Sstevel@tonic-gatecall either of these methods then the result will be a 1526*0Sstevel@tonic-gatereference to a C<Net::FTP::dataconn> based object. 1527*0Sstevel@tonic-gate 1528*0Sstevel@tonic-gate=over 4 1529*0Sstevel@tonic-gate 1530*0Sstevel@tonic-gate=item nlst ( [ DIR ] ) 1531*0Sstevel@tonic-gate 1532*0Sstevel@tonic-gateSend an C<NLST> command to the server, with an optional parameter. 1533*0Sstevel@tonic-gate 1534*0Sstevel@tonic-gate=item list ( [ DIR ] ) 1535*0Sstevel@tonic-gate 1536*0Sstevel@tonic-gateSame as C<nlst> but using the C<LIST> command 1537*0Sstevel@tonic-gate 1538*0Sstevel@tonic-gate=item retr ( FILE ) 1539*0Sstevel@tonic-gate 1540*0Sstevel@tonic-gateBegin the retrieval of a file called C<FILE> from the remote server. 1541*0Sstevel@tonic-gate 1542*0Sstevel@tonic-gate=item stor ( FILE ) 1543*0Sstevel@tonic-gate 1544*0Sstevel@tonic-gateTell the server that you wish to store a file. C<FILE> is the 1545*0Sstevel@tonic-gatename of the new file that should be created. 1546*0Sstevel@tonic-gate 1547*0Sstevel@tonic-gate=item stou ( FILE ) 1548*0Sstevel@tonic-gate 1549*0Sstevel@tonic-gateSame as C<stor> but using the C<STOU> command. The name of the unique 1550*0Sstevel@tonic-gatefile which was created on the server will be available via the C<unique_name> 1551*0Sstevel@tonic-gatemethod after the data connection has been closed. 1552*0Sstevel@tonic-gate 1553*0Sstevel@tonic-gate=item appe ( FILE ) 1554*0Sstevel@tonic-gate 1555*0Sstevel@tonic-gateTell the server that we want to append some data to the end of a file 1556*0Sstevel@tonic-gatecalled C<FILE>. If this file does not exist then create it. 1557*0Sstevel@tonic-gate 1558*0Sstevel@tonic-gate=back 1559*0Sstevel@tonic-gate 1560*0Sstevel@tonic-gateIf for some reason you want to have complete control over the data connection, 1561*0Sstevel@tonic-gatethis includes generating it and calling the C<response> method when required, 1562*0Sstevel@tonic-gatethen the user can use these methods to do so. 1563*0Sstevel@tonic-gate 1564*0Sstevel@tonic-gateHowever calling these methods only affects the use of the methods above that 1565*0Sstevel@tonic-gatecan return a data connection. They have no effect on methods C<get>, C<put>, 1566*0Sstevel@tonic-gateC<put_unique> and those that do not require data connections. 1567*0Sstevel@tonic-gate 1568*0Sstevel@tonic-gate=over 4 1569*0Sstevel@tonic-gate 1570*0Sstevel@tonic-gate=item port ( [ PORT ] ) 1571*0Sstevel@tonic-gate 1572*0Sstevel@tonic-gateSend a C<PORT> command to the server. If C<PORT> is specified then it is sent 1573*0Sstevel@tonic-gateto the server. If not, then a listen socket is created and the correct information 1574*0Sstevel@tonic-gatesent to the server. 1575*0Sstevel@tonic-gate 1576*0Sstevel@tonic-gate=item pasv () 1577*0Sstevel@tonic-gate 1578*0Sstevel@tonic-gateTell the server to go into passive mode. Returns the text that represents the 1579*0Sstevel@tonic-gateport on which the server is listening, this text is in a suitable form to 1580*0Sstevel@tonic-gatesent to another ftp server using the C<port> method. 1581*0Sstevel@tonic-gate 1582*0Sstevel@tonic-gate=back 1583*0Sstevel@tonic-gate 1584*0Sstevel@tonic-gateThe following methods can be used to transfer files between two remote 1585*0Sstevel@tonic-gateservers, providing that these two servers can connect directly to each other. 1586*0Sstevel@tonic-gate 1587*0Sstevel@tonic-gate=over 4 1588*0Sstevel@tonic-gate 1589*0Sstevel@tonic-gate=item pasv_xfer ( SRC_FILE, DEST_SERVER [, DEST_FILE ] ) 1590*0Sstevel@tonic-gate 1591*0Sstevel@tonic-gateThis method will do a file transfer between two remote ftp servers. If 1592*0Sstevel@tonic-gateC<DEST_FILE> is omitted then the leaf name of C<SRC_FILE> will be used. 1593*0Sstevel@tonic-gate 1594*0Sstevel@tonic-gate=item pasv_xfer_unique ( SRC_FILE, DEST_SERVER [, DEST_FILE ] ) 1595*0Sstevel@tonic-gate 1596*0Sstevel@tonic-gateLike C<pasv_xfer> but the file is stored on the remote server using 1597*0Sstevel@tonic-gatethe STOU command. 1598*0Sstevel@tonic-gate 1599*0Sstevel@tonic-gate=item pasv_wait ( NON_PASV_SERVER ) 1600*0Sstevel@tonic-gate 1601*0Sstevel@tonic-gateThis method can be used to wait for a transfer to complete between a passive 1602*0Sstevel@tonic-gateserver and a non-passive server. The method should be called on the passive 1603*0Sstevel@tonic-gateserver with the C<Net::FTP> object for the non-passive server passed as an 1604*0Sstevel@tonic-gateargument. 1605*0Sstevel@tonic-gate 1606*0Sstevel@tonic-gate=item abort () 1607*0Sstevel@tonic-gate 1608*0Sstevel@tonic-gateAbort the current data transfer. 1609*0Sstevel@tonic-gate 1610*0Sstevel@tonic-gate=item quit () 1611*0Sstevel@tonic-gate 1612*0Sstevel@tonic-gateSend the QUIT command to the remote FTP server and close the socket connection. 1613*0Sstevel@tonic-gate 1614*0Sstevel@tonic-gate=back 1615*0Sstevel@tonic-gate 1616*0Sstevel@tonic-gate=head2 Methods for the adventurous 1617*0Sstevel@tonic-gate 1618*0Sstevel@tonic-gateC<Net::FTP> inherits from C<Net::Cmd> so methods defined in C<Net::Cmd> may 1619*0Sstevel@tonic-gatebe used to send commands to the remote FTP server. 1620*0Sstevel@tonic-gate 1621*0Sstevel@tonic-gate=over 4 1622*0Sstevel@tonic-gate 1623*0Sstevel@tonic-gate=item quot (CMD [,ARGS]) 1624*0Sstevel@tonic-gate 1625*0Sstevel@tonic-gateSend a command, that Net::FTP does not directly support, to the remote 1626*0Sstevel@tonic-gateserver and wait for a response. 1627*0Sstevel@tonic-gate 1628*0Sstevel@tonic-gateReturns most significant digit of the response code. 1629*0Sstevel@tonic-gate 1630*0Sstevel@tonic-gateB<WARNING> This call should only be used on commands that do not require 1631*0Sstevel@tonic-gatedata connections. Misuse of this method can hang the connection. 1632*0Sstevel@tonic-gate 1633*0Sstevel@tonic-gate=back 1634*0Sstevel@tonic-gate 1635*0Sstevel@tonic-gate=head1 THE dataconn CLASS 1636*0Sstevel@tonic-gate 1637*0Sstevel@tonic-gateSome of the methods defined in C<Net::FTP> return an object which will 1638*0Sstevel@tonic-gatebe derived from this class.The dataconn class itself is derived from 1639*0Sstevel@tonic-gatethe C<IO::Socket::INET> class, so any normal IO operations can be performed. 1640*0Sstevel@tonic-gateHowever the following methods are defined in the dataconn class and IO should 1641*0Sstevel@tonic-gatebe performed using these. 1642*0Sstevel@tonic-gate 1643*0Sstevel@tonic-gate=over 4 1644*0Sstevel@tonic-gate 1645*0Sstevel@tonic-gate=item read ( BUFFER, SIZE [, TIMEOUT ] ) 1646*0Sstevel@tonic-gate 1647*0Sstevel@tonic-gateRead C<SIZE> bytes of data from the server and place it into C<BUFFER>, also 1648*0Sstevel@tonic-gateperforming any <CRLF> translation necessary. C<TIMEOUT> is optional, if not 1649*0Sstevel@tonic-gategiven, the timeout value from the command connection will be used. 1650*0Sstevel@tonic-gate 1651*0Sstevel@tonic-gateReturns the number of bytes read before any <CRLF> translation. 1652*0Sstevel@tonic-gate 1653*0Sstevel@tonic-gate=item write ( BUFFER, SIZE [, TIMEOUT ] ) 1654*0Sstevel@tonic-gate 1655*0Sstevel@tonic-gateWrite C<SIZE> bytes of data from C<BUFFER> to the server, also 1656*0Sstevel@tonic-gateperforming any <CRLF> translation necessary. C<TIMEOUT> is optional, if not 1657*0Sstevel@tonic-gategiven, the timeout value from the command connection will be used. 1658*0Sstevel@tonic-gate 1659*0Sstevel@tonic-gateReturns the number of bytes written before any <CRLF> translation. 1660*0Sstevel@tonic-gate 1661*0Sstevel@tonic-gate=item bytes_read () 1662*0Sstevel@tonic-gate 1663*0Sstevel@tonic-gateReturns the number of bytes read so far. 1664*0Sstevel@tonic-gate 1665*0Sstevel@tonic-gate=item abort () 1666*0Sstevel@tonic-gate 1667*0Sstevel@tonic-gateAbort the current data transfer. 1668*0Sstevel@tonic-gate 1669*0Sstevel@tonic-gate=item close () 1670*0Sstevel@tonic-gate 1671*0Sstevel@tonic-gateClose the data connection and get a response from the FTP server. Returns 1672*0Sstevel@tonic-gateI<true> if the connection was closed successfully and the first digit of 1673*0Sstevel@tonic-gatethe response from the server was a '2'. 1674*0Sstevel@tonic-gate 1675*0Sstevel@tonic-gate=back 1676*0Sstevel@tonic-gate 1677*0Sstevel@tonic-gate=head1 UNIMPLEMENTED 1678*0Sstevel@tonic-gate 1679*0Sstevel@tonic-gateThe following RFC959 commands have not been implemented: 1680*0Sstevel@tonic-gate 1681*0Sstevel@tonic-gate=over 4 1682*0Sstevel@tonic-gate 1683*0Sstevel@tonic-gate=item B<SMNT> 1684*0Sstevel@tonic-gate 1685*0Sstevel@tonic-gateMount a different file system structure without changing login or 1686*0Sstevel@tonic-gateaccounting information. 1687*0Sstevel@tonic-gate 1688*0Sstevel@tonic-gate=item B<HELP> 1689*0Sstevel@tonic-gate 1690*0Sstevel@tonic-gateAsk the server for "helpful information" (that's what the RFC says) on 1691*0Sstevel@tonic-gatethe commands it accepts. 1692*0Sstevel@tonic-gate 1693*0Sstevel@tonic-gate=item B<MODE> 1694*0Sstevel@tonic-gate 1695*0Sstevel@tonic-gateSpecifies transfer mode (stream, block or compressed) for file to be 1696*0Sstevel@tonic-gatetransferred. 1697*0Sstevel@tonic-gate 1698*0Sstevel@tonic-gate=item B<SYST> 1699*0Sstevel@tonic-gate 1700*0Sstevel@tonic-gateRequest remote server system identification. 1701*0Sstevel@tonic-gate 1702*0Sstevel@tonic-gate=item B<STAT> 1703*0Sstevel@tonic-gate 1704*0Sstevel@tonic-gateRequest remote server status. 1705*0Sstevel@tonic-gate 1706*0Sstevel@tonic-gate=item B<STRU> 1707*0Sstevel@tonic-gate 1708*0Sstevel@tonic-gateSpecifies file structure for file to be transferred. 1709*0Sstevel@tonic-gate 1710*0Sstevel@tonic-gate=item B<REIN> 1711*0Sstevel@tonic-gate 1712*0Sstevel@tonic-gateReinitialize the connection, flushing all I/O and account information. 1713*0Sstevel@tonic-gate 1714*0Sstevel@tonic-gate=back 1715*0Sstevel@tonic-gate 1716*0Sstevel@tonic-gate=head1 REPORTING BUGS 1717*0Sstevel@tonic-gate 1718*0Sstevel@tonic-gateWhen reporting bugs/problems please include as much information as possible. 1719*0Sstevel@tonic-gateIt may be difficult for me to reproduce the problem as almost every setup 1720*0Sstevel@tonic-gateis different. 1721*0Sstevel@tonic-gate 1722*0Sstevel@tonic-gateA small script which yields the problem will probably be of help. It would 1723*0Sstevel@tonic-gatealso be useful if this script was run with the extra options C<Debug => 1> 1724*0Sstevel@tonic-gatepassed to the constructor, and the output sent with the bug report. If you 1725*0Sstevel@tonic-gatecannot include a small script then please include a Debug trace from a 1726*0Sstevel@tonic-gaterun of your program which does yield the problem. 1727*0Sstevel@tonic-gate 1728*0Sstevel@tonic-gate=head1 AUTHOR 1729*0Sstevel@tonic-gate 1730*0Sstevel@tonic-gateGraham Barr <gbarr@pobox.com> 1731*0Sstevel@tonic-gate 1732*0Sstevel@tonic-gate=head1 SEE ALSO 1733*0Sstevel@tonic-gate 1734*0Sstevel@tonic-gateL<Net::Netrc> 1735*0Sstevel@tonic-gateL<Net::Cmd> 1736*0Sstevel@tonic-gate 1737*0Sstevel@tonic-gateftp(1), ftpd(8), RFC 959 1738*0Sstevel@tonic-gatehttp://www.cis.ohio-state.edu/htbin/rfc/rfc959.html 1739*0Sstevel@tonic-gate 1740*0Sstevel@tonic-gate=head1 USE EXAMPLES 1741*0Sstevel@tonic-gate 1742*0Sstevel@tonic-gateFor an example of the use of Net::FTP see 1743*0Sstevel@tonic-gate 1744*0Sstevel@tonic-gate=over 4 1745*0Sstevel@tonic-gate 1746*0Sstevel@tonic-gate=item http://www.csh.rit.edu/~adam/Progs/ 1747*0Sstevel@tonic-gate 1748*0Sstevel@tonic-gateC<autoftp> is a program that can retrieve, send, or list files via 1749*0Sstevel@tonic-gatethe FTP protocol in a non-interactive manner. 1750*0Sstevel@tonic-gate 1751*0Sstevel@tonic-gate=back 1752*0Sstevel@tonic-gate 1753*0Sstevel@tonic-gate=head1 CREDITS 1754*0Sstevel@tonic-gate 1755*0Sstevel@tonic-gateHenry Gabryjelski <henryg@WPI.EDU> - for the suggestion of creating directories 1756*0Sstevel@tonic-gaterecursively. 1757*0Sstevel@tonic-gate 1758*0Sstevel@tonic-gateNathan Torkington <gnat@frii.com> - for some input on the documentation. 1759*0Sstevel@tonic-gate 1760*0Sstevel@tonic-gateRoderick Schertler <roderick@gate.net> - for various inputs 1761*0Sstevel@tonic-gate 1762*0Sstevel@tonic-gate=head1 COPYRIGHT 1763*0Sstevel@tonic-gate 1764*0Sstevel@tonic-gateCopyright (c) 1995-1998 Graham Barr. All rights reserved. 1765*0Sstevel@tonic-gateThis program is free software; you can redistribute it and/or modify it 1766*0Sstevel@tonic-gateunder the same terms as Perl itself. 1767*0Sstevel@tonic-gate 1768*0Sstevel@tonic-gate=for html <hr> 1769*0Sstevel@tonic-gate 1770*0Sstevel@tonic-gateI<$Id: //depot/libnet/Net/FTP.pm#80 $> 1771*0Sstevel@tonic-gate 1772*0Sstevel@tonic-gate=cut 1773