Blame lib/Net/FTP/dataconn.pm

Packit bd23c0
##
Packit bd23c0
## Generic data connection package
Packit bd23c0
##
Packit bd23c0
Packit bd23c0
package Net::FTP::dataconn;
Packit bd23c0
Packit bd23c0
use 5.008001;
Packit bd23c0
Packit bd23c0
use strict;
Packit bd23c0
use warnings;
Packit bd23c0
Packit bd23c0
use Carp;
Packit bd23c0
use Errno;
Packit bd23c0
use Net::Cmd;
Packit bd23c0
Packit bd23c0
our $VERSION = '3.11';
Packit bd23c0
Packit bd23c0
$Net::FTP::IOCLASS or die "please load Net::FTP before Net::FTP::dataconn";
Packit bd23c0
our @ISA = $Net::FTP::IOCLASS;
Packit bd23c0
Packit bd23c0
sub reading {
Packit bd23c0
  my $data = shift;
Packit bd23c0
  ${*$data}{'net_ftp_bytesread'} = 0;
Packit bd23c0
}
Packit bd23c0
Packit bd23c0
Packit bd23c0
sub abort {
Packit bd23c0
  my $data = shift;
Packit bd23c0
  my $ftp  = ${*$data}{'net_ftp_cmd'};
Packit bd23c0
Packit bd23c0
  # no need to abort if we have finished the xfer
Packit bd23c0
  return $data->close
Packit bd23c0
    if ${*$data}{'net_ftp_eof'};
Packit bd23c0
Packit bd23c0
  # for some reason if we continuously open RETR connections and not
Packit bd23c0
  # read a single byte, then abort them after a while the server will
Packit bd23c0
  # close our connection, this prevents the unexpected EOF on the
Packit bd23c0
  # command channel -- GMB
Packit bd23c0
  if (exists ${*$data}{'net_ftp_bytesread'}
Packit bd23c0
    && (${*$data}{'net_ftp_bytesread'} == 0))
Packit bd23c0
  {
Packit bd23c0
    my $buf     = "";
Packit bd23c0
    my $timeout = $data->timeout;
Packit bd23c0
    $data->can_read($timeout) && sysread($data, $buf, 1);
Packit bd23c0
  }
Packit bd23c0
Packit bd23c0
  ${*$data}{'net_ftp_eof'} = 1;    # fake
Packit bd23c0
Packit bd23c0
  $ftp->abort;                     # this will close me
Packit bd23c0
}
Packit bd23c0
Packit bd23c0
Packit bd23c0
sub _close {
Packit bd23c0
  my $data = shift;
Packit bd23c0
  my $ftp  = ${*$data}{'net_ftp_cmd'};
Packit bd23c0
Packit bd23c0
  $data->SUPER::close();
Packit bd23c0
Packit bd23c0
  delete ${*$ftp}{'net_ftp_dataconn'}
Packit bd23c0
    if defined $ftp
Packit bd23c0
    && exists ${*$ftp}{'net_ftp_dataconn'}
Packit bd23c0
    && $data == ${*$ftp}{'net_ftp_dataconn'};
Packit bd23c0
}
Packit bd23c0
Packit bd23c0
Packit bd23c0
sub close {
Packit bd23c0
  my $data = shift;
Packit bd23c0
  my $ftp  = ${*$data}{'net_ftp_cmd'};
Packit bd23c0
Packit bd23c0
  if (exists ${*$data}{'net_ftp_bytesread'} && !${*$data}{'net_ftp_eof'}) {
Packit bd23c0
    my $junk;
Packit bd23c0
    eval { local($SIG{__DIE__}); $data->read($junk, 1, 0) };
Packit bd23c0
    return $data->abort unless ${*$data}{'net_ftp_eof'};
Packit bd23c0
  }
Packit bd23c0
Packit bd23c0
  $data->_close;
Packit bd23c0
Packit bd23c0
  return unless defined $ftp;
Packit bd23c0
Packit bd23c0
  $ftp->response() == CMD_OK
Packit bd23c0
    && $ftp->message =~ /unique file name:\s*(\S*)\s*\)/
Packit bd23c0
    && (${*$ftp}{'net_ftp_unique'} = $1);
Packit bd23c0
Packit bd23c0
  $ftp->status == CMD_OK;
Packit bd23c0
}
Packit bd23c0
Packit bd23c0
Packit bd23c0
sub _select {
Packit bd23c0
  my ($data, $timeout, $do_read) = @_;
Packit bd23c0
  my ($rin, $rout, $win, $wout, $tout, $nfound);
Packit bd23c0
Packit bd23c0
  vec($rin = '', fileno($data), 1) = 1;
Packit bd23c0
Packit bd23c0
  ($win, $rin) = ($rin, $win) unless $do_read;
Packit bd23c0
Packit bd23c0
  while (1) {
Packit bd23c0
    $nfound = select($rout = $rin, $wout = $win, undef, $tout = $timeout);
Packit bd23c0
Packit bd23c0
    last if $nfound >= 0;
Packit bd23c0
Packit bd23c0
    croak "select: $!"
Packit bd23c0
      unless $!{EINTR};
Packit bd23c0
  }
Packit bd23c0
Packit bd23c0
  $nfound;
Packit bd23c0
}
Packit bd23c0
Packit bd23c0
Packit bd23c0
sub can_read {
Packit bd23c0
  _select(@_[0, 1], 1);
Packit bd23c0
}
Packit bd23c0
Packit bd23c0
Packit bd23c0
sub can_write {
Packit bd23c0
  _select(@_[0, 1], 0);
Packit bd23c0
}
Packit bd23c0
Packit bd23c0
Packit bd23c0
sub cmd {
Packit bd23c0
  my $ftp = shift;
Packit bd23c0
Packit bd23c0
  ${*$ftp}{'net_ftp_cmd'};
Packit bd23c0
}
Packit bd23c0
Packit bd23c0
Packit bd23c0
sub bytes_read {
Packit bd23c0
  my $ftp = shift;
Packit bd23c0
Packit bd23c0
  ${*$ftp}{'net_ftp_bytesread'} || 0;
Packit bd23c0
}
Packit bd23c0
Packit bd23c0
1;
Packit bd23c0
Packit bd23c0
__END__
Packit bd23c0
Packit bd23c0
=head1 NAME
Packit bd23c0
Packit bd23c0
Net::FTP::dataconn - FTP Client data connection class
Packit bd23c0
Packit bd23c0
=head1 DESCRIPTION
Packit bd23c0
Packit bd23c0
Some of the methods defined in C<Net::FTP> return an object which will
Packit bd23c0
be derived from this class. The dataconn class itself is derived from
Packit bd23c0
the C<IO::Socket::INET> class, so any normal IO operations can be performed.
Packit bd23c0
However the following methods are defined in the dataconn class and IO should
Packit bd23c0
be performed using these.
Packit bd23c0
Packit bd23c0
=over 4
Packit bd23c0
Packit bd23c0
=item read ( BUFFER, SIZE [, TIMEOUT ] )
Packit bd23c0
Packit bd23c0
Read C<SIZE> bytes of data from the server and place it into C<BUFFER>, also
Packit bd23c0
performing any <CRLF> translation necessary. C<TIMEOUT> is optional, if not
Packit bd23c0
given, the timeout value from the command connection will be used.
Packit bd23c0
Packit bd23c0
Returns the number of bytes read before any <CRLF> translation.
Packit bd23c0
Packit bd23c0
=item write ( BUFFER, SIZE [, TIMEOUT ] )
Packit bd23c0
Packit bd23c0
Write C<SIZE> bytes of data from C<BUFFER> to the server, also
Packit bd23c0
performing any <CRLF> translation necessary. C<TIMEOUT> is optional, if not
Packit bd23c0
given, the timeout value from the command connection will be used.
Packit bd23c0
Packit bd23c0
Returns the number of bytes written before any <CRLF> translation.
Packit bd23c0
Packit bd23c0
=item bytes_read ()
Packit bd23c0
Packit bd23c0
Returns the number of bytes read so far.
Packit bd23c0
Packit bd23c0
=item abort ()
Packit bd23c0
Packit bd23c0
Abort the current data transfer.
Packit bd23c0
Packit bd23c0
=item close ()
Packit bd23c0
Packit bd23c0
Close the data connection and get a response from the FTP server. Returns
Packit bd23c0
I<true> if the connection was closed successfully and the first digit of
Packit bd23c0
the response from the server was a '2'.
Packit bd23c0
Packit bd23c0
=back
Packit bd23c0
Packit bd23c0
=cut