What's the Perl equivalent of PHP's $_SERVER[...]? - perl

What's the Perl equivalent for the following PHP calls?
$_SERVER["HTTP_HOST"]
$_SERVER["REQUEST_URI"]
Any help would be much appreciated.

Another way, than variable environement, is to use CGI :
use strict;
use warnings;
use CGI ;
print CGI->new->url();
Moreover, it also offers a lot of CGI manipulation such
as accessing params send to your cgi, cookies etc...

Environment variables are a series of hidden values that the web server sends to every CGI you run. Your CGI can parse them and use the data they send. Environment variables are stored in a hash called %ENV.
For example, $ENV{'HTTP_HOST'} will give the hostname of your server.
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print <<EndOfHTML;
<html><head><title>Print Environment</title></head>
<body>
EndOfHTML
foreach my $key (sort(keys %ENV)) {
print "$key = $ENV{$key}<br>\n";
}
print "</body></html>";
For more details see CGI Environmental variables

Or you can do this and use the variable $page_url.
my $page_url = 'http';
$page_url.='s' if $ENV{HTTPS};
$page_url.='://';
if($ENV{SERVER_PORT}!=80)
{
$page_url.="$ENV{SERVER_NAME}:$ENV{SERVER_PORT}$ENV{REQUEST_URI}";
}
else
{
$page_url.=$ENV{SERVER_NAME}.$ENV{REQUEST_URI};
}

What's the environment you're working in? If it's CGI script try:
use Data::Dumper;
print Dumper \%ENV;

Related

Accept POST parameters with FCGI

I am trying to get URL parameters using CGI and FCGI.
When executing the script on my browser I am only getting parameters of my first request, but the request $count does increment.
use CGI;
use FCGI;
my $fcgiRequest = FCGI::Request();
while ($fcgiRequest->Accept() >= 0)
{
print("Content-type: text/html\r\n\r\n", ++$count);
my $q = new CGI;
print "name = " . $q->param("name") ;
print "\n";
}
You can't use CGI.pm and FCGI.pm together like this. You need some glue-code in between, because CGI needs to read stuff from the environment, and it can't in the way you invoke it.
There is a module CGI::Fast included with Perl that does this for you. Instead of using CGI and FCGI, you just use CGI::Fast and change a bit of code.
use strict;
use warnings;
use CGI::Fast;
my $count;
while (my $q = CGI::Fast->new) {
# $q is a fresh CGI object for the current request
print("Content-type: text/html\r\n\r\n", ++$count);
print "name = " . $q->param("name") ;
print "\n";
}
If you already have a CGI script, you could put that in a function and call it inside of that loop.
If you're interested in how CGI::Fast works, feel free to take a look at its source code on CPAN. The main thing is that the environment and the file handles (for STDOUT and STDERR) need to be mapped to each new request, while your implementation has CGI always parse the first one.
Please note that the examples in both the perldoc and on CPAN that I have linked are very out-of-date and don't represent modern Perl code.
Today, you would probably not use CGI any more, as it has been removed from current Perl releases. Instead, you could take a look at the PSGI interface specification and Plack on how to implement it. The good thing about that is that it provides a clear interface across different deployment-technologies (such as CGI and Fast CGI). You can just let your program run as a simple CGI with Apache or nginx, or as a persistent FCGI process with Apache or other webservers, or as a standalone application through various Plack webservers that are written in Perl and are tailored for specific purposes.
Once a CGI.pm object is created for a request, it's reused there on out.
You can reset CGI.pm by adding the following to the end of the loop:
CGI::_reset_globals();

Input parameter for perl CGI script

I need some insight on my Perl CGI script.
First of all all this is running under webmin so i'm doing a custom module.
I'm calling a CGI Perl script passing 2 parameter from another Perl CGI. The link I'm calling is in the following format:
http://IP:8080/foobar/alat.cgi?sysinfo=xxxxxxx&SR=yyyyyyyy
The alat.cgi script look like this
#!/usr/bin/perl
use CGI qw(:standard);
ReadParse();
$q = new CGI;
my $dir = $in->param('SR');
my $s = $in->param('sysinfo');
ui_print_header(undef, $text{'edit_title'}.$dir, "");
print $dir."<br>";
print $s"<br>";
The only output I get printed is the value of $dir and $s seems to be empty.
What am I doing wrong?
As #Сухой27 said, add use strict;, but also use warnings; to the top of your script, right below the shebang (#!/usr/bin/perl) line. Those will tell you about syntax errors and other stuff where Perl is doing something other than you might intend.
With CGI (which is btw not part of the Perl core in the latest 5.22 release any more) and the object oriented approach you are tyring to take, you don't need to use ReadParse(). That is an abomination left in from Perl 4's cgilib.pl times.
I don't know what your ui_print_header function does. I'm guessing it outputs a bunch of HTML. Are you sure you defined it?
With fixing all your syntax errors and using modern syntax, your program would look like this. I'll break down what is happening for you.
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my $q = CGI->new;
my $dir = $q->param('SR');
my $s = $q->param('sysinfo');
# you need to declare this to use it below
my %text = ( edit_title => 'foo' );
# we declare this sub further down
ui_print_header(undef, $text{'edit_title'} . $dir, q{});
print $dir . '<br />';
print $s . '<br />';
sub ui_print_header {
my ( $foo, $title, $dir, $bar ) = #_;
# do stuff here...
}
Let's look at some of the things I did here.
Saying new CGI as the CGI docs suggest is fine, but since we are using the OOP way you can use the more common CGI->new. It's the same thing really, but it's consistent with the rest of the OOP Perl world and it's more clear that you are calling the new method on the CGI package.
If you have $q, keep using it. There is no $in.
Declare all your variables with my.
Declare %text so you can use $text{'edit_title'} later. Probably you imported that, or ommitted it from the code you showed us.
Declare ui_print_header(). See above.
q{} is the same as '', but it's clearer that it's an empty string.
thank you everyone for the very quick answer, and as I was suspecting I just had some silly mistake.
Adding here the corrected code that now works
#!/usr/bin/perl
# Run alat on selected sysinfo and allow display of output
#use strict;
use diagnostics;
require 'recoverpoint-lib.pl';
use CGI qw(:standard);
ReadParse();
my $q = new CGI;
my $dir = $q->param('SR');
my $s = $q->param('sysinfo');
ui_print_header(undef, $text{'edit_title'}.$dir, "");
print $dir."<br>";
print $s."<br>";
Just to clarify for some of previous answer, this is a custom module of webmin so variable $text is imported and function ui_print_header is a webmin defined one, it basically print the page header in HTML
As you enable strict and warnings you can easily know the errors.Also you should check Apache error logs, I think the script should be like this:
#!/usr/bin/perl
use CGI qw(:standard);
use strict;
use warnings;
ReadParse();
my $q = new CGI;
my $dir = $q->param('SR');
my $s = $q->param('sysinfo');
ui_print_header(undef, $text{'edit_title'}.$dir, "");
print $dir."<br>";
print $s."<br>";

Perl CGI get user's user-agent

I have Perl CGI pages, (.pl extension). How Can I get a persons raw user agent string? There are ways of doing it in Javascript, (which I have been), though I'd rather move over to completely Perl, rather then having some Javascript and some Perl.
In example, to get a person's IP: $ENV{REMOTE_ADDR}
User agent is stored in $ENV{HTTP_USER_AGENT}
Use the CGI module:
#!/usr/bin/perl -wT
use strict;
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print header;
print start_html("Environment");
foreach my $key (sort(keys(%ENV))) {
print "$key = $ENV{$key}<br>\n";
}
print end_html;
As people have already mentioned, it's always available in the $ENV{HTTP_USER_AGENT} variable. But if you're using CGI.pm, you can also get it by calling the user_agent() function.

Strange behavior when passing parameters to a Perl/CGI script, from another Perl/CGI script

For a project at work, I need to call one Perl/CGI script from another. An extremely simplified version of that script that I'm using for testing is here (the real scripts don't use recursion, but this way I don't have to copy & paste a lot of code):
#!/usr/local/bin/perl
use CGI qw(:standard);
use POSIX 'setsid';
$|=1;
print "Content-type: text/html\n\n";
#names = param;
print "#names";
if(defined(param('submit'))){
#delete_all();
system('perl testParams.pl abc=123');
exit(0);
} else{
print "NO SUBMIT PARAM";
}
What this script is supposed to do:
Print names of all parameters.
If a submit parameter is defined, run the script again but with a parameter called "abc".
If a "submit" parameter is not defined, print "NO SUBMIT PARAM".
What the script actually does:
Print names of all parameters.
If a "submit" parameter is defined, run the script again with the same parameters that the original script was run with.
If a "submit" parameter is not defined, print "NO SUBMIT PARAM".
Any idea what's causing Perl/CGI to ignore the new parameters and instead send the old ones when running the script?
CGI only processes command line args when a CGI environment isn't found. The CGI environment is being inherited from the parent process. You could wipe it using
my %CGI_VARS = map { $_ => 1 } qw(
REQUEST_METHOD
CONTENT_LENGTH
CONTENT_TYPE
...
);
local %ENV =
map { $_ => $ENV{$_} }
grep !$CGI_VARS{$_} && !/^HTTP/,
keys(%ENV);
But this reeks of bad design. Really, your two scripts should be thin front ends to a common module.
You could even use the same script for both (by using a symlink), but alter the behaviour based on the URL used to call up the script.
From CGI with nested apps, each calling param() to get their args the simple answer is to create new CGI object from #ARGV
#!/usr/bin/perl --
use strict;
use warnings;
use CGI ();
Main( #ARGV );
exit( 0 );
sub Main {
my $cgi = #_ ? CGI->new(#_) : CGI->new;
}

In Perl, how do I send CGI parameters on the command line?

Normally i get the data from a webpage but i want to send it from the command line to facilitate debugging.
To get the data i do something like:
my $query = new CGI;
my $username = $query->param("the_username");
this doesn't seem to work:
$ ./script.pl the_username=user1
EDIT:
Actually the above works. The if statement that checked $username was wrong (using == instead of eq).
As I found out long time ago, you can indeed pass query string parameters to a script using CGI.pm. I am not recommending this as a preferred debugging method (better to have replicable stuff saved in files which are then directed to the STDIN of the script), however, it does work:
#!/usr/bin/env perl
use warnings; use strict;
use CGI;
my $cgi = CGI->new;
my $param_name = 'the_username';
printf(
"The value of '%s' is '%s'.\n",
$param_name, $cgi->param($param_name)
);
Output:
$ ./t.pl the_username=yadayada
The value of 'the_username' is 'yadayada'.
CGI reads the variables from standard input.
See this part of the CGI.pm documentation:
http://search.cpan.org/dist/CGI/lib/CGI.pod#DEBUGGING