How to get query string from URL - perl - perl

I'm not aware of how to grab the query string from the URL using Perl. I've tried a couple of ways, example:
my $qs = $ENV{'QUERY_STRING'};
my #d = split(/&/, $qs);
if ( $d[1] eq 'reports' ) {
... do something
}
and
use CGI;
my $q = CGI->new;
my $page = $q->param('page');
But am not getting the value of the key. Right now I'm manually placing in the query string, i.e. project.local/routes.cgi?page=reports but I get the following from the command line:
Use of uninitialized value $qs in split at ./routes.cgi line 23.
Use of uninitialized value $d[1] in string eq at ./routes.cgi line 25.
I'm not sure why this warning exists as it should just be undef if it doesn't exist?
How should I store and check a query string variable? I'm primarily using the routes.cgi script as a routes controller where all links point to i.e. <a href="project.local/routes.cgi?page=xx"> and then I process a template toolkit file and redirect to that page (good concept?)
Results of diagnostics:
Use of uninitialized value $qs in split at ./routes.cgi line 23 (#1)
(W uninitialized) An undefined value was used as if it were already
defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.
Edit:
use URI qw( );
use URI::QueryParam qw( );
my $u = URI->new($base_url);
my ($p) = $u->query_param('page');
if ( $p eq 'reports' ) {
...do something
}

Man, youre fighting many days (based on your past questions) with your route.cgi. Reading thru comments and answers in your past questions, many developers already said to you: use some framework.
Now for your question(s):
Use of uninitialized value $qs in split at ./routes.cgi line 23.
Thats mean (in line, what the use diagnostics says) - the $qs variable isn't contains any value. Why the $ENV{'QUERY_STRING'}; isn't have a value is depends on your environment, but generally, you should not depend on some environment variables but on what you get from the HTTP request.
Use of uninitialized value $d[1] in string eq at ./routes.cgi line 25.
Of course, because the $qs is undefined, the split splits the nothing, and the splitted nothing is nothing too - so you get nothing to your #d array and therefore the $d[1] isn't initialised.
BTW, when you comes from the php-word (as you said in one of your questions), you should to know, than after an succesfull split of the "QUERY_STRING" at & you will get to $d[0] the value page=report and not only the report.
As #AndyLester told you, for handling URL's (getting or composing) its parts here is the URI::URL module, but you really should at least read it's description.
Ad routes: generally is better and nicer and more SEO friendly to have URLs like:
http://example.com/blog/archive/2013/12/20
and not
http://example.com/run?section=blog&action=archive&year=2014&month=12&day=20
So, for the "routes" don't use URL parameters, but the PATH_INFO. And this "philosophy" is already developed into many frameworks, like Poet+Mason, Mojolicious, Dancer and many others, or here are standalone modules for handling routes. (search MetaCPAN.org).
From my point of view, the perl web-app developemnt based on the next commands:
Install my own perl-environment (need only once)
curl -L http://install.perlbrew.pl | bash
#relog, to init the environment
perlbrew available
prelbrew install perl-5.20.0
prelbrew switch perl-5.20.0
prelbrew install-cpanm
When got my "own" perl
cpanm Poet #will install a bunch of modules
#or alternatively
cpanm Mojolicious
And from now, things are relatively easy:
cd my_development_directory
poet new myapp
cd myapp
echo 'This is my report <% localtime %>' > comps/report.mc
./bin/run.pl
and you have an running perl web-application. So, point your browser to: http://localhost:5000/report and will get
This is my report Tue Jul 29 16:09:52 2014
and alongside you will get an great debug panel and much more... (see Mason & Poet manuals)
I'm still an beginner in perl development, so other more experianced perl-monks could give you better advices.

You want to use the URI::URL module.
http://search.cpan.org/dist/URI/lib/URI/URL.pm

jm666 is correct, you really should consider using a framework. However, if you are looking to keep your module installs to a minimum, try something like this...
use strict;
use warnings;
use URI::Escape;
use Data::Dumper;
#this will catch anything after the "?", as in SomeURL?Var=111&OtherVar=QQQ
my $RequestHash;
if($ENV{"QUERY_STRING"}) {
#QUERY_STRING="id=demo:5&other=some%20text&last=more%20text"
my #TempArray=split("&", $ENV{"QUERY_STRING"});
foreach my $item (#TempArray) {
my ($Key, $Value)=split("=", uri_unescape($item)); #need to fix this to work with more than one "=" in the value
$RequestHash->{lc($Key)}=$Value; #normalize the key name to lower case - because you never know what users will do
} #end foreach
} #end query check if
print Data::Dumper::Dumper($RequestHash);

Related

Perl: CGI redirect from multiple submit buttons

I have a small CGI Script with 2 submit buttons. I want that the current Script redirects the User to another script, depending on which submit button is pressed.
The CGi-Script:
#!/usr/bin/perl -w
# Modules
use strict;
use warnings;
use CGI;
my $q = CGI->new();
print $q->header();
print $q->submit(-name=>'button',-value => 'disable');
print $q->submit(-name=>'button',-value => 'enable');
if ($q->param('button') eq "disable"){
print $q->redirect(-uri=>"http://1.1.1.1./cgi-bin/services/switch_XXX.cgi?disable");
} elsf ($q->param('button') eq "enable"){
print $q->redirect(-uri=>"http://1.1.1.1./cgi-bin/services/switch_XXX.cgi?enable");
} else {
}
But none of the actions is actually performed. The Error-Log shows the following:
[Tue Mar 06 11:48:44 2018] [error] [client XXXX] Use of uninitialized value in string eq at /var/www/cgi-bin/test.cgi line 23.
[Tue Mar 06 11:48:44 2018] [error] [client XXXX] Use of uninitialized value in string eq at /var/www/cgi-bin/test.cgi line 26.
Could someone of you tell me what causes the error and why the redirect is not working?
Many thanks in advance!
See "Generating a redirection header" in the CGI docs: "If you use redirection like this, you should not print out a header as well."
The messages you're seeing in the log are referring to the $q->param('button') eq "disable" checks: $q->param('button') is returning undef because the field has not been submitted yet, so you're comparing "disable" to the undefined value. These are warning messages only, that you can avoid by first checking if $q->param('button') has a true value before doing the eq comparison. (Note: In other cases, one might want to use defined to check for undef, because there are some values in Perl that are defined but still false, see Truth and Falsehood - but in this case, both "disable" and "enable" are true values.)
Also, your submit buttons need to be in a <form>. And note you've got a typo with elsf. This works for me:
#!/usr/bin/env perl
use strict;
use warnings;
use CGI;
my $q = CGI->new();
if ( $q->param('button') && $q->param('button') eq "disable" ) {
print $q->redirect(-uri=>"...");
} elsif ( $q->param('button') && $q->param('button') eq "enable" ) {
print $q->redirect(-uri=>"...");
} else {
print $q->header();
print $q->start_html;
print $q->start_form;
print $q->submit(-name=>'button', -value=>'disable');
print $q->submit(-name=>'button', -value=>'enable');
print $q->end_form;
print $q->end_html;
}
If you are just starting to write web applications in Perl, I would urge you to read CGI::Alternatives and decide whether you really want to use such old technology when newer and better (and still Perl-based) alternatives are available.
However, if you decide to stick with CGI (and CGI.pm) then there are a couple of things that can make your life easier.
It's a rare CGI program that needs two CGI objects
For most CGI programs, using an object-oriented approach is overkill. You rarely need objects. CGI.pm has a, simpler, function-based approach that you can use instead. Simply, import the functions that you want to use as you load the module:
use CGI qw[param header redirect];
Then use them without creating an object first:
if (param) {
print redirect(...);
} else {
print header(...);
}
The CGI-Generation functions are a terrible idea
It's even in the documentation.
HTML Generation functions should no longer be used
All HTML generation
functions within CGI.pm are no longer being maintained. Any issues,
bugs, or patches will be rejected unless they relate to fundamentally
broken page rendering.
The rationale for this is that the HTML generation functions of CGI.pm
are an obfuscation at best and a maintenance nightmare at worst. You
should be using a template engine for better separation of concerns.
See CGI::Alternatives for an example of using CGI.pm with the
Template::Toolkit module.
These functions, and perldoc for them, are considered deprecated, they
are no longer being maintained and no fixes or features for them will
be accepted. They will, however, continue to exist in CGI.pm without
any deprecation warnings ("soft" deprecation) so you can continue to
use them if you really want to. All documentation for these functions
has been moved to CGI::HTML::Functions.
Putting your HTML into an external template is a much better idea. And it will be easier for your front-end developer to edit. Yes, I realise you probably don't have a front-end developer on your project right now - but don't you want to plan ahead?
Having said that, your program becomes something like this:
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw[param header redirect];
my $disable_url = '...';
my $enable_url = '...';
if (param('button') {
if (param('button') eq 'disable') {
print redirect($disable_url);
} elsif (param('button') eq 'enable') {
print redirect($enable_url);
}
exit;
}
print header;
print $some_output_that_is_generated_from_a_template.

How to create own module for reuse in Perl?

I wish to create my own module and I want to use that module name for further use. The main concept is: Create a module which should contain subroutines for line count, word-count and character count, and in main program I should use that module and I should read the file and the output should show me total number of lines, total number of words and total number of characters in that file.
package Countsample;
use strict;
use base"Exporter";
use 5.010;
our #EXPORT=qw/line_count/;
sub line_count
{my $line=#_;
return $line;
}
1;
This above doc is saved in Count.pm.
#!usr/bin/perl
use Countsample;
open FH,"text1.txt";
line_count();
print"$line\n";
The above code is saved in Count1.pl format.
I think this much information is enough to create, if you need any further information then let me know.
Kindly help me to create complete this task.
Let's start with the module. It was already mentioned, that it is common practice to name the file as the package it contains.
And there is a reason for this: using use with a name builds on the expectation that there will be a file somewhere in the path list (#INC) for modules by that name containing a matching namespace declaration (package whatever). This connection makes possible, what Exporter does in the first place.
http://perldoc.perl.org/Exporter.html
A more indepth but still succinct explanation of this can be found here
http://www.perlmonks.org/?node_id=102347
So the file would be named Countsample.pm:
package Countsample;
use strict;
use warnings;
use base "Exporter";
use 5.010;
our #EXPORT=qw/line_count/;
sub line_count
{
my ($fd) = (#_);
my $lines = 0;
while (<$fd>) {
$lines++
}
return $lines;
}
1;
I added use strict and use warnings to be notified about errors.
Then I changed the assignment of the arguments; the arguments in #_ are a list, so I assign those to a list on the left side (see the parentheses around $fd). You could use
my $fd = shift;
alternatively.
I chose to pass an open filehandle as an argument here, then count the lines, simply by reading the file linewise and returning the number of lines.
There are many ways to get the number of lines out of a file, just as a reference:
http://www.perlmonks.org/?node_id=538824
The main program then looks like this:
#!/usr/bin/perl
use v5.14;
use strict;
use warnings;
use Countsample;
open (my $fd, "<", "text1.txt");
say line_count($fd);
close($fd);
See http://perldoc.perl.org/functions/open.html for the ways to open a file that are available and preferable.
You really need to work on your question asking. You're not giving us enough to go on. You need to tell us:
Exactly what you want to do
Exactly what you have done
Exactly what expected behaviour you are seeing (including any error messages)
Let's step through getting past some of your errors.
Firstly, when I ran your program, I got this.
$ ./Count1.pl
bash: ./Count1.pl: usr/bin/perl: bad interpreter: No such file or directory
Ok, so that's just a stupid typo. But because you haven't explained what problems you are getting, we don't know if that's the problem you're seeing or whether you've introduced the typo when posting your question.
But it's easy to fix. The shebang line needs to be #!/usr/bin/perl. I'm pretty sure you had exactly the same typo in your last question!
Now what happens when I run your code.
$ ./Count1.pl
Can't locate Countsample.pm in #INC (you may need to install the Countsample module) (#INC contains: ...)
This is because your package doesn't have the same name as your module file. Why would you do that? It just complicates your life.
Ok, so let's fix the use statement so it's looking for the right thing - use Count.
Now I get a different error.
$ ./Count1.pl
Undefined subroutine &main::line_count called at ./Count1.pl line 5.
That's going to be a little harder to track down. So to make my life easier I'll turn on use strict and use warnings in both of the files.
I now get this:
$ ./Count1.pl
Global symbol "$line" requires explicit package name at ./Count1.pl line 9.
Execution of ./Count1.pl aborted due to compilation errors.
That means I'll need to declare the variable $line at some point so I'll add my $line just after the use Count line.
And now I get this:
$ ./Count1.pl
Name "main::FH" used only once: possible typo at ./Count1.pl line 8.
Undefined subroutine &main::line_count called at ./Count1.pl line 9.
At which point, I'm afraid, I get bored of digging. Had you presented us with this version of the code, then I might have had some energy left to investigate from here. But because I've spent ten minutes finding silly typos and fixing pointless bugs, I've lost all enthusiasm.
It's important to realise that the people here are all volunteers. We're happy to help you solve your problems, but you need to do some of the work yourself. You need to ensure that we don't waste time fixing obvious things that you could have found yourself. And you need to be a lot clearer than you have been so far when explaining what the problem is.
Here's the version of you code that I got to. Perhaps someone else will have the enthusiasm to take it to the next stage.
Count.pm
package Countsample;
use strict;
use warnings;
use base "Exporter";
use 5.010;
our #EXPORT = qw/line_count/;
sub line_count {
my $line = #_;
return $line;
}
1;
Count1.pl
#!/usr/bin/perl
use strict;
use warnings;
use Count;
my $line;
open FH,"text1.txt";
line_count();
print "$line\n";
Update: The "undefined subroutine" error was because I forgot to change the name of the package in Count.pm. Having done that I now get:
$ ./Count1.pl
Name "main::FH" used only once: possible typo at ./Count1.pl line 8.
Use of uninitialized value $line in concatenation (.) or string at ./Count1.pl line 10.
Which is the point at which you really need to start thinking about how your module works. What subroutines do you need? What parameters do they take? What do they return?

How to make use of UUIDGEN of unix in perl script

I am trying to generate a unique number using uuidgen (of unix). The generated unique number should get stored in a variable. When i am doing it in a function , I am facing errors.
Can anyone let me know how to make use of uuidgen script in perl.
#!/usr/bin/perl
sub function_uuidgen
{
my myuuid;
system(`export myuuid=uuidgen`);
print "\n unique id is : $myuuid";
# I need not to export the variable, I just need to unique number generated by UUID GENERATOR in a variable.
}
int main
{
print "\n I am in main function";
&function_uuidgen;
}
I am facing the below error when I am running uuidgen as mentioned below. Can anybody help me out with exporting the JAVA VARIABLE in perl ? How to export the path variable,in case if this error is related to that.
Error :
/bin/java: uuidgen 1: not found
Code :
sub function_uuidgen
{
my $myuuid = qx(uuidgen);
chomp $myuuid;
print "\n unique id is : $myuuid";
# I need to export the variable, as it is giving me error without exporting.
}
int main
{
print "\n I am in main function";
function_uuidgen();
}
You're mixing up C and Perl here.
As far as I know you can't access exportet system variables that way from perl (correct me if I am wrong. I don't have much knowledge of linux system variables).
A way to generate UUID's would be the Data::GUID Module from CPAN
use strict;
use warnings;
use Data::GUID qw( guid_string );
my $guid = guid_string();
print "$guid\n";
Also Perl doesn't have an int main function. Your code starts at the top and runs down to the bottom. Of course this gets a bit different if you create an object orientated module.
If you for some reason can't use Data::GUID, this is a way to use the output of uuidgen (note the backticks):
#!/usr/bin/perl
use strict;
use warnings;
my $uuid=`uuidgen`;
chomp $uuid;
print "$uuid\n";
Example output:
$ ./hep.pl
fe82c4f6-a1f2-4242-ab45-853780931927
$
Also, using & before function calls went out of fashion many years ago :-)
Without knowing anything about uuidgen: You could just
my $perlVar = `uuidgen`;
within perl.
Assuming calling uuidgen in your console returns the number you are looking for.
export is a shell command that adds a variable and value to its environment block. The environment block is private to a process, but (by default) copied to a child process. You appear to be thinking it is some sort of global area - it is not.
So, all you would be doing is adding a value to the shell's environment block, not your own! (That's the shell created by system(), not the one you were running from). Placing the export inside back-ticks is strange, if not wrong.
Easier to use:
my $myuuid = qx(uuidgen);
chomp $myuuid;
Notice I am using qx instead of back-ticks `` because they can be confusing (back-ticks are deprecated in UNIX shells as well).
To run the subroutine, loose the C style int main:
print "\n I am in ", __PACKAGE__, "package\n";
function_uuidgen();
The leading & on a subroutine call has side-effects that you probably don't need.

Use of uninitialized value $form_data{"BuildAcct"}

* SECOND UPDATE FOR SUNDAY*
Now at this point I have found some added success at displaying the desired sub
The new snippet of code which enabled me to actually invoke a specific sub as I wanted.
In researching I stumbled upon the following snippet which deals with reading incoming FORM data.
This snippet does enable the invocation of the sub of my choice from this script.
However from the CLI when I run perl -x against the script the system returns the following
nonfatal *warnings* that I would like to gain understanding of and resolve.
My research shows that (tr///) and $ENV{"REQUEST_METHOD"} and $buffer are returning empty
values "" OR 0.
How would I best resolve these following errors?
I realize I can just delete any
reference to (tr///) and $buffer to resolve those errors, however, I question removing
*$ENV{"REQUEST_METHOD"}* as it seems this imperative to the function of this snippet???
CLI ERROR
Use of uninitialized value in transliteration (tr///) at test.pl line 36 (#1)
Use of uninitialized value $ENV{"REQUEST_METHOD"} in string eq at test.pl line 37 (#1)
Use of uninitialized value $buffer in split at test.pl line 44 (#1)
#!/usr/bin/perl -w
# (test.pl)
use DBI;
use DBD::mysql;
use warnings;
use strict;
use diagnostics;
$| = 1;
# The script I am wanting to create, is to allow users at (NAS) HotSpot to create a user account
# which is to write into MySQL db TABLE's *radcheck* and *radreply*.
#
# Now at this point I have found some added success at displaying the desired *sub*
# The new snippet of code which enabled me to actually *invoke* a specific *sub* as I wanted
# from an HTML form.
# Please see below for solution which still has some questions.
print "Content-type: text/html\n\n";
sub BuildAcctNow {
print "<h1 style=\"color:blue;font-family:Arial;font-size:xx-large;\">TO BUILD YOUR ACCOUNT TODAY WE WILL NEED A SMALL AMOUNT OF INFORMATION</h1><br><br>\n\n";
}
sub PauseAcctNow {
print "<h2 style=\"color:red;font-family:Arial;font-size:xx-large;\">YOUR ACCOUNT HAS BEEN PAUSED PLEASE MAKE A PAYMENT HERE.</h2><br><br>\n\n";
}
# In researching I stumbled upon the fllowing snippet which deals with reading inward FORM data.
# This snippet *does* enable the *invocation* of the *sub* of my choice from this script.
# However from the CLI when I run perl -x against the script the system returns the following
# *nonfatal* *warnings* that I would like to gain understading of and resolve.
# My research shows that (tr///) and $ENV{"REQUEST_METHOD"} and $buffer are returning empty
# values, How would I best resolve these following errors? I realize I can just delete any
# reference to (tr///) and $buffer to resolve those errors, howerver I question removing
# $ENV{"REQUEST_METHOD"} as it seems this imperative to the function of th ssnippet???
#
#
# Use of uninitialized value in transliteration (tr///) at test.pl line 36 (#1)
# Use of uninitialized value $ENV{"REQUEST_METHOD"} in string eq at test.pl line 37 (#1)
# Use of uninitialized value $buffer in split at test.pl line 44 (#1)
my ($buffer, #pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
$buffer = $ENV{'QUERY_STRING'};
}
# Split information into name/value pairs
#pairs = split(/&/, $buffer);
foreach $pair (#pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%(..)/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
if ($FORM{PauseAcct}) {
PauseAcctNow();
exit;
}
elsif ($FORM{BuildAcct}) {
BuildAcctNow();
exit;
}
END SECOND SUNDAY UPDATE
SUNDAY UPDATE **
I have made a simple script to hopefully exhibit what I am trying to do to this point hopefully?
The script I am ultimately needing to create will write to MySQL db into radcheck and radreply to enable users to log onto a (NAS) HotSpot.
So I will have more than one subroutine within the script.
The script presently displays an empty screen VIA browser when I use a HTML doc with a properly named SUBMIT form within the doc named BuildAcct.
I am traditionally used to defining the sub within the script and then I would define if test(s) within the script which would wait for match(es) from any defined form name(s) when they are interacted with to then call a particular sub.
Below is a test script I have created just trying to get past the antiquated use of & when calling a sub, this is causing me some grief and I am hoping for some valuable input.
#!/usr/bin/perl -w
# (test.pl)
use DBI;
use DBD::mysql;
use warnings;
#use strict;
# Presently due to my errors below I have disabled *use strict*.
$| = 1;
# The script I am wanting to create, is to allow users at (NAS) HotSpot to create a user account
# which is to write into MySQL db TABLE's *radcheck* and *radreply*.
#
# Trying to bring myself up to speed with a very basic task which I have defined below, in my
# older scripts I would define the *sub* itself, then in the script I would use an *if* test
# which checks to see if any defined FORM value returns a hit such as $form_data{'BuildAcct'} ne ""
# to call the required *sub* _ThisOne_.
print "Content-type: text/plain\n\n";
sub ThisOne {
print "Trying to display this subroutine upon submission of BuildAcct\n";
}
# Following is the *if* test I am accustomed to using to make a call to a particular sub when
# the form NAME BuildAcct is interacted with, but this is unacceptable now I realize.
# CLI Return:
# Use of uninitialized value $form_data{"BuildAcct"} in string ne at test.pl line 32.
# Use of uninitialized value $form_data{"BuildAcct"} in string ne at test.pl line 41.
if ($form_data{'BuildAcct'} ne "")
{
&ThisOne;
exit;
}
# SO, I have Google'd, and looked over numerous methods of calling *subs*, I am just stuck though,
# Why can't the following *if* test work if use of & is no longer used?
if ($form_data{'BuildAcct'} ne "")
{
ThisOne();
exit;
}
Thanking you in advance for help...
Best Regards
UPDATE **
I have turned the -w switch off on the script, not sure if that poses a negative influence, pretty new to perl.
I also created some clunky code that is ugly.
The weird thing is that from the CLI when I execute the script the system returns:
Use of uninitialized value $form_data{"BuildAcct"} in string at acctmanager.pl line 211.
Use of uninitialized value $form_data{"Test"} in string at acctmanager.pl line 212.
Yet VIA browser from a HTML doc I can change the SUBMIT name value back and forth between BuildAcct and Test and the script successfully returns two different and correct subroutines when submitted.
The BuildAcct sub returns form fields I defined within that subroutine, whereas Test does a MySQL TABLE GROUP rowfetch and displays 3 different tables from a db and prints them to the browser.
Below is my present code :-(
local ($form_data{'BuildAcct'}) = "$form_data{'BuildAcct'}";
local ($form_data{'Test'}) = "$form_data{'Test'}";
#
# AddNewUser FORM definition.
if ($form_data{'BuildAcct'} ne "")
{
&AddNewUser;
exit;
}
#
# DispTest FORM definition.
elsif ($form_data{'Test'} ne "")
{
&DispTest;
exit;
}
Could someone give me a nudge into the right direction possibly?
Thanking you in advance
ORIGINAL POST
At this point I have a FORM on an HTML doc named BuildAcct, likewise within my script I have defined the following which is to make the call to the subroutine AddNewUser when the user submits the HTML FORM...
if ($form_data{'BuildAcct'} ne "")
{
&AddNewUser;
exit;
}
The script uses cgi-lib.pl
# Enable parsing of FORM_DATA VIA cgi-lib.pl.
&ReadParse(*form_data);
## FORM or IMG FORM Fix
foreach (keys %form_data)
{
## Fix incoming form data with Image buttons
$form_data{$1} = $form_data{$_} if (/(.*)\.x/);
}
The thing I can't understand is why does this work in another script I use but this new script returns the following upon execution at the CLI;
Use of uninitialized value $form_data{"BuildAcct"} in string ne at acctmanager.pl line 208.
Use of uninitialized value $form_data{"Test"} in string ne at acctmanager.pl line 215.
Help and suggestions are greatly appreciated.
Best Regards
My best guess is that %form_data hash is being populated via cgi-lib.pl, therefore when you run it via command line, cgi-lib.pl isn't getting any input from the web browser... having said this, you haven't included the code where you're using cgi-lib.pl, so I can't be sure.
p.s. don't turn off warnings. They're there for a reason. If nothing else, you can paste the warning into google. While you're at it, alway put use strict; at the top of your script, and fix all undeclared variables.
To fix the error "Use of uninitialized value $form_data{"BuildAcct"} in string",
You can check with defined($form_data{"BuildAcct"}) or defined $form_data{"BuildAcct"} like below, before making use of $form_data{"BuildAcct"} :
if (defined $form_data{"BuildAcct"}) { < other code based on
$form_data{"BuildAcct"} > }

Finding the path to a Perl module upon loading

I am using a legacy Perl application which loads a library, call it "blah". I need to know where does "blah" resides in my file system.
I am not familiar at all with Perl, and I wonder what is the equivalent way to print the path to the module, along the lines of the special variable __file__ in Python. In other words, the Perl equivalent of the following Python script:
import blah
print blah.__file__
Many thanks.
use blah;
print $INC{'blah.pm'};
use Blah1::Blah2::blah;
print $INC{'Blah1/Blah2/blah.pm'};
The case is significant, even on Windows. use Blah will create an entry for $INC{'Blah.pm'} and use blah will create an entry for $INC{'blah.pm'}.
C:\>perl -MList::util -e "print join $/, keys %INC"
XSLoader.pm
Carp.pm
warnings/register.pm
Exporter.pm
vars.pm
strict.pm
List/util.pm
warnings.pm
To expand on my comment on mob's answer, try a more loose use of %INC to help you:
#!/usr/bin/perl
use strict;
use warnings;
use blah;
foreach (keys %INC) {
if (m'blah.pm') {
print "$_ => $INC{$_}\n";
}
}
The relevant perldoc perlvar on the subject says
%INC
The hash %INC contains entries
for each filename included via the do,
require, or use operators. The key is
the filename you specified (with
module names converted to pathnames),
and the value is the location of the
file found. The require operator uses
this hash to determine whether a
particular file has already been
included.
If the file was loaded via a
hook (e.g. a subroutine reference, see
require for a description of these
hooks), this hook is by default
inserted into %INC in place of a
filename. Note, however, that the hook
may have set the %INC entry by itself
to provide some more specific info.
If even that doesn't help, you may, as the previous document suggests, read about the require command, to help you understand how it is getting to be loaded in the first place. This should help you back it out, perhaps by iterating through #INC, which are the folders that Perl will search for to find files to be required.
I found the following one-liner which solved my problem:
$ perl -MList::Util -e'print $_ . " => " . $INC{$_} . "\n" for keys %INC'
Where -MList::Util stands for the List::Util module (in my case, I used -MBlah)