📄 fetch.pm
字号:
sub _curl_fetch { my $self = shift; my %hash = @_; my ($to); my $tmpl = { to => { required => 1, store => \$to } }; check( $tmpl, \%hash ) or return; if (my $curl = can_run('curl')) { ### these long opts are self explanatory - I like that -jmb my $cmd = [ $curl ]; push(@$cmd, '--connect-timeout', $TIMEOUT) if $TIMEOUT; push(@$cmd, '--silent') unless $DEBUG; ### curl does the right thing with passive, regardless ### if ($self->scheme eq 'ftp') { push(@$cmd, '--user', "anonymous:$FROM_EMAIL"); } ### curl doesn't follow 302 (temporarily moved) etc automatically ### so we add --location to enable that. push @$cmd, '--fail', '--location', '--output', ### DO NOT quote things for IPC::Run, it breaks stuff. $IPC::Cmd::USE_IPC_RUN ? ($to, $self->uri) : (QUOTE. $to .QUOTE, QUOTE. $self->uri .QUOTE); my $captured; unless(run( command => $cmd, buffer => \$captured, verbose => $DEBUG ) ) { return $self->_error(loc("Command failed: %1", $captured || '')); } return $to; } else { $METHOD_FAIL->{'curl'} = 1; return; }}### use File::Copy for fetching file:// urls ######### See section 3.10 of RFC 1738 (http://www.faqs.org/rfcs/rfc1738.html)### Also see wikipedia on file:// (http://en.wikipedia.org/wiki/File://)### sub _file_fetch { my $self = shift; my %hash = @_; my ($to); my $tmpl = { to => { required => 1, store => \$to } }; check( $tmpl, \%hash ) or return; ### prefix a / on unix systems with a file uri, since it would ### look somewhat like this: ### file:///home/kane/file ### wheras windows file uris for 'c:\some\dir\file' might look like: ### file:///C:/some/dir/file ### file:///C|/some/dir/file ### or for a network share '\\host\share\some\dir\file': ### file:////host/share/some/dir/file ### ### VMS file uri's for 'DISK$USER:[MY.NOTES]NOTE123456.TXT' might look like: ### file://vms.host.edu/disk$user/my/notes/note12345.txt ### my $path = $self->path; my $vol = $self->vol; my $share = $self->share; my $remote; if (!$share and $self->host) { return $self->_error(loc( "Currently %1 cannot handle hosts in %2 urls", 'File::Fetch', 'file://' )); } if( $vol ) { $path = File::Spec->catdir( split /\//, $path ); $remote = File::Spec->catpath( $vol, $path, $self->file); } elsif( $share ) { ### win32 specific, and a share name, so we wont bother with File::Spec $path =~ s|/+|\\|g; $remote = "\\\\".$self->host."\\$share\\$path"; } else { ### File::Spec on VMS can not currently handle UNIX syntax. my $file_class = ON_VMS ? 'File::Spec::Unix' : 'File::Spec'; $remote = $file_class->catfile( $path, $self->file ); } ### File::Copy is littered with 'die' statements :( ### my $rv = eval { File::Copy::copy( $remote, $to ) }; ### something went wrong ### if( !$rv or $@ ) { return $self->_error(loc("Could not copy '%1' to '%2': %3 %4", $remote, $to, $!, $@)); } return $to;}### use /usr/bin/rsync to fetch filessub _rsync_fetch { my $self = shift; my %hash = @_; my ($to); my $tmpl = { to => { required => 1, store => \$to } }; check( $tmpl, \%hash ) or return; if (my $rsync = can_run('rsync')) { my $cmd = [ $rsync ]; ### XXX: rsync has no I/O timeouts at all, by default push(@$cmd, '--timeout=' . $TIMEOUT) if $TIMEOUT; push(@$cmd, '--quiet') unless $DEBUG; ### DO NOT quote things for IPC::Run, it breaks stuff. push @$cmd, $IPC::Cmd::USE_IPC_RUN ? ($self->uri, $to) : (QUOTE. $self->uri .QUOTE, QUOTE. $to .QUOTE); my $captured; unless(run( command => $cmd, buffer => \$captured, verbose => $DEBUG ) ) { return $self->_error(loc("Command %1 failed: %2", "@$cmd" || '', $captured || '')); } return $to; } else { $METHOD_FAIL->{'rsync'} = 1; return; }}################################### Error code##################################=pod=head2 $ff->error([BOOL])Returns the last encountered error as string.Pass it a true value to get the C<Carp::longmess()> output instead.=cut### error handling the way Archive::Extract does itsub _error { my $self = shift; my $error = shift; $self->_error_msg( $error ); $self->_error_msg_long( Carp::longmess($error) ); if( $WARN ) { carp $DEBUG ? $self->_error_msg_long : $self->_error_msg; } return;}sub error { my $self = shift; return shift() ? $self->_error_msg_long : $self->_error_msg;}1;=pod=head1 HOW IT WORKSFile::Fetch is able to fetch a variety of uris, by using severalexternal programs and modules.Below is a mapping of what utilities will be used in what orderfor what schemes, if available: file => LWP, file http => LWP, wget, curl, lynx ftp => LWP, Net::FTP, wget, curl, ncftp, ftp rsync => rsyncIf you'd like to disable the use of one or more of these utilitiesand/or modules, see the C<$BLACKLIST> variable further down.If a utility or module isn't available, it will be marked in a cache(see the C<$METHOD_FAIL> variable further down), so it will not betried again. The C<fetch> method will only fail when all options areexhausted, and it was not able to retrieve the file.A special note about fetching files from an ftp uri:By default, all ftp connections are done in passive mode. To changethat, see the C<$FTP_PASSIVE> variable further down.Furthermore, ftp uris only support anonymous connections, so nonamed user/password pair can be passed along.C</bin/ftp> is blacklisted by default; see the C<$BLACKLIST> variablefurther down.=head1 GLOBAL VARIABLESThe behaviour of File::Fetch can be altered by changing the followingglobal variables:=head2 $File::Fetch::FROM_EMAILThis is the email address that will be sent as your anonymous ftppassword.Default is C<File-Fetch@example.com>.=head2 $File::Fetch::USER_AGENTThis is the useragent as C<LWP> will report it.Default is C<File::Fetch/$VERSION>.=head2 $File::Fetch::FTP_PASSIVEThis variable controls whether the environment variable C<FTP_PASSIVE>and any passive switches to commandline tools will be set to true.Default value is 1.Note: When $FTP_PASSIVE is true, C<ncftp> will not be used to fetchfiles, since passive mode can only be set interactively for this binary=head2 $File::Fetch::TIMEOUTWhen set, controls the network timeout (counted in seconds).Default value is 0.=head2 $File::Fetch::WARNThis variable controls whether errors encountered internally byC<File::Fetch> should be C<carp>'d or not.Set to false to silence warnings. Inspect the output of the C<error()>method manually to see what went wrong.Defaults to C<true>.=head2 $File::Fetch::DEBUGThis enables debugging output when calling commandline utilities tofetch files.This also enables C<Carp::longmess> errors, instead of the regularC<carp> errors.Good for tracking down why things don't work with your particularsetup.Default is 0.=head2 $File::Fetch::BLACKLISTThis is an array ref holding blacklisted modules/utilities for fetchingfiles with.To disallow the use of, for example, C<LWP> and C<Net::FTP>, you couldset $File::Fetch::BLACKLIST to: $File::Fetch::BLACKLIST = [qw|lwp netftp|]The default blacklist is [qw|ftp|], as C</bin/ftp> is rather unreliable.See the note on C<MAPPING> below.=head2 $File::Fetch::METHOD_FAILThis is a hashref registering what modules/utilities were known to failfor fetching files (mostly because they weren't installed).You can reset this cache by assigning an empty hashref to it, orindividually remove keys.See the note on C<MAPPING> below.=head1 MAPPINGHere's a quick mapping for the utilities/modules, and their names forthe $BLACKLIST, $METHOD_FAIL and other internal functions. LWP => lwp Net::FTP => netftp wget => wget lynx => lynx ncftp => ncftp ftp => ftp curl => curl rsync => rsync=head1 FREQUENTLY ASKED QUESTIONS=head2 So how do I use a proxy with File::Fetch?C<File::Fetch> currently only supports proxies with LWP::UserAgent.You will need to set your environment variables accordingly. Forexample, to use an ftp proxy: $ENV{ftp_proxy} = 'foo.com';Refer to the LWP::UserAgent manpage for more details.=head2 I used 'lynx' to fetch a file, but its contents is all wrong!C<lynx> can only fetch remote files by dumping its contents to C<STDOUT>,which we in turn capture. If that content is a 'custom' error file(like, say, a C<404 handler>), you will get that contents instead.Sadly, C<lynx> doesn't support any options to return a different exitcode on non-C<200 OK> status, giving us no way to tell the differencebetween a 'successfull' fetch and a custom error page.Therefor, we recommend to only use C<lynx> as a last resort. This is why it is at the back of our list of methods to try as well.=head2 Files I'm trying to fetch have reserved characters or non-ASCII characters in them. What do I do?C<File::Fetch> is relatively smart about things. When trying to write a file to disk, it removes the C<query parameters> (see the C<output_file> method for details) from the file name before creatingit. In most cases this suffices.If you have any other characters you need to escape, please install the C<URI::Escape> module from CPAN, and pre-encode your URI beforepassing it to C<File::Fetch>. You can read about the details of URIs and URI encoding here: http://www.faqs.org/rfcs/rfc2396.html=head1 TODO=over 4=item Implement $PREFER_BINTo indicate to rather use commandline tools than modules=back=head1 BUG REPORTSPlease report bugs or other issues to E<lt>bug-file-fetch@rt.cpan.org<gt>.=head1 AUTHORThis module by Jos Boumans E<lt>kane@cpan.orgE<gt>.=head1 COPYRIGHTThis library is free software; you may redistribute and/or modify it under the same terms as Perl itself.=cut# Local variables:# c-indentation-style: bsd# c-basic-offset: 4# indent-tabs-mode: nil# End:# vim: expandtab shiftwidth=4:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -