Dave Adams <mailto:[EMAIL PROTECTED]> wrote:
I urge all readers *not* to use this site. Just don't visit it. I won't even quote the url. If you want to learn about perl and CGI visit Ovid's course at http://users.easystreet.com/ovid/cgi_course/index.html. : Being a junior perl programmer, I read a lot of docs and I came : across a really good site that is well written and structured. : If you are just starting out, I would highly recommend it. No. This is an outdated tutorial. It was written between 1999 and 2001. The Author fails to emphasize the use of lexical variables, strictures, and warnings. The CGI section is impressive, but apparently omits taint checking and again leaves out strict and warnings. Here's an example which teaches several poor lessons. (I added the line numbers.) 1: #!/usr/local/bin/perl 2: use CGI; 3: 4: $cgiobject=new CGI; 5: 6: print $cgiobject->header; 7: 8: #read in template page 9: $templateFile="smallville.html"; 10: open(INFILE,"<$templateFile"); 11: @templatePage=<INFILE>; 12: close(INFILE); 13: 14: #condense page array into one scalar variable 15: $resultPage=join("",@templatePage); 16: 17: #determine current date 18: ($sec,$min,$hour,$mday, 19: $mon,$year,$wday,$yday,$isdst)=localtime(time); 20: $curDay=(Sunday,Monday,Tuesday,Wednesday, 21: Thursday,Friday,Saturday)[$wday]; 22: $curMonth=(January,February,March,April, 23: May,June,July,August,September, 24: October,November,December)[$mon]; 25: $liveDate="$curDay, $curMonth $mday, ".($year+1900); 26: 27: #search-and-replace on date 28: $resultPage=~s/INSERT DATE HERE/$liveDate/g; 29: 30: #done, output page to browser 31: print $resultPage; The author is obviously used to writing without strictures. That date routine (lines 17-25) is very telling. Those are barewords in lines 20 through 24. They're not wrapped by the qw() operator. Note the lack of error checking in I/O operations (lines 10 and 12), the use of double quotes when single quotes will do (lines 9 and 15), and the lack of white space to improve readability (though he does use good leading white space). Note the inconsistency in the variable naming convention. Line 4 uses "$cgiobject" as a variable name while the mixed case ($cgiObject) seems to be the convention. Many of these items may seem very minor mistakes. One mistake is okay, but after six years, this should be a near perfect perl guide. Here's an untested, insecure rewrite. It requires a previous introduction CGI security would be needed. Like this one: http://users.easystreet.com/ovid/cgi_course/lessons/lesson_three.html 1: #!/usr/bin/perl -T 2: 3: use strict; 4: use warnings; 5: 6: use POSIX 'strftime'; 7: use CGI::Carp qw(fatalsToBrowser); 8: use CGI; 9: 10: # Read template page. 11: my $file = 'smallville.html'; 12: open my $fh, '<', $file or die qq(Cannot open "$file": $!); 13: my $template = do { local $/; <$fh> }; 14: close $fh or die qq(Cannot close "$file": $!); 15: 16: # Current date. 17: my $date = strftime '%A, %B %d, %Y', localtime; 18: 19: # Search and replace fields. 20: $template =~ s/INSERT DATE HERE/$date/g; 21: 22: # Output page to browser. 23: my $cgi = CGI->new(); 24: print $cgi->header(), $template; 25: 26: __END__ I prefer strftime() for dates because it is a fairly common routine. In fact, the guide I used to write this format was written for PHP. Let's take a look at some typically bad subroutines (the arbitrary line numbers are mine). We can see by line 3 that the idea of getting return values from a subroutine is not foreign to this script's author. Yet he consistently operates on external variables in every subroutine in his script. Worse, there are other examples in these pages where the author *does* use lexically scoped variables. He even insists on it later on. 1: sub build_a_pizza() 2: #build the pizza form using old "build-a-pizza" script 3: { @allparams=$cgiobject->param(); 4: if ($#allparams>-1) 5: {&get_state_variables} 6: else 7: {&init} 8: 9: if ($orderComplete) 10: { &complete_order } 11: else 12: { &build_order } 13: } . . . 56: sub init() 57: #define initial values for pizza parameters 58: { $name="Your name"; 59: $address="Where to?"; 60: $phone="Your phone"; 61: $deliver="deliver"; 62: $toppings="pepperoni"; 63: $size="large"; 64: } 65: 66: sub get_state_variables() 67: #grab any parameters which were submitted 68: { $name=$cgiobject->param("order_name"); 69: $address=$cgiobject->param("order_address"); 70: $phone=$cgiobject->param("order_phone"); 71: $deliver=$cgiobject->param("order_deliver"); 72: $toppings=$cgiobject->param("order_toppings"); 73: $size=$cgiobject->param("order_size"); 74: $newOrderFlag=$cgiobject->param("newOrderFlag"); 75: $orderComplete=$cgiobject->param("finish") 76: } We can assume that the author just doesn't know better. But only if we stop reading. Later the author agrees that subroutine values *should* always be passed in and out. Here's an excerpt. <quote> Along these lines, one generally wants to avoid global variables, and subroutines tend to work on variables within their own little mental space. Thus, we typically pass values into subroutines - the values they need to know - and subroutines can return values back to the calling expressions. You scratch their back, they scratch yours. . . . sub mySub { my ($value,$list,$hash)[EMAIL PROTECTED]; ...etc... } </quote> This portion was written in March, 2001. The author has known of these techniques for more than four years. So the author of this particular perl guide should either pull it off the web or rewrite it. I urge all readers *not* to use this site. Just don't visit it. HTH, Charles K. Clarkson -- Mobile Homes Specialist 254 968-8328 -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>