3 # Copyright (c) 1995 Graham Barr <Graham.Barr@tiuk.ti.com>. All rights
4 # reserved. This program is free software; you can redistribute it and/or
5 # modify it under the same terms as Perl itself.
11 Net::FTP - FTP Client class
17 $ftp = Net::FTP->new("some.host.name");
18 $ftp->login("anonymous","me@here.there");
20 $ftp->get("that.file");
25 C<Net::FTP> is a class implementing a simple FTP client in Perl as described
28 C<Net::FTP> provides methods that will perform various operations. These methods
29 could be split into groups depending the level of interface the user requires.
35 =item new (HOST [,OPTIONS])
37 This is the constructor for a new Net::SMTP object. C<HOST> is the
38 name of the remote host to which a FTP connection is required.
40 C<OPTIONS> are passed in a hash like fasion, using key and value pairs.
43 B<Firewall> - The name of a machine which acts as a FTP firewall. This can be
44 overridden by an environment variable C<FTP_FIREWALL>. If specified, and the
45 given host cannot be directly connected to, then the
46 connection is made to the firwall machine and the string C<@hostname> is
47 appended to the login identifier.
49 B<Port> - The port number to connect to on the remote machine for the
52 B<Timeout> - Set a timeout value (defaults to 120)
54 B<Debug> - Debug level
56 B<Passive> - If set to I<true> then all data transfers will be done using
57 passive mode. This is required for some I<dumb> servers.
63 Unless otherwise stated all methods return either a I<true> or I<false>
64 value, with I<true> meaning that the operation was a success. When a method
65 states that it returns a value, falure will be returned as I<undef> or an
70 =item login ([LOGIN [,PASSWORD [, ACCOUNT] ] ])
72 Log into the remote FTP server with the given login information. If
73 no arguments are given then the C<Net::FTP> uses the C<Net::Netrc>
74 package to lookup the login information for the connected host.
75 If no information is found then a login of I<anonymous> is used.
76 If no password is given and the login is I<anonymous> then the users
77 Email address will be used for a password.
79 If the connection is via a firewall then the C<authorize> method will
80 be called with no arguments.
82 =item authorize ( [AUTH [, RESP]])
84 This is a protocol used by some firewall ftp proxies. It is used
85 to authorise the user to send data out. If both arguments are not specified
86 then C<authorize> uses C<Net::Netrc> to do a lookup.
88 =item type (TYPE [, ARGS])
90 This method will send the TYPE command to the remote FTP server
91 to change the type of data transfer. The return value is the previous
94 =item ascii ([ARGS]) binary([ARGS]) ebcdic([ARGS]) byte([ARGS])
96 Synonyms for C<type> with the first arguments set correctly
98 B<NOTE> ebcdic and byte are not fully supported.
100 =item rename ( OLDNAME, NEWNAME )
102 Rename a file on the remote FTP server from C<OLDNAME> to C<NEWNAME>. This
103 is done by sending the RNFR and RNTO commands.
105 =item delete ( FILENAME )
107 Send a request to the server to delete C<FILENAME>.
109 =item cwd ( [ DIR ] )
111 Change the current working directory to C<DIR>, or / if not given.
115 Change directory to the parent of the current directory.
119 Returns the full pathname of the current directory.
123 Remove the directory with the name C<DIR>.
125 =item mkdir ( DIR [, RECURSE ])
127 Create a new directory with the name C<DIR>. If C<RECURSE> is I<true> then
128 C<mkdir> will attempt to create all the directories in the given path.
130 Returns the full pathname to the new directory.
134 Get a directory listing of C<DIR>, or the current directory.
136 Returns a reference to a list of lines returned from the server.
138 =item dir ( [ DIR ] )
140 Get a directory listing of C<DIR>, or the current directory in long format.
142 Returns a reference to a list of lines returned from the server.
144 =item get ( REMOTE_FILE [, LOCAL_FILE ] )
146 Get C<REMOTE_FILE> from the server and store locally. C<LOCAL_FILE> may be
147 a filename or a filehandle. If not specified the the file will be stored in
148 the current directory with the same leafname as the remote file.
150 Returns C<LOCAL_FILE>, or the generated local file name if C<LOCAL_FILE>
153 =item put ( LOCAL_FILE [, REMOTE_FILE ] )
155 Put a file on the remote server. C<LOCAL_FILE> may be a name or a filehandle.
156 If C<LOCAL_FILE> is a filehandle then C<REMOTE_FILE> must be specified. If
157 C<REMOTE_FILE> is not specified then the file will be stored in the current
158 directory with the same leafname as C<LOCAL_FILE>.
160 Returns C<REMOTE_FILE>, or the generated remote filename if C<REMOTE_FILE>
163 =item put_unique ( LOCAL_FILE [, REMOTE_FILE ] )
165 Same as put but uses the C<STOU> command.
167 Returns the name of the file on the server.
169 =item append ( LOCAL_FILE [, REMOTE_FILE ] )
171 Same as put but appends to the file on the remote server.
173 Returns C<REMOTE_FILE>, or the generated remote filename if C<REMOTE_FILE>
178 Returns the name of the last file stored on the server using the
183 Returns the I<modification time> of the given file
187 Returns the size in bytes for the given file.
191 The following methods can return different results depending on
192 how they are called. If the user explicitly calls either
193 of the C<pasv> or C<port> methods then these methods will
194 return a I<true> or I<false> value. If the user does not
195 call either of these methods then the result will be a
196 reference to a C<Net::FTP::dataconn> based object.
200 =item nlst ( [ DIR ] )
202 Send a C<NLST> command to the server, with an optional parameter.
204 =item list ( [ DIR ] )
206 Same as C<nlst> but using the C<LIST> command
210 Begin the retrieval of a file called C<FILE> from the remote server.
214 Tell the server that you wish to store a file. C<FILE> is the
215 name of the new file that should be created.
219 Same as C<stor> but using the C<STOU> command. The name of the unique
220 file which was created on the server will be avalaliable via the C<unique_name>
221 method after the data connection has been closed.
225 Tell the server that we want to append some data to the end of a file
226 called C<FILE>. If this file does not exist then create it.
230 If for some reason you want to have complete control over the data connection,
231 this includes generating it and calling the C<response> method when required,
232 then the user can use these methods to do so.
234 However calling these methods only affects the use of the methods above that
235 can return a data connection. They have no effect on methods C<get>, C<put>,
236 C<put_unique> and those that do not require data connections.
240 =item port ( [ PORT ] )
242 Send a C<PORT> command to the server. If C<PORT> is specified then it is sent
243 to the server. If not the a listen socket is created and the correct information
248 Tell the server to go into passive mode. Returns the text that represents the
249 port on which the server is listening, this text is in a suitable form to
250 sent to another ftp server using the C<port> method.
254 The following methods can be used to transfer files between two remote
255 servers, providing that these two servers can connect directly to each other.
259 =item pasv_xfer ( SRC_FILE, DEST_SERVER [, DEST_FILE ] )
261 This method will do a file transfer between two remote ftp servers. If
262 C<DEST_FILE> is omitted then the leaf name of C<SRC_FILE> will be used.
264 =item pasv_wait ( NON_PASV_SERVER )
266 This method can be used to wait for a transfer to complete between a passive
267 server and a non-passive server. The method should be called on the passive
268 server with the C<Net::FTP> object for the non-passive server passed as an
273 Abort the current data transfer.
277 Send the QUIT command to the remote FTP server and close the socket connection.
281 =head2 Methods for the adventurous
283 C<Net::FTP> inherits from C<Net::Cmd> so methods defined in C<Net::Cmd> may
284 be used to send commands to the remote FTP server.
288 =item quot (CMD [,ARGS])
290 Send a command, that Net::FTP does not directly support, to the remote
291 server and wait for a response.
293 Returns most significant digit of the response code.
295 B<WARNING> This call should only be used on commands that do not require
296 data connections. Misuse of this method can hang the connection.
300 =head1 THE dataconn CLASS
302 Some of the methods defined in C<Net::FTP> return an object which will
303 be derived from this class.The dataconn class itself is derived from
304 the C<IO::Socket::INET> class, so any normal IO operations can be performed.
305 However the following methods are defined in the dataconn class and IO should
306 be performed using these.
310 =item read ( BUFFER, SIZE [, TIMEOUT ] )
312 Read C<SIZE> bytes of data from the server and place it into C<BUFFER>, also
313 performing any <CRLF> translation necessary. C<TIMEOUT> is optional, if not
314 given the the timeout value from the command connection will be used.
316 Returns the number of bytes read before any <CRLF> translation.
318 =item write ( BUFFER, SIZE [, TIMEOUT ] )
320 Write C<SIZE> bytes of data from C<BUFFER> to the server, also
321 performing any <CRLF> translation necessary. C<TIMEOUT> is optional, if not
322 given the the timeout value from the command connection will be used.
324 Returns the number of bytes written before any <CRLF> translation.
328 Abort the current data transfer.
332 Close the data connection and get a response from the FTP server. Returns
333 I<true> if the connection was closed sucessfully and the first digit of
334 the response from the server was a '2'.
340 Graham Barr <Graham.Barr@tiuk.ti.com>
345 $Date: 1996/09/05 06:53:58 $
347 The VERSION is derived from the revision by changing each number after the
348 first dot into a 2 digit number so
350 Revision 1.8 => VERSION 1.08
351 Revision 1.2.3 => VERSION 1.0203
360 Henry Gabryjelski <henryg@WPI.EDU> - for the suggestion of creating directories
365 Copyright (c) 1995 Graham Barr. All rights reserved. This program is free
366 software; you can redistribute it and/or modify it under the same terms
374 use vars qw(@ISA $VERSION);
381 use Net::Telnet qw(TELNET_IAC TELNET_IP TELNET_DM);
383 $VERSION = do{my @r=(q$Revision: 2.8 $=~/(\d+)/g);sprintf "%d."."%02d"x$#r,@r};
384 @ISA = qw(Exporter Net::Cmd IO::Socket::INET);
395 unless(defined inet_aton($peer))
397 $fire = $ENV{FTP_FIREWALL} || $arg{Firewall} || undef;
405 my $ftp = $pkg->SUPER::new(PeerAddr => $peer,
406 PeerPort => $arg{Port} || 'ftp(21)',
408 Timeout => defined $arg{Timeout}
413 ${*$ftp}{'net_ftp_passive'} = $arg{Passive} || 0; # Always use pasv mode
414 ${*$ftp}{'net_ftp_host'} = $host; # Remote hostname
415 ${*$ftp}{'net_ftp_type'} = 'A'; # ASCII/binary/etc mode
417 ${*$ftp}{'net_ftp_firewall'} = $fire
422 $ftp->debug(exists $arg{Debug} ? $arg{Debug} : undef);
424 unless ($ftp->response() == CMD_OK)
426 $ftp->SUPER::close();
434 ## User interface methods
442 && $ftp->SUPER::close;
450 && defined fileno($ftp)
454 sub DESTROY { shift->close }
456 sub ascii { shift->type('A',@_); }
457 sub binary { shift->type('I',@_); }
461 carp "TYPE E is unsupported, shall default to I";
467 carp "TYPE L is unsupported, shall default to I";
471 # Allow the user to send a command directly, BE CAREFUL !!
478 $ftp->command( uc $cmd, @_);
488 unless $ftp->_MDTM($file);
490 my @gt = reverse ($ftp->message =~ /(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/);
501 ? ($ftp->message =~ /(\d+)/)[0]
507 my($ftp,$user,$pass,$acct) = @_;
510 unless (defined $user)
514 my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_host'});
516 ($user,$pass,$acct) = $rc->lpa()
520 $user ||= "anonymous";
523 if(defined ${*$ftp}{'net_ftp_firewall'})
525 $user .= "@" . ${*$ftp}{'net_ftp_host'};
528 $ok = $ftp->_USER($user);
530 # Some dumb firewall's don't prefix the connection messages
531 $ok = $ftp->response()
532 if($ok == CMD_OK && $ftp->code == 220 && $user =~ /\@/);
536 unless(defined $pass)
540 my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_host'}, $ruser);
542 ($ruser,$pass,$acct) = $rc->lpa()
545 $pass = "-" . (getpwuid($>))[0] . "@"
546 if (!defined $pass && $ruser =~ /^anonymous/o);
549 $ok = $ftp->_PASS($pass || "");
552 $ok = $ftp->_ACCT($acct || "")
553 if ($ok == CMD_MORE);
556 if($ok == CMD_OK && defined ${*$ftp}{'net_ftp_firewall'});
563 @_ >= 1 || @_ <= 3 or croak 'usage: $ftp->authorize( [AUTH [, RESP]])';
565 my($ftp,$auth,$resp) = @_;
567 unless(defined $resp)
571 $auth ||= (getpwuid($>))[0];
573 my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}, $auth)
574 || Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'});
576 ($auth,$resp) = $rc->lpa()
580 my $ok = $ftp->_AUTH($auth || "");
582 $ok = $ftp->_RESP($resp || "")
583 if ($ok == CMD_MORE);
590 @_ == 3 or croak 'usage: $ftp->rename(FROM, TO)';
592 my($ftp,$from,$to) = @_;
602 my $oldval = ${*$ftp}{'net_ftp_type'};
605 unless (defined $type);
608 unless ($ftp->_TYPE($type,@_));
610 ${*$ftp}{'net_ftp_type'} = join(" ",$type,@_);
619 send($ftp,pack("CC",TELNET_IAC,TELNET_IP),0);
620 send($ftp,pack("C", TELNET_IAC),MSG_OOB);
621 send($ftp,pack("C", TELNET_DM),0);
623 $ftp->command("ABOR");
625 defined ${*$ftp}{'net_ftp_dataconn'}
626 ? ${*$ftp}{'net_ftp_dataconn'}->close()
630 if $ftp->status == CMD_REJECT;
632 $ftp->status == CMD_OK;
637 my($ftp,$remote,$local,$where) = @_;
639 my($loc,$len,$buf,$resp,$localfd,$data);
642 $localfd = ref($local) ? fileno($local)
645 ($local = $remote) =~ s#^.*/##
646 unless(defined $local);
648 ${*$ftp}{'net_ftp_rest'} = $where
651 delete ${*$ftp}{'net_ftp_port'};
652 delete ${*$ftp}{'net_ftp_pasv'};
654 $data = $ftp->retr($remote) or
665 unless(($where) ? open($loc,">>$local") : open($loc,">$local"))
667 carp "Cannot open Local file $local: $!\n";
672 if ($ftp->binary && !binmode($loc))
674 carp "Cannot binmode Local file $local: $!\n";
682 $len = $data->read($buf,1024);
684 while($len > 0 && syswrite($loc,$buf,$len) == $len);
687 unless defined $localfd;
689 $data->close(); # implied $ftp->response
696 @_ == 2 || @_ == 3 or croak 'usage: $ftp->cwd( [ DIR ] )';
709 @_ == 1 or croak 'usage: $ftp->cdup()';
715 @_ == 1 || croak 'usage: $ftp->pwd()';
724 @_ == 2 || croak 'usage: $ftp->rmdir( DIR )';
731 @_ == 2 || @_ == 3 or croak 'usage: $ftp->mkdir( DIR [, RECURSE ] )';
733 my($ftp,$dir,$recurse) = @_;
735 $ftp->_MKD($dir) || $recurse or
741 my @path = split(m#(?=/+)#, $dir);
747 $path .= shift @path;
750 $path = $ftp->_extract_path($path);
752 # 521 means directory already exists
754 unless $ftp->ok || $ftp->code == 521;
758 $ftp->_extract_path($path);
763 @_ == 2 || croak 'usage: $ftp->delete( FILENAME )';
768 sub put { shift->_store_cmd("stor",@_) }
769 sub put_unique { shift->_store_cmd("stou",@_) }
770 sub append { shift->_store_cmd("appe",@_) }
772 sub nlst { shift->_data_cmd("NLST",@_) }
773 sub list { shift->_data_cmd("LIST",@_) }
774 sub retr { shift->_data_cmd("RETR",@_) }
775 sub stor { shift->_data_cmd("STOR",@_) }
776 sub stou { shift->_data_cmd("STOU",@_) }
777 sub appe { shift->_data_cmd("APPE",@_) }
781 my($ftp,$cmd,$local,$remote) = @_;
782 my($loc,$sock,$len,$buf,$localfd);
785 $localfd = ref($local) ? fileno($local)
788 unless(defined $remote)
790 croak 'Must specify remote filename with stream input'
793 ($remote = $local) =~ s%.*/%%;
804 unless(open($loc,"<$local"))
806 carp "Cannot open Local file $local: $!\n";
809 if ($ftp->binary && !binmode($loc))
811 carp "Cannot binmode Local file $local: $!\n";
816 delete ${*$ftp}{'net_ftp_port'};
817 delete ${*$ftp}{'net_ftp_pasv'};
819 $sock = $ftp->_data_cmd($cmd, $remote) or
824 $len = sysread($loc,$buf="",1024);
826 while($len && $sock->write($buf,$len) == $len);
829 unless defined $localfd;
833 ($remote) = $ftp->message =~ /unique file name:\s*(\S*)\s*\)/
834 if ('STOU' eq uc $cmd);
841 @_ == 1 || @_ == 2 or croak 'usage: $ftp->port([PORT])';
846 delete ${*$ftp}{'net_ftp_intern_port'};
848 unless(defined $port)
850 # create a Listen socket at same address as the command socket
852 ${*$ftp}{'net_ftp_listen'} ||= IO::Socket::INET->new(Listen => 5,
854 LocalAddr => $ftp->sockhost,
857 my $listen = ${*$ftp}{'net_ftp_listen'};
859 my($myport, @myaddr) = ($listen->sockport, split(/\./,$listen->sockhost));
861 $port = join(',', @myaddr, $myport >> 8, $myport & 0xff);
863 ${*$ftp}{'net_ftp_intern_port'} = 1;
866 $ok = $ftp->_PORT($port);
868 ${*$ftp}{'net_ftp_port'} = $port;
873 sub ls { shift->_list_cmd("NLST",@_); }
874 sub dir { shift->_list_cmd("LIST",@_); }
878 @_ == 1 or croak 'usage: $ftp->pasv()';
882 delete ${*$ftp}{'net_ftp_intern_port'};
884 $ftp->_PASV && $ftp->message =~ /(\d+(,\d+)+)/
885 ? ${*$ftp}{'net_ftp_pasv'} = $1
892 ${*$ftp}{'net_ftp_unique'} || undef;
896 ## Depreciated methods
901 carp "Use of Net::FTP::lsl depreciated, use 'dir'"
908 carp "Use of Net::FTP::authorise depreciated, use 'authorize'"
920 my($ftp, $path) = @_;
923 $ftp->message =~ /\s\"(.*)\"\s/o &&
924 ($path = $1) =~ s/\"\"/\"/g;
930 ## Communication methods
937 my $pkg = "Net::FTP::" . $ftp->type;
941 delete ${*$ftp}{'net_ftp_dataconn'};
943 if(defined ${*$ftp}{'net_ftp_pasv'})
945 my @port = split(/,/,${*$ftp}{'net_ftp_pasv'});
947 $data = $pkg->new(PeerAddr => join(".",@port[0..3]),
948 PeerPort => $port[4] * 256 + $port[5],
952 elsif(defined ${*$ftp}{'net_ftp_listen'})
954 $data = ${*$ftp}{'net_ftp_listen'}->accept($pkg);
955 close(delete ${*$ftp}{'net_ftp_listen'});
961 $data->timeout($ftp->timeout);
962 ${*$ftp}{'net_ftp_dataconn'} = $data;
963 ${*$data}{'net_ftp_cmd'} = $ftp;
974 delete ${*$ftp}{'net_ftp_port'};
975 delete ${*$ftp}{'net_ftp_pasv'};
977 my $data = $ftp->_data_cmd($cmd,@_);
980 unless(defined $data);
982 bless $data, "Net::FTP::A"; # Force ASCII mode
987 while($data->read($databuf,1024))
992 my $list = [ split(/\n/,$buf) ];
1005 my $where = delete ${*$ftp}{'net_ftp_rest'} || 0;
1007 if(${*$ftp}{'net_ftp_passive'} &&
1008 !defined ${*$ftp}{'net_ftp_pasv'} &&
1009 !defined ${*$ftp}{'net_ftp_port'})
1013 $ok = defined $ftp->pasv;
1014 $ok = $ftp->_REST($where)
1019 $ftp->command($cmd,@_);
1020 $data = $ftp->_dataconn();
1021 $ok = CMD_INFO == $ftp->response();
1028 unless (defined ${*$ftp}{'net_ftp_port'} ||
1029 defined ${*$ftp}{'net_ftp_pasv'});
1031 $ok = $ftp->_REST($where)
1037 $ftp->command($cmd,@_);
1040 if(defined ${*$ftp}{'net_ftp_pasv'});
1042 $ok = CMD_INFO == $ftp->response();
1045 unless exists ${*$ftp}{'net_ftp_intern_port'};
1047 $ok ? $ftp->_dataconn()
1052 ## Over-ride methods (Net::Cmd)
1055 sub debug_text { $_[2] =~ /^(pass|resp)/i ? "$1 ....\n" : $_[2]; }
1061 delete ${*$ftp}{'net_ftp_port'};
1062 $ftp->SUPER::command(@_);
1068 my $code = $ftp->SUPER::response();
1070 delete ${*$ftp}{'net_ftp_pasv'}
1071 if ($code != CMD_MORE && $code != CMD_INFO);
1077 ## Allow 2 servers to talk directly
1082 my($sftp,$sfile,$dftp,$dfile) = @_;
1084 ($dfile = $sfile) =~ s#.*/##
1085 unless(defined $dfile);
1087 my $port = $sftp->pasv or
1090 unless($dftp->port($port) && $sftp->retr($sfile) && $dftp->stou($dfile))
1097 $dftp->pasv_wait($sftp);
1102 @_ == 2 or croak 'usage: $ftp->pasv_wait(NON_PASV_FTP)';
1104 my($ftp, $non_pasv) = @_;
1105 my($file,$rin,$rout);
1107 vec($rin,fileno($ftp),1) = 1;
1108 select($rout=$rin, undef, undef, undef);
1111 $non_pasv->response();
1114 unless $ftp->ok() && $non_pasv->ok();
1117 if $ftp->message =~ /unique file name:\s*(\S*)\s*\)/;
1120 if $non_pasv->message =~ /unique file name:\s*(\S*)\s*\)/;
1125 sub cmd { shift->command(@_)->responce() }
1127 ########################################
1132 sub _ABOR { shift->command("ABOR")->response() == CMD_OK }
1133 sub _CDUP { shift->command("CDUP")->response() == CMD_OK }
1134 sub _NOOP { shift->command("NOOP")->response() == CMD_OK }
1135 sub _PASV { shift->command("PASV")->response() == CMD_OK }
1136 sub _QUIT { shift->command("QUIT")->response() == CMD_OK }
1137 sub _DELE { shift->command("DELE",@_)->response() == CMD_OK }
1138 sub _CWD { shift->command("CWD", @_)->response() == CMD_OK }
1139 sub _PORT { shift->command("PORT",@_)->response() == CMD_OK }
1140 sub _RMD { shift->command("RMD", @_)->response() == CMD_OK }
1141 sub _MKD { shift->command("MKD", @_)->response() == CMD_OK }
1142 sub _PWD { shift->command("PWD", @_)->response() == CMD_OK }
1143 sub _TYPE { shift->command("TYPE",@_)->response() == CMD_OK }
1144 sub _RNTO { shift->command("RNTO",@_)->response() == CMD_OK }
1145 sub _ACCT { shift->command("ACCT",@_)->response() == CMD_OK }
1146 sub _RESP { shift->command("RESP",@_)->response() == CMD_OK }
1147 sub _MDTM { shift->command("MDTM",@_)->response() == CMD_OK }
1148 sub _SIZE { shift->command("SIZE",@_)->response() == CMD_OK }
1149 sub _APPE { shift->command("APPE",@_)->response() == CMD_INFO }
1150 sub _LIST { shift->command("LIST",@_)->response() == CMD_INFO }
1151 sub _NLST { shift->command("NLST",@_)->response() == CMD_INFO }
1152 sub _RETR { shift->command("RETR",@_)->response() == CMD_INFO }
1153 sub _STOR { shift->command("STOR",@_)->response() == CMD_INFO }
1154 sub _STOU { shift->command("STOU",@_)->response() == CMD_INFO }
1155 sub _RNFR { shift->command("RNFR",@_)->response() == CMD_MORE }
1156 sub _REST { shift->command("REST",@_)->response() == CMD_MORE }
1157 sub _USER { shift->command("user",@_)->response() } # A certain brain dead firewall :-)
1158 sub _PASS { shift->command("PASS",@_)->response() }
1159 sub _AUTH { shift->command("AUTH",@_)->response() }
1161 sub _ALLO { shift->unsupported(@_) }
1162 sub _SMNT { shift->unsupported(@_) }
1163 sub _HELP { shift->unsupported(@_) }
1164 sub _MODE { shift->unsupported(@_) }
1165 sub _SITE { shift->unsupported(@_) }
1166 sub _SYST { shift->unsupported(@_) }
1167 sub _STAT { shift->unsupported(@_) }
1168 sub _STRU { shift->unsupported(@_) }
1169 sub _REIN { shift->unsupported(@_) }
1172 ## Generic data connection package
1175 package Net::FTP::dataconn;
1178 use vars qw(@ISA $timeout);
1181 @ISA = qw(IO::Socket::INET);
1186 my $ftp = ${*$data}{'net_ftp_cmd'};
1188 $ftp->abort; # this will close me
1194 my $ftp = ${*$data}{'net_ftp_cmd'};
1196 $data->SUPER::close();
1198 delete ${*$ftp}{'net_ftp_dataconn'}
1199 if exists ${*$ftp}{'net_ftp_dataconn'} &&
1200 $data == ${*$ftp}{'net_ftp_dataconn'};
1202 $ftp->response() == CMD_OK &&
1203 $ftp->message =~ /unique file name:\s*(\S*)\s*\)/ &&
1204 (${*$ftp}{'net_ftp_unique'} = $1);
1206 $ftp->status == CMD_OK;
1212 local *timeout = \$_[0]; shift;
1217 return 1 unless $timeout;
1220 vec($rin,fileno($data),1) = 1;
1222 $win = $rw ? undef : $rin;
1223 $rin = undef unless $rw;
1225 my $nfound = select($rin, $win, undef, $timeout);
1236 local *timeout = \$_[0];
1238 $data->_select($timeout,1);
1244 local *timeout = \$_[0];
1246 $data->_select($timeout,0);
1253 ${*$ftp}{'net_ftp_cmd'};
1257 @Net::FTP::L::ISA = qw(Net::FTP::I);
1258 @Net::FTP::E::ISA = qw(Net::FTP::I);
1261 ## Package to read/write on ASCII data connections
1264 package Net::FTP::A;
1266 use vars qw(@ISA $buf);
1269 @ISA = qw(Net::FTP::dataconn);
1274 local *buf = \$_[0]; shift;
1275 my $size = shift || croak 'read($buf,$size,[$offset])';
1276 my $offset = shift || 0;
1277 my $timeout = $data->timeout;
1282 $offset = length $buf
1283 if($offset > length $buf);
1290 $data->can_read($timeout) or
1293 my $n = sysread($data, ${*$data}, $size, length ${*$data});
1298 ${*$data} =~ s/(\015)?(?!\012)\Z//so;
1301 ${*$data} =~ s/\015\012/\n/sgo;
1303 substr($buf,$offset) = ${*$data};
1305 $l += length(${*$data});
1306 $offset += length(${*$data});
1311 if($l == 0 && $n > 0);
1313 if($n == 0 && $l == 0)
1315 substr($buf,$offset) = ${*$data};
1326 local *buf = \$_[0]; shift;
1327 my $size = shift || croak 'write($buf,$size,[$timeout])';
1328 my $timeout = @_ ? shift : $data->timeout;
1330 $data->can_write($timeout) or
1333 # What is previous pkt ended in \015 or not ??
1336 ($tmp = $buf) =~ s/(?!\015)\012/\015\012/sg;
1338 my $len = $size + length($tmp) - length($buf);
1339 my $wrote = syswrite($data, $tmp, $len);
1343 $wrote = $wrote == $len ? $size
1351 ## Package to read/write on BINARY data connections
1354 package Net::FTP::I;
1356 use vars qw(@ISA $buf);
1359 @ISA = qw(Net::FTP::dataconn);
1364 local *buf = \$_[0]; shift;
1365 my $size = shift || croak 'read($buf,$size,[$timeout])';
1366 my $timeout = @_ ? shift : $data->timeout;
1368 $data->can_read($timeout) or
1371 my $n = sysread($data, $buf, $size);
1379 local *buf = \$_[0]; shift;
1380 my $size = shift || croak 'write($buf,$size,[$timeout])';
1381 my $timeout = @_ ? shift : $data->timeout;
1383 $data->can_write($timeout) or
1386 syswrite($data, $buf, $size);