For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > January 2008 > Newbie Perl Question









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Newbie Perl Question
Bryce

2008-01-22, 4:29 am

Can anyone help me modify this Perl script?

#!/usr/bin/perl
use CGI ':standard';
$query = new CGI;
print redirect($query->param("url"));

I need it to send a standard 404 response (instead of the standard redirect()
seen above) if the "url" GET parameter was non-existent or null, or if the HTTP
Referer didn't contain the case insensitive substring "mysite.com/thisurl.php".

I like helping myself and tried my best using tutorials to do this on my own.
Alas, my attempts have failed. Nothing but 500 server errors. E.g.:

#!/usr/bin/perl
use CGI ':standard';
$query = new CGI;

$destination = $query->param("url")
$origin = $ENV{'HTTP_REFERER'}

if ($destination !eq '' && $origin =~ /mysite\.com\/thisurl\.php/) {
print redirect($destination);
} else {
print "Status: 404 Not Found\n\n";
}

Many thanks, and apologizes in advance for my n00bness.
RedGrittyBrick

2008-01-22, 8:16 am

Bryce wrote:
> Can anyone help me modify this Perl script?
>
> #!/usr/bin/perl
> use CGI ':standard';
> $query = new CGI;
> print redirect($query->param("url"));
>
> I need it to send a standard 404 response (instead of the standard redirect()
> seen above) if the "url" GET parameter was non-existent or null, or if the HTTP
> Referer didn't contain the case insensitive substring "mysite.com/thisurl.php".
>
> I like helping myself and tried my best using tutorials to do this on my own.
> Alas, my attempts have failed. Nothing but 500 server errors. E.g.:
>
> #!/usr/bin/perl
> use CGI ':standard';
> $query = new CGI;
>
> $destination = $query->param("url")
> $origin = $ENV{'HTTP_REFERER'}
>
> if ($destination !eq '' && $origin =~ /mysite\.com\/thisurl\.php/) {
> print redirect($destination);


redirect() is a procedure of CGI.pm.

> } else {
> print "Status: 404 Not Found\n\n";


That print does not use any procedure of CGI.pm

I expect your print statement places text in the body not in the
headers. A proper 404 response is part of the headers.

> }
>
> Many thanks, and apologizes in advance for my n00bness.


Generally I think it is a mistake to mix the use of CGI.pm with plain
print statements. I'd choose one approach and use it consistently
throughout.

CGI.pm can be used in procedural or object-oriented fashions. Choose one.

The documentation can be read by issuing the command
perldoc CGI

Somewhere in there are these examples:

print $query->header('image/gif');

-or-

print $query->header('text/html','204 No response');

-or-

print $query->header(-type=>'image/gif',
-nph=>1,
-status=>'402 Payment required',
-expires=>'+3d',
-cookie=>$cookie,
-charset=>'utf-7',
-attachment=>'foo.gif',
-Cost=>'$2.00');

Note that these are in object-oriented style. You should be able to work
out the equivalent procedural statements.

A '404 unavailable' response may not be appropriate - I'd review all the
other documented 400-499 responses to see if any of them are more
appropriate. You might want to use something like '403 Forbidden' instead.

I hope that helps.
Bryce

2008-01-23, 4:24 am

On Tue, 22 Jan 2008 10:45:10 +0000, RedGrittyBrick wrote:

> I hope that helps.


I appreciate your response, and yes, your advice would normally be helpful. :-)

The problem is, I know nothing of Perl. I created the demonstration code in
my original post by falling back on my general knowledge of basic coding syntax,
and by gleaning hints from Perl code examples I discovered online. Admittedly,
that's a horrible way to write code. But when faced with performing a simple
task in a language one doesn't know, it sometimes works. ....and other times,
it doesn't. Like this time.

I hate asking others to write code for me. (I do learn the languages I'm most
often subject to.) Alas, asking for a free lunch was the essence of my plea in
this case. I assumed karma would excuse that, since this is only the second
time I've had to use -- and ask for help with -- Perl in five years.

> A '404 unavailable' response may not be appropriate - I'd review all the
> other documented 400-499 responses to see if any of them are more
> appropriate. You might want to use something like '403 Forbidden' instead.


You're correct, except that in this case, the goal is making the script appear
to not exist if hit by someone coming from anything other than the desired HTTP
Referer, or if no &url= parameter is provided. (I'll spare you the unamusing
story of why this corny deception is necessary.)

Thanks for the reply.
Jürgen Exner

2008-01-23, 4:24 am

zerospam@example.com (Bryce) wrote:
>You're correct, except that in this case, the goal is making the script appear
>to not exist if hit by someone coming from anything other than the desired HTTP
>Referer, or if no &url= parameter is provided. (I'll spare you the unamusing
>story of why this corny deception is necessary.)


Both of which can be faked trivially, of course.

jue
Bryce

2008-01-23, 8:14 am

Jürgen Exner wrote:

> zeros...@example.com (Bryce) wrote:
>
> Both of which can be faked trivially, of course.


Of course. That's why I wouldn't be using this method if the Referer URL in
question were publicly known. Which it isn't.
RedGrittyBrick

2008-01-23, 8:14 am

