Passing Variable with redirect in cgi/perl - perl

I have two cgi script. Login.cgi and welcome.cgi
I want to pass variable between these two pages
Here are the two pages i have
#!C:/Perl/bin/perl.exe -w
#login.cgi
use strict;
use warnings;
use CGI::Pretty qw(:all);
my $cgi = new CGI;
my $username = $cgi->param('username');
my $password = $cgi->param('password');
if ( ( $cgi->param('username') eq 'demo' ) && ( $cgi->param('password') eq 'demo' ) ) {
print $cgi->redirect("welcome.cgi");
}
else {
print header();
print start_html( -title => "Login" );
if ( $cgi->param('username') or $cgi->param('password') ) {
print center( font( { -color => 'red' }, "Invalid input" ) );
}
print generate_form();
print end_html();
}
sub generate_form {
return start_form,
h1("Please Login"),
p( "username", textfield('username') ),
p( "password", textfield('password') ), p(submit),
end_form;
}
Another page welcome.cgi
#!C:/Perl/bin/perl.exe -w
#welcome.cgi
use warnings;
use CGI::Pretty qw(:all);
use strict;
my $cgi=new CGI;
my $username;
print header();
print start_html("Welcome"),h1("Hello, $username");
print end_html();
How do I get the username variable passed to welcome.cgi?

use CGI::Session.
For a tutorial on all the different ways to pass information between scripts and why this implementation is a good choice, read CGI::Session::Tutorial
Implemented in your login script:
#login.cgi
use strict;
use warnings;
use CGI::Pretty qw(:all);
use CGI::Session;
my $cgi = new CGI;
my $session = CGI::Session->new($cgi) or die CGI->Session->errstr;
my $username = $cgi->param('username') // '';
my $password = $cgi->param('password') // '';
if ( $username eq 'demo' && $password eq 'demo' ) {
$session->param(username => $username);
print $cgi->redirect("welcome.cgi");
exit;
}
print $session->header();
print start_html( -title => "Login" );
if ( $username or $cgi->param('password') ) {
print center( font( { -color => 'red' }, "Invalid input" ) );
}
print start_form,
h1("Please Login"),
p( "username", textfield('username') ),
p( "password", textfield('password') ), p(submit),
end_form,
end_html();
And in your welcome script:
#welcome.cgi
use strict;
use warnings;
use CGI::Pretty qw(:all);
use CGI::Session;
my $cgi = new CGI;
my $session = CGI::Session->new($cgi) or die CGI->Session->errstr;
my $username = $session->param('username');
print header();
print start_html("Welcome"),h1("Hello, $username");
print end_html();

You can either pass it directly (by encoding it in a query string and adding that to the URL you are redirecting to) or you can store it in a cookie or a session and then retrieve it in the other script.

I would have to slightly disagree with Mr.Miller here. CGI::Session is at present outdated in many regards especially due to:
The method to set cookies is outdated, and does not adhere to the RFC6265
The Cookie ID algorithm is not secure enough, the author has moved on to other projects.
And thus should not be used unless for educational purposes.
With regards to the original question, you can look at this simple tutorial
http://practicalperl5.blogspot.in/2014/07/perl-login-script.html

Related

issues with CGI::Minimal

