diff options
author | Graham Barr <gbarr@pobox.com> | 1996-01-02 08:46:21 -0600 |
---|---|---|
committer | Graham Barr <gbarr@pobox.com> | 2009-01-24 15:13:57 -0600 |
commit | fd77ae996c2072b825071bc09b82558c9210c4ba (patch) | |
tree | 217e388b50dd0585d12911927cb80ee25e223841 | |
parent | 80b46cb092321cdd20f394eb666b6b722aa86dcf (diff) | |
download | perl-libnet-fd77ae996c2072b825071bc09b82558c9210c4ba.tar.gz |
Net-FTP-1.18_1
-rw-r--r-- | ftp/ChangeLog | 26 | ||||
-rw-r--r-- | ftp/MANIFEST | 8 | ||||
-rw-r--r-- | ftp/Makefile.PL | 185 | ||||
-rw-r--r-- | ftp/README | 56 | ||||
-rw-r--r-- | ftp/README.CPAN | 76 | ||||
-rw-r--r-- | ftp/README.DEBUG | 13 | ||||
-rw-r--r-- | ftp/lib/Net/FTP.pm | 333 | ||||
-rw-r--r-- | ftp/lib/Net/Netrc.pm | 123 | ||||
-rw-r--r-- | ftp/lib/Net/Socket.pm (renamed from ftp/lib/IO/Socket.pm) | 51 | ||||
-rw-r--r-- | ftp/t/require.t | 11 |
10 files changed, 612 insertions, 270 deletions
diff --git a/ftp/ChangeLog b/ftp/ChangeLog index 9f1bb51..dd8eea4 100644 --- a/ftp/ChangeLog +++ b/ftp/ChangeLog @@ -1,3 +1,29 @@ +Thu Apr 25 1996 Graham Barr <bodg@tiuk.ti.com> + + o Fixed a bug in A::read when a line ended in "\r\n". Replaced regexp + with explicit substr and chop + +Mon Mar 18 1996 Graham Barr <bodg@tiuk.ti.com> + + o Removed parse_dir and file_mode as there is now a File::Listing + package avaliable with libwww which can do directory listings + +Tue Mar 5 1996 Graham Barr <bodg@tiuk.ti.com> + + o Changes to Net::FTP::A::read for files which have very long + lines and do not fit into a single buffer + o Changes to responce for knackered FTP servers which send + a Transfer Complete response before they send the data ?? :-( + +Wed Jan 3 1996 Graham Barr <bodg@tiuk.ti.com> + + o Moved netrc stuff into Net::Netrc + +Tue Dec 19 1995 Graham Barr <bodg@tiuk.ti.com> + + o Fixed a problem with Net::FTP::A:read which caused the last line + of a transfer to be dropped if it did not end in a \n + Mon Dec 11 1995 Graham Barr <bodg@tiuk.ti.com> o Introduced IO::Socket which eventually will be released diff --git a/ftp/MANIFEST b/ftp/MANIFEST index 9bd1df5..436e029 100644 --- a/ftp/MANIFEST +++ b/ftp/MANIFEST @@ -2,6 +2,10 @@ ChangeLog MANIFEST This file Makefile.PL Makemaker makefile README Copyright -lib/IO/Socket.pm (v1.01) Generic socket package -lib/Net/FTP.pm (v1.08) FTP package +README.CPAN +README.DEBUG +lib/Net/Socket.pm TEMP replacement for IO::Socket +lib/Net/FTP.pm (v1.17) FTP package +lib/Net/Netrc.pm (v0) t/dummy.t +t/require.t diff --git a/ftp/Makefile.PL b/ftp/Makefile.PL index a399259..baffa1d 100644 --- a/ftp/Makefile.PL +++ b/ftp/Makefile.PL @@ -1,69 +1,172 @@ # This -*- perl -*- script makes the Makefile -# $Id: Makefile.PL,v 1.4 1995/12/11 13:16:04 gbarr Exp gbarr $ +# $Id: Makefile.PL,v 1.8 1996/03/28 08:03:48 gbarr Exp $ + +#--- Configuration section --- + +%install_pgm = (); + +#--- End User Configuration - You should not have to change anything below this line + +$NAME = 'Net::FTP'; + +$lib_only = 0; + +#--- End Configuration use ExtUtils::MakeMaker; use ExtUtils::Manifest qw(maniread); -use lib qw(./lib); +use FileHandle; -sub initialize { - local($_); +#--- MY package - my $manifest = maniread(); +sub MY::libscan +{ + my($self,$path) = @_; + + return '' + if($path =~ m:/(RCS|CVS|SCCS)/: || + $path =~ m:[~%]$: || + $path =~ m:\.(orig|rej)$: + ); + + $path; +} - $Version = eval { require "./lib/Net/FTP.pm"; Net::FTP->Version . "b"; } || "0.00"; +#--- End MY package - my %pl_files = (); - my @exe_files = (); +sub doIt +{ + my $manifest = maniread(); + + my %PL_FILES = (); + my %EXE_FILES = (); + my %macro = (); + #--- Install what ? + foreach (keys %$manifest) { - $pl_files{$_} = $1 if(/(.*)\.PL\Z/ && !/^Makefile.PL$/); - push(@exe_files,$_) if(m#\bbin/# && !m#demo#); + $PL_FILES{$_} = $1 if(/(.*)\.PL\Z/ && !/^Makefile.PL$/); + + if(m#\bbin/# && !m#demo#) { + my $f = $_; + + $f =~ s#\.PL$##; + + if(defined $install_pgm{$f} && $install_pgm{$f}) { + $EXE_FILES{$f} = 1 if(-x $f || -f "$f.PL"); + } + } } - - my $hash = { - VERSION => $Version, - NAME => 'Net::FTP', - SKIP => [qw(static dynamic)], - PL_FILES => \%pl_files, - EXE_FILES => \@exe_files, - + + %EXE_FILES = () if($lib_only); + + #--- Dist. VERSION + + unless(defined $VERSION) + { + my($pm,$rcs); + my $fh = new FileHandle; + + ($pm = $NAME . ".pm") =~ s,.*::,,; + ($pm = $NAME . ".pm") =~ s,::,/,g unless(-f $pm); + $pm = "lib/" . $pm unless(-f $pm); + + if($fh->open($pm)) + { + while (<$fh>) + { + chomp; + next unless /\$([\w:]*\bVERSION)\b.*=/; + my $module_version_variable = $1; + my($eval) = "$_;"; + eval $eval; + die "Could not eval '$eval': $@" if $@; + $VERSION = $ {$module_version_variable}; + last; + } + close $fh; + } + + ($rcs = $pm) =~ s:([^/]+\.pm):RCS/$1,v:; + + # update VERSION when checked in + $macro{CONFIGDEP} = $rcs + if(-f $rcs); + } + + $VERSION .= $RELTYPE + if(defined $RELTYPE); + + #--- Write the Makefile + + %hash = ( + VERSION => $VERSION, + NAME => $NAME, + PL_FILES => \%PL_FILES, + EXE_FILES => [ keys %EXE_FILES ], + + 'linkext' => {LINKTYPE => '' }, 'dist' => {COMPRESS => 'gzip -9f', SUFFIX => 'gz', POSTOP => 'mv $(DISTNAME)-$(VERSION).tar.gz ../', DIST_DEFAULT => 'all tardist', CI => 'ci -l' }, + + 'clean' => {FILES => join(" ", qw(*% *.html *.bak *.old lib/*% lib/*/*%),values %PL_FILES)}, + ); + + $hash{macro} = \%macro + if(%macro); + + $hash{DISTNAME} = $DISTNAME + if(defined $DISTNAME); + + WriteMakefile( %hash ) ; + +} - 'linkext' => {LINKTYPE => '' }, - 'clean' => {FILES => '*% *.html *.bak *.old lib/*% lib/*/*% $(EXE_FILES)'}, - }; +#--- UNIVERSAL package - $hash; -} +sub UNIVERSAL::require_version +{ + my($self, $wanted) = @_; + my $pkg = ref $self || $self; + my $version = ${"${pkg}::VERSION"} || "(undef)"; -if ($ExtUtils::MakeMaker::Version < 4.17) { - my $hash = initialize(); - WriteMakefile( %$hash ) ; -} -else { - WriteMakefile( CONFIGURE => \&initialize ) ; + die("$pkg $wanted required--this is only version $version") + if $version < $wanted; + + $version; } +#--- End UNIVERSAL package +#--- Installation check -sub MY::test { - q{ -TEST_VERBOSE=0 +sub require_version +{ + my($pkg,$version,$msg) = @_; -test: - $(FULLPERL) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -e 'use Test::Harness qw(&runtests $$verbose); $$verbose=$(TEST_VERBOSE); runtests @ARGV;' t/*.t + $| = 1; + print "Checking for $pkg..."; -}; -} + eval " require $pkg; $pkg->require_version('$version') "; -sub MY::libscan { - return '' if m:/(RCS|CVS)/:; - return '' if m/[~%]$/; - return '' if m/\.(orig|rej)$/; - $_; + print $@ ? "failed\n" . $msg : "ok\n"; } +#--- Check for Socket + +require_version( +'Socket', +'1.30', +" +For Net::FTP to work you require the Socket distribution +version 1.30 or later. +" +); + +#--- Write the Makefile + +doIt(); + @@ -1,6 +1,53 @@ -Copyright (c) 1995 Graham Barr <Graham.Barr@tiuk.ti.com>. All rights -reserved. This program is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. +This distribution 1.18_1 is identical to 1.18 except that IO::Socket has been +renamed as Net::Socket. This is because the IO::* modules are having a serious +re-fit. + +This is the README file for Net::FTP + +Net::FTP is a perl5 package which implements the client side of +a FTP connection as per RFC959 + +In order to use this package you will need Perl version 5.001m or +better. The File::Listing package can be found in the libwww distribution. +To use the complete libwww distribution you require 5.002, If you +do not have 5.002 File::Listing can be extracted from libwww and will work +with 5.001 + +See lib/Net/FTP.pm for details of the library. See ChangeLog for recent +changes. POD style documentation is included in all/most modules and scripts. +You should be able to use the 'perldoc' utility to extract documentation +from these files. + +Before building this extension you will require the following modules. The +building of the Makefile will abort if you do not have the required versions. +All of these modules should be avaliable from CPAN (see README.CPAN for +more information) + + Socket v1.03 + +You install the library by running these commands: + + perl Makefile.PL + make + make test + make install + +You can edit the configuration section of Makefile.PL to select which +programs to install in addition to the library itself. If you don't +want to install any programs at all then make the initial Makefile with: + + perl Makefile.PL -l + + +Please report any bugs/suggestions to <Graham.Barr@tiuk.ti.com> + +When reporting bugs/problems please, if possible, include a transcript of +a run with the Debug option turned on. + +Copyright 1996 Graham Barr. All rights reserved. + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. This release has got a significant number of changes sine the last release so is probably prone to a few bugs. @@ -15,5 +62,6 @@ future releases will be 100% compatable. *** NOTE *** NOTE *** NOTE *** NOTE *** NOTE *** NOTE *** NOTE *** NOTE *** -Please report any bugs/suggestions to <Graham.Barr@tiuk.ti.com>. +Share and Enjoy! +Graham <Graham.Barr@tiuk.ti.com> diff --git a/ftp/README.CPAN b/ftp/README.CPAN new file mode 100644 index 0000000..e15683e --- /dev/null +++ b/ftp/README.CPAN @@ -0,0 +1,76 @@ + +Welcome to the CPAN, the Comprehensive Perl Archive Network. + +This document describes the CPAN itself, the Network. + +--- + +Network + +The master CPAN site is at ftp://ftp.funet.fi/ +(Finland, Europe). + +The list of the registered CPAN sites follows. +Please note that the sorting order is alphabetical on fields: + + + continent - country/state - ftp-url + + +and thus the North American servers happen to be listed last (for the +moment, anyway, no Oceanian or South American sites volunteered, yet). + + +Registered CPAN sites + + + Africa + + South Africa ftp://ftp.is.co.za/programming/perl/CPAN/ + + Asia + + Japan ftp://ftp.lab.kdd.co.jp/lang/perl/CPAN/ + Taiwan ftp://dongpo.math.ncu.edu.tw/perl/CPAN/ + + Australasia + + Australia ftp://coombs.anu.edu.au/pub/perl/ + ftp://ftp.mame.mu.oz.au/pub/perl/CPAN/ + New Zealand ftp://ftp.tekotago.ac.nz/pub/perl/CPAN/ + + Europe + + Finland ftp://ftp.funet.fi/pub/languages/perl/CPAN/ + France ftp://ftp.ibp.fr/pub/perl/CPAN/ + ftp://ftp.pasteur.fr/pub/computing/unix/perl/CPAN/ + Germany ftp://ftp.leo.org/pub/comp/programming/languages/perl/CPAN/ + ftp://ftp.rz.ruhr-uni-bochum.de/pub/CPAN/ + the Netherlands ftp://ftp.cs.ruu.nl/pub/PERL/CPAN/ + Portugal ftp://ftp.ci.uminho.pt/pub/lang/perl/ + Slovenia ftp://ftp.arnes.si/software/perl/CPAN/ + Sweden ftp://ftp.sunet.se/pub/lang/perl/CPAN/ + Switzerland ftp://ftp.switch.ch/mirror/CPAN/ + UK ftp://ftp.demon.co.uk/pub/mirrors/perl/CPAN/ + ftp://unix.hensa.ac.uk/mirrors/perl-CPAN/ + + North America + + Florida ftp://ftp.cis.ufl.edu/pub/perl/CPAN/ + Illinois ftp://uiarchive.cso.uiuc.edu/pub/lang/perl/CPAN/ + Massachusetts ftp://ftp.delphi.com/pub/mirrors/packages/perl/CPAN/ + Oklahoma ftp://ftp.uoknor.edu/mirrors/CPAN/ + Texas ftp://ftp.sedl.org/pub/mirrors/CPAN/ + ftp://ftp.sterling.com/programming/languages/perl/ + + + +We apologise for the diversity of the CPAN path names but +having identical and hopefully as short as possible path names +across several separate ftp sites is well nigh impossible. + +Feedback + +You can send email +to the CPAN administrators, cpan-adm@ftp.funet.fi. + diff --git a/ftp/README.DEBUG b/ftp/README.DEBUG new file mode 100644 index 0000000..0783569 --- /dev/null +++ b/ftp/README.DEBUG @@ -0,0 +1,13 @@ +When debugging a script which uses Net::FTP please try the following + + Ensure you have the most upto date version of the Net-FTP distribution + from CPAN + + Try adding 'Debug => 1' to the Net::FTP->new line and see if there is + anything obvious in the transcript + + Failing that, and you belive it is a real Net::FTP problem then mail the + transcript to <bodg@tiuk.ti.com>. I run a mail filter here so I would + appreciate the text Net::FTP to be in the subject. + + diff --git a/ftp/lib/Net/FTP.pm b/ftp/lib/Net/FTP.pm index a10c483..c98652b 100644 --- a/ftp/lib/Net/FTP.pm +++ b/ftp/lib/Net/FTP.pm @@ -30,7 +30,8 @@ Net::FTP - FTP Client class =head1 DESCRIPTION -C<Net::FTP> is a class implementing a simple FTP client in Perl. +C<Net::FTP> is a class implementing a simple FTP client in Perl as described +in RFC959 =head2 TO BE CONTINUED ... @@ -39,11 +40,11 @@ C<Net::FTP> is a class implementing a simple FTP client in Perl. require 5.001; use Socket 1.3; use Carp; -use IO::Socket; +use Net::Socket; -@ISA = qw(IO::Socket); +@ISA = qw(Net::Socket); -$VERSION = sprintf("%d.%02d", q$Revision: 1.8 $ =~ /(\d+)\.(\d+)/); +$VERSION = sprintf("%d.%02d", q$Revision: 1.18 $ =~ /(\d+)\.(\d+)/); sub Version { $VERSION } use strict; @@ -63,19 +64,20 @@ remote host. Possible options are: =cut -sub FTP_READY { 0 } -sub FTP_RESPONSE { 1 } -sub FTP_XFER { 2 } +sub FTP_READY { 0 } # Ready +sub FTP_RESPONSE { 1 } # Waiting for a response +sub FTP_XFER { 2 } # Doing data xfer sub new { my $pkg = shift; my $host = shift; my %arg = @_; - my $me = bless IO::Socket->new(Peer => $host, + my $me = bless Net::Socket->new(Peer => $host, Service => 'ftp', Port => $arg{Port} || 'ftp' ), $pkg; + ${*$me} = ""; # partial response text @{*$me} = (); # Last response text %{*$me} = (%{*$me}, # Copy current values @@ -95,6 +97,9 @@ sub new { $me->autoflush(1); + $me->debug($arg{Debug}) + if(exists $arg{Debug}); + unless(2 == $me->response()) { $me->close(); @@ -120,8 +125,13 @@ sub debug { my $me = shift; my $debug = ${*$me}{Debug}; - ${*$me}{Debug} = 0 + shift - if @_; + if(@_) + { + ${*$me}{Debug} = 0 + shift; + + printf STDERR "\n$me VERSION %s\n", $Net::FTP::VERSION + if(${*$me}{Debug}); + } $debug; } @@ -183,8 +193,14 @@ sub login { my $acct = shift if(defined $pass); my $ok; - ($user,$pass,$acct) = netrc(${*$me}{FtpHost}) - unless defined $user; + unless(defined $user) + { + require Net::Netrc; + my $rc = Net::Netrc->lookup(${*$me}{FtpHost}); + + ($user,$pass,$acct) = $rc->lpa() + if $rc; + } $user = "anonymous" unless defined $user; @@ -265,6 +281,7 @@ sub get { my $me = shift; my $remote = shift; my $local = shift; + my $where = shift || 0; my($loc,$len,$buf,$resp,$localfd,$data); local *FD; @@ -281,15 +298,21 @@ sub get { { $loc = \*FD; - unless(open($loc,">$local")) + unless(($where) ? open($loc,">>$local") : open($loc,">$local")) { carp "Cannot open Local file $local: $!\n"; return undef; } } - $data = $me->retr($remote) or - return undef; + if ($where) { + $data = $me->rest_cmd($where,$remote) or + return undef; + } + else { + $data = $me->retr($remote) or + return undef; + } $buf = ''; @@ -302,9 +325,7 @@ sub get { close($loc) unless $localfd; - $resp = $data->close(); - - 200 <= $resp && $resp < 300; + $data->close() == 2; # implied $me->response } sub cwd { @@ -315,6 +336,13 @@ sub cwd { : $me->CWD($dir); } +sub pwd { + my $me = shift; + + $me->PWD() ? ($me->message =~ /\"([^\"]+)/)[0] + : undef; +} + sub put { shift->send("stor",@_) } sub put_unique { shift->send("stou",@_) } sub append { shift->send("appe",@_) } @@ -399,7 +427,7 @@ sub port { # create a Listen socket at same address as the command socket - $listen = IO::Socket->new(Listen => 5, + $listen = Net::Socket->new(Listen => 5, Service => 'ftp', Addr => $me->sockhost, ); @@ -448,7 +476,7 @@ sub timeout { sub accept { my $me = shift; - + return undef unless defined ${*$me}{LISTEN}; my $data = ${*$me}{LISTEN}->accept; @@ -487,25 +515,30 @@ sub list_cmd { my $cmd = lc shift; my $data = $me->$cmd(@_); - die "undef" unless(defined $data); + return undef + unless(defined $data); bless $data, "Net::FTP::A"; # Force ASCII mode my $databuf = ''; - my $list = []; + my $buf = ''; while($data->read($databuf,1024)) { - push(@{$list}, split(/\n/,$databuf)); ## break into lines + $buf .= $databuf; } + my $list = [ split(/\n/,$buf) ]; + + $data->close(); + wantarray ? @{$list} : $list; } sub data_cmd { my $me = shift; + my $cmd = uc shift; my $ok = 1; my $pasv = defined ${*$me}{Pasv} ? 1 : 0; - my $cmd = uc shift; $ok = $me->port unless $pasv || defined ${*$me}{Port}; @@ -518,6 +551,27 @@ sub data_cmd { : undef; } +sub rest_cmd { + my $me = shift; + my $ok = 1; + my $pasv = defined ${*$me}{Pasv} ? 1 : 0; + my $where = shift; + my $file = shift; + + $ok = $me->port + unless $pasv || defined ${*$me}{Port}; + + $ok = $me->REST($where) + if $ok; + + $ok = $me->RETR($file) + if $ok; + + return $pasv ? $ok + : $ok ? $me->accept() + : undef; +} + sub cmd { my $me = shift; @@ -538,7 +592,7 @@ sub send_cmd { ${*$me}{State} = FTP_RESPONSE; - printf STDERR "$me>> %s\n", $cmd=~/^(pass|resp)/i ? "$1 ...." : $cmd + printf STDERR "\n$me>> %s", $cmd=~/^(pass|resp)/i ? "$1 ....\n" : $cmd if $me->debug; } @@ -575,14 +629,16 @@ sub response { my($code,$more,$rin,$rout,$partial,$buf) = (undef,0,'','','',''); @{*$me} = (); # the responce + $buf = ${*$me}; + my @buf = (); vec($rin,fileno($me),1) = 1; do { - if(($timeout==0) || select($rout=$rin, undef, undef, $timeout)) + if(length($buf) || ($timeout==0) || select($rout=$rin, undef, undef, $timeout)) { - unless(sysread($me, $buf, 1024)) + unless(length($buf) || sysread($me, $buf, 1024)) { carp "Unexpected EOF on command channel"; return undef; @@ -590,21 +646,25 @@ sub response { substr($buf,0,0) = $partial; ## prepend from last sysread - my @buf = split(/\r?\n/, $buf); ## break into lines + @buf = split(/\r?\n/, $buf); ## break into lines $partial = (substr($buf, -1, 1) eq "\n") ? '' : pop(@buf); - my $cmd; - foreach $cmd (@buf) + $buf = ""; + + while (@buf) { + my $cmd = shift @buf; print STDERR "$me<< $cmd\n" if $me->debug; ($code,$more) = ($1,$2) if $cmd =~ /^(\d\d\d)(.)/; - + push(@{*$me},$'); + + last unless(defined $more && $more eq "-"); } } else @@ -613,7 +673,10 @@ sub response { return undef; } } - while(length($partial) || (defined $more && $more eq "-")); + while((scalar(@{*$me}) == 0) || (defined $more && $more eq "-")); + + ${*$me} = @buf ? join("\n",@buf,"") : ""; + ${*$me} .= $partial; ${*$me}{Code} = $code; ${*$me}{State} = FTP_READY; @@ -621,138 +684,6 @@ sub response { substr($code,0,1); } -sub netrc { - my $host = shift; - my $file = (getpwuid($>))[7] . "/.netrc"; - my($login,$pass,$acct) = (undef,undef,undef); - local *NETRC; - local $_; - - my @stat = stat($file); - - if(@stat) - { - if($stat[2] & 077) - { - carp "Bad permissions: $file"; - return (); - } - if($stat[4] != $<) - { - carp "Not owner: $file"; - return (); - } - } - - if(open(NETRC,$file)) - { - my($mach,$macdef,$tok,@tok) = (0,0); - -LINE_LOOP: - while(<NETRC>) - { - $macdef = 0 if /\A\n\Z/; - - next if $macdef; - - push(@tok, split(/[\s\n]+/, $_)); - -TOKEN_LOOP: - while(@tok) - { - if($tok[0] eq "default") - { - last LINE_LOOP if $mach; - - shift(@tok); - $mach = 1; - ($login,$pass,$acct) = (undef,undef,undef); - - next TOKEN_LOOP; - } - - last TOKEN_LOOP unless @tok > 1; - $tok = shift(@tok); - - if($tok eq "machine") - { - last LINE_LOOP if $mach; - $mach = 1 if $host eq shift(@tok); - ($login,$pass,$acct) = (undef,undef,undef); - } - elsif($tok eq "login") - { - $login = shift(@tok); - } - elsif($tok eq "password") - { - $pass = shift(@tok); - } - elsif($tok eq "account") - { - $acct = shift(@tok); - } - elsif($tok eq "macdef") - { - $macdef = 1; - } - } - } - close(NETRC); - - return ($login,$pass,$acct) - if $mach; - } - - return (); -} - -sub file_mode { - local $_ = shift; - my $mode = 0; - my($type,$ch); - - s/^(.)// and $type = $1; - - foreach $ch (split(//,$_)) - { - $mode <<= 1; - $mode |= 1 unless $ch eq "-"; - } - - $type eq "d" and $mode |= 0040000 or # Directory - $type eq "l" and $mode |= 0120000 or # Symbolic Link - $mode |= 0100000; # Regular File - - $mode |= 0004000 if /^...s....../i; - $mode |= 0002000 if /^......s.../i; - $mode |= 0001000 if /^.........t/i; - - $mode; -} - -sub parse_dir -{ - my $me = shift; - my $dir = shift; - my @files = (); - - local $_; - - foreach (@$dir) - { - if(/^([\-FlrwxsStTdD]{10}).*(\w+)\s+(\w*\D)\s*(\d+)\s+(\w{3}\s+\d+\s*(\d+:\d+|\d{4}))\s+(\S+)(\s+->\s+(\S+))?/ ) - { - my($mode,$owner,$group,$size,$date,$file,$link) = ($1,$2,$3,$4,$5,$7,$9); - - $mode = file_mode($mode); - push(@files, [$mode, $owner, $group, $size, $date, $file, $link]); - } - } - wantarray ? @files : \@files; -} - - ;######################################## ;# ;# RFC959 commands @@ -782,6 +713,7 @@ sub RNFR { shift->send_cmd("RNFR",@_)->response() == 3} sub RNTO { shift->send_cmd("RNTO",@_)->response() == 2} sub ACCT { shift->send_cmd("ACCT",@_)->response() == 2} sub RESP { shift->send_cmd("RESP",@_)->response() == 2} +sub REST { shift->send_cmd("REST",@_)->response() == 3} sub USER { my $ok = shift->send_cmd("USER",@_)->response();($ok == 2 || $ok == 3) ? $ok : 0;} sub PASS { my $ok = shift->send_cmd("PASS",@_)->response();($ok == 2 || $ok == 3) ? $ok : 0;} sub AUTH { my $ok = shift->send_cmd("AUTH",@_)->response();($ok == 2 || $ok == 3) ? $ok : 0;} @@ -795,10 +727,10 @@ sub SYST { no_imp; } sub STAT { no_imp; } sub STRU { no_imp; } sub REIN { no_imp; } -sub REST { no_imp; } package Net::FTP::dataconn; use Carp; +no strict 'vars'; sub abort { my $fd = shift; @@ -812,15 +744,24 @@ sub close { my $fd = shift; my $ftp = ${*$fd}{Cmd}; - $fd->IO::Socket::close(); + $fd->Net::Socket::close(); delete ${*$ftp}{DATA}; $ftp->response(); } +sub timeout { + my $me = shift; + my $timeout = ${*$me}{Timeout}; + + ${*$me}{Timeout} = 0 + shift if(@_); + + $timeout; +} + sub _select { my $fd = shift; - my $timeout = shift; + local *timeout = \$_[0]; shift; my $rw = shift; my($rin,$win); @@ -842,14 +783,14 @@ sub _select { sub can_read { my $fd = shift; - my $timeout = shift; + local *timeout = \$_[0]; $fd->_select($timeout,1); } sub can_write { my $fd = shift; - my $timeout = shift; + local *timeout = \$_[0]; $fd->_select($timeout,0); } @@ -860,8 +801,6 @@ sub cmd { ${*$me}{Cmd}; } -# should I have a close sub which calls response ?? - @Net::FTP::L::ISA = qw(Net::FTP::I); @Net::FTP::E::ISA = qw(Net::FTP::I); @@ -875,29 +814,51 @@ no strict 'vars'; sub read { my $fd = shift; local *buf = \$_[0]; shift; - my $size = shift || croak 'read($buf,$size,[$timeout])'; - my $timeout = @_ ? shift : ${*$fd}{Timeout}; + my $size = shift || croak 'read($buf,$size,[$offset])'; + my $offset = shift || 0; + my $timeout = ${*$fd}{Timeout}; + my $l; - $fd->can_read($timeout) or + croak "Bad offset" + if($offset < 0); + + $offset = length $buf + if($offset > length $buf); + + $l = 0; + READ: + { + $fd->can_read($timeout) or croak "Timeout"; - # this needs a bit more thought so I return the correct number of bytes !! + my $n = sysread($fd, ${*$fd}, $size, length ${*$fd}); - $buf = ''; + return $n + unless($n >= 0); - my $n = sysread($fd, $buf, $size); + my $lf = substr(${*$fd},-1,1) eq "\r" ? chop(${*$fd}) + : ""; - if($n >= 0) - { - substr($buf,0,0) = ${*$fd}; - $buf =~ s/\r\n/\n/g; - $buf =~ s/([^\n]*)\Z//so; - ${*$fd} = $1; + ${*$fd} =~ s/\r\n/\n/go; + + substr($buf,$offset) = ${*$fd}; + + $l += length(${*$fd}); + $offset += length(${*$fd}); + + ${*$fd} = $lf; + + redo READ + if($l == 0 && $n > 0); - $n = length $buf; + if($n == 0 && $l == 0) + { + substr($buf,$offset) = ${*$fd}; + ${*$fd} = ""; + } } - $n; + return $l; } sub write { @@ -964,7 +925,7 @@ Graham Barr <Graham.Barr@tiuk.ti.com> =head2 REVISION -$Revision: 1.8 $ +$Revision: 1.17 $ =head2 COPYRIGHT diff --git a/ftp/lib/Net/Netrc.pm b/ftp/lib/Net/Netrc.pm new file mode 100644 index 0000000..58f0663 --- /dev/null +++ b/ftp/lib/Net/Netrc.pm @@ -0,0 +1,123 @@ +package Net::Netrc; + +use Carp; +use strict; + +my %netrc = (); + +sub _readrc { + my $host = shift; + my $file = (getpwuid($>))[7] . "/.netrc"; + my($login,$pass,$acct) = (undef,undef,undef); + local *NETRC; + local $_; + + $netrc{default} = undef; + + my @stat = stat($file); + + if(@stat) + { + if($stat[2] & 077) + { + carp "Bad permissions: $file"; + return (); + } + if($stat[4] != $<) + { + carp "Not owner: $file"; + return (); + } + } + + if(open(NETRC,$file)) + { + my($mach,$macdef,$tok,@tok) = (0,0); + + while(<NETRC>) + { + undef $macdef if /\A\n\Z/; + + if($macdef) + { + push(@$macdef,$_); + next; + } + + push(@tok, split(/[\s\n]+/, $_)); + +TOKEN: + while(@tok) + { + if($tok[0] eq "default") + { + shift(@tok); + $mach = $netrc{default} = {}; + + next TOKEN; + } + + last TOKEN unless @tok > 1; + $tok = shift(@tok); + + if($tok eq "machine") + { + my $host = shift @tok; + $mach = $netrc{$host} = {}; + } + elsif($tok =~ /^(login|password|account)$/) + { + next TOKEN unless $mach; + my $value = shift @tok; + $mach->{$1} = $value; + } + elsif($tok eq "macdef") + { + next TOKEN unless $mach; + my $value = shift @tok; + $mach->{macdef} = {} unless exists $mach->{macdef}; + $macdef = $mach->{machdef}{$value} = []; + } + } + } + close(NETRC); + } +} + +sub lookup { + my $pkg = shift; + my $mach = shift; + + _readrc() unless exists $netrc{default}; + + return bless \$mach if exists $netrc{$mach}; + + return bless \("default") if defined $netrc{default}; + + return undef; +} + +sub login { + my $me = shift; + $me = $netrc{$$me}; + exists $me->{login} ? $me->{login} : undef; +} + +sub account { + my $me = shift; + $me = $netrc{$$me}; + exists $me->{account} ? $me->{account} : undef; +} + +sub password { + my $me = shift; + $me = $netrc{$$me}; + exists $me->{password} ? $me->{password} : undef; +} + +sub lpa { + my $me = shift; + ($me->login, $me->password, $me->account); +} + +1; diff --git a/ftp/lib/IO/Socket.pm b/ftp/lib/Net/Socket.pm index a0f77a0..d24e625 100644 --- a/ftp/lib/IO/Socket.pm +++ b/ftp/lib/Net/Socket.pm @@ -1,42 +1,13 @@ -package IO::Socket; +package Net::Socket; =head1 NAME -IO::Socket - Socket filedescriptor class - -=head1 SYNOPSIS - - use IO::Socket; - - $sock = IO::Socket->new(Peer => $host, - Service => 'ftp', - ); - - $sock = IO::Socket->new(Listen => 5, - Proto => 'tcp' - ); - +Net::Socket - TEMPORARY Socket filedescriptor class, so Net::FTP still +works while IO::Socket is having a re-fit <GBARR> =head1 DESCRIPTION -C<IO::Socket> is a class which simplifies the creating of a socket. With -one function call it will do all the required lookups and system calls -to create the required socket. - -To create a socket connection to a foreign host C<ftp.uu.net> using -the C<ftp> service - - $sock = IO::Socket->new(Peer => $host, - Service => 'ftp', - ); - -If you want to use the same protocal as the C<ftp> service but provide -your own port number to connect to - - $sock = IO::Socket->new(Peer => $host, - Service => 'ftp', - Port => 2001, - ); +NO TEXT --- THIS MODULE IS TEMPORARY =cut @@ -48,7 +19,7 @@ require Exporter; @ISA = qw(Exporter); @EXPORT_OK = @Socket::EXPORT; -$VERSION = sprintf("%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/); +$VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/); sub Version { $VERSION } ## @@ -161,7 +132,7 @@ sub new { : undef; - if($type == SOCK_STREAM) + if($type == SOCK_STREAM || $destaddr) { croak "bad peer address" unless defined $destaddr; @@ -197,7 +168,7 @@ sub autoflush { =head2 accept -perform the system call C<accept> on the socket and return a new IO::Soscket +perform the system call C<accept> on the socket and return a new Net::Socket object. This object can be used to communicate with the client that was trying to connect. @@ -211,6 +182,12 @@ sub accept { accept($new,$sock) or croak "accept: $!"; + ${*$new}{Peername} = getpeername($new) or + croak "getpeername: $!"; + + ${*$new}{Sockname} = getsockname($new) or + croak "getsockname: $!"; + $new; } @@ -340,7 +317,7 @@ Graham Barr <Graham.Barr@tiuk.ti.com> =head1 REVISION -$Revision: 1.1 $ +$Revision: 1.2 $ =head1 COPYRIGHT diff --git a/ftp/t/require.t b/ftp/t/require.t new file mode 100644 index 0000000..5f37e74 --- /dev/null +++ b/ftp/t/require.t @@ -0,0 +1,11 @@ +# +# Dummy test file +# + + +print "1..1\n"; + +require IO::Socket; +require Net::FTP; + +print "ok 1\n"; |