homepage Welcome to WebmasterWorld Guest from 54.198.140.148
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / Perl Server Side CGI Scripting
Forum Library, Charter, Moderators: coopster & jatar k & phranque

Perl Server Side CGI Scripting Forum

    
array and counting distinctions
help wanted on an array with two variables and one counter
creativeedg10




msg:4097780
 6:12 am on Mar 15, 2010 (gmt 0)

Hello everyone,

I am a CGI student completely new to the subject. I have a project due in two days, and I've been struggling with it all week. Unfortunately, my instructor poorly teaches the subject, and I am out of resources but the online world. May you please help me?

I have an html page that contains a form. This form is simply a list of radio buttons of college names.

In CGI, I must return the college name to the user..in addition to the college mascot (which is not a value in the html form). I'm lost about how to set up this array?

Lastly, I must also return a counter that is counting how many times the user clicks on a college radio button. I don't know where to start. The array scenario is giving me the most difficult time. Do I use an index array or hash? How do I communicate the college name with the mascot together?

I would appreciate any help you may have to offer. Thank you for your time in reading.

 

janharders




msg:4097832
 8:26 am on Mar 15, 2010 (gmt 0)

Welcome to WebmasterWorld, creativeedg10!

Yes, a hash would be the easiest way to go.
Since you'll need to save data in some way (they were probably aiming at cookies, but that's boring): introducing files.

The following code will read data from a file (with read_file) that is in
key = value
key2 = value2
format and fill it into a hash.
It'll then increase one value in that hash and write it back to the file with write_file.

run it from the command line a few times to see that counter increase over multiple runs.
That should get your started, but feel free to ask if you have any questions.


#!/usr/bin/perl
use strict;

my %hash = read_file('test.txt');
print 'test: ' . $hash{'test'} . "\n";
$hash{'test'}++;
print 'test: ' . $hash{'test'} . "\n";
write_file('test.txt', %hash);


sub read_file {
my $file = shift;
my %hash = ();
if(!-e $file)
{
warn "file '" . $file . "' does not exist!\n";
return ();
}
open(FILE, '<', $file) || die "Error opening '" . $file . "': " . $!;
while(my $line = <FILE>)
{
chomp($line);
next if(!$line);
print $line . "\n";
my ($key, $value) = split(/\s*=\s*/, $line, 2);
$hash{ $key } = $value;
}
close(FILE);
return %hash;
}

sub write_file {
my $file = shift;
my %hash = @_;
open(FILE, '>', $file) || die "Error opening '" . $file . "': " . $!;
for my $key (keys %hash)
{
print $key . " = " . $hash{ $key } . "\n";
print FILE $key . ' = ' . $hash{ $key } . "\n";
}
close(FILE);
}

creativeedg10




msg:4098086
 4:46 pm on Mar 15, 2010 (gmt 0)

Hi janharders,

Thank you so much for your quick and thorough response. I did some further research after posting here and think I am on the right track as you mention.

Unfortunately, I still get errors when viewing in the browser, but it's a start.

The following is the CGI code I have started. If you could supply me with your review and further advice, I would value your feedback as well. Thanks again so much for your help.

#!/usr/bin/perl
#final.cgi - saves form data to a file, and creates a dynamic
#Web page that displays a message and survey statistics
print "Content-type: text/html\n\n";
use CGI qw(:standard -debug);
use strict;

#declare variables
my ($college, $mascot, $size, @records, @errors);
my %college_count = ("Baker", 0,
"Michigan", 0,
"State", 0,
"Eastern", 0,
"Central", 0,
"Wayne", 0,
"Lawrence", 0,
"Mercy", 0);
my %mascot = ("Baker", "Bears",
"Michigan","Wolverines",
"State", "Spartans",
"Eastern", "Eagles",
"Central", "Chippewas",
"Wayne", "Warriors",
"Lawrence", "Devils",
"Mercy", "Titans");

#assign input items to variables
$college = param('College');

#validate input data
if($college ne "Baker" and $college ne "Michigan" and $college ne "State" and $college ne "Eastern" and $college ne "Central" and $college ne "Wayne" and $college ne "Lawrence" and $college ne "Mercy"){
push(@errors, "Select a college");
}

#determine size of @errors array
$size = @errors;