My existing code works fine with vanilla cgi
#!/usr/bin/env perl
use strict;
use CGI;
use CGI::Carp qw/fatalsToBrowser warningsToBrowser/;
use CGI::Session;
my ( $session, $cgi);
$cgi = new CGI();
$cgi->charset('UTF-8');
$session = new CGI::Session( "driver:File;serializer:Storable",
$cgi, { Directory => '../home/tmp' } );
$session->expire( 'authorized', '1440m' );
changing over to CGI::Minimal causes CGI::Session to error out
#!/usr/bin/env perl
use strict;
use CGI::Minimal;
use CGI::Carp qw/fatalsToBrowser warningsToBrowser/;
use CGI::Session;
my ( $session, $cgi);
my $cgi = CGI::Minimal->new;
$session = new CGI::Session( "driver:File;serializer:Storable",
$cgi, { Directory => '../web/tmp' } ) or or die CGI::Session->errstr();
$session->expire( 'authorized', '1440m' );
The error
Can't call method "expire" on an undefined value at /var/webserver/iris/htdocs/index.cgi line 13.
Edit: after or die CGI::Session->errstr() is added
new(): failed: query object CGI::Minimal=HASH(0x9916a64) does not support cookie() and param() methods:
Not really sure what causes this, really appreciate any insight.
Since CGI::Minimal is indeed rather minimal you'd have to handle Cookies yourself and pass the manually retrieved session_id, instead of the cgi object, to the CGI::Session constructor.
use warnings;
use strict;
use CGI::Cookie;
use CGI::Minimal;
use CGI::Carp qw/fatalsToBrowser warningsToBrowser/;
use CGI::Session;
my $cgi = CGI::Minimal->new();
my %cookies = CGI::Cookie->fetch;
my $session_id;
if( defined $cookies{'SESSION_ID'} ){
$session_id = $cookies{'SESSION_ID'}->value;
}
my $session = CGI::Session->new(
"driver:File;serializer:Storable",
$session_id,
{ Directory => '../web/tmp' }
) or die CGI::Session->errstr();
$session->expire( 'authorized', '1440m' );
my $session_cookie = CGI::Cookie->new(-name => 'SESSION_ID',-value => $session->id());
print $session->header(-cookie=>[$session_cookie]);
print 'ok with session_id: ' . $session->id();

how to get session id from cookie jar in perl?

My question is very simple.. It is how to get session id from cookie jar ... I have tried below code :-
use warnings;
use HTTP::Cookies;
use HTTP::Request::Common;
use LWP::UserAgent;
$ua = new LWP::UserAgent;
if ( !$ua ) {
print "Can not get the page :UserAgent fialed \n";
return 0;
}
my $cookies = new HTTP::Cookies( file => './cookies.dat', autosave => 1 );
$ua->cookie_jar($cookies);
# push does all magic to exrtact cookies and add to header for further reqs. useragent should be newer
push #{ $ua->requests_redirectable }, 'POST';
$result = $ua->request(
POST "URL",
{ Username => 'admin',
Password => 'admin',
Submit => 'Submit',
}
);
my $session_id = $cookies->extract_cookies($result);
print $session_id->content;
print "\n\n";
$resp = $result->content;
#print "Result is \n\n\n $resp \n";
$anotherURI = URL;
$requestObject = HTTP::Request::Common::GET $anotherURI;
$result = $ua->request($requestObject);
$resp = $result->content;
#print $resp."\n";
I am not getting where the session id is stored and how to fetch it ?
Note:- URL contains the URL of the page.
I wrote HTTP::CookieMonster to make this kind of thing a bit easier. If you don't know which cookie you're looking for, you can do something like this:
use strict;
use warnings;
use HTTP::CookieMonster;
use WWW::Mechanize;
my $mech = WWW::Mechanize->new;
my $monster = HTTP::CookieMonster->new( $mech->cookie_jar );
my $url = 'http://www.nytimes.com';
$mech->get( $url );
my #all_cookies = $monster->all_cookies;
foreach my $cookie ( #all_cookies ) {
printf( "key: %s value: %s\n", $cookie->key, $cookie->val);
}
If you already know the cookie's key, you can something like:
my $cookie = $monster->get_cookie('RMID');
my $session_id = $cookie->val;
Have a look at HTTP::Cookies->scan.
Something like this should do the trick (should add a constraint on the domain at least):
my $session_id;
$cookie_jar->scan(
sub {
my ($key, $val, $path, $domain, $port,
$path_spec, $secure, $expires, $discard, $hash
) = #_;
if ( $key eq "session_id" ) {
$session_id = $val;
}
}
);

How to redirect using Perl?

I am new to Perl and I am trying to redirect a user to another page on my server when he enters the right password. The page that I want to redirect to (hello.pl) is in the same directory as my Perl script for the page; however when I try to redirect all I get is a message:
Status: 302 Found Location: hello.pl
But the browser doesn't actually go to the hell0.pl which is what I want. I looked online and in the Perl books but it looks that I'm doing everything right, can someone tell me why my code isn't redirecting? Here's the code for it:
I omitted the code for setting up page and getting user input stored in $var ie I did $var = CGI->new at the top of the file, also I am using CGI.pm as a library.
#!/usr/bin/perl -wT
use strict;
use CGI qw(:standard);
print header,
start_html("Input Form"),
start_form,
"Please enter your username:",
textfield(-name=>'username',
-maxlength=>20),p,
"Please enter your password:",
password_field(-name=>'password',
-maxlength=>20),p,
submit,
end_form,
hr, "\n";
my $var = CGI->new;
my $username = $var->param("username");
my $password = $var->param("password");
my $open = "opensesamie";
if ($password ne $open) {
print "Sorry wrong password";
} else {
print $var->redirect('hello.pl');
print $var->start_html,p,
"Hello, $username",p,
"The current time is ",scalar(localtime),
$var->end_html;
}
print end_html;
Sorry for the delay - I have had to set up a working HTTP server to test my code.
Thank you for posting your full code. It is as I guessed - you have started a message at the top of your program and then added the redirect output to it, whereas you need only the redirect output sent to the client.
I think this is what you need. It checks to see if both the username and password parameters have been sent. If not then the form must be displayed to ask for them. If so then either an error message must be sent if the password is wrong, or a redirect if it is right.
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw(:standard);
my %names = map { $_ => 1 } param;
my $open = 'opensesamie';
if ($names{username} and $names{password}) {
my $username = param('username');
my $password = param('password');
if ($password eq $open) {
print
header,
start_html,
p('Sorry, wrong password'),
end_html;
}
else {
print redirect('hello.pl');
}
}
else {
print
header,
start_html('Input Form'),
start_form,
p('Please enter your username:'),
textfield( -name => 'username', -maxlength => 20),
p('Please enter your password:'),
password_field( -name => 'password', -maxlength => 20),
p,
submit,
end_form,
hr,
end_html;
}
You are outputting two headers. Don't use both header and redirect for the same request.
#!/usr/bin/perl -wT
use strict;
use CGI qw(:standard);
my $cgi = CGI->new;
my $username = $cgi->param("username");
my $password = $cgi->param("password");
if ($password eq "opensesamie") {
print $cgi->redirect('hello.pl');
exit();
}
print header;
print start_html("Please Login");
print p({-class => "error"}, "Incorrect password") if $password;
print ... print the form here ...;
I think you have something like this.
Have you started the HTTP print statements somewhere before the if that tests the password? That would make the headers that print $cgi->redirect just part of the HTML text.
use strict;
use warnings;
use CGI;
my %passwords;
my $cgi = CGI->new;
my $username = $cgi->param('username');
my $password = $cgi->param('password');
print
$cgi->header,
$cgi->start_html;
if ($password ne $open) {
print 'Sorry wrong password';
}
else {
print $var->redirect('hello.pl');
print
$var->start_html, p,
"Hello, $username", p,
"The current time is ", scalar(localtime),
$var->end_html;
}
You need to separate the success/failure completely, like this
use strict;
use warnings;
use CGI;
my %passwords;
my $cgi = CGI->new;
my $username = $cgi->param('username);
my $password = $cgi->param('password);
my $open = $passwords{$username};
if ($password ne $open) {
print
$cgi->header,
$cgi->start_html;
$cgi->p('Sorry wrong password'),
$cgi->end_html;
}
else {
print $var->redirect('hello.pl');
}

how to get POST values in perl

I am trying to customize a script and need to get a POST value from a form using perl.
I have no background of perl but this is a fairly simple thing so I guess it should not be hard.
This is the php version of the code I would like to have in PERL:
<?php
$download = ($_POST['dl']) ? '1' : '0';
?>
I know this may not be at all related to the PERL version but it could help I guess clarifying what exactly I am looking to do.
Well, in that case please have a look at this simple code: This would help you:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
sub output_top($);
sub output_end($);
sub display_results($);
sub output_form($);
my $q = new CGI;
print $q->header();
# Output stylesheet, heading etc
output_top($q);
if ($q->param()) {
# Parameters are defined, therefore the form has been submitted
display_results($q);
} else {
# We're here for the first time, display the form
output_form($q);
}
# Output footer and end html
output_end($q);
exit 0;
# Outputs the start html tag, stylesheet and heading
sub output_top($) {
my ($q) = #_;
print $q->start_html(
-title => 'A Questionaire',
-bgcolor => 'white');
}
# Outputs a footer line and end html tags
sub output_end($) {
my ($q) = #_;
print $q->div("My Web Form");
print $q->end_html;
}
# Displays the results of the form
sub display_results($) {
my ($q) = #_;
my $username = $q->param('user_name');
}
# Outputs a web form
sub output_form($) {
my ($q) = #_;
print $q->start_form(
-name => 'main',
-method => 'POST',
);
print $q->start_table;
print $q->Tr(
$q->td('Name:'),
$q->td(
$q->textfield(-name => "user_name", -size => 50)
)
);
print $q->Tr(
$q->td($q->submit(-value => 'Submit')),
$q->td(' ')
);
print $q->end_table;
print $q->end_form;
}
Style advice: you almost never need to assign 0 or 1 to a variable. Simply evaluate the value itself in bool context.
In CGI.pm (CGI), the param method merges POST and GET parameters, so we need to inspect the request method separately:
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use CGI qw();
my $c = CGI->new;
print $c->header('text/plain');
if ('POST' eq $c->request_method && $c->param('dl')) {
# yes, parameter exists
} else {
# no
}
print 'Do not taunt happy fun CGI.';
With Plack::Request (PSGI), you have different methods for POST (body_parameters) and GET (query_parameters) in addition to the mixed interface (parameters):
#!/usr/bin/env plackup
use strict;
use warnings FATAL => 'all';
use Plack::Request qw();
my $app = sub {
my ($env) = #_;
my $req = Plack::Request->new($env);
if ($req->body_parameters->get_all('dl')) {
# yes
} else {
# no
}
return [200, [Content_Type => 'text/plain'], ['Do not taunt happy fun Plack.']];
};
Here's a good place to start: The Fool's Guide to CGI.pm,
the Perl module for CGI scripting.
This will show you "...how to get the POST value (from a submitted form) and assign it to a variable."
Hope this helps!
The above examples are bit complicated. The below code reads POST values into a variable. You can extract Key Value from that. If its GET then its better to use CGI module.
#!/usr/bin/perl
my $FormData = '';
read(STDIN, $FormData, $ENV{'CONTENT_LENGTH'});
## Variable $FormData holds all POST values passed
use CGI;
my $cgi = new CGI;
print $cgi->header();
print "$FormData";

Why is this password check not working as expected?

I am trying to expand from php. Here is a basic problem I have and can not figure it out...
password.pl
#!/usr/bin/perl
use CGI;
$q = new CGI;
print "Content-type:text/html\r\n\r\n";
print '<html>';
print '<head>';
print '<title>Card</title>';
print '</head>';
print '<body>';
print '<FORM METHOD=POST ACTION=/card.pl>';
print '<INPUT TYPE=password NAME=password SIZE=25>';
print '<input type=submit value=Submit>';
print '</FORM>';
print '</body>';
print '</html>';
1;
card.pl
#!/usr/bin/perl
use CGI;
$q = new CGI;
$password = $q->param("password");
print $password;
if ($password == pass)
{
print 'Yup';
}
else
{
print 'Wrong Password';
}
1;
Nothing is passing to card.pl from the password.pl form? I have used a simular example before with no problem?
More coffee...
use strict;, use warnings; and look in your error logs. Also validate your HTML.
Then you'll be alerted to problems like:
Bareword "pass" not allowed while "strict subs" in use at card.pl line 7.
You probably want:
($password eq 'pass')
In my continuing quest to disabuse the abuse of CGI.pm, your first script would be much better as–
use strict;
use warnings;
use CGI qw( :standard );
print
header(),
start_html("O HAI CARD"),
start_form(-action => "card.pl"),
fieldset(
legend("None Shall Pass!"),
password_field(-name => "password",
-size => 25),
submit(-value => "Submit"),
),
end_form(),
end_html();
Your second as, perhaps, just for example, et cetera–
use strict;
use warnings;
use CGI;
my $q = CGI->new;
print
$q->header,
$q->start_html("O HAI CARD");
my $password = $q->param("password");
if ( $password eq "pass" )
{
print $q->h2("You're all good");
}
else
{
print $q->h2({-style => "color:#a00"},
"You're all good");
}
print $q->end_html();
Or, maybe better, all together–
use strict;
use warnings;
no warnings "uninitialized";
use CGI qw( :standard );
print
header(),
start_html("O HAI CARD");
print param("password") eq "pass" ?
h2("Yes!") : h2({-style => "color:#a00"}, ":(");
print
start_form(),
fieldset(
legend("None Shall Pass!"),
password_field(-name => "password",
-size => 25),
submit(-value => "Submit"),
),
end_form(),
end_html();
RIF, read the docs: CGI.