CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Residual effect

 



Larkdog
User

Aug 29, 2004, 5:22 AM

Post #1 of 12 (1471 views)
Residual effect Can't Post

I have a perl script for a guestbook @ www.mrlarkins.com

Seems that there is some kind of residual effect when someone submits an entry. Its kinda wierd...

One person will submit an entry, then when the next person makes a submission it has the first persons info mixed in with it...I dont have the foggiest idea what is causing this. Do you?
www.MrLarkins.com


davorg
Thaumaturge / Moderator

Aug 31, 2004, 1:34 AM

Post #2 of 12 (1419 views)
Re: [Larkdog] Residual effect [In reply to] Can't Post

Well, I guess it's caused by a bug in your code. But it's hard to give any more details without seeing the code.

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


Larkdog
User

Aug 31, 2004, 5:05 AM

Post #3 of 12 (1411 views)
Re: [davorg] Residual effect [In reply to] Can't Post


In Reply To
Well, I guess it's caused by a bug in your code. But it's hard to give any more details without seeing the code.



here you go:


Code
    

#!/usr/bin/perl

print "Content-type:text/html\n\n";

$|++;

use CGI::Carp qw(fatalsToBrowser);

# Relative path of Guestbook.html

$guestbook_file = '../html/guestbook/guestbook.html';

@month = ("January", "February", "March", "April", "May",

"June", "July", "August", "September", "October",

"November", "December");

if($ENV{'REQUEST_METHOD'} eq "POST"){

$data_length = $ENV{'CONTENT_LENGTH'};

$bytes_read = read(STDIN, $my_data, $data_length);

}

@name_value_array = split(/&/, $my_data);

foreach $name_value_pair (@name_value_array) {

($name, $value) = split(/=/, $name_value_pair);

$name =~ tr/+/ /;

$value =~ tr/+/ /;

$name =~ s/%(..)/pack("C",hex($1))/eg;

$value =~ s/%(..)/pack("C",hex($1))/eg;

if($form_data{$name})

{

$form_data{$name} .= "\t$value";

}

else

{

$form_data{$name} = $value;

}

}

($Seconds, $Minutes, $Hours, $DayInMonth, $Month,

$ShortYear, $DayOfWeek, $DayOfYear, $IsDST) = localtime(time);

$Year = $ShortYear + 1900;

$EntryDate = "$month[$Month] $DayInMonth, $Year";

open(GUESTBOOK, "<$guestbook_file") ||

die "Can't open GUESTBOOK: $guestbook_file\n";

@guestbook =<GUESTBOOK>;

close(GUESTBOOK);

open(GUESTBOOK, ">$guestbook_file") ||

die "Can't open GUESTBOOK: $guestbook_file\n";

foreach $line (@guestbook){

if($line =~ /<!--My Latest Guest:-->/i) {

print GUESTBOOK "<!--My Latest Guest:-->\n";

print GUESTBOOK "<DL>\n";

if($form_data{'email'}) {

print GUESTBOOK "<DD><I><B><A HREF=\"mailto:$form_data{'email'}\">

$form_data{'name'}</A></B></I>\n";

} else {

print GUESTBOOK "<DD><B>From : </B><I> $form_data{'name'}</I>\n";

}

print GUESTBOOK "<DD><B>Period: </B><I>$form_data{'period'}</I>\n";

print GUESTBOOK "<DD><B>Homepage:</B><I><A HREF=\"$form_data{'web'}\">$form_data{'web'}</A></I>\n";

print GUESTBOOK "<P>\n";

print GUESTBOOK "$form_data{'comments'}\n";

print GUESTBOOK "</P>\n";

print GUESTBOOK "<p><I><font size=2>\n";

print GUESTBOOK "signed on $EntryDate\n";

print GUESTBOOK "</font></I>\n";

print GUESTBOOK "</DL>\n";

print GUESTBOOK "<HR color=blue size=3>\n";

} else {

print GUESTBOOK "$line";

}

}

close(GUESTBOOK);





open (MAIL, "|sendmail -t");

print MAIL "To: $form_data{'name'}<$form_data{'email'}>\n";

print MAIL "From: Mr. Larkins <mrlarkins\@mrlarkins.com>\n";

print MAIL "Thank you $form_data{'name'} for signing my guestbook. You should be able to view it immediately.\n";

print MAIL "You submitted the following information to www.MrLarkins.com.\n";

print MAIL " \n";

print MAIL "Name: $form_data{'name'}\n";

print MAIL "Email Address: $form_data{'email'}\n";

print MAIL "Web Address: $form_data{'web'}\n";

