From 787a690ec94d904da883b726dc88aa4098ff8056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= Date: Mon, 15 Apr 2013 14:43:16 +0200 Subject: [PATCH] Teach rpmlint --- .build-0.38-1.fc20.log | 94 + .build-0.42-1.fc20.log | 94 + .rpmlint | 2 + File-Fetch-0.38/CHANGES | 214 +++ File-Fetch-0.38/MANIFEST | 9 + File-Fetch-0.38/META.json | 54 + File-Fetch-0.38/META.yml | 32 + File-Fetch-0.38/MYMETA.json | 54 + File-Fetch-0.38/MYMETA.yml | 32 + File-Fetch-0.38/Makefile | 898 +++++++++ File-Fetch-0.38/Makefile.PL | 56 + File-Fetch-0.38/README | 40 + File-Fetch-0.38/blib/arch/.exists | 0 .../blib/arch/auto/File/Fetch/.exists | 0 File-Fetch-0.38/blib/bin/.exists | 0 File-Fetch-0.38/blib/lib/File/.exists | 0 File-Fetch-0.38/blib/lib/File/Fetch.pm | 1658 ++++++++++++++++ .../blib/lib/auto/File/Fetch/.exists | 0 File-Fetch-0.38/blib/man1/.exists | 0 File-Fetch-0.38/blib/man3/.exists | 0 File-Fetch-0.38/blib/man3/File::Fetch.3pm | 456 +++++ File-Fetch-0.38/blib/script/.exists | 0 File-Fetch-0.38/debugfiles.list | 0 File-Fetch-0.38/debuglinks.list | 0 File-Fetch-0.38/debugsources.list | 0 File-Fetch-0.38/lib/File/Fetch.pm | 1658 ++++++++++++++++ File-Fetch-0.38/pm_to_blib | 0 File-Fetch-0.38/t/01_File-Fetch.t | 281 +++ File-Fetch-0.38/t/null_subclass.t | 23 + File-Fetch-0.42/CHANGES | 222 +++ File-Fetch-0.42/MANIFEST | 9 + File-Fetch-0.42/META.json | 54 + File-Fetch-0.42/META.yml | 32 + File-Fetch-0.42/MYMETA.json | 54 + File-Fetch-0.42/MYMETA.yml | 32 + File-Fetch-0.42/Makefile | 898 +++++++++ File-Fetch-0.42/Makefile.PL | 56 + File-Fetch-0.42/README | 40 + File-Fetch-0.42/blib/arch/.exists | 0 .../blib/arch/auto/File/Fetch/.exists | 0 File-Fetch-0.42/blib/bin/.exists | 0 File-Fetch-0.42/blib/lib/File/.exists | 0 File-Fetch-0.42/blib/lib/File/Fetch.pm | 1708 +++++++++++++++++ .../blib/lib/auto/File/Fetch/.exists | 0 File-Fetch-0.42/blib/man1/.exists | 0 File-Fetch-0.42/blib/man3/.exists | 0 File-Fetch-0.42/blib/man3/File::Fetch.3pm | 459 +++++ File-Fetch-0.42/blib/script/.exists | 0 File-Fetch-0.42/debugfiles.list | 0 File-Fetch-0.42/debuglinks.list | 0 File-Fetch-0.42/debugsources.list | 0 File-Fetch-0.42/lib/File/Fetch.pm | 1708 +++++++++++++++++ File-Fetch-0.42/pm_to_blib | 0 File-Fetch-0.42/t/01_File-Fetch.t | 303 +++ File-Fetch-0.42/t/null_subclass.t | 23 + noarch/perl-File-Fetch-0.38-1.fc20.noarch.rpm | Bin 0 -> 25572 bytes noarch/perl-File-Fetch-0.42-1.fc20.noarch.rpm | Bin 0 -> 25792 bytes perl-File-Fetch-0.38-1.fc20.src.rpm | Bin 0 -> 23731 bytes perl-File-Fetch-0.42-1.fc20.src.rpm | Bin 0 -> 24063 bytes 59 files changed, 11253 insertions(+) create mode 100644 .build-0.38-1.fc20.log create mode 100644 .build-0.42-1.fc20.log create mode 100644 .rpmlint create mode 100644 File-Fetch-0.38/CHANGES create mode 100644 File-Fetch-0.38/MANIFEST create mode 100644 File-Fetch-0.38/META.json create mode 100644 File-Fetch-0.38/META.yml create mode 100644 File-Fetch-0.38/MYMETA.json create mode 100644 File-Fetch-0.38/MYMETA.yml create mode 100644 File-Fetch-0.38/Makefile create mode 100644 File-Fetch-0.38/Makefile.PL create mode 100644 File-Fetch-0.38/README create mode 100644 File-Fetch-0.38/blib/arch/.exists create mode 100644 File-Fetch-0.38/blib/arch/auto/File/Fetch/.exists create mode 100644 File-Fetch-0.38/blib/bin/.exists create mode 100644 File-Fetch-0.38/blib/lib/File/.exists create mode 100644 File-Fetch-0.38/blib/lib/File/Fetch.pm create mode 100644 File-Fetch-0.38/blib/lib/auto/File/Fetch/.exists create mode 100644 File-Fetch-0.38/blib/man1/.exists create mode 100644 File-Fetch-0.38/blib/man3/.exists create mode 100644 File-Fetch-0.38/blib/man3/File::Fetch.3pm create mode 100644 File-Fetch-0.38/blib/script/.exists create mode 100644 File-Fetch-0.38/debugfiles.list create mode 100644 File-Fetch-0.38/debuglinks.list create mode 100644 File-Fetch-0.38/debugsources.list create mode 100644 File-Fetch-0.38/lib/File/Fetch.pm create mode 100644 File-Fetch-0.38/pm_to_blib create mode 100644 File-Fetch-0.38/t/01_File-Fetch.t create mode 100644 File-Fetch-0.38/t/null_subclass.t create mode 100644 File-Fetch-0.42/CHANGES create mode 100644 File-Fetch-0.42/MANIFEST create mode 100644 File-Fetch-0.42/META.json create mode 100644 File-Fetch-0.42/META.yml create mode 100644 File-Fetch-0.42/MYMETA.json create mode 100644 File-Fetch-0.42/MYMETA.yml create mode 100644 File-Fetch-0.42/Makefile create mode 100644 File-Fetch-0.42/Makefile.PL create mode 100644 File-Fetch-0.42/README create mode 100644 File-Fetch-0.42/blib/arch/.exists create mode 100644 File-Fetch-0.42/blib/arch/auto/File/Fetch/.exists create mode 100644 File-Fetch-0.42/blib/bin/.exists create mode 100644 File-Fetch-0.42/blib/lib/File/.exists create mode 100644 File-Fetch-0.42/blib/lib/File/Fetch.pm create mode 100644 File-Fetch-0.42/blib/lib/auto/File/Fetch/.exists create mode 100644 File-Fetch-0.42/blib/man1/.exists create mode 100644 File-Fetch-0.42/blib/man3/.exists create mode 100644 File-Fetch-0.42/blib/man3/File::Fetch.3pm create mode 100644 File-Fetch-0.42/blib/script/.exists create mode 100644 File-Fetch-0.42/debugfiles.list create mode 100644 File-Fetch-0.42/debuglinks.list create mode 100644 File-Fetch-0.42/debugsources.list create mode 100644 File-Fetch-0.42/lib/File/Fetch.pm create mode 100644 File-Fetch-0.42/pm_to_blib create mode 100644 File-Fetch-0.42/t/01_File-Fetch.t create mode 100644 File-Fetch-0.42/t/null_subclass.t create mode 100644 noarch/perl-File-Fetch-0.38-1.fc20.noarch.rpm create mode 100644 noarch/perl-File-Fetch-0.42-1.fc20.noarch.rpm create mode 100644 perl-File-Fetch-0.38-1.fc20.src.rpm create mode 100644 perl-File-Fetch-0.42-1.fc20.src.rpm diff --git a/.build-0.38-1.fc20.log b/.build-0.38-1.fc20.log new file mode 100644 index 0000000..5bbbce1 --- /dev/null +++ b/.build-0.38-1.fc20.log @@ -0,0 +1,94 @@ + + +Provádění(%prep): /bin/sh -e /var/tmp/rpm-tmp.UqULff ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd /home/petr/fedora/perl-File-Fetch ++ rm -rf File-Fetch-0.38 ++ /usr/bin/gzip -dc /home/petr/fedora/perl-File-Fetch/File-Fetch-0.38.tar.gz ++ /usr/bin/tar -xf - ++ STATUS=0 ++ '[' 0 -ne 0 ']' ++ cd File-Fetch-0.38 ++ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w . ++ exit 0 +Provádění(%build): /bin/sh -e /var/tmp/rpm-tmp.4FMg91 ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd File-Fetch-0.38 ++ perl Makefile.PL INSTALLDIRS=vendor +Checking if your kit is complete... +Looks good +Writing Makefile for File::Fetch +Writing MYMETA.yml and MYMETA.json ++ make -j5 +cp lib/File/Fetch.pm blib/lib/File/Fetch.pm +Manifying blib/man3/File::Fetch.3pm ++ exit 0 +Provádění(%install): /bin/sh -e /var/tmp/rpm-tmp.coAhfQ ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ '[' /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64 '!=' / ']' ++ rm -rf /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64 +++ dirname /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64 ++ mkdir -p /home/petr/rpmbuild/BUILDROOT ++ mkdir /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64 ++ cd File-Fetch-0.38 ++ make pure_install DESTDIR=/home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64 +Manifying blib/man3/File::Fetch.3pm +Installing /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64/usr/share/perl5/vendor_perl/File/Fetch.pm +Installing /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64/usr/share/man/man3/File::Fetch.3pm ++ find /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64 -type f -name .packlist -exec rm -f '{}' ';' ++ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64/usr ++ /usr/lib/rpm/find-debuginfo.sh --strict-build-id -m --run-dwz --dwz-low-mem-die-limit 10000000 --dwz-max-die-limit 110000000 /home/petr/fedora/perl-File-Fetch/File-Fetch-0.38 ++ /usr/lib/rpm/check-rpaths /usr/lib/rpm/check-buildroot ++ /usr/lib/rpm/redhat/brp-compress ++ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip ++ /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1 ++ /usr/lib/rpm/redhat/brp-python-hardlink ++ /usr/lib/rpm/redhat/brp-java-repack-jars +Provádění(%check): /bin/sh -e /var/tmp/rpm-tmp.0P0n9E ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd File-Fetch-0.38 ++ make test +PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t + + +####################### NOTE ############################## + +Some of these tests assume you are connected to the +internet. If you are not, or if certain protocols or hosts +are blocked and/or firewalled, these tests could fail due +to no fault of the module itself. + +########################################################### + +t/01_File-Fetch.t .. ok +t/null_subclass.t .. ok +All tests successful. +Files=2, Tests=450, 27 wallclock secs ( 0.09 usr 0.01 sys + 0.68 cusr 0.41 csys = 1.19 CPU) +Result: PASS ++ exit 0 +Processing files: perl-File-Fetch-0.38-1.fc20.noarch +Provádění(%doc): /bin/sh -e /var/tmp/rpm-tmp.8lWAIN ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd File-Fetch-0.38 ++ DOCDIR=/home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64/usr/share/doc/perl-File-Fetch-0.38 ++ export DOCDIR ++ /usr/bin/mkdir -p /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64/usr/share/doc/perl-File-Fetch-0.38 ++ cp -pr CHANGES README /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64/usr/share/doc/perl-File-Fetch-0.38 ++ exit 0 +Provides: perl(File::Fetch) = 0.38 perl-File-Fetch = 0.38-1.fc20 +Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +Requires: perl(Carp) perl(Cwd) perl(File::Basename) perl(File::Copy) perl(File::Path) perl(File::Spec::Unix) perl(File::Temp) perl(FileHandle) perl(Locale::Maketext::Simple) perl(constant) perl(strict) perl(vars) +Kontroluji nezabalené soubory: /usr/lib/rpm/check-files /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64 +Zapsáno: /home/petr/fedora/perl-File-Fetch/perl-File-Fetch-0.38-1.fc20.src.rpm +Zapsáno: /home/petr/fedora/perl-File-Fetch/noarch/perl-File-Fetch-0.38-1.fc20.noarch.rpm +Provádění(%clean): /bin/sh -e /var/tmp/rpm-tmp.gwOJXd ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd File-Fetch-0.38 ++ /usr/bin/rm -rf /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.38-1.fc20.x86_64 ++ exit 0 diff --git a/.build-0.42-1.fc20.log b/.build-0.42-1.fc20.log new file mode 100644 index 0000000..518dfb8 --- /dev/null +++ b/.build-0.42-1.fc20.log @@ -0,0 +1,94 @@ + + +Provádění(%prep): /bin/sh -e /var/tmp/rpm-tmp.eHPRZy ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd /home/petr/fedora/perl-File-Fetch ++ rm -rf File-Fetch-0.42 ++ /usr/bin/gzip -dc /home/petr/fedora/perl-File-Fetch/File-Fetch-0.42.tar.gz ++ /usr/bin/tar -xf - ++ STATUS=0 ++ '[' 0 -ne 0 ']' ++ cd File-Fetch-0.42 ++ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w . ++ exit 0 +Provádění(%build): /bin/sh -e /var/tmp/rpm-tmp.o2lDpS ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd File-Fetch-0.42 ++ perl Makefile.PL INSTALLDIRS=vendor +Checking if your kit is complete... +Looks good +Writing Makefile for File::Fetch +Writing MYMETA.yml and MYMETA.json ++ make -j5 +cp lib/File/Fetch.pm blib/lib/File/Fetch.pm +Manifying blib/man3/File::Fetch.3pm ++ exit 0 +Provádění(%install): /bin/sh -e /var/tmp/rpm-tmp.gmoy0c ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ '[' /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64 '!=' / ']' ++ rm -rf /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64 +++ dirname /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64 ++ mkdir -p /home/petr/rpmbuild/BUILDROOT ++ mkdir /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64 ++ cd File-Fetch-0.42 ++ make pure_install DESTDIR=/home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64 +Manifying blib/man3/File::Fetch.3pm +Installing /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64/usr/share/perl5/vendor_perl/File/Fetch.pm +Installing /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64/usr/share/man/man3/File::Fetch.3pm ++ find /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64 -type f -name .packlist -exec rm -f '{}' ';' ++ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64/usr ++ /usr/lib/rpm/find-debuginfo.sh --strict-build-id -m --run-dwz --dwz-low-mem-die-limit 10000000 --dwz-max-die-limit 110000000 /home/petr/fedora/perl-File-Fetch/File-Fetch-0.42 ++ /usr/lib/rpm/check-rpaths /usr/lib/rpm/check-buildroot ++ /usr/lib/rpm/redhat/brp-compress ++ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip ++ /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1 ++ /usr/lib/rpm/redhat/brp-python-hardlink ++ /usr/lib/rpm/redhat/brp-java-repack-jars +Provádění(%check): /bin/sh -e /var/tmp/rpm-tmp.gKkeoy ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd File-Fetch-0.42 ++ make test +PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t + + +####################### NOTE ############################## + +Some of these tests assume you are connected to the +internet. If you are not, or if certain protocols or hosts +are blocked and/or firewalled, these tests could fail due +to no fault of the module itself. + +########################################################### + +t/01_File-Fetch.t .. ok +t/null_subclass.t .. ok +All tests successful. +Files=2, Tests=472, 34 wallclock secs ( 0.09 usr 0.01 sys + 0.69 cusr 0.52 csys = 1.31 CPU) +Result: PASS ++ exit 0 +Processing files: perl-File-Fetch-0.42-1.fc20.noarch +Provádění(%doc): /bin/sh -e /var/tmp/rpm-tmp.4fCaBv ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd File-Fetch-0.42 ++ DOCDIR=/home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64/usr/share/doc/perl-File-Fetch-0.42 ++ export DOCDIR ++ /usr/bin/mkdir -p /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64/usr/share/doc/perl-File-Fetch-0.42 ++ cp -pr CHANGES README /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64/usr/share/doc/perl-File-Fetch-0.42 ++ exit 0 +Provides: perl(File::Fetch) = 0.42 perl-File-Fetch = 0.42-1.fc20 +Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +Requires: perl(Carp) perl(Cwd) perl(File::Basename) perl(File::Copy) perl(File::Path) perl(File::Spec::Unix) perl(File::Temp) perl(FileHandle) perl(Locale::Maketext::Simple) perl(constant) perl(strict) perl(vars) +Kontroluji nezabalené soubory: /usr/lib/rpm/check-files /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64 +Zapsáno: /home/petr/fedora/perl-File-Fetch/perl-File-Fetch-0.42-1.fc20.src.rpm +Zapsáno: /home/petr/fedora/perl-File-Fetch/noarch/perl-File-Fetch-0.42-1.fc20.noarch.rpm +Provádění(%clean): /bin/sh -e /var/tmp/rpm-tmp.26zpQn ++ umask 022 ++ cd /home/petr/fedora/perl-File-Fetch ++ cd File-Fetch-0.42 ++ /usr/bin/rm -rf /home/petr/rpmbuild/BUILDROOT/perl-File-Fetch-0.42-1.fc20.x86_64 ++ exit 0 diff --git a/.rpmlint b/.rpmlint new file mode 100644 index 0000000..21e112e --- /dev/null +++ b/.rpmlint @@ -0,0 +1,2 @@ +from Config import * +addFilter("spelling-error .* (http|rsync)"); diff --git a/File-Fetch-0.38/CHANGES b/File-Fetch-0.38/CHANGES new file mode 100644 index 0000000..c35ee01 --- /dev/null +++ b/File-Fetch-0.38/CHANGES @@ -0,0 +1,214 @@ +Changes for 0.38 Thu Jan 10 20:52:53 2013 +================================================= +* Add support for an optional tempdir_root + parameter (Kent Fredric) + +Changes for 0.36 Thu Jun 28 13:41:31 2012 +================================================= +* Added 'file_default' option for URLs that do + not have a file component (Andrew Kirkpatrick) + +Changes for 0.34 Thu Apr 12 22:25:01 2012 +================================================= +* Added heuristics to skip tests when no + Internet access + +Changes for 0.32 Mon Jan 17 10:26:40 2011 +================================================= +* Added support for HTTP::Tiny + +Changes for 0.30 Fri Jan 7 21:00:27 2011 +================================================= +* Apply blead patches from Peter Acklam + +Changes for 0.28 Sun Nov 7 21:22:26 2010 +================================================= +* Added support for FreeBSDs 'fetch' command for + both http and ftp schemes. + +Changes for 0.26 Sat Nov 6 23:30:59 2010 +================================================= +* Added support for HTTP::Lite +* Resolved issue with '-l' switch and iosock fetch + +Changes for 0.24 Wed Jan 6 23:32:19 2010 +================================================= +* Applied a patch from brian d foy RT #53427 + that makes new() respect sub-classes. + +Changes for 0.22 Sat Nov 14 23:13:16 2009 +================================================= +* Bumped to stable version + +Changes for 0.21_02 Thu Nov 12 12:55:57 2009 +================================================= +* Additional checks for the iosock retriever + +Changes for 0.21_01 Wed Nov 11 23:38:27 2009 +================================================= +* Added a simple IO::Socket/IO::Select based http retriever, + based on code suggested by Paul 'Leonerd' Evans + +Changes for 0.20 Sat Jun 27 16:30:59 2009 +================================================= +* Promote 0.19_01 to stable + +Changes for 0.19_01 Mon Feb 9 18:04:01 2009 +================================================= +* Address: #42268: Wishlist: slurp to scalar + File::Fetch can now fetch to scalars as well + +Changes for 0.18 Wed Dec 17 14:00:40 2008 +================================================= +* Address #41412: User agent string contains uninterpolated + $VERSION. +* Use IPC::Cmd 0.42's supplied QUOTE constant, rather than + rolling our own + +Changes for 0.16 Fri Oct 10 13:54:40 2008 +================================================= +* Promote 0.15_04 to stable. + +Changes for 0.15_04 Mon Sep 22 15:08:49 2008 +================================================= +* Address: #37649: Feature request: Support lftp + File::Fetch now supports lftp, with one minor caveat: it uses + a temporary file to store the commands for lftp, as they are + multiline commands. Without this, we run into portability issues + with 'special' characters on various platforms, like ; and &. + +Changes for 0.15_03 Sun Jul 13 15:56:41 2008 +================================================= +* Add -q to curl, to inhibit the reading of .curlrc, + which may interfere with the options we pass ourselves. + This addresses #36902 + +Changes for 0.15_02 Sun May 18 13:42:30 2008 +================================================= +* Address #35018: Treat HTTP 404 Message as fail with lynx + lynx now does a -head request first to make sure the file + exists before proceeding + +Changes for 0.15_01 Sun Apr 6 13:55:36 2008 +================================================= +* Address: #32755: File-Fetch tests cannot fail if + unable to connect to internet. Tests are now skipped + if it looks as the failure is due to a lacking network + connection. +* New IPC::Cmd (0.41) fixes an IPC::Open3 bug, which we + now rely on. + +Changes for 0.14 Fri Dec 14 13:42:30 2007 +================================================= +* Promote 0.13_04 to stable. + +Changes for 0.13_04 Wed Nov 14 20:07:02 2007 +================================================= +* VMS patches for file:// uris by John M. + +Changes for 0.13_03 2007-11-04 21:32:40 +================================================= +* Restore OS specific file:// URI behaviour. The + RFC's specify that the url definition is host OS + specific, so what a url means on one machine will + mean something different on another. + VMS is now treated according to RFC 1738 + (http://www.faqs.org/rfcs/rfc1738.html). + +Changes for 0.13_02 Sun Nov 4 10:38:40 CET 2007 +================================================= +* Apply a perl 5.5.x compatibility fix. Users with + perl 5.6.0 or higher do not need to upgrade. + +Changes for 0.13_01 Sat Nov 3 18:55:10 CET 2007 +================================================= +* Apply a modified version of dmq's patch to deal + properly with file:// URIs on Win32. +* Add test cases for Win32 file:// URIs + +Changes for 0.12 Mon Oct 15 14:32:23 CEST 2007 +================================================= +* Treat VMS like UNIX when dealing with file URIs + +Changes for 0.10 Fri Jan 26 13:51:19 CET 2007 +================================================ +* Promote 0.09_02 to stable. + +Changes for 0.09_02 Sun Jan 7 18:44:09 CET 2007 +================================================ +* The quotation as done in 0.09_01 doesn't play + nicely with Win32 and IPC::Run. IPC::Run is + therefor disabled during the fetch() call. +* Remove File::Fetch::Item as a class. All objects + are now plain File::Fetch objects. This has no + impact on user-end code, except code that checks + the class of objects. +* URI encoding is not always clear or trivial. Add + a FAQ entry about it. +* Add $ff->output_file as accessor, which is the + requested file, stripped from query parameters. +* Errors are now stored per object rather than + class wide. + +Changes for 0.09_01 Wed Jan 3 17:17:31 CET 2007 +================================================ +* address: #23864: File:Fetch does not use quotation + marks while using wget: + * the handlers for lynx, wget, curl and rsync now + quote their URIs. + +Changes for 0.08 Wed Jul 5 13:56:36 CEST 2006 +================================================ +* address: #18942: unproper handling of http errors + in external handlers: + * the wget handler, on a failed attempt, now + unlinks its outputfile + * the curl handler is updated to follow '302 moved' + and such like status messages + * lynx use is further discouraged, as it doesn't + communicate http status messages back to the caller + at all. +* address #11483: File::Fetch 0.07 cannot do an FTP + fetch on Win32. FTP fetching using Net::FTP should + now work properly on win32. +* update test suite so it runs safely under PERL_CORE + +Changes for 0.07 Thu Dec 23 09:31:00 PST 2004 +================================================ + +* Add $TIMEOUT to specify the network timeout + +Changes for 0.06 Thu Dec 16 03:21:00 PST 2004 +================================================ + +* Add rsync support + +Changes for 0.05 Fri Jun 18 13:55:51 CEST 2004 +================================================= + +* Update faq +* Silence silly warnings + +Changes for 0.04 Fri Jun 11 22:40:34 CEST 2004 +================================================= + +* Add file support using File::Copy + +Changes for 0.03 Fri Jun 11 20:40:22 CEST 2004 +================================================= + +* Add I18N support +* Add better error handling + +Changes for 0.02 Sat May 22 14:40:29 CEST 2004 +================================================= + +* Add an extra 'FAQ' entry +* Include a 'use File::Fetch::Item' + + +Changes for 0.01 Tue May 4 15:48:24 CEST 2004 +================================================= + +* Initial release + diff --git a/File-Fetch-0.38/MANIFEST b/File-Fetch-0.38/MANIFEST new file mode 100644 index 0000000..702c16f --- /dev/null +++ b/File-Fetch-0.38/MANIFEST @@ -0,0 +1,9 @@ +CHANGES +lib/File/Fetch.pm +Makefile.PL +MANIFEST This list of files +README +t/01_File-Fetch.t +t/null_subclass.t +META.yml Module YAML meta-data (added by MakeMaker) +META.json Module JSON meta-data (added by MakeMaker) diff --git a/File-Fetch-0.38/META.json b/File-Fetch-0.38/META.json new file mode 100644 index 0000000..665f737 --- /dev/null +++ b/File-Fetch-0.38/META.json @@ -0,0 +1,54 @@ +{ + "abstract" : "Generic file fetching code", + "author" : [ + "Jos Boumans " + ], + "dynamic_config" : 1, + "generated_by" : "ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.120921", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "File-Fetch", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "runtime" : { + "requires" : { + "File::Basename" : "0", + "File::Copy" : "0", + "File::Path" : "0", + "File::Spec" : "0.82", + "IPC::Cmd" : "0.42", + "Locale::Maketext::Simple" : "0", + "Module::Load::Conditional" : "0.04", + "Params::Check" : "0.07", + "Test::More" : "0" + } + } + }, + "release_status" : "stable", + "resources" : { + "repository" : { + "url" : "https://github.com/jib/file-fetch" + } + }, + "version" : "0.38" +} diff --git a/File-Fetch-0.38/META.yml b/File-Fetch-0.38/META.yml new file mode 100644 index 0000000..fa7e613 --- /dev/null +++ b/File-Fetch-0.38/META.yml @@ -0,0 +1,32 @@ +--- +abstract: 'Generic file fetching code' +author: + - 'Jos Boumans ' +build_requires: + ExtUtils::MakeMaker: 0 +configure_requires: + ExtUtils::MakeMaker: 0 +dynamic_config: 1 +generated_by: 'ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.120921' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: File-Fetch +no_index: + directory: + - t + - inc +requires: + File::Basename: 0 + File::Copy: 0 + File::Path: 0 + File::Spec: 0.82 + IPC::Cmd: 0.42 + Locale::Maketext::Simple: 0 + Module::Load::Conditional: 0.04 + Params::Check: 0.07 + Test::More: 0 +resources: + repository: https://github.com/jib/file-fetch +version: 0.38 diff --git a/File-Fetch-0.38/MYMETA.json b/File-Fetch-0.38/MYMETA.json new file mode 100644 index 0000000..7366c09 --- /dev/null +++ b/File-Fetch-0.38/MYMETA.json @@ -0,0 +1,54 @@ +{ + "abstract" : "Generic file fetching code", + "author" : [ + "Jos Boumans " + ], + "dynamic_config" : 0, + "generated_by" : "ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.120921", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "File-Fetch", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "runtime" : { + "requires" : { + "File::Basename" : "0", + "File::Copy" : "0", + "File::Path" : "0", + "File::Spec" : "0.82", + "IPC::Cmd" : "0.42", + "Locale::Maketext::Simple" : "0", + "Module::Load::Conditional" : "0.04", + "Params::Check" : "0.07", + "Test::More" : "0" + } + } + }, + "release_status" : "stable", + "resources" : { + "repository" : { + "url" : "https://github.com/jib/file-fetch" + } + }, + "version" : "0.38" +} diff --git a/File-Fetch-0.38/MYMETA.yml b/File-Fetch-0.38/MYMETA.yml new file mode 100644 index 0000000..9c497fd --- /dev/null +++ b/File-Fetch-0.38/MYMETA.yml @@ -0,0 +1,32 @@ +--- +abstract: 'Generic file fetching code' +author: + - 'Jos Boumans ' +build_requires: + ExtUtils::MakeMaker: 0 +configure_requires: + ExtUtils::MakeMaker: 0 +dynamic_config: 0 +generated_by: 'ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.120921' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: File-Fetch +no_index: + directory: + - t + - inc +requires: + File::Basename: 0 + File::Copy: 0 + File::Path: 0 + File::Spec: 0.82 + IPC::Cmd: 0.42 + Locale::Maketext::Simple: 0 + Module::Load::Conditional: 0.04 + Params::Check: 0.07 + Test::More: 0 +resources: + repository: https://github.com/jib/file-fetch +version: 0.38 diff --git a/File-Fetch-0.38/Makefile b/File-Fetch-0.38/Makefile new file mode 100644 index 0000000..e50e4f9 --- /dev/null +++ b/File-Fetch-0.38/Makefile @@ -0,0 +1,898 @@ +# This Makefile is for the File::Fetch extension to perl. +# +# It was generated automatically by MakeMaker version +# 6.6302 (Revision: 66302) from the contents of +# Makefile.PL. Don't edit this file, edit Makefile.PL instead. +# +# ANY CHANGES MADE HERE WILL BE LOST! +# +# MakeMaker ARGV: (q[INSTALLDIRS=vendor]) +# + +# MakeMaker Parameters: + +# ABSTRACT => q[Generic file fetching code] +# AUTHOR => [q[Jos Boumans ]] +# BUILD_REQUIRES => { } +# CONFIGURE_REQUIRES => { } +# INSTALLDIRS => q[perl] +# LICENSE => q[perl] +# META_MERGE => { resources=>{ repository=>q[https://github.com/jib/file-fetch] } } +# NAME => q[File::Fetch] +# PREREQ_PM => { File::Copy=>q[0], File::Spec=>q[0.82], Locale::Maketext::Simple=>q[0], IPC::Cmd=>q[0.42], Params::Check=>q[0.07], Test::More=>q[0], File::Path=>q[0], Module::Load::Conditional=>q[0.04], File::Basename=>q[0] } +# VERSION_FROM => q[lib/File/Fetch.pm] +# clean => { FILES=>q[t/tmp] } +# dist => { COMPRESS=>q[gzip -9f], SUFFIX=>q[gz] } + +# --- MakeMaker post_initialize section: + + +# --- MakeMaker const_config section: + +# These definitions are from config.sh (via /usr/lib64/perl5/Config.pm). +# They may have been overridden via Makefile.PL or on the command line. +AR = ar +CC = gcc +CCCDLFLAGS = -fPIC +CCDLFLAGS = -Wl,--enable-new-dtags -Wl,-rpath,/usr/lib64/perl5/CORE +DLEXT = so +DLSRC = dl_dlopen.xs +EXE_EXT = +FULL_AR = /usr/bin/ar +LD = gcc +LDDLFLAGS = -shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -Wl,-z,relro +LDFLAGS = -fstack-protector +LIBC = +LIB_EXT = .a +OBJ_EXT = .o +OSNAME = linux +OSVERS = 2.6.32-358.2.1.el6.x86_64 +RANLIB = : +SITELIBEXP = /usr/local/share/perl5 +SITEARCHEXP = /usr/local/lib64/perl5 +SO = so +VENDORARCHEXP = /usr/lib64/perl5/vendor_perl +VENDORLIBEXP = /usr/share/perl5/vendor_perl + + +# --- MakeMaker constants section: +AR_STATIC_ARGS = cr +DIRFILESEP = / +DFSEP = $(DIRFILESEP) +NAME = File::Fetch +NAME_SYM = File_Fetch +VERSION = 0.38 +VERSION_MACRO = VERSION +VERSION_SYM = 0_38 +DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" +XS_VERSION = 0.38 +XS_VERSION_MACRO = XS_VERSION +XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" +INST_ARCHLIB = blib/arch +INST_SCRIPT = blib/script +INST_BIN = blib/bin +INST_LIB = blib/lib +INST_MAN1DIR = blib/man1 +INST_MAN3DIR = blib/man3 +MAN1EXT = 1 +MAN3EXT = 3pm +INSTALLDIRS = vendor +DESTDIR = +PREFIX = $(VENDORPREFIX) +PERLPREFIX = /usr +SITEPREFIX = /usr/local +VENDORPREFIX = /usr +INSTALLPRIVLIB = /usr/share/perl5 +DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB) +INSTALLSITELIB = /usr/local/share/perl5 +DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB) +INSTALLVENDORLIB = /usr/share/perl5/vendor_perl +DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB) +INSTALLARCHLIB = /usr/lib64/perl5 +DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB) +INSTALLSITEARCH = /usr/local/lib64/perl5 +DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH) +INSTALLVENDORARCH = /usr/lib64/perl5/vendor_perl +DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH) +INSTALLBIN = /usr/bin +DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN) +INSTALLSITEBIN = /usr/local/bin +DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN) +INSTALLVENDORBIN = /usr/bin +DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN) +INSTALLSCRIPT = /usr/bin +DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT) +INSTALLSITESCRIPT = /usr/local/bin +DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT) +INSTALLVENDORSCRIPT = /usr/bin +DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT) +INSTALLMAN1DIR = /usr/share/man/man1 +DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR) +INSTALLSITEMAN1DIR = /usr/local/share/man/man1 +DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR) +INSTALLVENDORMAN1DIR = /usr/share/man/man1 +DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR) +INSTALLMAN3DIR = /usr/share/man/man3 +DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR) +INSTALLSITEMAN3DIR = /usr/local/share/man/man3 +DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR) +INSTALLVENDORMAN3DIR = /usr/share/man/man3 +DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR) +PERL_LIB = /usr/share/perl5 +PERL_ARCHLIB = /usr/lib64/perl5 +LIBPERL_A = libperl.a +FIRST_MAKEFILE = Makefile +MAKEFILE_OLD = Makefile.old +MAKE_APERL_FILE = Makefile.aperl +PERLMAINCC = $(CC) +PERL_INC = /usr/lib64/perl5/CORE +PERL = /usr/bin/perl +FULLPERL = /usr/bin/perl +ABSPERL = $(PERL) +PERLRUN = $(PERL) +FULLPERLRUN = $(FULLPERL) +ABSPERLRUN = $(ABSPERL) +PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +PERL_CORE = 0 +PERM_DIR = 755 +PERM_RW = 644 +PERM_RWX = 755 + +MAKEMAKER = /usr/share/perl5/ExtUtils/MakeMaker.pm +MM_VERSION = 6.6302 +MM_REVISION = 66302 + +# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). +# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) +# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) +# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. +MAKE = make +FULLEXT = File/Fetch +BASEEXT = Fetch +PARENT_NAME = File +DLBASE = $(BASEEXT) +VERSION_FROM = lib/File/Fetch.pm +OBJECT = +LDFROM = $(OBJECT) +LINKTYPE = dynamic +BOOTDEP = + +# Handy lists of source code files: +XS_FILES = +C_FILES = +O_FILES = +H_FILES = +MAN1PODS = +MAN3PODS = lib/File/Fetch.pm + +# Where is the Config information that we are using/depend on +CONFIGDEP = $(PERL_ARCHLIB)$(DFSEP)Config.pm $(PERL_INC)$(DFSEP)config.h + +# Where to build things +INST_LIBDIR = $(INST_LIB)/File +INST_ARCHLIBDIR = $(INST_ARCHLIB)/File + +INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) +INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) + +INST_STATIC = +INST_DYNAMIC = +INST_BOOT = + +# Extra linker info +EXPORT_LIST = +PERL_ARCHIVE = +PERL_ARCHIVE_AFTER = + + +TO_INST_PM = lib/File/Fetch.pm + +PM_TO_BLIB = lib/File/Fetch.pm \ + blib/lib/File/Fetch.pm + + +# --- MakeMaker platform_constants section: +MM_Unix_VERSION = 6.6302 +PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc + + +# --- MakeMaker tool_autosplit section: +# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto +AUTOSPLITFILE = $(ABSPERLRUN) -e 'use AutoSplit; autosplit($$$$ARGV[0], $$$$ARGV[1], 0, 1, 1)' -- + + + +# --- MakeMaker tool_xsubpp section: + + +# --- MakeMaker tools_other section: +SHELL = /bin/sh +CHMOD = chmod +CP = cp +MV = mv +NOOP = $(TRUE) +NOECHO = @ +RM_F = rm -f +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 +MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' -- +EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' -- +FALSE = false +TRUE = true +ECHO = echo +ECHO_N = echo -n +UNINST = 0 +VERBINST = 0 +MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' -- +DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' -- +UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' -- +WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' -- +MACROSTART = +MACROEND = +USEMAKEFILE = -f +FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' -- + + +# --- MakeMaker makemakerdflt section: +makemakerdflt : all + $(NOECHO) $(NOOP) + + +# --- MakeMaker dist section: +TAR = tar +TARFLAGS = cvf +ZIP = zip +ZIPFLAGS = -r +COMPRESS = gzip -9f +SUFFIX = gz +SHAR = shar +PREOP = $(NOECHO) $(NOOP) +POSTOP = $(NOECHO) $(NOOP) +TO_UNIX = $(NOECHO) $(NOOP) +CI = ci -u +RCS_LABEL = rcs -Nv$(VERSION_SYM): -q +DIST_CP = best +DIST_DEFAULT = tardist +DISTNAME = File-Fetch +DISTVNAME = File-Fetch-0.38 + + +# --- MakeMaker macro section: + + +# --- MakeMaker depend section: + + +# --- MakeMaker cflags section: + + +# --- MakeMaker const_loadlibs section: + + +# --- MakeMaker const_cccmd section: + + +# --- MakeMaker post_constants section: + + +# --- MakeMaker pasthru section: + +PASTHRU = LIBPERL_A="$(LIBPERL_A)"\ + LINKTYPE="$(LINKTYPE)"\ + PREFIX="$(PREFIX)" + + +# --- MakeMaker special_targets section: +.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT) + +.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir + + + +# --- MakeMaker c_o section: + + +# --- MakeMaker xs_c section: + + +# --- MakeMaker xs_o section: + + +# --- MakeMaker top_targets section: +all :: pure_all manifypods + $(NOECHO) $(NOOP) + + +pure_all :: config pm_to_blib subdirs linkext + $(NOECHO) $(NOOP) + +subdirs :: $(MYEXTLIB) + $(NOECHO) $(NOOP) + +config :: $(FIRST_MAKEFILE) blibdirs + $(NOECHO) $(NOOP) + +help : + perldoc ExtUtils::MakeMaker + + +# --- MakeMaker blibdirs section: +blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists + $(NOECHO) $(NOOP) + +# Backwards compat with 6.18 through 6.25 +blibdirs.ts : blibdirs + $(NOECHO) $(NOOP) + +$(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_LIBDIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR) + $(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists + +$(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHLIB) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB) + $(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists + +$(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_AUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR) + $(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists + +$(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR) + $(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists + +$(INST_BIN)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_BIN) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN) + $(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists + +$(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_SCRIPT) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT) + $(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists + +$(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN1DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR) + $(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists + +$(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN3DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR) + $(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists + + + +# --- MakeMaker linkext section: + +linkext :: $(LINKTYPE) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dlsyms section: + + +# --- MakeMaker dynamic section: + +dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dynamic_bs section: + +BOOTSTRAP = + + +# --- MakeMaker dynamic_lib section: + + +# --- MakeMaker static section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make static" +static :: $(FIRST_MAKEFILE) $(INST_STATIC) + $(NOECHO) $(NOOP) + + +# --- MakeMaker static_lib section: + + +# --- MakeMaker manifypods section: + +POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--" +POD2MAN = $(POD2MAN_EXE) + + +manifypods : pure_all \ + lib/File/Fetch.pm + $(NOECHO) $(POD2MAN) --section=3 --perm_rw=$(PERM_RW) \ + lib/File/Fetch.pm $(INST_MAN3DIR)/File::Fetch.$(MAN3EXT) + + + + +# --- MakeMaker processPL section: + + +# --- MakeMaker installbin section: + + +# --- MakeMaker subdirs section: + +# none + +# --- MakeMaker clean_subdirs section: +clean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker clean section: + +# Delete temporary files but do not touch installed files. We don't delete +# the Makefile here so a later make realclean still has a makefile to use. + +clean :: clean_subdirs + - $(RM_F) \ + *$(LIB_EXT) core \ + core.[0-9] $(INST_ARCHAUTODIR)/extralibs.all \ + core.[0-9][0-9] $(BASEEXT).bso \ + pm_to_blib.ts MYMETA.json \ + core.[0-9][0-9][0-9][0-9] MYMETA.yml \ + $(BASEEXT).x $(BOOTSTRAP) \ + perl$(EXE_EXT) tmon.out \ + *$(OBJ_EXT) pm_to_blib \ + $(INST_ARCHAUTODIR)/extralibs.ld blibdirs.ts \ + core.[0-9][0-9][0-9][0-9][0-9] *perl.core \ + core.*perl.*.? $(MAKE_APERL_FILE) \ + $(BASEEXT).def perl \ + core.[0-9][0-9][0-9] mon.out \ + lib$(BASEEXT).def perlmain.c \ + perl.exe so_locations \ + $(BASEEXT).exp + - $(RM_RF) \ + t/tmp blib + - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL) + + +# --- MakeMaker realclean_subdirs section: +realclean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker realclean section: +# Delete temporary files (via clean) and also delete dist files +realclean purge :: clean realclean_subdirs + - $(RM_F) \ + $(MAKEFILE_OLD) $(FIRST_MAKEFILE) + - $(RM_RF) \ + $(DISTVNAME) + + +# --- MakeMaker metafile section: +metafile : create_distdir + $(NOECHO) $(ECHO) Generating META.yml + $(NOECHO) $(ECHO) '---' > META_new.yml + $(NOECHO) $(ECHO) 'abstract: '\''Generic file fetching code'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'author:' >> META_new.yml + $(NOECHO) $(ECHO) ' - '\''Jos Boumans '\''' >> META_new.yml + $(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'dynamic_config: 1' >> META_new.yml + $(NOECHO) $(ECHO) 'generated_by: '\''ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'license: perl' >> META_new.yml + $(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml + $(NOECHO) $(ECHO) ' url: http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml + $(NOECHO) $(ECHO) ' version: 1.4' >> META_new.yml + $(NOECHO) $(ECHO) 'name: File-Fetch' >> META_new.yml + $(NOECHO) $(ECHO) 'no_index:' >> META_new.yml + $(NOECHO) $(ECHO) ' directory:' >> META_new.yml + $(NOECHO) $(ECHO) ' - t' >> META_new.yml + $(NOECHO) $(ECHO) ' - inc' >> META_new.yml + $(NOECHO) $(ECHO) 'requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Basename: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Copy: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Path: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Spec: 0.82' >> META_new.yml + $(NOECHO) $(ECHO) ' IPC::Cmd: 0.42' >> META_new.yml + $(NOECHO) $(ECHO) ' Locale::Maketext::Simple: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' Module::Load::Conditional: 0.04' >> META_new.yml + $(NOECHO) $(ECHO) ' Params::Check: 0.07' >> META_new.yml + $(NOECHO) $(ECHO) ' Test::More: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'resources:' >> META_new.yml + $(NOECHO) $(ECHO) ' repository: https://github.com/jib/file-fetch' >> META_new.yml + $(NOECHO) $(ECHO) 'version: 0.38' >> META_new.yml + -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml + $(NOECHO) $(ECHO) Generating META.json + $(NOECHO) $(ECHO) '{' > META_new.json + $(NOECHO) $(ECHO) ' "abstract" : "Generic file fetching code",' >> META_new.json + $(NOECHO) $(ECHO) ' "author" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "Jos Boumans "' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "dynamic_config" : 1,' >> META_new.json + $(NOECHO) $(ECHO) ' "generated_by" : "ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921",' >> META_new.json + $(NOECHO) $(ECHO) ' "license" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "perl_5"' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "meta-spec" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "2"' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "name" : "File-Fetch",' >> META_new.json + $(NOECHO) $(ECHO) ' "no_index" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "directory" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "t",' >> META_new.json + $(NOECHO) $(ECHO) ' "inc"' >> META_new.json + $(NOECHO) $(ECHO) ' ]' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "prereqs" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "build" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "configure" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "runtime" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Basename" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Copy" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Path" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Spec" : "0.82",' >> META_new.json + $(NOECHO) $(ECHO) ' "IPC::Cmd" : "0.42",' >> META_new.json + $(NOECHO) $(ECHO) ' "Locale::Maketext::Simple" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "Module::Load::Conditional" : "0.04",' >> META_new.json + $(NOECHO) $(ECHO) ' "Params::Check" : "0.07",' >> META_new.json + $(NOECHO) $(ECHO) ' "Test::More" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "release_status" : "stable",' >> META_new.json + $(NOECHO) $(ECHO) ' "resources" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "repository" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "url" : "https://github.com/jib/file-fetch"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "0.38"' >> META_new.json + $(NOECHO) $(ECHO) '}' >> META_new.json + -$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json + + +# --- MakeMaker signature section: +signature : + cpansign -s + + +# --- MakeMaker dist_basics section: +distclean :: realclean distcheck + $(NOECHO) $(NOOP) + +distcheck : + $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck + +skipcheck : + $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck + +manifest : + $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest + +veryclean : realclean + $(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old + + + +# --- MakeMaker dist_core section: + +dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE) + $(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \ + -e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' -- + +tardist : $(DISTVNAME).tar$(SUFFIX) + $(NOECHO) $(NOOP) + +uutardist : $(DISTVNAME).tar$(SUFFIX) + uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu + +$(DISTVNAME).tar$(SUFFIX) : distdir + $(PREOP) + $(TO_UNIX) + $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(COMPRESS) $(DISTVNAME).tar + $(POSTOP) + +zipdist : $(DISTVNAME).zip + $(NOECHO) $(NOOP) + +$(DISTVNAME).zip : distdir + $(PREOP) + $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(POSTOP) + +shdist : distdir + $(PREOP) + $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar + $(RM_RF) $(DISTVNAME) + $(POSTOP) + + +# --- MakeMaker distdir section: +create_distdir : + $(RM_RF) $(DISTVNAME) + $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \ + -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" + +distdir : create_distdir distmeta + $(NOECHO) $(NOOP) + + + +# --- MakeMaker dist_test section: +disttest : distdir + cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL "INSTALLDIRS=vendor" + cd $(DISTVNAME) && $(MAKE) $(PASTHRU) + cd $(DISTVNAME) && $(MAKE) test $(PASTHRU) + + + +# --- MakeMaker dist_ci section: + +ci : + $(PERLRUN) "-MExtUtils::Manifest=maniread" \ + -e "@all = keys %{ maniread() };" \ + -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \ + -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});" + + +# --- MakeMaker distmeta section: +distmeta : create_distdir metafile + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -e q{META.yml};' \ + -e 'eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.yml to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -f q{META.json};' \ + -e 'eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.json to MANIFEST: $$$${'\''@'\''}\n"' -- + + + +# --- MakeMaker distsignature section: +distsignature : create_distdir + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) } ' \ + -e ' or print "Could not add SIGNATURE to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE + cd $(DISTVNAME) && cpansign -s + + + +# --- MakeMaker install section: + +install :: pure_install doc_install + $(NOECHO) $(NOOP) + +install_perl :: pure_perl_install doc_perl_install + $(NOECHO) $(NOOP) + +install_site :: pure_site_install doc_site_install + $(NOECHO) $(NOOP) + +install_vendor :: pure_vendor_install doc_vendor_install + $(NOECHO) $(NOOP) + +pure_install :: pure_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +doc_install :: doc_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +pure__install : pure_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +doc__install : doc_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_perl_install :: all + $(NOECHO) $(MOD_INSTALL) \ + read $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist \ + write $(DESTINSTALLARCHLIB)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(DESTINSTALLPRIVLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLARCHLIB) \ + $(INST_BIN) $(DESTINSTALLBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(SITEARCHEXP)/auto/$(FULLEXT) + + +pure_site_install :: all + $(NOECHO) $(MOD_INSTALL) \ + read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \ + write $(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(DESTINSTALLSITELIB) \ + $(INST_ARCHLIB) $(DESTINSTALLSITEARCH) \ + $(INST_BIN) $(DESTINSTALLSITEBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSITESCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(PERL_ARCHLIB)/auto/$(FULLEXT) + +pure_vendor_install :: all + $(NOECHO) $(MOD_INSTALL) \ + read $(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist \ + write $(DESTINSTALLVENDORARCH)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(DESTINSTALLVENDORLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) \ + $(INST_BIN) $(DESTINSTALLVENDORBIN) \ + $(INST_SCRIPT) $(DESTINSTALLVENDORSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR) + +doc_perl_install :: all + $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod + -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB) + -$(NOECHO) $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLPRIVLIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(DESTINSTALLARCHLIB)/perllocal.pod + +doc_site_install :: all + $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod + -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB) + -$(NOECHO) $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLSITELIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(DESTINSTALLARCHLIB)/perllocal.pod + +doc_vendor_install :: all + $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod + -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB) + -$(NOECHO) $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLVENDORLIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(DESTINSTALLARCHLIB)/perllocal.pod + + +uninstall :: uninstall_from_$(INSTALLDIRS)dirs + $(NOECHO) $(NOOP) + +uninstall_from_perldirs :: + $(NOECHO) $(UNINSTALL) $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist + +uninstall_from_sitedirs :: + $(NOECHO) $(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist + +uninstall_from_vendordirs :: + $(NOECHO) $(UNINSTALL) $(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist + + +# --- MakeMaker force section: +# Phony target to force checking subdirectories. +FORCE : + $(NOECHO) $(NOOP) + + +# --- MakeMaker perldepend section: + + +# --- MakeMaker makefile section: +# We take a very conservative approach here, but it's worth it. +# We move Makefile to Makefile.old here to avoid gnu make looping. +$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) + $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?" + $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..." + -$(NOECHO) $(RM_F) $(MAKEFILE_OLD) + -$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) + - $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL) + $(PERLRUN) Makefile.PL "INSTALLDIRS=vendor" + $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <==" + $(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <==" + $(FALSE) + + + +# --- MakeMaker staticmake section: + +# --- MakeMaker makeaperl section --- +MAP_TARGET = perl +FULLPERL = /usr/bin/perl + +$(MAP_TARGET) :: static $(MAKE_APERL_FILE) + $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@ + +$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib + $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) + $(NOECHO) $(PERLRUNINST) \ + Makefile.PL DIR= \ + MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ + MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= \ + INSTALLDIRS=vendor + + +# --- MakeMaker test section: + +TEST_VERBOSE=0 +TEST_TYPE=test_$(LINKTYPE) +TEST_FILE = test.pl +TEST_FILES = t/*.t +TESTDB_SW = -d + +testdb :: testdb_$(LINKTYPE) + +test :: $(TEST_TYPE) subdirs-test + +subdirs-test :: + $(NOECHO) $(NOOP) + + +test_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-MExtUtils::Command::MM" "-e" "test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES) + +testdb_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +test_ : test_dynamic + +test_static :: test_dynamic +testdb_static :: testdb_dynamic + + +# --- MakeMaker ppd section: +# Creates a PPD (Perl Package Description) for a binary distribution. +ppd : + $(NOECHO) $(ECHO) '' > $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' Generic file fetching code' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' Jos Boumans <kane[at]cpan.org>' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) '' >> $(DISTNAME).ppd + + +# --- MakeMaker pm_to_blib section: + +pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM) + $(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \ + lib/File/Fetch.pm blib/lib/File/Fetch.pm + $(NOECHO) $(TOUCH) pm_to_blib + + +# --- MakeMaker selfdocument section: + + +# --- MakeMaker postamble section: + + +# End. diff --git a/File-Fetch-0.38/Makefile.PL b/File-Fetch-0.38/Makefile.PL new file mode 100644 index 0000000..336d6ff --- /dev/null +++ b/File-Fetch-0.38/Makefile.PL @@ -0,0 +1,56 @@ +use ExtUtils::MakeMaker; +use strict; + +WriteMakefile1( + LICENSE => 'perl', + META_MERGE => { + resources => { + repository => 'https://github.com/jib/file-fetch', + }, + }, + #BUILD_REQUIRES => { + #}, + + NAME => 'File::Fetch', + VERSION_FROM => 'lib/File/Fetch.pm', # finds $VERSION + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz' }, + PREREQ_PM => { + 'IPC::Cmd' => 0.42, # ipc::open3 bugfix + 'Test::More' => 0, + 'File::Copy' => 0, + 'File::Spec' => 0.82, + 'File::Path' => 0, + 'File::Basename' => 0, + 'Params::Check' => 0.07, + 'Module::Load::Conditional' => 0.04, + 'Locale::Maketext::Simple' => 0, + }, + INSTALLDIRS => ( $] >= 5.009005 ? 'perl' : 'site' ), + AUTHOR => 'Jos Boumans ', + ABSTRACT => 'Generic file fetching code', + clean => {FILES => 't/tmp'}, +); + +sub WriteMakefile1 { #Written by Alexandr Ciornii, version 0.21. Added by eumm-upgrade. + my %params=@_; + my $eumm_version=$ExtUtils::MakeMaker::VERSION; + $eumm_version=eval $eumm_version; + die "EXTRA_META is deprecated" if exists $params{EXTRA_META}; + die "License not specified" if not exists $params{LICENSE}; + if ($params{BUILD_REQUIRES} and $eumm_version < 6.5503) { + #EUMM 6.5502 has problems with BUILD_REQUIRES + $params{PREREQ_PM}={ %{$params{PREREQ_PM} || {}} , %{$params{BUILD_REQUIRES}} }; + delete $params{BUILD_REQUIRES}; + } + delete $params{CONFIGURE_REQUIRES} if $eumm_version < 6.52; + delete $params{MIN_PERL_VERSION} if $eumm_version < 6.48; + delete $params{META_MERGE} if $eumm_version < 6.46; + delete $params{META_ADD} if $eumm_version < 6.46; + delete $params{LICENSE} if $eumm_version < 6.31; + delete $params{AUTHOR} if $] < 5.005; + delete $params{ABSTRACT_FROM} if $] < 5.005; + delete $params{BINARY_LOCATION} if $] < 5.005; + + WriteMakefile(%params); +} + diff --git a/File-Fetch-0.38/README b/File-Fetch-0.38/README new file mode 100644 index 0000000..84a6a63 --- /dev/null +++ b/File-Fetch-0.38/README @@ -0,0 +1,40 @@ +This is the README file for File::Fetch, a perl module for generic +file fetching. + +Please refer to 'perldoc File::Fetch' after installation for details. + +##################################################################### + +* Description + +File::Fetch + + File::Fetch is a generic file fetching mechanism. + + It allows you to fetch any file pointed to by a ftp, http + or file uri by a number of different means. + +##################################################################### + +* Installation + +File::Fetch follows the standard perl module install process + +perl Makefile.PL +make +make test +make install + +The module uses no C or XS parts, so no c-compiler is required. + +###################################################################### + +AUTHOR + This module by Jos Boumans . + +COPYRIGHT + This module is copyright (c) 2002 Jos Boumans . All + rights reserved. + + This library is free software; you may redistribute and/or modify it + under the same terms as Perl itself. diff --git a/File-Fetch-0.38/blib/arch/.exists b/File-Fetch-0.38/blib/arch/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/blib/arch/auto/File/Fetch/.exists b/File-Fetch-0.38/blib/arch/auto/File/Fetch/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/blib/bin/.exists b/File-Fetch-0.38/blib/bin/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/blib/lib/File/.exists b/File-Fetch-0.38/blib/lib/File/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/blib/lib/File/Fetch.pm b/File-Fetch-0.38/blib/lib/File/Fetch.pm new file mode 100644 index 0000000..37f7bc6 --- /dev/null +++ b/File-Fetch-0.38/blib/lib/File/Fetch.pm @@ -0,0 +1,1658 @@ +package File::Fetch; + +use strict; +use FileHandle; +use File::Temp; +use File::Copy; +use File::Spec; +use File::Spec::Unix; +use File::Basename qw[dirname]; + +use Cwd qw[cwd]; +use Carp qw[carp]; +use IPC::Cmd qw[can_run run QUOTE]; +use File::Path qw[mkpath]; +use File::Temp qw[tempdir]; +use Params::Check qw[check]; +use Module::Load::Conditional qw[can_load]; +use Locale::Maketext::Simple Style => 'gettext'; + +use vars qw[ $VERBOSE $PREFER_BIN $FROM_EMAIL $USER_AGENT + $BLACKLIST $METHOD_FAIL $VERSION $METHODS + $FTP_PASSIVE $TIMEOUT $DEBUG $WARN + ]; + +$VERSION = '0.38'; +$VERSION = eval $VERSION; # avoid warnings with development releases +$PREFER_BIN = 0; # XXX TODO implement +$FROM_EMAIL = 'File-Fetch@example.com'; +$USER_AGENT = "File::Fetch/$VERSION"; +$BLACKLIST = [qw|ftp|]; +$METHOD_FAIL = { }; +$FTP_PASSIVE = 1; +$TIMEOUT = 0; +$DEBUG = 0; +$WARN = 1; + +### methods available to fetch the file depending on the scheme +$METHODS = { + http => [ qw|lwp httptiny wget curl lftp fetch httplite lynx iosock| ], + ftp => [ qw|lwp netftp wget curl lftp fetch ncftp ftp| ], + file => [ qw|lwp lftp file| ], + rsync => [ qw|rsync| ] +}; + +### silly warnings ### +local $Params::Check::VERBOSE = 1; +local $Params::Check::VERBOSE = 1; +local $Module::Load::Conditional::VERBOSE = 0; +local $Module::Load::Conditional::VERBOSE = 0; + +### see what OS we are on, important for file:// uris ### +use constant ON_WIN => ($^O eq 'MSWin32'); +use constant ON_VMS => ($^O eq 'VMS'); +use constant ON_UNIX => (!ON_WIN); +use constant HAS_VOL => (ON_WIN); +use constant HAS_SHARE => (ON_WIN); +use constant HAS_FETCH => ( $^O =~ m!^(freebsd|netbsd|dragonfly)$! ); + +=pod + +=head1 NAME + +File::Fetch - A generic file fetching mechanism + +=head1 SYNOPSIS + + use File::Fetch; + + ### build a File::Fetch object ### + my $ff = File::Fetch->new(uri => 'http://some.where.com/dir/a.txt'); + + ### fetch the uri to cwd() ### + my $where = $ff->fetch() or die $ff->error; + + ### fetch the uri to /tmp ### + my $where = $ff->fetch( to => '/tmp' ); + + ### parsed bits from the uri ### + $ff->uri; + $ff->scheme; + $ff->host; + $ff->path; + $ff->file; + +=head1 DESCRIPTION + +File::Fetch is a generic file fetching mechanism. + +It allows you to fetch any file pointed to by a C, C, +C, or C uri by a number of different means. + +See the C section further down for details. + +=head1 ACCESSORS + +A C object has the following accessors + +=over 4 + +=item $ff->uri + +The uri you passed to the constructor + +=item $ff->scheme + +The scheme from the uri (like 'file', 'http', etc) + +=item $ff->host + +The hostname in the uri. Will be empty if host was originally +'localhost' for a 'file://' url. + +=item $ff->vol + +On operating systems with the concept of a volume the second element +of a file:// is considered to the be volume specification for the file. +Thus on Win32 this routine returns the volume, on other operating +systems this returns nothing. + +On Windows this value may be empty if the uri is to a network share, in +which case the 'share' property will be defined. Additionally, volume +specifications that use '|' as ':' will be converted on read to use ':'. + +On VMS, which has a volume concept, this field will be empty because VMS +file specifications are converted to absolute UNIX format and the volume +information is transparently included. + +=item $ff->share + +On systems with the concept of a network share (currently only Windows) returns +the sharename from a file://// url. On other operating systems returns empty. + +=item $ff->path + +The path from the uri, will be at least a single '/'. + +=item $ff->file + +The name of the remote file. For the local file name, the +result of $ff->output_file will be used. + +=item $ff->file_default + +The name of the default local file, that $ff->output_file falls back to if +it would otherwise return no filename. For example when fetching a URI like +http://www.abc.net.au/ the contents retrieved may be from a remote file called +'index.html'. The default value of this attribute is literally 'file_default'. + +=cut + + +########################## +### Object & Accessors ### +########################## + +{ + ### template for autogenerated accessors ### + my $Tmpl = { + scheme => { default => 'http' }, + host => { default => 'localhost' }, + path => { default => '/' }, + file => { required => 1 }, + uri => { required => 1 }, + vol => { default => '' }, # windows for file:// uris + share => { default => '' }, # windows for file:// uris + file_default => { default => 'file_default' }, + tempdir_root => { required => 1 }, # Should be lazy-set at ->new() + _error_msg => { no_override => 1 }, + _error_msg_long => { no_override => 1 }, + }; + + for my $method ( keys %$Tmpl ) { + no strict 'refs'; + *$method = sub { + my $self = shift; + $self->{$method} = $_[0] if @_; + return $self->{$method}; + } + } + + sub _create { + my $class = shift; + my %hash = @_; + + my $args = check( $Tmpl, \%hash ) or return; + + bless $args, $class; + + if( lc($args->scheme) ne 'file' and not $args->host ) { + return $class->_error(loc( + "Hostname required when fetching from '%1'",$args->scheme)); + } + + for (qw[path]) { + unless( $args->$_() ) { # 5.5.x needs the () + return $class->_error(loc("No '%1' specified",$_)); + } + } + + return $args; + } +} + +=item $ff->output_file + +The name of the output file. This is the same as $ff->file, +but any query parameters are stripped off. For example: + + http://example.com/index.html?x=y + +would make the output file be C rather than +C. + +=back + +=cut + +sub output_file { + my $self = shift; + my $file = $self->file; + + $file =~ s/\?.*$//g; + + $file ||= $self->file_default; + + return $file; +} + +### XXX do this or just point to URI::Escape? +# =head2 $esc_uri = $ff->escaped_uri +# +# =cut +# +# ### most of this is stolen straight from URI::escape +# { ### Build a char->hex map +# my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255; +# +# sub escaped_uri { +# my $self = shift; +# my $uri = $self->uri; +# +# ### Default unsafe characters. RFC 2732 ^(uric - reserved) +# $uri =~ s/([^A-Za-z0-9\-_.!~*'()])/ +# $escapes{$1} || $self->_fail_hi($1)/ge; +# +# return $uri; +# } +# +# sub _fail_hi { +# my $self = shift; +# my $char = shift; +# +# $self->_error(loc( +# "Can't escape '%1', try using the '%2' module instead", +# sprintf("\\x{%04X}", ord($char)), 'URI::Escape' +# )); +# } +# +# sub output_file { +# +# } +# +# +# } + +=head1 METHODS + +=head2 $ff = File::Fetch->new( uri => 'http://some.where.com/dir/file.txt' ); + +Parses the uri and creates a corresponding File::Fetch::Item object, +that is ready to be Ced and returns it. + +Returns false on failure. + +=cut + +sub new { + my $class = shift; + my %hash = @_; + + my ($uri, $file_default, $tempdir_root); + my $tmpl = { + uri => { required => 1, store => \$uri }, + file_default => { required => 0, store => \$file_default }, + tempdir_root => { required => 0, store => \$tempdir_root }, + }; + + check( $tmpl, \%hash ) or return; + + ### parse the uri to usable parts ### + my $href = $class->_parse_uri( $uri ) or return; + + $href->{file_default} = $file_default if $file_default; + $href->{tempdir_root} = File::Spec->rel2abs( $tempdir_root ) if $tempdir_root; + $href->{tempdir_root} = File::Spec->rel2abs( Cwd::cwd ) if not $href->{tempdir_root}; + + ### make it into a FFI object ### + my $ff = $class->_create( %$href ) or return; + + + ### return the object ### + return $ff; +} + +### parses an uri to a hash structure: +### +### $class->_parse_uri( 'ftp://ftp.cpan.org/pub/mirror/index.txt' ) +### +### becomes: +### +### $href = { +### scheme => 'ftp', +### host => 'ftp.cpan.org', +### path => '/pub/mirror', +### file => 'index.html' +### }; +### +### In the case of file:// urls there maybe be additional fields +### +### For systems with volume specifications such as Win32 there will be +### a volume specifier provided in the 'vol' field. +### +### 'vol' => 'volumename' +### +### For windows file shares there may be a 'share' key specified +### +### 'share' => 'sharename' +### +### Note that the rules of what a file:// url means vary by the operating system +### of the host being addressed. Thus file:///d|/foo/bar.txt means the obvious +### 'D:\foo\bar.txt' on windows, but on unix it means '/d|/foo/bar.txt' and +### not '/foo/bar.txt' +### +### Similarly if the host interpreting the url is VMS then +### file:///disk$user/my/notes/note12345.txt' means +### 'DISK$USER:[MY.NOTES]NOTE123456.TXT' but will be returned the same as +### if it is unix where it means /disk$user/my/notes/note12345.txt'. +### Except for some cases in the File::Spec methods, Perl on VMS will generally +### handle UNIX format file specifications. +### +### This means it is impossible to serve certain file:// urls on certain systems. +### +### Thus are the problems with a protocol-less specification. :-( +### + +sub _parse_uri { + my $self = shift; + my $uri = shift or return; + + my $href = { uri => $uri }; + + ### find the scheme ### + $uri =~ s|^(\w+)://||; + $href->{scheme} = $1; + + ### See rfc 1738 section 3.10 + ### http://www.faqs.org/rfcs/rfc1738.html + ### And wikipedia for more on windows file:// urls + ### http://en.wikipedia.org/wiki/File:// + if( $href->{scheme} eq 'file' ) { + + my @parts = split '/',$uri; + + ### file://hostname/... + ### file://hostname/... + ### normalize file://localhost with file:/// + $href->{host} = $parts[0] || ''; + + ### index in @parts where the path components begin; + my $index = 1; + + ### file:////hostname/sharename/blah.txt + if ( HAS_SHARE and not length $parts[0] and not length $parts[1] ) { + + $href->{host} = $parts[2] || ''; # avoid warnings + $href->{share} = $parts[3] || ''; # avoid warnings + + $index = 4 # index after the share + + ### file:///D|/blah.txt + ### file:///D:/blah.txt + } elsif (HAS_VOL) { + + ### this code comes from dmq's patch, but: + ### XXX if volume is empty, wouldn't that be an error? --kane + ### if so, our file://localhost test needs to be fixed as wel + $href->{vol} = $parts[1] || ''; + + ### correct D| style colume descriptors + $href->{vol} =~ s/\A([A-Z])\|\z/$1:/i if ON_WIN; + + $index = 2; # index after the volume + } + + ### rebuild the path from the leftover parts; + $href->{path} = join '/', '', splice( @parts, $index, $#parts ); + + } else { + ### using anything but qw() in hash slices may produce warnings + ### in older perls :-( + @{$href}{ qw(host path) } = $uri =~ m|([^/]*)(/.*)$|s; + } + + ### split the path into file + dir ### + { my @parts = File::Spec::Unix->splitpath( delete $href->{path} ); + $href->{path} = $parts[1]; + $href->{file} = $parts[2]; + } + + ### host will be empty if the target was 'localhost' and the + ### scheme was 'file' + $href->{host} = '' if ($href->{host} eq 'localhost') and + ($href->{scheme} eq 'file'); + + return $href; +} + +=head2 $where = $ff->fetch( [to => /my/output/dir/ | \$scalar] ) + +Fetches the file you requested and returns the full path to the file. + +By default it writes to C, but you can override that by specifying +the C argument: + + ### file fetch to /tmp, full path to the file in $where + $where = $ff->fetch( to => '/tmp' ); + + ### file slurped into $scalar, full path to the file in $where + ### file is downloaded to a temp directory and cleaned up at exit time + $where = $ff->fetch( to => \$scalar ); + +Returns the full path to the downloaded file on success, and false +on failure. + +=cut + +sub fetch { + my $self = shift or return; + my %hash = @_; + + my $target; + my $tmpl = { + to => { default => cwd(), store => \$target }, + }; + + check( $tmpl, \%hash ) or return; + + my ($to, $fh); + ### you want us to slurp the contents + if( ref $target and UNIVERSAL::isa( $target, 'SCALAR' ) ) { + $to = tempdir( 'FileFetch.XXXXXX', DIR => $self->tempdir_root, CLEANUP => 1 ); + + ### plain old fetch + } else { + $to = $target; + + ### On VMS force to VMS format so File::Spec will work. + $to = VMS::Filespec::vmspath($to) if ON_VMS; + + ### create the path if it doesn't exist yet ### + unless( -d $to ) { + eval { mkpath( $to ) }; + + return $self->_error(loc("Could not create path '%1'",$to)) if $@; + } + } + + ### set passive ftp if required ### + local $ENV{FTP_PASSIVE} = $FTP_PASSIVE; + + ### we dont use catfile on win32 because if we are using a cygwin tool + ### under cmd.exe they wont understand windows style separators. + my $out_to = ON_WIN ? $to.'/'.$self->output_file + : File::Spec->catfile( $to, $self->output_file ); + + for my $method ( @{ $METHODS->{$self->scheme} } ) { + my $sub = '_'.$method.'_fetch'; + + unless( __PACKAGE__->can($sub) ) { + $self->_error(loc("Cannot call method for '%1' -- WEIRD!", + $method)); + next; + } + + ### method is blacklisted ### + next if grep { lc $_ eq $method } @$BLACKLIST; + + ### method is known to fail ### + next if $METHOD_FAIL->{$method}; + + ### there's serious issues with IPC::Run and quoting of command + ### line arguments. using quotes in the wrong place breaks things, + ### and in the case of say, + ### C:\cygwin\bin\wget.EXE --quiet --passive-ftp --output-document + ### "index.html" "http://www.cpan.org/index.html?q=1&y=2" + ### it doesn't matter how you quote, it always fails. + local $IPC::Cmd::USE_IPC_RUN = 0; + + if( my $file = $self->$sub( + to => $out_to + )){ + + unless( -e $file && -s _ ) { + $self->_error(loc("'%1' said it fetched '%2', ". + "but it was not created",$method,$file)); + + ### mark the failure ### + $METHOD_FAIL->{$method} = 1; + + next; + + } else { + + ### slurp mode? + if( ref $target and UNIVERSAL::isa( $target, 'SCALAR' ) ) { + + ### open the file + open my $fh, "<$file" or do { + $self->_error( + loc("Could not open '%1': %2", $file, $!)); + return; + }; + + ### slurp + $$target = do { local $/; <$fh> }; + + } + + my $abs = File::Spec->rel2abs( $file ); + return $abs; + + } + } + } + + + ### if we got here, we looped over all methods, but we weren't able + ### to fetch it. + return; +} + +######################## +### _*_fetch methods ### +######################## + +### LWP fetching ### +sub _lwp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### modules required to download with lwp ### + my $use_list = { + LWP => '0.0', + 'LWP::UserAgent' => '0.0', + 'HTTP::Request' => '0.0', + 'HTTP::Status' => '0.0', + URI => '0.0', + + }; + + unless( can_load( modules => $use_list ) ) { + $METHOD_FAIL->{'lwp'} = 1; + return; + } + + ### setup the uri object + my $uri = URI->new( File::Spec::Unix->catfile( + $self->path, $self->file + ) ); + + ### special rules apply for file:// uris ### + $uri->scheme( $self->scheme ); + $uri->host( $self->scheme eq 'file' ? '' : $self->host ); + $uri->userinfo("anonymous:$FROM_EMAIL") if $self->scheme ne 'file'; + + ### set up the useragent object + my $ua = LWP::UserAgent->new(); + $ua->timeout( $TIMEOUT ) if $TIMEOUT; + $ua->agent( $USER_AGENT ); + $ua->from( $FROM_EMAIL ); + $ua->env_proxy; + + my $res = $ua->mirror($uri, $to) or return; + + ### uptodate or fetched ok ### + if ( $res->code == 304 or $res->code == 200 ) { + return $to; + + } else { + return $self->_error(loc("Fetch failed! HTTP response: %1 %2 [%3]", + $res->code, HTTP::Status::status_message($res->code), + $res->status_line)); + } + +} + +### HTTP::Tiny fetching ### +sub _httptiny_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $use_list = { + 'HTTP::Tiny' => '0.008', + + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'httptiny'} = 1; + return; + } + + my $uri = $self->uri; + + my $http = HTTP::Tiny->new( ( $TIMEOUT ? ( timeout => $TIMEOUT ) : () ) ); + + my $rc = $http->mirror( $uri, $to ); + + unless ( $rc->{success} ) { + + return $self->_error(loc( "Fetch failed! HTTP response: %1 [%2]", + $rc->{status}, $rc->{reason} ) ); + + } + + return $to; + +} + +### HTTP::Lite fetching ### +sub _httplite_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### modules required to download with lwp ### + my $use_list = { + 'HTTP::Lite' => '2.2', + + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'httplite'} = 1; + return; + } + + my $uri = $self->uri; + my $retries = 0; + + RETRIES: while ( $retries++ < 5 ) { + + my $http = HTTP::Lite->new(); + # Naughty naughty but there isn't any accessor/setter + $http->{timeout} = $TIMEOUT if $TIMEOUT; + $http->http11_mode(1); + + my $fh = FileHandle->new; + + unless ( $fh->open($to,'>') ) { + return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + } + + $fh->autoflush(1); + + binmode $fh; + + my $rc = $http->request( $uri, sub { my ($self,$dref,$cbargs) = @_; local $\; print {$cbargs} $$dref }, $fh ); + + close $fh; + + if ( $rc == 301 || $rc == 302 ) { + my $loc; + HEADERS: for ($http->headers_array) { + /Location: (\S+)/ and $loc = $1, last HEADERS; + } + #$loc or last; # Think we should squeal here. + if ($loc =~ m!^/!) { + $uri =~ s{^(\w+?://[^/]+)/.*$}{$1}; + $uri .= $loc; + } + else { + $uri = $loc; + } + next RETRIES; + } + elsif ( $rc == 200 ) { + return $to; + } + else { + return $self->_error(loc("Fetch failed! HTTP response: %1 [%2]", + $rc, $http->status_message)); + } + + } # Loop for 5 retries. + + return $self->_error("Fetch failed! Gave up after 5 tries"); + +} + +### Simple IO::Socket::INET fetching ### +sub _iosock_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $use_list = { + 'IO::Socket::INET' => '0.0', + 'IO::Select' => '0.0', + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'iosock'} = 1; + return; + } + + my $sock = IO::Socket::INET->new( + PeerHost => $self->host, + ( $self->host =~ /:/ ? () : ( PeerPort => 80 ) ), + ); + + unless ( $sock ) { + return $self->_error(loc("Could not open socket to '%1', '%2'",$self->host,$!)); + } + + my $fh = FileHandle->new; + + # Check open() + + unless ( $fh->open($to,'>') ) { + return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + } + + $fh->autoflush(1); + binmode $fh; + + my $path = File::Spec::Unix->catfile( $self->path, $self->file ); + my $req = "GET $path HTTP/1.0\x0d\x0aHost: " . $self->host . "\x0d\x0a\x0d\x0a"; + $sock->send( $req ); + + my $select = IO::Select->new( $sock ); + + my $resp = ''; + my $normal = 0; + while ( $select->can_read( $TIMEOUT || 60 ) ) { + my $ret = $sock->sysread( $resp, 4096, length($resp) ); + if ( !defined $ret or $ret == 0 ) { + $select->remove( $sock ); + $normal++; + } + } + close $sock; + + unless ( $normal ) { + return $self->_error(loc("Socket timed out after '%1' seconds", ( $TIMEOUT || 60 ))); + } + + # Check the "response" + # Strip preceding blank lines apparently they are allowed (RFC 2616 4.1) + $resp =~ s/^(\x0d?\x0a)+//; + # Check it is an HTTP response + unless ( $resp =~ m!^HTTP/(\d+)\.(\d+)!i ) { + return $self->_error(loc("Did not get a HTTP response from '%1'",$self->host)); + } + + # Check for OK + my ($code) = $resp =~ m!^HTTP/\d+\.\d+\s+(\d+)!i; + unless ( $code eq '200' ) { + return $self->_error(loc("Got a '%1' from '%2' expected '200'",$code,$self->host)); + } + + { + local $\; + print $fh +($resp =~ m/\x0d\x0a\x0d\x0a(.*)$/s )[0]; + } + close $fh; + return $to; +} + +### Net::FTP fetching +sub _netftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### required modules ### + my $use_list = { 'Net::FTP' => 0 }; + + unless( can_load( modules => $use_list ) ) { + $METHOD_FAIL->{'netftp'} = 1; + return; + } + + ### make connection ### + my $ftp; + my @options = ($self->host); + push(@options, Timeout => $TIMEOUT) if $TIMEOUT; + unless( $ftp = Net::FTP->new( @options ) ) { + return $self->_error(loc("Ftp creation failed: %1",$@)); + } + + ### login ### + unless( $ftp->login( anonymous => $FROM_EMAIL ) ) { + return $self->_error(loc("Could not login to '%1'",$self->host)); + } + + ### set binary mode, just in case ### + $ftp->binary; + + ### create the remote path + ### remember remote paths are unix paths! [#11483] + my $remote = File::Spec::Unix->catfile( $self->path, $self->file ); + + ### fetch the file ### + my $target; + unless( $target = $ftp->get( $remote, $to ) ) { + return $self->_error(loc("Could not fetch '%1' from '%2'", + $remote, $self->host)); + } + + ### log out ### + $ftp->quit; + + return $target; + +} + +### /bin/wget fetch ### +sub _wget_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $wget; + ### see if we have a wget binary ### + unless( $wget = can_run('wget') ) { + $METHOD_FAIL->{'wget'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $wget, '--quiet' ]; + + ### if a timeout is set, add it ### + push(@$cmd, '--timeout=' . $TIMEOUT) if $TIMEOUT; + + ### run passive if specified ### + push @$cmd, '--passive-ftp' if $FTP_PASSIVE; + + ### set the output document, add the uri ### + push @$cmd, '--output-document', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + +### /bin/lftp fetch ### +sub _lftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a lftp binary ### + my $lftp; + unless( $lftp = can_run('lftp') ) { + $METHOD_FAIL->{'lftp'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $lftp, '-f' ]; + + my $fh = File::Temp->new; + + my $str; + + ### if a timeout is set, add it ### + $str .= "set net:timeout $TIMEOUT;\n" if $TIMEOUT; + + ### run passive if specified ### + $str .= "set ftp:passive-mode 1;\n" if $FTP_PASSIVE; + + ### set the output document, add the uri ### + ### quote the URI, because lftp supports certain shell + ### expansions, most notably & for backgrounding. + ### ' quote does nto work, must be " + $str .= q[get ']. $self->uri .q[' -o ]. $to . $/; + + if( $DEBUG ) { + my $pp_str = join ' ', split $/, $str; + print "# lftp command: $pp_str\n"; + } + + ### write straight to the file. + $fh->autoflush(1); + print $fh $str; + + ### the command needs to be 1 string to be executed + push @$cmd, $fh->filename; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + + + +### /bin/ftp fetch ### +sub _ftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a ftp binary ### + my $ftp; + unless( $ftp = can_run('ftp') ) { + $METHOD_FAIL->{'ftp'} = 1; + return; + } + + my $fh = FileHandle->new; + + local $SIG{CHLD} = 'IGNORE'; + + unless ($fh->open("$ftp -n", '|-')) { + return $self->_error(loc("%1 creation failed: %2", $ftp, $!)); + } + + my @dialog = ( + "lcd " . dirname($to), + "open " . $self->host, + "user anonymous $FROM_EMAIL", + "cd /", + "cd " . $self->path, + "binary", + "get " . $self->file . " " . $self->output_file, + "quit", + ); + + foreach (@dialog) { $fh->print($_, "\n") } + $fh->close or return; + + return $to; +} + +### lynx is stupid - it decompresses any .gz file it finds to be text +### use /bin/lynx to fetch files +sub _lynx_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a lynx binary ### + my $lynx; + unless ( $lynx = can_run('lynx') ){ + $METHOD_FAIL->{'lynx'} = 1; + return; + } + + unless( IPC::Cmd->can_capture_buffer ) { + $METHOD_FAIL->{'lynx'} = 1; + + return $self->_error(loc( + "Can not capture buffers. Can not use '%1' to fetch files", + 'lynx' )); + } + + ### check if the HTTP resource exists ### + if ($self->uri =~ /^https?:\/\//i) { + my $cmd = [ + $lynx, + '-head', + '-source', + "-auth=anonymous:$FROM_EMAIL", + ]; + + push @$cmd, "-connect_timeout=$TIMEOUT" if $TIMEOUT; + + push @$cmd, $self->uri; + + ### shell out ### + my $head; + unless(run( command => $cmd, + buffer => \$head, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $head || '')); + } + + unless($head =~ /^HTTP\/\d+\.\d+ 200\b/) { + return $self->_error(loc("Command failed: %1", $head || '')); + } + } + + ### write to the output file ourselves, since lynx ass_u_mes to much + my $local = FileHandle->new( $to, 'w' ) + or return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + + ### dump to stdout ### + my $cmd = [ + $lynx, + '-source', + "-auth=anonymous:$FROM_EMAIL", + ]; + + push @$cmd, "-connect_timeout=$TIMEOUT" if $TIMEOUT; + + ### DO NOT quote things for IPC::Run, it breaks stuff. + push @$cmd, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### DO NOT quote things for IPC::Run, it breaks stuff. + # $IPC::Cmd::USE_IPC_RUN + # ? $self->uri + # : QUOTE. $self->uri .QUOTE; + + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $captured || '')); + } + + ### print to local file ### + ### XXX on a 404 with a special error page, $captured will actually + ### hold the contents of that page, and make it *appear* like the + ### request was a success, when really it wasn't :( + ### there doesn't seem to be an option for lynx to change the exit + ### code based on a 4XX status or so. + ### the closest we can come is using --error_file and parsing that, + ### which is very unreliable ;( + $local->print( $captured ); + $local->close or return; + + return $to; +} + +### use /bin/ncftp to fetch files +sub _ncftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### we can only set passive mode in interactive sessions, so bail out + ### if $FTP_PASSIVE is set + return if $FTP_PASSIVE; + + ### see if we have a ncftp binary ### + my $ncftp; + unless( $ncftp = can_run('ncftp') ) { + $METHOD_FAIL->{'ncftp'} = 1; + return; + } + + my $cmd = [ + $ncftp, + '-V', # do not be verbose + '-p', $FROM_EMAIL, # email as password + $self->host, # hostname + dirname($to), # local dir for the file + # remote path to the file + ### DO NOT quote things for IPC::Run, it breaks stuff. + $IPC::Cmd::USE_IPC_RUN + ? File::Spec::Unix->catdir( $self->path, $self->file ) + : QUOTE. File::Spec::Unix->catdir( + $self->path, $self->file ) .QUOTE + + ]; + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $captured || '')); + } + + return $to; + +} + +### use /bin/curl to fetch files +sub _curl_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $curl; + unless ( $curl = can_run('curl') ) { + $METHOD_FAIL->{'curl'} = 1; + return; + } + + ### these long opts are self explanatory - I like that -jmb + my $cmd = [ $curl, '-q' ]; + + 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', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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; + +} + +### /usr/bin/fetch fetch! ### +sub _fetch_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a fetch binary ### + my $fetch; + unless( HAS_FETCH and $fetch = can_run('fetch') ) { + $METHOD_FAIL->{'fetch'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $fetch, '-q' ]; + + ### if a timeout is set, add it ### + push(@$cmd, '-T', $TIMEOUT) if $TIMEOUT; + + ### run passive if specified ### + #push @$cmd, '-p' if $FTP_PASSIVE; + local $ENV{'FTP_PASSIVE_MODE'} = 1 if $FTP_PASSIVE; + + ### set the output document, add the uri ### + push @$cmd, '-o', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + +### 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 + ### whereas 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 files +sub _rsync_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $rsync; + unless ( $rsync = can_run('rsync') ) { + $METHOD_FAIL->{'rsync'} = 1; + return; + } + + 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, $self->uri, $to; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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 %1 failed: %2", + "@$cmd" || '', $captured || '')); + } + + return $to; + +} + +################################# +# +# Error code +# +################################# + +=pod + +=head2 $ff->error([BOOL]) + +Returns the last encountered error as string. +Pass it a true value to get the C output instead. + +=cut + +### error handling the way Archive::Extract does it +sub _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 WORKS + +File::Fetch is able to fetch a variety of uris, by using several +external programs and modules. + +Below is a mapping of what utilities will be used in what order +for what schemes, if available: + + file => LWP, lftp, file + http => LWP, HTTP::Lite, wget, curl, lftp, fetch, lynx, iosock + ftp => LWP, Net::FTP, wget, curl, lftp, fetch, ncftp, ftp + rsync => rsync + +If you'd like to disable the use of one or more of these utilities +and/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 be +tried again. The C method will only fail when all options are +exhausted, and it was not able to retrieve the file. + +The C utility is available on FreeBSD. NetBSD and Dragonfly BSD +may also have it from C. We only check for C on those +three platforms. + +C is a very limited L based mechanism for +retrieving C schemed urls. It doesn't follow redirects for instance. + +A special note about fetching files from an ftp uri: + +By default, all ftp connections are done in passive mode. To change +that, see the C<$FTP_PASSIVE> variable further down. + +Furthermore, ftp uris only support anonymous connections, so no +named user/password pair can be passed along. + +C is blacklisted by default; see the C<$BLACKLIST> variable +further down. + +=head1 GLOBAL VARIABLES + +The behaviour of File::Fetch can be altered by changing the following +global variables: + +=head2 $File::Fetch::FROM_EMAIL + +This is the email address that will be sent as your anonymous ftp +password. + +Default is C. + +=head2 $File::Fetch::USER_AGENT + +This is the useragent as C will report it. + +Default is C. + +=head2 $File::Fetch::FTP_PASSIVE + +This variable controls whether the environment variable C +and any passive switches to commandline tools will be set to true. + +Default value is 1. + +Note: When $FTP_PASSIVE is true, C will not be used to fetch +files, since passive mode can only be set interactively for this binary + +=head2 $File::Fetch::TIMEOUT + +When set, controls the network timeout (counted in seconds). + +Default value is 0. + +=head2 $File::Fetch::WARN + +This variable controls whether errors encountered internally by +C should be C'd or not. + +Set to false to silence warnings. Inspect the output of the C +method manually to see what went wrong. + +Defaults to C. + +=head2 $File::Fetch::DEBUG + +This enables debugging output when calling commandline utilities to +fetch files. +This also enables C errors, instead of the regular +C errors. + +Good for tracking down why things don't work with your particular +setup. + +Default is 0. + +=head2 $File::Fetch::BLACKLIST + +This is an array ref holding blacklisted modules/utilities for fetching +files with. + +To disallow the use of, for example, C and C, you could +set $File::Fetch::BLACKLIST to: + + $File::Fetch::BLACKLIST = [qw|lwp netftp|] + +The default blacklist is [qw|ftp|], as C is rather unreliable. + +See the note on C below. + +=head2 $File::Fetch::METHOD_FAIL + +This is a hashref registering what modules/utilities were known to fail +for fetching files (mostly because they weren't installed). + +You can reset this cache by assigning an empty hashref to it, or +individually remove keys. + +See the note on C below. + +=head1 MAPPING + + +Here's a quick mapping for the utilities/modules, and their names for +the $BLACKLIST, $METHOD_FAIL and other internal functions. + + LWP => lwp + HTTP::Lite => httplite + HTTP::Tiny => httptiny + Net::FTP => netftp + wget => wget + lynx => lynx + ncftp => ncftp + ftp => ftp + curl => curl + rsync => rsync + lftp => lftp + fetch => fetch + IO::Socket => iosock + +=head1 FREQUENTLY ASKED QUESTIONS + +=head2 So how do I use a proxy with File::Fetch? + +C currently only supports proxies with LWP::UserAgent. +You will need to set your environment variables accordingly. For +example, 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 can only fetch remote files by dumping its contents to C, +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 doesn't support any options to return a different exit +code on non-C<200 OK> status, giving us no way to tell the difference +between a 'successful' fetch and a custom error page. + +Therefor, we recommend to only use C 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 is relatively smart about things. When trying to write +a file to disk, it removes the C (see the +C method for details) from the file name before creating +it. In most cases this suffices. + +If you have any other characters you need to escape, please install +the C module from CPAN, and pre-encode your URI before +passing it to C. 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_BIN + +To indicate to rather use commandline tools than modules + +=back + +=head1 BUG REPORTS + +Please report bugs or other issues to Ebug-file-fetch@rt.cpan.org. + +=head1 AUTHOR + +This module by Jos Boumans Ekane@cpan.orgE. + +=head1 COPYRIGHT + +This 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: + + + + diff --git a/File-Fetch-0.38/blib/lib/auto/File/Fetch/.exists b/File-Fetch-0.38/blib/lib/auto/File/Fetch/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/blib/man1/.exists b/File-Fetch-0.38/blib/man1/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/blib/man3/.exists b/File-Fetch-0.38/blib/man3/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/blib/man3/File::Fetch.3pm b/File-Fetch-0.38/blib/man3/File::Fetch.3pm new file mode 100644 index 0000000..e13072f --- /dev/null +++ b/File-Fetch-0.38/blib/man3/File::Fetch.3pm @@ -0,0 +1,456 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.20) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "File::Fetch 3" +.TH File::Fetch 3 "2013-01-10" "perl v5.16.3" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +File::Fetch \- A generic file fetching mechanism +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& use File::Fetch; +\& +\& ### build a File::Fetch object ### +\& my $ff = File::Fetch\->new(uri => \*(Aqhttp://some.where.com/dir/a.txt\*(Aq); +\& +\& ### fetch the uri to cwd() ### +\& my $where = $ff\->fetch() or die $ff\->error; +\& +\& ### fetch the uri to /tmp ### +\& my $where = $ff\->fetch( to => \*(Aq/tmp\*(Aq ); +\& +\& ### parsed bits from the uri ### +\& $ff\->uri; +\& $ff\->scheme; +\& $ff\->host; +\& $ff\->path; +\& $ff\->file; +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +File::Fetch is a generic file fetching mechanism. +.PP +It allows you to fetch any file pointed to by a \f(CW\*(C`ftp\*(C'\fR, \f(CW\*(C`http\*(C'\fR, +\&\f(CW\*(C`file\*(C'\fR, or \f(CW\*(C`rsync\*(C'\fR uri by a number of different means. +.PP +See the \f(CW\*(C`HOW IT WORKS\*(C'\fR section further down for details. +.SH "ACCESSORS" +.IX Header "ACCESSORS" +A \f(CW\*(C`File::Fetch\*(C'\fR object has the following accessors +.ie n .IP "$ff\->uri" 4 +.el .IP "\f(CW$ff\fR\->uri" 4 +.IX Item "$ff->uri" +The uri you passed to the constructor +.ie n .IP "$ff\->scheme" 4 +.el .IP "\f(CW$ff\fR\->scheme" 4 +.IX Item "$ff->scheme" +The scheme from the uri (like 'file', 'http', etc) +.ie n .IP "$ff\->host" 4 +.el .IP "\f(CW$ff\fR\->host" 4 +.IX Item "$ff->host" +The hostname in the uri. Will be empty if host was originally +\&'localhost' for a 'file://' url. +.ie n .IP "$ff\->vol" 4 +.el .IP "\f(CW$ff\fR\->vol" 4 +.IX Item "$ff->vol" +On operating systems with the concept of a volume the second element +of a file:// is considered to the be volume specification for the file. +Thus on Win32 this routine returns the volume, on other operating +systems this returns nothing. +.Sp +On Windows this value may be empty if the uri is to a network share, in +which case the 'share' property will be defined. Additionally, volume +specifications that use '|' as ':' will be converted on read to use ':'. +.Sp +On \s-1VMS\s0, which has a volume concept, this field will be empty because \s-1VMS\s0 +file specifications are converted to absolute \s-1UNIX\s0 format and the volume +information is transparently included. +.ie n .IP "$ff\->share" 4 +.el .IP "\f(CW$ff\fR\->share" 4 +.IX Item "$ff->share" +On systems with the concept of a network share (currently only Windows) returns +the sharename from a file://// url. On other operating systems returns empty. +.ie n .IP "$ff\->path" 4 +.el .IP "\f(CW$ff\fR\->path" 4 +.IX Item "$ff->path" +The path from the uri, will be at least a single '/'. +.ie n .IP "$ff\->file" 4 +.el .IP "\f(CW$ff\fR\->file" 4 +.IX Item "$ff->file" +The name of the remote file. For the local file name, the +result of \f(CW$ff\fR\->output_file will be used. +.ie n .IP "$ff\->file_default" 4 +.el .IP "\f(CW$ff\fR\->file_default" 4 +.IX Item "$ff->file_default" +The name of the default local file, that \f(CW$ff\fR\->output_file falls back to if +it would otherwise return no filename. For example when fetching a \s-1URI\s0 like +http://www.abc.net.au/ the contents retrieved may be from a remote file called +\&'index.html'. The default value of this attribute is literally 'file_default'. +.ie n .IP "$ff\->output_file" 4 +.el .IP "\f(CW$ff\fR\->output_file" 4 +.IX Item "$ff->output_file" +The name of the output file. This is the same as \f(CW$ff\fR\->file, +but any query parameters are stripped off. For example: +.Sp +.Vb 1 +\& http://example.com/index.html?x=y +.Ve +.Sp +would make the output file be \f(CW\*(C`index.html\*(C'\fR rather than +\&\f(CW\*(C`index.html?x=y\*(C'\fR. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$ff = File::Fetch\->new( uri => 'http://some.where.com/dir/file.txt' );" +.el .SS "\f(CW$ff\fP = File::Fetch\->new( uri => 'http://some.where.com/dir/file.txt' );" +.IX Subsection "$ff = File::Fetch->new( uri => 'http://some.where.com/dir/file.txt' );" +Parses the uri and creates a corresponding File::Fetch::Item object, +that is ready to be \f(CW\*(C`fetch\*(C'\fRed and returns it. +.PP +Returns false on failure. +.ie n .SS "$where = $ff\->fetch( [to => /my/output/dir/ | \e$scalar] )" +.el .SS "\f(CW$where\fP = \f(CW$ff\fP\->fetch( [to => /my/output/dir/ | \e$scalar] )" +.IX Subsection "$where = $ff->fetch( [to => /my/output/dir/ | $scalar] )" +Fetches the file you requested and returns the full path to the file. +.PP +By default it writes to \f(CW\*(C`cwd()\*(C'\fR, but you can override that by specifying +the \f(CW\*(C`to\*(C'\fR argument: +.PP +.Vb 2 +\& ### file fetch to /tmp, full path to the file in $where +\& $where = $ff\->fetch( to => \*(Aq/tmp\*(Aq ); +\& +\& ### file slurped into $scalar, full path to the file in $where +\& ### file is downloaded to a temp directory and cleaned up at exit time +\& $where = $ff\->fetch( to => \e$scalar ); +.Ve +.PP +Returns the full path to the downloaded file on success, and false +on failure. +.ie n .SS "$ff\->error([\s-1BOOL\s0])" +.el .SS "\f(CW$ff\fP\->error([\s-1BOOL\s0])" +.IX Subsection "$ff->error([BOOL])" +Returns the last encountered error as string. +Pass it a true value to get the \f(CW\*(C`Carp::longmess()\*(C'\fR output instead. +.SH "HOW IT WORKS" +.IX Header "HOW IT WORKS" +File::Fetch is able to fetch a variety of uris, by using several +external programs and modules. +.PP +Below is a mapping of what utilities will be used in what order +for what schemes, if available: +.PP +.Vb 4 +\& file => LWP, lftp, file +\& http => LWP, HTTP::Lite, wget, curl, lftp, fetch, lynx, iosock +\& ftp => LWP, Net::FTP, wget, curl, lftp, fetch, ncftp, ftp +\& rsync => rsync +.Ve +.PP +If you'd like to disable the use of one or more of these utilities +and/or modules, see the \f(CW$BLACKLIST\fR variable further down. +.PP +If a utility or module isn't available, it will be marked in a cache +(see the \f(CW$METHOD_FAIL\fR variable further down), so it will not be +tried again. The \f(CW\*(C`fetch\*(C'\fR method will only fail when all options are +exhausted, and it was not able to retrieve the file. +.PP +The \f(CW\*(C`fetch\*(C'\fR utility is available on FreeBSD. NetBSD and Dragonfly \s-1BSD\s0 +may also have it from \f(CW\*(C`pkgsrc\*(C'\fR. We only check for \f(CW\*(C`fetch\*(C'\fR on those +three platforms. +.PP +\&\f(CW\*(C`iosock\*(C'\fR is a very limited IO::Socket::INET based mechanism for +retrieving \f(CW\*(C`http\*(C'\fR schemed urls. It doesn't follow redirects for instance. +.PP +A special note about fetching files from an ftp uri: +.PP +By default, all ftp connections are done in passive mode. To change +that, see the \f(CW$FTP_PASSIVE\fR variable further down. +.PP +Furthermore, ftp uris only support anonymous connections, so no +named user/password pair can be passed along. +.PP +\&\f(CW\*(C`/bin/ftp\*(C'\fR is blacklisted by default; see the \f(CW$BLACKLIST\fR variable +further down. +.SH "GLOBAL VARIABLES" +.IX Header "GLOBAL VARIABLES" +The behaviour of File::Fetch can be altered by changing the following +global variables: +.ie n .SS "$File::Fetch::FROM_EMAIL" +.el .SS "\f(CW$File::Fetch::FROM_EMAIL\fP" +.IX Subsection "$File::Fetch::FROM_EMAIL" +This is the email address that will be sent as your anonymous ftp +password. +.PP +Default is \f(CW\*(C`File\-Fetch@example.com\*(C'\fR. +.ie n .SS "$File::Fetch::USER_AGENT" +.el .SS "\f(CW$File::Fetch::USER_AGENT\fP" +.IX Subsection "$File::Fetch::USER_AGENT" +This is the useragent as \f(CW\*(C`LWP\*(C'\fR will report it. +.PP +Default is \f(CW\*(C`File::Fetch/$VERSION\*(C'\fR. +.ie n .SS "$File::Fetch::FTP_PASSIVE" +.el .SS "\f(CW$File::Fetch::FTP_PASSIVE\fP" +.IX Subsection "$File::Fetch::FTP_PASSIVE" +This variable controls whether the environment variable \f(CW\*(C`FTP_PASSIVE\*(C'\fR +and any passive switches to commandline tools will be set to true. +.PP +Default value is 1. +.PP +Note: When \f(CW$FTP_PASSIVE\fR is true, \f(CW\*(C`ncftp\*(C'\fR will not be used to fetch +files, since passive mode can only be set interactively for this binary +.ie n .SS "$File::Fetch::TIMEOUT" +.el .SS "\f(CW$File::Fetch::TIMEOUT\fP" +.IX Subsection "$File::Fetch::TIMEOUT" +When set, controls the network timeout (counted in seconds). +.PP +Default value is 0. +.ie n .SS "$File::Fetch::WARN" +.el .SS "\f(CW$File::Fetch::WARN\fP" +.IX Subsection "$File::Fetch::WARN" +This variable controls whether errors encountered internally by +\&\f(CW\*(C`File::Fetch\*(C'\fR should be \f(CW\*(C`carp\*(C'\fR'd or not. +.PP +Set to false to silence warnings. Inspect the output of the \f(CW\*(C`error()\*(C'\fR +method manually to see what went wrong. +.PP +Defaults to \f(CW\*(C`true\*(C'\fR. +.ie n .SS "$File::Fetch::DEBUG" +.el .SS "\f(CW$File::Fetch::DEBUG\fP" +.IX Subsection "$File::Fetch::DEBUG" +This enables debugging output when calling commandline utilities to +fetch files. +This also enables \f(CW\*(C`Carp::longmess\*(C'\fR errors, instead of the regular +\&\f(CW\*(C`carp\*(C'\fR errors. +.PP +Good for tracking down why things don't work with your particular +setup. +.PP +Default is 0. +.ie n .SS "$File::Fetch::BLACKLIST" +.el .SS "\f(CW$File::Fetch::BLACKLIST\fP" +.IX Subsection "$File::Fetch::BLACKLIST" +This is an array ref holding blacklisted modules/utilities for fetching +files with. +.PP +To disallow the use of, for example, \f(CW\*(C`LWP\*(C'\fR and \f(CW\*(C`Net::FTP\*(C'\fR, you could +set \f(CW$File::Fetch::BLACKLIST\fR to: +.PP +.Vb 1 +\& $File::Fetch::BLACKLIST = [qw|lwp netftp|] +.Ve +.PP +The default blacklist is [qw|ftp|], as \f(CW\*(C`/bin/ftp\*(C'\fR is rather unreliable. +.PP +See the note on \f(CW\*(C`MAPPING\*(C'\fR below. +.ie n .SS "$File::Fetch::METHOD_FAIL" +.el .SS "\f(CW$File::Fetch::METHOD_FAIL\fP" +.IX Subsection "$File::Fetch::METHOD_FAIL" +This is a hashref registering what modules/utilities were known to fail +for fetching files (mostly because they weren't installed). +.PP +You can reset this cache by assigning an empty hashref to it, or +individually remove keys. +.PP +See the note on \f(CW\*(C`MAPPING\*(C'\fR below. +.SH "MAPPING" +.IX Header "MAPPING" +Here's a quick mapping for the utilities/modules, and their names for +the \f(CW$BLACKLIST\fR, \f(CW$METHOD_FAIL\fR and other internal functions. +.PP +.Vb 10 +\& LWP => lwp +\& HTTP::Lite => httplite +\& HTTP::Tiny => httptiny +\& Net::FTP => netftp +\& wget => wget +\& lynx => lynx +\& ncftp => ncftp +\& ftp => ftp +\& curl => curl +\& rsync => rsync +\& lftp => lftp +\& fetch => fetch +\& IO::Socket => iosock +.Ve +.SH "FREQUENTLY ASKED QUESTIONS" +.IX Header "FREQUENTLY ASKED QUESTIONS" +.SS "So how do I use a proxy with File::Fetch?" +.IX Subsection "So how do I use a proxy with File::Fetch?" +\&\f(CW\*(C`File::Fetch\*(C'\fR currently only supports proxies with LWP::UserAgent. +You will need to set your environment variables accordingly. For +example, to use an ftp proxy: +.PP +.Vb 1 +\& $ENV{ftp_proxy} = \*(Aqfoo.com\*(Aq; +.Ve +.PP +Refer to the LWP::UserAgent manpage for more details. +.SS "I used 'lynx' to fetch a file, but its contents is all wrong!" +.IX Subsection "I used 'lynx' to fetch a file, but its contents is all wrong!" +\&\f(CW\*(C`lynx\*(C'\fR can only fetch remote files by dumping its contents to \f(CW\*(C`STDOUT\*(C'\fR, +which we in turn capture. If that content is a 'custom' error file +(like, say, a \f(CW\*(C`404 handler\*(C'\fR), you will get that contents instead. +.PP +Sadly, \f(CW\*(C`lynx\*(C'\fR doesn't support any options to return a different exit +code on non\-\f(CW\*(C`200 OK\*(C'\fR status, giving us no way to tell the difference +between a 'successful' fetch and a custom error page. +.PP +Therefor, we recommend to only use \f(CW\*(C`lynx\*(C'\fR as a last resort. This is +why it is at the back of our list of methods to try as well. +.SS "Files I'm trying to fetch have reserved characters or non-ASCII characters in them. What do I do?" +.IX Subsection "Files I'm trying to fetch have reserved characters or non-ASCII characters in them. What do I do?" +\&\f(CW\*(C`File::Fetch\*(C'\fR is relatively smart about things. When trying to write +a file to disk, it removes the \f(CW\*(C`query parameters\*(C'\fR (see the +\&\f(CW\*(C`output_file\*(C'\fR method for details) from the file name before creating +it. In most cases this suffices. +.PP +If you have any other characters you need to escape, please install +the \f(CW\*(C`URI::Escape\*(C'\fR module from \s-1CPAN\s0, and pre-encode your \s-1URI\s0 before +passing it to \f(CW\*(C`File::Fetch\*(C'\fR. You can read about the details of URIs +and \s-1URI\s0 encoding here: +.PP +.Vb 1 +\& http://www.faqs.org/rfcs/rfc2396.html +.Ve +.SH "TODO" +.IX Header "TODO" +.ie n .IP "Implement $PREFER_BIN" 4 +.el .IP "Implement \f(CW$PREFER_BIN\fR" 4 +.IX Item "Implement $PREFER_BIN" +To indicate to rather use commandline tools than modules +.SH "BUG REPORTS" +.IX Header "BUG REPORTS" +Please report bugs or other issues to . +.SH "AUTHOR" +.IX Header "AUTHOR" +This module by Jos Boumans . +.SH "COPYRIGHT" +.IX Header "COPYRIGHT" +This library is free software; you may redistribute and/or modify it +under the same terms as Perl itself. diff --git a/File-Fetch-0.38/blib/script/.exists b/File-Fetch-0.38/blib/script/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/debugfiles.list b/File-Fetch-0.38/debugfiles.list new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/debuglinks.list b/File-Fetch-0.38/debuglinks.list new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/debugsources.list b/File-Fetch-0.38/debugsources.list new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/lib/File/Fetch.pm b/File-Fetch-0.38/lib/File/Fetch.pm new file mode 100644 index 0000000..37f7bc6 --- /dev/null +++ b/File-Fetch-0.38/lib/File/Fetch.pm @@ -0,0 +1,1658 @@ +package File::Fetch; + +use strict; +use FileHandle; +use File::Temp; +use File::Copy; +use File::Spec; +use File::Spec::Unix; +use File::Basename qw[dirname]; + +use Cwd qw[cwd]; +use Carp qw[carp]; +use IPC::Cmd qw[can_run run QUOTE]; +use File::Path qw[mkpath]; +use File::Temp qw[tempdir]; +use Params::Check qw[check]; +use Module::Load::Conditional qw[can_load]; +use Locale::Maketext::Simple Style => 'gettext'; + +use vars qw[ $VERBOSE $PREFER_BIN $FROM_EMAIL $USER_AGENT + $BLACKLIST $METHOD_FAIL $VERSION $METHODS + $FTP_PASSIVE $TIMEOUT $DEBUG $WARN + ]; + +$VERSION = '0.38'; +$VERSION = eval $VERSION; # avoid warnings with development releases +$PREFER_BIN = 0; # XXX TODO implement +$FROM_EMAIL = 'File-Fetch@example.com'; +$USER_AGENT = "File::Fetch/$VERSION"; +$BLACKLIST = [qw|ftp|]; +$METHOD_FAIL = { }; +$FTP_PASSIVE = 1; +$TIMEOUT = 0; +$DEBUG = 0; +$WARN = 1; + +### methods available to fetch the file depending on the scheme +$METHODS = { + http => [ qw|lwp httptiny wget curl lftp fetch httplite lynx iosock| ], + ftp => [ qw|lwp netftp wget curl lftp fetch ncftp ftp| ], + file => [ qw|lwp lftp file| ], + rsync => [ qw|rsync| ] +}; + +### silly warnings ### +local $Params::Check::VERBOSE = 1; +local $Params::Check::VERBOSE = 1; +local $Module::Load::Conditional::VERBOSE = 0; +local $Module::Load::Conditional::VERBOSE = 0; + +### see what OS we are on, important for file:// uris ### +use constant ON_WIN => ($^O eq 'MSWin32'); +use constant ON_VMS => ($^O eq 'VMS'); +use constant ON_UNIX => (!ON_WIN); +use constant HAS_VOL => (ON_WIN); +use constant HAS_SHARE => (ON_WIN); +use constant HAS_FETCH => ( $^O =~ m!^(freebsd|netbsd|dragonfly)$! ); + +=pod + +=head1 NAME + +File::Fetch - A generic file fetching mechanism + +=head1 SYNOPSIS + + use File::Fetch; + + ### build a File::Fetch object ### + my $ff = File::Fetch->new(uri => 'http://some.where.com/dir/a.txt'); + + ### fetch the uri to cwd() ### + my $where = $ff->fetch() or die $ff->error; + + ### fetch the uri to /tmp ### + my $where = $ff->fetch( to => '/tmp' ); + + ### parsed bits from the uri ### + $ff->uri; + $ff->scheme; + $ff->host; + $ff->path; + $ff->file; + +=head1 DESCRIPTION + +File::Fetch is a generic file fetching mechanism. + +It allows you to fetch any file pointed to by a C, C, +C, or C uri by a number of different means. + +See the C section further down for details. + +=head1 ACCESSORS + +A C object has the following accessors + +=over 4 + +=item $ff->uri + +The uri you passed to the constructor + +=item $ff->scheme + +The scheme from the uri (like 'file', 'http', etc) + +=item $ff->host + +The hostname in the uri. Will be empty if host was originally +'localhost' for a 'file://' url. + +=item $ff->vol + +On operating systems with the concept of a volume the second element +of a file:// is considered to the be volume specification for the file. +Thus on Win32 this routine returns the volume, on other operating +systems this returns nothing. + +On Windows this value may be empty if the uri is to a network share, in +which case the 'share' property will be defined. Additionally, volume +specifications that use '|' as ':' will be converted on read to use ':'. + +On VMS, which has a volume concept, this field will be empty because VMS +file specifications are converted to absolute UNIX format and the volume +information is transparently included. + +=item $ff->share + +On systems with the concept of a network share (currently only Windows) returns +the sharename from a file://// url. On other operating systems returns empty. + +=item $ff->path + +The path from the uri, will be at least a single '/'. + +=item $ff->file + +The name of the remote file. For the local file name, the +result of $ff->output_file will be used. + +=item $ff->file_default + +The name of the default local file, that $ff->output_file falls back to if +it would otherwise return no filename. For example when fetching a URI like +http://www.abc.net.au/ the contents retrieved may be from a remote file called +'index.html'. The default value of this attribute is literally 'file_default'. + +=cut + + +########################## +### Object & Accessors ### +########################## + +{ + ### template for autogenerated accessors ### + my $Tmpl = { + scheme => { default => 'http' }, + host => { default => 'localhost' }, + path => { default => '/' }, + file => { required => 1 }, + uri => { required => 1 }, + vol => { default => '' }, # windows for file:// uris + share => { default => '' }, # windows for file:// uris + file_default => { default => 'file_default' }, + tempdir_root => { required => 1 }, # Should be lazy-set at ->new() + _error_msg => { no_override => 1 }, + _error_msg_long => { no_override => 1 }, + }; + + for my $method ( keys %$Tmpl ) { + no strict 'refs'; + *$method = sub { + my $self = shift; + $self->{$method} = $_[0] if @_; + return $self->{$method}; + } + } + + sub _create { + my $class = shift; + my %hash = @_; + + my $args = check( $Tmpl, \%hash ) or return; + + bless $args, $class; + + if( lc($args->scheme) ne 'file' and not $args->host ) { + return $class->_error(loc( + "Hostname required when fetching from '%1'",$args->scheme)); + } + + for (qw[path]) { + unless( $args->$_() ) { # 5.5.x needs the () + return $class->_error(loc("No '%1' specified",$_)); + } + } + + return $args; + } +} + +=item $ff->output_file + +The name of the output file. This is the same as $ff->file, +but any query parameters are stripped off. For example: + + http://example.com/index.html?x=y + +would make the output file be C rather than +C. + +=back + +=cut + +sub output_file { + my $self = shift; + my $file = $self->file; + + $file =~ s/\?.*$//g; + + $file ||= $self->file_default; + + return $file; +} + +### XXX do this or just point to URI::Escape? +# =head2 $esc_uri = $ff->escaped_uri +# +# =cut +# +# ### most of this is stolen straight from URI::escape +# { ### Build a char->hex map +# my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255; +# +# sub escaped_uri { +# my $self = shift; +# my $uri = $self->uri; +# +# ### Default unsafe characters. RFC 2732 ^(uric - reserved) +# $uri =~ s/([^A-Za-z0-9\-_.!~*'()])/ +# $escapes{$1} || $self->_fail_hi($1)/ge; +# +# return $uri; +# } +# +# sub _fail_hi { +# my $self = shift; +# my $char = shift; +# +# $self->_error(loc( +# "Can't escape '%1', try using the '%2' module instead", +# sprintf("\\x{%04X}", ord($char)), 'URI::Escape' +# )); +# } +# +# sub output_file { +# +# } +# +# +# } + +=head1 METHODS + +=head2 $ff = File::Fetch->new( uri => 'http://some.where.com/dir/file.txt' ); + +Parses the uri and creates a corresponding File::Fetch::Item object, +that is ready to be Ced and returns it. + +Returns false on failure. + +=cut + +sub new { + my $class = shift; + my %hash = @_; + + my ($uri, $file_default, $tempdir_root); + my $tmpl = { + uri => { required => 1, store => \$uri }, + file_default => { required => 0, store => \$file_default }, + tempdir_root => { required => 0, store => \$tempdir_root }, + }; + + check( $tmpl, \%hash ) or return; + + ### parse the uri to usable parts ### + my $href = $class->_parse_uri( $uri ) or return; + + $href->{file_default} = $file_default if $file_default; + $href->{tempdir_root} = File::Spec->rel2abs( $tempdir_root ) if $tempdir_root; + $href->{tempdir_root} = File::Spec->rel2abs( Cwd::cwd ) if not $href->{tempdir_root}; + + ### make it into a FFI object ### + my $ff = $class->_create( %$href ) or return; + + + ### return the object ### + return $ff; +} + +### parses an uri to a hash structure: +### +### $class->_parse_uri( 'ftp://ftp.cpan.org/pub/mirror/index.txt' ) +### +### becomes: +### +### $href = { +### scheme => 'ftp', +### host => 'ftp.cpan.org', +### path => '/pub/mirror', +### file => 'index.html' +### }; +### +### In the case of file:// urls there maybe be additional fields +### +### For systems with volume specifications such as Win32 there will be +### a volume specifier provided in the 'vol' field. +### +### 'vol' => 'volumename' +### +### For windows file shares there may be a 'share' key specified +### +### 'share' => 'sharename' +### +### Note that the rules of what a file:// url means vary by the operating system +### of the host being addressed. Thus file:///d|/foo/bar.txt means the obvious +### 'D:\foo\bar.txt' on windows, but on unix it means '/d|/foo/bar.txt' and +### not '/foo/bar.txt' +### +### Similarly if the host interpreting the url is VMS then +### file:///disk$user/my/notes/note12345.txt' means +### 'DISK$USER:[MY.NOTES]NOTE123456.TXT' but will be returned the same as +### if it is unix where it means /disk$user/my/notes/note12345.txt'. +### Except for some cases in the File::Spec methods, Perl on VMS will generally +### handle UNIX format file specifications. +### +### This means it is impossible to serve certain file:// urls on certain systems. +### +### Thus are the problems with a protocol-less specification. :-( +### + +sub _parse_uri { + my $self = shift; + my $uri = shift or return; + + my $href = { uri => $uri }; + + ### find the scheme ### + $uri =~ s|^(\w+)://||; + $href->{scheme} = $1; + + ### See rfc 1738 section 3.10 + ### http://www.faqs.org/rfcs/rfc1738.html + ### And wikipedia for more on windows file:// urls + ### http://en.wikipedia.org/wiki/File:// + if( $href->{scheme} eq 'file' ) { + + my @parts = split '/',$uri; + + ### file://hostname/... + ### file://hostname/... + ### normalize file://localhost with file:/// + $href->{host} = $parts[0] || ''; + + ### index in @parts where the path components begin; + my $index = 1; + + ### file:////hostname/sharename/blah.txt + if ( HAS_SHARE and not length $parts[0] and not length $parts[1] ) { + + $href->{host} = $parts[2] || ''; # avoid warnings + $href->{share} = $parts[3] || ''; # avoid warnings + + $index = 4 # index after the share + + ### file:///D|/blah.txt + ### file:///D:/blah.txt + } elsif (HAS_VOL) { + + ### this code comes from dmq's patch, but: + ### XXX if volume is empty, wouldn't that be an error? --kane + ### if so, our file://localhost test needs to be fixed as wel + $href->{vol} = $parts[1] || ''; + + ### correct D| style colume descriptors + $href->{vol} =~ s/\A([A-Z])\|\z/$1:/i if ON_WIN; + + $index = 2; # index after the volume + } + + ### rebuild the path from the leftover parts; + $href->{path} = join '/', '', splice( @parts, $index, $#parts ); + + } else { + ### using anything but qw() in hash slices may produce warnings + ### in older perls :-( + @{$href}{ qw(host path) } = $uri =~ m|([^/]*)(/.*)$|s; + } + + ### split the path into file + dir ### + { my @parts = File::Spec::Unix->splitpath( delete $href->{path} ); + $href->{path} = $parts[1]; + $href->{file} = $parts[2]; + } + + ### host will be empty if the target was 'localhost' and the + ### scheme was 'file' + $href->{host} = '' if ($href->{host} eq 'localhost') and + ($href->{scheme} eq 'file'); + + return $href; +} + +=head2 $where = $ff->fetch( [to => /my/output/dir/ | \$scalar] ) + +Fetches the file you requested and returns the full path to the file. + +By default it writes to C, but you can override that by specifying +the C argument: + + ### file fetch to /tmp, full path to the file in $where + $where = $ff->fetch( to => '/tmp' ); + + ### file slurped into $scalar, full path to the file in $where + ### file is downloaded to a temp directory and cleaned up at exit time + $where = $ff->fetch( to => \$scalar ); + +Returns the full path to the downloaded file on success, and false +on failure. + +=cut + +sub fetch { + my $self = shift or return; + my %hash = @_; + + my $target; + my $tmpl = { + to => { default => cwd(), store => \$target }, + }; + + check( $tmpl, \%hash ) or return; + + my ($to, $fh); + ### you want us to slurp the contents + if( ref $target and UNIVERSAL::isa( $target, 'SCALAR' ) ) { + $to = tempdir( 'FileFetch.XXXXXX', DIR => $self->tempdir_root, CLEANUP => 1 ); + + ### plain old fetch + } else { + $to = $target; + + ### On VMS force to VMS format so File::Spec will work. + $to = VMS::Filespec::vmspath($to) if ON_VMS; + + ### create the path if it doesn't exist yet ### + unless( -d $to ) { + eval { mkpath( $to ) }; + + return $self->_error(loc("Could not create path '%1'",$to)) if $@; + } + } + + ### set passive ftp if required ### + local $ENV{FTP_PASSIVE} = $FTP_PASSIVE; + + ### we dont use catfile on win32 because if we are using a cygwin tool + ### under cmd.exe they wont understand windows style separators. + my $out_to = ON_WIN ? $to.'/'.$self->output_file + : File::Spec->catfile( $to, $self->output_file ); + + for my $method ( @{ $METHODS->{$self->scheme} } ) { + my $sub = '_'.$method.'_fetch'; + + unless( __PACKAGE__->can($sub) ) { + $self->_error(loc("Cannot call method for '%1' -- WEIRD!", + $method)); + next; + } + + ### method is blacklisted ### + next if grep { lc $_ eq $method } @$BLACKLIST; + + ### method is known to fail ### + next if $METHOD_FAIL->{$method}; + + ### there's serious issues with IPC::Run and quoting of command + ### line arguments. using quotes in the wrong place breaks things, + ### and in the case of say, + ### C:\cygwin\bin\wget.EXE --quiet --passive-ftp --output-document + ### "index.html" "http://www.cpan.org/index.html?q=1&y=2" + ### it doesn't matter how you quote, it always fails. + local $IPC::Cmd::USE_IPC_RUN = 0; + + if( my $file = $self->$sub( + to => $out_to + )){ + + unless( -e $file && -s _ ) { + $self->_error(loc("'%1' said it fetched '%2', ". + "but it was not created",$method,$file)); + + ### mark the failure ### + $METHOD_FAIL->{$method} = 1; + + next; + + } else { + + ### slurp mode? + if( ref $target and UNIVERSAL::isa( $target, 'SCALAR' ) ) { + + ### open the file + open my $fh, "<$file" or do { + $self->_error( + loc("Could not open '%1': %2", $file, $!)); + return; + }; + + ### slurp + $$target = do { local $/; <$fh> }; + + } + + my $abs = File::Spec->rel2abs( $file ); + return $abs; + + } + } + } + + + ### if we got here, we looped over all methods, but we weren't able + ### to fetch it. + return; +} + +######################## +### _*_fetch methods ### +######################## + +### LWP fetching ### +sub _lwp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### modules required to download with lwp ### + my $use_list = { + LWP => '0.0', + 'LWP::UserAgent' => '0.0', + 'HTTP::Request' => '0.0', + 'HTTP::Status' => '0.0', + URI => '0.0', + + }; + + unless( can_load( modules => $use_list ) ) { + $METHOD_FAIL->{'lwp'} = 1; + return; + } + + ### setup the uri object + my $uri = URI->new( File::Spec::Unix->catfile( + $self->path, $self->file + ) ); + + ### special rules apply for file:// uris ### + $uri->scheme( $self->scheme ); + $uri->host( $self->scheme eq 'file' ? '' : $self->host ); + $uri->userinfo("anonymous:$FROM_EMAIL") if $self->scheme ne 'file'; + + ### set up the useragent object + my $ua = LWP::UserAgent->new(); + $ua->timeout( $TIMEOUT ) if $TIMEOUT; + $ua->agent( $USER_AGENT ); + $ua->from( $FROM_EMAIL ); + $ua->env_proxy; + + my $res = $ua->mirror($uri, $to) or return; + + ### uptodate or fetched ok ### + if ( $res->code == 304 or $res->code == 200 ) { + return $to; + + } else { + return $self->_error(loc("Fetch failed! HTTP response: %1 %2 [%3]", + $res->code, HTTP::Status::status_message($res->code), + $res->status_line)); + } + +} + +### HTTP::Tiny fetching ### +sub _httptiny_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $use_list = { + 'HTTP::Tiny' => '0.008', + + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'httptiny'} = 1; + return; + } + + my $uri = $self->uri; + + my $http = HTTP::Tiny->new( ( $TIMEOUT ? ( timeout => $TIMEOUT ) : () ) ); + + my $rc = $http->mirror( $uri, $to ); + + unless ( $rc->{success} ) { + + return $self->_error(loc( "Fetch failed! HTTP response: %1 [%2]", + $rc->{status}, $rc->{reason} ) ); + + } + + return $to; + +} + +### HTTP::Lite fetching ### +sub _httplite_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### modules required to download with lwp ### + my $use_list = { + 'HTTP::Lite' => '2.2', + + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'httplite'} = 1; + return; + } + + my $uri = $self->uri; + my $retries = 0; + + RETRIES: while ( $retries++ < 5 ) { + + my $http = HTTP::Lite->new(); + # Naughty naughty but there isn't any accessor/setter + $http->{timeout} = $TIMEOUT if $TIMEOUT; + $http->http11_mode(1); + + my $fh = FileHandle->new; + + unless ( $fh->open($to,'>') ) { + return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + } + + $fh->autoflush(1); + + binmode $fh; + + my $rc = $http->request( $uri, sub { my ($self,$dref,$cbargs) = @_; local $\; print {$cbargs} $$dref }, $fh ); + + close $fh; + + if ( $rc == 301 || $rc == 302 ) { + my $loc; + HEADERS: for ($http->headers_array) { + /Location: (\S+)/ and $loc = $1, last HEADERS; + } + #$loc or last; # Think we should squeal here. + if ($loc =~ m!^/!) { + $uri =~ s{^(\w+?://[^/]+)/.*$}{$1}; + $uri .= $loc; + } + else { + $uri = $loc; + } + next RETRIES; + } + elsif ( $rc == 200 ) { + return $to; + } + else { + return $self->_error(loc("Fetch failed! HTTP response: %1 [%2]", + $rc, $http->status_message)); + } + + } # Loop for 5 retries. + + return $self->_error("Fetch failed! Gave up after 5 tries"); + +} + +### Simple IO::Socket::INET fetching ### +sub _iosock_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $use_list = { + 'IO::Socket::INET' => '0.0', + 'IO::Select' => '0.0', + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'iosock'} = 1; + return; + } + + my $sock = IO::Socket::INET->new( + PeerHost => $self->host, + ( $self->host =~ /:/ ? () : ( PeerPort => 80 ) ), + ); + + unless ( $sock ) { + return $self->_error(loc("Could not open socket to '%1', '%2'",$self->host,$!)); + } + + my $fh = FileHandle->new; + + # Check open() + + unless ( $fh->open($to,'>') ) { + return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + } + + $fh->autoflush(1); + binmode $fh; + + my $path = File::Spec::Unix->catfile( $self->path, $self->file ); + my $req = "GET $path HTTP/1.0\x0d\x0aHost: " . $self->host . "\x0d\x0a\x0d\x0a"; + $sock->send( $req ); + + my $select = IO::Select->new( $sock ); + + my $resp = ''; + my $normal = 0; + while ( $select->can_read( $TIMEOUT || 60 ) ) { + my $ret = $sock->sysread( $resp, 4096, length($resp) ); + if ( !defined $ret or $ret == 0 ) { + $select->remove( $sock ); + $normal++; + } + } + close $sock; + + unless ( $normal ) { + return $self->_error(loc("Socket timed out after '%1' seconds", ( $TIMEOUT || 60 ))); + } + + # Check the "response" + # Strip preceding blank lines apparently they are allowed (RFC 2616 4.1) + $resp =~ s/^(\x0d?\x0a)+//; + # Check it is an HTTP response + unless ( $resp =~ m!^HTTP/(\d+)\.(\d+)!i ) { + return $self->_error(loc("Did not get a HTTP response from '%1'",$self->host)); + } + + # Check for OK + my ($code) = $resp =~ m!^HTTP/\d+\.\d+\s+(\d+)!i; + unless ( $code eq '200' ) { + return $self->_error(loc("Got a '%1' from '%2' expected '200'",$code,$self->host)); + } + + { + local $\; + print $fh +($resp =~ m/\x0d\x0a\x0d\x0a(.*)$/s )[0]; + } + close $fh; + return $to; +} + +### Net::FTP fetching +sub _netftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### required modules ### + my $use_list = { 'Net::FTP' => 0 }; + + unless( can_load( modules => $use_list ) ) { + $METHOD_FAIL->{'netftp'} = 1; + return; + } + + ### make connection ### + my $ftp; + my @options = ($self->host); + push(@options, Timeout => $TIMEOUT) if $TIMEOUT; + unless( $ftp = Net::FTP->new( @options ) ) { + return $self->_error(loc("Ftp creation failed: %1",$@)); + } + + ### login ### + unless( $ftp->login( anonymous => $FROM_EMAIL ) ) { + return $self->_error(loc("Could not login to '%1'",$self->host)); + } + + ### set binary mode, just in case ### + $ftp->binary; + + ### create the remote path + ### remember remote paths are unix paths! [#11483] + my $remote = File::Spec::Unix->catfile( $self->path, $self->file ); + + ### fetch the file ### + my $target; + unless( $target = $ftp->get( $remote, $to ) ) { + return $self->_error(loc("Could not fetch '%1' from '%2'", + $remote, $self->host)); + } + + ### log out ### + $ftp->quit; + + return $target; + +} + +### /bin/wget fetch ### +sub _wget_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $wget; + ### see if we have a wget binary ### + unless( $wget = can_run('wget') ) { + $METHOD_FAIL->{'wget'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $wget, '--quiet' ]; + + ### if a timeout is set, add it ### + push(@$cmd, '--timeout=' . $TIMEOUT) if $TIMEOUT; + + ### run passive if specified ### + push @$cmd, '--passive-ftp' if $FTP_PASSIVE; + + ### set the output document, add the uri ### + push @$cmd, '--output-document', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + +### /bin/lftp fetch ### +sub _lftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a lftp binary ### + my $lftp; + unless( $lftp = can_run('lftp') ) { + $METHOD_FAIL->{'lftp'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $lftp, '-f' ]; + + my $fh = File::Temp->new; + + my $str; + + ### if a timeout is set, add it ### + $str .= "set net:timeout $TIMEOUT;\n" if $TIMEOUT; + + ### run passive if specified ### + $str .= "set ftp:passive-mode 1;\n" if $FTP_PASSIVE; + + ### set the output document, add the uri ### + ### quote the URI, because lftp supports certain shell + ### expansions, most notably & for backgrounding. + ### ' quote does nto work, must be " + $str .= q[get ']. $self->uri .q[' -o ]. $to . $/; + + if( $DEBUG ) { + my $pp_str = join ' ', split $/, $str; + print "# lftp command: $pp_str\n"; + } + + ### write straight to the file. + $fh->autoflush(1); + print $fh $str; + + ### the command needs to be 1 string to be executed + push @$cmd, $fh->filename; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + + + +### /bin/ftp fetch ### +sub _ftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a ftp binary ### + my $ftp; + unless( $ftp = can_run('ftp') ) { + $METHOD_FAIL->{'ftp'} = 1; + return; + } + + my $fh = FileHandle->new; + + local $SIG{CHLD} = 'IGNORE'; + + unless ($fh->open("$ftp -n", '|-')) { + return $self->_error(loc("%1 creation failed: %2", $ftp, $!)); + } + + my @dialog = ( + "lcd " . dirname($to), + "open " . $self->host, + "user anonymous $FROM_EMAIL", + "cd /", + "cd " . $self->path, + "binary", + "get " . $self->file . " " . $self->output_file, + "quit", + ); + + foreach (@dialog) { $fh->print($_, "\n") } + $fh->close or return; + + return $to; +} + +### lynx is stupid - it decompresses any .gz file it finds to be text +### use /bin/lynx to fetch files +sub _lynx_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a lynx binary ### + my $lynx; + unless ( $lynx = can_run('lynx') ){ + $METHOD_FAIL->{'lynx'} = 1; + return; + } + + unless( IPC::Cmd->can_capture_buffer ) { + $METHOD_FAIL->{'lynx'} = 1; + + return $self->_error(loc( + "Can not capture buffers. Can not use '%1' to fetch files", + 'lynx' )); + } + + ### check if the HTTP resource exists ### + if ($self->uri =~ /^https?:\/\//i) { + my $cmd = [ + $lynx, + '-head', + '-source', + "-auth=anonymous:$FROM_EMAIL", + ]; + + push @$cmd, "-connect_timeout=$TIMEOUT" if $TIMEOUT; + + push @$cmd, $self->uri; + + ### shell out ### + my $head; + unless(run( command => $cmd, + buffer => \$head, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $head || '')); + } + + unless($head =~ /^HTTP\/\d+\.\d+ 200\b/) { + return $self->_error(loc("Command failed: %1", $head || '')); + } + } + + ### write to the output file ourselves, since lynx ass_u_mes to much + my $local = FileHandle->new( $to, 'w' ) + or return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + + ### dump to stdout ### + my $cmd = [ + $lynx, + '-source', + "-auth=anonymous:$FROM_EMAIL", + ]; + + push @$cmd, "-connect_timeout=$TIMEOUT" if $TIMEOUT; + + ### DO NOT quote things for IPC::Run, it breaks stuff. + push @$cmd, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### DO NOT quote things for IPC::Run, it breaks stuff. + # $IPC::Cmd::USE_IPC_RUN + # ? $self->uri + # : QUOTE. $self->uri .QUOTE; + + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $captured || '')); + } + + ### print to local file ### + ### XXX on a 404 with a special error page, $captured will actually + ### hold the contents of that page, and make it *appear* like the + ### request was a success, when really it wasn't :( + ### there doesn't seem to be an option for lynx to change the exit + ### code based on a 4XX status or so. + ### the closest we can come is using --error_file and parsing that, + ### which is very unreliable ;( + $local->print( $captured ); + $local->close or return; + + return $to; +} + +### use /bin/ncftp to fetch files +sub _ncftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### we can only set passive mode in interactive sessions, so bail out + ### if $FTP_PASSIVE is set + return if $FTP_PASSIVE; + + ### see if we have a ncftp binary ### + my $ncftp; + unless( $ncftp = can_run('ncftp') ) { + $METHOD_FAIL->{'ncftp'} = 1; + return; + } + + my $cmd = [ + $ncftp, + '-V', # do not be verbose + '-p', $FROM_EMAIL, # email as password + $self->host, # hostname + dirname($to), # local dir for the file + # remote path to the file + ### DO NOT quote things for IPC::Run, it breaks stuff. + $IPC::Cmd::USE_IPC_RUN + ? File::Spec::Unix->catdir( $self->path, $self->file ) + : QUOTE. File::Spec::Unix->catdir( + $self->path, $self->file ) .QUOTE + + ]; + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $captured || '')); + } + + return $to; + +} + +### use /bin/curl to fetch files +sub _curl_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $curl; + unless ( $curl = can_run('curl') ) { + $METHOD_FAIL->{'curl'} = 1; + return; + } + + ### these long opts are self explanatory - I like that -jmb + my $cmd = [ $curl, '-q' ]; + + 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', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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; + +} + +### /usr/bin/fetch fetch! ### +sub _fetch_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a fetch binary ### + my $fetch; + unless( HAS_FETCH and $fetch = can_run('fetch') ) { + $METHOD_FAIL->{'fetch'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $fetch, '-q' ]; + + ### if a timeout is set, add it ### + push(@$cmd, '-T', $TIMEOUT) if $TIMEOUT; + + ### run passive if specified ### + #push @$cmd, '-p' if $FTP_PASSIVE; + local $ENV{'FTP_PASSIVE_MODE'} = 1 if $FTP_PASSIVE; + + ### set the output document, add the uri ### + push @$cmd, '-o', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + +### 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 + ### whereas 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 files +sub _rsync_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $rsync; + unless ( $rsync = can_run('rsync') ) { + $METHOD_FAIL->{'rsync'} = 1; + return; + } + + 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, $self->uri, $to; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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 %1 failed: %2", + "@$cmd" || '', $captured || '')); + } + + return $to; + +} + +################################# +# +# Error code +# +################################# + +=pod + +=head2 $ff->error([BOOL]) + +Returns the last encountered error as string. +Pass it a true value to get the C output instead. + +=cut + +### error handling the way Archive::Extract does it +sub _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 WORKS + +File::Fetch is able to fetch a variety of uris, by using several +external programs and modules. + +Below is a mapping of what utilities will be used in what order +for what schemes, if available: + + file => LWP, lftp, file + http => LWP, HTTP::Lite, wget, curl, lftp, fetch, lynx, iosock + ftp => LWP, Net::FTP, wget, curl, lftp, fetch, ncftp, ftp + rsync => rsync + +If you'd like to disable the use of one or more of these utilities +and/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 be +tried again. The C method will only fail when all options are +exhausted, and it was not able to retrieve the file. + +The C utility is available on FreeBSD. NetBSD and Dragonfly BSD +may also have it from C. We only check for C on those +three platforms. + +C is a very limited L based mechanism for +retrieving C schemed urls. It doesn't follow redirects for instance. + +A special note about fetching files from an ftp uri: + +By default, all ftp connections are done in passive mode. To change +that, see the C<$FTP_PASSIVE> variable further down. + +Furthermore, ftp uris only support anonymous connections, so no +named user/password pair can be passed along. + +C is blacklisted by default; see the C<$BLACKLIST> variable +further down. + +=head1 GLOBAL VARIABLES + +The behaviour of File::Fetch can be altered by changing the following +global variables: + +=head2 $File::Fetch::FROM_EMAIL + +This is the email address that will be sent as your anonymous ftp +password. + +Default is C. + +=head2 $File::Fetch::USER_AGENT + +This is the useragent as C will report it. + +Default is C. + +=head2 $File::Fetch::FTP_PASSIVE + +This variable controls whether the environment variable C +and any passive switches to commandline tools will be set to true. + +Default value is 1. + +Note: When $FTP_PASSIVE is true, C will not be used to fetch +files, since passive mode can only be set interactively for this binary + +=head2 $File::Fetch::TIMEOUT + +When set, controls the network timeout (counted in seconds). + +Default value is 0. + +=head2 $File::Fetch::WARN + +This variable controls whether errors encountered internally by +C should be C'd or not. + +Set to false to silence warnings. Inspect the output of the C +method manually to see what went wrong. + +Defaults to C. + +=head2 $File::Fetch::DEBUG + +This enables debugging output when calling commandline utilities to +fetch files. +This also enables C errors, instead of the regular +C errors. + +Good for tracking down why things don't work with your particular +setup. + +Default is 0. + +=head2 $File::Fetch::BLACKLIST + +This is an array ref holding blacklisted modules/utilities for fetching +files with. + +To disallow the use of, for example, C and C, you could +set $File::Fetch::BLACKLIST to: + + $File::Fetch::BLACKLIST = [qw|lwp netftp|] + +The default blacklist is [qw|ftp|], as C is rather unreliable. + +See the note on C below. + +=head2 $File::Fetch::METHOD_FAIL + +This is a hashref registering what modules/utilities were known to fail +for fetching files (mostly because they weren't installed). + +You can reset this cache by assigning an empty hashref to it, or +individually remove keys. + +See the note on C below. + +=head1 MAPPING + + +Here's a quick mapping for the utilities/modules, and their names for +the $BLACKLIST, $METHOD_FAIL and other internal functions. + + LWP => lwp + HTTP::Lite => httplite + HTTP::Tiny => httptiny + Net::FTP => netftp + wget => wget + lynx => lynx + ncftp => ncftp + ftp => ftp + curl => curl + rsync => rsync + lftp => lftp + fetch => fetch + IO::Socket => iosock + +=head1 FREQUENTLY ASKED QUESTIONS + +=head2 So how do I use a proxy with File::Fetch? + +C currently only supports proxies with LWP::UserAgent. +You will need to set your environment variables accordingly. For +example, 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 can only fetch remote files by dumping its contents to C, +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 doesn't support any options to return a different exit +code on non-C<200 OK> status, giving us no way to tell the difference +between a 'successful' fetch and a custom error page. + +Therefor, we recommend to only use C 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 is relatively smart about things. When trying to write +a file to disk, it removes the C (see the +C method for details) from the file name before creating +it. In most cases this suffices. + +If you have any other characters you need to escape, please install +the C module from CPAN, and pre-encode your URI before +passing it to C. 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_BIN + +To indicate to rather use commandline tools than modules + +=back + +=head1 BUG REPORTS + +Please report bugs or other issues to Ebug-file-fetch@rt.cpan.org. + +=head1 AUTHOR + +This module by Jos Boumans Ekane@cpan.orgE. + +=head1 COPYRIGHT + +This 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: + + + + diff --git a/File-Fetch-0.38/pm_to_blib b/File-Fetch-0.38/pm_to_blib new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.38/t/01_File-Fetch.t b/File-Fetch-0.38/t/01_File-Fetch.t new file mode 100644 index 0000000..538c55e --- /dev/null +++ b/File-Fetch-0.38/t/01_File-Fetch.t @@ -0,0 +1,281 @@ +BEGIN { chdir 't' if -d 't' }; + +use strict; +use lib '../lib'; + +use Test::More 'no_plan'; + +use Cwd qw[cwd]; +use File::Basename qw[basename]; +use Data::Dumper; + +use_ok('File::Fetch'); + +### optionally set debugging ### +$File::Fetch::DEBUG = $File::Fetch::DEBUG = 1 if $ARGV[0]; +$IPC::Cmd::DEBUG = $IPC::Cmd::DEBUG = 1 if $ARGV[0]; + +unless( $ENV{PERL_CORE} ) { + warn qq[ + +####################### NOTE ############################## + +Some of these tests assume you are connected to the +internet. If you are not, or if certain protocols or hosts +are blocked and/or firewalled, these tests could fail due +to no fault of the module itself. + +########################################################### + +]; + + sleep 3 unless $File::Fetch::DEBUG; +} + +### show us the tools IPC::Cmd will use to run binary programs +if( $File::Fetch::DEBUG ) { + ### stupid 'used only once' warnings ;( + diag( "IPC::Run enabled: " . + $IPC::Cmd::USE_IPC_RUN || $IPC::Cmd::USE_IPC_RUN ); + diag( "IPC::Run available: " . IPC::Cmd->can_use_ipc_run ); + diag( "IPC::Run vesion: $IPC::Run::VERSION" ); + diag( "IPC::Open3 enabled: " . + $IPC::Cmd::USE_IPC_OPEN3 || $IPC::Cmd::USE_IPC_OPEN3 ); + diag( "IPC::Open3 available: " . IPC::Cmd->can_use_ipc_open3 ); + diag( "IPC::Open3 vesion: $IPC::Open3::VERSION" ); +} + +### Heuristics +my %heuristics = map { $_ => 1 } qw(http ftp rsync file); +### _parse_uri tests +### these go on all platforms +my @map = ( + { uri => 'ftp://cpan.org/pub/mirror/index.txt', + scheme => 'ftp', + host => 'cpan.org', + path => '/pub/mirror/', + file => 'index.txt' + }, + { uri => 'rsync://cpan.pair.com/CPAN/MIRRORING.FROM', + scheme => 'rsync', + host => 'cpan.pair.com', + path => '/CPAN/', + file => 'MIRRORING.FROM', + }, + { uri => 'http://localhost/tmp/index.txt', + scheme => 'http', + host => 'localhost', # host is empty only on 'file://' + path => '/tmp/', + file => 'index.txt', + }, + + ### only test host part, the rest is OS dependant + { uri => 'file://localhost/tmp/index.txt', + host => '', # host should be empty on 'file://' + }, +); + +### these only if we're not on win32/vms +push @map, ( + { uri => 'file:///usr/local/tmp/foo.txt', + scheme => 'file', + host => '', + path => '/usr/local/tmp/', + file => 'foo.txt', + }, + { uri => 'file://hostname/tmp/foo.txt', + scheme => 'file', + host => 'hostname', + path => '/tmp/', + file => 'foo.txt', + }, +) if not &File::Fetch::ON_WIN and not &File::Fetch::ON_VMS; + +### these only on win32 +push @map, ( + { uri => 'file:////hostname/share/tmp/foo.txt', + scheme => 'file', + host => 'hostname', + share => 'share', + path => '/tmp/', + file => 'foo.txt', + }, + { uri => 'file:///D:/tmp/foo.txt', + scheme => 'file', + host => '', + vol => 'D:', + path => '/tmp/', + file => 'foo.txt', + }, + { uri => 'file:///D|/tmp/foo.txt', + scheme => 'file', + host => '', + vol => 'D:', + path => '/tmp/', + file => 'foo.txt', + }, +) if &File::Fetch::ON_WIN; + + +### sanity tests +{ + no warnings; + like( $File::Fetch::USER_AGENT, qr/$File::Fetch::VERSION/, + "User agent contains version" ); + like( $File::Fetch::FROM_EMAIL, qr/@/, + q[Email contains '@'] ); +} + +### parse uri tests ### +for my $entry (@map ) { + my $uri = $entry->{'uri'}; + + my $href = File::Fetch->_parse_uri( $uri ); + ok( $href, "Able to parse uri '$uri'" ); + + for my $key ( sort keys %$entry ) { + is( $href->{$key}, $entry->{$key}, + " '$key' ok ($entry->{$key}) for $uri"); + } +} + +### File::Fetch->new tests ### +for my $entry (@map) { + my $ff = File::Fetch->new( uri => $entry->{uri} ); + + ok( $ff, "Object for uri '$entry->{uri}'" ); + isa_ok( $ff, "File::Fetch", " Object" ); + + for my $acc ( keys %$entry ) { + is( $ff->$acc(), $entry->{$acc}, + " Accessor '$acc' ok ($entry->{$acc})" ); + } +} + +### fetch() tests ### + +### file:// tests ### +{ + my $prefix = &File::Fetch::ON_UNIX ? 'file://' : 'file:///'; + my $uri = $prefix . cwd() .'/'. basename($0); + + for (qw[lwp lftp file]) { + _fetch_uri( file => $uri, $_ ); + } +} + +### Heuristics +{ + require IO::Socket::INET; + my $sock = IO::Socket::INET->new( PeerAddr => 'ftp.funet.fi', PeerPort => 21, Timeout => 20 ) + or $heuristics{ftp} = 0; +} + +### ftp:// tests ### +{ my $uri = 'ftp://ftp.funet.fi/pub/CPAN/index.html'; + for (qw[lwp netftp wget curl lftp fetch ncftp]) { + + ### STUPID STUPID warnings ### + next if $_ eq 'ncftp' and $File::Fetch::FTP_PASSIVE + and $File::Fetch::FTP_PASSIVE; + + _fetch_uri( ftp => $uri, $_ ); + } +} + +### Heuristics +{ + require IO::Socket::INET; + my $sock = IO::Socket::INET->new( PeerAddr => 'www.cpan.org', PeerPort => 80, Timeout => 20 ) + or $heuristics{http} = 0; +} + +### http:// tests ### +{ for my $uri ( 'http://www.cpan.org/index.html', + 'http://www.cpan.org/index.html?q=1', + 'http://www.cpan.org/index.html?q=1&y=2', + ) { + for (qw[lwp httptiny wget curl lftp fetch lynx httplite iosock]) { + _fetch_uri( http => $uri, $_ ); + } + } +} + +### Heuristics +{ + require IO::Socket::INET; + my $sock = IO::Socket::INET->new( PeerAddr => 'cpan.pair.com', PeerPort => 873, Timeout => 20 ) + or $heuristics{rsync} = 0; +} + +### rsync:// tests ### +{ my $uri = 'rsync://cpan.pair.com/CPAN/MIRRORING.FROM'; + + for (qw[rsync]) { + _fetch_uri( rsync => $uri, $_ ); + } +} + +sub _fetch_uri { + my $type = shift; + my $uri = shift; + my $method = shift or return; + + SKIP: { + skip "'$method' fetching tests disabled under perl core", 4 + if $ENV{PERL_CORE}; + + skip "'$type' fetching tests disabled due to heuristic failure", 4 + unless $heuristics{ $type }; + + ### stupid warnings ### + $File::Fetch::METHODS = + $File::Fetch::METHODS = { $type => [$method] }; + + ### fetch regularly + my $ff = File::Fetch->new( uri => $uri ); + + ok( $ff, "FF object for $uri (fetch with $method)" ); + + for my $to ( 'tmp', do { \my $o } ) { SKIP: { + + + my $how = ref $to ? 'slurp' : 'file'; + my $skip = ref $to ? 4 : 3; + + ok( 1, " Fetching '$uri' in $how mode" ); + + my $file = $ff->fetch( to => $to ); + + skip "You do not have '$method' installed/available", $skip + if $File::Fetch::METHOD_FAIL->{$method} && + $File::Fetch::METHOD_FAIL->{$method}; + + ### if the file wasn't fetched, it may be a network/firewall issue + skip "Fetch failed; no network connectivity for '$type'?", $skip + unless $file; + + ok( $file, " File ($file) fetched with $method ($uri)" ); + + ### check we got some contents if we were meant to slurp + if( ref $to ) { + ok( $$to, " Contents slurped" ); + } + + ok( $file && -s $file, + " File has size" ); + is( $file && basename($file), $ff->output_file, + " File has expected name" ); + + unlink $file; + }} + } +} + + + + + + + + diff --git a/File-Fetch-0.38/t/null_subclass.t b/File-Fetch-0.38/t/null_subclass.t new file mode 100644 index 0000000..630a607 --- /dev/null +++ b/File-Fetch-0.38/t/null_subclass.t @@ -0,0 +1,23 @@ +use strict; +use warnings; + +use Test::More tests => 5; + +my $parent_class = 'File::Fetch'; +my $child_class = 'File::Fetch::Subclass'; + +use_ok( $parent_class ); + +my $ff_parent = $parent_class->new( uri => 'http://example.com/index.html' ); +isa_ok( $ff_parent, $parent_class ); + +can_ok( $child_class, qw( new fetch ) ); +my $ff_child = $child_class->new( uri => 'http://example.com/index.html' ); +isa_ok( $ff_child, $child_class ); +isa_ok( $ff_child, $parent_class ); + +BEGIN { + package File::Fetch::Subclass; + use vars qw(@ISA); + unshift @ISA, qw(File::Fetch); + } diff --git a/File-Fetch-0.42/CHANGES b/File-Fetch-0.42/CHANGES new file mode 100644 index 0000000..ce25b36 --- /dev/null +++ b/File-Fetch-0.42/CHANGES @@ -0,0 +1,222 @@ +Changes for 0.42 Fri Apr 12 15:28:34 2013 +================================================= +* Skip slurp tests for git:// + +Changes for 0.40 Fri Apr 12 11:18:52 2013 +================================================= +* Added git:// url support + +Changes for 0.38 Thu Jan 10 20:52:53 2013 +================================================= +* Add support for an optional tempdir_root + parameter (Kent Fredric) + +Changes for 0.36 Thu Jun 28 13:41:31 2012 +================================================= +* Added 'file_default' option for URLs that do + not have a file component (Andrew Kirkpatrick) + +Changes for 0.34 Thu Apr 12 22:25:01 2012 +================================================= +* Added heuristics to skip tests when no + Internet access + +Changes for 0.32 Mon Jan 17 10:26:40 2011 +================================================= +* Added support for HTTP::Tiny + +Changes for 0.30 Fri Jan 7 21:00:27 2011 +================================================= +* Apply blead patches from Peter Acklam + +Changes for 0.28 Sun Nov 7 21:22:26 2010 +================================================= +* Added support for FreeBSDs 'fetch' command for + both http and ftp schemes. + +Changes for 0.26 Sat Nov 6 23:30:59 2010 +================================================= +* Added support for HTTP::Lite +* Resolved issue with '-l' switch and iosock fetch + +Changes for 0.24 Wed Jan 6 23:32:19 2010 +================================================= +* Applied a patch from brian d foy RT #53427 + that makes new() respect sub-classes. + +Changes for 0.22 Sat Nov 14 23:13:16 2009 +================================================= +* Bumped to stable version + +Changes for 0.21_02 Thu Nov 12 12:55:57 2009 +================================================= +* Additional checks for the iosock retriever + +Changes for 0.21_01 Wed Nov 11 23:38:27 2009 +================================================= +* Added a simple IO::Socket/IO::Select based http retriever, + based on code suggested by Paul 'Leonerd' Evans + +Changes for 0.20 Sat Jun 27 16:30:59 2009 +================================================= +* Promote 0.19_01 to stable + +Changes for 0.19_01 Mon Feb 9 18:04:01 2009 +================================================= +* Address: #42268: Wishlist: slurp to scalar + File::Fetch can now fetch to scalars as well + +Changes for 0.18 Wed Dec 17 14:00:40 2008 +================================================= +* Address #41412: User agent string contains uninterpolated + $VERSION. +* Use IPC::Cmd 0.42's supplied QUOTE constant, rather than + rolling our own + +Changes for 0.16 Fri Oct 10 13:54:40 2008 +================================================= +* Promote 0.15_04 to stable. + +Changes for 0.15_04 Mon Sep 22 15:08:49 2008 +================================================= +* Address: #37649: Feature request: Support lftp + File::Fetch now supports lftp, with one minor caveat: it uses + a temporary file to store the commands for lftp, as they are + multiline commands. Without this, we run into portability issues + with 'special' characters on various platforms, like ; and &. + +Changes for 0.15_03 Sun Jul 13 15:56:41 2008 +================================================= +* Add -q to curl, to inhibit the reading of .curlrc, + which may interfere with the options we pass ourselves. + This addresses #36902 + +Changes for 0.15_02 Sun May 18 13:42:30 2008 +================================================= +* Address #35018: Treat HTTP 404 Message as fail with lynx + lynx now does a -head request first to make sure the file + exists before proceeding + +Changes for 0.15_01 Sun Apr 6 13:55:36 2008 +================================================= +* Address: #32755: File-Fetch tests cannot fail if + unable to connect to internet. Tests are now skipped + if it looks as the failure is due to a lacking network + connection. +* New IPC::Cmd (0.41) fixes an IPC::Open3 bug, which we + now rely on. + +Changes for 0.14 Fri Dec 14 13:42:30 2007 +================================================= +* Promote 0.13_04 to stable. + +Changes for 0.13_04 Wed Nov 14 20:07:02 2007 +================================================= +* VMS patches for file:// uris by John M. + +Changes for 0.13_03 2007-11-04 21:32:40 +================================================= +* Restore OS specific file:// URI behaviour. The + RFC's specify that the url definition is host OS + specific, so what a url means on one machine will + mean something different on another. + VMS is now treated according to RFC 1738 + (http://www.faqs.org/rfcs/rfc1738.html). + +Changes for 0.13_02 Sun Nov 4 10:38:40 CET 2007 +================================================= +* Apply a perl 5.5.x compatibility fix. Users with + perl 5.6.0 or higher do not need to upgrade. + +Changes for 0.13_01 Sat Nov 3 18:55:10 CET 2007 +================================================= +* Apply a modified version of dmq's patch to deal + properly with file:// URIs on Win32. +* Add test cases for Win32 file:// URIs + +Changes for 0.12 Mon Oct 15 14:32:23 CEST 2007 +================================================= +* Treat VMS like UNIX when dealing with file URIs + +Changes for 0.10 Fri Jan 26 13:51:19 CET 2007 +================================================ +* Promote 0.09_02 to stable. + +Changes for 0.09_02 Sun Jan 7 18:44:09 CET 2007 +================================================ +* The quotation as done in 0.09_01 doesn't play + nicely with Win32 and IPC::Run. IPC::Run is + therefor disabled during the fetch() call. +* Remove File::Fetch::Item as a class. All objects + are now plain File::Fetch objects. This has no + impact on user-end code, except code that checks + the class of objects. +* URI encoding is not always clear or trivial. Add + a FAQ entry about it. +* Add $ff->output_file as accessor, which is the + requested file, stripped from query parameters. +* Errors are now stored per object rather than + class wide. + +Changes for 0.09_01 Wed Jan 3 17:17:31 CET 2007 +================================================ +* address: #23864: File:Fetch does not use quotation + marks while using wget: + * the handlers for lynx, wget, curl and rsync now + quote their URIs. + +Changes for 0.08 Wed Jul 5 13:56:36 CEST 2006 +================================================ +* address: #18942: unproper handling of http errors + in external handlers: + * the wget handler, on a failed attempt, now + unlinks its outputfile + * the curl handler is updated to follow '302 moved' + and such like status messages + * lynx use is further discouraged, as it doesn't + communicate http status messages back to the caller + at all. +* address #11483: File::Fetch 0.07 cannot do an FTP + fetch on Win32. FTP fetching using Net::FTP should + now work properly on win32. +* update test suite so it runs safely under PERL_CORE + +Changes for 0.07 Thu Dec 23 09:31:00 PST 2004 +================================================ + +* Add $TIMEOUT to specify the network timeout + +Changes for 0.06 Thu Dec 16 03:21:00 PST 2004 +================================================ + +* Add rsync support + +Changes for 0.05 Fri Jun 18 13:55:51 CEST 2004 +================================================= + +* Update faq +* Silence silly warnings + +Changes for 0.04 Fri Jun 11 22:40:34 CEST 2004 +================================================= + +* Add file support using File::Copy + +Changes for 0.03 Fri Jun 11 20:40:22 CEST 2004 +================================================= + +* Add I18N support +* Add better error handling + +Changes for 0.02 Sat May 22 14:40:29 CEST 2004 +================================================= + +* Add an extra 'FAQ' entry +* Include a 'use File::Fetch::Item' + + +Changes for 0.01 Tue May 4 15:48:24 CEST 2004 +================================================= + +* Initial release + diff --git a/File-Fetch-0.42/MANIFEST b/File-Fetch-0.42/MANIFEST new file mode 100644 index 0000000..702c16f --- /dev/null +++ b/File-Fetch-0.42/MANIFEST @@ -0,0 +1,9 @@ +CHANGES +lib/File/Fetch.pm +Makefile.PL +MANIFEST This list of files +README +t/01_File-Fetch.t +t/null_subclass.t +META.yml Module YAML meta-data (added by MakeMaker) +META.json Module JSON meta-data (added by MakeMaker) diff --git a/File-Fetch-0.42/META.json b/File-Fetch-0.42/META.json new file mode 100644 index 0000000..e5fe766 --- /dev/null +++ b/File-Fetch-0.42/META.json @@ -0,0 +1,54 @@ +{ + "abstract" : "Generic file fetching code", + "author" : [ + "Jos Boumans " + ], + "dynamic_config" : 1, + "generated_by" : "ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.130880", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "File-Fetch", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "runtime" : { + "requires" : { + "File::Basename" : "0", + "File::Copy" : "0", + "File::Path" : "0", + "File::Spec" : "0.82", + "IPC::Cmd" : "0.42", + "Locale::Maketext::Simple" : "0", + "Module::Load::Conditional" : "0.04", + "Params::Check" : "0.07", + "Test::More" : "0" + } + } + }, + "release_status" : "stable", + "resources" : { + "repository" : { + "url" : "https://github.com/jib/file-fetch" + } + }, + "version" : "0.42" +} diff --git a/File-Fetch-0.42/META.yml b/File-Fetch-0.42/META.yml new file mode 100644 index 0000000..792437a --- /dev/null +++ b/File-Fetch-0.42/META.yml @@ -0,0 +1,32 @@ +--- +abstract: 'Generic file fetching code' +author: + - 'Jos Boumans ' +build_requires: + ExtUtils::MakeMaker: 0 +configure_requires: + ExtUtils::MakeMaker: 0 +dynamic_config: 1 +generated_by: 'ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.130880' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: File-Fetch +no_index: + directory: + - t + - inc +requires: + File::Basename: 0 + File::Copy: 0 + File::Path: 0 + File::Spec: 0.82 + IPC::Cmd: 0.42 + Locale::Maketext::Simple: 0 + Module::Load::Conditional: 0.04 + Params::Check: 0.07 + Test::More: 0 +resources: + repository: https://github.com/jib/file-fetch +version: 0.42 diff --git a/File-Fetch-0.42/MYMETA.json b/File-Fetch-0.42/MYMETA.json new file mode 100644 index 0000000..f126e43 --- /dev/null +++ b/File-Fetch-0.42/MYMETA.json @@ -0,0 +1,54 @@ +{ + "abstract" : "Generic file fetching code", + "author" : [ + "Jos Boumans " + ], + "dynamic_config" : 0, + "generated_by" : "ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.130880, CPAN::Meta::Converter version 2.120921", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "File-Fetch", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "runtime" : { + "requires" : { + "File::Basename" : "0", + "File::Copy" : "0", + "File::Path" : "0", + "File::Spec" : "0.82", + "IPC::Cmd" : "0.42", + "Locale::Maketext::Simple" : "0", + "Module::Load::Conditional" : "0.04", + "Params::Check" : "0.07", + "Test::More" : "0" + } + } + }, + "release_status" : "stable", + "resources" : { + "repository" : { + "url" : "https://github.com/jib/file-fetch" + } + }, + "version" : "0.42" +} diff --git a/File-Fetch-0.42/MYMETA.yml b/File-Fetch-0.42/MYMETA.yml new file mode 100644 index 0000000..01b4669 --- /dev/null +++ b/File-Fetch-0.42/MYMETA.yml @@ -0,0 +1,32 @@ +--- +abstract: 'Generic file fetching code' +author: + - 'Jos Boumans ' +build_requires: + ExtUtils::MakeMaker: 0 +configure_requires: + ExtUtils::MakeMaker: 0 +dynamic_config: 0 +generated_by: 'ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.130880, CPAN::Meta::Converter version 2.120921' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: File-Fetch +no_index: + directory: + - t + - inc +requires: + File::Basename: 0 + File::Copy: 0 + File::Path: 0 + File::Spec: 0.82 + IPC::Cmd: 0.42 + Locale::Maketext::Simple: 0 + Module::Load::Conditional: 0.04 + Params::Check: 0.07 + Test::More: 0 +resources: + repository: https://github.com/jib/file-fetch +version: 0.42 diff --git a/File-Fetch-0.42/Makefile b/File-Fetch-0.42/Makefile new file mode 100644 index 0000000..1dc5b16 --- /dev/null +++ b/File-Fetch-0.42/Makefile @@ -0,0 +1,898 @@ +# This Makefile is for the File::Fetch extension to perl. +# +# It was generated automatically by MakeMaker version +# 6.6302 (Revision: 66302) from the contents of +# Makefile.PL. Don't edit this file, edit Makefile.PL instead. +# +# ANY CHANGES MADE HERE WILL BE LOST! +# +# MakeMaker ARGV: (q[INSTALLDIRS=vendor]) +# + +# MakeMaker Parameters: + +# ABSTRACT => q[Generic file fetching code] +# AUTHOR => [q[Jos Boumans ]] +# BUILD_REQUIRES => { } +# CONFIGURE_REQUIRES => { } +# INSTALLDIRS => q[perl] +# LICENSE => q[perl] +# META_MERGE => { resources=>{ repository=>q[https://github.com/jib/file-fetch] } } +# NAME => q[File::Fetch] +# PREREQ_PM => { File::Copy=>q[0], File::Spec=>q[0.82], Locale::Maketext::Simple=>q[0], IPC::Cmd=>q[0.42], Params::Check=>q[0.07], Test::More=>q[0], File::Path=>q[0], Module::Load::Conditional=>q[0.04], File::Basename=>q[0] } +# VERSION_FROM => q[lib/File/Fetch.pm] +# clean => { FILES=>q[t/tmp] } +# dist => { COMPRESS=>q[gzip -9f], SUFFIX=>q[gz] } + +# --- MakeMaker post_initialize section: + + +# --- MakeMaker const_config section: + +# These definitions are from config.sh (via /usr/lib64/perl5/Config.pm). +# They may have been overridden via Makefile.PL or on the command line. +AR = ar +CC = gcc +CCCDLFLAGS = -fPIC +CCDLFLAGS = -Wl,--enable-new-dtags -Wl,-rpath,/usr/lib64/perl5/CORE +DLEXT = so +DLSRC = dl_dlopen.xs +EXE_EXT = +FULL_AR = /usr/bin/ar +LD = gcc +LDDLFLAGS = -shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -Wl,-z,relro +LDFLAGS = -fstack-protector +LIBC = +LIB_EXT = .a +OBJ_EXT = .o +OSNAME = linux +OSVERS = 2.6.32-358.2.1.el6.x86_64 +RANLIB = : +SITELIBEXP = /usr/local/share/perl5 +SITEARCHEXP = /usr/local/lib64/perl5 +SO = so +VENDORARCHEXP = /usr/lib64/perl5/vendor_perl +VENDORLIBEXP = /usr/share/perl5/vendor_perl + + +# --- MakeMaker constants section: +AR_STATIC_ARGS = cr +DIRFILESEP = / +DFSEP = $(DIRFILESEP) +NAME = File::Fetch +NAME_SYM = File_Fetch +VERSION = 0.42 +VERSION_MACRO = VERSION +VERSION_SYM = 0_42 +DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" +XS_VERSION = 0.42 +XS_VERSION_MACRO = XS_VERSION +XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" +INST_ARCHLIB = blib/arch +INST_SCRIPT = blib/script +INST_BIN = blib/bin +INST_LIB = blib/lib +INST_MAN1DIR = blib/man1 +INST_MAN3DIR = blib/man3 +MAN1EXT = 1 +MAN3EXT = 3pm +INSTALLDIRS = vendor +DESTDIR = +PREFIX = $(VENDORPREFIX) +PERLPREFIX = /usr +SITEPREFIX = /usr/local +VENDORPREFIX = /usr +INSTALLPRIVLIB = /usr/share/perl5 +DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB) +INSTALLSITELIB = /usr/local/share/perl5 +DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB) +INSTALLVENDORLIB = /usr/share/perl5/vendor_perl +DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB) +INSTALLARCHLIB = /usr/lib64/perl5 +DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB) +INSTALLSITEARCH = /usr/local/lib64/perl5 +DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH) +INSTALLVENDORARCH = /usr/lib64/perl5/vendor_perl +DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH) +INSTALLBIN = /usr/bin +DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN) +INSTALLSITEBIN = /usr/local/bin +DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN) +INSTALLVENDORBIN = /usr/bin +DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN) +INSTALLSCRIPT = /usr/bin +DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT) +INSTALLSITESCRIPT = /usr/local/bin +DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT) +INSTALLVENDORSCRIPT = /usr/bin +DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT) +INSTALLMAN1DIR = /usr/share/man/man1 +DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR) +INSTALLSITEMAN1DIR = /usr/local/share/man/man1 +DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR) +INSTALLVENDORMAN1DIR = /usr/share/man/man1 +DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR) +INSTALLMAN3DIR = /usr/share/man/man3 +DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR) +INSTALLSITEMAN3DIR = /usr/local/share/man/man3 +DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR) +INSTALLVENDORMAN3DIR = /usr/share/man/man3 +DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR) +PERL_LIB = /usr/share/perl5 +PERL_ARCHLIB = /usr/lib64/perl5 +LIBPERL_A = libperl.a +FIRST_MAKEFILE = Makefile +MAKEFILE_OLD = Makefile.old +MAKE_APERL_FILE = Makefile.aperl +PERLMAINCC = $(CC) +PERL_INC = /usr/lib64/perl5/CORE +PERL = /usr/bin/perl +FULLPERL = /usr/bin/perl +ABSPERL = $(PERL) +PERLRUN = $(PERL) +FULLPERLRUN = $(FULLPERL) +ABSPERLRUN = $(ABSPERL) +PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +PERL_CORE = 0 +PERM_DIR = 755 +PERM_RW = 644 +PERM_RWX = 755 + +MAKEMAKER = /usr/share/perl5/ExtUtils/MakeMaker.pm +MM_VERSION = 6.6302 +MM_REVISION = 66302 + +# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). +# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) +# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) +# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. +MAKE = make +FULLEXT = File/Fetch +BASEEXT = Fetch +PARENT_NAME = File +DLBASE = $(BASEEXT) +VERSION_FROM = lib/File/Fetch.pm +OBJECT = +LDFROM = $(OBJECT) +LINKTYPE = dynamic +BOOTDEP = + +# Handy lists of source code files: +XS_FILES = +C_FILES = +O_FILES = +H_FILES = +MAN1PODS = +MAN3PODS = lib/File/Fetch.pm + +# Where is the Config information that we are using/depend on +CONFIGDEP = $(PERL_ARCHLIB)$(DFSEP)Config.pm $(PERL_INC)$(DFSEP)config.h + +# Where to build things +INST_LIBDIR = $(INST_LIB)/File +INST_ARCHLIBDIR = $(INST_ARCHLIB)/File + +INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) +INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) + +INST_STATIC = +INST_DYNAMIC = +INST_BOOT = + +# Extra linker info +EXPORT_LIST = +PERL_ARCHIVE = +PERL_ARCHIVE_AFTER = + + +TO_INST_PM = lib/File/Fetch.pm + +PM_TO_BLIB = lib/File/Fetch.pm \ + blib/lib/File/Fetch.pm + + +# --- MakeMaker platform_constants section: +MM_Unix_VERSION = 6.6302 +PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc + + +# --- MakeMaker tool_autosplit section: +# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto +AUTOSPLITFILE = $(ABSPERLRUN) -e 'use AutoSplit; autosplit($$$$ARGV[0], $$$$ARGV[1], 0, 1, 1)' -- + + + +# --- MakeMaker tool_xsubpp section: + + +# --- MakeMaker tools_other section: +SHELL = /bin/sh +CHMOD = chmod +CP = cp +MV = mv +NOOP = $(TRUE) +NOECHO = @ +RM_F = rm -f +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 +MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' -- +EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' -- +FALSE = false +TRUE = true +ECHO = echo +ECHO_N = echo -n +UNINST = 0 +VERBINST = 0 +MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' -- +DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' -- +UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' -- +WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' -- +MACROSTART = +MACROEND = +USEMAKEFILE = -f +FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' -- + + +# --- MakeMaker makemakerdflt section: +makemakerdflt : all + $(NOECHO) $(NOOP) + + +# --- MakeMaker dist section: +TAR = tar +TARFLAGS = cvf +ZIP = zip +ZIPFLAGS = -r +COMPRESS = gzip -9f +SUFFIX = gz +SHAR = shar +PREOP = $(NOECHO) $(NOOP) +POSTOP = $(NOECHO) $(NOOP) +TO_UNIX = $(NOECHO) $(NOOP) +CI = ci -u +RCS_LABEL = rcs -Nv$(VERSION_SYM): -q +DIST_CP = best +DIST_DEFAULT = tardist +DISTNAME = File-Fetch +DISTVNAME = File-Fetch-0.42 + + +# --- MakeMaker macro section: + + +# --- MakeMaker depend section: + + +# --- MakeMaker cflags section: + + +# --- MakeMaker const_loadlibs section: + + +# --- MakeMaker const_cccmd section: + + +# --- MakeMaker post_constants section: + + +# --- MakeMaker pasthru section: + +PASTHRU = LIBPERL_A="$(LIBPERL_A)"\ + LINKTYPE="$(LINKTYPE)"\ + PREFIX="$(PREFIX)" + + +# --- MakeMaker special_targets section: +.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT) + +.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir + + + +# --- MakeMaker c_o section: + + +# --- MakeMaker xs_c section: + + +# --- MakeMaker xs_o section: + + +# --- MakeMaker top_targets section: +all :: pure_all manifypods + $(NOECHO) $(NOOP) + + +pure_all :: config pm_to_blib subdirs linkext + $(NOECHO) $(NOOP) + +subdirs :: $(MYEXTLIB) + $(NOECHO) $(NOOP) + +config :: $(FIRST_MAKEFILE) blibdirs + $(NOECHO) $(NOOP) + +help : + perldoc ExtUtils::MakeMaker + + +# --- MakeMaker blibdirs section: +blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists + $(NOECHO) $(NOOP) + +# Backwards compat with 6.18 through 6.25 +blibdirs.ts : blibdirs + $(NOECHO) $(NOOP) + +$(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_LIBDIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR) + $(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists + +$(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHLIB) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB) + $(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists + +$(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_AUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR) + $(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists + +$(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR) + $(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists + +$(INST_BIN)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_BIN) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN) + $(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists + +$(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_SCRIPT) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT) + $(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists + +$(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN1DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR) + $(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists + +$(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN3DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR) + $(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists + + + +# --- MakeMaker linkext section: + +linkext :: $(LINKTYPE) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dlsyms section: + + +# --- MakeMaker dynamic section: + +dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dynamic_bs section: + +BOOTSTRAP = + + +# --- MakeMaker dynamic_lib section: + + +# --- MakeMaker static section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make static" +static :: $(FIRST_MAKEFILE) $(INST_STATIC) + $(NOECHO) $(NOOP) + + +# --- MakeMaker static_lib section: + + +# --- MakeMaker manifypods section: + +POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--" +POD2MAN = $(POD2MAN_EXE) + + +manifypods : pure_all \ + lib/File/Fetch.pm + $(NOECHO) $(POD2MAN) --section=3 --perm_rw=$(PERM_RW) \ + lib/File/Fetch.pm $(INST_MAN3DIR)/File::Fetch.$(MAN3EXT) + + + + +# --- MakeMaker processPL section: + + +# --- MakeMaker installbin section: + + +# --- MakeMaker subdirs section: + +# none + +# --- MakeMaker clean_subdirs section: +clean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker clean section: + +# Delete temporary files but do not touch installed files. We don't delete +# the Makefile here so a later make realclean still has a makefile to use. + +clean :: clean_subdirs + - $(RM_F) \ + *$(LIB_EXT) core \ + core.[0-9] $(INST_ARCHAUTODIR)/extralibs.all \ + core.[0-9][0-9] $(BASEEXT).bso \ + pm_to_blib.ts MYMETA.json \ + core.[0-9][0-9][0-9][0-9] MYMETA.yml \ + $(BASEEXT).x $(BOOTSTRAP) \ + perl$(EXE_EXT) tmon.out \ + *$(OBJ_EXT) pm_to_blib \ + $(INST_ARCHAUTODIR)/extralibs.ld blibdirs.ts \ + core.[0-9][0-9][0-9][0-9][0-9] *perl.core \ + core.*perl.*.? $(MAKE_APERL_FILE) \ + $(BASEEXT).def perl \ + core.[0-9][0-9][0-9] mon.out \ + lib$(BASEEXT).def perlmain.c \ + perl.exe so_locations \ + $(BASEEXT).exp + - $(RM_RF) \ + t/tmp blib + - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL) + + +# --- MakeMaker realclean_subdirs section: +realclean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker realclean section: +# Delete temporary files (via clean) and also delete dist files +realclean purge :: clean realclean_subdirs + - $(RM_F) \ + $(MAKEFILE_OLD) $(FIRST_MAKEFILE) + - $(RM_RF) \ + $(DISTVNAME) + + +# --- MakeMaker metafile section: +metafile : create_distdir + $(NOECHO) $(ECHO) Generating META.yml + $(NOECHO) $(ECHO) '---' > META_new.yml + $(NOECHO) $(ECHO) 'abstract: '\''Generic file fetching code'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'author:' >> META_new.yml + $(NOECHO) $(ECHO) ' - '\''Jos Boumans '\''' >> META_new.yml + $(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'dynamic_config: 1' >> META_new.yml + $(NOECHO) $(ECHO) 'generated_by: '\''ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'license: perl' >> META_new.yml + $(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml + $(NOECHO) $(ECHO) ' url: http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml + $(NOECHO) $(ECHO) ' version: 1.4' >> META_new.yml + $(NOECHO) $(ECHO) 'name: File-Fetch' >> META_new.yml + $(NOECHO) $(ECHO) 'no_index:' >> META_new.yml + $(NOECHO) $(ECHO) ' directory:' >> META_new.yml + $(NOECHO) $(ECHO) ' - t' >> META_new.yml + $(NOECHO) $(ECHO) ' - inc' >> META_new.yml + $(NOECHO) $(ECHO) 'requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Basename: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Copy: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Path: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Spec: 0.82' >> META_new.yml + $(NOECHO) $(ECHO) ' IPC::Cmd: 0.42' >> META_new.yml + $(NOECHO) $(ECHO) ' Locale::Maketext::Simple: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' Module::Load::Conditional: 0.04' >> META_new.yml + $(NOECHO) $(ECHO) ' Params::Check: 0.07' >> META_new.yml + $(NOECHO) $(ECHO) ' Test::More: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'resources:' >> META_new.yml + $(NOECHO) $(ECHO) ' repository: https://github.com/jib/file-fetch' >> META_new.yml + $(NOECHO) $(ECHO) 'version: 0.42' >> META_new.yml + -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml + $(NOECHO) $(ECHO) Generating META.json + $(NOECHO) $(ECHO) '{' > META_new.json + $(NOECHO) $(ECHO) ' "abstract" : "Generic file fetching code",' >> META_new.json + $(NOECHO) $(ECHO) ' "author" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "Jos Boumans "' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "dynamic_config" : 1,' >> META_new.json + $(NOECHO) $(ECHO) ' "generated_by" : "ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921",' >> META_new.json + $(NOECHO) $(ECHO) ' "license" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "perl_5"' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "meta-spec" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "2"' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "name" : "File-Fetch",' >> META_new.json + $(NOECHO) $(ECHO) ' "no_index" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "directory" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "t",' >> META_new.json + $(NOECHO) $(ECHO) ' "inc"' >> META_new.json + $(NOECHO) $(ECHO) ' ]' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "prereqs" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "build" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "configure" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "runtime" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Basename" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Copy" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Path" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Spec" : "0.82",' >> META_new.json + $(NOECHO) $(ECHO) ' "IPC::Cmd" : "0.42",' >> META_new.json + $(NOECHO) $(ECHO) ' "Locale::Maketext::Simple" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "Module::Load::Conditional" : "0.04",' >> META_new.json + $(NOECHO) $(ECHO) ' "Params::Check" : "0.07",' >> META_new.json + $(NOECHO) $(ECHO) ' "Test::More" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "release_status" : "stable",' >> META_new.json + $(NOECHO) $(ECHO) ' "resources" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "repository" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "url" : "https://github.com/jib/file-fetch"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "0.42"' >> META_new.json + $(NOECHO) $(ECHO) '}' >> META_new.json + -$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json + + +# --- MakeMaker signature section: +signature : + cpansign -s + + +# --- MakeMaker dist_basics section: +distclean :: realclean distcheck + $(NOECHO) $(NOOP) + +distcheck : + $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck + +skipcheck : + $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck + +manifest : + $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest + +veryclean : realclean + $(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old + + + +# --- MakeMaker dist_core section: + +dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE) + $(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \ + -e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' -- + +tardist : $(DISTVNAME).tar$(SUFFIX) + $(NOECHO) $(NOOP) + +uutardist : $(DISTVNAME).tar$(SUFFIX) + uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu + +$(DISTVNAME).tar$(SUFFIX) : distdir + $(PREOP) + $(TO_UNIX) + $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(COMPRESS) $(DISTVNAME).tar + $(POSTOP) + +zipdist : $(DISTVNAME).zip + $(NOECHO) $(NOOP) + +$(DISTVNAME).zip : distdir + $(PREOP) + $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(POSTOP) + +shdist : distdir + $(PREOP) + $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar + $(RM_RF) $(DISTVNAME) + $(POSTOP) + + +# --- MakeMaker distdir section: +create_distdir : + $(RM_RF) $(DISTVNAME) + $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \ + -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" + +distdir : create_distdir distmeta + $(NOECHO) $(NOOP) + + + +# --- MakeMaker dist_test section: +disttest : distdir + cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL "INSTALLDIRS=vendor" + cd $(DISTVNAME) && $(MAKE) $(PASTHRU) + cd $(DISTVNAME) && $(MAKE) test $(PASTHRU) + + + +# --- MakeMaker dist_ci section: + +ci : + $(PERLRUN) "-MExtUtils::Manifest=maniread" \ + -e "@all = keys %{ maniread() };" \ + -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \ + -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});" + + +# --- MakeMaker distmeta section: +distmeta : create_distdir metafile + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -e q{META.yml};' \ + -e 'eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.yml to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -f q{META.json};' \ + -e 'eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.json to MANIFEST: $$$${'\''@'\''}\n"' -- + + + +# --- MakeMaker distsignature section: +distsignature : create_distdir + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) } ' \ + -e ' or print "Could not add SIGNATURE to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE + cd $(DISTVNAME) && cpansign -s + + + +# --- MakeMaker install section: + +install :: pure_install doc_install + $(NOECHO) $(NOOP) + +install_perl :: pure_perl_install doc_perl_install + $(NOECHO) $(NOOP) + +install_site :: pure_site_install doc_site_install + $(NOECHO) $(NOOP) + +install_vendor :: pure_vendor_install doc_vendor_install + $(NOECHO) $(NOOP) + +pure_install :: pure_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +doc_install :: doc_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +pure__install : pure_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +doc__install : doc_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_perl_install :: all + $(NOECHO) $(MOD_INSTALL) \ + read $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist \ + write $(DESTINSTALLARCHLIB)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(DESTINSTALLPRIVLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLARCHLIB) \ + $(INST_BIN) $(DESTINSTALLBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(SITEARCHEXP)/auto/$(FULLEXT) + + +pure_site_install :: all + $(NOECHO) $(MOD_INSTALL) \ + read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \ + write $(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(DESTINSTALLSITELIB) \ + $(INST_ARCHLIB) $(DESTINSTALLSITEARCH) \ + $(INST_BIN) $(DESTINSTALLSITEBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSITESCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(PERL_ARCHLIB)/auto/$(FULLEXT) + +pure_vendor_install :: all + $(NOECHO) $(MOD_INSTALL) \ + read $(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist \ + write $(DESTINSTALLVENDORARCH)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(DESTINSTALLVENDORLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) \ + $(INST_BIN) $(DESTINSTALLVENDORBIN) \ + $(INST_SCRIPT) $(DESTINSTALLVENDORSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR) + +doc_perl_install :: all + $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod + -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB) + -$(NOECHO) $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLPRIVLIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(DESTINSTALLARCHLIB)/perllocal.pod + +doc_site_install :: all + $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod + -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB) + -$(NOECHO) $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLSITELIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(DESTINSTALLARCHLIB)/perllocal.pod + +doc_vendor_install :: all + $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod + -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB) + -$(NOECHO) $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLVENDORLIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(DESTINSTALLARCHLIB)/perllocal.pod + + +uninstall :: uninstall_from_$(INSTALLDIRS)dirs + $(NOECHO) $(NOOP) + +uninstall_from_perldirs :: + $(NOECHO) $(UNINSTALL) $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist + +uninstall_from_sitedirs :: + $(NOECHO) $(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist + +uninstall_from_vendordirs :: + $(NOECHO) $(UNINSTALL) $(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist + + +# --- MakeMaker force section: +# Phony target to force checking subdirectories. +FORCE : + $(NOECHO) $(NOOP) + + +# --- MakeMaker perldepend section: + + +# --- MakeMaker makefile section: +# We take a very conservative approach here, but it's worth it. +# We move Makefile to Makefile.old here to avoid gnu make looping. +$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) + $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?" + $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..." + -$(NOECHO) $(RM_F) $(MAKEFILE_OLD) + -$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) + - $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL) + $(PERLRUN) Makefile.PL "INSTALLDIRS=vendor" + $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <==" + $(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <==" + $(FALSE) + + + +# --- MakeMaker staticmake section: + +# --- MakeMaker makeaperl section --- +MAP_TARGET = perl +FULLPERL = /usr/bin/perl + +$(MAP_TARGET) :: static $(MAKE_APERL_FILE) + $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@ + +$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib + $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) + $(NOECHO) $(PERLRUNINST) \ + Makefile.PL DIR= \ + MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ + MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= \ + INSTALLDIRS=vendor + + +# --- MakeMaker test section: + +TEST_VERBOSE=0 +TEST_TYPE=test_$(LINKTYPE) +TEST_FILE = test.pl +TEST_FILES = t/*.t +TESTDB_SW = -d + +testdb :: testdb_$(LINKTYPE) + +test :: $(TEST_TYPE) subdirs-test + +subdirs-test :: + $(NOECHO) $(NOOP) + + +test_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-MExtUtils::Command::MM" "-e" "test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES) + +testdb_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +test_ : test_dynamic + +test_static :: test_dynamic +testdb_static :: testdb_dynamic + + +# --- MakeMaker ppd section: +# Creates a PPD (Perl Package Description) for a binary distribution. +ppd : + $(NOECHO) $(ECHO) '' > $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' Generic file fetching code' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' Jos Boumans <kane[at]cpan.org>' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) '' >> $(DISTNAME).ppd + + +# --- MakeMaker pm_to_blib section: + +pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM) + $(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \ + lib/File/Fetch.pm blib/lib/File/Fetch.pm + $(NOECHO) $(TOUCH) pm_to_blib + + +# --- MakeMaker selfdocument section: + + +# --- MakeMaker postamble section: + + +# End. diff --git a/File-Fetch-0.42/Makefile.PL b/File-Fetch-0.42/Makefile.PL new file mode 100644 index 0000000..336d6ff --- /dev/null +++ b/File-Fetch-0.42/Makefile.PL @@ -0,0 +1,56 @@ +use ExtUtils::MakeMaker; +use strict; + +WriteMakefile1( + LICENSE => 'perl', + META_MERGE => { + resources => { + repository => 'https://github.com/jib/file-fetch', + }, + }, + #BUILD_REQUIRES => { + #}, + + NAME => 'File::Fetch', + VERSION_FROM => 'lib/File/Fetch.pm', # finds $VERSION + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz' }, + PREREQ_PM => { + 'IPC::Cmd' => 0.42, # ipc::open3 bugfix + 'Test::More' => 0, + 'File::Copy' => 0, + 'File::Spec' => 0.82, + 'File::Path' => 0, + 'File::Basename' => 0, + 'Params::Check' => 0.07, + 'Module::Load::Conditional' => 0.04, + 'Locale::Maketext::Simple' => 0, + }, + INSTALLDIRS => ( $] >= 5.009005 ? 'perl' : 'site' ), + AUTHOR => 'Jos Boumans ', + ABSTRACT => 'Generic file fetching code', + clean => {FILES => 't/tmp'}, +); + +sub WriteMakefile1 { #Written by Alexandr Ciornii, version 0.21. Added by eumm-upgrade. + my %params=@_; + my $eumm_version=$ExtUtils::MakeMaker::VERSION; + $eumm_version=eval $eumm_version; + die "EXTRA_META is deprecated" if exists $params{EXTRA_META}; + die "License not specified" if not exists $params{LICENSE}; + if ($params{BUILD_REQUIRES} and $eumm_version < 6.5503) { + #EUMM 6.5502 has problems with BUILD_REQUIRES + $params{PREREQ_PM}={ %{$params{PREREQ_PM} || {}} , %{$params{BUILD_REQUIRES}} }; + delete $params{BUILD_REQUIRES}; + } + delete $params{CONFIGURE_REQUIRES} if $eumm_version < 6.52; + delete $params{MIN_PERL_VERSION} if $eumm_version < 6.48; + delete $params{META_MERGE} if $eumm_version < 6.46; + delete $params{META_ADD} if $eumm_version < 6.46; + delete $params{LICENSE} if $eumm_version < 6.31; + delete $params{AUTHOR} if $] < 5.005; + delete $params{ABSTRACT_FROM} if $] < 5.005; + delete $params{BINARY_LOCATION} if $] < 5.005; + + WriteMakefile(%params); +} + diff --git a/File-Fetch-0.42/README b/File-Fetch-0.42/README new file mode 100644 index 0000000..84a6a63 --- /dev/null +++ b/File-Fetch-0.42/README @@ -0,0 +1,40 @@ +This is the README file for File::Fetch, a perl module for generic +file fetching. + +Please refer to 'perldoc File::Fetch' after installation for details. + +##################################################################### + +* Description + +File::Fetch + + File::Fetch is a generic file fetching mechanism. + + It allows you to fetch any file pointed to by a ftp, http + or file uri by a number of different means. + +##################################################################### + +* Installation + +File::Fetch follows the standard perl module install process + +perl Makefile.PL +make +make test +make install + +The module uses no C or XS parts, so no c-compiler is required. + +###################################################################### + +AUTHOR + This module by Jos Boumans . + +COPYRIGHT + This module is copyright (c) 2002 Jos Boumans . All + rights reserved. + + This library is free software; you may redistribute and/or modify it + under the same terms as Perl itself. diff --git a/File-Fetch-0.42/blib/arch/.exists b/File-Fetch-0.42/blib/arch/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/blib/arch/auto/File/Fetch/.exists b/File-Fetch-0.42/blib/arch/auto/File/Fetch/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/blib/bin/.exists b/File-Fetch-0.42/blib/bin/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/blib/lib/File/.exists b/File-Fetch-0.42/blib/lib/File/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/blib/lib/File/Fetch.pm b/File-Fetch-0.42/blib/lib/File/Fetch.pm new file mode 100644 index 0000000..75e42c6 --- /dev/null +++ b/File-Fetch-0.42/blib/lib/File/Fetch.pm @@ -0,0 +1,1708 @@ +package File::Fetch; + +use strict; +use FileHandle; +use File::Temp; +use File::Copy; +use File::Spec; +use File::Spec::Unix; +use File::Basename qw[dirname]; + +use Cwd qw[cwd]; +use Carp qw[carp]; +use IPC::Cmd qw[can_run run QUOTE]; +use File::Path qw[mkpath]; +use File::Temp qw[tempdir]; +use Params::Check qw[check]; +use Module::Load::Conditional qw[can_load]; +use Locale::Maketext::Simple Style => 'gettext'; + +use vars qw[ $VERBOSE $PREFER_BIN $FROM_EMAIL $USER_AGENT + $BLACKLIST $METHOD_FAIL $VERSION $METHODS + $FTP_PASSIVE $TIMEOUT $DEBUG $WARN + ]; + +$VERSION = '0.42'; +$VERSION = eval $VERSION; # avoid warnings with development releases +$PREFER_BIN = 0; # XXX TODO implement +$FROM_EMAIL = 'File-Fetch@example.com'; +$USER_AGENT = "File::Fetch/$VERSION"; +$BLACKLIST = [qw|ftp|]; +$METHOD_FAIL = { }; +$FTP_PASSIVE = 1; +$TIMEOUT = 0; +$DEBUG = 0; +$WARN = 1; + +### methods available to fetch the file depending on the scheme +$METHODS = { + http => [ qw|lwp httptiny wget curl lftp fetch httplite lynx iosock| ], + ftp => [ qw|lwp netftp wget curl lftp fetch ncftp ftp| ], + file => [ qw|lwp lftp file| ], + rsync => [ qw|rsync| ], + git => [ qw|git| ], +}; + +### silly warnings ### +local $Params::Check::VERBOSE = 1; +local $Params::Check::VERBOSE = 1; +local $Module::Load::Conditional::VERBOSE = 0; +local $Module::Load::Conditional::VERBOSE = 0; + +### see what OS we are on, important for file:// uris ### +use constant ON_WIN => ($^O eq 'MSWin32'); +use constant ON_VMS => ($^O eq 'VMS'); +use constant ON_UNIX => (!ON_WIN); +use constant HAS_VOL => (ON_WIN); +use constant HAS_SHARE => (ON_WIN); +use constant HAS_FETCH => ( $^O =~ m!^(freebsd|netbsd|dragonfly)$! ); + +=pod + +=head1 NAME + +File::Fetch - A generic file fetching mechanism + +=head1 SYNOPSIS + + use File::Fetch; + + ### build a File::Fetch object ### + my $ff = File::Fetch->new(uri => 'http://some.where.com/dir/a.txt'); + + ### fetch the uri to cwd() ### + my $where = $ff->fetch() or die $ff->error; + + ### fetch the uri to /tmp ### + my $where = $ff->fetch( to => '/tmp' ); + + ### parsed bits from the uri ### + $ff->uri; + $ff->scheme; + $ff->host; + $ff->path; + $ff->file; + +=head1 DESCRIPTION + +File::Fetch is a generic file fetching mechanism. + +It allows you to fetch any file pointed to by a C, C, +C, C or C uri by a number of different means. + +See the C section further down for details. + +=head1 ACCESSORS + +A C object has the following accessors + +=over 4 + +=item $ff->uri + +The uri you passed to the constructor + +=item $ff->scheme + +The scheme from the uri (like 'file', 'http', etc) + +=item $ff->host + +The hostname in the uri. Will be empty if host was originally +'localhost' for a 'file://' url. + +=item $ff->vol + +On operating systems with the concept of a volume the second element +of a file:// is considered to the be volume specification for the file. +Thus on Win32 this routine returns the volume, on other operating +systems this returns nothing. + +On Windows this value may be empty if the uri is to a network share, in +which case the 'share' property will be defined. Additionally, volume +specifications that use '|' as ':' will be converted on read to use ':'. + +On VMS, which has a volume concept, this field will be empty because VMS +file specifications are converted to absolute UNIX format and the volume +information is transparently included. + +=item $ff->share + +On systems with the concept of a network share (currently only Windows) returns +the sharename from a file://// url. On other operating systems returns empty. + +=item $ff->path + +The path from the uri, will be at least a single '/'. + +=item $ff->file + +The name of the remote file. For the local file name, the +result of $ff->output_file will be used. + +=item $ff->file_default + +The name of the default local file, that $ff->output_file falls back to if +it would otherwise return no filename. For example when fetching a URI like +http://www.abc.net.au/ the contents retrieved may be from a remote file called +'index.html'. The default value of this attribute is literally 'file_default'. + +=cut + + +########################## +### Object & Accessors ### +########################## + +{ + ### template for autogenerated accessors ### + my $Tmpl = { + scheme => { default => 'http' }, + host => { default => 'localhost' }, + path => { default => '/' }, + file => { required => 1 }, + uri => { required => 1 }, + vol => { default => '' }, # windows for file:// uris + share => { default => '' }, # windows for file:// uris + file_default => { default => 'file_default' }, + tempdir_root => { required => 1 }, # Should be lazy-set at ->new() + _error_msg => { no_override => 1 }, + _error_msg_long => { no_override => 1 }, + }; + + for my $method ( keys %$Tmpl ) { + no strict 'refs'; + *$method = sub { + my $self = shift; + $self->{$method} = $_[0] if @_; + return $self->{$method}; + } + } + + sub _create { + my $class = shift; + my %hash = @_; + + my $args = check( $Tmpl, \%hash ) or return; + + bless $args, $class; + + if( lc($args->scheme) ne 'file' and not $args->host ) { + return $class->_error(loc( + "Hostname required when fetching from '%1'",$args->scheme)); + } + + for (qw[path]) { + unless( $args->$_() ) { # 5.5.x needs the () + return $class->_error(loc("No '%1' specified",$_)); + } + } + + return $args; + } +} + +=item $ff->output_file + +The name of the output file. This is the same as $ff->file, +but any query parameters are stripped off. For example: + + http://example.com/index.html?x=y + +would make the output file be C rather than +C. + +=back + +=cut + +sub output_file { + my $self = shift; + my $file = $self->file; + + $file =~ s/\?.*$//g; + + $file ||= $self->file_default; + + return $file; +} + +### XXX do this or just point to URI::Escape? +# =head2 $esc_uri = $ff->escaped_uri +# +# =cut +# +# ### most of this is stolen straight from URI::escape +# { ### Build a char->hex map +# my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255; +# +# sub escaped_uri { +# my $self = shift; +# my $uri = $self->uri; +# +# ### Default unsafe characters. RFC 2732 ^(uric - reserved) +# $uri =~ s/([^A-Za-z0-9\-_.!~*'()])/ +# $escapes{$1} || $self->_fail_hi($1)/ge; +# +# return $uri; +# } +# +# sub _fail_hi { +# my $self = shift; +# my $char = shift; +# +# $self->_error(loc( +# "Can't escape '%1', try using the '%2' module instead", +# sprintf("\\x{%04X}", ord($char)), 'URI::Escape' +# )); +# } +# +# sub output_file { +# +# } +# +# +# } + +=head1 METHODS + +=head2 $ff = File::Fetch->new( uri => 'http://some.where.com/dir/file.txt' ); + +Parses the uri and creates a corresponding File::Fetch::Item object, +that is ready to be Ced and returns it. + +Returns false on failure. + +=cut + +sub new { + my $class = shift; + my %hash = @_; + + my ($uri, $file_default, $tempdir_root); + my $tmpl = { + uri => { required => 1, store => \$uri }, + file_default => { required => 0, store => \$file_default }, + tempdir_root => { required => 0, store => \$tempdir_root }, + }; + + check( $tmpl, \%hash ) or return; + + ### parse the uri to usable parts ### + my $href = $class->_parse_uri( $uri ) or return; + + $href->{file_default} = $file_default if $file_default; + $href->{tempdir_root} = File::Spec->rel2abs( $tempdir_root ) if $tempdir_root; + $href->{tempdir_root} = File::Spec->rel2abs( Cwd::cwd ) if not $href->{tempdir_root}; + + ### make it into a FFI object ### + my $ff = $class->_create( %$href ) or return; + + + ### return the object ### + return $ff; +} + +### parses an uri to a hash structure: +### +### $class->_parse_uri( 'ftp://ftp.cpan.org/pub/mirror/index.txt' ) +### +### becomes: +### +### $href = { +### scheme => 'ftp', +### host => 'ftp.cpan.org', +### path => '/pub/mirror', +### file => 'index.html' +### }; +### +### In the case of file:// urls there maybe be additional fields +### +### For systems with volume specifications such as Win32 there will be +### a volume specifier provided in the 'vol' field. +### +### 'vol' => 'volumename' +### +### For windows file shares there may be a 'share' key specified +### +### 'share' => 'sharename' +### +### Note that the rules of what a file:// url means vary by the operating system +### of the host being addressed. Thus file:///d|/foo/bar.txt means the obvious +### 'D:\foo\bar.txt' on windows, but on unix it means '/d|/foo/bar.txt' and +### not '/foo/bar.txt' +### +### Similarly if the host interpreting the url is VMS then +### file:///disk$user/my/notes/note12345.txt' means +### 'DISK$USER:[MY.NOTES]NOTE123456.TXT' but will be returned the same as +### if it is unix where it means /disk$user/my/notes/note12345.txt'. +### Except for some cases in the File::Spec methods, Perl on VMS will generally +### handle UNIX format file specifications. +### +### This means it is impossible to serve certain file:// urls on certain systems. +### +### Thus are the problems with a protocol-less specification. :-( +### + +sub _parse_uri { + my $self = shift; + my $uri = shift or return; + + my $href = { uri => $uri }; + + ### find the scheme ### + $uri =~ s|^(\w+)://||; + $href->{scheme} = $1; + + ### See rfc 1738 section 3.10 + ### http://www.faqs.org/rfcs/rfc1738.html + ### And wikipedia for more on windows file:// urls + ### http://en.wikipedia.org/wiki/File:// + if( $href->{scheme} eq 'file' ) { + + my @parts = split '/',$uri; + + ### file://hostname/... + ### file://hostname/... + ### normalize file://localhost with file:/// + $href->{host} = $parts[0] || ''; + + ### index in @parts where the path components begin; + my $index = 1; + + ### file:////hostname/sharename/blah.txt + if ( HAS_SHARE and not length $parts[0] and not length $parts[1] ) { + + $href->{host} = $parts[2] || ''; # avoid warnings + $href->{share} = $parts[3] || ''; # avoid warnings + + $index = 4 # index after the share + + ### file:///D|/blah.txt + ### file:///D:/blah.txt + } elsif (HAS_VOL) { + + ### this code comes from dmq's patch, but: + ### XXX if volume is empty, wouldn't that be an error? --kane + ### if so, our file://localhost test needs to be fixed as wel + $href->{vol} = $parts[1] || ''; + + ### correct D| style colume descriptors + $href->{vol} =~ s/\A([A-Z])\|\z/$1:/i if ON_WIN; + + $index = 2; # index after the volume + } + + ### rebuild the path from the leftover parts; + $href->{path} = join '/', '', splice( @parts, $index, $#parts ); + + } else { + ### using anything but qw() in hash slices may produce warnings + ### in older perls :-( + @{$href}{ qw(host path) } = $uri =~ m|([^/]*)(/.*)$|s; + } + + ### split the path into file + dir ### + { my @parts = File::Spec::Unix->splitpath( delete $href->{path} ); + $href->{path} = $parts[1]; + $href->{file} = $parts[2]; + } + + ### host will be empty if the target was 'localhost' and the + ### scheme was 'file' + $href->{host} = '' if ($href->{host} eq 'localhost') and + ($href->{scheme} eq 'file'); + + return $href; +} + +=head2 $where = $ff->fetch( [to => /my/output/dir/ | \$scalar] ) + +Fetches the file you requested and returns the full path to the file. + +By default it writes to C, but you can override that by specifying +the C argument: + + ### file fetch to /tmp, full path to the file in $where + $where = $ff->fetch( to => '/tmp' ); + + ### file slurped into $scalar, full path to the file in $where + ### file is downloaded to a temp directory and cleaned up at exit time + $where = $ff->fetch( to => \$scalar ); + +Returns the full path to the downloaded file on success, and false +on failure. + +=cut + +sub fetch { + my $self = shift or return; + my %hash = @_; + + my $target; + my $tmpl = { + to => { default => cwd(), store => \$target }, + }; + + check( $tmpl, \%hash ) or return; + + my ($to, $fh); + ### you want us to slurp the contents + if( ref $target and UNIVERSAL::isa( $target, 'SCALAR' ) ) { + $to = tempdir( 'FileFetch.XXXXXX', DIR => $self->tempdir_root, CLEANUP => 1 ); + + ### plain old fetch + } else { + $to = $target; + + ### On VMS force to VMS format so File::Spec will work. + $to = VMS::Filespec::vmspath($to) if ON_VMS; + + ### create the path if it doesn't exist yet ### + unless( -d $to ) { + eval { mkpath( $to ) }; + + return $self->_error(loc("Could not create path '%1'",$to)) if $@; + } + } + + ### set passive ftp if required ### + local $ENV{FTP_PASSIVE} = $FTP_PASSIVE; + + ### we dont use catfile on win32 because if we are using a cygwin tool + ### under cmd.exe they wont understand windows style separators. + my $out_to = ON_WIN ? $to.'/'.$self->output_file + : File::Spec->catfile( $to, $self->output_file ); + + for my $method ( @{ $METHODS->{$self->scheme} } ) { + my $sub = '_'.$method.'_fetch'; + + unless( __PACKAGE__->can($sub) ) { + $self->_error(loc("Cannot call method for '%1' -- WEIRD!", + $method)); + next; + } + + ### method is blacklisted ### + next if grep { lc $_ eq $method } @$BLACKLIST; + + ### method is known to fail ### + next if $METHOD_FAIL->{$method}; + + ### there's serious issues with IPC::Run and quoting of command + ### line arguments. using quotes in the wrong place breaks things, + ### and in the case of say, + ### C:\cygwin\bin\wget.EXE --quiet --passive-ftp --output-document + ### "index.html" "http://www.cpan.org/index.html?q=1&y=2" + ### it doesn't matter how you quote, it always fails. + local $IPC::Cmd::USE_IPC_RUN = 0; + + if( my $file = $self->$sub( + to => $out_to + )){ + + unless( -e $file && -s _ ) { + $self->_error(loc("'%1' said it fetched '%2', ". + "but it was not created",$method,$file)); + + ### mark the failure ### + $METHOD_FAIL->{$method} = 1; + + next; + + } else { + + ### slurp mode? + if( ref $target and UNIVERSAL::isa( $target, 'SCALAR' ) ) { + + ### open the file + open my $fh, "<$file" or do { + $self->_error( + loc("Could not open '%1': %2", $file, $!)); + return; + }; + + ### slurp + $$target = do { local $/; <$fh> }; + + } + + my $abs = File::Spec->rel2abs( $file ); + return $abs; + + } + } + } + + + ### if we got here, we looped over all methods, but we weren't able + ### to fetch it. + return; +} + +######################## +### _*_fetch methods ### +######################## + +### LWP fetching ### +sub _lwp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### modules required to download with lwp ### + my $use_list = { + LWP => '0.0', + 'LWP::UserAgent' => '0.0', + 'HTTP::Request' => '0.0', + 'HTTP::Status' => '0.0', + URI => '0.0', + + }; + + unless( can_load( modules => $use_list ) ) { + $METHOD_FAIL->{'lwp'} = 1; + return; + } + + ### setup the uri object + my $uri = URI->new( File::Spec::Unix->catfile( + $self->path, $self->file + ) ); + + ### special rules apply for file:// uris ### + $uri->scheme( $self->scheme ); + $uri->host( $self->scheme eq 'file' ? '' : $self->host ); + $uri->userinfo("anonymous:$FROM_EMAIL") if $self->scheme ne 'file'; + + ### set up the useragent object + my $ua = LWP::UserAgent->new(); + $ua->timeout( $TIMEOUT ) if $TIMEOUT; + $ua->agent( $USER_AGENT ); + $ua->from( $FROM_EMAIL ); + $ua->env_proxy; + + my $res = $ua->mirror($uri, $to) or return; + + ### uptodate or fetched ok ### + if ( $res->code == 304 or $res->code == 200 ) { + return $to; + + } else { + return $self->_error(loc("Fetch failed! HTTP response: %1 %2 [%3]", + $res->code, HTTP::Status::status_message($res->code), + $res->status_line)); + } + +} + +### HTTP::Tiny fetching ### +sub _httptiny_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $use_list = { + 'HTTP::Tiny' => '0.008', + + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'httptiny'} = 1; + return; + } + + my $uri = $self->uri; + + my $http = HTTP::Tiny->new( ( $TIMEOUT ? ( timeout => $TIMEOUT ) : () ) ); + + my $rc = $http->mirror( $uri, $to ); + + unless ( $rc->{success} ) { + + return $self->_error(loc( "Fetch failed! HTTP response: %1 [%2]", + $rc->{status}, $rc->{reason} ) ); + + } + + return $to; + +} + +### HTTP::Lite fetching ### +sub _httplite_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### modules required to download with lwp ### + my $use_list = { + 'HTTP::Lite' => '2.2', + + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'httplite'} = 1; + return; + } + + my $uri = $self->uri; + my $retries = 0; + + RETRIES: while ( $retries++ < 5 ) { + + my $http = HTTP::Lite->new(); + # Naughty naughty but there isn't any accessor/setter + $http->{timeout} = $TIMEOUT if $TIMEOUT; + $http->http11_mode(1); + + my $fh = FileHandle->new; + + unless ( $fh->open($to,'>') ) { + return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + } + + $fh->autoflush(1); + + binmode $fh; + + my $rc = $http->request( $uri, sub { my ($self,$dref,$cbargs) = @_; local $\; print {$cbargs} $$dref }, $fh ); + + close $fh; + + if ( $rc == 301 || $rc == 302 ) { + my $loc; + HEADERS: for ($http->headers_array) { + /Location: (\S+)/ and $loc = $1, last HEADERS; + } + #$loc or last; # Think we should squeal here. + if ($loc =~ m!^/!) { + $uri =~ s{^(\w+?://[^/]+)/.*$}{$1}; + $uri .= $loc; + } + else { + $uri = $loc; + } + next RETRIES; + } + elsif ( $rc == 200 ) { + return $to; + } + else { + return $self->_error(loc("Fetch failed! HTTP response: %1 [%2]", + $rc, $http->status_message)); + } + + } # Loop for 5 retries. + + return $self->_error("Fetch failed! Gave up after 5 tries"); + +} + +### Simple IO::Socket::INET fetching ### +sub _iosock_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $use_list = { + 'IO::Socket::INET' => '0.0', + 'IO::Select' => '0.0', + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'iosock'} = 1; + return; + } + + my $sock = IO::Socket::INET->new( + PeerHost => $self->host, + ( $self->host =~ /:/ ? () : ( PeerPort => 80 ) ), + ); + + unless ( $sock ) { + return $self->_error(loc("Could not open socket to '%1', '%2'",$self->host,$!)); + } + + my $fh = FileHandle->new; + + # Check open() + + unless ( $fh->open($to,'>') ) { + return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + } + + $fh->autoflush(1); + binmode $fh; + + my $path = File::Spec::Unix->catfile( $self->path, $self->file ); + my $req = "GET $path HTTP/1.0\x0d\x0aHost: " . $self->host . "\x0d\x0a\x0d\x0a"; + $sock->send( $req ); + + my $select = IO::Select->new( $sock ); + + my $resp = ''; + my $normal = 0; + while ( $select->can_read( $TIMEOUT || 60 ) ) { + my $ret = $sock->sysread( $resp, 4096, length($resp) ); + if ( !defined $ret or $ret == 0 ) { + $select->remove( $sock ); + $normal++; + } + } + close $sock; + + unless ( $normal ) { + return $self->_error(loc("Socket timed out after '%1' seconds", ( $TIMEOUT || 60 ))); + } + + # Check the "response" + # Strip preceding blank lines apparently they are allowed (RFC 2616 4.1) + $resp =~ s/^(\x0d?\x0a)+//; + # Check it is an HTTP response + unless ( $resp =~ m!^HTTP/(\d+)\.(\d+)!i ) { + return $self->_error(loc("Did not get a HTTP response from '%1'",$self->host)); + } + + # Check for OK + my ($code) = $resp =~ m!^HTTP/\d+\.\d+\s+(\d+)!i; + unless ( $code eq '200' ) { + return $self->_error(loc("Got a '%1' from '%2' expected '200'",$code,$self->host)); + } + + { + local $\; + print $fh +($resp =~ m/\x0d\x0a\x0d\x0a(.*)$/s )[0]; + } + close $fh; + return $to; +} + +### Net::FTP fetching +sub _netftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### required modules ### + my $use_list = { 'Net::FTP' => 0 }; + + unless( can_load( modules => $use_list ) ) { + $METHOD_FAIL->{'netftp'} = 1; + return; + } + + ### make connection ### + my $ftp; + my @options = ($self->host); + push(@options, Timeout => $TIMEOUT) if $TIMEOUT; + unless( $ftp = Net::FTP->new( @options ) ) { + return $self->_error(loc("Ftp creation failed: %1",$@)); + } + + ### login ### + unless( $ftp->login( anonymous => $FROM_EMAIL ) ) { + return $self->_error(loc("Could not login to '%1'",$self->host)); + } + + ### set binary mode, just in case ### + $ftp->binary; + + ### create the remote path + ### remember remote paths are unix paths! [#11483] + my $remote = File::Spec::Unix->catfile( $self->path, $self->file ); + + ### fetch the file ### + my $target; + unless( $target = $ftp->get( $remote, $to ) ) { + return $self->_error(loc("Could not fetch '%1' from '%2'", + $remote, $self->host)); + } + + ### log out ### + $ftp->quit; + + return $target; + +} + +### /bin/wget fetch ### +sub _wget_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $wget; + ### see if we have a wget binary ### + unless( $wget = can_run('wget') ) { + $METHOD_FAIL->{'wget'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $wget, '--quiet' ]; + + ### if a timeout is set, add it ### + push(@$cmd, '--timeout=' . $TIMEOUT) if $TIMEOUT; + + ### run passive if specified ### + push @$cmd, '--passive-ftp' if $FTP_PASSIVE; + + ### set the output document, add the uri ### + push @$cmd, '--output-document', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + +### /bin/lftp fetch ### +sub _lftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a lftp binary ### + my $lftp; + unless( $lftp = can_run('lftp') ) { + $METHOD_FAIL->{'lftp'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $lftp, '-f' ]; + + my $fh = File::Temp->new; + + my $str; + + ### if a timeout is set, add it ### + $str .= "set net:timeout $TIMEOUT;\n" if $TIMEOUT; + + ### run passive if specified ### + $str .= "set ftp:passive-mode 1;\n" if $FTP_PASSIVE; + + ### set the output document, add the uri ### + ### quote the URI, because lftp supports certain shell + ### expansions, most notably & for backgrounding. + ### ' quote does nto work, must be " + $str .= q[get ']. $self->uri .q[' -o ]. $to . $/; + + if( $DEBUG ) { + my $pp_str = join ' ', split $/, $str; + print "# lftp command: $pp_str\n"; + } + + ### write straight to the file. + $fh->autoflush(1); + print $fh $str; + + ### the command needs to be 1 string to be executed + push @$cmd, $fh->filename; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + + + +### /bin/ftp fetch ### +sub _ftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a ftp binary ### + my $ftp; + unless( $ftp = can_run('ftp') ) { + $METHOD_FAIL->{'ftp'} = 1; + return; + } + + my $fh = FileHandle->new; + + local $SIG{CHLD} = 'IGNORE'; + + unless ($fh->open("$ftp -n", '|-')) { + return $self->_error(loc("%1 creation failed: %2", $ftp, $!)); + } + + my @dialog = ( + "lcd " . dirname($to), + "open " . $self->host, + "user anonymous $FROM_EMAIL", + "cd /", + "cd " . $self->path, + "binary", + "get " . $self->file . " " . $self->output_file, + "quit", + ); + + foreach (@dialog) { $fh->print($_, "\n") } + $fh->close or return; + + return $to; +} + +### lynx is stupid - it decompresses any .gz file it finds to be text +### use /bin/lynx to fetch files +sub _lynx_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a lynx binary ### + my $lynx; + unless ( $lynx = can_run('lynx') ){ + $METHOD_FAIL->{'lynx'} = 1; + return; + } + + unless( IPC::Cmd->can_capture_buffer ) { + $METHOD_FAIL->{'lynx'} = 1; + + return $self->_error(loc( + "Can not capture buffers. Can not use '%1' to fetch files", + 'lynx' )); + } + + ### check if the HTTP resource exists ### + if ($self->uri =~ /^https?:\/\//i) { + my $cmd = [ + $lynx, + '-head', + '-source', + "-auth=anonymous:$FROM_EMAIL", + ]; + + push @$cmd, "-connect_timeout=$TIMEOUT" if $TIMEOUT; + + push @$cmd, $self->uri; + + ### shell out ### + my $head; + unless(run( command => $cmd, + buffer => \$head, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $head || '')); + } + + unless($head =~ /^HTTP\/\d+\.\d+ 200\b/) { + return $self->_error(loc("Command failed: %1", $head || '')); + } + } + + ### write to the output file ourselves, since lynx ass_u_mes to much + my $local = FileHandle->new( $to, 'w' ) + or return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + + ### dump to stdout ### + my $cmd = [ + $lynx, + '-source', + "-auth=anonymous:$FROM_EMAIL", + ]; + + push @$cmd, "-connect_timeout=$TIMEOUT" if $TIMEOUT; + + ### DO NOT quote things for IPC::Run, it breaks stuff. + push @$cmd, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### DO NOT quote things for IPC::Run, it breaks stuff. + # $IPC::Cmd::USE_IPC_RUN + # ? $self->uri + # : QUOTE. $self->uri .QUOTE; + + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $captured || '')); + } + + ### print to local file ### + ### XXX on a 404 with a special error page, $captured will actually + ### hold the contents of that page, and make it *appear* like the + ### request was a success, when really it wasn't :( + ### there doesn't seem to be an option for lynx to change the exit + ### code based on a 4XX status or so. + ### the closest we can come is using --error_file and parsing that, + ### which is very unreliable ;( + $local->print( $captured ); + $local->close or return; + + return $to; +} + +### use /bin/ncftp to fetch files +sub _ncftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### we can only set passive mode in interactive sessions, so bail out + ### if $FTP_PASSIVE is set + return if $FTP_PASSIVE; + + ### see if we have a ncftp binary ### + my $ncftp; + unless( $ncftp = can_run('ncftp') ) { + $METHOD_FAIL->{'ncftp'} = 1; + return; + } + + my $cmd = [ + $ncftp, + '-V', # do not be verbose + '-p', $FROM_EMAIL, # email as password + $self->host, # hostname + dirname($to), # local dir for the file + # remote path to the file + ### DO NOT quote things for IPC::Run, it breaks stuff. + $IPC::Cmd::USE_IPC_RUN + ? File::Spec::Unix->catdir( $self->path, $self->file ) + : QUOTE. File::Spec::Unix->catdir( + $self->path, $self->file ) .QUOTE + + ]; + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $captured || '')); + } + + return $to; + +} + +### use /bin/curl to fetch files +sub _curl_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $curl; + unless ( $curl = can_run('curl') ) { + $METHOD_FAIL->{'curl'} = 1; + return; + } + + ### these long opts are self explanatory - I like that -jmb + my $cmd = [ $curl, '-q' ]; + + 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', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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; + +} + +### /usr/bin/fetch fetch! ### +sub _fetch_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a fetch binary ### + my $fetch; + unless( HAS_FETCH and $fetch = can_run('fetch') ) { + $METHOD_FAIL->{'fetch'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $fetch, '-q' ]; + + ### if a timeout is set, add it ### + push(@$cmd, '-T', $TIMEOUT) if $TIMEOUT; + + ### run passive if specified ### + #push @$cmd, '-p' if $FTP_PASSIVE; + local $ENV{'FTP_PASSIVE_MODE'} = 1 if $FTP_PASSIVE; + + ### set the output document, add the uri ### + push @$cmd, '-o', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + +### 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 + ### whereas 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 files +sub _rsync_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $rsync; + unless ( $rsync = can_run('rsync') ) { + $METHOD_FAIL->{'rsync'} = 1; + return; + } + + 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, $self->uri, $to; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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 %1 failed: %2", + "@$cmd" || '', $captured || '')); + } + + return $to; + +} + +### use git to fetch files +sub _git_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $git; + unless ( $git = can_run('git') ) { + $METHOD_FAIL->{'git'} = 1; + return; + } + + my $cmd = [ $git, 'clone' ]; + + #push(@$cmd, '--timeout=' . $TIMEOUT) if $TIMEOUT; + + push(@$cmd, '--quiet') unless $DEBUG; + + ### DO NOT quote things for IPC::Run, it breaks stuff. + push @$cmd, $self->uri, $to; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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 %1 failed: %2", + "@$cmd" || '', $captured || '')); + } + + return $to; + +} + +################################# +# +# Error code +# +################################# + +=pod + +=head2 $ff->error([BOOL]) + +Returns the last encountered error as string. +Pass it a true value to get the C output instead. + +=cut + +### error handling the way Archive::Extract does it +sub _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 WORKS + +File::Fetch is able to fetch a variety of uris, by using several +external programs and modules. + +Below is a mapping of what utilities will be used in what order +for what schemes, if available: + + file => LWP, lftp, file + http => LWP, HTTP::Lite, wget, curl, lftp, fetch, lynx, iosock + ftp => LWP, Net::FTP, wget, curl, lftp, fetch, ncftp, ftp + rsync => rsync + git => git + +If you'd like to disable the use of one or more of these utilities +and/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 be +tried again. The C method will only fail when all options are +exhausted, and it was not able to retrieve the file. + +The C utility is available on FreeBSD. NetBSD and Dragonfly BSD +may also have it from C. We only check for C on those +three platforms. + +C is a very limited L based mechanism for +retrieving C schemed urls. It doesn't follow redirects for instance. + +C only supports C style urls. + +A special note about fetching files from an ftp uri: + +By default, all ftp connections are done in passive mode. To change +that, see the C<$FTP_PASSIVE> variable further down. + +Furthermore, ftp uris only support anonymous connections, so no +named user/password pair can be passed along. + +C is blacklisted by default; see the C<$BLACKLIST> variable +further down. + +=head1 GLOBAL VARIABLES + +The behaviour of File::Fetch can be altered by changing the following +global variables: + +=head2 $File::Fetch::FROM_EMAIL + +This is the email address that will be sent as your anonymous ftp +password. + +Default is C. + +=head2 $File::Fetch::USER_AGENT + +This is the useragent as C will report it. + +Default is C. + +=head2 $File::Fetch::FTP_PASSIVE + +This variable controls whether the environment variable C +and any passive switches to commandline tools will be set to true. + +Default value is 1. + +Note: When $FTP_PASSIVE is true, C will not be used to fetch +files, since passive mode can only be set interactively for this binary + +=head2 $File::Fetch::TIMEOUT + +When set, controls the network timeout (counted in seconds). + +Default value is 0. + +=head2 $File::Fetch::WARN + +This variable controls whether errors encountered internally by +C should be C'd or not. + +Set to false to silence warnings. Inspect the output of the C +method manually to see what went wrong. + +Defaults to C. + +=head2 $File::Fetch::DEBUG + +This enables debugging output when calling commandline utilities to +fetch files. +This also enables C errors, instead of the regular +C errors. + +Good for tracking down why things don't work with your particular +setup. + +Default is 0. + +=head2 $File::Fetch::BLACKLIST + +This is an array ref holding blacklisted modules/utilities for fetching +files with. + +To disallow the use of, for example, C and C, you could +set $File::Fetch::BLACKLIST to: + + $File::Fetch::BLACKLIST = [qw|lwp netftp|] + +The default blacklist is [qw|ftp|], as C is rather unreliable. + +See the note on C below. + +=head2 $File::Fetch::METHOD_FAIL + +This is a hashref registering what modules/utilities were known to fail +for fetching files (mostly because they weren't installed). + +You can reset this cache by assigning an empty hashref to it, or +individually remove keys. + +See the note on C below. + +=head1 MAPPING + + +Here's a quick mapping for the utilities/modules, and their names for +the $BLACKLIST, $METHOD_FAIL and other internal functions. + + LWP => lwp + HTTP::Lite => httplite + HTTP::Tiny => httptiny + Net::FTP => netftp + wget => wget + lynx => lynx + ncftp => ncftp + ftp => ftp + curl => curl + rsync => rsync + lftp => lftp + fetch => fetch + IO::Socket => iosock + +=head1 FREQUENTLY ASKED QUESTIONS + +=head2 So how do I use a proxy with File::Fetch? + +C currently only supports proxies with LWP::UserAgent. +You will need to set your environment variables accordingly. For +example, 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 can only fetch remote files by dumping its contents to C, +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 doesn't support any options to return a different exit +code on non-C<200 OK> status, giving us no way to tell the difference +between a 'successful' fetch and a custom error page. + +Therefor, we recommend to only use C 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 is relatively smart about things. When trying to write +a file to disk, it removes the C (see the +C method for details) from the file name before creating +it. In most cases this suffices. + +If you have any other characters you need to escape, please install +the C module from CPAN, and pre-encode your URI before +passing it to C. 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_BIN + +To indicate to rather use commandline tools than modules + +=back + +=head1 BUG REPORTS + +Please report bugs or other issues to Ebug-file-fetch@rt.cpan.org. + +=head1 AUTHOR + +This module by Jos Boumans Ekane@cpan.orgE. + +=head1 COPYRIGHT + +This 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: + + + + diff --git a/File-Fetch-0.42/blib/lib/auto/File/Fetch/.exists b/File-Fetch-0.42/blib/lib/auto/File/Fetch/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/blib/man1/.exists b/File-Fetch-0.42/blib/man1/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/blib/man3/.exists b/File-Fetch-0.42/blib/man3/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/blib/man3/File::Fetch.3pm b/File-Fetch-0.42/blib/man3/File::Fetch.3pm new file mode 100644 index 0000000..99e311c --- /dev/null +++ b/File-Fetch-0.42/blib/man3/File::Fetch.3pm @@ -0,0 +1,459 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.20) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "File::Fetch 3" +.TH File::Fetch 3 "2013-04-12" "perl v5.16.3" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +File::Fetch \- A generic file fetching mechanism +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& use File::Fetch; +\& +\& ### build a File::Fetch object ### +\& my $ff = File::Fetch\->new(uri => \*(Aqhttp://some.where.com/dir/a.txt\*(Aq); +\& +\& ### fetch the uri to cwd() ### +\& my $where = $ff\->fetch() or die $ff\->error; +\& +\& ### fetch the uri to /tmp ### +\& my $where = $ff\->fetch( to => \*(Aq/tmp\*(Aq ); +\& +\& ### parsed bits from the uri ### +\& $ff\->uri; +\& $ff\->scheme; +\& $ff\->host; +\& $ff\->path; +\& $ff\->file; +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +File::Fetch is a generic file fetching mechanism. +.PP +It allows you to fetch any file pointed to by a \f(CW\*(C`ftp\*(C'\fR, \f(CW\*(C`http\*(C'\fR, +\&\f(CW\*(C`file\*(C'\fR, \f(CW\*(C`git\*(C'\fR or \f(CW\*(C`rsync\*(C'\fR uri by a number of different means. +.PP +See the \f(CW\*(C`HOW IT WORKS\*(C'\fR section further down for details. +.SH "ACCESSORS" +.IX Header "ACCESSORS" +A \f(CW\*(C`File::Fetch\*(C'\fR object has the following accessors +.ie n .IP "$ff\->uri" 4 +.el .IP "\f(CW$ff\fR\->uri" 4 +.IX Item "$ff->uri" +The uri you passed to the constructor +.ie n .IP "$ff\->scheme" 4 +.el .IP "\f(CW$ff\fR\->scheme" 4 +.IX Item "$ff->scheme" +The scheme from the uri (like 'file', 'http', etc) +.ie n .IP "$ff\->host" 4 +.el .IP "\f(CW$ff\fR\->host" 4 +.IX Item "$ff->host" +The hostname in the uri. Will be empty if host was originally +\&'localhost' for a 'file://' url. +.ie n .IP "$ff\->vol" 4 +.el .IP "\f(CW$ff\fR\->vol" 4 +.IX Item "$ff->vol" +On operating systems with the concept of a volume the second element +of a file:// is considered to the be volume specification for the file. +Thus on Win32 this routine returns the volume, on other operating +systems this returns nothing. +.Sp +On Windows this value may be empty if the uri is to a network share, in +which case the 'share' property will be defined. Additionally, volume +specifications that use '|' as ':' will be converted on read to use ':'. +.Sp +On \s-1VMS\s0, which has a volume concept, this field will be empty because \s-1VMS\s0 +file specifications are converted to absolute \s-1UNIX\s0 format and the volume +information is transparently included. +.ie n .IP "$ff\->share" 4 +.el .IP "\f(CW$ff\fR\->share" 4 +.IX Item "$ff->share" +On systems with the concept of a network share (currently only Windows) returns +the sharename from a file://// url. On other operating systems returns empty. +.ie n .IP "$ff\->path" 4 +.el .IP "\f(CW$ff\fR\->path" 4 +.IX Item "$ff->path" +The path from the uri, will be at least a single '/'. +.ie n .IP "$ff\->file" 4 +.el .IP "\f(CW$ff\fR\->file" 4 +.IX Item "$ff->file" +The name of the remote file. For the local file name, the +result of \f(CW$ff\fR\->output_file will be used. +.ie n .IP "$ff\->file_default" 4 +.el .IP "\f(CW$ff\fR\->file_default" 4 +.IX Item "$ff->file_default" +The name of the default local file, that \f(CW$ff\fR\->output_file falls back to if +it would otherwise return no filename. For example when fetching a \s-1URI\s0 like +http://www.abc.net.au/ the contents retrieved may be from a remote file called +\&'index.html'. The default value of this attribute is literally 'file_default'. +.ie n .IP "$ff\->output_file" 4 +.el .IP "\f(CW$ff\fR\->output_file" 4 +.IX Item "$ff->output_file" +The name of the output file. This is the same as \f(CW$ff\fR\->file, +but any query parameters are stripped off. For example: +.Sp +.Vb 1 +\& http://example.com/index.html?x=y +.Ve +.Sp +would make the output file be \f(CW\*(C`index.html\*(C'\fR rather than +\&\f(CW\*(C`index.html?x=y\*(C'\fR. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$ff = File::Fetch\->new( uri => 'http://some.where.com/dir/file.txt' );" +.el .SS "\f(CW$ff\fP = File::Fetch\->new( uri => 'http://some.where.com/dir/file.txt' );" +.IX Subsection "$ff = File::Fetch->new( uri => 'http://some.where.com/dir/file.txt' );" +Parses the uri and creates a corresponding File::Fetch::Item object, +that is ready to be \f(CW\*(C`fetch\*(C'\fRed and returns it. +.PP +Returns false on failure. +.ie n .SS "$where = $ff\->fetch( [to => /my/output/dir/ | \e$scalar] )" +.el .SS "\f(CW$where\fP = \f(CW$ff\fP\->fetch( [to => /my/output/dir/ | \e$scalar] )" +.IX Subsection "$where = $ff->fetch( [to => /my/output/dir/ | $scalar] )" +Fetches the file you requested and returns the full path to the file. +.PP +By default it writes to \f(CW\*(C`cwd()\*(C'\fR, but you can override that by specifying +the \f(CW\*(C`to\*(C'\fR argument: +.PP +.Vb 2 +\& ### file fetch to /tmp, full path to the file in $where +\& $where = $ff\->fetch( to => \*(Aq/tmp\*(Aq ); +\& +\& ### file slurped into $scalar, full path to the file in $where +\& ### file is downloaded to a temp directory and cleaned up at exit time +\& $where = $ff\->fetch( to => \e$scalar ); +.Ve +.PP +Returns the full path to the downloaded file on success, and false +on failure. +.ie n .SS "$ff\->error([\s-1BOOL\s0])" +.el .SS "\f(CW$ff\fP\->error([\s-1BOOL\s0])" +.IX Subsection "$ff->error([BOOL])" +Returns the last encountered error as string. +Pass it a true value to get the \f(CW\*(C`Carp::longmess()\*(C'\fR output instead. +.SH "HOW IT WORKS" +.IX Header "HOW IT WORKS" +File::Fetch is able to fetch a variety of uris, by using several +external programs and modules. +.PP +Below is a mapping of what utilities will be used in what order +for what schemes, if available: +.PP +.Vb 5 +\& file => LWP, lftp, file +\& http => LWP, HTTP::Lite, wget, curl, lftp, fetch, lynx, iosock +\& ftp => LWP, Net::FTP, wget, curl, lftp, fetch, ncftp, ftp +\& rsync => rsync +\& git => git +.Ve +.PP +If you'd like to disable the use of one or more of these utilities +and/or modules, see the \f(CW$BLACKLIST\fR variable further down. +.PP +If a utility or module isn't available, it will be marked in a cache +(see the \f(CW$METHOD_FAIL\fR variable further down), so it will not be +tried again. The \f(CW\*(C`fetch\*(C'\fR method will only fail when all options are +exhausted, and it was not able to retrieve the file. +.PP +The \f(CW\*(C`fetch\*(C'\fR utility is available on FreeBSD. NetBSD and Dragonfly \s-1BSD\s0 +may also have it from \f(CW\*(C`pkgsrc\*(C'\fR. We only check for \f(CW\*(C`fetch\*(C'\fR on those +three platforms. +.PP +\&\f(CW\*(C`iosock\*(C'\fR is a very limited IO::Socket::INET based mechanism for +retrieving \f(CW\*(C`http\*(C'\fR schemed urls. It doesn't follow redirects for instance. +.PP +\&\f(CW\*(C`git\*(C'\fR only supports \f(CW\*(C`git://\*(C'\fR style urls. +.PP +A special note about fetching files from an ftp uri: +.PP +By default, all ftp connections are done in passive mode. To change +that, see the \f(CW$FTP_PASSIVE\fR variable further down. +.PP +Furthermore, ftp uris only support anonymous connections, so no +named user/password pair can be passed along. +.PP +\&\f(CW\*(C`/bin/ftp\*(C'\fR is blacklisted by default; see the \f(CW$BLACKLIST\fR variable +further down. +.SH "GLOBAL VARIABLES" +.IX Header "GLOBAL VARIABLES" +The behaviour of File::Fetch can be altered by changing the following +global variables: +.ie n .SS "$File::Fetch::FROM_EMAIL" +.el .SS "\f(CW$File::Fetch::FROM_EMAIL\fP" +.IX Subsection "$File::Fetch::FROM_EMAIL" +This is the email address that will be sent as your anonymous ftp +password. +.PP +Default is \f(CW\*(C`File\-Fetch@example.com\*(C'\fR. +.ie n .SS "$File::Fetch::USER_AGENT" +.el .SS "\f(CW$File::Fetch::USER_AGENT\fP" +.IX Subsection "$File::Fetch::USER_AGENT" +This is the useragent as \f(CW\*(C`LWP\*(C'\fR will report it. +.PP +Default is \f(CW\*(C`File::Fetch/$VERSION\*(C'\fR. +.ie n .SS "$File::Fetch::FTP_PASSIVE" +.el .SS "\f(CW$File::Fetch::FTP_PASSIVE\fP" +.IX Subsection "$File::Fetch::FTP_PASSIVE" +This variable controls whether the environment variable \f(CW\*(C`FTP_PASSIVE\*(C'\fR +and any passive switches to commandline tools will be set to true. +.PP +Default value is 1. +.PP +Note: When \f(CW$FTP_PASSIVE\fR is true, \f(CW\*(C`ncftp\*(C'\fR will not be used to fetch +files, since passive mode can only be set interactively for this binary +.ie n .SS "$File::Fetch::TIMEOUT" +.el .SS "\f(CW$File::Fetch::TIMEOUT\fP" +.IX Subsection "$File::Fetch::TIMEOUT" +When set, controls the network timeout (counted in seconds). +.PP +Default value is 0. +.ie n .SS "$File::Fetch::WARN" +.el .SS "\f(CW$File::Fetch::WARN\fP" +.IX Subsection "$File::Fetch::WARN" +This variable controls whether errors encountered internally by +\&\f(CW\*(C`File::Fetch\*(C'\fR should be \f(CW\*(C`carp\*(C'\fR'd or not. +.PP +Set to false to silence warnings. Inspect the output of the \f(CW\*(C`error()\*(C'\fR +method manually to see what went wrong. +.PP +Defaults to \f(CW\*(C`true\*(C'\fR. +.ie n .SS "$File::Fetch::DEBUG" +.el .SS "\f(CW$File::Fetch::DEBUG\fP" +.IX Subsection "$File::Fetch::DEBUG" +This enables debugging output when calling commandline utilities to +fetch files. +This also enables \f(CW\*(C`Carp::longmess\*(C'\fR errors, instead of the regular +\&\f(CW\*(C`carp\*(C'\fR errors. +.PP +Good for tracking down why things don't work with your particular +setup. +.PP +Default is 0. +.ie n .SS "$File::Fetch::BLACKLIST" +.el .SS "\f(CW$File::Fetch::BLACKLIST\fP" +.IX Subsection "$File::Fetch::BLACKLIST" +This is an array ref holding blacklisted modules/utilities for fetching +files with. +.PP +To disallow the use of, for example, \f(CW\*(C`LWP\*(C'\fR and \f(CW\*(C`Net::FTP\*(C'\fR, you could +set \f(CW$File::Fetch::BLACKLIST\fR to: +.PP +.Vb 1 +\& $File::Fetch::BLACKLIST = [qw|lwp netftp|] +.Ve +.PP +The default blacklist is [qw|ftp|], as \f(CW\*(C`/bin/ftp\*(C'\fR is rather unreliable. +.PP +See the note on \f(CW\*(C`MAPPING\*(C'\fR below. +.ie n .SS "$File::Fetch::METHOD_FAIL" +.el .SS "\f(CW$File::Fetch::METHOD_FAIL\fP" +.IX Subsection "$File::Fetch::METHOD_FAIL" +This is a hashref registering what modules/utilities were known to fail +for fetching files (mostly because they weren't installed). +.PP +You can reset this cache by assigning an empty hashref to it, or +individually remove keys. +.PP +See the note on \f(CW\*(C`MAPPING\*(C'\fR below. +.SH "MAPPING" +.IX Header "MAPPING" +Here's a quick mapping for the utilities/modules, and their names for +the \f(CW$BLACKLIST\fR, \f(CW$METHOD_FAIL\fR and other internal functions. +.PP +.Vb 10 +\& LWP => lwp +\& HTTP::Lite => httplite +\& HTTP::Tiny => httptiny +\& Net::FTP => netftp +\& wget => wget +\& lynx => lynx +\& ncftp => ncftp +\& ftp => ftp +\& curl => curl +\& rsync => rsync +\& lftp => lftp +\& fetch => fetch +\& IO::Socket => iosock +.Ve +.SH "FREQUENTLY ASKED QUESTIONS" +.IX Header "FREQUENTLY ASKED QUESTIONS" +.SS "So how do I use a proxy with File::Fetch?" +.IX Subsection "So how do I use a proxy with File::Fetch?" +\&\f(CW\*(C`File::Fetch\*(C'\fR currently only supports proxies with LWP::UserAgent. +You will need to set your environment variables accordingly. For +example, to use an ftp proxy: +.PP +.Vb 1 +\& $ENV{ftp_proxy} = \*(Aqfoo.com\*(Aq; +.Ve +.PP +Refer to the LWP::UserAgent manpage for more details. +.SS "I used 'lynx' to fetch a file, but its contents is all wrong!" +.IX Subsection "I used 'lynx' to fetch a file, but its contents is all wrong!" +\&\f(CW\*(C`lynx\*(C'\fR can only fetch remote files by dumping its contents to \f(CW\*(C`STDOUT\*(C'\fR, +which we in turn capture. If that content is a 'custom' error file +(like, say, a \f(CW\*(C`404 handler\*(C'\fR), you will get that contents instead. +.PP +Sadly, \f(CW\*(C`lynx\*(C'\fR doesn't support any options to return a different exit +code on non\-\f(CW\*(C`200 OK\*(C'\fR status, giving us no way to tell the difference +between a 'successful' fetch and a custom error page. +.PP +Therefor, we recommend to only use \f(CW\*(C`lynx\*(C'\fR as a last resort. This is +why it is at the back of our list of methods to try as well. +.SS "Files I'm trying to fetch have reserved characters or non-ASCII characters in them. What do I do?" +.IX Subsection "Files I'm trying to fetch have reserved characters or non-ASCII characters in them. What do I do?" +\&\f(CW\*(C`File::Fetch\*(C'\fR is relatively smart about things. When trying to write +a file to disk, it removes the \f(CW\*(C`query parameters\*(C'\fR (see the +\&\f(CW\*(C`output_file\*(C'\fR method for details) from the file name before creating +it. In most cases this suffices. +.PP +If you have any other characters you need to escape, please install +the \f(CW\*(C`URI::Escape\*(C'\fR module from \s-1CPAN\s0, and pre-encode your \s-1URI\s0 before +passing it to \f(CW\*(C`File::Fetch\*(C'\fR. You can read about the details of URIs +and \s-1URI\s0 encoding here: +.PP +.Vb 1 +\& http://www.faqs.org/rfcs/rfc2396.html +.Ve +.SH "TODO" +.IX Header "TODO" +.ie n .IP "Implement $PREFER_BIN" 4 +.el .IP "Implement \f(CW$PREFER_BIN\fR" 4 +.IX Item "Implement $PREFER_BIN" +To indicate to rather use commandline tools than modules +.SH "BUG REPORTS" +.IX Header "BUG REPORTS" +Please report bugs or other issues to . +.SH "AUTHOR" +.IX Header "AUTHOR" +This module by Jos Boumans . +.SH "COPYRIGHT" +.IX Header "COPYRIGHT" +This library is free software; you may redistribute and/or modify it +under the same terms as Perl itself. diff --git a/File-Fetch-0.42/blib/script/.exists b/File-Fetch-0.42/blib/script/.exists new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/debugfiles.list b/File-Fetch-0.42/debugfiles.list new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/debuglinks.list b/File-Fetch-0.42/debuglinks.list new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/debugsources.list b/File-Fetch-0.42/debugsources.list new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/lib/File/Fetch.pm b/File-Fetch-0.42/lib/File/Fetch.pm new file mode 100644 index 0000000..75e42c6 --- /dev/null +++ b/File-Fetch-0.42/lib/File/Fetch.pm @@ -0,0 +1,1708 @@ +package File::Fetch; + +use strict; +use FileHandle; +use File::Temp; +use File::Copy; +use File::Spec; +use File::Spec::Unix; +use File::Basename qw[dirname]; + +use Cwd qw[cwd]; +use Carp qw[carp]; +use IPC::Cmd qw[can_run run QUOTE]; +use File::Path qw[mkpath]; +use File::Temp qw[tempdir]; +use Params::Check qw[check]; +use Module::Load::Conditional qw[can_load]; +use Locale::Maketext::Simple Style => 'gettext'; + +use vars qw[ $VERBOSE $PREFER_BIN $FROM_EMAIL $USER_AGENT + $BLACKLIST $METHOD_FAIL $VERSION $METHODS + $FTP_PASSIVE $TIMEOUT $DEBUG $WARN + ]; + +$VERSION = '0.42'; +$VERSION = eval $VERSION; # avoid warnings with development releases +$PREFER_BIN = 0; # XXX TODO implement +$FROM_EMAIL = 'File-Fetch@example.com'; +$USER_AGENT = "File::Fetch/$VERSION"; +$BLACKLIST = [qw|ftp|]; +$METHOD_FAIL = { }; +$FTP_PASSIVE = 1; +$TIMEOUT = 0; +$DEBUG = 0; +$WARN = 1; + +### methods available to fetch the file depending on the scheme +$METHODS = { + http => [ qw|lwp httptiny wget curl lftp fetch httplite lynx iosock| ], + ftp => [ qw|lwp netftp wget curl lftp fetch ncftp ftp| ], + file => [ qw|lwp lftp file| ], + rsync => [ qw|rsync| ], + git => [ qw|git| ], +}; + +### silly warnings ### +local $Params::Check::VERBOSE = 1; +local $Params::Check::VERBOSE = 1; +local $Module::Load::Conditional::VERBOSE = 0; +local $Module::Load::Conditional::VERBOSE = 0; + +### see what OS we are on, important for file:// uris ### +use constant ON_WIN => ($^O eq 'MSWin32'); +use constant ON_VMS => ($^O eq 'VMS'); +use constant ON_UNIX => (!ON_WIN); +use constant HAS_VOL => (ON_WIN); +use constant HAS_SHARE => (ON_WIN); +use constant HAS_FETCH => ( $^O =~ m!^(freebsd|netbsd|dragonfly)$! ); + +=pod + +=head1 NAME + +File::Fetch - A generic file fetching mechanism + +=head1 SYNOPSIS + + use File::Fetch; + + ### build a File::Fetch object ### + my $ff = File::Fetch->new(uri => 'http://some.where.com/dir/a.txt'); + + ### fetch the uri to cwd() ### + my $where = $ff->fetch() or die $ff->error; + + ### fetch the uri to /tmp ### + my $where = $ff->fetch( to => '/tmp' ); + + ### parsed bits from the uri ### + $ff->uri; + $ff->scheme; + $ff->host; + $ff->path; + $ff->file; + +=head1 DESCRIPTION + +File::Fetch is a generic file fetching mechanism. + +It allows you to fetch any file pointed to by a C, C, +C, C or C uri by a number of different means. + +See the C section further down for details. + +=head1 ACCESSORS + +A C object has the following accessors + +=over 4 + +=item $ff->uri + +The uri you passed to the constructor + +=item $ff->scheme + +The scheme from the uri (like 'file', 'http', etc) + +=item $ff->host + +The hostname in the uri. Will be empty if host was originally +'localhost' for a 'file://' url. + +=item $ff->vol + +On operating systems with the concept of a volume the second element +of a file:// is considered to the be volume specification for the file. +Thus on Win32 this routine returns the volume, on other operating +systems this returns nothing. + +On Windows this value may be empty if the uri is to a network share, in +which case the 'share' property will be defined. Additionally, volume +specifications that use '|' as ':' will be converted on read to use ':'. + +On VMS, which has a volume concept, this field will be empty because VMS +file specifications are converted to absolute UNIX format and the volume +information is transparently included. + +=item $ff->share + +On systems with the concept of a network share (currently only Windows) returns +the sharename from a file://// url. On other operating systems returns empty. + +=item $ff->path + +The path from the uri, will be at least a single '/'. + +=item $ff->file + +The name of the remote file. For the local file name, the +result of $ff->output_file will be used. + +=item $ff->file_default + +The name of the default local file, that $ff->output_file falls back to if +it would otherwise return no filename. For example when fetching a URI like +http://www.abc.net.au/ the contents retrieved may be from a remote file called +'index.html'. The default value of this attribute is literally 'file_default'. + +=cut + + +########################## +### Object & Accessors ### +########################## + +{ + ### template for autogenerated accessors ### + my $Tmpl = { + scheme => { default => 'http' }, + host => { default => 'localhost' }, + path => { default => '/' }, + file => { required => 1 }, + uri => { required => 1 }, + vol => { default => '' }, # windows for file:// uris + share => { default => '' }, # windows for file:// uris + file_default => { default => 'file_default' }, + tempdir_root => { required => 1 }, # Should be lazy-set at ->new() + _error_msg => { no_override => 1 }, + _error_msg_long => { no_override => 1 }, + }; + + for my $method ( keys %$Tmpl ) { + no strict 'refs'; + *$method = sub { + my $self = shift; + $self->{$method} = $_[0] if @_; + return $self->{$method}; + } + } + + sub _create { + my $class = shift; + my %hash = @_; + + my $args = check( $Tmpl, \%hash ) or return; + + bless $args, $class; + + if( lc($args->scheme) ne 'file' and not $args->host ) { + return $class->_error(loc( + "Hostname required when fetching from '%1'",$args->scheme)); + } + + for (qw[path]) { + unless( $args->$_() ) { # 5.5.x needs the () + return $class->_error(loc("No '%1' specified",$_)); + } + } + + return $args; + } +} + +=item $ff->output_file + +The name of the output file. This is the same as $ff->file, +but any query parameters are stripped off. For example: + + http://example.com/index.html?x=y + +would make the output file be C rather than +C. + +=back + +=cut + +sub output_file { + my $self = shift; + my $file = $self->file; + + $file =~ s/\?.*$//g; + + $file ||= $self->file_default; + + return $file; +} + +### XXX do this or just point to URI::Escape? +# =head2 $esc_uri = $ff->escaped_uri +# +# =cut +# +# ### most of this is stolen straight from URI::escape +# { ### Build a char->hex map +# my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255; +# +# sub escaped_uri { +# my $self = shift; +# my $uri = $self->uri; +# +# ### Default unsafe characters. RFC 2732 ^(uric - reserved) +# $uri =~ s/([^A-Za-z0-9\-_.!~*'()])/ +# $escapes{$1} || $self->_fail_hi($1)/ge; +# +# return $uri; +# } +# +# sub _fail_hi { +# my $self = shift; +# my $char = shift; +# +# $self->_error(loc( +# "Can't escape '%1', try using the '%2' module instead", +# sprintf("\\x{%04X}", ord($char)), 'URI::Escape' +# )); +# } +# +# sub output_file { +# +# } +# +# +# } + +=head1 METHODS + +=head2 $ff = File::Fetch->new( uri => 'http://some.where.com/dir/file.txt' ); + +Parses the uri and creates a corresponding File::Fetch::Item object, +that is ready to be Ced and returns it. + +Returns false on failure. + +=cut + +sub new { + my $class = shift; + my %hash = @_; + + my ($uri, $file_default, $tempdir_root); + my $tmpl = { + uri => { required => 1, store => \$uri }, + file_default => { required => 0, store => \$file_default }, + tempdir_root => { required => 0, store => \$tempdir_root }, + }; + + check( $tmpl, \%hash ) or return; + + ### parse the uri to usable parts ### + my $href = $class->_parse_uri( $uri ) or return; + + $href->{file_default} = $file_default if $file_default; + $href->{tempdir_root} = File::Spec->rel2abs( $tempdir_root ) if $tempdir_root; + $href->{tempdir_root} = File::Spec->rel2abs( Cwd::cwd ) if not $href->{tempdir_root}; + + ### make it into a FFI object ### + my $ff = $class->_create( %$href ) or return; + + + ### return the object ### + return $ff; +} + +### parses an uri to a hash structure: +### +### $class->_parse_uri( 'ftp://ftp.cpan.org/pub/mirror/index.txt' ) +### +### becomes: +### +### $href = { +### scheme => 'ftp', +### host => 'ftp.cpan.org', +### path => '/pub/mirror', +### file => 'index.html' +### }; +### +### In the case of file:// urls there maybe be additional fields +### +### For systems with volume specifications such as Win32 there will be +### a volume specifier provided in the 'vol' field. +### +### 'vol' => 'volumename' +### +### For windows file shares there may be a 'share' key specified +### +### 'share' => 'sharename' +### +### Note that the rules of what a file:// url means vary by the operating system +### of the host being addressed. Thus file:///d|/foo/bar.txt means the obvious +### 'D:\foo\bar.txt' on windows, but on unix it means '/d|/foo/bar.txt' and +### not '/foo/bar.txt' +### +### Similarly if the host interpreting the url is VMS then +### file:///disk$user/my/notes/note12345.txt' means +### 'DISK$USER:[MY.NOTES]NOTE123456.TXT' but will be returned the same as +### if it is unix where it means /disk$user/my/notes/note12345.txt'. +### Except for some cases in the File::Spec methods, Perl on VMS will generally +### handle UNIX format file specifications. +### +### This means it is impossible to serve certain file:// urls on certain systems. +### +### Thus are the problems with a protocol-less specification. :-( +### + +sub _parse_uri { + my $self = shift; + my $uri = shift or return; + + my $href = { uri => $uri }; + + ### find the scheme ### + $uri =~ s|^(\w+)://||; + $href->{scheme} = $1; + + ### See rfc 1738 section 3.10 + ### http://www.faqs.org/rfcs/rfc1738.html + ### And wikipedia for more on windows file:// urls + ### http://en.wikipedia.org/wiki/File:// + if( $href->{scheme} eq 'file' ) { + + my @parts = split '/',$uri; + + ### file://hostname/... + ### file://hostname/... + ### normalize file://localhost with file:/// + $href->{host} = $parts[0] || ''; + + ### index in @parts where the path components begin; + my $index = 1; + + ### file:////hostname/sharename/blah.txt + if ( HAS_SHARE and not length $parts[0] and not length $parts[1] ) { + + $href->{host} = $parts[2] || ''; # avoid warnings + $href->{share} = $parts[3] || ''; # avoid warnings + + $index = 4 # index after the share + + ### file:///D|/blah.txt + ### file:///D:/blah.txt + } elsif (HAS_VOL) { + + ### this code comes from dmq's patch, but: + ### XXX if volume is empty, wouldn't that be an error? --kane + ### if so, our file://localhost test needs to be fixed as wel + $href->{vol} = $parts[1] || ''; + + ### correct D| style colume descriptors + $href->{vol} =~ s/\A([A-Z])\|\z/$1:/i if ON_WIN; + + $index = 2; # index after the volume + } + + ### rebuild the path from the leftover parts; + $href->{path} = join '/', '', splice( @parts, $index, $#parts ); + + } else { + ### using anything but qw() in hash slices may produce warnings + ### in older perls :-( + @{$href}{ qw(host path) } = $uri =~ m|([^/]*)(/.*)$|s; + } + + ### split the path into file + dir ### + { my @parts = File::Spec::Unix->splitpath( delete $href->{path} ); + $href->{path} = $parts[1]; + $href->{file} = $parts[2]; + } + + ### host will be empty if the target was 'localhost' and the + ### scheme was 'file' + $href->{host} = '' if ($href->{host} eq 'localhost') and + ($href->{scheme} eq 'file'); + + return $href; +} + +=head2 $where = $ff->fetch( [to => /my/output/dir/ | \$scalar] ) + +Fetches the file you requested and returns the full path to the file. + +By default it writes to C, but you can override that by specifying +the C argument: + + ### file fetch to /tmp, full path to the file in $where + $where = $ff->fetch( to => '/tmp' ); + + ### file slurped into $scalar, full path to the file in $where + ### file is downloaded to a temp directory and cleaned up at exit time + $where = $ff->fetch( to => \$scalar ); + +Returns the full path to the downloaded file on success, and false +on failure. + +=cut + +sub fetch { + my $self = shift or return; + my %hash = @_; + + my $target; + my $tmpl = { + to => { default => cwd(), store => \$target }, + }; + + check( $tmpl, \%hash ) or return; + + my ($to, $fh); + ### you want us to slurp the contents + if( ref $target and UNIVERSAL::isa( $target, 'SCALAR' ) ) { + $to = tempdir( 'FileFetch.XXXXXX', DIR => $self->tempdir_root, CLEANUP => 1 ); + + ### plain old fetch + } else { + $to = $target; + + ### On VMS force to VMS format so File::Spec will work. + $to = VMS::Filespec::vmspath($to) if ON_VMS; + + ### create the path if it doesn't exist yet ### + unless( -d $to ) { + eval { mkpath( $to ) }; + + return $self->_error(loc("Could not create path '%1'",$to)) if $@; + } + } + + ### set passive ftp if required ### + local $ENV{FTP_PASSIVE} = $FTP_PASSIVE; + + ### we dont use catfile on win32 because if we are using a cygwin tool + ### under cmd.exe they wont understand windows style separators. + my $out_to = ON_WIN ? $to.'/'.$self->output_file + : File::Spec->catfile( $to, $self->output_file ); + + for my $method ( @{ $METHODS->{$self->scheme} } ) { + my $sub = '_'.$method.'_fetch'; + + unless( __PACKAGE__->can($sub) ) { + $self->_error(loc("Cannot call method for '%1' -- WEIRD!", + $method)); + next; + } + + ### method is blacklisted ### + next if grep { lc $_ eq $method } @$BLACKLIST; + + ### method is known to fail ### + next if $METHOD_FAIL->{$method}; + + ### there's serious issues with IPC::Run and quoting of command + ### line arguments. using quotes in the wrong place breaks things, + ### and in the case of say, + ### C:\cygwin\bin\wget.EXE --quiet --passive-ftp --output-document + ### "index.html" "http://www.cpan.org/index.html?q=1&y=2" + ### it doesn't matter how you quote, it always fails. + local $IPC::Cmd::USE_IPC_RUN = 0; + + if( my $file = $self->$sub( + to => $out_to + )){ + + unless( -e $file && -s _ ) { + $self->_error(loc("'%1' said it fetched '%2', ". + "but it was not created",$method,$file)); + + ### mark the failure ### + $METHOD_FAIL->{$method} = 1; + + next; + + } else { + + ### slurp mode? + if( ref $target and UNIVERSAL::isa( $target, 'SCALAR' ) ) { + + ### open the file + open my $fh, "<$file" or do { + $self->_error( + loc("Could not open '%1': %2", $file, $!)); + return; + }; + + ### slurp + $$target = do { local $/; <$fh> }; + + } + + my $abs = File::Spec->rel2abs( $file ); + return $abs; + + } + } + } + + + ### if we got here, we looped over all methods, but we weren't able + ### to fetch it. + return; +} + +######################## +### _*_fetch methods ### +######################## + +### LWP fetching ### +sub _lwp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### modules required to download with lwp ### + my $use_list = { + LWP => '0.0', + 'LWP::UserAgent' => '0.0', + 'HTTP::Request' => '0.0', + 'HTTP::Status' => '0.0', + URI => '0.0', + + }; + + unless( can_load( modules => $use_list ) ) { + $METHOD_FAIL->{'lwp'} = 1; + return; + } + + ### setup the uri object + my $uri = URI->new( File::Spec::Unix->catfile( + $self->path, $self->file + ) ); + + ### special rules apply for file:// uris ### + $uri->scheme( $self->scheme ); + $uri->host( $self->scheme eq 'file' ? '' : $self->host ); + $uri->userinfo("anonymous:$FROM_EMAIL") if $self->scheme ne 'file'; + + ### set up the useragent object + my $ua = LWP::UserAgent->new(); + $ua->timeout( $TIMEOUT ) if $TIMEOUT; + $ua->agent( $USER_AGENT ); + $ua->from( $FROM_EMAIL ); + $ua->env_proxy; + + my $res = $ua->mirror($uri, $to) or return; + + ### uptodate or fetched ok ### + if ( $res->code == 304 or $res->code == 200 ) { + return $to; + + } else { + return $self->_error(loc("Fetch failed! HTTP response: %1 %2 [%3]", + $res->code, HTTP::Status::status_message($res->code), + $res->status_line)); + } + +} + +### HTTP::Tiny fetching ### +sub _httptiny_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $use_list = { + 'HTTP::Tiny' => '0.008', + + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'httptiny'} = 1; + return; + } + + my $uri = $self->uri; + + my $http = HTTP::Tiny->new( ( $TIMEOUT ? ( timeout => $TIMEOUT ) : () ) ); + + my $rc = $http->mirror( $uri, $to ); + + unless ( $rc->{success} ) { + + return $self->_error(loc( "Fetch failed! HTTP response: %1 [%2]", + $rc->{status}, $rc->{reason} ) ); + + } + + return $to; + +} + +### HTTP::Lite fetching ### +sub _httplite_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### modules required to download with lwp ### + my $use_list = { + 'HTTP::Lite' => '2.2', + + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'httplite'} = 1; + return; + } + + my $uri = $self->uri; + my $retries = 0; + + RETRIES: while ( $retries++ < 5 ) { + + my $http = HTTP::Lite->new(); + # Naughty naughty but there isn't any accessor/setter + $http->{timeout} = $TIMEOUT if $TIMEOUT; + $http->http11_mode(1); + + my $fh = FileHandle->new; + + unless ( $fh->open($to,'>') ) { + return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + } + + $fh->autoflush(1); + + binmode $fh; + + my $rc = $http->request( $uri, sub { my ($self,$dref,$cbargs) = @_; local $\; print {$cbargs} $$dref }, $fh ); + + close $fh; + + if ( $rc == 301 || $rc == 302 ) { + my $loc; + HEADERS: for ($http->headers_array) { + /Location: (\S+)/ and $loc = $1, last HEADERS; + } + #$loc or last; # Think we should squeal here. + if ($loc =~ m!^/!) { + $uri =~ s{^(\w+?://[^/]+)/.*$}{$1}; + $uri .= $loc; + } + else { + $uri = $loc; + } + next RETRIES; + } + elsif ( $rc == 200 ) { + return $to; + } + else { + return $self->_error(loc("Fetch failed! HTTP response: %1 [%2]", + $rc, $http->status_message)); + } + + } # Loop for 5 retries. + + return $self->_error("Fetch failed! Gave up after 5 tries"); + +} + +### Simple IO::Socket::INET fetching ### +sub _iosock_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $use_list = { + 'IO::Socket::INET' => '0.0', + 'IO::Select' => '0.0', + }; + + unless( can_load(modules => $use_list) ) { + $METHOD_FAIL->{'iosock'} = 1; + return; + } + + my $sock = IO::Socket::INET->new( + PeerHost => $self->host, + ( $self->host =~ /:/ ? () : ( PeerPort => 80 ) ), + ); + + unless ( $sock ) { + return $self->_error(loc("Could not open socket to '%1', '%2'",$self->host,$!)); + } + + my $fh = FileHandle->new; + + # Check open() + + unless ( $fh->open($to,'>') ) { + return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + } + + $fh->autoflush(1); + binmode $fh; + + my $path = File::Spec::Unix->catfile( $self->path, $self->file ); + my $req = "GET $path HTTP/1.0\x0d\x0aHost: " . $self->host . "\x0d\x0a\x0d\x0a"; + $sock->send( $req ); + + my $select = IO::Select->new( $sock ); + + my $resp = ''; + my $normal = 0; + while ( $select->can_read( $TIMEOUT || 60 ) ) { + my $ret = $sock->sysread( $resp, 4096, length($resp) ); + if ( !defined $ret or $ret == 0 ) { + $select->remove( $sock ); + $normal++; + } + } + close $sock; + + unless ( $normal ) { + return $self->_error(loc("Socket timed out after '%1' seconds", ( $TIMEOUT || 60 ))); + } + + # Check the "response" + # Strip preceding blank lines apparently they are allowed (RFC 2616 4.1) + $resp =~ s/^(\x0d?\x0a)+//; + # Check it is an HTTP response + unless ( $resp =~ m!^HTTP/(\d+)\.(\d+)!i ) { + return $self->_error(loc("Did not get a HTTP response from '%1'",$self->host)); + } + + # Check for OK + my ($code) = $resp =~ m!^HTTP/\d+\.\d+\s+(\d+)!i; + unless ( $code eq '200' ) { + return $self->_error(loc("Got a '%1' from '%2' expected '200'",$code,$self->host)); + } + + { + local $\; + print $fh +($resp =~ m/\x0d\x0a\x0d\x0a(.*)$/s )[0]; + } + close $fh; + return $to; +} + +### Net::FTP fetching +sub _netftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### required modules ### + my $use_list = { 'Net::FTP' => 0 }; + + unless( can_load( modules => $use_list ) ) { + $METHOD_FAIL->{'netftp'} = 1; + return; + } + + ### make connection ### + my $ftp; + my @options = ($self->host); + push(@options, Timeout => $TIMEOUT) if $TIMEOUT; + unless( $ftp = Net::FTP->new( @options ) ) { + return $self->_error(loc("Ftp creation failed: %1",$@)); + } + + ### login ### + unless( $ftp->login( anonymous => $FROM_EMAIL ) ) { + return $self->_error(loc("Could not login to '%1'",$self->host)); + } + + ### set binary mode, just in case ### + $ftp->binary; + + ### create the remote path + ### remember remote paths are unix paths! [#11483] + my $remote = File::Spec::Unix->catfile( $self->path, $self->file ); + + ### fetch the file ### + my $target; + unless( $target = $ftp->get( $remote, $to ) ) { + return $self->_error(loc("Could not fetch '%1' from '%2'", + $remote, $self->host)); + } + + ### log out ### + $ftp->quit; + + return $target; + +} + +### /bin/wget fetch ### +sub _wget_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + my $wget; + ### see if we have a wget binary ### + unless( $wget = can_run('wget') ) { + $METHOD_FAIL->{'wget'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $wget, '--quiet' ]; + + ### if a timeout is set, add it ### + push(@$cmd, '--timeout=' . $TIMEOUT) if $TIMEOUT; + + ### run passive if specified ### + push @$cmd, '--passive-ftp' if $FTP_PASSIVE; + + ### set the output document, add the uri ### + push @$cmd, '--output-document', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + +### /bin/lftp fetch ### +sub _lftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a lftp binary ### + my $lftp; + unless( $lftp = can_run('lftp') ) { + $METHOD_FAIL->{'lftp'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $lftp, '-f' ]; + + my $fh = File::Temp->new; + + my $str; + + ### if a timeout is set, add it ### + $str .= "set net:timeout $TIMEOUT;\n" if $TIMEOUT; + + ### run passive if specified ### + $str .= "set ftp:passive-mode 1;\n" if $FTP_PASSIVE; + + ### set the output document, add the uri ### + ### quote the URI, because lftp supports certain shell + ### expansions, most notably & for backgrounding. + ### ' quote does nto work, must be " + $str .= q[get ']. $self->uri .q[' -o ]. $to . $/; + + if( $DEBUG ) { + my $pp_str = join ' ', split $/, $str; + print "# lftp command: $pp_str\n"; + } + + ### write straight to the file. + $fh->autoflush(1); + print $fh $str; + + ### the command needs to be 1 string to be executed + push @$cmd, $fh->filename; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + + + +### /bin/ftp fetch ### +sub _ftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a ftp binary ### + my $ftp; + unless( $ftp = can_run('ftp') ) { + $METHOD_FAIL->{'ftp'} = 1; + return; + } + + my $fh = FileHandle->new; + + local $SIG{CHLD} = 'IGNORE'; + + unless ($fh->open("$ftp -n", '|-')) { + return $self->_error(loc("%1 creation failed: %2", $ftp, $!)); + } + + my @dialog = ( + "lcd " . dirname($to), + "open " . $self->host, + "user anonymous $FROM_EMAIL", + "cd /", + "cd " . $self->path, + "binary", + "get " . $self->file . " " . $self->output_file, + "quit", + ); + + foreach (@dialog) { $fh->print($_, "\n") } + $fh->close or return; + + return $to; +} + +### lynx is stupid - it decompresses any .gz file it finds to be text +### use /bin/lynx to fetch files +sub _lynx_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a lynx binary ### + my $lynx; + unless ( $lynx = can_run('lynx') ){ + $METHOD_FAIL->{'lynx'} = 1; + return; + } + + unless( IPC::Cmd->can_capture_buffer ) { + $METHOD_FAIL->{'lynx'} = 1; + + return $self->_error(loc( + "Can not capture buffers. Can not use '%1' to fetch files", + 'lynx' )); + } + + ### check if the HTTP resource exists ### + if ($self->uri =~ /^https?:\/\//i) { + my $cmd = [ + $lynx, + '-head', + '-source', + "-auth=anonymous:$FROM_EMAIL", + ]; + + push @$cmd, "-connect_timeout=$TIMEOUT" if $TIMEOUT; + + push @$cmd, $self->uri; + + ### shell out ### + my $head; + unless(run( command => $cmd, + buffer => \$head, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $head || '')); + } + + unless($head =~ /^HTTP\/\d+\.\d+ 200\b/) { + return $self->_error(loc("Command failed: %1", $head || '')); + } + } + + ### write to the output file ourselves, since lynx ass_u_mes to much + my $local = FileHandle->new( $to, 'w' ) + or return $self->_error(loc( + "Could not open '%1' for writing: %2",$to,$!)); + + ### dump to stdout ### + my $cmd = [ + $lynx, + '-source', + "-auth=anonymous:$FROM_EMAIL", + ]; + + push @$cmd, "-connect_timeout=$TIMEOUT" if $TIMEOUT; + + ### DO NOT quote things for IPC::Run, it breaks stuff. + push @$cmd, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### DO NOT quote things for IPC::Run, it breaks stuff. + # $IPC::Cmd::USE_IPC_RUN + # ? $self->uri + # : QUOTE. $self->uri .QUOTE; + + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $captured || '')); + } + + ### print to local file ### + ### XXX on a 404 with a special error page, $captured will actually + ### hold the contents of that page, and make it *appear* like the + ### request was a success, when really it wasn't :( + ### there doesn't seem to be an option for lynx to change the exit + ### code based on a 4XX status or so. + ### the closest we can come is using --error_file and parsing that, + ### which is very unreliable ;( + $local->print( $captured ); + $local->close or return; + + return $to; +} + +### use /bin/ncftp to fetch files +sub _ncftp_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### we can only set passive mode in interactive sessions, so bail out + ### if $FTP_PASSIVE is set + return if $FTP_PASSIVE; + + ### see if we have a ncftp binary ### + my $ncftp; + unless( $ncftp = can_run('ncftp') ) { + $METHOD_FAIL->{'ncftp'} = 1; + return; + } + + my $cmd = [ + $ncftp, + '-V', # do not be verbose + '-p', $FROM_EMAIL, # email as password + $self->host, # hostname + dirname($to), # local dir for the file + # remote path to the file + ### DO NOT quote things for IPC::Run, it breaks stuff. + $IPC::Cmd::USE_IPC_RUN + ? File::Spec::Unix->catdir( $self->path, $self->file ) + : QUOTE. File::Spec::Unix->catdir( + $self->path, $self->file ) .QUOTE + + ]; + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG ) + ) { + return $self->_error(loc("Command failed: %1", $captured || '')); + } + + return $to; + +} + +### use /bin/curl to fetch files +sub _curl_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $curl; + unless ( $curl = can_run('curl') ) { + $METHOD_FAIL->{'curl'} = 1; + return; + } + + ### these long opts are self explanatory - I like that -jmb + my $cmd = [ $curl, '-q' ]; + + 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', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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; + +} + +### /usr/bin/fetch fetch! ### +sub _fetch_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + + ### see if we have a fetch binary ### + my $fetch; + unless( HAS_FETCH and $fetch = can_run('fetch') ) { + $METHOD_FAIL->{'fetch'} = 1; + return; + } + + ### no verboseness, thanks ### + my $cmd = [ $fetch, '-q' ]; + + ### if a timeout is set, add it ### + push(@$cmd, '-T', $TIMEOUT) if $TIMEOUT; + + ### run passive if specified ### + #push @$cmd, '-p' if $FTP_PASSIVE; + local $ENV{'FTP_PASSIVE_MODE'} = 1 if $FTP_PASSIVE; + + ### set the output document, add the uri ### + push @$cmd, '-o', $to, $self->uri; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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); + + ### shell out ### + my $captured; + unless(run( command => $cmd, + buffer => \$captured, + verbose => $DEBUG + )) { + ### wget creates the output document always, even if the fetch + ### fails.. so unlink it in that case + 1 while unlink $to; + + return $self->_error(loc( "Command failed: %1", $captured || '' )); + } + + return $to; +} + +### 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 + ### whereas 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 files +sub _rsync_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $rsync; + unless ( $rsync = can_run('rsync') ) { + $METHOD_FAIL->{'rsync'} = 1; + return; + } + + 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, $self->uri, $to; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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 %1 failed: %2", + "@$cmd" || '', $captured || '')); + } + + return $to; + +} + +### use git to fetch files +sub _git_fetch { + my $self = shift; + my %hash = @_; + + my ($to); + my $tmpl = { + to => { required => 1, store => \$to } + }; + check( $tmpl, \%hash ) or return; + my $git; + unless ( $git = can_run('git') ) { + $METHOD_FAIL->{'git'} = 1; + return; + } + + my $cmd = [ $git, 'clone' ]; + + #push(@$cmd, '--timeout=' . $TIMEOUT) if $TIMEOUT; + + push(@$cmd, '--quiet') unless $DEBUG; + + ### DO NOT quote things for IPC::Run, it breaks stuff. + push @$cmd, $self->uri, $to; + + ### with IPC::Cmd > 0.41, this is fixed in teh library, + ### and there's no need for special casing any more. + ### 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 %1 failed: %2", + "@$cmd" || '', $captured || '')); + } + + return $to; + +} + +################################# +# +# Error code +# +################################# + +=pod + +=head2 $ff->error([BOOL]) + +Returns the last encountered error as string. +Pass it a true value to get the C output instead. + +=cut + +### error handling the way Archive::Extract does it +sub _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 WORKS + +File::Fetch is able to fetch a variety of uris, by using several +external programs and modules. + +Below is a mapping of what utilities will be used in what order +for what schemes, if available: + + file => LWP, lftp, file + http => LWP, HTTP::Lite, wget, curl, lftp, fetch, lynx, iosock + ftp => LWP, Net::FTP, wget, curl, lftp, fetch, ncftp, ftp + rsync => rsync + git => git + +If you'd like to disable the use of one or more of these utilities +and/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 be +tried again. The C method will only fail when all options are +exhausted, and it was not able to retrieve the file. + +The C utility is available on FreeBSD. NetBSD and Dragonfly BSD +may also have it from C. We only check for C on those +three platforms. + +C is a very limited L based mechanism for +retrieving C schemed urls. It doesn't follow redirects for instance. + +C only supports C style urls. + +A special note about fetching files from an ftp uri: + +By default, all ftp connections are done in passive mode. To change +that, see the C<$FTP_PASSIVE> variable further down. + +Furthermore, ftp uris only support anonymous connections, so no +named user/password pair can be passed along. + +C is blacklisted by default; see the C<$BLACKLIST> variable +further down. + +=head1 GLOBAL VARIABLES + +The behaviour of File::Fetch can be altered by changing the following +global variables: + +=head2 $File::Fetch::FROM_EMAIL + +This is the email address that will be sent as your anonymous ftp +password. + +Default is C. + +=head2 $File::Fetch::USER_AGENT + +This is the useragent as C will report it. + +Default is C. + +=head2 $File::Fetch::FTP_PASSIVE + +This variable controls whether the environment variable C +and any passive switches to commandline tools will be set to true. + +Default value is 1. + +Note: When $FTP_PASSIVE is true, C will not be used to fetch +files, since passive mode can only be set interactively for this binary + +=head2 $File::Fetch::TIMEOUT + +When set, controls the network timeout (counted in seconds). + +Default value is 0. + +=head2 $File::Fetch::WARN + +This variable controls whether errors encountered internally by +C should be C'd or not. + +Set to false to silence warnings. Inspect the output of the C +method manually to see what went wrong. + +Defaults to C. + +=head2 $File::Fetch::DEBUG + +This enables debugging output when calling commandline utilities to +fetch files. +This also enables C errors, instead of the regular +C errors. + +Good for tracking down why things don't work with your particular +setup. + +Default is 0. + +=head2 $File::Fetch::BLACKLIST + +This is an array ref holding blacklisted modules/utilities for fetching +files with. + +To disallow the use of, for example, C and C, you could +set $File::Fetch::BLACKLIST to: + + $File::Fetch::BLACKLIST = [qw|lwp netftp|] + +The default blacklist is [qw|ftp|], as C is rather unreliable. + +See the note on C below. + +=head2 $File::Fetch::METHOD_FAIL + +This is a hashref registering what modules/utilities were known to fail +for fetching files (mostly because they weren't installed). + +You can reset this cache by assigning an empty hashref to it, or +individually remove keys. + +See the note on C below. + +=head1 MAPPING + + +Here's a quick mapping for the utilities/modules, and their names for +the $BLACKLIST, $METHOD_FAIL and other internal functions. + + LWP => lwp + HTTP::Lite => httplite + HTTP::Tiny => httptiny + Net::FTP => netftp + wget => wget + lynx => lynx + ncftp => ncftp + ftp => ftp + curl => curl + rsync => rsync + lftp => lftp + fetch => fetch + IO::Socket => iosock + +=head1 FREQUENTLY ASKED QUESTIONS + +=head2 So how do I use a proxy with File::Fetch? + +C currently only supports proxies with LWP::UserAgent. +You will need to set your environment variables accordingly. For +example, 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 can only fetch remote files by dumping its contents to C, +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 doesn't support any options to return a different exit +code on non-C<200 OK> status, giving us no way to tell the difference +between a 'successful' fetch and a custom error page. + +Therefor, we recommend to only use C 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 is relatively smart about things. When trying to write +a file to disk, it removes the C (see the +C method for details) from the file name before creating +it. In most cases this suffices. + +If you have any other characters you need to escape, please install +the C module from CPAN, and pre-encode your URI before +passing it to C. 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_BIN + +To indicate to rather use commandline tools than modules + +=back + +=head1 BUG REPORTS + +Please report bugs or other issues to Ebug-file-fetch@rt.cpan.org. + +=head1 AUTHOR + +This module by Jos Boumans Ekane@cpan.orgE. + +=head1 COPYRIGHT + +This 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: + + + + diff --git a/File-Fetch-0.42/pm_to_blib b/File-Fetch-0.42/pm_to_blib new file mode 100644 index 0000000..e69de29 diff --git a/File-Fetch-0.42/t/01_File-Fetch.t b/File-Fetch-0.42/t/01_File-Fetch.t new file mode 100644 index 0000000..e4fdccf --- /dev/null +++ b/File-Fetch-0.42/t/01_File-Fetch.t @@ -0,0 +1,303 @@ +BEGIN { chdir 't' if -d 't' }; + +use strict; +use lib '../lib'; + +use Test::More 'no_plan'; + +use Cwd qw[cwd]; +use File::Basename qw[basename]; +use File::Path qw[rmtree]; +use Data::Dumper; + +use_ok('File::Fetch'); + +### optionally set debugging ### +$File::Fetch::DEBUG = $File::Fetch::DEBUG = 1 if $ARGV[0]; +$IPC::Cmd::DEBUG = $IPC::Cmd::DEBUG = 1 if $ARGV[0]; + +unless( $ENV{PERL_CORE} ) { + warn qq[ + +####################### NOTE ############################## + +Some of these tests assume you are connected to the +internet. If you are not, or if certain protocols or hosts +are blocked and/or firewalled, these tests could fail due +to no fault of the module itself. + +########################################################### + +]; + + sleep 3 unless $File::Fetch::DEBUG; +} + +### show us the tools IPC::Cmd will use to run binary programs +if( $File::Fetch::DEBUG ) { + ### stupid 'used only once' warnings ;( + diag( "IPC::Run enabled: " . + $IPC::Cmd::USE_IPC_RUN || $IPC::Cmd::USE_IPC_RUN ); + diag( "IPC::Run available: " . IPC::Cmd->can_use_ipc_run ); + diag( "IPC::Run vesion: $IPC::Run::VERSION" ); + diag( "IPC::Open3 enabled: " . + $IPC::Cmd::USE_IPC_OPEN3 || $IPC::Cmd::USE_IPC_OPEN3 ); + diag( "IPC::Open3 available: " . IPC::Cmd->can_use_ipc_open3 ); + diag( "IPC::Open3 vesion: $IPC::Open3::VERSION" ); +} + +### Heuristics +my %heuristics = map { $_ => 1 } qw(http ftp rsync file git); +### _parse_uri tests +### these go on all platforms +my @map = ( + { uri => 'ftp://cpan.org/pub/mirror/index.txt', + scheme => 'ftp', + host => 'cpan.org', + path => '/pub/mirror/', + file => 'index.txt' + }, + { uri => 'rsync://cpan.pair.com/CPAN/MIRRORING.FROM', + scheme => 'rsync', + host => 'cpan.pair.com', + path => '/CPAN/', + file => 'MIRRORING.FROM', + }, + { uri => 'git://github.com/jib/file-fetch.git', + scheme => 'git', + host => 'github.com', + path => '/jib/', + file => 'file-fetch.git', + }, + { uri => 'http://localhost/tmp/index.txt', + scheme => 'http', + host => 'localhost', # host is empty only on 'file://' + path => '/tmp/', + file => 'index.txt', + }, + + ### only test host part, the rest is OS dependant + { uri => 'file://localhost/tmp/index.txt', + host => '', # host should be empty on 'file://' + }, +); + +### these only if we're not on win32/vms +push @map, ( + { uri => 'file:///usr/local/tmp/foo.txt', + scheme => 'file', + host => '', + path => '/usr/local/tmp/', + file => 'foo.txt', + }, + { uri => 'file://hostname/tmp/foo.txt', + scheme => 'file', + host => 'hostname', + path => '/tmp/', + file => 'foo.txt', + }, +) if not &File::Fetch::ON_WIN and not &File::Fetch::ON_VMS; + +### these only on win32 +push @map, ( + { uri => 'file:////hostname/share/tmp/foo.txt', + scheme => 'file', + host => 'hostname', + share => 'share', + path => '/tmp/', + file => 'foo.txt', + }, + { uri => 'file:///D:/tmp/foo.txt', + scheme => 'file', + host => '', + vol => 'D:', + path => '/tmp/', + file => 'foo.txt', + }, + { uri => 'file:///D|/tmp/foo.txt', + scheme => 'file', + host => '', + vol => 'D:', + path => '/tmp/', + file => 'foo.txt', + }, +) if &File::Fetch::ON_WIN; + + +### sanity tests +{ + no warnings; + like( $File::Fetch::USER_AGENT, qr/$File::Fetch::VERSION/, + "User agent contains version" ); + like( $File::Fetch::FROM_EMAIL, qr/@/, + q[Email contains '@'] ); +} + +### parse uri tests ### +for my $entry (@map ) { + my $uri = $entry->{'uri'}; + + my $href = File::Fetch->_parse_uri( $uri ); + ok( $href, "Able to parse uri '$uri'" ); + + for my $key ( sort keys %$entry ) { + is( $href->{$key}, $entry->{$key}, + " '$key' ok ($entry->{$key}) for $uri"); + } +} + +### File::Fetch->new tests ### +for my $entry (@map) { + my $ff = File::Fetch->new( uri => $entry->{uri} ); + + ok( $ff, "Object for uri '$entry->{uri}'" ); + isa_ok( $ff, "File::Fetch", " Object" ); + + for my $acc ( keys %$entry ) { + is( $ff->$acc(), $entry->{$acc}, + " Accessor '$acc' ok ($entry->{$acc})" ); + } +} + +### fetch() tests ### + +### file:// tests ### +{ + my $prefix = &File::Fetch::ON_UNIX ? 'file://' : 'file:///'; + my $uri = $prefix . cwd() .'/'. basename($0); + + for (qw[lwp lftp file]) { + _fetch_uri( file => $uri, $_ ); + } +} + +### Heuristics +{ + require IO::Socket::INET; + my $sock = IO::Socket::INET->new( PeerAddr => 'ftp.funet.fi', PeerPort => 21, Timeout => 20 ) + or $heuristics{ftp} = 0; +} + +### ftp:// tests ### +{ my $uri = 'ftp://ftp.funet.fi/pub/CPAN/index.html'; + for (qw[lwp netftp wget curl lftp fetch ncftp]) { + + ### STUPID STUPID warnings ### + next if $_ eq 'ncftp' and $File::Fetch::FTP_PASSIVE + and $File::Fetch::FTP_PASSIVE; + + _fetch_uri( ftp => $uri, $_ ); + } +} + +### Heuristics +{ + require IO::Socket::INET; + my $sock = IO::Socket::INET->new( PeerAddr => 'www.cpan.org', PeerPort => 80, Timeout => 20 ) + or $heuristics{http} = 0; +} + +### http:// tests ### +{ for my $uri ( 'http://www.cpan.org/index.html', + 'http://www.cpan.org/index.html?q=1', + 'http://www.cpan.org/index.html?q=1&y=2', + ) { + for (qw[lwp httptiny wget curl lftp fetch lynx httplite iosock]) { + _fetch_uri( http => $uri, $_ ); + } + } +} + +### Heuristics +{ + require IO::Socket::INET; + my $sock = IO::Socket::INET->new( PeerAddr => 'cpan.pair.com', PeerPort => 873, Timeout => 20 ) + or $heuristics{rsync} = 0; +} + +### rsync:// tests ### +{ my $uri = 'rsync://cpan.pair.com/CPAN/MIRRORING.FROM'; + + for (qw[rsync]) { + _fetch_uri( rsync => $uri, $_ ); + } +} + +### Heuristics +{ + require IO::Socket::INET; + my $sock = IO::Socket::INET->new( PeerAddr => 'github.com', PeerPort => 9418, Timeout => 20 ) + or $heuristics{git} = 0; +} + +### git:// tests ### +{ my $uri = 'git://github.com/jib/file-fetch.git'; + + for (qw[git]) { + _fetch_uri( git => $uri, $_ ); + } +} + +sub _fetch_uri { + my $type = shift; + my $uri = shift; + my $method = shift or return; + + SKIP: { + skip "'$method' fetching tests disabled under perl core", 4 + if $ENV{PERL_CORE}; + + skip "'$type' fetching tests disabled due to heuristic failure", 4 + unless $heuristics{ $type }; + + ### stupid warnings ### + $File::Fetch::METHODS = + $File::Fetch::METHODS = { $type => [$method] }; + + ### fetch regularly + my $ff = File::Fetch->new( uri => $uri ); + + ok( $ff, "FF object for $uri (fetch with $method)" ); + + for my $to ( 'tmp', do { \my $o } ) { SKIP: { + + + my $how = ref $to && $type ne 'git' ? 'slurp' : 'file'; + my $skip = ref $to ? 4 : 3; + + ok( 1, " Fetching '$uri' in $how mode" ); + + my $file = $ff->fetch( to => $to ); + + skip "You do not have '$method' installed/available", $skip + if $File::Fetch::METHOD_FAIL->{$method} && + $File::Fetch::METHOD_FAIL->{$method}; + + ### if the file wasn't fetched, it may be a network/firewall issue + skip "Fetch failed; no network connectivity for '$type'?", $skip + unless $file; + + ok( $file, " File ($file) fetched with $method ($uri)" ); + + ### check we got some contents if we were meant to slurp + if( ref $to && $type ne 'git' ) { + ok( $$to, " Contents slurped" ); + } + + ok( $file && -s $file, + " File has size" ); + is( $file && basename($file), $ff->output_file, + " File has expected name" ); + + rmtree $file; + }} + } +} + + + + + + + + diff --git a/File-Fetch-0.42/t/null_subclass.t b/File-Fetch-0.42/t/null_subclass.t new file mode 100644 index 0000000..630a607 --- /dev/null +++ b/File-Fetch-0.42/t/null_subclass.t @@ -0,0 +1,23 @@ +use strict; +use warnings; + +use Test::More tests => 5; + +my $parent_class = 'File::Fetch'; +my $child_class = 'File::Fetch::Subclass'; + +use_ok( $parent_class ); + +my $ff_parent = $parent_class->new( uri => 'http://example.com/index.html' ); +isa_ok( $ff_parent, $parent_class ); + +can_ok( $child_class, qw( new fetch ) ); +my $ff_child = $child_class->new( uri => 'http://example.com/index.html' ); +isa_ok( $ff_child, $child_class ); +isa_ok( $ff_child, $parent_class ); + +BEGIN { + package File::Fetch::Subclass; + use vars qw(@ISA); + unshift @ISA, qw(File::Fetch); + } diff --git a/noarch/perl-File-Fetch-0.38-1.fc20.noarch.rpm b/noarch/perl-File-Fetch-0.38-1.fc20.noarch.rpm new file mode 100644 index 0000000000000000000000000000000000000000..f7c5d3cb0e3d6f5e0d90c30925bac9e976c839d4 GIT binary patch literal 25572 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 G3RzkZW9K*k literal 0 HcmV?d00001 diff --git a/noarch/perl-File-Fetch-0.42-1.fc20.noarch.rpm b/noarch/perl-File-Fetch-0.42-1.fc20.noarch.rpm new file mode 100644 index 0000000000000000000000000000000000000000..87bbccec437d05201dec6b4f0a7d86b4db5d1008 GIT binary patch literal 25792 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Π-om}6fY<< zUkKl)kh~6Hu})g@__)k#bi=|NpS<^N_CTB-O3G)!o}KTwKbti_7)?RO+4PK9)662^ znZB8A-VBu^{_I_hmchNW;QKipvKfR2U1Yc<@i-`fP+B@i8kxb@IU=G&My?Wy3(u>! zev=N?NpNpXZU!b>2+M4uzgQ_oQ@G4-Ll_;tE|uIb3SPIG=s)SNzS%#!MSa7skj z=g760*57Y)SBWKd=+tuvuNL~y{9f24sUaO&zO5NGGK*t}f(ril<3{NUo8JQa)1oJBGK`9yOC9wmDx zRJZwFRpy9R2J`SQbY%1O8?mdmY5aEUx6SR?Vt!acJE!pRtI_K3^#@U9G@3H0Y~8o?HHV? zGSj}WEX>pVD9O-0PL0+?zBsDNz;6jJm^?GV{4V;G3A?P|%W_`Xkr~Q^6glQ+phfMW zDii96$DC3QN1%dBb&>Ms>#&GCzcf3`6_fHSQ&g?wv~vnodm4mvf~3m)4dw`#HHrxU zIN17$WQkzA$gDy!q3VopndTZC6o>&mMk}-*V7Bgv5kfBVRxB z9jyjqWCwu8xUdN|xuon`CDc-|s#45DVuQbNo0TP4Z-wmGG5wCw8GJL|;rN8ah$B`* z%krJ-N9THDmWHc$)GjB7n72rPB=#(YY&#B`N=WW?@>skAlA;=00>OFL(3@2j2iY6g zE33(R>?c(|T0Qul_*NKxKw; z|Htjvr91VO?XcmRmpH==gErRBQI)7tc9AS<+=tPF%8>JeD|LDay9d)M+^xOfWaXtXgPJ8`yi3Bcgkn2WG6h&64ar@dnr=}JIy2C1RVjDlBCQB>5-JfcjeUSKO zHm&7_Iq_a+6CAOM@D7X{IrgBgIpFD%+zORhJ(E`+)?XNkBnWJ1`PS_;&&lOAV2z8) zEc+G2XCP`#yn1YBtDiZ?f6b)t6nup5*!)_AYu9duTmjlo?JR78dR0?6gwmIM#hRB{ z^F|~RBSiMVIB3p81}l)t4x8G!SGs54QGfO6zSzB)RMrX;$UL)9>eFraqNRQrf^(A$ zlrsHDmUpzBowBQo1o(Dn#nvd@Q+( z=0crF3uDWKkQyvY1d?7>Gh_u>=T;tfnlHDsz`@I2D}xto{2h{Pi&{~{CTZoJ&4br) zFXe+?2gCvp8RMd9?Z*?48w1WY3}vRhsA`oD@~d044YC;+fc_M86m?SYS5U6S!~HiTjNUAwDcsk&pRLq$TLt5`x@r z+NHjd%v$`un!jYG{<=0USQ;Dd%{{F_YIE_;lA){6wQv?IWXro&3k!bh(2Xo#H>(@Q z)qXKQOwZ*K!+5^Jt$O7yj;kT&zK+i}X#RN$7NWbUOq2h0MC48)n5cm1F)KvE9pUdT3P>Znyh(RnT2A}@6d%f zxJ2T@-6+0x(fzj>PJE?=oA^Uos?*TLKw=H>z~9musNZwq1l%DwXB!_~T=mqz+z!_R zH}UZ@NFkIij4&i;TO1J#>Gt9h_iy<+L=kGFp=tHb{AS3D?v+Lv6~oSy_?|{Md5l|6W=!5OvUN4@53h`?I^bDS@!!9kDyiws%xg#6W_yBWYb|*d#%YWNO z7P;fKFJ9Z}s8#()7XjN!{#kdc4Ik;{CUkJ+lRhw4RA}O_BLPSeQ_kHp z4{^KA;-(0sZOluoe*HOsAu|X_r?Tr+&qCj{r%e52&sy9|Vcnz9(=VyfQq2_(sDBd4 zYjFmJNBxlJUVUaAR(g^yKuogitzrh|Yh?3-PVDx52ModU_fd>yRoLQwVj@u{n+&2n ztd*QRd}sgBfqyeg4W$}h($qWN&Tol;r}i5&hO|kIk~L)1%~|V1Utlu?Z-9C9jJEvm z=Y=#zF#qU+4%qtkk8)};R4GC*Y!W%dK-AR*5p(vh}9bvjM zCEai4pXcd#(9KES5cV*V#pK~Qn3Xd!yno=X8(g`$O(sCQBI|xErFneKDDpldG@?Q! zM+mB4JF>zQ)y*b?Ut?1eTIn?{V?LOTsb`?VkY&u>8 zg5UO@1HsUM%h-q$-%!X%web%w;>pe+==z;s!dSaPZUSn)yOVxQ zyBY^xB`53eQ4RNUAWc)?XW6t06$FA;c%JU4&sSaD6o>z|!U?VoCSEh+q{{@)U2Q!l zJ+w*_9%`qqW}l;o#!>;O%_)R9X+;ocvpT;qxQb}zM1uA8AW@|)(c&Z)VfLeL_x13{ zE!R1yO4asy=~WD)Jc+L^1}^d}cHo_Hnz9JuOVU%8MeN}?=u@ypDTWLUAkb0kq_={% zFn9$pRo|z!L2MT%!O4;Vt_X|Ix1qz6$BqU$x0pX59cN<9{;G_z4STHLjYA7>C*Y9y zv7}=i1{$8upymx*?dx8xLMpZ29)oj@>qC$y^rL^j;1i|CPMVd0YeC{#xtq!mVW=X; zgNKr)^-BcDW(YQGFTq-OxHk`h=jL0vbk)`>bs#%VIx5dmUX4xIU6xt}|0L}Hii9A$ z`gr@G%gpR%9&Dslj;4X#U0xJtC47yo5a|bRa}7{ zoNXF=!N8YvXw#HRMc!+RIM_bP-h}h6d^?#csy&~j!w6ghj-KPVuyW_7gW8!0G!!r% zTT)F5CT|%%^dCJQQQd5lu6*d#Yzp|L{}p+vk}u5#h+;9wK;HVJtS*5+RvJVABM;9$0ty_Z{@AG^yfF4=C(TU<#fg9R$D4J{a)zi+=9KS z;qbGD=$k(K5ScC3034kksMZ9Y%4)`_xhkJ@TWd2>NWU;ul2YmqY_YkFx|$0kMRi1` zz`t(mATu*P$-zr8ibqhB;@40i`=o#S?g7~|x1=*sP@%lZTPs5u# zL`iRFRHo5=XVDHKMCpC3dr2|iX+v5Yeah!v3WBS^#?Y0I46%xcfKEB}?(7*_KpdG{ zqeie-c7_1*Wabuba_Ju6QE79*@mYWyHQ3tUKGAaR=k>yi7gIgeYYd#)SXFQa!&Vb<6gg%Of!P=<(`daxdF1<+HWQk&Xxez^UfOL% zEslTc;%I5Kn-mfSTJZ8XQW7v9-=ZxO2+C(;VTY02pLaWygcNTtXI)XfESvvWJnvkf ziYFwazAfsKhHL#PweGBdxG6huh~(UmVM*j5y4KR3E^DYwJBL4daxV(#>N#bc%#VgF z>Ve$66n~~0Kf2&gaG3(HPVa+L4tjZe8qrxZH8lbxf-Ag#B#zR57w4o!z?hS_WTL}J z5&ZNT+X~+`D0nN}PC>nK6enuz!RL*mqFy2pJ5cB;Cn>^JM&w*#+ zy4v)-@-&iEO9pOI+ZduMrSma=twPodvT_K~*=li311Z0$;x!Ek(Re*3fBNZB-p?x_ z#e+kv)WDx)$6VbziNk7Ots?m|eeJPBRr9XqOoGEV^()~}QfyGWz>5QLPZmEZm=38A zoQvq%>Z!mXzS;9h%o7zy8A>eWF`Y5%+Ze0pUyKsAPyu@m%orp&V<2EVQ*sRjpY)zv zomB*2JPyB$bf5EAZXW+y3rH9$)jTSrqKcLZ=awI9GCA-s5{@gU7qIm!k#7{ueW*d+ zwvRot{g3Jcg<|DQ#u5pk%~XV^V{7FKD}zZlJM45&iVzzZGL0r#>V=j0d011q?N0a0 z{v~M65VPoG)ptoENcbuqKYRC7B*AEa9}0Yw%4X)+0F3eV246clByD$1dBcJ)a8z|u6`+RX-Q9$S8wmkefyB7=)T6~TzACB z1uhYH$Dx3Hw20<6_*eK=E|ou+a5yP#Rt@6{)#fCs?bNi3pQXWMsI!_ryQ<>8$)xjv z_OeNO*%rA#JFU$xoc7-ySB83JBmb&X#J9d&Yh~_Rlu2u7=TY%~v_fu?*PZ$?e0Qgu zoQaRwsj?rAC~HMYz(yl9V7mqGAo&4hb9XI|_ z>o4w*O$YSo{RdyvWT;iF?Js<&DsPqb9ufDpI!BAfp-d()FMv59$2Lj&_Gd&w?)g&M zPth6G+!pMJ3Fxoh@J188XS&_`vM@w&bRV8u_;y#5(U;PC@?R!_wJJ27Q5u$^o%&4} z2?J8ZO%)Tm_w0S$hwv8Za*o$vZTEzsLL9`l#wB!ARcZZMOKJcepWFdRj9l}^ zYaD6Yy_mb>JOprIG%B6Bk;D;ii$|$gph$rG%1LTCEuD}wfh)FCSto=Xm`8(OyUYPA zjYH?k9)5gcrYw~zbcWfmtyikRGGj3W%S?liO>qT7ID=~I=_|H4{Up+W%L$RBHaiQ{ zo57|G`8iO$l6AJF&K+iH^aj3B{;0(^z1F`HBN6^2H|KYLD{k-Z+kJ|m!r~Z>^5zIX#_>AqCTuHI1;Bb{TD}LePN3ShK=&1%BQ=AV#qvz zN*zi4Y(~^Tk;C5|YZ48BXOtLwfA0X8?IA#yI@eRmvA}gH+7pl4rZ$fyw*(m=t z%aGXP4+6%x@f% zDJTIL;xTs5b_Jh?VnaGxGc-u?-Rdjrxw2t$&ZdT~kskVu@EqgBUM@5WXR zJm2X$A-iZjZ9|&Y_Q-flr~XMA%?}yoD^oyGU5n025zZx|Wv$~g`+i#iU9$3WQ&F-r6Mvv>FXVyT|BV9r69-=$X=Xr^eUSCi}Mt58H=T41Pt7 z>TIGfcaTBZ5~)Xfbj~RUiicX?!zTX@ z`M_b;W5TQ-KLbu0((zrxHMGn&DA4WY2ZyI2d$eNvT{jU#Z;=efqNfFi z{;C&6&Kiwlh_{Ud@O!Fb%sy-NH6Ue=^e1|_F`nw>)N~;Bdk6Gw=^Cx;hz}|#*IR@~ zj*_`7jsZ4Qmy|gJ9UxG@?dudBO7aW%c<+km2(EUY9}3sZB+>5$`t6yL(r(3c`}CKh zULq2VE(JS!y#sJ+k^aweV{P=xMt$>w;&0aG7 z+bww{(9-%v`rgRdHzTYIswO|dq$2Id@@S4UIR_k2sFq#kvLavH^*lrYr52DvPd;Ts zr-GRUDNSopL@i$K$*sQqY-!uwjresZ^CTPb_S#!Ap>4VhT|FYK7YK{cGkB<-MS9kg zG3(A~#LhmgzUU}{j$-BbR^>wr+iS&`U5WiJa6+F%edZ7}CL0e~&du@fD~K$6A~Y2$ zPc2i1N<|aiTL*RyNGbRekGgWjVHB@>F&UObWgG$i4au*^ zarAO#kJN0(!InCP zx@OYou<}9O34NL!mfAUNHp*|7GHJb(b}CMV1I-iz)q;?m*@0=DKV*=wP*FlxeNLNc zGX3>HlIgczutaQ?mKk{HAJScf1#(1^XRfD-mKVgzPlCbrcc}Scb{_y%91csX`0bS# z8k9bBIUj01y#8vYnzDvl6g770jabo;AUUG{$x0qkTcmcN5l@M)C4lD(YP?XfLHjBz zG@w$;Tyhg-!*=xfX=st;-Jk7dV-0|x{YvMUta1#W`BpJ^1To*7&c4hYSg0|21QkDz zJ=?ewJ=z%higNEzOI6RVlG|_s3Szg8&QR)kN$JD!`Az-&e25$;bkwd5D|KKj;*Ux0 zw!0?bt2iG|Hw-<%cdDHr=lPU|vH+J8*+*P~>HuG<)suVHhNUvTe`&E2%OXd`T;q{l z*k!`U1g2IvBXQ?nPYB>%!G9C6h1Nhgc07I~ptna(cH=lm%K6?IkTMKxMA>kH0acDb zlL~ki)e4&S1aa%5wh>9RD^pVS4a{?5gO6)N z>cDi$T_Z8iYd`@29G+Rf(zUBXOUKpn_4_h6w^8>7o=%+&rY0$sN0fgEup0l%9q|GU zs4fi?jhAO)ClNfsFms^L1IK-?;0Wy#$_>Vj7RDEMWt-8YgEyIX(Psgqj0CPC2nYr2 z$hQRbo;FN2-i`R-fhz?@Ma7TY9_aVm{g`2_|MJ3aXtKq1vWH-iFgU z@|R1{Ai`8Mue)%*w)cCAg;Wk@hx*bwL3a1VO4(>Ep*^mLD1OINkQK3TWTKK}@4e}q>aZjV|++?F?M zc5dg2vT@9CCK9xqS60iqG_lZJH4xB_r3}&STOjaYH&iS0`#Tu-c|aQ((wScrzhZe z>-6t!ZWf!#z+fcsi;|lm#h6jV>-AsgHpm7Ga8L`^0#hA|EFXA(bw6bxD4skX4z|Pz zT^T84Q+8Vu0)#vtFd09J0| z{p6sPQ{d{&Y{u4u%6*6a-1#belt(7qe~pZIGE~IYH64h~c8X{n-8ak9vTgH%zk2Yb3P_$4j4-c4dkozm}{@Xn<6+fO^3`7_9 z0Mhm2t#5V?=}VX{qnvoBFq$7y!D(>0b6Y7h!M_=U>K$n%&ymTauT9sFRwd6{#}nCZ zJ#K!g4MxJQRJXU~^aU3+N|NOlWsy=<;1=3dT?*B)CnJja>60zve(f?)9ZDKca$(2u| zAOMmfNZnt0<{x~q{)utCo*tfa7gd6;+~xYBjUdo7ZktZ3>O5Ta6^Bw zqm;-KxCZ@5O8kcGMZNK`_G^-AT!_K0-Y7O#v5ue4bGs61rO!auW&Jg^rXJV1DHtvi zj|s$b;R0&uzC-@CnxAGOHOl1`hwq2h^WxzE0010Ffb#HFQH@gn>8>>oxs_`VmeU9M lY;57wYqSo+)e!&z{;dJ@<^w8DCjYkS-y8w}0000ASz64NE@uD$ literal 0 HcmV?d00001 diff --git a/perl-File-Fetch-0.38-1.fc20.src.rpm b/perl-File-Fetch-0.38-1.fc20.src.rpm new file mode 100644 index 0000000000000000000000000000000000000000..f6013dc2d5019f2d05914b0518e9e5952ce67cd7 GIT binary patch literal 23731 zcma&N1y~);vZ#%_yGw9)cXxN!MR0ew;KAK31a}D%+}+*XJy=M%i~X_B-RJyrZ$H#j zzg5-K)id3--~lcwF4w?8KtMr29Rbd^43bv100v2btC=MOGb0-}0}G>t87ni$|78OO zf&8D5u~o;QAGUX&I#2|G0u2;#prC+&fFA=j1W?`^Fc$nAsNenXHlQCA5vZYnf&r9w z{}oWb`-J~ty(}mmw~WZ}((ivJd@&%NZ01E&BVB=ypw}+w8aN;5zn|j^kb(Jw(th|~ff_g-ROEyIe6ZCA z|NUTxe;DF@ZlHjA0yS{W5btxpZ>7KweqY-=hkh^|P`}4Vd@wvvzt124!3ZBb`@!$; z{XKsEgONY{>mU674&KKfelR9bzsFyHFwO_RuN&Bhzy)exJec+e;`1~Qbff{%}2;mRr0czlQ2=Nc*{b1`4et&N7{*(`v0_yki*+BjNe560P_=9DD z`aQn#gY`fBwI6Ko;s5c$h9A5S)bIJ31ND2p2OkXh;P-v@?zi~h_kHuuk{|rOZ$QOB z{>OO-c|Y$UALm^PU=MJ%G9$47mID%t_i|um|Cz)NU}kAzZ{=bK@?Iu*dH+=>NK9;P z9Xwn}yd2y}Tpj)iCNZ)1`e&@8gO$B2!2I1~>P2Eg^2x&0@e@7CCrj6N4fpAN0w6m$ zlYDY^@v=AjM53W8^G~R~o1H1ZnZ&_@#N5il0^kg=cLio(V(-ET%pXL>=9bIc(#(;8 znSq6!lhM@KiP0HgZfWAmXy#z|9sr^xETt?@_kL>;XICp1S1U6RWq_+QiL#Z8i8Bem zqvN|4{@;THLBs*>09yw~JK#)A@>ZtKCeBs>mw&DGKT0B_tBEt?XK#@A74R}Kxd2R@ z%`6$s98K&Q9h^TinFD8H`rlQQ3B=aQ-pv!l-r+s$UwJ9g0goYO5P8u1J^)b>W377^ z6EjmbQxj8e01F2fo2i+Zg$Xl&$J~U2!@`Wm%z}dpgu{fB(~O6i+nj~Nl-a}-SjX5{ zfXu?p!^~-JVfy~EKN^W6aGAi@``<3W+V-#Z@1XyKem{%<+5XM%`rrNk^#7|5++=X? zyXs$Ci(10dRm0WF)`gc>!NdmeF3vRncwAh8d&~6$#7vwWKe}cP_Aag__W$MaF#mA; zv)x2ZTmbeac7Xq86mxL&`fmnh6IaXsW>9kknEgKtyu2FrR-XUOtPZgIcOvieNt@W4 z+x~kl8D%kEUNO6W=Ogc6X7YXj-WTNx@O0(nRkN~l{I6&Q2XnV~x4eUiIdGVRy}6aE zm4m&B?Z@n2{5zyu(_K!yL@!TOkT)0U8t>od2D%hl#U2@XP}5>Fj6+98N9fVCU!zaB%^czpqXa_#A=0 z|7y&P+^p}w%*YPZ%#6(J?-#BQKN};^&cFh~&d36+5{xWBvx*p^@c;jDBKhYV2oMI6 z_cvexoRq}G&DG)aducIwuL;0{@P2GufL;<7MlNo~|2QSUt@K{A{w439r~lR7lmCA? zjsK&VF}~jv1jNkI$^qoFx0NFZ56J&#u^?e#uyiFZ};}%D=t+VFvb5h@*i8 z8rZ@Xdpu6z>3)60aj?`S7F0{Foim9(a*nNqEhLIWH?96M_p;ruT;BD2@b#A~L2f3adBjU+BLbUKYa2!* z0=;@Z{}P*_W^W;PA%6#Wd+i~}4VerR@!`79&jQto+Y>hQHD*l}CKXH{k4)(#{7Wu!`vyMuQ+B(tWwVuTrSZO55*lAX9Ik+&yp5PS16a zmstO7u^p}}YLa$CF)Ax5@8`x@A5v(%4qGl_9)nJM5bn;oc@&{TP=CH(31pb~*+T+? z=YtsGXyd*B-dyK-gScxrIdK+Oa}@?&Ff~O(l+5=uJqJcJE8UDal^Cw((5T% zmoG)cg1Q;p&4ErZpz|#|+V(q3nE5jcYjE)A=&b0*f;1SYT_l1{*q-V%f2D{UHL)qHtAn1Hsi0tJ- zFI*RsQapr^z#)1nX<_6jwsi!QnWZ`jBJLh6!GB=<@g<>+w_NliuFXu!skoDtPMhYj1SwHW3U)rxf+k~FmOoA z&p5-0QIvX|+`@v}5VJQ_HaZI<9fS7!34T=QPKh|C`^@k@I&=~lY`#4hrDNkF?LNRu zy4d;!MNRur2#Cl%oLh(f>C+xxUk>cXf}MOt;b6|1!vTXs#d~P>V|_RdtPL6?VdUcA zWhd7pVCs3@zUrOiyt2zrL!f7$5<4BLHAC46G=rbMDP@?|Ewyo_*SbEgD0Dh{9PCS* zk73$9B*MpX7-CTK&mgVYzqB9bLd3^;Ild^6@?a9;l$NsN5p>2qnGZ1*Fy+63l2sru z3F9^nG|9)JhCHTpou<0%C}NHe%W{+VXif3>YzXf4-R^Bsb`^P8`7oSC--E2)lvZojI?fbOE(Ss3m8c>K z`dYu)Q}ZQ**caR{Fm_gWuLCbA{yA6(h0^Q`XaTP4Wprdd$bPALgR3B2xWrEJiXl5> z;4u7sC_ZRTrYt-{U_M9(F5L@qJ&JPQH30-Md;0K-OG3@nJ~ly}iZ}OqzKyZKYj!-Q zV0_e%nH&N1jhIts zym|52*I3^I8HnL~f0(l{$0M)}qw_+6Rc=^E5@r`iw(eE$dHxw%YXTvVu>Q39I+W$L z8c0oSn2Ge^v>zxZAi?%7HzR+^jV>56)-52yBM8MO+;i*UC{D5&QMSxTV@h5cY0$*S zYHpQJ1mK!s;U(^1+%G}wZ#fWdSt_U1Mjm1IK}{i+vKrNWwttp_H-aZ14P}Z1?edJn zf1NjkS@{AhTg+Wr02$#QY>tQeoM28HTSiJrdFZ@LC?l}n2}wo-_WW7cylEx+%Z}@0 zng*^)OQK*g=)-Ew+OM+#o9#p>;VBX>+C9UE1PJIFM+O0?Fg=>SLTW5HA-Qiyi{&A( zjTr~Hg!}{I7-;TG{XN-9#DYWO=^^+W3#h-PJL3fpBiUrJq#1YV)h75+adLxkq}7r@ zZ7JIX)1fZW{MJn@%#=d)*hBdoj`LA14k_Kxe~?}VKa3aJU&hlaA?1iKU{#8`5e5vR zt=+>4*>YmllNLPwzI8dXJYuDm*Y{xYL@S)siDq&L0;@S(yZTeAt9u9j?R-$)?^PCS zW*RPb2Kn#P=HJ9XcW!y?$gW@9Bq*B+{SL=%vjDs1yq0a8QcZ+2`3%%OrcZ$yD|$8{o*IG|r$EFW)zZ z6;afl#w?5F4#~|xIY9VT{z|e{mHZjMknL4LHwU|u78k8Tml|V639t$hK*Q?C|Nci7 zi$AC@7p0%iUoD-12#WI8qbvpivQt7G^C`{)fy9|hpMm-3nrmjRQ0dR?ipMuQWe;4^ zVP2;CL5}L-b@rp3k%&?`dyX@Rdzf&uUIXX&n&$HfZ|BXdg^0`G^bf ziCeUxf|mH+=@E7ivj}>P>b(+*d`z^xk0^g5TUlt>m{F>me>rX)aEDttp-L?L`ZG-# zmR-n}b^eHA`vVW(*aatV%W6Bs z%H$}tM7q0L4vCe3yxD>`4{VzD!n}Nj$*cLM#_ur(w_CFhEBOscf64p!*n=EtfKLPp z4{5VKQ!qU;E3fl}6%j|F8O+~>7ge1!`y%RJ722`3fn?AtIf zEXb@RW_}bRqkaSx*oV{VqU?d$czpuHmz3LEj53w5`B6ra9+ z=o88QuPuT^@CtgwM7(XxQ@LBTEopfKIj-`q8)yZ~O&z()v>wG_zT}fzyPbs40lm^S zU>S+1KmAv2{in6|bndgdu75VRh4r6{dmWvUESCD&cb^({yIQIef^U1lqnbdL9_xOG zN3?wmlyyWIqchkOu`6s4ZLiU;Sq{1oX;~Y;*6>uvXuey_Ug6u83E%4z1c!LTR8s4N zGmWp0=HRFBx^s3?ojzwItW8Pe+g4X$w`fs*%H@EEU-pi>5@Cu>FeBAJZe15QGtl~G z{tLVkb4(fI*EM?_-QMNnN_uQM@;#*9H(S5rbZSPs$>6QORaJgM5Pyx1?u<$b*m9bT z=7a#3xk6p2tz8p;P|x24m!*0gktEi=@DP7o-OGt+hCc(oN})n_g(l*{Y{R>NUrE={ zX6faXD@f`6lw(CwU+JR>IDfJq$bu}Fkn zB`aNodfS#U&T!M?fE*YK$kWm{!Mh}4Q8Vppy+j3TdaqG{?)fYbMfV_V$W<7e@F4~@Nq7T!khZ(|Gw_LU9? zF%g?vQ>In9=i@>ju(LJlw^tFwL5}cE|Z65}cgtWa7WGx|VK&a5T zBq_`zYO9o!gmE*$L_EiM@6kMS#OFGc<(~>7?+qE#ZW6}|N@G`UD8KW34oMuO`!Z7! z^60fe_gG;G82$`WnaHNjyA*gwL5-LPJHzT|oV_2v_4=b6U@?0unySr9HKF5_7~A<( zxYL)3g#)Ks&iu?Tzeyw9nL%;_yxV}ZxUkHrJkz9yzv@Fy9R(~8g8j-S!l^SRye z?>X?mF2z%kVYda*cBB(sn6d`3?z6b-j0utJ!#0S3jHS1YdED)wEmL4#}jSLvdTN0dPTWuS+(R?w}TCH7}jgK%inw;^5P zq?@9@v3Zt23V01~?jH*WnTIM80Xa+{+eU1Xma7I0MCs56i~$I7LP8@2_I&OdUv!n5 z>_upT#zk2~KK*=qMP)d91eL$1%hpW(ww@m`r5%DoZ})a$zVsKbH~XDjB{sxNbN?-gi?hd#ak%s=q$r1Sj1hh!13^zh97=T zsJo_1`^vGqZqCHx2)6#p0rRL3+8}{1$|xNu*mYoMzxcSdz0PT@@4^J?kD_#1k`)Jp zid@e=N28O4O4M~jZ+I0jom{&H7>_z5;IlI#Fe68G*Ln^_Gqym_+nfjs0>Dp@b&!NR zkEOg&-=4YQOd^M#wiNO4+VafG7l<}1*(@l)w!7;uA&#}m{SLsv&`R40Lp>cXdy6Ka zo49|c1-J(VbRq2gh^T@M7D35$2XO$|>d8D;^C$n!Ugd=82!`w8#6rI3>0lt4JLPl- zy_?A@mhou%l{1_Y-j!Q+BFg|zC=)CH-c2MGD&%gVNiR5U>obCoP|Zc9Xzk0?U~m;5 z_r5gq_$NpCl7ecS0$}$fc$m5hL@aALTe{5`80J{uEH_mnta%} zLvS-eH=_Og2W52w#vf!t`CG?e_efLHF5{@S-Umjw=FEffihkR=^6&D0F>q1Q{g(-Z zsVENotJyUwD_n`!WtIa^8+$2^^*_L+@`&te;uA?2ExoEJBM?{VOd?T7 zQcSw z9PtAQ&AAbYoQ@ftRYmkTcJ|p^e0}+4_2{82^c0Wpvzz*M*!(Y_LB5n^kepNvSh7V>?`6|QRZj;)9m+SkqZatmEexfy zj>?74O|ttuH*2CQ)Fms*RacnU(+Ic?55Q*W6yp&xBh7nQeIj(gM&dQf9ILeL$>m$&11qrjSi+11qNK-SnzwVP1slh`%c4A~wE zsk>no;}_4apS1Yt`A$fWyEWq5b28QH!#FfhW;`{qTWmhgdGPIg%gl%6V>*sRyOb?- z{+TajUIPpy9xFuTJY&4#%30CN78(7KK5ZTlCQrMr|``;0A#<}v4Texl>C@c;GlV$)ve^(zWJZLy7VZf#|b@oImXy7QZBzx*%Klg-skEd(#= z^FUpR#OY9K?%idv(KX4JNwI9A%VpYGr5J6Mdnx)$KQ31c3Z(12aKjlFdcQdF4zLGsRy3jgMJblbuPqoi@ zXT^VrCu!#Z9N7Wt(JQ_QcHn3ftn270UyoVAJnmD;Lq>Me+1MCy-=g1}k{5rk4S%Vv zRJ%wjoL7SUx4x+BV`0isK<3GLl#RP1u`zBG2JcFz!}o9@%cx+Ah>dlwskl--!t$}X z7Oh9w+ll7`eqY;GJ{nX)VX;p9NTF5tI~M9}Z-bDAL6x#yn)YpMv7D%=EbPP(R=WV# zd#@6CoV!(UGk5~X<22HVjq^d;ad=5D9@AZ3-35J~y8wA>xjxDBZ>#W_aqDG}mH=}s zfuFX&sJ;On9LBGKy}!@KEoUpd_tQi?^{$!b4}H1Av;W}`+wSZ3}p^)Ar_lC zxRHH=#jR@}3p^WX%dL+sZ+!#Timu9!k3MZ#YIc$ZcvJPCJ%X{WXLG}jeiM=#U(V^U zqz~pn6;F%kHaBVg^x&i{BI$<0CV-sp<r~@3^Uy0pY_mc81qioWd!wEuAL(eHKTUnP81qp^ ztFJd$xj}Yo#dWzo-gDj8+Ptagc`_4rs^b1yIw=@PFeOp0bC9T@iq|bs{rJiR-bcNQ ziLavVap>9r>?iug>rUMgt=8e-dOS2khep_P<}(tHG5=Z;;&r!?Rc*Cbt6wJ7GiedT z7WWm1*q0HG790b_$qVXV%FD4OQ!w|V6HnKSA!STnxc8KRJ@Ms1BVA84Ha&T348G^wOi<4#big*U|n}z4Zc;6F4?=W z;DCl1NR+&of#cms6B84xa;vUf`=$$)`jfAPHy@4=W(?_tgkiv9gtmYSMW+ct%Ih|lZFq+h>6VgdBJCN5IaPoCyAi}<5O(J&3bUP^1 zB38yCdPly?6L3mG9fCXNG(7p|$J5Aa$279l?8uXNONyK&`P^3ySF&sxnGh@vanAN5#hV6YNa{PNqF|rRQ&1GnLXCINonV!TTgC81=>loJ6q^p z7&ouoc%d<*>f+32jC)w3Mvn2?#P z8dPrLdCrfSw5|*(A@NtpqV7qe<5oFMxY_$XS*S*|&$rX}RIxprm}X5LRw@BoCNsu% zb?1||{xFi^wz>=1W71=VfTi##@9hRvj@O)3D;tNOC*9qVK^{U9`l8mS=>i&4E{;0M zG;7i8;_(V6^n$9r(xeG(f^E%Qn?@5oSG-|=CZgNawk#8G+@1Sr2f@1F$b^#%_I(K~ zRgJxKg4*($joIsP|0wCn0lyz@Jy>#rKA+s;jzNY-6G0UAHE56HvSL1-l=$!;T|VABxkrvF!5LKzf)BPxm<%ULxsksQS@5 znyN{%8aLFQ5*14Fmbv@5#>%I^>T#Is$ zQPYx@B7kOh!G4L0`_wc?v%OD{2V3+8j;I-&+9|=>Cc}4k;ex9iM}`WQW``pm=CGHc zwF>_^>MpI>(}wjx zRi)W&?8W)Pw^Nqt#XoAGq+IMtlw#9t%oF&RQ1%sDy*7A!6Z8vG!~JbJ9!?|`a&=Iw zo`7%qW8cKJXN==;un`E)BJSaE%(S1FwdGQeb6N1%StiQRuP!q#ZMB}(A~jAZ zArUEzcp<6@_@=LB1B%i1H-&Ml7*!Ck>A2*5g~M$<5*U)XIeBB4w=0~k;5*ZPJF-`) z-d)-1X8P0yv%;6wXkzWR&GxWe%~X4Ak@xR`XfU5hs#ecsSjDlI6-etkS&rkzY8=-r z-xS8L{*v%D<;+x zZZZxeLFm#Xv5BPY5vz!ymg<4Xk2#*{KK;*5eIo}qCOkWU2^I8?10+T$`R}rbMGVJ< z3b0`)q>tC&naxxkvOp|{m19^Hpa#l&Inu}YhCcJf)Qc?}*_2*Vw z*>6Y5hYO|}!Jc0710grJNVv5Qtc1$;d$x7=lDt&xl&RNq;Z(cjKl>CST-X{*0B56x zU(&UiDx0un$b;4F2b?Yh^Kw z3Xl0z?P7CZAM#q>kVKA*iGn?Wm#;XhR9k*>i0X^9sF`#WTYA5F6n&pFZLCeGS)t{q z&nmCwuAFTu-PoEt1cNtqysl3cn?UjYcvbi;9`2?33Q{=aGwvI|wu%<}&hN)Aem7P~{ z)In)$4ML4Z849E9v1?`hE_a2wVhrd++Mt`|eRPLKNg7>Sa$tz!OB!2_L75&Ek4x@F zzLDkOqCC47y|VNh#0xa4U|*6!Wr!W{!mmpq0bGps%9*}fe}_w`%h0{Ljj+RmD)1=H zjW1km>zaRx**zI(L`9UV`~G!`2jg>0QKDx9`|;{JLOyCBOHw}3OFxw!CuW? z%?adKQxF&egUpfgY#;Vb?eI%=` zL|mUZWVY`=;|*wz5FcE{b5SkZX`8LM$e04!wb#WSsf1M!T}yV=u2njC@TO^I<^rX| z@wkN3&|%UmXOFX-R9_Aoinix%I9@=1!h&=L2yxB0>;AHKd*)@#!-ElK@lI;?oGh?e zmrZi-$cI4o zF#ooG+SG)sQEB#=-GxkVRQ7Rw5xjI%Lm;;^+e7WavTWYu$P=sFp<{8?e1BNU=KAnp zj1NE(N6LYH-Ev@!eor7k=F1j) zQ1ea2bWfK=+;UKVh!J>WxbX{YMrg{*53z+&;_HwYxleJ32I4=aBOqdo=|O`|JiOyC&m_?3cc)MW!9w0~^^%Y}3nyAj z&>!3u{YlS-51qdcE@z}r{=_?PD(QR`Hhx$74Wf{KyMeE1xuvqviI)!t*PF#cXQnS+ zza(0eB}LC;JQ&9gG4rBVK*v_w0>Rm$TnJ`2hD#nZxFG6K(!jmy=f298m@$RQ*SvW_pD^PM|R=J^EdMeC0h3JytEwVc2`c%Q!OT(Jb$ z&ppubOy+xxplJ7AZLo?jPkf@9SL`nQZT>{!vX6%q;l&OZsM?Qx+>8_-qD35y+~@T} zW41)$hD%te)M_M!oDL1b^aDRETJaj!mIBah;g;NXJ4hWp&2Vfmyh@3Zaf<~^ zH0vo9OS@REi?Hr9qw8kX2on`rWTNv^4OH;&Hq_~P^zSXIPvG2K;<@-H-kDDimRx~k zZLq<7?&}EjAiXy7ZI!&!l=qb(F!3S8u|@wbv?+qoBd%)u2}Z#-!!f{tf=wMAAtiO| z`ab-V>+(c0t^v_B^MFtJqc@cKPd&yolz@E9>Qww|~<3H?aCc?5t2a=ECBo5kj%JMe%(Dk5^OlS~F(Lwyc(`q3q86fxo&)t4a2I zOQ>X-#5zHr<`%madZV;4Cc_Dp?))aQ`P1J!IIdL)JMT3tI0+qd+klJQ#gu@lNSgB&E+e0$C)FA;seLJjTgx* zy6&E{zntOF)`vfM>)LzjJ&B`>nn;IdisAD#9_E=D7cn#zraP#PUb|4bJB(MCzo&v9z3_I%m zEqwWRYo>EV{|owP!z6Mno5!2XR#o*93(X|Xz{uyG&hY@Zu_(6+R#o4hPH+nNQQb4% z^Dk7jUitXN7_8iTOL4SOB@hX?*$pKRj=QGV*SF%6Pzs@Ri&_;1!_+oAl%nAxV@QM6 zM1s8f`Hym3sXhY$(~2MYS+jaO{H9q`S949etc&&*jv|u3ggW4sM&j$4 z`6H7wCTf^fC3P;~5FVx7VL4`2R#HBY*0=D$Usey7R1$ky3CIKb$2i+I$Jh*4Tz)`IBQf* zD7Yu{5?3J!%fCb)=M{>a+iOYb#eWNFQ!0sbN zXoMs(GXj2!gR!o8vHl|fgFzaXrW>%NH)0z-jF6UXwmwtIh+KQAd1w%{?h$ZEMZ&DS z?p2pnTv3BUICA^9SkMbuLuK8pl3q>(->p(vJiExw)`mqodT=Hn@Yh%Atd%UorXUw3 z!1%HY!ai5&<7D`yj$2CaPsu%9$k^8A6};pe`!GMa3s;h>Keorex;15yPR4%0;=>(@ z2fr$sC{#GK(zrK-+dUhTCZIG6=G(sVip9|>OY?>4HFn;uh8%4!UG)fuBfKKY(k7C) z#wlHIZyYd7<1gS{W@cc=;Bw&->YP;~QfT<1?1OLpYAmhwrEV8;lQ-D(%_MDtWW~|! z^{o@(WU?_L9c(RAcO{hDQuqCq%t|tZaVVFn8vt|xYG7wMCMV|HhLsBt3H}u5c8e%*W zqMsnAsCp#{-qTCk!kiM@PzNv`+yT2iMLtYzj%Vm12=k`Z!sgeE<60jC5s2pYepseq zUpO8iJ6Uo``GG-PaG6BOfiOqJ&}R2=$(TwUP%!sNr;R8qGCc#XS^>)hyw<`}OXbUF z#LQkHnT-Ka^Qye+&v=(ZQl;y zKJynuJ-jvVF&y$)7BG%^{sX2(7ZEejBZt`J*IFyUY%DPn0d&Ya29Jquqtaf`QaSav{hwIW#f z1T=z88D1+!L%oONOR6~f8D@(+jANX$>?G#1F+7J znyb?z;>vIo_@C?s1XSvtc&`-yx|>rm$IU?((s4H7kzx<7{X1-)rtQWI`qh1Pu-u#g zB_N>Hf_Rfo)d%Om?KDXX__L+voO7YLMZ`m>nj#!VB{e9fI;{!+w_;@4<`??XQks(m zG~6~JW@fpv4W#6mHb1UltdP%SipMD-_Y5E|hf-y+%HSH(UbmLJe;G7ey55>Ee4&zs z34;hLi=sH_CtB>i`ba#Vy#4DA#x=1yXQ)m^n}(E;u!mL41Abh29S35s7 z()8hqG#lP2f(XYctd!9;{u(n40K1SWf{uV4rLAfRPAn|k>4qEP;&mP}14Eujl0f9O zm60P^6_$gMOODN?-P3b9d(zY0li!?(%e-lt#ZJ81hQ4VJ+%vma>j7j}6$@oCY6hdq0zUOkoz1~gjm ze&HC@AXW6j2mKuEsv()ic&F}Gg!fnlyQ4XZ9VsRg3rfPR=-xAlU2wPjM)xOch;A@u zisgszSCSbb|JqM0I;S*-;&0tywFIvMqrvyGDw@Xln0@XTsyL-Qawbr^hA<`S z@p1|Ls9+LFJ*SP1ZyEZ@@+mb$`Z1ZLw_y`cxnCRgwDsS3+YoW7oZOy<@zILCRr0FO zo%`FwquUsUsAuG^Z&FY}@dG0#n~U!St@)(Y;r#4Bt-AQtK@!!=Rwvj5s=;*f1hr9= z7PCf(ea6A&pDHX4;kU)j@9}3)H9`RAQ1D8|f}-%@!v!Ty8fFyd=rv2I%)xspCn_$gCl`+z=DtE+OZ0JdIj!MI^$aDO>`o2mJ zzzS^Z0zaNfp1jpJd11+PkFpDh&zN+93rR|#xc<`Jthz3I!I|V}T2E8BtOxO)SY?M? z59u`CadEs?bJQzwv`nj-NWWV~aS{3VrFmJ~gFW_=EeB14s7KDY)o`_VkIybMn6Itp&Cx;G0X+z1CfIQ9&O}!Ha4g|6AQa$gfsqY* zuXkuDHdas@sgu3VrAr8MSOddrT%j;VMpwOjUeubg+(=n5DRUTO5$s{>>}Wq(bA@iU zalS5agR2nXIBQ)bGsJA6S{Sv-Ku$h^={8Eh`2bWVkws}488G4Ve;69BeRpcrF3j*A zCnx1O(xzQi@C$-5nhxdJ5@)mA-PiH_jqRa=c{xf59n8_jNin0mL}pzB8+!8`NZ30n z-HRg=lTMiF7}x*PsZ0Kayzplg+BtPiBZ8x~%wOGMM5d1Bt1%a|Y?nxttRVWQ z3~K2h+HW@(81KY5WcDsE4i7J&0-k~NgeN+G6m52&k0;86dgseu}qp~Zl-!$jnQ9V z2-?Ws6&GS(#+}MY#FpjuS9aX$F=;eu^z~iwTAw9E<4IYxxFv2&0XFgXQ;}{b_7{to zC?F7jmKF+JZOWqv&}@C3pJwVA$q21>b*$B)=I;HX)R@|e)IO2TNxu3 zyM2Z>+2TI{X9_Z#_l<});LY+)r9`A9RUDiQd;#+9p`#P)3yIgMGMHp%3)x1?!MDHZ zV~wg+#Ts-!Ppb0KlTLE9ErihV%bz(NY-w)RxLDg)U$a(ncil8)jiuJQ652&G&)Lz< zJ_U4IJ(@!WVe9X_vz&i4ygbW#UUP~*d3JC7D&pb5DMznml?3*;(&$9UIFMri zvJHyVE~btV=Uka8_>e)an>(el^d#uW|+j}DxM^1(@l@lk?hY3ngwGa2~#{OzoqJ; zvZFobe>*v5N>=4n&zIKbO-Tdm&VjX15x8H;KhJj;;otY0KBMsIk3N8VNeS;PH!s3` zb3g^aAVNK5cELPj=vK0Ct%1_uCW(ak&CN~0ozES;7?svySkp=qbIO|8-o#{MJ=W%k zWc)syKFxya>K7F>18#8(^JccvO;czDrRB;nPPV8m)r=rcujBYcTbmtdkO``t25H9I zH~X=N^E3sOw3Uej^#B}(h^h{AXg%&XFqg?M5qNET>V<_)Cz=PF5jTl&472d}S@tG7 zvmJz8%bwkF)$_uasjx)bYQHD^1(kl-EAQL9u$SXF5e{N!@a7dl*KHbW2~TE{U77>534~{`{yHrhp#33K?z~2q{s@>DJgxzl%^gwaF2AMr zk|-jj>q&xoyOcRVj&It~(@E9s1*U|q)9wZxU}J*@W=mUKu&S$N`wG5^H`i1EW#mY3 z*RGa2V2vqS=ftTdk`p+JTSq#b}sWi-W zsu&g`TYl6tp@a*JD%5~IuKJ-6j3rs(FK7z7bdSS)p_Ehy5Dm=!O3nkiN$rp_Aa;v} zwJhpiZV#ZsglPChphpl^ybi=RRrJKNmdIOOP5)9oelOD+?IKgGfX>5S!PT`3 z>|uoDA8F_kiqNEIoIpz7b3^NIg%v|*g~X3jJ7x}3Q9g;9=-B0*Znw+}-9bx#uWQU@ zON8J+T{M?ieh-q8xTx2#{ZXW%2Gr7HwM@U!Jz2-*RuZ3uSRUg~FDhrvs@%f!*r#!x ztdk&#J(*;(lDT+Xr6s*pTN+0THuy~DkWDU+aKQ|8#*TuHm**BzDg4+3 z^^s`?q9K#g%L3?D1SBeh_z?PyiA*u{e32tI39ogL=0#Q2i@ zHL|!f;r3X}q+ID4s(fAsBV-hQ7ffPv(;%~v8Lfe9jF%%Tj1pCxt zj$oB~ywQC2saIuquq2{`(tXDaCO&>;zFhB3`@X*|tiP`WvFE76jS#g9vIU>h7*l!Q z9N`0fdkV|yo6U*|?~W(GIwNlJW8R}X?CF)Fc{B*{;4`fJG;$~`xQ27zkdpg%1Pg{I zU;$sTxE8X#(!^daq$q2pqiNFA`}6w1=uV$Hk12GByYq)A^L<9~Epk7q^f+LZM=U|lrJGAigPw8?o2uNO@plreJKo4Ai+t;alJc*BG+0}B;Z5_Zq z>y;&k-xHKFgP7BjxN>iWk!+XXjQbZXkQBEYtqU97MM<9Z0jpICi?JYMGDsfyuL*jb z0DO|Ea6P#SyIRP#xsfp#vyzko{``1ptF(q&T6r)`N;@QZ6_FxwtZkhLhY^VI>v0zA zFdlZz9u_q)nt^L&v+MedYucr}JUB@W4nGayyy&{$+HTcR^{}H&0HvD(XaE?|AS$eD z54V*q$rb-c-Ld@d&G_tmvBgGex3yHXllt}8X0z}C zcIslZIeh6`yx_p*))ES=4w8|{;!HNn`J`HOVbx(gaML1(YgC%`>YGSzG|w878xt8Dkf@6_F)GE=rUlb*)8dp)A=dDv>4alx*EX_?@Zlz5VXZ z{oeDMdCko8d4JxY=XpNw^E~ID`9!4;Cgh4N` zc#*O}Lq~lByfXjp+L|2KtuM%B!_!K-2VWJYGF)WDPT;lkoX^d9OL95#B}B=DE@q>> z3MD1ItCh8ttTS?E?XcL|IMtEi%XFn3wrZyNysxqn_paXGq0oH>o;cW+V;dSOE@dVl z|5E(M>sh2L(PGxiK37apUKN9rcMO>r!@OjV#&uQ4k@}9l70F2W%rN!2)QNBl>~ef* zb%uN^%s;6s#_M*?%?q1FGs;)qW+xq3cVMe_W8#>BxSY72wvcAatlJCTy@9PG+Bi%PW-RTL7L8INCIVCACHrqB?yjeW?$cSXUVkULjV zPP)&&<%1PCz8ox^Z81ce&fpn8BJK<%H_qHWVyaM-f5A@@_q@)frTpgc+gn3? zvwaB)L?a?^lzf?p232KNa93`bg_Akv%n5Yx=;?e!(UAEF*KuMEdFDkr|9xtEfns;^ zjoBB&(%zY*0&|$Mq>5$!q4rc)8y?hg#!pts@7f|#4y9jf?iQ=z-lJ|js;p&quk2@*l(8$*8y504L^h%2jEba2?=3|%k+0|54dL{L!L`tT1I-alKK?_>#2$dY~ z4!wbDM(?Tb3Ej*7+i_>4roK^Ni4%E*VX_|ILBh>c9?BqY&gqH zP$C%Q%}3i9Diz_KM6Y>zv>ypry5SGIv;U@=a{4jHR;>KH`XM>>s&lE{=dE*-rB#ga8IC`{XzDT>C|E6bSO?2+f6x`unCQTR&P1gRmRkH~bjuqN{wPw* zC|ADn=%b^=4Q+g8eA5T?Kh=#1@9s(-u-(6d75--W?A&J7Xwa1J^H7Si(P6P?Qtf5<%$F!MO_*hxoLyHUO7At+ ze9m+8fJRkcx~kMJpHINA79w){k}3F09QBX+NyC~sl0cO_5GU&o6@c+7i>rszSh=O9VcdXqrfWtm$UtkW%#c= zZZS5}%#`s8yqc^2klOWh>bRf^L-R~;%i+Eoiat^!zg&ARf&s^kj-}o{86&Vzx4k5| z>&6AK4(d2^CA=`n4`1C^mP!sMYMxy8L1<6^kq^fvf7#1@=fE*r9jxhlKjd$wPim&) zOqXGSa<@O{it)6w6nyfF&vP+e8#_1C{PeliS}ZWcRI_zj2Q|H`p7ngp=gC{wF-aG^ zfD2D|KQHvyw|TVM^WM0Klgel zUqw~g7TYBbM}K5rGFuuJ0v)XO0?+EMPHd)q@DEG#zbo5^&TMJ4dDHfJuZ+zWKaJb1 zsx0xO=Vkse#*-zFi+|U-h}~)9t*GCX)77aI+gQ{zGCcIA_#W}&**H2Hjgwvy3olx#@phsfnN;w!Y7Hdynfsr z7R#4RBy#K(gNv6I7v_dXpS$}U;W^wa6?N!hmx^T6-oZO%U6PR z_o2G2`+IPG7#XSPEn|y=Mmbo~kHKI5^)k2qFrpd^B6r@Y3{lT&d^XFzy&*=Il0DRY zO^BH6b7g7xS!GjG;c&?X?mE?DBgx%@Rc@7!A_yu7MVIj-I^X|XCUYOeQo@936cGfvT9`(vT zANG?S;%WnW<6IVp{p1&x9u6#TAnR`$@)ubw+GTf1Fx8SfYnTjk-y*bNIZ}vL$$30) z$U1ocnYdg=$0l*gNuFwUeByrd$L+0dLZXyQ%6=I|v~%$1h@z-k?T$kl@WRo6<|v09 zuG~_Md5Ildp-0EPI$nqG6u4hj`ZniYbCC&MFGsXUc5?EVhujH5en#nM^@h*IBc&TB zB(S`C36klz_lAL|uN5>7-HlwHkl0Q;YNnrb z((klbV>E(z|S%D>${8auOi7T*PnvhH=UWSU=GsTf`! z!MzH;`14Ev>fOVZ&x83{+U1uTFONLz>B)WIwlxDwYRL3Se#7-B@{k%kVgLE(x!H#C z5fc>kZ9~JO$VGeF`+(@l-7bZ$2PR7EV_d2C#Z0|Nt}MkIS?0?ui!zm7P5AvpD+9ma zU*e7R@uytSyr`A6928a;`Sa>3*NGjc15KBcHs2h2R1Naub$J#1$>*Q6f2dsPk`<12 zODsz{8!6z{Ux^w^zv?cqJ36JgWv9sftEhC1I@=aRh+uWA|Ekzn@42#t&wIn_JkJ>L zMNGB|CHqb58{aXkh)+t-7aWo?;GtwmuQQJ+fX}+Fqe`X?O+1OOgh|LybBqc^yW)L5 z4Cfh(KPWFSDc7=a6e-tXc>NhY3q=%zx5sC0&o^*35QDZl7lf7O70EuP>3X z-t2G+J}ZE&;M)_WlF1r&{rui;byZ^hihS@Y?SZWK;%K>!$<*sr`DumXrjuJOxeTv0 z2X49XQ#HJ6!*Ayg2kyRHB!?Nv4fi!gH&3x z&o>_KT%9sMU?4Ad^!mvYhI83|*>iUQgQh8S{YR4{;mZCJ8KcA$)t4IlwJ+hCfvpSX z+Jv6!<*46h!xe6y_dHieKKDzcj=uoU3#(jbp6ItJHl7G4rPIO5FIUt`oo>ayMdq8$ z?0I@JgD16tKXXXJ()Fr1*OW#0i7UOsucnwE8hYV3u4knC|yy z*6Dvevkv#4&aBfl)ie5!XVw}0@r@2L$Xb6LN~g`FgLoLs8Akz;z+czjP;f7h!6ebB ze?mA%*}>gFGKgdTHBV1DdOLx{WW~bW!zdISBl6D?dyon;NO*t%U!Gicmc(^@-7DoThK^u?_l4*1bNM-3bkpdYw1_@-s zJ>8tX4+02gvFJ!09VUolK#}6{5v0TMQRlDVbl~o^Fa{pfMgDDGczF0bv|Ln7!{=~y{JFK2rf_wQ)5l%v^SvlRR7AV9cP7>P_kL2G|wrqVc$d^Nj)pwph7zOSCBQ09{H~T42~82uK;&QuxfyXIi$g@`u_`v zM0!$55&z2P0aEDy0&u`l3FNh6a>Q6eAyEk5{4rd^A14|f$61QAfh;hB1^Gsz(AQ)| z(+FW4xDyRW;AD(SAh94>;mF^X(KY<>JPeM3qd;1*4hHcde_&01jAi2(OpaQ1f*>8h zk;wpo77ncdtq5rtpwYiB2&g*k!e|2cFa}u@U@#-8cmR^Rwwg9H(*tC(m}`j42FJo7 zkv3rz`kI0zlLFUDstc4K8Xig&66xq{>#+umvp$qk8e^?AhT|AisLViNemC-GbyG#6 zU2Hs^Y_ZlZXbj2&tE>vLp@0zqoIya#3;FG44nUXzP@SRyO5Y4>Yw-O@oj(NrQ#3z> ztu2}#!vBM4emHLp(Qpb0NTIPoAdCu0LW|QTNJJ7y00#O=*4rBhvQp}ox#r%KQeSOuG;BaLE$iy>9 zU-S$AO82EYb2Ls1X9AJ5Fn~q-+JgWbHS%jqqSHuJ78Dya5*P{K00famM`!{FP9s2Q z!Vw%0^c(6(h%a{m0`PQm{0gOpQ362*KqCSK5|IcpppFDJHXN0y4LL(+fONPr6J&+a z0j*F#iwgX(UqHw}j)LJ|w8z(1WaH@OZqA0%PGi6+(D0Y!GAVQ{ zg-FH)F*yVzPVFX>zYf#G7$EkW1+cMo_kak@mE16Btd*yulMU9*#l-_oBvA>#-;973 zE0PYiXvkHlk^|aw96p2$wM#$?i~#Wfg92y~f#_Jk*9@*4jU|#IAde}`*uT^0s6!s% zIotBp9~N}4LKaR`kY)%pJYemBa<;d12i$B?HfURjj1xNcYlu*3h=mxS1t?JQB{5=k zpihHuoH%L_)cJ$p>VO@C1m%hW=ota}x_Slx24pb+42cPuw$bUFPfG?!2*$Cr@idCX zmq!*YJ-8OYk=K`9hgv!#002v5YtR4y literal 0 HcmV?d00001 diff --git a/perl-File-Fetch-0.42-1.fc20.src.rpm b/perl-File-Fetch-0.42-1.fc20.src.rpm new file mode 100644 index 0000000000000000000000000000000000000000..6252e5cd29b632437bd5db28fcb734444bf74ead GIT binary patch literal 24063 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