issues with CGI::Minimal - perl

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();

Related

Running perl code using `atom` throws me Undefined subroutine &main::send_request

I'm writing my first perl script for the requirement
generate HTTP request against a particular web uri in succession using different URL scheme patterns
use HTTP::Request::Generator 'generate_requests';
use URI;
use HTTP::Request::Common;
use strict; # safety net
use warnings; # safety ne
use Test::LWP::UserAgent 'send_request';
use LWP::UserAgent 'send_request';
use Test::More;
use URI;
use HTTP::Request::Common;
use LWP::UserAgent;
my $g = generate_requests(
method => 'POST',
host => ['example.com','www.example.com'],
pattern => 'https://example.com/{bar,foo,gallery}/[00..99].html',
wrap => sub {
my( $req ) = #_;
# Fix up some values
$req->{headers}->{'Content-Length'} = 666;
},
);
while( my $r = $g->()) {
send_request( $r );
};
I'm using atom editor and activeperl on windows 10, I get following error from running above code.
Undefined subroutine &main::send_request called at C:\Users\ADMINI~1\AppData\Local\Temp\atom_script_tempfiles\0ac821e0-0886-11eb-9588-291dbc37d883 line 57.
I have already installed all necessary modules and lib but i think its unable to refer the method send_request. Pls assist.
NOTE
I have replaced real values in variable for privacy reasons.
UPDATE
I plan to use following module
pattern => 'https://example.{com,org,net}/page_[00..99].html', from
https://metacpan.org/pod/HTTP::Request::Generator.
LWP::UserAgent is an object-oriented module. It doesn't export functions. You want to call send_request like this:
my $ua = 'LWP::UserAgent'->new;
while ( my $r = $g->() ) {
$ua->send_request( $r );
}
That said, send_request is an undocumented internal method. I think it is probably more intended for people who are subclassing LWP::UserAgent. You probably want the request method instead.
my $ua = 'LWP::UserAgent'->new;
while ( my $r = $g->() ) {
my $response = $ua->request( $r );
}
Full code:
use strict;
use warnings;
use HTTP::Request::Generator 'generate_requests';
use LWP::UserAgent;
my $ua = 'LWP::UserAgent'->new;
my $gen = generate_requests(
method => 'POST',
host => [ 'example.com', 'www.example.com' ],
pattern => 'https://example.com/{bar,foo,gallery}/[00..99].html',
wrap => sub {
my ( $req ) = #_;
# Fix up some values
$req->{'headers'}{'Content-Length'} = 666;
},
);
while ( my $req = $gen->() ) {
my $response = $ua->request( $req );
# Do something with $response here?
}

Passing Variable with redirect in cgi/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

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

How to overwrite a function used in a module-method?

#!/usr/bin/env perl
use warnings;
use 5.012;
use utf8;
use WWW::Mechanize::Cached;
use Some::Module qw(some_method);
my $url = '...';
my $result = some_method( $url );
The some_method() uses itself get() form LWP::Simple.
How could I overwrite the get() with my my_get() in this script?
sub my_get {
my $url;
my $mech = WWW::Mechanize::Cached->new();
$mech->get( $url );
my $content = $mech->content( format => 'text' );
return $content;
}
sub WWW::Mechanize::Cached::get {
# your code
}
OR, if the get method is actually, as you imply in the question, is inherited from LWP::Simple -
sub LWP::Simple::get {
# your code
}

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.