print MAIL "Class Period: $form_data{'period'}\n";

print MAIL "Comments:\n";

print MAIL "$form_data{'comments'}\n";

print MAIL " \n";

print MAIL "Thanks.\n";

print MAIL "Mr. Larkins\n";

close (MAIL);

open (MAIL, "|sendmail -t");

print MAIL "To: Mr. Larkins <mrlarkins\@mrlarkins.com>\n";

print MAIL "From: $form_data{'name'}<$form_data{'email'}>\n";

print MAIL "Subject: I signed your guestbook\n\n";

print MAIL "$form_data{'name'} submitted the following entry to your guestbook.\n";

print MAIL " \n";

print MAIL "Name: $form_data{'name'}\n";

print MAIL "Email Address: $form_data{'email'}\n";

print MAIL "Web Address: $form_data{'web'}\n";

print MAIL "Class Period: $form_data{'period'}\n";

print MAIL "Comments:\n";

print MAIL "$form_data{'comments'}\n";

close (MAIL);



print <<"EOF"

<HTML><TITLE>Entry Submitted</TITLE><HEAD> <META HTTP-EQUIV="refresh" content="4;URL=../guestbook/guestbook.html"></HEAD><BODY>



<H1>Your GuestBook Entry has been Submitted\!</H1>

Your guestbook entry has been successfully added to the

guestbook and in <font size=24>3</font> seconds you will be taken back to view it.

</BODY>

EOF

#===========================



it would also be helpful if you guided me in convert this old style into one that uses 'param' feature
www.MrLarkins.com

(This post was
edited by Larkdog on Aug 31, 2004, 5:12 AM)


davorg
Thaumaturge / Moderator

Aug 31, 2004, 5:23 AM

Post #4 of 12 (1408 views)
Re: [Larkdog] Residual effect [In reply to] Can't Post

Is this running under mod_perl os some other persistant framework?

The main problem seems to be that you don't have "use strict" in your code. This means that all of your variables are package variables and aren't getting reset each time that the program is run. You should add "use strict" to the code (and, of course, "use warnings" as well) and then declare all of your variables with "my".

Another possible cause of the error is that you don't lock the files that you write. If two processes try to write to the file at the same time there is nothing to stop them. This means that your file will get corrupted.

Apart from that, you are using a very nasty (and potentially buggy) CGI parameter parser. This isn't causing your problem but it's generally considered a bad idea given that Perl has bundled the CGI module for almost ten years.

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


Larkdog
User

Aug 31, 2004, 11:21 AM

Post #5 of 12 (1393 views)
Re: [davorg] Residual effect [In reply to] Can't Post

umm, as to you first question about running under mod_perl, perhaps...I am unsure. You see, I have a lease from another company for hosting my website. And originally, when things were set up, I couldn't get the script to work from the cgi-bin. But it would work from the perl folder, so that is where it resides. Does that mean it is running under mod_perl? I dont know.

I went ahead and cleaned up the script abit (been a while since I wrote it, with help of course). I am not sure if I used the 'param' correctly, please look closely there. But I think I have used 'my' to declare all my variables.

Now about locking the files that are written to so that two processes dont execute at the same time. I have NO experience with this, so more details would be appreciated there...is that a CHMOD thing or something else in the script?


UPDATED SCRIPT BELOW:


Code
    



#!/usr/bin/perl

use strict;

use warnings;

use CGI ':cgi';

use CGI::Carp qw(fatalsToBrowser);

print header;

my $guestbook_file = '../html/guestbook/guestbook.html';

