Deciphering File::Fetch error - perl

I was trying to use File::Fetch in a simple script to download a file. Unfortunately, it errors out and I can't seem to find why.
use strict;
use warnings;
use File::Fetch;
my $url = 'https://ftp.mozilla.org/pub/firefox/releases/42.0b7/linux-i686/en-US/firefox-42.0b7.tar.bz2';
my $ff = File::Fetch->new(uri => $url);
my $where = $ff->fetch( to => '/tmp' ) or die $ff->error;
print "Downloaded to ".$where."\n";
At execution:
#./filefetch.pl
Use of uninitialized value in die at ./filefetch.pl line 12.
Died at ./filefetch.pl line 12.

Going into File::Fetch::fetch() with the debugger, the problem is File::Fetch failed to find a way to deal with the https scheme. It appears to have no support for https. It correctly returned false, but it did not populate its error field.
You are correct in assuming it should consider missing a scheme an error. You can report a bug here.

Related

Get reason for failed LWP::Simple head request

I have migrated my scrilpts from CentOS 7 to 8 and there's a new Perl version. I have the folowing snippet that uses head to check if a URL exists:
#!/bin/perl
use strict;
use warnings;
use LWP::Simple;
my $sitemapurl = "https://www.prosinger.net";
if (head($sitemapurl)) {
...
}
else {
print "The $sitemapurl doesn't exist\n";
exit(1);
}
It now always returns that the URL doesn't exist. I'm quite sure that this has to do something with https (I have perl-LWP-Protocol-https installed), but I'm not sure how to get any feedback information from head method to check what the error code is.
Any ideas?
You can use LWP::UserAgent instead of LWP::Simple, which allows you to get an error message:
my $ua = LWP::UserAgent->new;
my $sitemapurl = "https://www.prosinger.net";
my $req = $ua->head($sitemapurl);
if ($req->is_success) {
...
} else {
die "Could not head($sitemapurl): " . $req->status_line;
}
Running this code prints:
Could not head(https://www.prosinger.net): 403 Forbidden at head.pl line 15.
You can fix this (for this specific website; this will not work for all website) by setting a User-Agent in your LWP::UserAgent object:
my $ua = LWP::UserAgent->new( agent => 'anything seems to work' );
Of interest is the decoded_content method of HTTP::Response that allows you to get the content of the request (you don't need it in that case, but you might later):
my $req = $ua->get(...);
if ($req->is_success) {
my $content = $req->decoded_content;
...
}
Your code that uses LWP::Simple and Dada's version that switches to LWP::UserAgent are basically doing the same thing, except that you can get details of the error when using LWP::UserAgent.
Running the LWP::UserAgent version gives this error:
Could not head(https://www.prosinger.net): 500 Can't connect to www.prosinger.net:443 (SSL connect attempt failed error:2707307E:OCSP routines:OCSP_check_validity:status not yet valid)
And Googling that error message gives this SO answer as the first result. Is it possible that the clocks on your your client machine and the server are out of sync?

Google Maps API error in Perl

Okay I'm working on finding the latitude and longitude of cities using Perl. I found the Geo::Coder::Google module and have it installed properly, but I'm getting an error when attempting to use it. The first time I got the error I went out and got an API key from Google thinking that was what I was missing, but that didn't solve the error either. Can someone help me figure out what I'm missing?
Here is the error I'm receiving:
Google Maps API returned error: 500 Can't verify SSL peers without knowing which Certificate Authorities to trust at test.pl line 7.
Here is the code I'm using right now:
1:#!/usr/bin/perl
2:use strict;
3:use warnings;
4:
5:use Geo::Coder::Google;
6:my $geocoder = Geo::Coder::Google->new( apiver => 3, gl => 'us', apikey => 'My API Key Here' );
7:my $location = $geocoder->geocode( location => 'Mount Vernon, IN' );
8:
9:print "$location->{'geometry'}->{'location'}->{'lat'}";
10:print "$location->{'geometry'}->{'location'}->{'lng'}";
The code you have written works fine as it stands—you don't need an API key. The problem is that your Secure Socket Layer support for the HTTPS is incomplete
You should start by reinstalling the LWP library to make sure that it is up to date. You should also install Mozilla::CA to make sure that the Certificates of Authority are current. (This is the most likely cause of the problem given the error message that you're getting.)
If it is still not working after that, then the only other culprits I can think of are IO::Socket::SSL and Crypt::SSLeay, but I would be surprised if they are out of date as they should be updated as dependencies of LWP
#!/usr/bin/perl
use strict;
use warnings 'all';
use Geo::Coder::Google;
my $geocoder = Geo::Coder::Google->new( apiver => 3 );
my $info = $geocoder->geocode( location => 'Mount Vernon, IN' );
my $location = $info->{geometry}{location};
printf "%s %s\n", $location->{lat}, $location->{lng};
output
37.9322662 -87.8950267
Try:
sudo cpan
install LMP::UserAgen Mozilla::CA

perl error- Can't call method "domain" on an undefined value

#!/usr/bin/perl -w
use Net::SMTP;
$smtp = Net::SMTP->new('mailhost');
print $smtp->domain,"\n";
$smtp->quit;
I run this pl file and get error "Can't call method "domain" on an undefined value"
and in this pl file:
#!/usr/bin/perl -w
use Net::SMTP;
$smtp = Net::SMTP->new('mailhost');
$smtp->mail($ENV{USER});
$smtp->to('postmaster');
$smtp->data();
$smtp->datasend("To: postmaster\n");
$smtp->datasend("\n");
$smtp->datasend("A simple test message\n");
$smtp->dataend();
$smtp->quit;
I get error Can't call method "mail" on an undefined value
What I need todo ?
Has it occured to you that Net::SMTP may have had problems finding your mailhost, and establishing an SMTP connection? I see that you took your scripts directly from the documentation – you do have to supply an actual value for mailhost.
If you had read the documentation a bit further, especially to the documentation for the new method, you'd have found this interesting snippet:
new ( [ HOST ] [, OPTIONS ] )
This is the constructor for a new Net::SMTP object. HOST is the name of the remote host to which an SMTP connection is required.
On failure undef will be returned and $# will contain the reason for the failure.
So let's print out that reson for failure:
my $mailhost = "your mailhost";
my $smpt = Net::SMTP->new($mailhost) or die "Can't connect to $mailhost: $#";
die aborts your program with an error message. This message should tell you more about the actual error.
Do note that the example code in the documentation is not neccessarily meant to be used for real projects – it is just there to showcase the capabilities of the module. For real code, always use strict; use warnings at the top of your code, and declare all your variables with my. This helps finding more errors.

Why does my Perl CGI program fail with "Software error: ..."?

When I try to run my Perl CGI program, the returned web page tells me:
Software error: For help, please send mail to the webmaster (root#localhost), giving this error message and the time and date of the error.
Here is my code in one of the file:
#!/usr/bin/perl
use lib "/home/ecoopr/ecoopr.com/CPAN";
use CGI;
use CGI::FormBuilder;
use CGI::Session;
use CGI::Carp (fatalsToBrowser);
use CGI::Session;
use HTML::Template;
use MIME::Base64 ();
use strict;
require "./db_lib.pl";
require "./config.pl";
my $query = CGI->new;
my $url = $query->url();
my $hostname = $query->url(-base => 1);
my $login_url = $hostname . '/login.pl';
my $redir_url = $login_url . '?d=' . $url;
my $domain_name = get_domain_name();
my $helpful_msg = $query->param('m');
my $new_trusted_user_fname = $query->param('u');
my $action = $query->param('a');
$new_trusted_user_fname = MIME::Base64::decode($new_trusted_user_fname);
####### Colin: Added July 12, 2009 #######
my $view = $query->param('view');
my $offset = $query->param('offset');
####### Colin: Added July , 2009 #######
#print $session->header;
#print $new_trusted_user;
my $helpful_msg_txt = qq[];
my $helpful_msg_div = qq[];
if ($helpful_msg)
The "please send mail to the webmaster" message you see is a generic message that the web server gives you when anything goes wrong and nothing handles it. It's not at all interesting in terms of solving the actual problem. Check the error log to find possible relevant error output from your program.
And, go through my How do I troubleshoot my Perl CGI script? advice on finding the problem.
My guess is that you have a syntax error with that dangling if(). What you have posted isn't a valid Perl program.
Good luck,
is that something related to suexec module
Improper configuration of suExec can cause permission errors
The suEXEC feature provides Apache users the ability to run CGI and SSI programs under user IDs different from the user ID of the calling web server. Normally, when a CGI or SSI program executes, it runs as the same user who is running the web server.
apache recommends that you not consider using suEXEC.
http://httpd.apache.org/docs/2.2/suexec.html
From the StackOverflow page: How to trap program crashes with HTTP error code 500
I see that your include: use CGI::Carp (fatalsToBrowser);
... stifles the HTTP 500 error. Simply removing this will allow the programs to crash "properly".

Why can't I connect to my CAS server with Perl's AuthCAS?

I'm attempting to use an existing CAS server to authenticate login for a Perl CGI web script and am using the AuthCAS Perl module (v 1.3.1). I can connect to the CAS server to get the service ticket but when I try to connect to validate the ticket my script returns with the following error from the IO::Socket::SSL module:
500 Can't connect to [CAS Server]:443 (Bad hostname '[CAS Server]')
([CAS Server] substituted for real server name)
Symptoms/Tests:
If I type the generated URL for the authentication into the web browser's location bar it returns just fine with the expected XML snippet. So it is not a bad host name.
If I generate a script without using the AuthCAS module but using the IO::Socket::SSL module directly to query the CAS server for validation on the generated service ticket the Perl script will run fine from the command line but not in the browser.
If I add the AuthCAS module into the script in item 2, the script no longer works on the command line and still doesn't work in the browser.
Here is the bare-bones script that produces the error:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use AuthCAS;
use CGI::Carp qw( fatalsToBrowser );
my $id = $ENV{QUERY_STRING};
my $q = new CGI;
my $target = "http://localhost/cgi-bin/testCAS.cgi";
my $cas = new AuthCAS(casUrl => 'https://cas_server/cas');
if ($id eq ""){
my $login_url = $cas->getServerLoginURL($target);
printf "Location: $login_url\n\n";
exit 0;
} else {
print $q->header();
print "CAS TEST<br>\n";
## When coming back from the CAS server a ticket is provided in the QUERY_STRING
print "QUERY_STRING = " . $id . "</br>\n";
## $ST should contain the received Service Ticket
my $ST = $q->param('ticket');
my $user = $cas->validateST($target, $ST); #### This is what fails
printf "Error: %s\n", &AuthCAS::get_errors() unless (defined $user);
}
Any ideas on where the conflict might be?
The error is coming from the line directly above the snippet Cebjyre quoted namely
$ssl_socket = new IO::Socket::SSL(%ssl_options);
namely the socket creation. All of the input parameters are correct. I had edited the module to put in debug statements and print out all the parameters just before that call and they are all fine. Looks like I'm going to have to dive deeper into the IO::Socket::SSL module.
As usually happens when I post questions like this, I found the problem. It turns out the Crypt::SSLeay module was not installed or at least not up to date. Of course the error messages didn't give me any clues. Updating it and all the problems go away and things are working fine now.
Well, from the module source it looks like that IO::Socket error is coming from get_https2
[...]
unless ($ssl_socket) {
$errors = sprintf "error %s unable to connect https://%s:%s/\n",&IO::Socket::SSL::errstr,$host,$port;
return undef;
}
[...]
which is called by callCAS, which is called by validateST.
One option is to temporarily edit the module file to put some debug statements in if you can, but if I had to guess, I'd say the casUrl you are supplying isn't matching up to the _parse_url regex properly - maybe you have three slashes after the https?