1b8851fccSafresh1# Net::FTP.pm 2b8851fccSafresh1# 35759b3d2Safresh1# Copyright (C) 1995-2004 Graham Barr. All rights reserved. 4*e0680481Safresh1# Copyright (C) 2013-2017, 2020, 2022 Steve Hay. All rights reserved. 5b8851fccSafresh1# This module is free software; you can redistribute it and/or modify it under 6b8851fccSafresh1# the same terms as Perl itself, i.e. under the terms of either the GNU General 7b8851fccSafresh1# Public License or the Artistic License, as specified in the F<LICENCE> file. 8b8851fccSafresh1# 9b8851fccSafresh1# Documentation (at end) improved 1996 by Nathan Torkington <gnat@frii.com>. 10b8851fccSafresh1 11b8851fccSafresh1package Net::FTP; 12b8851fccSafresh1 13b8851fccSafresh1use 5.008001; 14b8851fccSafresh1 15b8851fccSafresh1use strict; 16b8851fccSafresh1use warnings; 17b8851fccSafresh1 18b8851fccSafresh1use Carp; 19b8851fccSafresh1use Fcntl qw(O_WRONLY O_RDONLY O_APPEND O_CREAT O_TRUNC); 20b8851fccSafresh1use IO::Socket; 21b8851fccSafresh1use Net::Cmd; 22b8851fccSafresh1use Net::Config; 23b8851fccSafresh1use Socket; 24b8851fccSafresh1use Time::Local; 25b8851fccSafresh1 26*e0680481Safresh1our $VERSION = '3.15'; 27b8851fccSafresh1 28b8851fccSafresh1our $IOCLASS; 29b8851fccSafresh1my $family_key; 30b8851fccSafresh1BEGIN { 31b8851fccSafresh1 # Code for detecting if we can use SSL 32b8851fccSafresh1 my $ssl_class = eval { 33b8851fccSafresh1 require IO::Socket::SSL; 34b8851fccSafresh1 # first version with default CA on most platforms 35b8851fccSafresh1 no warnings 'numeric'; 36b8851fccSafresh1 IO::Socket::SSL->VERSION(2.007); 37b8851fccSafresh1 } && 'IO::Socket::SSL'; 38b8851fccSafresh1 39b8851fccSafresh1 my $nossl_warn = !$ssl_class && 40b8851fccSafresh1 'To use SSL please install IO::Socket::SSL with version>=2.007'; 41b8851fccSafresh1 42b8851fccSafresh1 # Code for detecting if we can use IPv6 43b8851fccSafresh1 my $inet6_class = eval { 44b8851fccSafresh1 require IO::Socket::IP; 45b8851fccSafresh1 no warnings 'numeric'; 465759b3d2Safresh1 IO::Socket::IP->VERSION(0.25); 47b8851fccSafresh1 } && 'IO::Socket::IP' || eval { 48b8851fccSafresh1 require IO::Socket::INET6; 49b8851fccSafresh1 no warnings 'numeric'; 50b8851fccSafresh1 IO::Socket::INET6->VERSION(2.62); 51b8851fccSafresh1 } && 'IO::Socket::INET6'; 52b8851fccSafresh1 53b8851fccSafresh1 sub can_ssl { $ssl_class }; 54b8851fccSafresh1 sub can_inet6 { $inet6_class }; 55b8851fccSafresh1 56b8851fccSafresh1 $IOCLASS = $ssl_class || $inet6_class || 'IO::Socket::INET'; 57b8851fccSafresh1 $family_key = 58b8851fccSafresh1 ( $ssl_class ? $ssl_class->can_ipv6 : $inet6_class || '' ) 59b8851fccSafresh1 eq 'IO::Socket::IP' 60b8851fccSafresh1 ? 'Family' : 'Domain'; 61b8851fccSafresh1} 62b8851fccSafresh1 63b8851fccSafresh1our @ISA = ('Exporter','Net::Cmd',$IOCLASS); 64b8851fccSafresh1 65b8851fccSafresh1use constant TELNET_IAC => 255; 66b8851fccSafresh1use constant TELNET_IP => 244; 67b8851fccSafresh1use constant TELNET_DM => 242; 68b8851fccSafresh1 69eac174f2Safresh1use constant EBCDIC => ord 'A' == 193; 70b8851fccSafresh1 71b8851fccSafresh1sub new { 72b8851fccSafresh1 my $pkg = shift; 73b8851fccSafresh1 my ($peer, %arg); 74b8851fccSafresh1 if (@_ % 2) { 75b8851fccSafresh1 $peer = shift; 76b8851fccSafresh1 %arg = @_; 77b8851fccSafresh1 } 78b8851fccSafresh1 else { 79b8851fccSafresh1 %arg = @_; 80b8851fccSafresh1 $peer = delete $arg{Host}; 81b8851fccSafresh1 } 82b8851fccSafresh1 83b8851fccSafresh1 my $host = $peer; 84b8851fccSafresh1 my $fire = undef; 85b8851fccSafresh1 my $fire_type = undef; 86b8851fccSafresh1 87b8851fccSafresh1 if (exists($arg{Firewall}) || Net::Config->requires_firewall($peer)) { 88b8851fccSafresh1 $fire = $arg{Firewall} 89b8851fccSafresh1 || $ENV{FTP_FIREWALL} 90b8851fccSafresh1 || $NetConfig{ftp_firewall} 91b8851fccSafresh1 || undef; 92b8851fccSafresh1 93b8851fccSafresh1 if (defined $fire) { 94b8851fccSafresh1 $peer = $fire; 95b8851fccSafresh1 delete $arg{Port}; 96b8851fccSafresh1 $fire_type = $arg{FirewallType} 97b8851fccSafresh1 || $ENV{FTP_FIREWALL_TYPE} 98b8851fccSafresh1 || $NetConfig{firewall_type} 99b8851fccSafresh1 || undef; 100b8851fccSafresh1 } 101b8851fccSafresh1 } 102b8851fccSafresh1 103b8851fccSafresh1 my %tlsargs; 104b8851fccSafresh1 if (can_ssl()) { 105b8851fccSafresh1 # for name verification strip port from domain:port, ipv4:port, [ipv6]:port 106b8851fccSafresh1 (my $hostname = $host) =~s{(?<!:):\d+$}{}; 107b8851fccSafresh1 %tlsargs = ( 108b8851fccSafresh1 SSL_verifycn_scheme => 'ftp', 109b8851fccSafresh1 SSL_verifycn_name => $hostname, 110b8851fccSafresh1 # use SNI if supported by IO::Socket::SSL 111b8851fccSafresh1 $pkg->can_client_sni ? (SSL_hostname => $hostname):(), 112b8851fccSafresh1 # reuse SSL session of control connection in data connections 113eac174f2Safresh1 SSL_session_cache_size => 10, 114eac174f2Safresh1 SSL_session_key => $hostname, 115b8851fccSafresh1 ); 116b8851fccSafresh1 # user defined SSL arg 117b8851fccSafresh1 $tlsargs{$_} = $arg{$_} for(grep { m{^SSL_} } keys %arg); 118eac174f2Safresh1 $tlsargs{SSL_reuse_ctx} = IO::Socket::SSL::SSL_Context->new(%tlsargs) 119eac174f2Safresh1 or return; 120b8851fccSafresh1 121b8851fccSafresh1 } elsif ($arg{SSL}) { 122b8851fccSafresh1 croak("IO::Socket::SSL >= 2.007 needed for SSL support"); 123b8851fccSafresh1 } 124b8851fccSafresh1 125b8851fccSafresh1 my $ftp = $pkg->SUPER::new( 126b8851fccSafresh1 PeerAddr => $peer, 127b8851fccSafresh1 PeerPort => $arg{Port} || ($arg{SSL} ? 'ftps(990)' : 'ftp(21)'), 128b8851fccSafresh1 LocalAddr => $arg{'LocalAddr'}, 129b8851fccSafresh1 $family_key => $arg{Domain} || $arg{Family}, 130b8851fccSafresh1 Proto => 'tcp', 131b8851fccSafresh1 Timeout => defined $arg{Timeout} ? $arg{Timeout} : 120, 132b8851fccSafresh1 %tlsargs, 133b8851fccSafresh1 $arg{SSL} ? ():( SSL_startHandshake => 0 ), 134b8851fccSafresh1 ) or return; 135b8851fccSafresh1 136b8851fccSafresh1 ${*$ftp}{'net_ftp_host'} = $host; # Remote hostname 137b8851fccSafresh1 ${*$ftp}{'net_ftp_type'} = 'A'; # ASCII/binary/etc mode 138b8851fccSafresh1 ${*$ftp}{'net_ftp_blksize'} = abs($arg{'BlockSize'} || 10240); 139b8851fccSafresh1 140b8851fccSafresh1 ${*$ftp}{'net_ftp_localaddr'} = $arg{'LocalAddr'}; 141b8851fccSafresh1 ${*$ftp}{'net_ftp_domain'} = $arg{Domain} || $arg{Family}; 142b8851fccSafresh1 143b8851fccSafresh1 ${*$ftp}{'net_ftp_firewall'} = $fire 144b8851fccSafresh1 if (defined $fire); 145b8851fccSafresh1 ${*$ftp}{'net_ftp_firewall_type'} = $fire_type 146b8851fccSafresh1 if (defined $fire_type); 147b8851fccSafresh1 148b8851fccSafresh1 ${*$ftp}{'net_ftp_passive'} = 149b8851fccSafresh1 int exists $arg{Passive} ? $arg{Passive} 150b8851fccSafresh1 : exists $ENV{FTP_PASSIVE} ? $ENV{FTP_PASSIVE} 151b8851fccSafresh1 : defined $fire ? $NetConfig{ftp_ext_passive} 152b8851fccSafresh1 : $NetConfig{ftp_int_passive}; # Whew! :-) 153b8851fccSafresh1 154b8851fccSafresh1 ${*$ftp}{net_ftp_tlsargs} = \%tlsargs if %tlsargs; 155b8851fccSafresh1 if ($arg{SSL}) { 156b8851fccSafresh1 ${*$ftp}{net_ftp_tlsprot} = 'P'; 157b8851fccSafresh1 ${*$ftp}{net_ftp_tlsdirect} = 1; 158b8851fccSafresh1 } 159b8851fccSafresh1 160b8851fccSafresh1 $ftp->hash(exists $arg{Hash} ? $arg{Hash} : 0, 1024); 161b8851fccSafresh1 162b8851fccSafresh1 $ftp->autoflush(1); 163b8851fccSafresh1 164b8851fccSafresh1 $ftp->debug(exists $arg{Debug} ? $arg{Debug} : undef); 165b8851fccSafresh1 166b8851fccSafresh1 unless ($ftp->response() == CMD_OK) { 167b8851fccSafresh1 $ftp->close(); 168b8851fccSafresh1 # keep @$ if no message. Happens, when response did not start with a code. 169b8851fccSafresh1 $@ = $ftp->message || $@; 170b8851fccSafresh1 undef $ftp; 171b8851fccSafresh1 } 172b8851fccSafresh1 173b8851fccSafresh1 $ftp; 174b8851fccSafresh1} 175b8851fccSafresh1 176b8851fccSafresh1## 177b8851fccSafresh1## User interface methods 178b8851fccSafresh1## 179b8851fccSafresh1 180b8851fccSafresh1 181b8851fccSafresh1sub host { 182b8851fccSafresh1 my $me = shift; 183b8851fccSafresh1 ${*$me}{'net_ftp_host'}; 184b8851fccSafresh1} 185b8851fccSafresh1 186b8851fccSafresh1sub passive { 187b8851fccSafresh1 my $ftp = shift; 188b8851fccSafresh1 return ${*$ftp}{'net_ftp_passive'} unless @_; 189b8851fccSafresh1 ${*$ftp}{'net_ftp_passive'} = shift; 190b8851fccSafresh1} 191b8851fccSafresh1 192b8851fccSafresh1 193b8851fccSafresh1sub hash { 194b8851fccSafresh1 my $ftp = shift; # self 195b8851fccSafresh1 196b8851fccSafresh1 my ($h, $b) = @_; 197b8851fccSafresh1 unless ($h) { 198b8851fccSafresh1 delete ${*$ftp}{'net_ftp_hash'}; 199b8851fccSafresh1 return [\*STDERR, 0]; 200b8851fccSafresh1 } 201b8851fccSafresh1 ($h, $b) = (ref($h) ? $h : \*STDERR, $b || 1024); 202b8851fccSafresh1 select((select($h), $| = 1)[0]); 203b8851fccSafresh1 $b = 512 if $b < 512; 204b8851fccSafresh1 ${*$ftp}{'net_ftp_hash'} = [$h, $b]; 205b8851fccSafresh1} 206b8851fccSafresh1 207b8851fccSafresh1 208b8851fccSafresh1sub quit { 209b8851fccSafresh1 my $ftp = shift; 210b8851fccSafresh1 211b8851fccSafresh1 $ftp->_QUIT; 212b8851fccSafresh1 $ftp->close; 213b8851fccSafresh1} 214b8851fccSafresh1 215b8851fccSafresh1 216b8851fccSafresh1sub DESTROY { } 217b8851fccSafresh1 218b8851fccSafresh1 219b8851fccSafresh1sub ascii { shift->type('A', @_); } 220b8851fccSafresh1sub binary { shift->type('I', @_); } 221b8851fccSafresh1 222b8851fccSafresh1 223b8851fccSafresh1sub ebcdic { 224b8851fccSafresh1 carp "TYPE E is unsupported, shall default to I"; 225b8851fccSafresh1 shift->type('E', @_); 226b8851fccSafresh1} 227b8851fccSafresh1 228b8851fccSafresh1 229b8851fccSafresh1sub byte { 230b8851fccSafresh1 carp "TYPE L is unsupported, shall default to I"; 231b8851fccSafresh1 shift->type('L', @_); 232b8851fccSafresh1} 233b8851fccSafresh1 234b8851fccSafresh1# Allow the user to send a command directly, BE CAREFUL !! 235b8851fccSafresh1 236b8851fccSafresh1 237b8851fccSafresh1sub quot { 238b8851fccSafresh1 my $ftp = shift; 239b8851fccSafresh1 my $cmd = shift; 240b8851fccSafresh1 241b8851fccSafresh1 $ftp->command(uc $cmd, @_); 242b8851fccSafresh1 $ftp->response(); 243b8851fccSafresh1} 244b8851fccSafresh1 245b8851fccSafresh1 246b8851fccSafresh1sub site { 247b8851fccSafresh1 my $ftp = shift; 248b8851fccSafresh1 249b8851fccSafresh1 $ftp->command("SITE", @_); 250b8851fccSafresh1 $ftp->response(); 251b8851fccSafresh1} 252b8851fccSafresh1 253b8851fccSafresh1 254b8851fccSafresh1sub mdtm { 255b8851fccSafresh1 my $ftp = shift; 256b8851fccSafresh1 my $file = shift; 257b8851fccSafresh1 258b8851fccSafresh1 # Server Y2K bug workaround 259b8851fccSafresh1 # 260b8851fccSafresh1 # sigh; some idiotic FTP servers use ("19%d",tm.tm_year) instead of 261b8851fccSafresh1 # ("%d",tm.tm_year+1900). This results in an extra digit in the 262b8851fccSafresh1 # string returned. To account for this we allow an optional extra 263b8851fccSafresh1 # digit in the year. Then if the first two digits are 19 we use the 264b8851fccSafresh1 # remainder, otherwise we subtract 1900 from the whole year. 265b8851fccSafresh1 266b8851fccSafresh1 $ftp->_MDTM($file) 267b8851fccSafresh1 && $ftp->message =~ /((\d\d)(\d\d\d?))(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ 268eac174f2Safresh1 ? timegm($8, $7, $6, $5, $4 - 1, $2 eq '19' ? ($3 + 1900) : $1) 269b8851fccSafresh1 : undef; 270b8851fccSafresh1} 271b8851fccSafresh1 272b8851fccSafresh1 273b8851fccSafresh1sub size { 274b8851fccSafresh1 my $ftp = shift; 275b8851fccSafresh1 my $file = shift; 276b8851fccSafresh1 my $io; 277b8851fccSafresh1 if ($ftp->supported("SIZE")) { 278b8851fccSafresh1 return $ftp->_SIZE($file) 279b8851fccSafresh1 ? ($ftp->message =~ /(\d+)\s*(bytes?\s*)?$/)[0] 280b8851fccSafresh1 : undef; 281b8851fccSafresh1 } 282b8851fccSafresh1 elsif ($ftp->supported("STAT")) { 283b8851fccSafresh1 my @msg; 284b8851fccSafresh1 return 285b8851fccSafresh1 unless $ftp->_STAT($file) && (@msg = $ftp->message) == 3; 286b8851fccSafresh1 foreach my $line (@msg) { 287b8851fccSafresh1 return (split(/\s+/, $line))[4] 288b8851fccSafresh1 if $line =~ /^[-rwxSsTt]{10}/; 289b8851fccSafresh1 } 290b8851fccSafresh1 } 291b8851fccSafresh1 else { 292b8851fccSafresh1 my @files = $ftp->dir($file); 293b8851fccSafresh1 if (@files) { 294b8851fccSafresh1 return (split(/\s+/, $1))[4] 295b8851fccSafresh1 if $files[0] =~ /^([-rwxSsTt]{10}.*)$/; 296b8851fccSafresh1 } 297b8851fccSafresh1 } 298b8851fccSafresh1 undef; 299b8851fccSafresh1} 300b8851fccSafresh1 301b8851fccSafresh1 302b8851fccSafresh1sub starttls { 303b8851fccSafresh1 my $ftp = shift; 304b8851fccSafresh1 can_ssl() or croak("IO::Socket::SSL >= 2.007 needed for SSL support"); 305b8851fccSafresh1 $ftp->is_SSL and croak("called starttls within SSL session"); 306b8851fccSafresh1 $ftp->_AUTH('TLS') == CMD_OK or return; 307b8851fccSafresh1 308b8851fccSafresh1 $ftp->connect_SSL or return; 309b8851fccSafresh1 $ftp->prot('P'); 310b8851fccSafresh1 return 1; 311b8851fccSafresh1} 312b8851fccSafresh1 313b8851fccSafresh1sub prot { 314b8851fccSafresh1 my ($ftp,$prot) = @_; 315b8851fccSafresh1 $prot eq 'C' or $prot eq 'P' or croak("prot must by C or P"); 316b8851fccSafresh1 $ftp->_PBSZ(0) or return; 317b8851fccSafresh1 $ftp->_PROT($prot) or return; 318b8851fccSafresh1 ${*$ftp}{net_ftp_tlsprot} = $prot; 319b8851fccSafresh1 return 1; 320b8851fccSafresh1} 321b8851fccSafresh1 322b8851fccSafresh1sub stoptls { 323b8851fccSafresh1 my $ftp = shift; 324b8851fccSafresh1 $ftp->is_SSL or croak("called stoptls outside SSL session"); 325b8851fccSafresh1 ${*$ftp}{net_ftp_tlsdirect} and croak("cannot stoptls direct SSL session"); 326b8851fccSafresh1 $ftp->_CCC() or return; 327b8851fccSafresh1 $ftp->stop_SSL(); 328b8851fccSafresh1 return 1; 329b8851fccSafresh1} 330b8851fccSafresh1 331b8851fccSafresh1sub login { 332b8851fccSafresh1 my ($ftp, $user, $pass, $acct) = @_; 333b8851fccSafresh1 my ($ok, $ruser, $fwtype); 334b8851fccSafresh1 335b8851fccSafresh1 unless (defined $user) { 336b8851fccSafresh1 require Net::Netrc; 337b8851fccSafresh1 338b8851fccSafresh1 my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_host'}); 339b8851fccSafresh1 340b8851fccSafresh1 ($user, $pass, $acct) = $rc->lpa() 341b8851fccSafresh1 if ($rc); 342b8851fccSafresh1 } 343b8851fccSafresh1 344b8851fccSafresh1 $user ||= "anonymous"; 345b8851fccSafresh1 $ruser = $user; 346b8851fccSafresh1 347b8851fccSafresh1 $fwtype = ${*$ftp}{'net_ftp_firewall_type'} 348b8851fccSafresh1 || $NetConfig{'ftp_firewall_type'} 349b8851fccSafresh1 || 0; 350b8851fccSafresh1 351b8851fccSafresh1 if ($fwtype && defined ${*$ftp}{'net_ftp_firewall'}) { 352b8851fccSafresh1 if ($fwtype == 1 || $fwtype == 7) { 353b8851fccSafresh1 $user .= '@' . ${*$ftp}{'net_ftp_host'}; 354b8851fccSafresh1 } 355b8851fccSafresh1 else { 356b8851fccSafresh1 require Net::Netrc; 357b8851fccSafresh1 358b8851fccSafresh1 my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}); 359b8851fccSafresh1 360b8851fccSafresh1 my ($fwuser, $fwpass, $fwacct) = $rc ? $rc->lpa() : (); 361b8851fccSafresh1 362b8851fccSafresh1 if ($fwtype == 5) { 363b8851fccSafresh1 $user = join('@', $user, $fwuser, ${*$ftp}{'net_ftp_host'}); 364b8851fccSafresh1 $pass = $pass . '@' . $fwpass; 365b8851fccSafresh1 } 366b8851fccSafresh1 else { 367b8851fccSafresh1 if ($fwtype == 2) { 368b8851fccSafresh1 $user .= '@' . ${*$ftp}{'net_ftp_host'}; 369b8851fccSafresh1 } 370b8851fccSafresh1 elsif ($fwtype == 6) { 371b8851fccSafresh1 $fwuser .= '@' . ${*$ftp}{'net_ftp_host'}; 372b8851fccSafresh1 } 373b8851fccSafresh1 374b8851fccSafresh1 $ok = $ftp->_USER($fwuser); 375b8851fccSafresh1 376b8851fccSafresh1 return 0 unless $ok == CMD_OK || $ok == CMD_MORE; 377b8851fccSafresh1 378b8851fccSafresh1 $ok = $ftp->_PASS($fwpass || ""); 379b8851fccSafresh1 380b8851fccSafresh1 return 0 unless $ok == CMD_OK || $ok == CMD_MORE; 381b8851fccSafresh1 382b8851fccSafresh1 $ok = $ftp->_ACCT($fwacct) 383b8851fccSafresh1 if defined($fwacct); 384b8851fccSafresh1 385b8851fccSafresh1 if ($fwtype == 3) { 386b8851fccSafresh1 $ok = $ftp->command("SITE", ${*$ftp}{'net_ftp_host'})->response; 387b8851fccSafresh1 } 388b8851fccSafresh1 elsif ($fwtype == 4) { 389b8851fccSafresh1 $ok = $ftp->command("OPEN", ${*$ftp}{'net_ftp_host'})->response; 390b8851fccSafresh1 } 391b8851fccSafresh1 392b8851fccSafresh1 return 0 unless $ok == CMD_OK || $ok == CMD_MORE; 393b8851fccSafresh1 } 394b8851fccSafresh1 } 395b8851fccSafresh1 } 396b8851fccSafresh1 397b8851fccSafresh1 $ok = $ftp->_USER($user); 398b8851fccSafresh1 399b8851fccSafresh1 # Some dumb firewalls don't prefix the connection messages 400b8851fccSafresh1 $ok = $ftp->response() 401b8851fccSafresh1 if ($ok == CMD_OK && $ftp->code == 220 && $user =~ /\@/); 402b8851fccSafresh1 403b8851fccSafresh1 if ($ok == CMD_MORE) { 404b8851fccSafresh1 unless (defined $pass) { 405b8851fccSafresh1 require Net::Netrc; 406b8851fccSafresh1 407b8851fccSafresh1 my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_host'}, $ruser); 408b8851fccSafresh1 409b8851fccSafresh1 ($ruser, $pass, $acct) = $rc->lpa() 410b8851fccSafresh1 if ($rc); 411b8851fccSafresh1 412b8851fccSafresh1 $pass = '-anonymous@' 413b8851fccSafresh1 if (!defined $pass && (!defined($ruser) || $ruser =~ /^anonymous/o)); 414b8851fccSafresh1 } 415b8851fccSafresh1 416b8851fccSafresh1 $ok = $ftp->_PASS($pass || ""); 417b8851fccSafresh1 } 418b8851fccSafresh1 419b8851fccSafresh1 $ok = $ftp->_ACCT($acct) 420b8851fccSafresh1 if (defined($acct) && ($ok == CMD_MORE || $ok == CMD_OK)); 421b8851fccSafresh1 422b8851fccSafresh1 if ($fwtype == 7 && $ok == CMD_OK && defined ${*$ftp}{'net_ftp_firewall'}) { 423b8851fccSafresh1 my ($f, $auth, $resp) = _auth_id($ftp); 424b8851fccSafresh1 $ftp->authorize($auth, $resp) if defined($resp); 425b8851fccSafresh1 } 426b8851fccSafresh1 427b8851fccSafresh1 $ok == CMD_OK; 428b8851fccSafresh1} 429b8851fccSafresh1 430b8851fccSafresh1 431b8851fccSafresh1sub account { 432eac174f2Safresh1 @_ == 2 or croak 'usage: $ftp->account($acct)'; 433b8851fccSafresh1 my $ftp = shift; 434b8851fccSafresh1 my $acct = shift; 435b8851fccSafresh1 $ftp->_ACCT($acct) == CMD_OK; 436b8851fccSafresh1} 437b8851fccSafresh1 438b8851fccSafresh1 439b8851fccSafresh1sub _auth_id { 440b8851fccSafresh1 my ($ftp, $auth, $resp) = @_; 441b8851fccSafresh1 442b8851fccSafresh1 unless (defined $resp) { 443b8851fccSafresh1 require Net::Netrc; 444b8851fccSafresh1 445b8851fccSafresh1 $auth ||= eval { (getpwuid($>))[0] } || $ENV{NAME}; 446b8851fccSafresh1 447b8851fccSafresh1 my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}, $auth) 448b8851fccSafresh1 || Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}); 449b8851fccSafresh1 450b8851fccSafresh1 ($auth, $resp) = $rc->lpa() 451b8851fccSafresh1 if ($rc); 452b8851fccSafresh1 } 453b8851fccSafresh1 ($ftp, $auth, $resp); 454b8851fccSafresh1} 455b8851fccSafresh1 456b8851fccSafresh1 457b8851fccSafresh1sub authorize { 458eac174f2Safresh1 @_ >= 1 || @_ <= 3 or croak 'usage: $ftp->authorize([$auth[, $resp]])'; 459b8851fccSafresh1 460b8851fccSafresh1 my ($ftp, $auth, $resp) = &_auth_id; 461b8851fccSafresh1 462b8851fccSafresh1 my $ok = $ftp->_AUTH($auth || ""); 463b8851fccSafresh1 464b8851fccSafresh1 return $ftp->_RESP($resp || "") 465b8851fccSafresh1 if ($ok == CMD_MORE); 466b8851fccSafresh1 467b8851fccSafresh1 $ok == CMD_OK; 468b8851fccSafresh1} 469b8851fccSafresh1 470b8851fccSafresh1 471b8851fccSafresh1sub rename { 472eac174f2Safresh1 @_ == 3 or croak 'usage: $ftp->rename($oldname, $newname)'; 473b8851fccSafresh1 474eac174f2Safresh1 my ($ftp, $oldname, $newname) = @_; 475b8851fccSafresh1 476eac174f2Safresh1 $ftp->_RNFR($oldname) 477eac174f2Safresh1 && $ftp->_RNTO($newname); 478b8851fccSafresh1} 479b8851fccSafresh1 480b8851fccSafresh1 481b8851fccSafresh1sub type { 482b8851fccSafresh1 my $ftp = shift; 483b8851fccSafresh1 my $type = shift; 484b8851fccSafresh1 my $oldval = ${*$ftp}{'net_ftp_type'}; 485b8851fccSafresh1 486b8851fccSafresh1 return $oldval 487b8851fccSafresh1 unless (defined $type); 488b8851fccSafresh1 489b8851fccSafresh1 return 490b8851fccSafresh1 unless ($ftp->_TYPE($type, @_)); 491b8851fccSafresh1 492b8851fccSafresh1 ${*$ftp}{'net_ftp_type'} = join(" ", $type, @_); 493b8851fccSafresh1 494b8851fccSafresh1 $oldval; 495b8851fccSafresh1} 496b8851fccSafresh1 497b8851fccSafresh1 498b8851fccSafresh1sub alloc { 499b8851fccSafresh1 my $ftp = shift; 500b8851fccSafresh1 my $size = shift; 501b8851fccSafresh1 my $oldval = ${*$ftp}{'net_ftp_allo'}; 502b8851fccSafresh1 503b8851fccSafresh1 return $oldval 504b8851fccSafresh1 unless (defined $size); 505b8851fccSafresh1 506b8851fccSafresh1 return 507b8851fccSafresh1 unless ($ftp->supported("ALLO") and $ftp->_ALLO($size, @_)); 508b8851fccSafresh1 509b8851fccSafresh1 ${*$ftp}{'net_ftp_allo'} = join(" ", $size, @_); 510b8851fccSafresh1 511b8851fccSafresh1 $oldval; 512b8851fccSafresh1} 513b8851fccSafresh1 514b8851fccSafresh1 515b8851fccSafresh1sub abort { 516b8851fccSafresh1 my $ftp = shift; 517b8851fccSafresh1 518b8851fccSafresh1 send($ftp, pack("CCC", TELNET_IAC, TELNET_IP, TELNET_IAC), MSG_OOB); 519b8851fccSafresh1 520b8851fccSafresh1 $ftp->command(pack("C", TELNET_DM) . "ABOR"); 521b8851fccSafresh1 522b8851fccSafresh1 ${*$ftp}{'net_ftp_dataconn'}->close() 523b8851fccSafresh1 if defined ${*$ftp}{'net_ftp_dataconn'}; 524b8851fccSafresh1 525b8851fccSafresh1 $ftp->response(); 526b8851fccSafresh1 527b8851fccSafresh1 $ftp->status == CMD_OK; 528b8851fccSafresh1} 529b8851fccSafresh1 530b8851fccSafresh1 531b8851fccSafresh1sub get { 532b8851fccSafresh1 my ($ftp, $remote, $local, $where) = @_; 533b8851fccSafresh1 534b8851fccSafresh1 my ($loc, $len, $buf, $resp, $data); 535b8851fccSafresh1 local *FD; 536b8851fccSafresh1 537b8851fccSafresh1 my $localfd = ref($local) || ref(\$local) eq "GLOB"; 538b8851fccSafresh1 539b8851fccSafresh1 ($local = $remote) =~ s#^.*/## 540b8851fccSafresh1 unless (defined $local); 541b8851fccSafresh1 542b8851fccSafresh1 croak("Bad remote filename '$remote'\n") 543b8851fccSafresh1 if $remote =~ /[\r\n]/s; 544b8851fccSafresh1 545b8851fccSafresh1 ${*$ftp}{'net_ftp_rest'} = $where if defined $where; 546b8851fccSafresh1 my $rest = ${*$ftp}{'net_ftp_rest'}; 547b8851fccSafresh1 548b8851fccSafresh1 delete ${*$ftp}{'net_ftp_port'}; 549b8851fccSafresh1 delete ${*$ftp}{'net_ftp_pasv'}; 550b8851fccSafresh1 551b8851fccSafresh1 $data = $ftp->retr($remote) 552b8851fccSafresh1 or return; 553b8851fccSafresh1 554b8851fccSafresh1 if ($localfd) { 555b8851fccSafresh1 $loc = $local; 556b8851fccSafresh1 } 557b8851fccSafresh1 else { 558b8851fccSafresh1 $loc = \*FD; 559b8851fccSafresh1 560b8851fccSafresh1 unless (sysopen($loc, $local, O_CREAT | O_WRONLY | ($rest ? O_APPEND: O_TRUNC))) { 561b8851fccSafresh1 carp "Cannot open Local file $local: $!\n"; 562b8851fccSafresh1 $data->abort; 563b8851fccSafresh1 return; 564b8851fccSafresh1 } 565b8851fccSafresh1 } 566b8851fccSafresh1 567b8851fccSafresh1 if ($ftp->type eq 'I' && !binmode($loc)) { 568b8851fccSafresh1 carp "Cannot binmode Local file $local: $!\n"; 569b8851fccSafresh1 $data->abort; 570b8851fccSafresh1 close($loc) unless $localfd; 571b8851fccSafresh1 return; 572b8851fccSafresh1 } 573b8851fccSafresh1 574b8851fccSafresh1 $buf = ''; 575b8851fccSafresh1 my ($count, $hashh, $hashb, $ref) = (0); 576b8851fccSafresh1 577b8851fccSafresh1 ($hashh, $hashb) = @$ref 578b8851fccSafresh1 if ($ref = ${*$ftp}{'net_ftp_hash'}); 579b8851fccSafresh1 580b8851fccSafresh1 my $blksize = ${*$ftp}{'net_ftp_blksize'}; 581b8851fccSafresh1 local $\; # Just in case 582b8851fccSafresh1 583b8851fccSafresh1 while (1) { 584b8851fccSafresh1 last unless $len = $data->read($buf, $blksize); 585b8851fccSafresh1 586b8851fccSafresh1 if (EBCDIC && $ftp->type ne 'I') { 587b8851fccSafresh1 $buf = $ftp->toebcdic($buf); 588b8851fccSafresh1 $len = length($buf); 589b8851fccSafresh1 } 590b8851fccSafresh1 591b8851fccSafresh1 if ($hashh) { 592b8851fccSafresh1 $count += $len; 593b8851fccSafresh1 print $hashh "#" x (int($count / $hashb)); 594b8851fccSafresh1 $count %= $hashb; 595b8851fccSafresh1 } 596b8851fccSafresh1 unless (print $loc $buf) { 597b8851fccSafresh1 carp "Cannot write to Local file $local: $!\n"; 598b8851fccSafresh1 $data->abort; 599b8851fccSafresh1 close($loc) 600b8851fccSafresh1 unless $localfd; 601b8851fccSafresh1 return; 602b8851fccSafresh1 } 603b8851fccSafresh1 } 604b8851fccSafresh1 605b8851fccSafresh1 print $hashh "\n" if $hashh; 606b8851fccSafresh1 607b8851fccSafresh1 unless ($localfd) { 608b8851fccSafresh1 unless (close($loc)) { 609b8851fccSafresh1 carp "Cannot close file $local (perhaps disk space) $!\n"; 610b8851fccSafresh1 return; 611b8851fccSafresh1 } 612b8851fccSafresh1 } 613b8851fccSafresh1 614b8851fccSafresh1 unless ($data->close()) # implied $ftp->response 615b8851fccSafresh1 { 616b8851fccSafresh1 carp "Unable to close datastream"; 617b8851fccSafresh1 return; 618b8851fccSafresh1 } 619b8851fccSafresh1 620b8851fccSafresh1 return $local; 621b8851fccSafresh1} 622b8851fccSafresh1 623b8851fccSafresh1 624b8851fccSafresh1sub cwd { 625eac174f2Safresh1 @_ == 1 || @_ == 2 or croak 'usage: $ftp->cwd([$dir])'; 626b8851fccSafresh1 627b8851fccSafresh1 my ($ftp, $dir) = @_; 628b8851fccSafresh1 629b8851fccSafresh1 $dir = "/" unless defined($dir) && $dir =~ /\S/; 630b8851fccSafresh1 631b8851fccSafresh1 $dir eq ".." 632b8851fccSafresh1 ? $ftp->_CDUP() 633b8851fccSafresh1 : $ftp->_CWD($dir); 634b8851fccSafresh1} 635b8851fccSafresh1 636b8851fccSafresh1 637b8851fccSafresh1sub cdup { 638b8851fccSafresh1 @_ == 1 or croak 'usage: $ftp->cdup()'; 639b8851fccSafresh1 $_[0]->_CDUP; 640b8851fccSafresh1} 641b8851fccSafresh1 642b8851fccSafresh1 643b8851fccSafresh1sub pwd { 644b8851fccSafresh1 @_ == 1 || croak 'usage: $ftp->pwd()'; 645b8851fccSafresh1 my $ftp = shift; 646b8851fccSafresh1 647b8851fccSafresh1 $ftp->_PWD(); 648b8851fccSafresh1 $ftp->_extract_path; 649b8851fccSafresh1} 650b8851fccSafresh1 651b8851fccSafresh1# rmdir( $ftp, $dir, [ $recurse ] ) 652b8851fccSafresh1# 653b8851fccSafresh1# Removes $dir on remote host via FTP. 654b8851fccSafresh1# $ftp is handle for remote host 655b8851fccSafresh1# 656b8851fccSafresh1# If $recurse is TRUE, the directory and deleted recursively. 657b8851fccSafresh1# This means all of its contents and subdirectories. 658b8851fccSafresh1# 659b8851fccSafresh1# Initial version contributed by Dinkum Software 660b8851fccSafresh1# 661b8851fccSafresh1sub rmdir { 662eac174f2Safresh1 @_ == 2 || @_ == 3 or croak('usage: $ftp->rmdir($dir[, $recurse])'); 663b8851fccSafresh1 664b8851fccSafresh1 # Pick off the args 665b8851fccSafresh1 my ($ftp, $dir, $recurse) = @_; 666b8851fccSafresh1 my $ok; 667b8851fccSafresh1 668b8851fccSafresh1 return $ok 669b8851fccSafresh1 if $ok = $ftp->_RMD($dir) 670b8851fccSafresh1 or !$recurse; 671b8851fccSafresh1 672b8851fccSafresh1 # Try to delete the contents 673b8851fccSafresh1 # Get a list of all the files in the directory, excluding the current and parent directories 6745759b3d2Safresh1 my @filelist = map { /^(?:\S+;)+ (.+)$/ ? ($1) : () } grep { !/^(?:\S+;)*type=[cp]dir;/i } $ftp->_list_cmd("MLSD", $dir); 675b8851fccSafresh1 676b8851fccSafresh1 # Fallback to using the less well-defined NLST command if MLSD fails 677b8851fccSafresh1 @filelist = grep { !/^\.{1,2}$/ } $ftp->ls($dir) 678b8851fccSafresh1 unless @filelist; 679b8851fccSafresh1 680b8851fccSafresh1 return 681b8851fccSafresh1 unless @filelist; # failed, it is probably not a directory 682b8851fccSafresh1 683b8851fccSafresh1 return $ftp->delete($dir) 684b8851fccSafresh1 if @filelist == 1 and $dir eq $filelist[0]; 685b8851fccSafresh1 686b8851fccSafresh1 # Go thru and delete each file or the directory 687b8851fccSafresh1 foreach my $file (map { m,/, ? $_ : "$dir/$_" } @filelist) { 688b8851fccSafresh1 next # successfully deleted the file 689b8851fccSafresh1 if $ftp->delete($file); 690b8851fccSafresh1 691b8851fccSafresh1 # Failed to delete it, assume its a directory 692b8851fccSafresh1 # Recurse and ignore errors, the final rmdir() will 693b8851fccSafresh1 # fail on any errors here 694b8851fccSafresh1 return $ok 695b8851fccSafresh1 unless $ok = $ftp->rmdir($file, 1); 696b8851fccSafresh1 } 697b8851fccSafresh1 698b8851fccSafresh1 # Directory should be empty 699b8851fccSafresh1 # Try to remove the directory again 700b8851fccSafresh1 # Pass results directly to caller 701b8851fccSafresh1 # If any of the prior deletes failed, this 702b8851fccSafresh1 # rmdir() will fail because directory is not empty 703b8851fccSafresh1 return $ftp->_RMD($dir); 704b8851fccSafresh1} 705b8851fccSafresh1 706b8851fccSafresh1 707b8851fccSafresh1sub restart { 708eac174f2Safresh1 @_ == 2 || croak 'usage: $ftp->restart($where)'; 709b8851fccSafresh1 710b8851fccSafresh1 my ($ftp, $where) = @_; 711b8851fccSafresh1 712b8851fccSafresh1 ${*$ftp}{'net_ftp_rest'} = $where; 713b8851fccSafresh1 714b8851fccSafresh1 return; 715b8851fccSafresh1} 716b8851fccSafresh1 717b8851fccSafresh1 718b8851fccSafresh1sub mkdir { 719eac174f2Safresh1 @_ == 2 || @_ == 3 or croak 'usage: $ftp->mkdir($dir[, $recurse])'; 720b8851fccSafresh1 721b8851fccSafresh1 my ($ftp, $dir, $recurse) = @_; 722b8851fccSafresh1 723b8851fccSafresh1 $ftp->_MKD($dir) || $recurse 724b8851fccSafresh1 or return; 725b8851fccSafresh1 726b8851fccSafresh1 my $path = $dir; 727b8851fccSafresh1 728b8851fccSafresh1 unless ($ftp->ok) { 729b8851fccSafresh1 my @path = split(m#(?=/+)#, $dir); 730b8851fccSafresh1 731b8851fccSafresh1 $path = ""; 732b8851fccSafresh1 733b8851fccSafresh1 while (@path) { 734b8851fccSafresh1 $path .= shift @path; 735b8851fccSafresh1 736b8851fccSafresh1 $ftp->_MKD($path); 737b8851fccSafresh1 738b8851fccSafresh1 $path = $ftp->_extract_path($path); 739b8851fccSafresh1 } 740b8851fccSafresh1 741b8851fccSafresh1 # If the creation of the last element was not successful, see if we 742b8851fccSafresh1 # can cd to it, if so then return path 743b8851fccSafresh1 744b8851fccSafresh1 unless ($ftp->ok) { 745b8851fccSafresh1 my ($status, $message) = ($ftp->status, $ftp->message); 746b8851fccSafresh1 my $pwd = $ftp->pwd; 747b8851fccSafresh1 748b8851fccSafresh1 if ($pwd && $ftp->cwd($dir)) { 749b8851fccSafresh1 $path = $dir; 750b8851fccSafresh1 $ftp->cwd($pwd); 751b8851fccSafresh1 } 752b8851fccSafresh1 else { 753b8851fccSafresh1 undef $path; 754b8851fccSafresh1 } 755b8851fccSafresh1 $ftp->set_status($status, $message); 756b8851fccSafresh1 } 757b8851fccSafresh1 } 758b8851fccSafresh1 759b8851fccSafresh1 $path; 760b8851fccSafresh1} 761b8851fccSafresh1 762b8851fccSafresh1 763b8851fccSafresh1sub delete { 764eac174f2Safresh1 @_ == 2 || croak 'usage: $ftp->delete($filename)'; 765b8851fccSafresh1 766b8851fccSafresh1 $_[0]->_DELE($_[1]); 767b8851fccSafresh1} 768b8851fccSafresh1 769b8851fccSafresh1 770b8851fccSafresh1sub put { shift->_store_cmd("stor", @_) } 771b8851fccSafresh1sub put_unique { shift->_store_cmd("stou", @_) } 772b8851fccSafresh1sub append { shift->_store_cmd("appe", @_) } 773b8851fccSafresh1 774b8851fccSafresh1 775b8851fccSafresh1sub nlst { shift->_data_cmd("NLST", @_) } 776b8851fccSafresh1sub list { shift->_data_cmd("LIST", @_) } 777b8851fccSafresh1sub retr { shift->_data_cmd("RETR", @_) } 778b8851fccSafresh1sub stor { shift->_data_cmd("STOR", @_) } 779b8851fccSafresh1sub stou { shift->_data_cmd("STOU", @_) } 780b8851fccSafresh1sub appe { shift->_data_cmd("APPE", @_) } 781b8851fccSafresh1 782b8851fccSafresh1 783b8851fccSafresh1sub _store_cmd { 784b8851fccSafresh1 my ($ftp, $cmd, $local, $remote) = @_; 785b8851fccSafresh1 my ($loc, $sock, $len, $buf); 786b8851fccSafresh1 local *FD; 787b8851fccSafresh1 788b8851fccSafresh1 my $localfd = ref($local) || ref(\$local) eq "GLOB"; 789b8851fccSafresh1 790b8851fccSafresh1 if (!defined($remote) and 'STOU' ne uc($cmd)) { 791b8851fccSafresh1 croak 'Must specify remote filename with stream input' 792b8851fccSafresh1 if $localfd; 793b8851fccSafresh1 794b8851fccSafresh1 require File::Basename; 795b8851fccSafresh1 $remote = File::Basename::basename($local); 796b8851fccSafresh1 } 797b8851fccSafresh1 if (defined ${*$ftp}{'net_ftp_allo'}) { 798b8851fccSafresh1 delete ${*$ftp}{'net_ftp_allo'}; 799b8851fccSafresh1 } 800b8851fccSafresh1 else { 801b8851fccSafresh1 802b8851fccSafresh1 # if the user hasn't already invoked the alloc method since the last 803b8851fccSafresh1 # _store_cmd call, figure out if the local file is a regular file(not 804b8851fccSafresh1 # a pipe, or device) and if so get the file size from stat, and send 805b8851fccSafresh1 # an ALLO command before sending the STOR, STOU, or APPE command. 806b8851fccSafresh1 my $size = do { local $^W; -f $local && -s _ }; # no ALLO if sending data from a pipe 807b8851fccSafresh1 ${*$ftp}{'net_ftp_allo'} = $size if $size; 808b8851fccSafresh1 } 809b8851fccSafresh1 croak("Bad remote filename '$remote'\n") 810b8851fccSafresh1 if defined($remote) and $remote =~ /[\r\n]/s; 811b8851fccSafresh1 812b8851fccSafresh1 if ($localfd) { 813b8851fccSafresh1 $loc = $local; 814b8851fccSafresh1 } 815b8851fccSafresh1 else { 816b8851fccSafresh1 $loc = \*FD; 817b8851fccSafresh1 818b8851fccSafresh1 unless (sysopen($loc, $local, O_RDONLY)) { 819b8851fccSafresh1 carp "Cannot open Local file $local: $!\n"; 820b8851fccSafresh1 return; 821b8851fccSafresh1 } 822b8851fccSafresh1 } 823b8851fccSafresh1 824b8851fccSafresh1 if ($ftp->type eq 'I' && !binmode($loc)) { 825b8851fccSafresh1 carp "Cannot binmode Local file $local: $!\n"; 826b8851fccSafresh1 return; 827b8851fccSafresh1 } 828b8851fccSafresh1 829b8851fccSafresh1 delete ${*$ftp}{'net_ftp_port'}; 830b8851fccSafresh1 delete ${*$ftp}{'net_ftp_pasv'}; 831b8851fccSafresh1 832b8851fccSafresh1 $sock = $ftp->_data_cmd($cmd, grep { defined } $remote) 833b8851fccSafresh1 or return; 834b8851fccSafresh1 835b8851fccSafresh1 $remote = ($ftp->message =~ /\w+\s*:\s*(.*)/)[0] 836b8851fccSafresh1 if 'STOU' eq uc $cmd; 837b8851fccSafresh1 838b8851fccSafresh1 my $blksize = ${*$ftp}{'net_ftp_blksize'}; 839b8851fccSafresh1 840b8851fccSafresh1 my ($count, $hashh, $hashb, $ref) = (0); 841b8851fccSafresh1 842b8851fccSafresh1 ($hashh, $hashb) = @$ref 843b8851fccSafresh1 if ($ref = ${*$ftp}{'net_ftp_hash'}); 844b8851fccSafresh1 845b8851fccSafresh1 while (1) { 846b8851fccSafresh1 last unless $len = read($loc, $buf = "", $blksize); 847b8851fccSafresh1 848b8851fccSafresh1 if (EBCDIC && $ftp->type ne 'I') { 849b8851fccSafresh1 $buf = $ftp->toascii($buf); 850b8851fccSafresh1 $len = length($buf); 851b8851fccSafresh1 } 852b8851fccSafresh1 853b8851fccSafresh1 if ($hashh) { 854b8851fccSafresh1 $count += $len; 855b8851fccSafresh1 print $hashh "#" x (int($count / $hashb)); 856b8851fccSafresh1 $count %= $hashb; 857b8851fccSafresh1 } 858b8851fccSafresh1 859b8851fccSafresh1 my $wlen; 860b8851fccSafresh1 unless (defined($wlen = $sock->write($buf, $len)) && $wlen == $len) { 861b8851fccSafresh1 $sock->abort; 862b8851fccSafresh1 close($loc) 863b8851fccSafresh1 unless $localfd; 864b8851fccSafresh1 print $hashh "\n" if $hashh; 865b8851fccSafresh1 return; 866b8851fccSafresh1 } 867b8851fccSafresh1 } 868b8851fccSafresh1 869b8851fccSafresh1 print $hashh "\n" if $hashh; 870b8851fccSafresh1 871b8851fccSafresh1 close($loc) 872b8851fccSafresh1 unless $localfd; 873b8851fccSafresh1 874b8851fccSafresh1 $sock->close() 875b8851fccSafresh1 or return; 876b8851fccSafresh1 877b8851fccSafresh1 if ('STOU' eq uc $cmd and $ftp->message =~ m/unique\s+file\s*name\s*:\s*(.*)\)|"(.*)"/) { 878b8851fccSafresh1 require File::Basename; 879b8851fccSafresh1 $remote = File::Basename::basename($+); 880b8851fccSafresh1 } 881b8851fccSafresh1 882b8851fccSafresh1 return $remote; 883b8851fccSafresh1} 884b8851fccSafresh1 885b8851fccSafresh1 886b8851fccSafresh1sub port { 887eac174f2Safresh1 @_ == 1 || @_ == 2 or croak 'usage: $self->port([$port])'; 888b8851fccSafresh1 return _eprt('PORT',@_); 889b8851fccSafresh1} 890b8851fccSafresh1 891b8851fccSafresh1sub eprt { 892eac174f2Safresh1 @_ == 1 || @_ == 2 or croak 'usage: $self->eprt([$port])'; 893b8851fccSafresh1 return _eprt('EPRT',@_); 894b8851fccSafresh1} 895b8851fccSafresh1 896b8851fccSafresh1sub _eprt { 897b8851fccSafresh1 my ($cmd,$ftp,$port) = @_; 898b8851fccSafresh1 delete ${*$ftp}{net_ftp_intern_port}; 899b8851fccSafresh1 unless ($port) { 900b8851fccSafresh1 my $listen = ${*$ftp}{net_ftp_listen} ||= $IOCLASS->new( 901b8851fccSafresh1 Listen => 1, 902b8851fccSafresh1 Timeout => $ftp->timeout, 903b8851fccSafresh1 LocalAddr => $ftp->sockhost, 904b8851fccSafresh1 $family_key => $ftp->sockdomain, 905b8851fccSafresh1 can_ssl() ? ( 906b8851fccSafresh1 %{ ${*$ftp}{net_ftp_tlsargs} }, 907b8851fccSafresh1 SSL_startHandshake => 0, 908b8851fccSafresh1 ):(), 909b8851fccSafresh1 ); 910b8851fccSafresh1 ${*$ftp}{net_ftp_intern_port} = 1; 911b8851fccSafresh1 my $fam = ($listen->sockdomain == AF_INET) ? 1:2; 912b8851fccSafresh1 if ( $cmd eq 'EPRT' || $fam == 2 ) { 913b8851fccSafresh1 $port = "|$fam|".$listen->sockhost."|".$listen->sockport."|"; 914b8851fccSafresh1 $cmd = 'EPRT'; 915b8851fccSafresh1 } else { 916b8851fccSafresh1 my $p = $listen->sockport; 917b8851fccSafresh1 $port = join(',',split(m{\.},$listen->sockhost),$p >> 8,$p & 0xff); 918b8851fccSafresh1 } 919b8851fccSafresh1 } elsif (ref($port) eq 'ARRAY') { 920b8851fccSafresh1 $port = join(',',split(m{\.},@$port[0]),@$port[1] >> 8,@$port[1] & 0xff); 921b8851fccSafresh1 } 922b8851fccSafresh1 my $ok = $cmd eq 'EPRT' ? $ftp->_EPRT($port) : $ftp->_PORT($port); 923b8851fccSafresh1 ${*$ftp}{net_ftp_port} = $port if $ok; 924b8851fccSafresh1 return $ok; 925b8851fccSafresh1} 926b8851fccSafresh1 927b8851fccSafresh1 928b8851fccSafresh1sub ls { shift->_list_cmd("NLST", @_); } 929b8851fccSafresh1sub dir { shift->_list_cmd("LIST", @_); } 930b8851fccSafresh1 931b8851fccSafresh1 932b8851fccSafresh1sub pasv { 933b8851fccSafresh1 my $ftp = shift; 934b8851fccSafresh1 @_ and croak 'usage: $ftp->port()'; 935b8851fccSafresh1 return $ftp->epsv if $ftp->sockdomain != AF_INET; 936b8851fccSafresh1 delete ${*$ftp}{net_ftp_intern_port}; 937b8851fccSafresh1 938b8851fccSafresh1 if ( $ftp->_PASV && 939b8851fccSafresh1 $ftp->message =~ m{(\d+,\d+,\d+,\d+),(\d+),(\d+)} ) { 940b8851fccSafresh1 my $port = 256 * $2 + $3; 941b8851fccSafresh1 ( my $ip = $1 ) =~s{,}{.}g; 942b8851fccSafresh1 return ${*$ftp}{net_ftp_pasv} = [ $ip,$port ]; 943b8851fccSafresh1 } 944b8851fccSafresh1 return; 945b8851fccSafresh1} 946b8851fccSafresh1 947b8851fccSafresh1sub epsv { 948b8851fccSafresh1 my $ftp = shift; 949b8851fccSafresh1 @_ and croak 'usage: $ftp->epsv()'; 950b8851fccSafresh1 delete ${*$ftp}{net_ftp_intern_port}; 951b8851fccSafresh1 952b8851fccSafresh1 $ftp->_EPSV && $ftp->message =~ m{\(([\x33-\x7e])\1\1(\d+)\1\)} 953b8851fccSafresh1 ? ${*$ftp}{net_ftp_pasv} = [ $ftp->peerhost, $2 ] 954b8851fccSafresh1 : undef; 955b8851fccSafresh1} 956b8851fccSafresh1 957b8851fccSafresh1 958b8851fccSafresh1sub unique_name { 959b8851fccSafresh1 my $ftp = shift; 960b8851fccSafresh1 ${*$ftp}{'net_ftp_unique'} || undef; 961b8851fccSafresh1} 962b8851fccSafresh1 963b8851fccSafresh1 964b8851fccSafresh1sub supported { 965eac174f2Safresh1 @_ == 2 or croak 'usage: $ftp->supported($cmd)'; 966b8851fccSafresh1 my $ftp = shift; 967b8851fccSafresh1 my $cmd = uc shift; 968b8851fccSafresh1 my $hash = ${*$ftp}{'net_ftp_supported'} ||= {}; 969b8851fccSafresh1 970b8851fccSafresh1 return $hash->{$cmd} 971b8851fccSafresh1 if exists $hash->{$cmd}; 972b8851fccSafresh1 973b8851fccSafresh1 return $hash->{$cmd} = 1 974b8851fccSafresh1 if $ftp->feature($cmd); 975b8851fccSafresh1 976b8851fccSafresh1 return $hash->{$cmd} = 0 977b8851fccSafresh1 unless $ftp->_HELP($cmd); 978b8851fccSafresh1 979b8851fccSafresh1 my $text = $ftp->message; 980b8851fccSafresh1 if ($text =~ /following.+commands/i) { 981b8851fccSafresh1 $text =~ s/^.*\n//; 982b8851fccSafresh1 while ($text =~ /(\*?)(\w+)(\*?)/sg) { 983b8851fccSafresh1 $hash->{"\U$2"} = !length("$1$3"); 984b8851fccSafresh1 } 985b8851fccSafresh1 } 986b8851fccSafresh1 else { 987b8851fccSafresh1 $hash->{$cmd} = $text !~ /unimplemented/i; 988b8851fccSafresh1 } 989b8851fccSafresh1 990b8851fccSafresh1 $hash->{$cmd} ||= 0; 991b8851fccSafresh1} 992b8851fccSafresh1 993b8851fccSafresh1## 994b8851fccSafresh1## Deprecated methods 995b8851fccSafresh1## 996b8851fccSafresh1 997b8851fccSafresh1 998b8851fccSafresh1sub lsl { 999b8851fccSafresh1 carp "Use of Net::FTP::lsl deprecated, use 'dir'" 1000b8851fccSafresh1 if $^W; 1001b8851fccSafresh1 goto &dir; 1002b8851fccSafresh1} 1003b8851fccSafresh1 1004b8851fccSafresh1 1005b8851fccSafresh1sub authorise { 1006b8851fccSafresh1 carp "Use of Net::FTP::authorise deprecated, use 'authorize'" 1007b8851fccSafresh1 if $^W; 1008b8851fccSafresh1 goto &authorize; 1009b8851fccSafresh1} 1010b8851fccSafresh1 1011b8851fccSafresh1 1012b8851fccSafresh1## 1013b8851fccSafresh1## Private methods 1014b8851fccSafresh1## 1015b8851fccSafresh1 1016b8851fccSafresh1 1017b8851fccSafresh1sub _extract_path { 1018b8851fccSafresh1 my ($ftp, $path) = @_; 1019b8851fccSafresh1 1020b8851fccSafresh1 # This tries to work both with and without the quote doubling 1021b8851fccSafresh1 # convention (RFC 959 requires it, but the first 3 servers I checked 1022b8851fccSafresh1 # didn't implement it). It will fail on a server which uses a quote in 1023b8851fccSafresh1 # the message which isn't a part of or surrounding the path. 1024b8851fccSafresh1 $ftp->ok 1025b8851fccSafresh1 && $ftp->message =~ /(?:^|\s)\"(.*)\"(?:$|\s)/ 1026b8851fccSafresh1 && ($path = $1) =~ s/\"\"/\"/g; 1027b8851fccSafresh1 1028b8851fccSafresh1 $path; 1029b8851fccSafresh1} 1030b8851fccSafresh1 1031b8851fccSafresh1## 1032b8851fccSafresh1## Communication methods 1033b8851fccSafresh1## 1034b8851fccSafresh1 1035b8851fccSafresh1 1036b8851fccSafresh1sub _dataconn { 1037b8851fccSafresh1 my $ftp = shift; 1038b8851fccSafresh1 my $pkg = "Net::FTP::" . $ftp->type; 1039b8851fccSafresh1 eval "require " . $pkg ## no critic (BuiltinFunctions::ProhibitStringyEval) 1040b8851fccSafresh1 or croak("cannot load $pkg required for type ".$ftp->type); 1041b8851fccSafresh1 $pkg =~ s/ /_/g; 1042b8851fccSafresh1 delete ${*$ftp}{net_ftp_dataconn}; 1043b8851fccSafresh1 1044b8851fccSafresh1 my $conn; 1045b8851fccSafresh1 my $pasv = ${*$ftp}{net_ftp_pasv}; 1046b8851fccSafresh1 if ($pasv) { 1047b8851fccSafresh1 $conn = $pkg->new( 1048b8851fccSafresh1 PeerAddr => $pasv->[0], 1049b8851fccSafresh1 PeerPort => $pasv->[1], 1050b8851fccSafresh1 LocalAddr => ${*$ftp}{net_ftp_localaddr}, 1051b8851fccSafresh1 $family_key => ${*$ftp}{net_ftp_domain}, 1052b8851fccSafresh1 Timeout => $ftp->timeout, 1053b8851fccSafresh1 can_ssl() ? ( 1054b8851fccSafresh1 SSL_startHandshake => 0, 1055*e0680481Safresh1 %{${*$ftp}{net_ftp_tlsargs}}, 1056b8851fccSafresh1 ):(), 1057b8851fccSafresh1 ) or return; 1058b8851fccSafresh1 } elsif (my $listen = delete ${*$ftp}{net_ftp_listen}) { 1059b8851fccSafresh1 $conn = $listen->accept($pkg) or return; 1060b8851fccSafresh1 $conn->timeout($ftp->timeout); 1061b8851fccSafresh1 close($listen); 1062b8851fccSafresh1 } else { 1063b8851fccSafresh1 croak("no listener in active mode"); 1064b8851fccSafresh1 } 1065b8851fccSafresh1 1066b8851fccSafresh1 if (( ${*$ftp}{net_ftp_tlsprot} || '') eq 'P') { 1067b8851fccSafresh1 if ($conn->connect_SSL) { 1068b8851fccSafresh1 # SSL handshake ok 1069b8851fccSafresh1 } else { 1070b8851fccSafresh1 carp("failed to ssl upgrade dataconn: $IO::Socket::SSL::SSL_ERROR"); 1071b8851fccSafresh1 return; 1072b8851fccSafresh1 } 1073b8851fccSafresh1 } 1074b8851fccSafresh1 1075b8851fccSafresh1 ${*$ftp}{net_ftp_dataconn} = $conn; 1076b8851fccSafresh1 ${*$conn} = ""; 1077b8851fccSafresh1 ${*$conn}{net_ftp_cmd} = $ftp; 1078b8851fccSafresh1 ${*$conn}{net_ftp_blksize} = ${*$ftp}{net_ftp_blksize}; 1079b8851fccSafresh1 return $conn; 1080b8851fccSafresh1} 1081b8851fccSafresh1 1082b8851fccSafresh1 1083b8851fccSafresh1sub _list_cmd { 1084b8851fccSafresh1 my $ftp = shift; 1085b8851fccSafresh1 my $cmd = uc shift; 1086b8851fccSafresh1 1087b8851fccSafresh1 delete ${*$ftp}{'net_ftp_port'}; 1088b8851fccSafresh1 delete ${*$ftp}{'net_ftp_pasv'}; 1089b8851fccSafresh1 1090b8851fccSafresh1 my $data = $ftp->_data_cmd($cmd, @_); 1091b8851fccSafresh1 1092b8851fccSafresh1 return 1093b8851fccSafresh1 unless (defined $data); 1094b8851fccSafresh1 1095b8851fccSafresh1 require Net::FTP::A; 1096b8851fccSafresh1 bless $data, "Net::FTP::A"; # Force ASCII mode 1097b8851fccSafresh1 1098b8851fccSafresh1 my $databuf = ''; 1099b8851fccSafresh1 my $buf = ''; 1100b8851fccSafresh1 my $blksize = ${*$ftp}{'net_ftp_blksize'}; 1101b8851fccSafresh1 1102b8851fccSafresh1 while ($data->read($databuf, $blksize)) { 1103b8851fccSafresh1 $buf .= $databuf; 1104b8851fccSafresh1 } 1105b8851fccSafresh1 1106b8851fccSafresh1 my $list = [split(/\n/, $buf)]; 1107b8851fccSafresh1 1108b8851fccSafresh1 $data->close(); 1109b8851fccSafresh1 1110b8851fccSafresh1 if (EBCDIC) { 1111b8851fccSafresh1 for (@$list) { $_ = $ftp->toebcdic($_) } 1112b8851fccSafresh1 } 1113b8851fccSafresh1 1114b8851fccSafresh1 wantarray 1115b8851fccSafresh1 ? @{$list} 1116b8851fccSafresh1 : $list; 1117b8851fccSafresh1} 1118b8851fccSafresh1 1119b8851fccSafresh1 1120b8851fccSafresh1sub _data_cmd { 1121b8851fccSafresh1 my $ftp = shift; 1122b8851fccSafresh1 my $cmd = uc shift; 1123b8851fccSafresh1 my $ok = 1; 1124b8851fccSafresh1 my $where = delete ${*$ftp}{'net_ftp_rest'} || 0; 1125b8851fccSafresh1 my $arg; 1126b8851fccSafresh1 1127b8851fccSafresh1 for my $arg (@_) { 1128b8851fccSafresh1 croak("Bad argument '$arg'\n") 1129b8851fccSafresh1 if $arg =~ /[\r\n]/s; 1130b8851fccSafresh1 } 1131b8851fccSafresh1 1132b8851fccSafresh1 if ( ${*$ftp}{'net_ftp_passive'} 1133b8851fccSafresh1 && !defined ${*$ftp}{'net_ftp_pasv'} 1134b8851fccSafresh1 && !defined ${*$ftp}{'net_ftp_port'}) 1135b8851fccSafresh1 { 1136b8851fccSafresh1 return unless defined $ftp->pasv; 1137b8851fccSafresh1 1138b8851fccSafresh1 if ($where and !$ftp->_REST($where)) { 1139b8851fccSafresh1 my ($status, $message) = ($ftp->status, $ftp->message); 1140b8851fccSafresh1 $ftp->abort; 1141b8851fccSafresh1 $ftp->set_status($status, $message); 1142b8851fccSafresh1 return; 1143b8851fccSafresh1 } 1144b8851fccSafresh1 1145b8851fccSafresh1 # first send command, then open data connection 1146b8851fccSafresh1 # otherwise the peer might not do a full accept (with SSL 1147b8851fccSafresh1 # handshake if PROT P) 1148b8851fccSafresh1 $ftp->command($cmd, @_); 1149b8851fccSafresh1 my $data = $ftp->_dataconn(); 1150b8851fccSafresh1 if (CMD_INFO == $ftp->response()) { 1151b8851fccSafresh1 $data->reading 1152b8851fccSafresh1 if $data && $cmd =~ /RETR|LIST|NLST|MLSD/; 1153b8851fccSafresh1 return $data; 1154b8851fccSafresh1 } 1155b8851fccSafresh1 $data->_close if $data; 1156b8851fccSafresh1 1157b8851fccSafresh1 return; 1158b8851fccSafresh1 } 1159b8851fccSafresh1 1160b8851fccSafresh1 $ok = $ftp->port 1161b8851fccSafresh1 unless (defined ${*$ftp}{'net_ftp_port'} 1162b8851fccSafresh1 || defined ${*$ftp}{'net_ftp_pasv'}); 1163b8851fccSafresh1 1164b8851fccSafresh1 $ok = $ftp->_REST($where) 1165b8851fccSafresh1 if $ok && $where; 1166b8851fccSafresh1 1167b8851fccSafresh1 return 1168b8851fccSafresh1 unless $ok; 1169b8851fccSafresh1 1170b8851fccSafresh1 if ($cmd =~ /(STOR|APPE|STOU)/ and exists ${*$ftp}{net_ftp_allo} and 1171b8851fccSafresh1 $ftp->supported("ALLO")) 1172b8851fccSafresh1 { 1173b8851fccSafresh1 $ftp->_ALLO(delete ${*$ftp}{net_ftp_allo}) 1174b8851fccSafresh1 or return; 1175b8851fccSafresh1 } 1176b8851fccSafresh1 1177b8851fccSafresh1 $ftp->command($cmd, @_); 1178b8851fccSafresh1 1179b8851fccSafresh1 return 1 1180b8851fccSafresh1 if (defined ${*$ftp}{'net_ftp_pasv'}); 1181b8851fccSafresh1 1182b8851fccSafresh1 $ok = CMD_INFO == $ftp->response(); 1183b8851fccSafresh1 1184b8851fccSafresh1 return $ok 1185b8851fccSafresh1 unless exists ${*$ftp}{'net_ftp_intern_port'}; 1186b8851fccSafresh1 1187b8851fccSafresh1 if ($ok) { 1188b8851fccSafresh1 my $data = $ftp->_dataconn(); 1189b8851fccSafresh1 1190b8851fccSafresh1 $data->reading 1191b8851fccSafresh1 if $data && $cmd =~ /RETR|LIST|NLST|MLSD/; 1192b8851fccSafresh1 1193b8851fccSafresh1 return $data; 1194b8851fccSafresh1 } 1195b8851fccSafresh1 1196b8851fccSafresh1 1197b8851fccSafresh1 close(delete ${*$ftp}{'net_ftp_listen'}); 1198b8851fccSafresh1 1199b8851fccSafresh1 return; 1200b8851fccSafresh1} 1201b8851fccSafresh1 1202b8851fccSafresh1## 1203b8851fccSafresh1## Over-ride methods (Net::Cmd) 1204b8851fccSafresh1## 1205b8851fccSafresh1 1206b8851fccSafresh1 1207b8851fccSafresh1sub debug_text { $_[2] =~ /^(pass|resp|acct)/i ? "$1 ....\n" : $_[2]; } 1208b8851fccSafresh1 1209b8851fccSafresh1 1210b8851fccSafresh1sub command { 1211b8851fccSafresh1 my $ftp = shift; 1212b8851fccSafresh1 1213b8851fccSafresh1 delete ${*$ftp}{'net_ftp_port'}; 1214b8851fccSafresh1 $ftp->SUPER::command(@_); 1215b8851fccSafresh1} 1216b8851fccSafresh1 1217b8851fccSafresh1 1218b8851fccSafresh1sub response { 1219b8851fccSafresh1 my $ftp = shift; 1220b8851fccSafresh1 my $code = $ftp->SUPER::response() || 5; # assume 500 if undef 1221b8851fccSafresh1 1222b8851fccSafresh1 delete ${*$ftp}{'net_ftp_pasv'} 1223b8851fccSafresh1 if ($code != CMD_MORE && $code != CMD_INFO); 1224b8851fccSafresh1 1225b8851fccSafresh1 $code; 1226b8851fccSafresh1} 1227b8851fccSafresh1 1228b8851fccSafresh1 1229b8851fccSafresh1sub parse_response { 1230b8851fccSafresh1 return ($1, $2 eq "-") 1231b8851fccSafresh1 if $_[1] =~ s/^(\d\d\d)([- ]?)//o; 1232b8851fccSafresh1 1233b8851fccSafresh1 my $ftp = shift; 1234b8851fccSafresh1 1235b8851fccSafresh1 # Darn MS FTP server is a load of CRAP !!!! 1236b8851fccSafresh1 # Expect to see undef here. 1237b8851fccSafresh1 return () 1238b8851fccSafresh1 unless 0 + (${*$ftp}{'net_cmd_code'} || 0); 1239b8851fccSafresh1 1240b8851fccSafresh1 (${*$ftp}{'net_cmd_code'}, 1); 1241b8851fccSafresh1} 1242b8851fccSafresh1 1243b8851fccSafresh1## 1244b8851fccSafresh1## Allow 2 servers to talk directly 1245b8851fccSafresh1## 1246b8851fccSafresh1 1247b8851fccSafresh1 1248b8851fccSafresh1sub pasv_xfer_unique { 1249b8851fccSafresh1 my ($sftp, $sfile, $dftp, $dfile) = @_; 1250b8851fccSafresh1 $sftp->pasv_xfer($sfile, $dftp, $dfile, 1); 1251b8851fccSafresh1} 1252b8851fccSafresh1 1253b8851fccSafresh1 1254b8851fccSafresh1sub pasv_xfer { 1255b8851fccSafresh1 my ($sftp, $sfile, $dftp, $dfile, $unique) = @_; 1256b8851fccSafresh1 1257b8851fccSafresh1 ($dfile = $sfile) =~ s#.*/## 1258b8851fccSafresh1 unless (defined $dfile); 1259b8851fccSafresh1 1260b8851fccSafresh1 my $port = $sftp->pasv 1261b8851fccSafresh1 or return; 1262b8851fccSafresh1 1263b8851fccSafresh1 $dftp->port($port) 1264b8851fccSafresh1 or return; 1265b8851fccSafresh1 1266b8851fccSafresh1 return 1267b8851fccSafresh1 unless ($unique ? $dftp->stou($dfile) : $dftp->stor($dfile)); 1268b8851fccSafresh1 1269b8851fccSafresh1 unless ($sftp->retr($sfile) && $sftp->response == CMD_INFO) { 1270b8851fccSafresh1 $sftp->retr($sfile); 1271b8851fccSafresh1 $dftp->abort; 1272b8851fccSafresh1 $dftp->response(); 1273b8851fccSafresh1 return; 1274b8851fccSafresh1 } 1275b8851fccSafresh1 1276b8851fccSafresh1 $dftp->pasv_wait($sftp); 1277b8851fccSafresh1} 1278b8851fccSafresh1 1279b8851fccSafresh1 1280b8851fccSafresh1sub pasv_wait { 1281eac174f2Safresh1 @_ == 2 or croak 'usage: $ftp->pasv_wait($non_pasv_server)'; 1282b8851fccSafresh1 1283eac174f2Safresh1 my ($ftp, $non_pasv_server) = @_; 1284b8851fccSafresh1 my ($file, $rin, $rout); 1285b8851fccSafresh1 1286b8851fccSafresh1 vec($rin = '', fileno($ftp), 1) = 1; 1287b8851fccSafresh1 select($rout = $rin, undef, undef, undef); 1288b8851fccSafresh1 1289b8851fccSafresh1 my $dres = $ftp->response(); 1290eac174f2Safresh1 my $sres = $non_pasv_server->response(); 1291b8851fccSafresh1 1292b8851fccSafresh1 return 1293b8851fccSafresh1 unless $dres == CMD_OK && $sres == CMD_OK; 1294b8851fccSafresh1 1295b8851fccSafresh1 return 1296eac174f2Safresh1 unless $ftp->ok() && $non_pasv_server->ok(); 1297b8851fccSafresh1 1298b8851fccSafresh1 return $1 1299b8851fccSafresh1 if $ftp->message =~ /unique file name:\s*(\S*)\s*\)/; 1300b8851fccSafresh1 1301b8851fccSafresh1 return $1 1302eac174f2Safresh1 if $non_pasv_server->message =~ /unique file name:\s*(\S*)\s*\)/; 1303b8851fccSafresh1 1304b8851fccSafresh1 return 1; 1305b8851fccSafresh1} 1306b8851fccSafresh1 1307b8851fccSafresh1 1308b8851fccSafresh1sub feature { 1309eac174f2Safresh1 @_ == 2 or croak 'usage: $ftp->feature($name)'; 1310eac174f2Safresh1 my ($ftp, $name) = @_; 1311b8851fccSafresh1 1312b8851fccSafresh1 my $feature = ${*$ftp}{net_ftp_feature} ||= do { 1313b8851fccSafresh1 my @feat; 1314b8851fccSafresh1 1315b8851fccSafresh1 # Example response 1316b8851fccSafresh1 # 211-Features: 1317b8851fccSafresh1 # MDTM 1318b8851fccSafresh1 # REST STREAM 1319b8851fccSafresh1 # SIZE 1320b8851fccSafresh1 # 211 End 1321b8851fccSafresh1 1322b8851fccSafresh1 @feat = map { /^\s+(.*\S)/ } $ftp->message 1323b8851fccSafresh1 if $ftp->_FEAT; 1324b8851fccSafresh1 1325b8851fccSafresh1 \@feat; 1326b8851fccSafresh1 }; 1327b8851fccSafresh1 1328eac174f2Safresh1 return grep { /^\Q$name\E\b/i } @$feature; 1329b8851fccSafresh1} 1330b8851fccSafresh1 1331b8851fccSafresh1 1332b8851fccSafresh1sub cmd { shift->command(@_)->response() } 1333b8851fccSafresh1 1334b8851fccSafresh1######################################## 1335b8851fccSafresh1# 1336b8851fccSafresh1# RFC959 + RFC2428 + RFC4217 commands 1337b8851fccSafresh1# 1338b8851fccSafresh1 1339b8851fccSafresh1 1340b8851fccSafresh1sub _ABOR { shift->command("ABOR")->response() == CMD_OK } 1341b8851fccSafresh1sub _ALLO { shift->command("ALLO", @_)->response() == CMD_OK } 1342b8851fccSafresh1sub _CDUP { shift->command("CDUP")->response() == CMD_OK } 1343b8851fccSafresh1sub _NOOP { shift->command("NOOP")->response() == CMD_OK } 1344b8851fccSafresh1sub _PASV { shift->command("PASV")->response() == CMD_OK } 1345b8851fccSafresh1sub _QUIT { shift->command("QUIT")->response() == CMD_OK } 1346b8851fccSafresh1sub _DELE { shift->command("DELE", @_)->response() == CMD_OK } 1347b8851fccSafresh1sub _CWD { shift->command("CWD", @_)->response() == CMD_OK } 1348b8851fccSafresh1sub _PORT { shift->command("PORT", @_)->response() == CMD_OK } 1349b8851fccSafresh1sub _RMD { shift->command("RMD", @_)->response() == CMD_OK } 1350b8851fccSafresh1sub _MKD { shift->command("MKD", @_)->response() == CMD_OK } 1351b8851fccSafresh1sub _PWD { shift->command("PWD", @_)->response() == CMD_OK } 1352b8851fccSafresh1sub _TYPE { shift->command("TYPE", @_)->response() == CMD_OK } 1353b8851fccSafresh1sub _RNTO { shift->command("RNTO", @_)->response() == CMD_OK } 1354b8851fccSafresh1sub _RESP { shift->command("RESP", @_)->response() == CMD_OK } 1355b8851fccSafresh1sub _MDTM { shift->command("MDTM", @_)->response() == CMD_OK } 1356b8851fccSafresh1sub _SIZE { shift->command("SIZE", @_)->response() == CMD_OK } 1357b8851fccSafresh1sub _HELP { shift->command("HELP", @_)->response() == CMD_OK } 1358b8851fccSafresh1sub _STAT { shift->command("STAT", @_)->response() == CMD_OK } 1359b8851fccSafresh1sub _FEAT { shift->command("FEAT", @_)->response() == CMD_OK } 1360b8851fccSafresh1sub _PBSZ { shift->command("PBSZ", @_)->response() == CMD_OK } 1361b8851fccSafresh1sub _PROT { shift->command("PROT", @_)->response() == CMD_OK } 1362b8851fccSafresh1sub _CCC { shift->command("CCC", @_)->response() == CMD_OK } 1363b8851fccSafresh1sub _EPRT { shift->command("EPRT", @_)->response() == CMD_OK } 1364b8851fccSafresh1sub _EPSV { shift->command("EPSV", @_)->response() == CMD_OK } 1365b8851fccSafresh1sub _APPE { shift->command("APPE", @_)->response() == CMD_INFO } 1366b8851fccSafresh1sub _LIST { shift->command("LIST", @_)->response() == CMD_INFO } 1367b8851fccSafresh1sub _NLST { shift->command("NLST", @_)->response() == CMD_INFO } 1368b8851fccSafresh1sub _RETR { shift->command("RETR", @_)->response() == CMD_INFO } 1369b8851fccSafresh1sub _STOR { shift->command("STOR", @_)->response() == CMD_INFO } 1370b8851fccSafresh1sub _STOU { shift->command("STOU", @_)->response() == CMD_INFO } 1371b8851fccSafresh1sub _RNFR { shift->command("RNFR", @_)->response() == CMD_MORE } 1372b8851fccSafresh1sub _REST { shift->command("REST", @_)->response() == CMD_MORE } 1373b8851fccSafresh1sub _PASS { shift->command("PASS", @_)->response() } 1374b8851fccSafresh1sub _ACCT { shift->command("ACCT", @_)->response() } 1375b8851fccSafresh1sub _AUTH { shift->command("AUTH", @_)->response() } 1376b8851fccSafresh1 1377b8851fccSafresh1 1378b8851fccSafresh1sub _USER { 1379b8851fccSafresh1 my $ftp = shift; 1380b8851fccSafresh1 my $ok = $ftp->command("USER", @_)->response(); 1381b8851fccSafresh1 1382b8851fccSafresh1 # A certain brain dead firewall :-) 1383b8851fccSafresh1 $ok = $ftp->command("user", @_)->response() 1384b8851fccSafresh1 unless $ok == CMD_MORE or $ok == CMD_OK; 1385b8851fccSafresh1 1386b8851fccSafresh1 $ok; 1387b8851fccSafresh1} 1388b8851fccSafresh1 1389b8851fccSafresh1 1390b8851fccSafresh1sub _SMNT { shift->unsupported(@_) } 1391b8851fccSafresh1sub _MODE { shift->unsupported(@_) } 1392b8851fccSafresh1sub _SYST { shift->unsupported(@_) } 1393b8851fccSafresh1sub _STRU { shift->unsupported(@_) } 1394b8851fccSafresh1sub _REIN { shift->unsupported(@_) } 1395b8851fccSafresh1 1396b8851fccSafresh1 1397b8851fccSafresh11; 1398b8851fccSafresh1 1399b8851fccSafresh1__END__ 1400b8851fccSafresh1 1401b8851fccSafresh1=head1 NAME 1402b8851fccSafresh1 1403b8851fccSafresh1Net::FTP - FTP Client class 1404b8851fccSafresh1 1405b8851fccSafresh1=head1 SYNOPSIS 1406b8851fccSafresh1 1407b8851fccSafresh1 use Net::FTP; 1408b8851fccSafresh1 1409b8851fccSafresh1 $ftp = Net::FTP->new("some.host.name", Debug => 0) 1410b8851fccSafresh1 or die "Cannot connect to some.host.name: $@"; 1411b8851fccSafresh1 1412b8851fccSafresh1 $ftp->login("anonymous",'-anonymous@') 1413b8851fccSafresh1 or die "Cannot login ", $ftp->message; 1414b8851fccSafresh1 1415b8851fccSafresh1 $ftp->cwd("/pub") 1416b8851fccSafresh1 or die "Cannot change working directory ", $ftp->message; 1417b8851fccSafresh1 1418b8851fccSafresh1 $ftp->get("that.file") 1419b8851fccSafresh1 or die "get failed ", $ftp->message; 1420b8851fccSafresh1 1421b8851fccSafresh1 $ftp->quit; 1422b8851fccSafresh1 1423b8851fccSafresh1=head1 DESCRIPTION 1424b8851fccSafresh1 1425b8851fccSafresh1C<Net::FTP> is a class implementing a simple FTP client in Perl as 1426b8851fccSafresh1described in RFC959. It provides wrappers for the commonly used subset of the 1427b8851fccSafresh1RFC959 commands. 1428b8851fccSafresh1If L<IO::Socket::IP> or L<IO::Socket::INET6> is installed it also provides 1429b8851fccSafresh1support for IPv6 as defined in RFC2428. 1430b8851fccSafresh1And with L<IO::Socket::SSL> installed it provides support for implicit FTPS 1431b8851fccSafresh1and explicit FTPS as defined in RFC4217. 1432b8851fccSafresh1 1433b8851fccSafresh1The Net::FTP class is a subclass of Net::Cmd and (depending on avaibility) of 1434b8851fccSafresh1IO::Socket::IP, IO::Socket::INET6 or IO::Socket::INET. 1435b8851fccSafresh1 1436eac174f2Safresh1=head2 Overview 1437b8851fccSafresh1 1438b8851fccSafresh1FTP stands for File Transfer Protocol. It is a way of transferring 1439b8851fccSafresh1files between networked machines. The protocol defines a client 1440b8851fccSafresh1(whose commands are provided by this module) and a server (not 1441b8851fccSafresh1implemented in this module). Communication is always initiated by the 1442b8851fccSafresh1client, and the server responds with a message and a status code (and 1443b8851fccSafresh1sometimes with data). 1444b8851fccSafresh1 1445b8851fccSafresh1The FTP protocol allows files to be sent to or fetched from the 1446b8851fccSafresh1server. Each transfer involves a B<local file> (on the client) and a 1447b8851fccSafresh1B<remote file> (on the server). In this module, the same file name 1448b8851fccSafresh1will be used for both local and remote if only one is specified. This 1449b8851fccSafresh1means that transferring remote file C</path/to/file> will try to put 1450b8851fccSafresh1that file in C</path/to/file> locally, unless you specify a local file 1451b8851fccSafresh1name. 1452b8851fccSafresh1 1453b8851fccSafresh1The protocol also defines several standard B<translations> which the 1454b8851fccSafresh1file can undergo during transfer. These are ASCII, EBCDIC, binary, 1455b8851fccSafresh1and byte. ASCII is the default type, and indicates that the sender of 1456b8851fccSafresh1files will translate the ends of lines to a standard representation 1457b8851fccSafresh1which the receiver will then translate back into their local 1458b8851fccSafresh1representation. EBCDIC indicates the file being transferred is in 1459b8851fccSafresh1EBCDIC format. Binary (also known as image) format sends the data as 1460b8851fccSafresh1a contiguous bit stream. Byte format transfers the data as bytes, the 1461b8851fccSafresh1values of which remain the same regardless of differences in byte size 1462b8851fccSafresh1between the two machines (in theory - in practice you should only use 1463b8851fccSafresh1this if you really know what you're doing). This class does not support 1464b8851fccSafresh1the EBCDIC or byte formats, and will default to binary instead if they 1465b8851fccSafresh1are attempted. 1466b8851fccSafresh1 1467eac174f2Safresh1=head2 Class Methods 1468b8851fccSafresh1 1469b8851fccSafresh1=over 4 1470b8851fccSafresh1 1471eac174f2Safresh1=item C<new([$host][, %options])> 1472b8851fccSafresh1 1473eac174f2Safresh1This is the constructor for a new Net::FTP object. C<$host> is the 1474b8851fccSafresh1name of the remote host to which an FTP connection is required. 1475b8851fccSafresh1 1476eac174f2Safresh1C<$host> is optional. If C<$host> is not given then it may instead be 1477b8851fccSafresh1passed as the C<Host> option described below. 1478b8851fccSafresh1 1479eac174f2Safresh1C<%options> are passed in a hash like fashion, using key and value pairs. 1480b8851fccSafresh1Possible options are: 1481b8851fccSafresh1 1482b8851fccSafresh1B<Host> - FTP host to connect to. It may be a single scalar, as defined for 1483b8851fccSafresh1the C<PeerAddr> option in L<IO::Socket::INET>, or a reference to 1484b8851fccSafresh1an array with hosts to try in turn. The L</host> method will return the value 1485b8851fccSafresh1which was used to connect to the host. 1486b8851fccSafresh1 1487b8851fccSafresh1B<Firewall> - The name of a machine which acts as an FTP firewall. This can be 1488b8851fccSafresh1overridden by an environment variable C<FTP_FIREWALL>. If specified, and the 1489b8851fccSafresh1given host cannot be directly connected to, then the 1490b8851fccSafresh1connection is made to the firewall machine and the string C<@hostname> is 1491b8851fccSafresh1appended to the login identifier. This kind of setup is also referred to 1492b8851fccSafresh1as an ftp proxy. 1493b8851fccSafresh1 1494b8851fccSafresh1B<FirewallType> - The type of firewall running on the machine indicated by 1495b8851fccSafresh1B<Firewall>. This can be overridden by an environment variable 1496b8851fccSafresh1C<FTP_FIREWALL_TYPE>. For a list of permissible types, see the description of 1497b8851fccSafresh1ftp_firewall_type in L<Net::Config>. 1498b8851fccSafresh1 1499b8851fccSafresh1B<BlockSize> - This is the block size that Net::FTP will use when doing 1500b8851fccSafresh1transfers. (defaults to 10240) 1501b8851fccSafresh1 1502b8851fccSafresh1B<Port> - The port number to connect to on the remote machine for the 1503b8851fccSafresh1FTP connection 1504b8851fccSafresh1 1505b8851fccSafresh1B<SSL> - If the connection should be done from start with SSL, contrary to later 1506b8851fccSafresh1upgrade with C<starttls>. 1507b8851fccSafresh1 1508b8851fccSafresh1B<SSL_*> - SSL arguments which will be applied when upgrading the control or 1509b8851fccSafresh1data connection to SSL. You can use SSL arguments as documented in 1510b8851fccSafresh1L<IO::Socket::SSL>, but it will usually use the right arguments already. 1511b8851fccSafresh1 1512b8851fccSafresh1B<Timeout> - Set a timeout value in seconds (defaults to 120) 1513b8851fccSafresh1 1514b8851fccSafresh1B<Debug> - debug level (see the debug method in L<Net::Cmd>) 1515b8851fccSafresh1 1516b8851fccSafresh1B<Passive> - If set to a non-zero value then all data transfers will 1517b8851fccSafresh1be done using passive mode. If set to zero then data transfers will be 1518b8851fccSafresh1done using active mode. If the machine is connected to the Internet 1519b8851fccSafresh1directly, both passive and active mode should work equally well. 1520b8851fccSafresh1Behind most firewall and NAT configurations passive mode has a better 1521b8851fccSafresh1chance of working. However, in some rare firewall configurations, 1522b8851fccSafresh1active mode actually works when passive mode doesn't. Some really old 1523b8851fccSafresh1FTP servers might not implement passive transfers. If not specified, 1524b8851fccSafresh1then the transfer mode is set by the environment variable 1525b8851fccSafresh1C<FTP_PASSIVE> or if that one is not set by the settings done by the 1526b8851fccSafresh1F<libnetcfg> utility. If none of these apply then passive mode is 1527b8851fccSafresh1used. 1528b8851fccSafresh1 1529b8851fccSafresh1B<Hash> - If given a reference to a file handle (e.g., C<\*STDERR>), 1530b8851fccSafresh1print hash marks (#) on that filehandle every 1024 bytes. This 1531b8851fccSafresh1simply invokes the C<hash()> method for you, so that hash marks 1532b8851fccSafresh1are displayed for all transfers. You can, of course, call C<hash()> 1533b8851fccSafresh1explicitly whenever you'd like. 1534b8851fccSafresh1 1535b8851fccSafresh1B<LocalAddr> - Local address to use for all socket connections. This 1536b8851fccSafresh1argument will be passed to the super class, i.e. L<IO::Socket::INET> 1537b8851fccSafresh1or L<IO::Socket::IP>. 1538b8851fccSafresh1 1539b8851fccSafresh1B<Domain> - Domain to use, i.e. AF_INET or AF_INET6. This 1540b8851fccSafresh1argument will be passed to the IO::Socket super class. 1541b8851fccSafresh1This can be used to enforce IPv4 even with L<IO::Socket::IP> 1542b8851fccSafresh1which would default to IPv6. 1543b8851fccSafresh1B<Family> is accepted as alternative name for B<Domain>. 1544b8851fccSafresh1 1545b8851fccSafresh1If the constructor fails undef will be returned and an error message will 1546b8851fccSafresh1be in $@ 1547b8851fccSafresh1 1548b8851fccSafresh1=back 1549b8851fccSafresh1 1550eac174f2Safresh1=head2 Object Methods 1551b8851fccSafresh1 1552b8851fccSafresh1Unless otherwise stated all methods return either a I<true> or I<false> 1553b8851fccSafresh1value, with I<true> meaning that the operation was a success. When a method 1554b8851fccSafresh1states that it returns a value, failure will be returned as I<undef> or an 1555b8851fccSafresh1empty list. 1556b8851fccSafresh1 1557b8851fccSafresh1C<Net::FTP> inherits from C<Net::Cmd> so methods defined in C<Net::Cmd> may 1558b8851fccSafresh1be used to send commands to the remote FTP server in addition to the methods 1559b8851fccSafresh1documented here. 1560b8851fccSafresh1 1561b8851fccSafresh1=over 4 1562b8851fccSafresh1 1563eac174f2Safresh1=item C<login([$login[, $password[, $account]]])> 1564b8851fccSafresh1 1565b8851fccSafresh1Log into the remote FTP server with the given login information. If 1566b8851fccSafresh1no arguments are given then the C<Net::FTP> uses the C<Net::Netrc> 1567b8851fccSafresh1package to lookup the login information for the connected host. 1568b8851fccSafresh1If no information is found then a login of I<anonymous> is used. 1569b8851fccSafresh1If no password is given and the login is I<anonymous> then I<anonymous@> 1570b8851fccSafresh1will be used for password. 1571b8851fccSafresh1 1572b8851fccSafresh1If the connection is via a firewall then the C<authorize> method will 1573b8851fccSafresh1be called with no arguments. 1574b8851fccSafresh1 1575eac174f2Safresh1=item C<starttls()> 1576b8851fccSafresh1 1577b8851fccSafresh1Upgrade existing plain connection to SSL. 1578b8851fccSafresh1The SSL arguments have to be given in C<new> already because they are needed for 1579b8851fccSafresh1data connections too. 1580b8851fccSafresh1 1581eac174f2Safresh1=item C<stoptls()> 1582b8851fccSafresh1 1583b8851fccSafresh1Downgrade existing SSL connection back to plain. 1584b8851fccSafresh1This is needed to work with some FTP helpers at firewalls, which need to see the 1585b8851fccSafresh1PORT and PASV commands and responses to dynamically open the necessary ports. 1586b8851fccSafresh1In this case C<starttls> is usually only done to protect the authorization. 1587b8851fccSafresh1 1588eac174f2Safresh1=item C<prot($level)> 1589b8851fccSafresh1 1590b8851fccSafresh1Set what type of data channel protection the client and server will be using. 1591eac174f2Safresh1Only C<$level>s "C" (clear) and "P" (private) are supported. 1592b8851fccSafresh1 1593eac174f2Safresh1=item C<host()> 1594b8851fccSafresh1 1595b8851fccSafresh1Returns the value used by the constructor, and passed to the IO::Socket super 1596b8851fccSafresh1class to connect to the host. 1597b8851fccSafresh1 1598eac174f2Safresh1=item C<account($acct)> 1599b8851fccSafresh1 1600b8851fccSafresh1Set a string identifying the user's account. 1601b8851fccSafresh1 1602eac174f2Safresh1=item C<authorize([$auth[, $resp]])> 1603b8851fccSafresh1 1604b8851fccSafresh1This is a protocol used by some firewall ftp proxies. It is used 1605b8851fccSafresh1to authorise the user to send data out. If both arguments are not specified 1606b8851fccSafresh1then C<authorize> uses C<Net::Netrc> to do a lookup. 1607b8851fccSafresh1 1608eac174f2Safresh1=item C<site($args)> 1609b8851fccSafresh1 1610b8851fccSafresh1Send a SITE command to the remote server and wait for a response. 1611b8851fccSafresh1 1612b8851fccSafresh1Returns most significant digit of the response code. 1613b8851fccSafresh1 1614eac174f2Safresh1=item C<ascii()> 1615b8851fccSafresh1 1616b8851fccSafresh1Transfer file in ASCII. CRLF translation will be done if required 1617b8851fccSafresh1 1618eac174f2Safresh1=item C<binary()> 1619b8851fccSafresh1 1620b8851fccSafresh1Transfer file in binary mode. No transformation will be done. 1621b8851fccSafresh1 1622b8851fccSafresh1B<Hint>: If both server and client machines use the same line ending for 1623b8851fccSafresh1text files, then it will be faster to transfer all files in binary mode. 1624b8851fccSafresh1 1625eac174f2Safresh1=item C<type([$type])> 1626b8851fccSafresh1 1627b8851fccSafresh1Set or get if files will be transferred in ASCII or binary mode. 1628b8851fccSafresh1 1629eac174f2Safresh1=item C<rename($oldname, $newname)> 1630b8851fccSafresh1 1631eac174f2Safresh1Rename a file on the remote FTP server from C<$oldname> to C<$newname>. This 1632b8851fccSafresh1is done by sending the RNFR and RNTO commands. 1633b8851fccSafresh1 1634eac174f2Safresh1=item C<delete($filename)> 1635b8851fccSafresh1 1636eac174f2Safresh1Send a request to the server to delete C<$filename>. 1637b8851fccSafresh1 1638eac174f2Safresh1=item C<cwd([$dir])> 1639b8851fccSafresh1 1640b8851fccSafresh1Attempt to change directory to the directory given in C<$dir>. If 1641b8851fccSafresh1C<$dir> is C<"..">, the FTP C<CDUP> command is used to attempt to 1642b8851fccSafresh1move up one directory. If no directory is given then an attempt is made 1643b8851fccSafresh1to change the directory to the root directory. 1644b8851fccSafresh1 1645eac174f2Safresh1=item C<cdup()> 1646b8851fccSafresh1 1647b8851fccSafresh1Change directory to the parent of the current directory. 1648b8851fccSafresh1 1649eac174f2Safresh1=item C<passive([$passive])> 1650b8851fccSafresh1 1651b8851fccSafresh1Set or get if data connections will be initiated in passive mode. 1652b8851fccSafresh1 1653eac174f2Safresh1=item C<pwd()> 1654b8851fccSafresh1 1655b8851fccSafresh1Returns the full pathname of the current directory. 1656b8851fccSafresh1 1657eac174f2Safresh1=item C<restart($where)> 1658b8851fccSafresh1 1659b8851fccSafresh1Set the byte offset at which to begin the next data transfer. Net::FTP simply 1660b8851fccSafresh1records this value and uses it when during the next data transfer. For this 1661b8851fccSafresh1reason this method will not return an error, but setting it may cause 1662b8851fccSafresh1a subsequent data transfer to fail. 1663b8851fccSafresh1 1664eac174f2Safresh1=item C<rmdir($dir[, $recurse])> 1665b8851fccSafresh1 1666eac174f2Safresh1Remove the directory with the name C<$dir>. If C<$recurse> is I<true> then 1667b8851fccSafresh1C<rmdir> will attempt to delete everything inside the directory. 1668b8851fccSafresh1 1669eac174f2Safresh1=item C<mkdir($dir[, $recurse])> 1670b8851fccSafresh1 1671eac174f2Safresh1Create a new directory with the name C<$dir>. If C<$recurse> is I<true> then 1672b8851fccSafresh1C<mkdir> will attempt to create all the directories in the given path. 1673b8851fccSafresh1 1674b8851fccSafresh1Returns the full pathname to the new directory. 1675b8851fccSafresh1 1676eac174f2Safresh1=item C<alloc($size[, $record_size])> 1677b8851fccSafresh1 1678b8851fccSafresh1The alloc command allows you to give the ftp server a hint about the size 1679b8851fccSafresh1of the file about to be transferred using the ALLO ftp command. Some storage 1680b8851fccSafresh1systems use this to make intelligent decisions about how to store the file. 1681eac174f2Safresh1The C<$size> argument represents the size of the file in bytes. The 1682eac174f2Safresh1C<$record_size> argument indicates a maximum record or page size for files 1683b8851fccSafresh1sent with a record or page structure. 1684b8851fccSafresh1 1685b8851fccSafresh1The size of the file will be determined, and sent to the server 1686b8851fccSafresh1automatically for normal files so that this method need only be called if 1687b8851fccSafresh1you are transferring data from a socket, named pipe, or other stream not 1688b8851fccSafresh1associated with a normal file. 1689b8851fccSafresh1 1690eac174f2Safresh1=item C<ls([$dir])> 1691b8851fccSafresh1 1692eac174f2Safresh1Get a directory listing of C<$dir>, or the current directory. 1693b8851fccSafresh1 1694b8851fccSafresh1In an array context, returns a list of lines returned from the server. In 1695b8851fccSafresh1a scalar context, returns a reference to a list. 1696b8851fccSafresh1 1697eac174f2Safresh1=item C<dir([$dir])> 1698b8851fccSafresh1 1699eac174f2Safresh1Get a directory listing of C<$dir>, or the current directory in long format. 1700b8851fccSafresh1 1701b8851fccSafresh1In an array context, returns a list of lines returned from the server. In 1702b8851fccSafresh1a scalar context, returns a reference to a list. 1703b8851fccSafresh1 1704eac174f2Safresh1=item C<get($remote_file[, $local_file[, $where]])> 1705b8851fccSafresh1 1706eac174f2Safresh1Get C<$remote_file> from the server and store locally. C<$local_file> may be 1707b8851fccSafresh1a filename or a filehandle. If not specified, the file will be stored in 1708b8851fccSafresh1the current directory with the same leafname as the remote file. 1709b8851fccSafresh1 1710eac174f2Safresh1If C<$where> is given then the first C<$where> bytes of the file will 1711b8851fccSafresh1not be transferred, and the remaining bytes will be appended to 1712b8851fccSafresh1the local file if it already exists. 1713b8851fccSafresh1 1714eac174f2Safresh1Returns C<$local_file>, or the generated local file name if C<$local_file> 1715b8851fccSafresh1is not given. If an error was encountered undef is returned. 1716b8851fccSafresh1 1717eac174f2Safresh1=item C<put($local_file[, $remote_file])> 1718b8851fccSafresh1 1719eac174f2Safresh1Put a file on the remote server. C<$local_file> may be a name or a filehandle. 1720eac174f2Safresh1If C<$local_file> is a filehandle then C<$remote_file> must be specified. If 1721eac174f2Safresh1C<$remote_file> is not specified then the file will be stored in the current 1722eac174f2Safresh1directory with the same leafname as C<$local_file>. 1723b8851fccSafresh1 1724eac174f2Safresh1Returns C<$remote_file>, or the generated remote filename if C<$remote_file> 1725b8851fccSafresh1is not given. 1726b8851fccSafresh1 1727b8851fccSafresh1B<NOTE>: If for some reason the transfer does not complete and an error is 1728b8851fccSafresh1returned then the contents that had been transferred will not be remove 1729b8851fccSafresh1automatically. 1730b8851fccSafresh1 1731eac174f2Safresh1=item C<put_unique($local_file[, $remote_file])> 1732b8851fccSafresh1 1733b8851fccSafresh1Same as put but uses the C<STOU> command. 1734b8851fccSafresh1 1735b8851fccSafresh1Returns the name of the file on the server. 1736b8851fccSafresh1 1737eac174f2Safresh1=item C<append($local_file[, $remote_file])> 1738b8851fccSafresh1 1739b8851fccSafresh1Same as put but appends to the file on the remote server. 1740b8851fccSafresh1 1741eac174f2Safresh1Returns C<$remote_file>, or the generated remote filename if C<$remote_file> 1742b8851fccSafresh1is not given. 1743b8851fccSafresh1 1744eac174f2Safresh1=item C<unique_name()> 1745b8851fccSafresh1 1746b8851fccSafresh1Returns the name of the last file stored on the server using the 1747b8851fccSafresh1C<STOU> command. 1748b8851fccSafresh1 1749eac174f2Safresh1=item C<mdtm($file)> 1750b8851fccSafresh1 1751b8851fccSafresh1Returns the I<modification time> of the given file 1752b8851fccSafresh1 1753eac174f2Safresh1=item C<size($file)> 1754b8851fccSafresh1 1755b8851fccSafresh1Returns the size in bytes for the given file as stored on the remote server. 1756b8851fccSafresh1 1757b8851fccSafresh1B<NOTE>: The size reported is the size of the stored file on the remote server. 1758b8851fccSafresh1If the file is subsequently transferred from the server in ASCII mode 1759b8851fccSafresh1and the remote server and local machine have different ideas about 1760b8851fccSafresh1"End Of Line" then the size of file on the local machine after transfer 1761b8851fccSafresh1may be different. 1762b8851fccSafresh1 1763eac174f2Safresh1=item C<supported($cmd)> 1764b8851fccSafresh1 1765b8851fccSafresh1Returns TRUE if the remote server supports the given command. 1766b8851fccSafresh1 1767eac174f2Safresh1=item C<hash([$filehandle_glob_ref[, $bytes_per_hash_mark]])> 1768b8851fccSafresh1 1769b8851fccSafresh1Called without parameters, or with the first argument false, hash marks 1770b8851fccSafresh1are suppressed. If the first argument is true but not a reference to a 1771b8851fccSafresh1file handle glob, then \*STDERR is used. The second argument is the number 1772b8851fccSafresh1of bytes per hash mark printed, and defaults to 1024. In all cases the 1773b8851fccSafresh1return value is a reference to an array of two: the filehandle glob reference 1774b8851fccSafresh1and the bytes per hash mark. 1775b8851fccSafresh1 1776eac174f2Safresh1=item C<feature($name)> 1777b8851fccSafresh1 1778b8851fccSafresh1Determine if the server supports the specified feature. The return 1779b8851fccSafresh1value is a list of lines the server responded with to describe the 1780b8851fccSafresh1options that it supports for the given feature. If the feature is 1781b8851fccSafresh1unsupported then the empty list is returned. 1782b8851fccSafresh1 1783b8851fccSafresh1 if ($ftp->feature( 'MDTM' )) { 1784b8851fccSafresh1 # Do something 1785b8851fccSafresh1 } 1786b8851fccSafresh1 1787b8851fccSafresh1 if (grep { /\bTLS\b/ } $ftp->feature('AUTH')) { 1788b8851fccSafresh1 # Server supports TLS 1789b8851fccSafresh1 } 1790b8851fccSafresh1 1791b8851fccSafresh1=back 1792b8851fccSafresh1 1793b8851fccSafresh1The following methods can return different results depending on 1794b8851fccSafresh1how they are called. If the user explicitly calls either 1795b8851fccSafresh1of the C<pasv> or C<port> methods then these methods will 1796b8851fccSafresh1return a I<true> or I<false> value. If the user does not 1797b8851fccSafresh1call either of these methods then the result will be a 1798b8851fccSafresh1reference to a C<Net::FTP::dataconn> based object. 1799b8851fccSafresh1 1800b8851fccSafresh1=over 4 1801b8851fccSafresh1 1802eac174f2Safresh1=item C<nlst([$dir])> 1803b8851fccSafresh1 1804b8851fccSafresh1Send an C<NLST> command to the server, with an optional parameter. 1805b8851fccSafresh1 1806eac174f2Safresh1=item C<list([$dir])> 1807b8851fccSafresh1 1808b8851fccSafresh1Same as C<nlst> but using the C<LIST> command 1809b8851fccSafresh1 1810eac174f2Safresh1=item C<retr($file)> 1811b8851fccSafresh1 1812eac174f2Safresh1Begin the retrieval of a file called C<$file> from the remote server. 1813b8851fccSafresh1 1814eac174f2Safresh1=item C<stor($file)> 1815b8851fccSafresh1 1816eac174f2Safresh1Tell the server that you wish to store a file. C<$file> is the 1817b8851fccSafresh1name of the new file that should be created. 1818b8851fccSafresh1 1819eac174f2Safresh1=item C<stou($file)> 1820b8851fccSafresh1 1821b8851fccSafresh1Same as C<stor> but using the C<STOU> command. The name of the unique 1822b8851fccSafresh1file which was created on the server will be available via the C<unique_name> 1823b8851fccSafresh1method after the data connection has been closed. 1824b8851fccSafresh1 1825eac174f2Safresh1=item C<appe($file)> 1826b8851fccSafresh1 1827b8851fccSafresh1Tell the server that we want to append some data to the end of a file 1828eac174f2Safresh1called C<$file>. If this file does not exist then create it. 1829b8851fccSafresh1 1830b8851fccSafresh1=back 1831b8851fccSafresh1 1832b8851fccSafresh1If for some reason you want to have complete control over the data connection, 1833b8851fccSafresh1this includes generating it and calling the C<response> method when required, 1834b8851fccSafresh1then the user can use these methods to do so. 1835b8851fccSafresh1 1836b8851fccSafresh1However calling these methods only affects the use of the methods above that 1837b8851fccSafresh1can return a data connection. They have no effect on methods C<get>, C<put>, 1838b8851fccSafresh1C<put_unique> and those that do not require data connections. 1839b8851fccSafresh1 1840b8851fccSafresh1=over 4 1841b8851fccSafresh1 1842eac174f2Safresh1=item C<port([$port])> 1843b8851fccSafresh1 1844eac174f2Safresh1=item C<eprt([$port])> 1845b8851fccSafresh1 1846eac174f2Safresh1Send a C<PORT> (IPv4) or C<EPRT> (IPv6) command to the server. If C<$port> is 1847b8851fccSafresh1specified then it is sent to the server. If not, then a listen socket is created 1848b8851fccSafresh1and the correct information sent to the server. 1849b8851fccSafresh1 1850eac174f2Safresh1=item C<pasv()> 1851b8851fccSafresh1 1852eac174f2Safresh1=item C<epsv()> 1853b8851fccSafresh1 1854b8851fccSafresh1Tell the server to go into passive mode (C<pasv> for IPv4, C<epsv> for IPv6). 1855b8851fccSafresh1Returns the text that represents the port on which the server is listening, this 1856b8851fccSafresh1text is in a suitable form to send to another ftp server using the C<port> or 1857b8851fccSafresh1C<eprt> method. 1858b8851fccSafresh1 1859b8851fccSafresh1=back 1860b8851fccSafresh1 1861b8851fccSafresh1The following methods can be used to transfer files between two remote 1862b8851fccSafresh1servers, providing that these two servers can connect directly to each other. 1863b8851fccSafresh1 1864b8851fccSafresh1=over 4 1865b8851fccSafresh1 1866eac174f2Safresh1=item C<pasv_xfer($src_file, $dest_server[, $dest_file ])> 1867b8851fccSafresh1 1868b8851fccSafresh1This method will do a file transfer between two remote ftp servers. If 1869eac174f2Safresh1C<$dest_file> is omitted then the leaf name of C<$src_file> will be used. 1870b8851fccSafresh1 1871eac174f2Safresh1=item C<pasv_xfer_unique($src_file, $dest_server[, $dest_file ])> 1872b8851fccSafresh1 1873b8851fccSafresh1Like C<pasv_xfer> but the file is stored on the remote server using 1874b8851fccSafresh1the STOU command. 1875b8851fccSafresh1 1876eac174f2Safresh1=item C<pasv_wait($non_pasv_server)> 1877b8851fccSafresh1 1878b8851fccSafresh1This method can be used to wait for a transfer to complete between a passive 1879b8851fccSafresh1server and a non-passive server. The method should be called on the passive 1880b8851fccSafresh1server with the C<Net::FTP> object for the non-passive server passed as an 1881b8851fccSafresh1argument. 1882b8851fccSafresh1 1883eac174f2Safresh1=item C<abort()> 1884b8851fccSafresh1 1885b8851fccSafresh1Abort the current data transfer. 1886b8851fccSafresh1 1887eac174f2Safresh1=item C<quit()> 1888b8851fccSafresh1 1889b8851fccSafresh1Send the QUIT command to the remote FTP server and close the socket connection. 1890b8851fccSafresh1 1891b8851fccSafresh1=back 1892b8851fccSafresh1 1893eac174f2Safresh1=head2 Methods for the Adventurous 1894b8851fccSafresh1 1895b8851fccSafresh1=over 4 1896b8851fccSafresh1 1897eac174f2Safresh1=item C<quot($cmd[, $args])> 1898b8851fccSafresh1 1899b8851fccSafresh1Send a command, that Net::FTP does not directly support, to the remote 1900b8851fccSafresh1server and wait for a response. 1901b8851fccSafresh1 1902b8851fccSafresh1Returns most significant digit of the response code. 1903b8851fccSafresh1 1904b8851fccSafresh1B<WARNING> This call should only be used on commands that do not require 1905b8851fccSafresh1data connections. Misuse of this method can hang the connection. 1906b8851fccSafresh1 1907eac174f2Safresh1=item C<can_inet6()> 1908b8851fccSafresh1 1909b8851fccSafresh1Returns whether we can use IPv6. 1910b8851fccSafresh1 1911eac174f2Safresh1=item C<can_ssl()> 1912b8851fccSafresh1 1913b8851fccSafresh1Returns whether we can use SSL. 1914b8851fccSafresh1 1915b8851fccSafresh1=back 1916b8851fccSafresh1 1917eac174f2Safresh1=head2 The dataconn Class 1918b8851fccSafresh1 1919b8851fccSafresh1Some of the methods defined in C<Net::FTP> return an object which will 1920b8851fccSafresh1be derived from the C<Net::FTP::dataconn> class. See L<Net::FTP::dataconn> for 1921b8851fccSafresh1more details. 1922b8851fccSafresh1 1923eac174f2Safresh1=head2 Unimplemented 1924b8851fccSafresh1 1925b8851fccSafresh1The following RFC959 commands have not been implemented: 1926b8851fccSafresh1 1927b8851fccSafresh1=over 4 1928b8851fccSafresh1 1929eac174f2Safresh1=item C<SMNT> 1930b8851fccSafresh1 1931b8851fccSafresh1Mount a different file system structure without changing login or 1932b8851fccSafresh1accounting information. 1933b8851fccSafresh1 1934eac174f2Safresh1=item C<HELP> 1935b8851fccSafresh1 1936b8851fccSafresh1Ask the server for "helpful information" (that's what the RFC says) on 1937b8851fccSafresh1the commands it accepts. 1938b8851fccSafresh1 1939eac174f2Safresh1=item C<MODE> 1940b8851fccSafresh1 1941b8851fccSafresh1Specifies transfer mode (stream, block or compressed) for file to be 1942b8851fccSafresh1transferred. 1943b8851fccSafresh1 1944eac174f2Safresh1=item C<SYST> 1945b8851fccSafresh1 1946b8851fccSafresh1Request remote server system identification. 1947b8851fccSafresh1 1948eac174f2Safresh1=item C<STAT> 1949b8851fccSafresh1 1950b8851fccSafresh1Request remote server status. 1951b8851fccSafresh1 1952eac174f2Safresh1=item C<STRU> 1953b8851fccSafresh1 1954b8851fccSafresh1Specifies file structure for file to be transferred. 1955b8851fccSafresh1 1956eac174f2Safresh1=item C<REIN> 1957b8851fccSafresh1 1958b8851fccSafresh1Reinitialize the connection, flushing all I/O and account information. 1959b8851fccSafresh1 1960b8851fccSafresh1=back 1961b8851fccSafresh1 1962eac174f2Safresh1=head1 EXPORTS 1963eac174f2Safresh1 1964eac174f2Safresh1I<None>. 1965eac174f2Safresh1 1966eac174f2Safresh1=head1 KNOWN BUGS 1967eac174f2Safresh1 1968eac174f2Safresh1See L<https://rt.cpan.org/Dist/Display.html?Status=Active&Queue=libnet>. 1969eac174f2Safresh1 1970eac174f2Safresh1=head2 Reporting Bugs 1971b8851fccSafresh1 1972b8851fccSafresh1When reporting bugs/problems please include as much information as possible. 1973b8851fccSafresh1It may be difficult for me to reproduce the problem as almost every setup 1974b8851fccSafresh1is different. 1975b8851fccSafresh1 1976b8851fccSafresh1A small script which yields the problem will probably be of help. It would 1977b8851fccSafresh1also be useful if this script was run with the extra options C<< Debug => 1 >> 1978b8851fccSafresh1passed to the constructor, and the output sent with the bug report. If you 1979b8851fccSafresh1cannot include a small script then please include a Debug trace from a 1980b8851fccSafresh1run of your program which does yield the problem. 1981b8851fccSafresh1 1982b8851fccSafresh1=head1 SEE ALSO 1983b8851fccSafresh1 1984b8851fccSafresh1L<Net::Netrc>, 1985b8851fccSafresh1L<Net::Cmd>, 1986eac174f2Safresh1L<IO::Socket::SSL>; 1987b8851fccSafresh1 1988eac174f2Safresh1L<ftp(1)>, 1989eac174f2Safresh1L<ftpd(8)>; 1990b8851fccSafresh1 1991eac174f2Safresh1L<https://www.ietf.org/rfc/rfc959.txt>, 1992eac174f2Safresh1L<https://www.ietf.org/rfc/rfc2428.txt>, 1993eac174f2Safresh1L<https://www.ietf.org/rfc/rfc4217.txt>. 1994b8851fccSafresh1 1995eac174f2Safresh1=head1 ACKNOWLEDGEMENTS 1996b8851fccSafresh1 1997eac174f2Safresh1Henry Gabryjelski E<lt>L<henryg@WPI.EDU|mailto:henryg@WPI.EDU>E<gt> - for the 1998eac174f2Safresh1suggestion of creating directories recursively. 1999b8851fccSafresh1 2000eac174f2Safresh1Nathan Torkington E<lt>L<gnat@frii.com|mailto:gnat@frii.com>E<gt> - for some 2001eac174f2Safresh1input on the documentation. 2002b8851fccSafresh1 2003eac174f2Safresh1Roderick Schertler E<lt>L<roderick@gate.net|mailto:roderick@gate.net>E<gt> - for 2004eac174f2Safresh1various inputs 2005b8851fccSafresh1 2006eac174f2Safresh1=head1 AUTHOR 2007b8851fccSafresh1 2008eac174f2Safresh1Graham Barr E<lt>L<gbarr@pobox.com|mailto:gbarr@pobox.com>E<gt>. 2009b8851fccSafresh1 2010eac174f2Safresh1Steve Hay E<lt>L<shay@cpan.org|mailto:shay@cpan.org>E<gt> is now maintaining 2011eac174f2Safresh1libnet as of version 1.22_02. 2012b8851fccSafresh1 2013b8851fccSafresh1=head1 COPYRIGHT 2014b8851fccSafresh1 20155759b3d2Safresh1Copyright (C) 1995-2004 Graham Barr. All rights reserved. 20165759b3d2Safresh1 2017*e0680481Safresh1Copyright (C) 2013-2017, 2020, 2022 Steve Hay. All rights reserved. 20185759b3d2Safresh1 20195759b3d2Safresh1=head1 LICENCE 2020b8851fccSafresh1 2021b8851fccSafresh1This module is free software; you can redistribute it and/or modify it under the 2022b8851fccSafresh1same terms as Perl itself, i.e. under the terms of either the GNU General Public 2023b8851fccSafresh1License or the Artistic License, as specified in the F<LICENCE> file. 2024b8851fccSafresh1 2025eac174f2Safresh1=head1 VERSION 2026eac174f2Safresh1 2027*e0680481Safresh1Version 3.15 2028eac174f2Safresh1 2029eac174f2Safresh1=head1 DATE 2030eac174f2Safresh1 2031*e0680481Safresh120 March 2023 2032eac174f2Safresh1 2033eac174f2Safresh1=head1 HISTORY 2034eac174f2Safresh1 2035eac174f2Safresh1See the F<Changes> file. 2036eac174f2Safresh1 2037b8851fccSafresh1=cut 2038