NAME

Net::FTP::Common - Perl extension for simplifying common usages of Net::FTP.

SYNOPSIS

our %netftp_cfg = 
   (Debug => 1, Timeout => 120);

our %common_cfg =    
   (
    # 
    # The first 2 options, if not present, 
    # lead to relying on .netrc for login
    #
    User => 'anonymous',           
    Pass => 'tbone@cpan.org',      

    #
    # Other options
    #

    LocalDir  => '/tmp/downloads'   # setup something for $ez->get
    LocalFile => 'delete.zip'       # setup something for $ez->get
    Host => 'ftp.fcc.gov',          # overwrite ftp.microsoft.com default
    RemoteDir  => '/',                    # automatic CD on remote machine to RemoteDir
    Type => 'A'                     # overwrite I (binary) TYPE default
    );

 # NOTE WELL!!! one constructor arg is  passed by reference, the 
 # other by value. This is inconsistent, but still it is A Good Thing.
 # Believe me! I thought about this. And I have a good reason for it:
 # This is to allow the least modification of legacy Net::FTP source code.

 $ez = Net::FTP::Common->new(\%common_cfg, %netftp_config); 

 # can we login to the machine?
 # Note: it is NEVER necessary to first login before calling
 # Net::FTP::Common API functions.                                
 # This function is just for checking to see if a machine is up. 
 # It is published as part of the API because I have found it 
 # useful when writing FTP scripts which scan for the 
 # first available FTP site to use for upload. The exact 
 # call-and-return semantics for this function are described
 # and justified below.

 $ez->login or die "cant login: $@";

 # Get a listing of a remote directory 

 @listing =	$ez->dir; 

 # Let's list a different directory, over-riding and changing the
 # default directory

 @listing =	$ez->dir(RemoteDir => '/pub/rfcs'); 

 # Let's list the default dir on several hosts

@host_listings = map { $ez->dir(Host => $_) } @host_list

 # Let's get the listings of several directories

 @dir_listings  = map { $ez->dir(RemoteDir  => $_) } @dir_list;

 # Get a file from the remote machine

 $ez->get(File => 'codex.txt', LocalFile => '/tmp/crypto.txt');

 # Get a file from the remote machine, specifying dir:
 $ez->get(File => 'codex.txt', LocalDir => '/tmp');

 # NOTE WELL:  because the prior call set LocalFile, it is still a
 # part of the object store. In other words this example will try
 # to store the downloaded file in /tmp/tmp/crypto.txt.
 # Better to say:

 $ez->get(File => 'codex.txt', LocalDir => '/tmp', LocalFile => '');


 # Send a file to the remote machine (*dont* use put!)

 $ez->send(File => 'codex.txt');

 # test for a file's existence on the remote machine (using =~)

 @file = $ez->grep(Grep => qr/[A-M]*[.]txt/);


 # test for a file on the remote machine (using eq)

 $ez->exists(File => 'needed-file.txt');

 # note this is no more than you manually calling:
 # (scalar grep { $_ eq 'needed-file.txt' } $ez->dir) > 0;

The test suite contains plenty of common examples.

DESCRIPTION

This module is intended to make the common uses of Net::FTP a one-line, no-argument affair. In software-engineering speak, the goal is to make use of FTP from Perl 95% configuration and 5% programming.

The way that it makes it a one-line affair is that the common pre-phase of login, cd, file type (binary/ascii) is handled for you. The way that it makes usage a no-argument affair is by pulling things from the hash that configured it at construction time. Should arguments be supplied to any API function, then these changes are applied to the hash of the object's state and used by any future-called API function which might need them.

Usage of this module is intended to be straightforward and stereotyped. The general steps to be used are:

  • use Net::FTP::Common

  • Define FTP configuration information

    This can be inlined within the script but oftentimes this will be stored in a module for usage in many other scripts.

  • Use a Net::FTP::Common API function

    Note well that you NEVER have to login first. All API functions automatically log you in and change to the configured or specified directory. However, sometimes it is useful to see if you can actually login before attempting to do something else on an FTP site. This is the only time you will need the login() API method.

    Note well: though Net::FTP works in the stateful way that the FTP protocol does, Net::FTP::Common works in a stateless "one-hit" fashion. That is, for each separate call to the API, a connection is established, the particular Net::FTP::Common functionality is performed and the connection is dropped. The disadvantage of this approach is the (usually irrelevant and insignificant) overhead of connection and disconnection. The advantage is that there is much less chance of incurring failure due to timeout.

