xref: /openbsd-src/gnu/usr.bin/perl/cpan/libnet/lib/Net/FTP.pm (revision e068048151d29f2562a32185e21a8ba885482260)
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