Bryce wrote:
> Alas, asking for a free lunch was the essence of my plea in this case.


Shame on you.

#!/usr/bin/perl
use strict;
use warnings;
use CGI ':standard';

my $query = new CGI;
my $destination = $query->param("url");
my $origin = $ENV{'HTTP_REFERER'};

if ($destination ne '' && $origin =~ m(mysite\.com/thisurl\.php)) {
print redirect($destination);
} else {
print
header(-status => '404 Not Found'),
start_html('Page Not Found'),
h1('Page Not Found'),
p('Please ignore the man behind the curtain.'),
end_html();
}

Shame on me :-)

It's untested - if your free sandwich contains bugs, you're on your own.
Gunnar Hjalmarsson

2008-01-23, 8:14 am

Bryce wrote:
> I like helping myself and tried my best using tutorials to do this on my own.
> Alas, my attempts have failed. Nothing but 500 server errors. E.g.:
>
> #!/usr/bin/perl
> use CGI ':standard';
> $query = new CGI;
>
> $destination = $query->param("url")
> $origin = $ENV{'HTTP_REFERER'}
>
> if ($destination !eq '' && $origin =~ /mysite\.com\/thisurl\.php/) {
> print redirect($destination);
> } else {
> print "Status: 404 Not Found\n\n";
> }


Add this line to the beginning of the script, to get more useful error
messages displayed in the browser:

use CGI::Carp 'fatalsToBrowser';

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
Ted Zlatanov

2008-01-23, 7:13 pm

On Wed, 23 Jan 2008 10:53:07 +0000 RedGrittyBrick <RedGrittyBrick@SpamWeary.foo> wrote:

R> use CGI ':standard';
....
R> my $query = new CGI;
....
R> my $origin = $ENV{'HTTP_REFERER'};

There is a referer() method for CGI queries. If you're bothering to
create the query object, you may as well use it.

Ted
Ted Zlatanov

2008-01-23, 7:13 pm

On Wed, 23 Jan 2008 12:08:42 +0100 Gunnar Hjalmarsson <noreply@gunnar.cc> wrote:

GH> Add this line to the beginning of the script, to get more useful error
GH> messages displayed in the browser:

GH> use CGI::Carp 'fatalsToBrowser';

This can be very insecure :) I usually also advise "and remember to
turn it off in production."

Ted
Joe Smith

2008-01-24, 4:29 am

Bryce wrote:

> if ($destination !eq '' && $origin =~ /mysite\.com\/thisurl\.php/) {


That is not valid perl code.

> I like helping myself and tried my best using tutorials to do this on my own.
> Alas, my attempts have failed. Nothing but 500 server errors. E.g.:


The first thing in getting rid of "500 Server Error": you _MUST_ make sure
the code compiles correctly. Use perl's "-cw" command-line option to test that.

linux% cat test.cgi
if ($destination !eq '' && $origin =~ /mysite\.com\/thisurl\.php/) {
print "OK\n";
}
linux% perl -cw test.cgi
syntax error at test.cgi line 1, near "$destination !"
test.cgi had compilation errors.
linux%

The string inequality operator is "ne" (and also "not $string1 eq $string2").

> was non-existent or null, or if ... didn't contain the case insensitive substring


Case insensitivity is done with "i" after the regex. Since "0" is not a valid URL,
the test for non-null can be done in a more simple fashion.

if ($destination and $origin =~ /\bmysite\.com\/thisurl\.php/i) { ... }

The \b ensures that "foobar123mysite.com/thisurl.php" won't match.

-Joe
Bryce

2008-01-25, 8:14 am

On Wed, 23 Jan 2008 10:53:07 +0000, RedGrittyBrick wrote:

> Shame on you.
> [...]
> Shame on me :-)
>
> It's untested - if your free sandwich contains bugs, you're on your own.


You're a saint, Mr. RGB! Works perfectly. A thousand blessings on your
compilers. :-)

And thanks also to the others who responded:

Gunnar - "use CGI::Carp 'fatalsToBrowser';" proved infinitely useful while
making one customization I decided upon to RGB's script. Thanks!

Ted - Yes, I'd definitely #exclude it post-testing. :-)

Joe - So noted. I always look for how to enable runtime error output for
problem-finding purposes. Unfortunately in this case, no shell access was
available to me. That's part of why I wound up in c.l.p.m begging help:
couldn't even diagnose *why* my own attempts at the script were failing.
Thanks also for the note on the matching. I love optimizations like that.
Tad J McClellan

2008-01-25, 10:13 pm

Bryce <zerospam@example.com> wrote:

> Gunnar - "use CGI::Carp 'fatalsToBrowser';" proved infinitely useful



There are lots of infinitely useful tips in the Perl FAQ.

If you are doing programming for the CGI, then you should
read all of the FAQs that mention it:


perldoc -q CGI

How can I make my CGI script more efficient?

Where can I learn about CGI or Web programming in Perl?

What is the correct form of response from a CGI script?

My CGI script runs from the command line but not the
browser. (500 Server Error)

How can I get better error messages from a CGI program?

How do I make sure users can't enter values into a form
that cause my CGI script to do bad things?

How do I decode a CGI form?


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com