#process input data or display error page
if($size == 0){
#process input data
#save form data to a file
open(OUTFILE, ">>", "survey.txt")
or die "Error opening survey.txt. #!, stopped";
print OUTFILE "$college\n";
close(OUTFILE);

#calculate survey statistics
open(INFILE, "<", "survey.txt")
or die "Error opening survey.txt. $!, stopped";
@records = <INFILE>;
close(INFILE);
foreach my $rec (@records) {
chomp($rec);
($college) = split(/,/, $rec);
$college_count{$college} = $college_count{$college} + 1;
}

#generate HTML acknowledgment
print "<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H2>Thank you for visiting the American College web site!</H2>\n";

print "<H2>You selected $college.</H2>\n";

foreach $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy"){
print "$key is home of the $mascot{$key}\n";
}

print "<EM><B>See the current college results below:</EM></B>\n";
print "<TABLE>\n";
foreach my $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy") {
print "<TR><TD>$key</TD> <TD>$college_count{$key}</TD></TR>\n";
}
print "</TABLE>\n";
print "</BODY></HTML>\n";
}
else {
#display error page
print "<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H2>You did not make a valid selection. Please click the BACK button and your browser \n";
print "and complete the survey. Thank you! </H2><BR>\n";
for(my $x = 0; $x < $size; $x = $x +1){
print "$errors[$x]<BR>\n";
}
print "</BODY></HTML>\n";
}

creativeedg10




msg:4098087
 4:47 pm on Mar 15, 2010 (gmt 0)

Sorry for the code display above. I see that it didn't set my tabs over correctly. It's a bit hard to read :/

janharders




msg:4098120
 5:50 pm on Mar 15, 2010 (gmt 0)

you're using "use strict;" which is great and you should keep doing that.
But that's also the reason your script fails, the line
foreach $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy") {
should be
foreach my $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy") {

also, you may want to add
use CGI::Carp qw(fatalsToBrowser);
somewhere at the top, so that it'll try to display errors in your browser rather than just die and give you a generic HTTP-500 Errorpage.

janharders




msg:4098121
 5:53 pm on Mar 15, 2010 (gmt 0)

Oh, and for the review-part: you're doing good so far. Maybe use the stuff I wrote earlier, that'll make the whole file-handling easier (while also not that efficient, but who cares).

phranque




msg:4098568
 5:54 am on Mar 16, 2010 (gmt 0)

welcome to WebmasterWorld [webmasterworld.com], creativeedg10!

what kind of errors are you getting?
sometimes it helps to run the script in the command line and see if anything obvious shows up there.
also note that whenever there is a 500 Internal Server Error there should be an entry in the server error log that shows what happened or perhaps at least a line number in the script that caused the error.

creativeedg10




msg:4098588
 7:12 am on Mar 16, 2010 (gmt 0)

janharders,

Thank you for your help and encouragement along the way. As a struggling beginner, I really appreciate it.

I did add the missing my in my foreach statement, but I'm still stuck. However, I'm hanging in there and doing the best I can. This is quite the learning experience.

The CGI::Carp code unfortunately doesn't seem to be providing information. I added it under use strict;

I'll have to look into the file-handling more too when I get a chance as you mention. I am getting this error in the perl -c check:

Variable "$INFILE" is not imported at final.cgi line 52.
Global symbol "$INFILE" requires explicit package name at final.cgi line 52.
final.cgi had compilation errors.

creativeedg10




msg:4098592
 7:18 am on Mar 16, 2010 (gmt 0)

Hi phranque,

Thank you for your interest. Yes, I am receiving the 500 Internal Server Error. I get this one too much, haha.

I just fixed the perl -c check. My syntax is okay so the error I had in line 52 mentioned in the previous post is cleared and fixed.

creativeedg10




msg:4098596
 7:20 am on Mar 16, 2010 (gmt 0)

I just did a perl -w check, and it appears that my entire array is being printed, not just an individual radio button selection...if I'm reading it right.


(offline mode: enter name=value pairs on standard input; press ^D or ^Z when done)
College=Baker
Use of uninitialized value in addition (+) at final.cgi line 55.
Use of uninitialized value in addition (+) at final.cgi line 55.
<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>
<BODY>
<H2>Thank you for visiting the American College web site!</H2>
<H2>You selected Baker.</H2>
Baker is home of the Bears
Michigan is home of the Wolverines
State is home of the Spartans
Eastern is home of the Eagles
Central is home of the Chippewas
Wayne is home of the Warriors
Lawrence is home of the Devils
Mercy is home of the Titans
<EM><B>See the current college results below:</EM></B>
<TABLE>
<TR><TD>Baker</TD> <TD>1</TD></TR>
<TR><TD>Michigan</TD> <TD>0</TD></TR>
<TR><TD>State</TD> <TD>0</TD></TR>
<TR><TD>Eastern</TD> <TD>0</TD></TR>
<TR><TD>Central</TD> <TD>0</TD></TR>
<TR><TD>Wayne</TD> <TD>0</TD></TR>
<TR><TD>Lawrence</TD> <TD>0</TD></TR>
<TR><TD>Mercy</TD> <TD>0</TD></TR>
</TABLE>
</BODY></HTML>


creativeedg10




msg:4098597
 7:22 am on Mar 16, 2010 (gmt 0)

Although, it did appear to do my counter addition...is this correct? Perhaps I'm not sure how to read this check?

I'm not entirely sure if I changed my code since the last preview, but it is as currently follows for reference:


#!/usr/bin/perl
#final.cgi - saves form data to a file, and creates a dynamic
#Web page that displays a message and survey statistics
print "Content-type: text/html\n\n";
use CGI qw(:standard -debug);
use strict;

#declare variables
my ($college, $mascot, $size, @records, @errors);
my %college_count = ("Baker", 0,
"Michigan", 0,
"State", 0,
"Eastern", 0,
"Central", 0,
"Wayne", 0,
"Lawrence", 0,
"Mercy", 0);
my %mascot = ("Baker", "Bears",
"Michigan","Wolverines",
"State", "Spartans",
"Eastern", "Eagles",
"Central", "Chippewas",
"Wayne", "Warriors",
"Lawrence", "Devils",
"Mercy", "Titans");

#assign input items to variables
$college = param('College');

#validate input data
if($college ne "Baker" and $college ne "Michigan" and $college ne "State" and $college ne "Eastern" and $college ne "Central" and $college ne "Wayne" and $college ne "Lawrence" and $college ne "Mercy"){
push(@errors, "Select a college");
}

#determine size of @errors array
$size = @errors;

#process input data or display error page
if($size == 0){
#process input data
#save form data to a file
open(OUTFILE, ">>", "survey.txt")
or die "Error opening survey.txt. #!, stopped";
print OUTFILE "$college\n";
close(OUTFILE);

#calculate survey statistics
open(INFILE, "<", "survey.txt")
or die "Error opening survey.txt. $!, stopped";
@records = <INFILE>;
close(INFILE);
foreach my $rec (@records) {
chomp($rec);
($college) = split(/,/, $rec);
$college_count{$college} = $college_count{$college} + 1;
}

#generate HTML acknowledgment
print "<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H2>Thank you for visiting the American College web site!</H2>\n";

print "<H2>You selected $college.</H2>\n";

foreach my $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy"){
print "$key is home of the $mascot{$key}\n";
}

print "<EM><B>See the current college results below:</EM></B>\n";
print "<TABLE>\n";
foreach my $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy") {
print "<TR><TD>$key</TD> <TD>$college_count{$key}</TD></TR>\n";
}
print "</TABLE>\n";
print "</BODY></HTML>\n";
}
else {
#display error page
print "<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H2>You did not make a valid selection. Please click the BACK button and your browser \n";
print "and complete the survey. Thank you! </H2><BR>\n";
for(my $x = 0; $x < $size; $x = $x +1){
print "$errors[$x]<BR>\n";
}
print "</BODY></HTML>\n";
}


creativeedg10




msg:4098601
 7:41 am on Mar 16, 2010 (gmt 0)

Nevermind again. I just fixed the problem of my repeating array with a new variable declaration and the following print out of code:


foreach $key (@mascot){
print "$key is home of the $mascot{$key}\n";
}


Now, it appears I only have two problems:

1. I have an error that reads "use of uninitialized value in (+) at final.cgi line 56

2. I can't get rid of the internal error for the life of me

creativeedg10




msg:4098611
 8:09 am on Mar 16, 2010 (gmt 0)

Okay, down to my last error...I just can't get rid of the internal browser error. Perl -w check is perfect.

So is that good or bad news? haha

janharders




msg:4098659
 10:40 am on Mar 16, 2010 (gmt 0)

did you give it the correct mode? cgi-scripts usually need 755, so try to set that via your ftp client.
also, make sure that #!/usr/bin/perl is the correct path to perl on the server. to make sure that it's not failing due to line ending-issues between operating systems, replace
#!/usr/bin/perl
with
#!/usr/bin/perl -w

it will add warning, which is nice anyway, but most of all, it'll make sure that line endings won't play a role in execution of the perl interpreter.

phranque




msg:4098679
 11:38 am on Mar 16, 2010 (gmt 0)

i assume you meant "Internal Server Error" rather than "internal browser error".
this is a 500 Internal Server Error [w3.org] HTTP Response status code which almost invariably results in a server error log entry.
common locations include /var/log/apache/error_log or /var/log/httpd/error_log although there may be an additional directory level or a different path if you are on a shared server.
in some case you can access your error log through a web-based server control panel.
if possible you should look in the error log for clues instead of wasting time on guesses.

janharders




msg:4098744
 1:40 pm on Mar 16, 2010 (gmt 0)

Problem is, with many shared hosting-environments, you don't get access to the errorlog.
And: since it runs fine on command line, it should not be a syntax-error. Since CGI::Carp doesn't help, my bet is on either chmod or shebang.

phranque




msg:4098790
 2:29 pm on Mar 16, 2010 (gmt 0)

if you run it from the commmand line as a native script (i.e. without specifying the perl command) then the shebang should be correct.
and don't forget permissions and ownership must be complementary.

janharders




msg:4098804
 2:47 pm on Mar 16, 2010 (gmt 0)

Well, depends on wether the command line run is on the same server. If it is, you're right and he's probably able to view the error log. If it's not, or he's running it as perl script.cgi, it doesn't say anything.
and yeah, you're right, ownership might be an issue, too. I don't recall the last time I've worked with suexec, does it throw any specific error message or does it just return a 403 or 500?

phranque




msg:4098823
 3:26 pm on Mar 16, 2010 (gmt 0)

by "run as native" i mean invoke with ./script.cgi in script directory or /path/to/script.cgi otherwise.
in either case there is no 500 - that's a http protocol thing.
also the error message when running as a script is whatever goes to stderr with time stamp, etc added in the http error log case.

janharders




msg:4098872
 3:58 pm on Mar 16, 2010 (gmt 0)

I know what you meant, the problem persists, though: if you invoke the script via shell to find the right interpreter, it won't help if it runs as cgi on another machine, because the path to perl might differ.
I still believe firmly that
ln -s /usr/bin/perl "/usr/bin/perl$(echo -e "\r")"

would make alot of 500's go away.
If he is able to access the errorlog, the solution should be at hand, but from my experience, many shared hosting providers don't give you direct access to the errorlog. Since I haven't worked on shared hosting for a few years now, that might have changed.

creativeedg10




msg:4099193
 1:49 am on Mar 17, 2010 (gmt 0)

Thanks for all the feedback. I'm working on the code right now and hopefully will be able to figure it out.

I am getting the 500 server error.

creativeedg10




msg:4099242
 3:10 am on Mar 17, 2010 (gmt 0)

Hi everyone,

Well, this was the fix:
replace
#!/usr/bin/perl
with
#!/usr/bin/perl -w

My code is officially working, and I owe so many thanks to you all for helping me along the way. It has been quite the learning experience, and you have no idea how much I appreciate your support, encouragement, and sharing of knowledge. Thanks for helping a beginner have the confidence to reach the final product!

phranque




msg:4099343
 7:10 am on Mar 17, 2010 (gmt 0)

that's actually quite strange.
the -w flag should enable warnings but it shouldn't actually "fix" anything or change how the script runs other than the possible warning output.

janharders




msg:4099364
 8:03 am on Mar 17, 2010 (gmt 0)

No, phranque, the -w fixes the line-ending problem, because the shell will run /usr/bin/perl with "-w\r" as an argument. perl itself is smart enough to handle that.

phranque




msg:4099497
 1:13 pm on Mar 17, 2010 (gmt 0)

if you're lucky, you learn something new every day.
i always just fixed the line ending problem.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / Perl Server Side CGI Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved