basic help for Perl CGI module - perl

I want to use the Perl CGI module for creating CGI scripts. I went through the documentation available
here but I seem to have missed something obvious because I have
run into problems with my first program. Here is the HTML:
<form name="form1" method="post" action="http://localhost/cgi-bin/filters.cgi">
<input name="mainbox" type="checkbox"> Mainbox<br> <br>
<input name="n1" type="checkbox">No. 1 <br><br>
<input name="n2" type="checkbox"> No. 2<br><br>
<input name="n3" type="checkbox">No. 3 <br>
<div style="text-align: center;"><input name="Submit" value="Submit" type="submit"></div>
</form>
I simply want the names of the parameters that are passed to the CGI file to be printed on a new
page. So (with my limited understanding), I wrote the following in filters.cgi:
#!/xampp/perl/bin/perl -w
use strict;
use warnings;
use CGI;
my $query = CGI->new;
print $query = $query->header('text/html');
my #names = $query->param;
my $q1 = CGI->new;
print $q1->header('text/html');
print $q1->start_html('hello');
foreach my $name (#names) {
print $q1->h1($name);
}
print $q1->end_html;
But this prints out nothing. It does not give me any error either and the syntax is OK.
I know I am missing something very simple here but I really want some help with this. How do
I write this script correctly? I am using XAMPP in Windows XP, if that makes any difference.
EDIT: Maybe I should mention that I have tried to figure this out myself. So I wrote the
following script which works:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my #arr = ('ac', 'fg', 'ty');
my $q1 = CGI->new;
print $q1->header('text/html');
$q1->start_html('hello world');
foreach my $el (#arr) {
print $q1->p($el);
}
$q1->end_html;
So the problem is somewhere in the parameters being passed. I don't even know where to look for
help in the long documentation, so decided to ask here. Also, I have seen the link Nikhil
has posted in the comments. One of the points mentioned there is that I should try running my
script from the command line. How do I pass these parameters from the command line?

The first issue you had was that you were assigning the result of calling $query->header('text/html') back into your $query variable, destroying the query object which meant that the next line my #names = $query->param wasn't working as expected.
Secondly, you were attempting to print the Content-type header twice, once using the $query CGI object and once using the $q1 object.
I have removed the unnecessary CGI object, $q1, and used the original $query object in all cases.
The following is the code with the above fixes applied.
#!/xampp/perl/bin/perl -w
use strict;
use warnings;
use CGI;
my $query = CGI->new;
my #names = $query->param;
print $query->header('text/html');
print $query->start_html('hello');
foreach my $name (#names) {
print $query->h1($name);
}
print $query->end_html;

print $query = $query->header('text/html');
This line is part of your problem. $query->header() returns some text, which isn't a useful value to set $query to. You're also creating two CGI objects ($query and $q1) where you only need one, and printing two sets of headers. Get rid of the duplication and the inappropriate assignment, and you should be fine.

Related

File upload using a Perl CGI script not working

