|
NAMENet::FTP::Common - simplify common usages of Net::FTPSYNOPSISour %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 # LocalFile => 'delete.zip' # setup something for $ez->get Host => 'ftp.fcc.gov', # overwrite ftp.microsoft.com default LocalDir => '/tmp', 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->ls; # Let's list a different directory, over-riding and changing the # default directory @listing = $ez->ls(RemoteDir => '/pub/rfcs'); # Let's list the default dir on several hosts @host_listings = map { $ez->ls(Host => $_) } @host_list # Let's get the listings of several directories @dir_listings = map { $ez->ls(RemoteDir => $_) } @dir_list; # Let's get a detailed directory listing... (thanks Kevin!) %listing = $ez->dir; # Note this is a hash, not an array return value. ### representative output 'test' => { 'owner' => 'root', 'month' => 'Jan', 'linkTarget' => undef, 'inode' => '1', 'size' => '6', 'group' => 'root', 'yearOrTime' => '1999', 'day' => '27', 'perm' => '-rw-r--r--' }, 'ranc' => { 'owner' => 'root', 'month' => 'Oct', 'linkTarget' => undef, 'inode' => '2', 'size' => '4096', 'group' => 'root', 'yearOrTime' => '00:42', 'day' => '31', 'perm' => 'drwxr-xr-x' } # Get a file from the remote machine $ez->get(RemoteFile => 'codex.txt', LocalFile => '/tmp/crypto.txt'); # Get a file from the remote machine, specifying dir: $ez->get(RemoteFile => '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(RemoteFile => 'codex.txt', LocalDir => '/tmp', LocalFile => ''); # Send a file to the remote machine (*dont* use put!) $ez->send(RemoteFile => '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(RemoteFile => 'needed-file.txt'); # note this is no more than you manually calling: # (scalar grep { $_ eq 'needed-file.txt' } $ez->ls) > 0; # Let's get all output written to STDERR to goto a logfile my $ez = Net::FTP::Common->new( { %CFG, STDERR => $logfile }, %netftp_cfg); The test suite contains plenty of common examples. DESCRIPTIONThis module is intended to make the common uses of Net::FTP a one-line, no-argument affair. In other words, you have 100% programming with Net::FTP. With Net::FTP::Common you will have 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:
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->ls (%override)When given no arguments, "ls()" 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->ls(RemoteDir => $_ ) } @dir; %retval = $ez->dir (%override)this function returns a hash NOT an arrayWhen given no arguments, "dir()" uses Common configuration information to login to the ftp site, change directory and transfer type and then return a hash of with detailed description of directory contents. You may only call this routine and expect a hash back. You may give this function any number of configuration arguments to over-ride the predefined configuration options. Here is the results of the example from the the test suite t/dir.t: my %retval = $ez->dir; 'incoming' => { 'owner' => 'root', 'month' => 'Jul', 'linkTarget' => undef, 'inode' => '2', 'size' => '4096', 'group' => 'root', 'yearOrTime' => '2001', 'day' => '10', 'perm' => 'drwxrwxrwx' }, 'holt' => { 'owner' => 'holt', 'month' => 'Jun', 'linkTarget' => undef, 'inode' => '2', 'size' => '4096', 'group' => 'daemon', 'yearOrTime' => '2000', 'day' => '12', 'perm' => 'drwxr-xr-x' }, 'SEEMORE-images' => { 'owner' => 'mel', 'month' => 'Aug', 'linkTarget' => 'images', 'inode' => '1', 'size' => '6', 'group' => 'lnc', 'yearOrTime' => '20:35', 'day' => '15', 'perm' => 'lrwxrwxrwx' }, 'dlr' => { 'owner' => 'root', 'month' => 'Sep', 'linkTarget' => undef, 'inode' => '2', 'size' => '4096', 'group' => 'root', 'yearOrTime' => '1998', 'day' => '11', 'perm' => 'drwxr-xr-x' }, 'fiser' => { 'owner' => '506', 'month' => 'May', 'linkTarget' => undef, 'inode' => '2', 'size' => '4096', 'group' => 'daemon', 'yearOrTime' => '1996', 'day' => '25', 'perm' => 'drwxr-xr-x' }, $ez->delete (%override)This method logins into the remote machine, changes to "RemoteDir" and then issues "$ftp->delete" on "RemoteFile"In the samples/delete-file directory of the distribution exists files called upload.pl and download.pl which together with Login.pm will log into a system and upload or delete the upfile $ez->mkdir (%override)Makes directories on remote FTP server. Will recurse if "Recurse => 1" is in the object's internal state of overridden at method call time.This function has no test case but a working example of its use is in scripts/rsync.pl. I use it to back up my stuff. $ez->exists (%override)This method uses the "RemoteFile" 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)This method 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)IMPORTANT: "LocalDir" must be set when you create a Net::FTP::Common object (i.e, when you call Net::FTP::Common->new) or your Net::FTP::Common will default "LocalDir" to "." and warn you about it.This method uses the "RemoteFile", "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)Sends a file. This API call must be used instead of "put".TRAPS FOR THE UNWARYBeware of how to use grep@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. Also note that the Net::FTP::Common login() function expects to be passed a hash, while the Net::FTP login() function expets to be passed a scalar. NOTESSample usagesA good example of Net::FTP::Common usage comes with your download:scripts/rsync.pl Although this script requires AppConfig, Net::FTP::Common in general does not... but go get AppConfig anyway, it rocks the house. TalksA slide talk on Net::FTP::Common in HTML format is available at<http://www.metaperl.org> TODODefinite things to do:
Musings:
Net::FTP FAQBecause I end up fielding so many Net::FTP questions, I feel it best to start a small FAQ.Trapping fatal exceptions <http://perlmonks.org/index.pl?node_id=317408> SEE ALSO
SUPPORTMailing List<http://tech.groups.yahoo.com/group/net-ftp-common/>DEVELOPMENTRepository<http://github.com/metaperl/net-ftp-common/tree/master>AUTHORT. M. Brannon <tbone@cpan.org>Acknowledgements
COPYRIGHT and LICENSECopyright (c) 2002-2009 Terrence Brannon.LicenseMIT License <http://www.opensource.org/licenses/mit-license.php> -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Visit the GSP FreeBSD Man Page Interface. |