/usr/share/perl5/Net/INET6Glue/FTP.pm is in libnet-inet6glue-perl 0.5-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | use strict;
use warnings;
package Net::INET6Glue::FTP;
our $VERSION = 0.4;
############################################################################
# implement EPRT, EPSV for Net::FTP to support IPv6
############################################################################
use Net::INET6Glue::INET_is_INET6;
use Net::FTP; # tested with version 2.77
BEGIN {
$Net::FTP::VERSION eq '2.77'
or warn "Not tested with Net::FTP version $Net::FTP::VERSION";
}
use Socket;
use Carp 'croak';
# implement EPRT
sub Net::FTP::_EPRT { shift->command("EPRT", @_)->response() == Net::FTP::CMD_OK }
sub Net::FTP::eprt {
@_ == 1 || @_ == 2 or croak 'usage: $ftp->eprt([PORT])';
my ($ftp,$port) = @_;
delete ${*$ftp}{net_ftp_intern_port};
unless ($port) {
my $listen = ${*$ftp}{net_ftp_listen} ||= IO::Socket::INET6->new(
Listen => 1,
Timeout => $ftp->timeout,
LocalAddr => $ftp->sockhost,
);
${*$ftp}{net_ftp_intern_port} = 1;
my $fam = ($listen->sockdomain == AF_INET) ? 1:2;
$port = "|$fam|".$listen->sockhost."|".$listen->sockport."|";
}
my $ok = $ftp->_EPRT($port);
${*$ftp}{net_ftp_port} = $port if $ok;
return $ok;
}
# implement EPSV
sub Net::FTP::_EPSV { shift->command("EPSV", @_)->response() == Net::FTP::CMD_OK }
sub Net::FTP::epsv {
my $ftp = shift;
@_ and croak 'usage: $ftp->epsv()';
delete ${*$ftp}{net_ftp_intern_port};
$ftp->_EPSV && $ftp->message =~ m{\(([\x33-\x7e])\1\1(\d+)\1\)}
? ${*$ftp}{'net_ftp_pasv'} = $2
: undef;
}
{
# redefine PORT and PASV so that they use EPRT and EPSV if necessary
no warnings 'redefine';
my $old_port = \&Net::FTP::port;
*Net::FTP::port =sub {
goto &$old_port if $_[0]->sockdomain == AF_INET or @_<1 or @_>2;
goto &Net::FTP::eprt;
};
my $old_pasv = \&Net::FTP::pasv;
*Net::FTP::pasv = sub {
goto &$old_pasv if $_[0]->sockdomain == AF_INET or @_<1 or @_>2;
goto &Net::FTP::epsv;
};
# redefined _dataconn to make use of the data it got from EPSV
# copied and adapted from Net::FTP::_dataconn
my $old_dataconn = \&Net::FTP::_dataconn;
*Net::FTP::_dataconn = sub {
goto &$old_dataconn if $_[0]->sockdomain == AF_INET;
my $ftp = shift;
my $pkg = "Net::FTP::" . $ftp->type;
eval "require $pkg";
$pkg =~ s/ /_/g;
delete ${*$ftp}{net_ftp_dataconn};
my $data;
if ( my $port = ${*$ftp}{net_ftp_pasv} ) {
$data = $pkg->new(
PeerAddr => $ftp->peerhost,
PeerPort => $port,
LocalAddr => ${*$ftp}{net_ftp_localaddr},
);
} elsif (my $listen = delete ${*$ftp}{net_ftp_listen}) {
$data = $listen->accept($pkg);
close($listen);
}
return if ! $data;
$data->timeout($ftp->timeout);
${*$ftp}{net_ftp_dataconn} = $data;
${*$data} = "";
${*$data}{net_ftp_cmd} = $ftp;
${*$data}{net_ftp_blksize} = ${*$ftp}{net_ftp_blksize};
return $data;
};
}
1;
=head1 NAME
Net::INET6Glue::FTP - adds IPv6 support to L<Net::FTP> by hotpatching
=head1 SYNOPSIS
use Net::INET6Glue::FTP;
use Net::FTP;
my $ftp = Net::FTP->new( '::1' );
$ftp->login(...)
=head1 DESCRIPTION
This module adds support for IPv6 by hotpatching support for EPRT and EPSV
commands into L<Net::FTP> and hotpatching B<pasv>, B<port> and B<_dataconn>
methods to make use of EPRT and EPSV on IPv6 connections.
It also includes L<Net::INET6Glue::INET_is_INET6> to make the L<Net::FTP>
sockets IPv6 capable.
=head1 COPYRIGHT
This module is copyright (c) 2008, Steffen Ullrich.
All Rights Reserved.
This module is free software. It may be used, redistributed and/or modified
under the same terms as Perl itself.
|