I use WWW::Mechanize to fetch and process web pages. I have a piece of code, which looping through a list of web pages. It looks approximately like this:
while (<$readFileHandle>) {
$mech->get("$url");
}
Now the problem occurs when one of the web pages in the list does not exist for some reason(which is ok). The issue is that in this case - the program returns an error and exits. The error looks like that:
Error GETing <url> Not Found at <PATH/file.pl> line ...
How can I ignore such type of error? I want the program just keep running.
You need to use eval {}; for this:
while ( my $url = readline($readFileHandle) ) {
chomp $url;
eval {
$mech->get($url);
};
if ($#) {
#error processing code
}
}
Related
I have a website using a perl script for customers to upload a pdf file for me to print and post the printed pages to them.
I am using PDF::API2 to detect the page size and number of pages in order to calculate the printing costs.
However, if the pdf file is password protected this does not work and I get this error -
Software error:
Objind 9 does not exist at index 0 at /home5/smckayws/public_html/hookincrochet.com/lib//PDF/API2/Basic/PDF/File.pm line 758.
I am trying to use the isEncrypted feature in the pdf::api2 module to catch that the file is encrypted in order to direct the customer to a different page so they can enter the page size and page number manually, but it is not working for me.
I just get the same error message as above.
I have tried the following code snippets found elsewhere.
my $pdf = PDF::API2->open( "$customer_directory/$filename" );
if ( defined $pdf && $pdf->isEncrypted )
{
print "$pdf is encrypted.\n";
exit;
}
while (glob "*.pdf") {
$pdf = PDF::API2->open($_);
print "$_ is encrypted.\n" if $pdf->isEncrypted();
}
Any help would be greatly appreciated.
My guess is that the PDFs might use a feature that your version of PDF::API2 doesn't support. This is a workaround for the problem.
Wrap the call to isEncrypted in an eval, catch the error and handle it.
This will only work if the error does not occur on unencrypted files.
my $pdf = PDF::API2->open( "$customer_directory/$filename" );
if ( defined $pdf ) {
eval { $pdf->isEncrypted };
if ($#) {
# there was some kind of error opening the file
# could abort now, or look more specific, like this:
if ($# =~ m/Objind 9 does not exist at index 0/) {
print "$pdf is encrypted.\n";
exit;
}
}
# file is not encrypted, opening worked, continue reading it
}
I've currently got a small script running that sends a 401 to the client, upon cancelling and not providing user details the script will return nothing.
I'd like to send a redirect to the page they have come from instead.
The main subroutine looks like this;
#!usr/bin/perl
use strict;
use CGI;
sub checkAuth {
my ($user, $pass) = &getAuthUsers(); # Get the user and pass of already authenticated users.
unless ($user) {
&sendAuthenticationHeader(); # Send 401
}
# Check user against DB and return 1 for success.
if ( &checkUser($user, $pass) eq 'Y') { return 1 };
else { # This is the redirect I'm trying to issue.
my $cgi = CGI->new();
print $cgi->redirect($ENV{HTTP_REFERER}); # Redirect to the referer url
exit;
}
}
Unfortunately whenever I try to send new headers it's just received as plain text.
Any help is appreciated, thanks in advance.
sendAuthenticationHeader() emits a header with a 401 status code.
print $cgi->redirect($ENV{HTTP_REFERER}); emits a header with a 302 status code. Of course, since you've already emitted a header, this gets treated as the body.
There's no point to return a 401 if you want to redirect. Change your code to
sub checkAuth {
my ($user, $pass) = getAuthUsers();
if (!$user || !checkUser($user, $pass)) {
print CGI::redirect($ENV{HTTP_REFERER});
exit;
}
}
Notes:
Removed incorrect &. Don't tell Perl to ignore the prototype of subs. Address the underlying issue instead if required.
The return value of checkUser is boolean, so it should return either a true or a false value (e.g. 0 or 1), not two true values (e.g. N or Y). The above code assumed you fixed this.
I'm a newbie in Perl.
I have a JSON-RPC server running at http://localhost:19000 and I need to call checkEmail() method.
use JSON::RPC::Client;
my $client = new JSON::RPC::Client;
my $url = 'http://localhost:19000';
my $callobj = {
method => 'checkEmail',
params => [ 'rprikhodchenko#gmail.com' ],
};
my $res = $client->call($url, $callobj);
if($res) {
if ($res->is_error) {
print "Error : ", $res->error_message;
}
else {
print $res->result;
}
}
else {
print $client->status_line;
}
When I try to launch it it tells following:
perl ./check_ac.pl
Not a HASH reference at /usr/local/share/perl/5.10.1/JSON/RPC/Client.pm line 193.
UPD:
Full stack-trace:
perl -MCarp::Always ./check_ac.pl
Not a HASH reference at /usr/local/share/perl/5.10.1/JSON/RPC/Client.pm line 193
JSON::RPC::ReturnObject::new('JSON::RPC::ReturnObject', 'HTTP::Response=HASH(0x9938d48)', 'JSON=SCALAR(0x96f1518)') called at /usr/local/share/perl/5.10.1/JSON/RPC/Client.pm line 118
JSON::RPC::Client::call('JSON::RPC::Client=HASH(0x944a818)', 'http://localhost:19000', 'HASH(0x96f1578)') called at ./check_ac.pl line 11
This error means that your JSON-RPC server is not actually one, inasmuch as it does not satisfy requirement 7.3. The error is triggered when JSON::RPC::Client assumes the document returned by the JSON-RPC service is well-formed (i.e., a JSON Object), and this assumptions turns out to have been in error. A bug report to the author of JSON::RPC::Client would be an appropriate way to request better error messaging.
I would attack this sort of problem by finding out what the server was returning that was causing JSON::RPC::Client to choke. Unfortunately, JRC fails to provide adequate hookpoints for finding this out, so you'll have to be a little bit tricky.
I don't like editing external libraries, so I recommend an extend-and-override approach to instrumenting traffic with the JSON-RPC server. Something like this (in check_ac.pl):
use Data::Dumper qw();
package JSON::RPC::InstrumentedClient;
use base 'JSON::RPC::Client';
# This would be better done with Module::Install, but I'm limiting dependencies today.
sub _get {
my ($self, #args) = #_;
return $self->_dump_response($self->SUPER::_get(#args));
}
sub _post {
my ($self, #args) = #_;
return $self->_dump_response($self->SUPER::_post(#args));
}
sub _dump_response {
my ($self, $response) = #_;
warn Data::Dumper::Dump([$response->decoded_content], [qw(content)]);
return $response;
}
package main;
my $client = JSON::RPC::InstrumentedClient->new();
my $url = 'http://localhost:19000';
... # rest of check_ac.pl
This wraps the calls to _get and _post that JSON::RPC::Client makes internally in such a way as to let you examine what the web server actually said in response to the request we made. The above code dumps the text content of the page; this might not be the right thing in your case and will blow up if an error is encountered. It's a debugging aid only, to help you figure out from the client code side what is wrong with the server.
That's enough caveats for now, I think. Good luck.
It seems to be a bug in method new of JSON::RPC::ReturnObject.
sub new {
my ($class, $obj, $json) = #_;
my $content = ( $json || JSON->new->utf8 )->decode( $obj->content );
#...
# line 193
$content->{error} ? $self->is_success(0) : $self->is_success(1);
#...
}
$content's value will be something returned from a JSON::decode() call. But looking at the documentation, it seems that JSON->decode() returns a scalar which could be a number, a string, an array reference, or a hash reference.
Unfortunately, JSON::RPC::ReturnObject->new() doesn't check what sort of thing JSON->decode() returned before trying to access it as a hashref. Given your error, I'm going to go ahead and assume what it got in your case was not one. :-)
I don't know if there's a way to force a fix from your code. I'd recommend contacting the author and letting him know about the issue, and/or filing a bug.
I am able to open Lotus notes api using Perl, without errors, also I can get list of views that includes Inbox, but when I try to read messages from that view it appears empty? What might I be doing wrong? (in fact it seems like something might of changed on notes side as this code used to work before)
Result of code below:
NAME of View is: ($Inbox) has count of: 0
etc.
CODE:
use Win32::OLE;
my $Notes = Win32::OLE->new('Notes.NotesSession')
or die "Cannot start Lotus Notes Session object.\n";
my $database = $Notes->GetDatabase("",'mail\VIMM.nsf');
$database->OpenMail;
my $array_ref = $database->{Views};
foreach my $view (#$array_ref) {
my $name = $view->{Name};
print "NAME of View is: $name ";
$view = $database->GetView($name);
print "has count of: ", $view->{entryCount}, "\n";
}
Is the mailbox open to all users? You could try setting the -Default- access to Manager and grant it all available roles, just to make sure it's not a security issue preventing the documents from being seen.
I believe it is spelled "EntryCount"?
Also, I recommend "use strict" and "use warnings".
Per runrig's comment, EntryCount is an attribute, so I believe you need:
$view->{entryCount}
Try checking Win32::OLE::LastError() messages. You can do this explicitly with a sub like:
sub w32_ok {
if (my $error = Win32::OLE::LastError()) {
print "Win32::OLE Error! Got: $error";
}
}
Or, have it croak errors, like:
Win32::OLE->Option( Warn => 3 ); # will now croak on errors.
It may be having problems accessing the data you want.
i'm using the following:
<?php
$doc = new DOMDocument();
$doc->load('http://twitter.com/statuses/user_timeline/XXXXXX.rss');
$arrFeeds = array();
foreach ($doc->getElementsByTagName('item') as $node) {
$itemRSS = array (
'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
'desc' => $node->getElementsByTagName('description')->item(0)->nodeValue,
'link' => $node->getElementsByTagName('link')->item(0)->nodeValue,
'date' => $node->getElementsByTagName('pubDate')->item(0)->nodeValue
);
array_push($arrFeeds, $itemRSS);
}
for($i=0;$i<=3;$i++) {
$tweet=substr($arrFeeds[$i]['title'],17);
$tweetDate=strtotime($arrFeeds[$i]['date']);
$newDate=date('G:ia l F Y ',$tweetDate);
if($i==0) { $b='style="border:none;"'; }
$tweetsBox.='<div class="tweetbox" ' . $b . '>
<div class="tweet"><p>' . $tweet . '</p>
<div class="tweetdate">#' . $newDate .'</div>
</div>
</div>';
}
return $tweetsBox;
?>
to return the 4 most recent tweets from a given timeline (XXXXX is the relevant feed)
It seems to work fine but i've recently been getting the following error sporadically:
PHP error debug
Error: DOMDocument::load(http://twitter.com/statuses/user_timeline/XXXXXX.rss) [domdocument.load]: failed to open stream: HTTP request failed! HTTP/1.1 502 Bad Gateway
I've read that the above code is dependant on Twitter beign available and I know it gets rather busy sometimes. Is there either a better way of receiving twits, or is there any kind of error trapping i could do to just to display "tweets are currently unavailable..." ind of message rather than causing an error. I'm usnig ModX CMS so any parse error kills the site rather than just ouputs a warning.
thanks.
I know this is old, but I was just searching for the same solution for a nearly identical script for grabbing a twitter timeline. I ended up doing this, though I haven't been able to thoroughly test it.
I defined the twitter url as a variable ($feedURL), which I also used in $doc_load. Then, I wrapped everything except for the $feedURL into this conditional statement:
$feedURL = "http://twitter.com/statuses/user_timeline/XXXXXXXX.rss"
$headers = #get_headers($feedURL);
if (preg_match("/200/", $headers[0])){
//the rest of you original code in here
}
else echo "Can't connect user-friendly message (or a fake tweet)";
So, it's just checking the headers of the the feed's page, and if its status is 200 (OK), then the rest of the script will execute. Otherwise, it'll echo a message of your choice.
(reference: http://www.phptalk.com/forum/topic/3940-how-to-check-if-an-external-url-is-valid-andor-get-file-size/ )
ETA: Or even better, save a cached version of the feed (which will also ensure you don't go over your API limit of loads):
<?php
$cache_file = dirname(__FILE__).'/cache/twitter_cache.rss';
// Start with the cache
if(file_exists($cache_file)){
$mtime = (strtotime("now") - filemtime($cache_file));
if($mtime > 600) {
$cache_rss = file_get_contents('http://twitter.com/statuses/user_timeline/75168146.rss');
$cache_static = fopen($cache_file, 'wb');
fwrite($cache_static, $cache_rss);
fclose($cache_static);
}
echo "<!-- twitter cache generated ".date('Y-m-d h:i:s', filemtime($cache_file))." -->";
}
else {
$cache_rss = file_get_contents('http://twitter.com/statuses/user_timeline/75168146.rss');
$cache_static = fopen($cache_file, 'wb');
fwrite($cache_static, $cache_rss);
fclose($cache_static);
}
//End of caching
?>
Then use $cache_file in your $doc->load($cache_file) statement instead of the actual feed url.
(Adapted from here: http://snipplr.com/view/8156/twitter-cache/).