METHODS

$ez = Net::FTP::Common-new($net_ftp_common_hashref, %net_ftp_hash)>

This method takes initialization information for Net::FTP::Common as well as Net::FTP and returns a new Net::FTP::Common object. Though the calling convention may seem a bit inconsistent, it is actually the best API to support re-use of legacy Net::FTP constructor calls. For example if you had a Net::FTP script which looked like this:

use Net::FTP;

$ftp = Net::FTP->new("some.host.name", Debug => 0);
$ftp->login("anonymous",'me@here.there');
$ftp->cwd("/pub");
$ftp->get("that.file");
$ftp->quit;

Here is all you would have to do to convert it to the Net::FTP::Common API:

           use Net::FTP::Common;

           $common_cfg = { Host => 'some.host.name', 
			   User => 'anonymous',
			   Pass => 'me@here.there',
			   RemoteDir  => '/pub'
			   }	

           $ftp = Net::FTP::Common->new($common_cfg, Debug => 0);
           $ftp->get("that.file");
           $ftp->quit;

$ez->Common(%config)

This is hardly ever necessary to use in isolation as all public API methods will call this as their first step in processing your request. However, it is available should you wish to extend this module.

$ez->GetCommon($config_key)

Again, this is hardly ever necessary to use in isolation. However, it is available should you wish to extend this module.

$ez->NetFTP(%netftp_config_overrides)

This creates and returns a Net::FTP object. In this case, any overrides are shuttled onward to the Net::FTP object as opposed to the configuration of the Net::FTP::Common object.

Also note that any overrides are preserved and used for all future calls.

$ez->login(%override)

This logs into an FTP server. %override is optional. It relies on 2 Common configuration options, User and Pass, which, if not present load to logging in via a .netrc file.

Normal login with User and Pass are tested. .netrc logins are not.

$ez->dir (%override)

When given no arguments, dir() uses Common configuration information to login to the ftp site, change directory and transfer type and then return an array of directory contents. You may only call this routine in array context and unlike Net::FTP, it returns a list representing the contents of the remote directory and in the case of no files, returns an empty array instead of (like Net::FTP) returning a 1-element array containing the element undef.

You may give this function any number of configuration arguments to over-ride the predefined configuration options. For example:

my %dir;
my @dir =qw (/tmp /pub /gnu);
map { @{$dir{$_}} = $ftp->dir(RemoteDir => $_ ) } @dir;

$ez->mkdir (%override)

Makes directories on remote FTP server. Will recurse if Recurse => 1 is in object's internal state of overridden at method call time.

Note this function has no test case. Good luck with it. Report any difficulties please.

$ez->exists (%override)

uses the File option of object internal state (or override) to check for a file in a directory listing. This means a eq, not regex match.

$ez->grep(%override)

uses the Grep option of object internal state (or override) to check for a file in a directory listing. This means a regex, not eq match.

$ez->get(%override)

uses the File, LocalFile, and LocalDir options of object internal state (or override) to download a file. No slashes need be appended to the end of LocalDir. If LocalFile and LocalDir arent defined, then the file is written to the current directory. LocalDir must exist: Net::FTP::Common will not create it for you.

All of the following have test cases and work:

LocalDir    LocalFile  Action
--------    ---------  ------
null        null       download to local dir using current dir
null        file       download to local dir using current dir but spec'ed file
dir         null       download to spec'ed dir using remote file name
dir         file       download to spec'ed dir using spec'ed file name

null is any Perl non-true value... 0, '', undef.

$ez->send(%override)

TRAPS FOR THE UNWARY

  • @file = $ez->grep(Grep => '[A-M]*[.]txt');

    is correct

    @file = $ez->grep('[A-M]*[.]txt');

    looks correct but is not because you did not name the argument as you are supposed to.

NOTES

  • big change from version after 2.30:

    Dir has been changed to RemoteDir to avoid confusion.

  • on object destruction:

    When a Net::FTP::Common object is goes out of scope, the following warning is thrown by Net::FTP:

    (in cleanup) Not a GLOB reference at Net/FTP.pm line 147.

    This is a harmless method that I should fix some day.

AUTHOR

T. M. Brannon <tbone@cpan.org>

3 POD Errors

The following errors were encountered while parsing the POD:

Around line 351:

You forgot a '=back' before '=head1'

Around line 472:

'=item' outside of any '=over'

Around line 483:

You forgot a '=back' before '=head1'