diff options
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Net/FTP.pm')
-rw-r--r-- | Master/tlpkg/tlperl/lib/Net/FTP.pm | 533 |
1 files changed, 346 insertions, 187 deletions
diff --git a/Master/tlpkg/tlperl/lib/Net/FTP.pm b/Master/tlpkg/tlperl/lib/Net/FTP.pm index 8107ef77e65..c791fac502f 100644 --- a/Master/tlpkg/tlperl/lib/Net/FTP.pm +++ b/Master/tlpkg/tlperl/lib/Net/FTP.pm @@ -1,6 +1,9 @@ # Net::FTP.pm # -# Copyright (c) 1995-2004 Graham Barr <gbarr@pobox.com>. All rights reserved. +# Versions up to 2.77_2 Copyright (c) 1995-2004 Graham Barr <gbarr@pobox.com>. +# All rights reserved. +# Changes in Version 2.77_3 onwards Copyright (C) 2013-2014 Steve Hay. All +# rights reserved. # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. # @@ -8,36 +11,58 @@ package Net::FTP; -require 5.001; +use 5.008001; use strict; -use vars qw(@ISA $VERSION); -use Carp; +use warnings; -use Socket 1.3; +use Carp; +use Fcntl qw(O_WRONLY O_RDONLY O_APPEND O_CREAT O_TRUNC); use IO::Socket; -use Time::Local; use Net::Cmd; use Net::Config; -use Fcntl qw(O_WRONLY O_RDONLY O_APPEND O_CREAT O_TRUNC); - -$VERSION = '2.79'; -@ISA = qw(Exporter Net::Cmd IO::Socket::INET); - -# Someday I will "use constant", when I am not bothered to much about -# compatibility with older releases of perl - -use vars qw($TELNET_IAC $TELNET_IP $TELNET_DM); -($TELNET_IAC, $TELNET_IP, $TELNET_DM) = (255, 244, 242); +use Socket; +use Time::Local; +our $VERSION = '3.05'; +our $IOCLASS; BEGIN { - - # make a constant so code is fast'ish - my $is_os390 = $^O eq 'os390'; - *trEBCDIC = sub () {$is_os390} + # Code for detecting if we can use SSL + my $ssl_class = eval { + require IO::Socket::SSL; + # first version with default CA on most platforms + no warnings 'numeric'; + IO::Socket::SSL->VERSION(2.007); + } && 'IO::Socket::SSL'; + + my $nossl_warn = !$ssl_class && + 'To use SSL please install IO::Socket::SSL with version>=2.007'; + + # Code for detecting if we can use IPv6 + my $inet6_class = eval { + require IO::Socket::IP; + no warnings 'numeric'; + IO::Socket::IP->VERSION(0.20); + } && 'IO::Socket::IP' || eval { + require IO::Socket::INET6; + no warnings 'numeric'; + IO::Socket::INET6->VERSION(2.62); + } && 'IO::Socket::INET6'; + + sub can_ssl { $ssl_class }; + sub can_inet6 { $inet6_class }; + + $IOCLASS = $ssl_class || $inet6_class || 'IO::Socket::INET'; } +our @ISA = ('Exporter','Net::Cmd',$IOCLASS); + +use constant TELNET_IAC => 255; +use constant TELNET_IP => 244; +use constant TELNET_DM => 242; + +use constant EBCDIC => $^O eq 'os390'; sub new { my $pkg = shift; @@ -71,16 +96,34 @@ sub new { } } + my %tlsargs; + if (can_ssl()) { + # for name verification strip port from domain:port, ipv4:port, [ipv6]:port + (my $hostname = $host) =~s{(?<!:):\d+$}{}; + %tlsargs = ( + SSL_verifycn_scheme => 'ftp', + SSL_verifycn_name => $hostname, + # use SNI if supported by IO::Socket::SSL + $pkg->can_client_sni ? (SSL_hostname => $hostname):(), + # reuse SSL session of control connection in data connections + SSL_session_cache => Net::FTP::_SSL_SingleSessionCache->new, + ); + # user defined SSL arg + $tlsargs{$_} = $arg{$_} for(grep { m{^SSL_} } keys %arg); + + } elsif ($arg{SSL}) { + croak("IO::Socket::SSL >= 2.007 needed for SSL support"); + } + my $ftp = $pkg->SUPER::new( PeerAddr => $peer, - PeerPort => $arg{Port} || 'ftp(21)', + PeerPort => $arg{Port} || ($arg{SSL} ? 'ftps(990)' : 'ftp(21)'), LocalAddr => $arg{'LocalAddr'}, Proto => 'tcp', - Timeout => defined $arg{Timeout} - ? $arg{Timeout} - : 120 - ) - or return undef; + Timeout => defined $arg{Timeout} ? $arg{Timeout} : 120, + %tlsargs, + $arg{SSL} ? ():( SSL_startHandshake => 0 ), + ) or return; ${*$ftp}{'net_ftp_host'} = $host; # Remote hostname ${*$ftp}{'net_ftp_type'} = 'A'; # ASCII/binary/etc mode @@ -99,6 +142,12 @@ sub new { : defined $fire ? $NetConfig{ftp_ext_passive} : $NetConfig{ftp_int_passive}; # Whew! :-) + ${*$ftp}{net_ftp_tlsargs} = \%tlsargs if %tlsargs; + if ($arg{SSL}) { + ${*$ftp}{net_ftp_tlsprot} = 'P'; + ${*$ftp}{net_ftp_tlsdirect} = 1; + } + $ftp->hash(exists $arg{Hash} ? $arg{Hash} : 0, 1024); $ftp->autoflush(1); @@ -223,10 +272,9 @@ sub size { } elsif ($ftp->supported("STAT")) { my @msg; - return undef + return unless $ftp->_STAT($file) && (@msg = $ftp->message) == 3; - my $line; - foreach $line (@msg) { + foreach my $line (@msg) { return (split(/\s+/, $line))[4] if $line =~ /^[-rwxSsTt]{10}/; } @@ -242,6 +290,35 @@ sub size { } +sub starttls { + my $ftp = shift; + can_ssl() or croak("IO::Socket::SSL >= 2.007 needed for SSL support"); + $ftp->is_SSL and croak("called starttls within SSL session"); + $ftp->_AUTH('TLS') == CMD_OK or return; + + $ftp->connect_SSL or return; + $ftp->prot('P'); + return 1; +} + +sub prot { + my ($ftp,$prot) = @_; + $prot eq 'C' or $prot eq 'P' or croak("prot must by C or P"); + $ftp->_PBSZ(0) or return; + $ftp->_PROT($prot) or return; + ${*$ftp}{net_ftp_tlsprot} = $prot; + return 1; +} + +sub stoptls { + my $ftp = shift; + $ftp->is_SSL or croak("called stoptls outside SSL session"); + ${*$ftp}{net_ftp_tlsdirect} and croak("cannot stoptls direct SSL session"); + $ftp->_CCC() or return; + $ftp->stop_SSL(); + return 1; +} + sub login { my ($ftp, $user, $pass, $acct) = @_; my ($ok, $ruser, $fwtype); @@ -400,7 +477,7 @@ sub type { return $oldval unless (defined $type); - return undef + return unless ($ftp->_TYPE($type, @_)); ${*$ftp}{'net_ftp_type'} = join(" ", $type, @_); @@ -417,8 +494,8 @@ sub alloc { return $oldval unless (defined $size); - return undef - unless ($ftp->_ALLO($size, @_)); + return + unless ($ftp->supported("ALLO") and $ftp->_ALLO($size, @_)); ${*$ftp}{'net_ftp_allo'} = join(" ", $size, @_); @@ -429,9 +506,9 @@ sub alloc { sub abort { my $ftp = shift; - send($ftp, pack("CCC", $TELNET_IAC, $TELNET_IP, $TELNET_IAC), MSG_OOB); + send($ftp, pack("CCC", TELNET_IAC, TELNET_IP, TELNET_IAC), MSG_OOB); - $ftp->command(pack("C", $TELNET_DM) . "ABOR"); + $ftp->command(pack("C", TELNET_DM) . "ABOR"); ${*$ftp}{'net_ftp_dataconn'}->close() if defined ${*$ftp}{'net_ftp_dataconn'}; @@ -463,7 +540,7 @@ sub get { delete ${*$ftp}{'net_ftp_pasv'}; $data = $ftp->retr($remote) - or return undef; + or return; if ($localfd) { $loc = $local; @@ -474,7 +551,7 @@ sub get { unless (sysopen($loc, $local, O_CREAT | O_WRONLY | ($rest ? O_APPEND: O_TRUNC))) { carp "Cannot open Local file $local: $!\n"; $data->abort; - return undef; + return; } } @@ -482,7 +559,7 @@ sub get { carp "Cannot binmode Local file $local: $!\n"; $data->abort; close($loc) unless $localfd; - return undef; + return; } $buf = ''; @@ -497,7 +574,7 @@ sub get { while (1) { last unless $len = $data->read($buf, $blksize); - if (trEBCDIC && $ftp->type ne 'I') { + if (EBCDIC && $ftp->type ne 'I') { $buf = $ftp->toebcdic($buf); $len = length($buf); } @@ -512,7 +589,7 @@ sub get { $data->abort; close($loc) unless $localfd; - return undef; + return; } } @@ -521,14 +598,14 @@ sub get { unless ($localfd) { unless (close($loc)) { carp "Cannot close file $local (perhaps disk space) $!\n"; - return undef; + return; } } unless ($data->close()) # implied $ftp->response { carp "Unable to close datastream"; - return undef; + return; } return $local; @@ -587,15 +664,14 @@ sub rmdir { # Get a list of all the files in the directory my @filelist = grep { !/^\.{1,2}$/ } $ftp->ls($dir); - return undef + return unless @filelist; # failed, it is probably not a directory return $ftp->delete($dir) if @filelist == 1 and $dir eq $filelist[0]; # Go thru and delete each file or the directory - my $file; - foreach $file (map { m,/, ? $_ : "$dir/$_" } @filelist) { + foreach my $file (map { m,/, ? $_ : "$dir/$_" } @filelist) { next # successfully deleted the file if $ftp->delete($file); @@ -622,7 +698,7 @@ sub restart { ${*$ftp}{'net_ftp_rest'} = $where; - return undef; + return; } @@ -632,7 +708,7 @@ sub mkdir { my ($ftp, $dir, $recurse) = @_; $ftp->_MKD($dir) || $recurse - or return undef; + or return; my $path = $dir; @@ -728,20 +804,20 @@ sub _store_cmd { unless (sysopen($loc, $local, O_RDONLY)) { carp "Cannot open Local file $local: $!\n"; - return undef; + return; } } if ($ftp->type eq 'I' && !binmode($loc)) { carp "Cannot binmode Local file $local: $!\n"; - return undef; + return; } delete ${*$ftp}{'net_ftp_port'}; delete ${*$ftp}{'net_ftp_pasv'}; $sock = $ftp->_data_cmd($cmd, grep { defined } $remote) - or return undef; + or return; $remote = ($ftp->message =~ /\w+\s*:\s*(.*)/)[0] if 'STOU' eq uc $cmd; @@ -756,7 +832,7 @@ sub _store_cmd { while (1) { last unless $len = read($loc, $buf = "", $blksize); - if (trEBCDIC && $ftp->type ne 'I') { + if (EBCDIC && $ftp->type ne 'I') { $buf = $ftp->toascii($buf); $len = length($buf); } @@ -773,7 +849,7 @@ sub _store_cmd { close($loc) unless $localfd; print $hashh "\n" if $hashh; - return undef; + return; } } @@ -783,7 +859,7 @@ sub _store_cmd { unless $localfd; $sock->close() - or return undef; + or return; if ('STOU' eq uc $cmd and $ftp->message =~ m/unique\s+file\s*name\s*:\s*(.*)\)|"(.*)"/) { require File::Basename; @@ -795,38 +871,43 @@ sub _store_cmd { sub port { - @_ == 1 || @_ == 2 or croak 'usage: $ftp->port([PORT])'; - - my ($ftp, $port) = @_; - my $ok; - - delete ${*$ftp}{'net_ftp_intern_port'}; - - unless (defined $port) { + @_ == 1 || @_ == 2 or croak 'usage: $self->port([PORT])'; + return _eprt('PORT',@_); +} - # create a Listen socket at same address as the command socket +sub eprt { + @_ == 1 || @_ == 2 or croak 'usage: $self->eprt([PORT])'; + return _eprt('EPRT',@_); +} - ${*$ftp}{'net_ftp_listen'} ||= IO::Socket::INET->new( - Listen => 5, - Proto => 'tcp', +sub _eprt { + my ($cmd,$ftp,$port) = @_; + delete ${*$ftp}{net_ftp_intern_port}; + unless ($port) { + my $listen = ${*$ftp}{net_ftp_listen} ||= $IOCLASS->new( + Listen => 1, Timeout => $ftp->timeout, LocalAddr => $ftp->sockhost, + can_ssl() ? ( + %{ ${*$ftp}{net_ftp_tlsargs} }, + SSL_startHandshake => 0, + ):(), ); - - my $listen = ${*$ftp}{'net_ftp_listen'}; - - my ($myport, @myaddr) = ($listen->sockport, split(/\./, $listen->sockhost)); - - $port = join(',', @myaddr, $myport >> 8, $myport & 0xff); - - ${*$ftp}{'net_ftp_intern_port'} = 1; + ${*$ftp}{net_ftp_intern_port} = 1; + my $fam = ($listen->sockdomain == AF_INET) ? 1:2; + if ( $cmd eq 'EPRT' || $fam == 2 ) { + $port = "|$fam|".$listen->sockhost."|".$listen->sockport."|"; + $cmd = 'EPRT'; + } else { + my $p = $listen->sockport; + $port = join(',',split(m{\.},$listen->sockhost),$p >> 8,$p & 0xff); + } + } elsif (ref($port) eq 'ARRAY') { + $port = join(',',split(m{\.},@$port[0]),@$port[1] >> 8,@$port[1] & 0xff); } - - $ok = $ftp->_PORT($port); - - ${*$ftp}{'net_ftp_port'} = $port; - - $ok; + my $ok = $cmd eq 'EPRT' ? $ftp->_EPRT($port) : $ftp->_PORT($port); + ${*$ftp}{net_ftp_port} = $port if $ok; + return $ok; } @@ -835,14 +916,27 @@ sub dir { shift->_list_cmd("LIST", @_); } sub pasv { - @_ == 1 or croak 'usage: $ftp->pasv()'; - my $ftp = shift; + @_ and croak 'usage: $ftp->port()'; + return $ftp->epsv if $ftp->sockdomain != AF_INET; + delete ${*$ftp}{net_ftp_intern_port}; + + if ( $ftp->_PASV && + $ftp->message =~ m{(\d+,\d+,\d+,\d+),(\d+),(\d+)} ) { + my $port = 256 * $2 + $3; + ( my $ip = $1 ) =~s{,}{.}g; + return ${*$ftp}{net_ftp_pasv} = [ $ip,$port ]; + } + return; +} - delete ${*$ftp}{'net_ftp_intern_port'}; +sub epsv { + my $ftp = shift; + @_ and croak 'usage: $ftp->epsv()'; + delete ${*$ftp}{net_ftp_intern_port}; - $ftp->_PASV && $ftp->message =~ /(\d+(,\d+)+)/ - ? ${*$ftp}{'net_ftp_pasv'} = $1 + $ftp->_EPSV && $ftp->message =~ m{\(([\x33-\x7e])\1\1(\d+)\1\)} + ? ${*$ftp}{net_ftp_pasv} = [ $ftp->peerhost, $2 ] : undef; } @@ -869,7 +963,7 @@ sub supported { unless $ftp->_HELP($cmd); my $text = $ftp->message; - if ($text =~ /following\s+commands/i) { + if ($text =~ /following.+commands/i) { $text =~ s/^.*\n//; while ($text =~ /(\*?)(\w+)(\*?)/sg) { $hash->{"\U$2"} = !length("$1$3"); @@ -926,41 +1020,55 @@ sub _extract_path { sub _dataconn { - my $ftp = shift; - my $data = undef; - my $pkg = "Net::FTP::" . $ftp->type; - - eval "require " . $pkg; - + my $ftp = shift; + my $pkg = "Net::FTP::" . $ftp->type; + eval "require " . $pkg ## no critic (BuiltinFunctions::ProhibitStringyEval) + or croak("cannot load $pkg required for type ".$ftp->type); $pkg =~ s/ /_/g; - - delete ${*$ftp}{'net_ftp_dataconn'}; - - if (defined ${*$ftp}{'net_ftp_pasv'}) { - my @port = map { 0 + $_ } split(/,/, ${*$ftp}{'net_ftp_pasv'}); - - $data = $pkg->new( - PeerAddr => join(".", @port[0 .. 3]), - PeerPort => $port[4] * 256 + $port[5], - LocalAddr => ${*$ftp}{'net_ftp_localaddr'}, - Proto => 'tcp', - Timeout => $ftp->timeout - ); - } - elsif (defined ${*$ftp}{'net_ftp_listen'}) { - $data = ${*$ftp}{'net_ftp_listen'}->accept($pkg); - close(delete ${*$ftp}{'net_ftp_listen'}); + delete ${*$ftp}{net_ftp_dataconn}; + + my $conn; + my $pasv = ${*$ftp}{net_ftp_pasv}; + if ($pasv) { + $conn = $pkg->new( + PeerAddr => $pasv->[0], + PeerPort => $pasv->[1], + LocalAddr => ${*$ftp}{net_ftp_localaddr}, + Timeout => $ftp->timeout, + can_ssl() ? ( + SSL_startHandshake => 0, + $ftp->is_SSL ? ( + SSL_reuse_ctx => $ftp, + SSL_verifycn_name => ${*$ftp}{net_ftp_tlsargs}{SSL_verifycn_name}, + # This will cause the use of SNI if supported by IO::Socket::SSL. + $ftp->can_client_sni ? ( + SSL_hostname => ${*$ftp}{net_ftp_tlsargs}{SSL_hostname} + ):(), + ) :( %{${*$ftp}{net_ftp_tlsargs}} ), + ):(), + ) or return; + } elsif (my $listen = delete ${*$ftp}{net_ftp_listen}) { + $conn = $listen->accept($pkg) or return; + $conn->timeout($ftp->timeout); + close($listen); + } else { + croak("no listener in active mode"); } - if ($data) { - ${*$data} = ""; - $data->timeout($ftp->timeout); - ${*$ftp}{'net_ftp_dataconn'} = $data; - ${*$data}{'net_ftp_cmd'} = $ftp; - ${*$data}{'net_ftp_blksize'} = ${*$ftp}{'net_ftp_blksize'}; + if (( ${*$ftp}{net_ftp_tlsprot} || '') eq 'P') { + if ($conn->connect_SSL) { + # SSL handshake ok + } else { + carp("failed to ssl upgrade dataconn: $IO::Socket::SSL::SSL_ERROR"); + return; + } } - $data; + ${*$ftp}{net_ftp_dataconn} = $conn; + ${*$conn} = ""; + ${*$conn}{net_ftp_cmd} = $ftp; + ${*$conn}{net_ftp_blksize} = ${*$ftp}{net_ftp_blksize}; + return $conn; } @@ -991,7 +1099,7 @@ sub _list_cmd { $data->close(); - if (trEBCDIC) { + if (EBCDIC) { for (@$list) { $_ = $ftp->toebcdic($_) } } @@ -1008,7 +1116,7 @@ sub _data_cmd { my $where = delete ${*$ftp}{'net_ftp_rest'} || 0; my $arg; - for $arg (@_) { + for my $arg (@_) { croak("Bad argument '$arg'\n") if $arg =~ /[\r\n]/s; } @@ -1017,27 +1125,28 @@ sub _data_cmd { && !defined ${*$ftp}{'net_ftp_pasv'} && !defined ${*$ftp}{'net_ftp_port'}) { - my $data = undef; - - return undef unless defined $ftp->pasv; - $data = $ftp->_dataconn() or return undef; + return unless defined $ftp->pasv; if ($where and !$ftp->_REST($where)) { my ($status, $message) = ($ftp->status, $ftp->message); $ftp->abort; $ftp->set_status($status, $message); - return undef; + return; } + # first send command, then open data connection + # otherwise the peer might not do a full accept (with SSL + # handshake if PROT P) $ftp->command($cmd, @_); + my $data = $ftp->_dataconn(); if (CMD_INFO == $ftp->response()) { $data->reading - if $cmd =~ /RETR|LIST|NLST/; + if $data && $cmd =~ /RETR|LIST|NLST/; return $data; } - $data->_close; + $data->_close if $data; - return undef; + return; } $ok = $ftp->port @@ -1047,12 +1156,14 @@ sub _data_cmd { $ok = $ftp->_REST($where) if $ok && $where; - return undef + return unless $ok; - if ($cmd =~ /(STOR|APPE|STOU)/ and exists ${*$ftp}{net_ftp_allo}) { + if ($cmd =~ /(STOR|APPE|STOU)/ and exists ${*$ftp}{net_ftp_allo} and + $ftp->supported("ALLO")) + { $ftp->_ALLO(delete ${*$ftp}{net_ftp_allo}) - or return undef; + or return; } $ftp->command($cmd, @_); @@ -1077,7 +1188,7 @@ sub _data_cmd { close(delete ${*$ftp}{'net_ftp_listen'}); - return undef; + return; } ## @@ -1139,19 +1250,19 @@ sub pasv_xfer { unless (defined $dfile); my $port = $sftp->pasv - or return undef; + or return; $dftp->port($port) - or return undef; + or return; - return undef + return unless ($unique ? $dftp->stou($dfile) : $dftp->stor($dfile)); unless ($sftp->retr($sfile) && $sftp->response == CMD_INFO) { $sftp->retr($sfile); $dftp->abort; $dftp->response(); - return undef; + return; } $dftp->pasv_wait($sftp); @@ -1170,10 +1281,10 @@ sub pasv_wait { my $dres = $ftp->response(); my $sres = $non_pasv->response(); - return undef + return unless $dres == CMD_OK && $sres == CMD_OK; - return undef + return unless $ftp->ok() && $non_pasv->ok(); return $1 @@ -1214,7 +1325,7 @@ sub cmd { shift->command(@_)->response() } ######################################## # -# RFC959 commands +# RFC959 + RFC2428 + RFC4217 commands # @@ -1238,6 +1349,11 @@ sub _SIZE { shift->command("SIZE", @_)->response() == CMD_OK } sub _HELP { shift->command("HELP", @_)->response() == CMD_OK } sub _STAT { shift->command("STAT", @_)->response() == CMD_OK } sub _FEAT { shift->command("FEAT", @_)->response() == CMD_OK } +sub _PBSZ { shift->command("PBSZ", @_)->response() == CMD_OK } +sub _PROT { shift->command("PROT", @_)->response() == CMD_OK } +sub _CCC { shift->command("CCC", @_)->response() == CMD_OK } +sub _EPRT { shift->command("EPRT", @_)->response() == CMD_OK } +sub _EPSV { shift->command("EPSV", @_)->response() == CMD_OK } sub _APPE { shift->command("APPE", @_)->response() == CMD_INFO } sub _LIST { shift->command("LIST", @_)->response() == CMD_INFO } sub _NLST { shift->command("NLST", @_)->response() == CMD_INFO } @@ -1269,6 +1385,26 @@ sub _SYST { shift->unsupported(@_) } sub _STRU { shift->unsupported(@_) } sub _REIN { shift->unsupported(@_) } +{ + # Session Cache with single entry + # used to make sure that we reuse same session for control and data channels + package Net::FTP::_SSL_SingleSessionCache; + sub new { my $x; return bless \$x,shift } + sub add_session { + my ($cache,$key,$session) = @_; + Net::SSLeay::SESSION_free($$cache) if $$cache; + $$cache = $session; + } + sub get_session { + my $cache = shift; + return $$cache + } + sub DESTROY { + my $cache = shift; + Net::SSLeay::SESSION_free($$cache) if $$cache; + } +} + 1; __END__ @@ -1330,7 +1466,9 @@ EBCDIC format. Binary (also known as image) format sends the data as a contiguous bit stream. Byte format transfers the data as bytes, the values of which remain the same regardless of differences in byte size between the two machines (in theory - in practice you should only use -this if you really know what you're doing). +this if you really know what you're doing). This class does not support +the EBCDIC or byte formats, and will default to binary instead if they +are attempted. =head1 CONSTRUCTOR @@ -1352,7 +1490,6 @@ the C<PeerAddr> option in L<IO::Socket::INET>, or a reference to an array with hosts to try in turn. The L</host> method will return the value which was used to connect to the host. - B<Firewall> - The name of a machine which acts as an FTP firewall. This can be overridden by an environment variable C<FTP_FIREWALL>. If specified, and the given host cannot be directly connected to, then the @@ -1371,6 +1508,13 @@ transfers. (defaults to 10240) B<Port> - The port number to connect to on the remote machine for the FTP connection +B<SSL> - If the connection should be done from start with SSL, contrary to later +upgrade with C<starttls>. + +B<SSL_*> - SSL arguments which will be applied when upgrading the control or +data connection to SSL. You can use SSL arguments as documented in +L<IO::Socket::SSL>, but it will usually use the right arguments already. + B<Timeout> - Set a timeout value in seconds (defaults to 120) B<Debug> - debug level (see the debug method in L<Net::Cmd>) @@ -1427,6 +1571,33 @@ will be used for password. If the connection is via a firewall then the C<authorize> method will be called with no arguments. +=item starttls () + +Upgrade existing plain connection to SSL. +The SSL arguments have to be given in C<new> already because they are needed for +data connections too. + +=item stoptls () + +Downgrade existing SSL connection back to plain. +This is needed to work with some FTP helpers at firewalls, which need to see the +PORT and PASV commands and responses to dynamically open the necessary ports. +In this case C<starttls> is usually only done to protect the authorization. + +=item prot ( LEVEL ) + +Set what type of data channel protection the client and server will be using. +Only C<LEVEL>s "C" (clear) and "P" (private) are supported. + +=item host () + +Returns the value used by the constructor, and passed to IO::Socket::INET, +to connect to the host. + +=item account( ACCT ) + +Set a string identifying the user's account. + =item authorize ( [AUTH [, RESP]]) This is a protocol used by some firewall ftp proxies. It is used @@ -1439,17 +1610,21 @@ Send a SITE command to the remote server and wait for a response. Returns most significant digit of the response code. -=item ascii +=item ascii () Transfer file in ASCII. CRLF translation will be done if required -=item binary +=item binary () Transfer file in binary mode. No transformation will be done. B<Hint>: If both server and client machines use the same line ending for text files, then it will be faster to transfer all files in binary mode. +=item type ( [ TYPE ] ) + +Set or get if files will be transferred in ASCII or binary mode. + =item rename ( OLDNAME, NEWNAME ) Rename a file on the remote FTP server from C<OLDNAME> to C<NEWNAME>. This @@ -1664,16 +1839,19 @@ C<put_unique> and those that do not require data connections. =over 4 =item port ( [ PORT ] ) +=item eprt ( [ PORT ] ) -Send a C<PORT> command to the server. If C<PORT> is specified then it is sent -to the server. If not, then a listen socket is created and the correct information -sent to the server. +Send a C<PORT> (IPv4) or C<EPRT> (IPv6) command to the server. If C<PORT> is +specified then it is sent to the server. If not, then a listen socket is created +and the correct information sent to the server. =item pasv () +=item epsv () -Tell the server to go into passive mode. Returns the text that represents the -port on which the server is listening, this text is in a suitable form to -sent to another ftp server using the C<port> method. +Tell the server to go into passive mode (C<pasv> for IPv4, C<epsv> for IPv6). +Returns the text that represents the port on which the server is listening, this +text is in a suitable form to send to another ftp server using the C<port> or +C<eprt> method. =back @@ -1723,49 +1901,21 @@ Returns most significant digit of the response code. B<WARNING> This call should only be used on commands that do not require data connections. Misuse of this method can hang the connection. -=back - -=head1 THE dataconn CLASS - -Some of the methods defined in C<Net::FTP> return an object which will -be derived from this class.The dataconn class itself is derived from -the C<IO::Socket::INET> class, so any normal IO operations can be performed. -However the following methods are defined in the dataconn class and IO should -be performed using these. - -=over 4 - -=item read ( BUFFER, SIZE [, TIMEOUT ] ) +=item can_inet6 () -Read C<SIZE> bytes of data from the server and place it into C<BUFFER>, also -performing any <CRLF> translation necessary. C<TIMEOUT> is optional, if not -given, the timeout value from the command connection will be used. +Returns whether we can use IPv6. -Returns the number of bytes read before any <CRLF> translation. +=item can_ssl () -=item write ( BUFFER, SIZE [, TIMEOUT ] ) +Returns whether we can use SSL. -Write C<SIZE> bytes of data from C<BUFFER> to the server, also -performing any <CRLF> translation necessary. C<TIMEOUT> is optional, if not -given, the timeout value from the command connection will be used. - -Returns the number of bytes written before any <CRLF> translation. - -=item bytes_read () - -Returns the number of bytes read so far. - -=item abort () - -Abort the current data transfer. - -=item close () +=back -Close the data connection and get a response from the FTP server. Returns -I<true> if the connection was closed successfully and the first digit of -the response from the server was a '2'. +=head1 THE dataconn CLASS -=back +Some of the methods defined in C<Net::FTP> return an object which will +be derived from the C<Net::FTP::dataconn> class. See L<Net::FTP::dataconn> for +more details. =head1 UNIMPLEMENTED @@ -1820,15 +1970,21 @@ run of your program which does yield the problem. =head1 AUTHOR -Graham Barr <gbarr@pobox.com> +Graham Barr E<lt>F<gbarr@pobox.com>E<gt> + +Steve Hay E<lt>F<shay@cpan.org>E<gt> is now maintaining libnet as of version +1.22_02 =head1 SEE ALSO -L<Net::Netrc> -L<Net::Cmd> +L<Net::Netrc>, +L<Net::Cmd>, +L<IO::Socket::SSL> -ftp(1), ftpd(8), RFC 959 +ftp(1), ftpd(8), RFC 959, RFC 2428, RFC 4217 http://www.ietf.org/rfc/rfc959.txt +http://www.ietf.org/rfc/rfc2428.txt +http://www.ietf.org/rfc/rfc4217.txt =head1 USE EXAMPLES @@ -1854,7 +2010,10 @@ Roderick Schertler <roderick@gate.net> - for various inputs =head1 COPYRIGHT -Copyright (c) 1995-2004 Graham Barr. All rights reserved. +Versions up to 2.77_2 Copyright (c) 1995-2004 Graham Barr. All rights reserved. +Changes in Version 2.77_3 onwards Copyright (C) 2013-2014 Steve Hay. All rights +reserved. + This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |