AnyEvent-FTP
view release on metacpan or search on metacpan
lib/AnyEvent/FTP/Client.pm view on Meta::CPAN
package AnyEvent::FTP::Client;
use 5.010;
use Moo;
use AnyEvent;
use AnyEvent::Socket qw( tcp_connect );
use AnyEvent::Handle;
use Carp qw( croak );
use Socket qw( unpack_sockaddr_in inet_ntoa );
# ABSTRACT: Simple asynchronous ftp client
our $VERSION = '0.20'; # VERSION
with 'AnyEvent::FTP::Role::Event';
with 'AnyEvent::FTP::Client::Role::ResponseBuffer';
with 'AnyEvent::FTP::Client::Role::RequestBuffer';
__PACKAGE__->define_events(qw( error close send greeting ));
has _connected => (
is => 'rw',
default => sub { 0 },
init_arg => undef,
);
has timeout => (
is => 'rw',
default => sub { 30 },
);
has passive => (
is => 'ro',
default => sub { 1 },
);
foreach my $xfer (qw( Store Fetch List ))
{
my $cb = sub {
return shift->passive
? 'AnyEvent::FTP::Client::Transfer::Passive::'.$xfer
: 'AnyEvent::FTP::Client::Transfer::Active::'.$xfer;
};
has '_'.lc($xfer) => ( is => 'ro', lazy => 1, default => $cb, init_arg => undef ),
}
sub BUILD
{
my($self) = @_;
$self->on_error(sub { warn shift });
$self->on_close(sub {
$self->clear_command;
$self->_connected(0);
delete $self->{handle};
});
require ($self->passive
? 'AnyEvent/FTP/Client/Transfer/Passive.pm'
: 'AnyEvent/FTP/Client/Transfer/Active.pm');
return;
}
sub connect
{
my($self, $host, $port) = @_;
lib/AnyEvent/FTP/Client.pm view on Meta::CPAN
my($self, $path) = @_;
my $cv = AnyEvent->condvar;
$self->push_command(['SIZE', $path])->cb(sub {
my $res = eval { shift->recv };
if(my $error = $@)
{ $cv->croak($error) }
else
{ $cv->send($res->message->[0]) }
});
$cv;
}
(eval sprintf('sub %s { shift->push_command([ %s => @_])};1', lc $_, $_)) // die $@
for qw( CWD CDUP NOOP ALLO SYST TYPE STRU MODE REST MKD RMD STAT HELP DELE RNFR RNTO USER PASS ACCT MDTM );
sub quit
{
my($self) = @_;
my $cv = AnyEvent->condvar;
my $res;
$self->push_command(['QUIT'])->cb(sub {
$res = eval { shift->recv } // $@;
});
my $save = $self->{event}->{close};
$self->{event}->{close} = [ sub {
if(defined $res && $res->is_success)
{ $cv->send($res) }
elsif(defined $res)
{ $cv->croak($res) }
else
{ $cv->croak("did not receive QUIT response from server") }
$_->() for @$save;
$self->{event}->{close} = $save;
} ];
return $cv;
}
sub site
{
require AnyEvent::FTP::Client::Site;
AnyEvent::FTP::Client::Site->new(shift);
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
AnyEvent::FTP::Client - Simple asynchronous ftp client
=head1 VERSION
version 0.20
=head1 SYNOPSIS
Non blocking example:
use strict;
use warnings;
use AnyEvent;
use AnyEvent::FTP::Client;
my $client = AnyEvent::FTP::Client->new( passive => 1);
my $done = AnyEvent->condvar;
# connect to CPAN ftp server
$client->connect('ftp://ftp.cpan.org/pub/CPAN/src')->cb(sub {
# use binary mode
$client->type('I')->cb(sub {
# download the file directly into a filehandle
open my $fh, '>', 'perl-5.16.3.tar.gz';
$client->retr('perl-5.16.3.tar.gz', $fh)->cb(sub {
# notify anyone listening to $done that
# the transfer is complete
$done->send;
});
});
});
# receive the done message once the transfer is
# complete. In real code you'd probably not
# want to do this because your event loop may
# not support blocking.
$done->recv;
Same, but using recv to wait for each command to complete (not supported in all event loops):
use strict;
use warnings;
use AnyEvent;
use AnyEvent::FTP::Client;
my $client = AnyEvent::FTP::Client->new( passive => 1);
my $done = AnyEvent->condvar;
# connect to CPAN ftp server
$client->connect('ftp://ftp.cpan.org/pub/CPAN/src')->recv;
# use binary mode
$client->type('I')->recv;
# download the file directly into a filehandle
open my $fh, '>', 'perl-5.16.3.tar.gz';
( run in 0.640 second using v1.01-cache-2.11-cpan-39bf76dae61 )