The following code doesn't have any syntax errors, but still doesn't working.Can I use server ip(like 100.100.100.100) for $Domain and what path should be given for $directory(i mean adding the serverip or domain name?Please help
#!/usr/bin/perl
use CGI;
$CGI::POST_MAX= 100 * 1024;
$CGI::DISABLE_UPLOADS=0;
$Referer = $ENV{HTTP_REFERER};
$Domain = "xxx.com";
$cgi = new CGI;
$file=$cgi->upload('text');
print $cgi->header,
$cgi->start_html
(
-title=>'CGI.pm File Upload'
);
print <<EOF;
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="text" size=60><br>
<input type="submit" value="Upload">
</form>
EOF
if($file)
{
if($Referer =~ "$Domain")
{
$directory="var/www/cgi-bin/uploads";
open UPLOAD, ">$directory$file";
binmode UPLOAD;
while(<$file>) {print UPLOAD;}
close UPLOAD;
}
}
$cgi->end_html;
exit;
Looks like you need to read the documentation on file upload basics again. The sample code they have is:
use autodie;
# undef may be returned if it's not a valid file handle
if ( my $io_handle = $q->upload('field_name') ) {
open ( my $out_file,'>>','/usr/local/web/users/feedback' );
while ( my $bytesread = $io_handle->read($buffer,1024) ) {
print $out_file $buffer;
}
}
There are some stylistic differences to your code, but the important thing to note that is that when your code runs this line:
$file=$cgi->upload('text');
Then $file contains an open filehandle. It does not contain the filename. This means that there are at least three errors in these lines of your code:
$directory="var/www/cgi-bin/uploads";
open UPLOAD, ">$directory$file";
The value you store in $directory should almost certainly start with a / (so it's /var/www/cgi-bin/uploads).
You also need another / between $directory and $file (otherwise, it will contain something like /var/www/cgi-bin/uploadsmyfile.dat).
You need to call $cgi->param('text') to get the name of the file that is being uploaded.
This is what is stopping your program from working. The upload section of your code should look like this:
my $filename = $cgi->param('text');
my $fh = $cgi->upload('text');
my $directory = '/var/www/cgi-bin/uploads';
open my $upload_fh, '>', "$directory/$filename"
or die "Can't open '$directory/$filename': $!";
print $upload_fh $_ while <$fh>;
Note that I've made some stylistic improvements here:
Used 3-argument version of open()
Used lexical filehandles
Checked the success of the open() call and killed the program with a useful error message if it fails
All in all, you seem to have learned CGI programming from a resource that is about twenty years out of date. Your code looks like it comes from the 1990s.
A few other tips:
Always use strict and use warnings.
Indirect object notation (new CGI) is potentially very confusing. Use CGI->new instead.
We've known that the HTML-generation functions in CGI.pm are a terrible idea since the end of the last millennium. Please don't use them. Many good templating solutions are available for Perl.
Writing a CGI program in 2017 is a terrible idea. Take a look at CGI::Alternatives for an introduction to Modern Perl Web Development tools.

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>";

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

perl cgi form processing

I am working on a file and I am trying to understand how to process a form in hopes of passing a hidden field. for simplicity, lets say i want my scipt to simply show the value of the hidden field when it is first presented to the user, incremented by one, and after it is 'submitted', the new script displayed with the updated hidden field. I am trying to gain insight on the explicit procedure so i can apply it to one of my current projects.
I have searched the web but most examples simply confuse me, can anyone chime in?
Values submitted by the form can be retrieved using the CGI module (since you haven't shown any code, I don't know whether you're using CGI or attempting to handle the CGI interactions by hand; if you're doing it by hand, You're Doing It Wrong) and its param method.
Given the HTML form:
<form action='my_script.cgi' method=POST>
<input type=hidden name=hidden_field value=1>
<input type=submit>
</form>
You can retrieve the hidden value with (in my_script.cgi):
#!/usr/bin/env perl
use strict;
use warnings;
use CGI;
my $q = CGI->new;
my $hidden_value = $q->param('hidden_field');
You could write the value of the hidden field to a cookie. Each time you refresh or revisit the same webpage, your script can read the cookie into the hidden variable and increment it by one. The following example uses a variable instead of a hidden field in the form.
#!/usr/bin/perl
#countvisits.cgi
use strict;
use warnings;
use CGI qw(:standard -debug);
use CGI::Carp qw(fatalsToBrowser);
#declare variables
my ($count, $C_record);
#Create a new CGI object
my $cgi = new CGI;
#Read the cookie
#assign input to variable
$count=$cgi->cookie('count');
$count++;
#create cookie
$C_record = cookie(-name => "count",
-value => $count,
-expires => "6M");
#send cookie to browser
print header(-cookie => $C_record);
#create Web page
print "<HTML>\n";
print "<HEAD><TITLE>Jubilee Book Club</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H1 ALIGN=center>Hello!<BR>\n";
print "You have been here $count times.</H1>\n";
print "</BODY></HTML>\n";

I want to check if number starts with 4 or 5 in CGI

I need to write some script in CGI which is new to me. I am trying to do if else with condition numbers starting with 5 or 6. So do one code if number starts with 5 and do another if number starts with 6.
use 5.013;
use warnings;
use Scalar::Util qw( looks_like_number );
use CGI;
my $param = CGI->new()->param('some_example');
given (substr $param, 0, 1) {
when (! looks_like_number($_) ) { say 'Not a number' }
when (5) { say 'starts with 5' }
when (6) { say 'starts with 6' }
}
Alternatively, rather than using substr to get the first letter, put $param and change (5) to your regex of choice.
I don't think you understand what CGI is. CGI is simply a set of environment variables that are set up by the webserver, and your program is executed with them. The output of the program becomes the webpage.
So if you want to write a CGI script in Python, PHP, C, Assembly, Whitespace... as long as it can be called and use environment variables, it's fine.
So this is really a language question. Which language are you using?
EDIT You specified Perl in a comment to this answer. I suggest you edit the question.
What's your input number? The Perl script will be run with a whole truckload of extra environment variables. Two of the most important are QUERY_STRING and REQUEST_METHOD. CGI consists of a specification of these environment variables, so any language can be used to write CGI.
Consider perl_cgi.cgi?something=else. The bit following the ? is the QUERY_STRING. You can specify this directly as part of an anchor:
Run with something equals else
or as part of a form (one of GET or POST, defaults to GET):
<form action="perl_cgi.cgi" method="[GET or POST]">
<input type="text" name="something" value="else"/>
<input type="submit" value="Submit!"/>
</form>
This will run your program with the same query string as above (or a different parameter, if the text box is changed) but REQUEST_METHOD will be either GET or POST depending.
So let's write a Perl CGI script to print the first number of the string we get (we're only passed strings):
use CGI;
$cgi=new CGI;
$x=$cgi->param('x');
$firstnum=substr($x, 0, 1);
print "Content-type: text/html\n\n";
print <<"EOF";
<html>
<head>
<title>My sample HTML page</title>
</head>
<body>
<p>The first number of $x is $firstnum</p>
</body>
</html>
EOF
This presupposes that this program is run as [program_name]?x=[some string]. It's up to you to make sure that's the case.
That should give you enough. You can check firstnum to see if its 5 or 6, then do different things depending.