open(GUESTBOOK, $guestbook_file")

or die "Can't open GUESTBOOK: $guestbook_file - $!\n";

my @guestbook = <GUESTBOOK>;

close(GUESTBOOK);

open(GUESTBOOK, $guestbook_file")

or die "Can't open GUESTBOOK: $guestbook_file - $!\n";

foreach (@GUESTBOOK) {

if (/<!--My Latest Guest:-->/i) {

print GUESTBOOK "<!--My Latest Guest:-->\n";

print GUESTBOOK "<DL>\n";

if(param('email') {

print GUESTBOOK "<DD><I><B><A HREF=\"mailto:param('email')\">

param('name')</A></B></I>\n";

} else {

print GUESTBOOK "<DD><B>From : </B><I> param('name')</I>\n";

}

print GUESTBOOK "<DD><B>Period: </B><I>param('period')</I>\n";

print GUESTBOOK "<DD><B>Homepage:</B><I><A HREF=\"param('web')\">param('web')</A></I>\n";

print GUESTBOOK "<P>\n";

print GUESTBOOK "param('comments')\n";

print GUESTBOOK "</P>\n";

print GUESTBOOK "<p><I><font size=2>\n";

print GUESTBOOK "signed on param('date')\n";

print GUESTBOOK "</font></I>\n";

print GUESTBOOK "</DL>\n";

print GUESTBOOK "<HR color=blue size=3>\n";

} else {

print GUESTBOOK $_;

}

}

close(GUESTBOOK);

open (MAIL, "|sendmail -t");

print MAIL "To: param('name')<param('email')>\n";

print MAIL "From: Mr. Larkins <mrlarkins\@mrlarkins.com>\n";

print MAIL "Thank you param('name') for signing my guestbook. You should be able to view it immediately.\n";

print MAIL "You submitted the following information to www.MrLarkins.com.\n";

print MAIL " \n";

print MAIL "Name: param('name')\n";

print MAIL "Email Address: param('email')\n";

print MAIL "Web Address: param('web')\n";

print MAIL "Class Period: param('period')\n";

print MAIL "Comments:\n";

print MAIL "param('comments')\n";

print MAIL " \n";

print MAIL "Thanks.\n";

print MAIL "Mr. Larkins\n";

close (MAIL);

open (MAIL, "|sendmail -t");

print MAIL "To: Mr. Larkins <mrlarkins\@mrlarkins.com>\n";

print MAIL "From: param('name')<param('email')>\n";

print MAIL "Subject: I signed your guestbook\n\n";

print MAIL "param('name') submitted the following entry to your guestbook.\n";

print MAIL " \n";

print MAIL "Name: param('name')\n";

print MAIL "Email Address: param('email')\n";

print MAIL "Web Address: param('web')\n";

print MAIL "Class Period: param('period')\n";

print MAIL "Comments:\n";

print MAIL "param('comments')\n";

close (MAIL);





print <<"EOF"

<HTML>

<TITLE>Entry Submitted</TITLE>

<HEAD>

<META HTTP-EQUIV="refresh" content="4;URL=../guestbook/guestbook.html">

</HEAD>

<BODY>



<H1>Your GuestBook Entry has been Submitted\!</H1>

<p>Your guestbook entry has been successfully added to the

guestbook and in <font size=24>3</font> seconds you will be taken back to view it.</p>

</BODY>

</HTML>

EOF

www.MrLarkins.com

(This post was
edited by Larkdog on Aug 31, 2004, 11:27 AM)


davorg
Thaumaturge / Moderator

Aug 31, 2004, 1:02 PM

Post #6 of 12 (1387 views)
Re: [Larkdog] Residual effect [In reply to] Can't Post

Yep. If you're running from a "perl" directory then the program is almost certainly running under Apache::Registry in mod_perl - this would explain the problems that you were seeing.

Here's my version of your program. I've made the following changes:

* Added the Fcntl module for file locking.
* Open file in read/write mode.
* Get exclusive lock on filehandle.
* Truncate filehandle after reading (thereby avoiding the need to close and reopen the file).
* Read all CGI parameters into a hash called %data. This is because you can't expand function calls (like param('foo')) in a quoted string.
* Replaced a couple of double quoted strings with qq() to remove the need to escape internal double quotes.
* Changed some multiple print statements into heredocs.
* Removed the variable data from the email sent to the person filling in the form. This is very important as it stops your form being used to send spam.

Hope it all makes sense.


Code
#!/usr/bin/perl 

use strict;
use warnings;

use CGI ':cgi';
use CGI::Carp qw(fatalsToBrowser);
use Fcntl ':flock';

print header;

my $guestbook_file = '../html/guestbook/guestbook.html';

open(GUESTBOOK, "+<$guestbook_file")
or die "Can't open GUESTBOOK: $guestbook_file - $!\n";

flock GUESTBOOK, LOCK_EX or die;

my @guestbook = <GUESTBOOK>;

seek GUESTBOOK, 0, 0;
truncate GUESTBOOK, 0;

my %data;
$data{$_} = param($_) for qw(email name period web comments date);

foreach (@guestbook) {
if (/<!--My Latest Guest:-->/i) {
print GUESTBOOK "<!--My Latest Guest:-->\n<DL>\n";

if($data{email}) {
print GUESTBOOK qq(<DD><I><B><A HREF="mailto:$data{email}">$data{name}</A></B></I>\n);
} else {
print GUESTBOOK "<DD><B>From : </B><I>$data{name}</I>\n";
}

print GUESTBOOK <<END;
<DD><B>Period: </B><I>$data{period}</I>;
<DD><B>Homepage:</B><I><A HREF="$data{web}">param('web')</A></I>
<P>
$data{comments}
</P>
<p><I><font size=2>
signed on $data{date}
</font></I>
</DL>
<HR color=blue size=3>
END
} else {
print GUESTBOOK $_;
}
}

close(GUESTBOOK);

open (MAIL, '|sendmail -t -oi') or die $!;

print MAIL <<END;
To: $data{name} <$data{email}>
From: Mr. Larkins <mrlarkins\@mrlarkins.com>

Thank you $data{name} for signing my guestbook. You should be able to view
it immediately.

Thanks.
Mr. Larkins
END

close (MAIL);

open (MAIL, '|sendmail -t -oi') or die $!;
print MAIL <<END;
To: Mr. Larkins <mrlarkins\@mrlarkins.com>
From: $data{name} <$data{email}>
Subject: I signed your guestbook

$data{name} submitted the following entry to your guestbook.

Name: $data{name}
Email Address: $data{email}
Web Address: $data{web}
Class Period: $data{period}
Comments:
$data{comments}
END

close (MAIL);

print <<EOF
<HTML>
<HEAD>
<TITLE>Entry Submitted</TITLE>
<META HTTP-EQUIV="refresh" content="4;URL=../guestbook/guestbook.html">
</HEAD>
<BODY>
<H1>Your GuestBook Entry has been Submitted\!</H1>
<p>Your guestbook entry has been successfully added to the
guestbook and in <font size=24>3</font> seconds you will be taken back
to view it.</p>
</BODY>
</HTML>
EOF


--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


Larkdog
User

Aug 31, 2004, 6:23 PM

Post #7 of 12 (1379 views)
Re: [davorg] Residual effect [In reply to] Can't Post

yes, that makes some sense, i will have to read, reread, and re-reread it and compare to the code before i fully understand every change... i think i can get it

i also like how you reworked the SENDMAIL, I really appreciate that!

Finally, I ran your code from the command line and got an error "can't find string terminator anywhere near EOF at line 37"...well that is where <<END; is ...am I missing something obvious???
www.MrLarkins.com

(This post was
edited by Larkdog on Aug 31, 2004, 6:33 PM)


davorg
Thaumaturge / Moderator

Aug 31, 2004, 10:23 PM

Post #8 of 12 (1369 views)
Re: [Larkdog] Residual effect [In reply to] Can't Post

It's probably just a cut and paste problem. All of the end-of-heredoc markers need to be on a line on their own - with no whitespace before or after them.

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


(This post was edited by davorg on Sep 1, 2004, 1:11 AM)


Larkdog
User

Sep 1, 2004, 5:12 AM

Post #9 of 12 (1357 views)
Re: [davorg] Residual effect [In reply to] Can't Post

yep that was it, empty spaces, man i should have known better! LOL

last thing, gettin it to add the date and time...could i do this?


Code
  

my @month = ("January", "February", "March", "April", "May",

"June", "July", "August", "September", "October",

"November", "December");

($Seconds, $Minutes, $Hours, $DayInMonth, $Month,

$ShortYear, $DayOfWeek, $DayOfYear, $IsDST) = localtime(time);

$Year = $ShortYear + 1900;

$EntryDate = "$month[$Month] $DayInMonth, $Year";

$EntryTime = "$Hours:$Minutes";



or is there a easier way?
www.MrLarkins.com


davorg
Thaumaturge / Moderator

Sep 1, 2004, 5:55 AM

Post #10 of 12 (1355 views)
Re: [Larkdog] Residual effect [In reply to] Can't Post

Well, you _could_ go to all that hassle, but I've never really understood why people insist on building their own date and time formatting functions when POSIX::strftime is included with the standard Perl installation.


Code
use POSIX 'strftime'; 

my @time = localtime;
$EntryDate = strftime '%B %d, %Y', @time;
$EntryTime = strftime '%H:%M', @time;


--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


Larkdog
User

Sep 1, 2004, 11:03 AM

Post #11 of 12 (1351 views)
Re: [davorg] Residual effect [In reply to] Can't Post

ok thanks, my problem is i dont know everything that is included with the standard Perl installation... thanks again,
a correction:


Code
 use POSIX 'strftime';  

my @time = localtime;
my $EntryDate = strftime '%B %d, %Y', @time;
my $EntryTime = strftime '%H:%M', @time;

www.MrLarkins.com

(This post was
edited by Larkdog on Sep 1, 2004, 2:37 PM)


Larkdog
User

Sep 1, 2004, 8:19 PM

Post #12 of 12 (1326 views)
Re: [davorg] Residual effect [In reply to] Can't Post

LOL, the clock is 1 hour fast...
www.MrLarkins.com

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives