stonecolddevin has asked for the wisdom of the Perl Monks concerning the following question:

Hey everyone, I just finished up this guestbook I have been finalizing for a couple weeks now, and it just won't work on the server I am uploading it to (if it helps, it is jcwren's server) this server. I have checked the error log and it comes up with this:
1257 Uncaught exception from user code: 1258 syntax error at /home/dhoss/public_html/dynamic/book/b +ook.cgi line 176, near "</html" 1259 Execution of /home/dhoss/public_html/dynamic/book/book.cgi abo +rted due to compilation errors. 1260 [Wed Apr 23 23:51:36 2003] [error] [client 152.163.188.167] Pr +emature end of script headers: /home/dhoss/public_html/dynamic/book/b +ook.cgi
Now here is the script:
#!/usr/bin/perl -w ################################################################### # ScapeBook version 1.0 # Date written: 3/30/03 (completed as final production on this date # Freeware compliments of http://dreamscapedesigns.cjb.net # Written and designed by Dhoss of DreamScape designs # This is freeware, however, if you choose to use this script, please +take # notice of the appending disclaimer and also keep this copyright inta +ct. # Email any and ALL problems to dhoss@dreamscapedesigns.cjb.net, or fi +ll out # our buglog form @ our website (http://dreamscapedesigns.cjb.net/bugs +.pl?action=ScapeBook) # Questons? Comments? Please email me at dhoss@dreamscapedesigns.cjb.n +et! # Have fun with your new guestbook!!! # -Dhoss #################################################################### # DISCLAIMER # Copyright Dreamscape designs 2003 version 1.0 # All problems arising from the use of this book that may cause # damage or other undesired performances are not a liabity of # Dreamscape designs, Devin J. Austin, or any other Dreamscape affilia +tes. # This copyright must remain intact. # Kindly ask for permission to sell the code for this guestbook , as I + will # gladly say yes. Written consent must be obtained before selling this + code! #################################################################### # Note to users: # view readme.txt for extensive FAQ, installation, configuration, and +tutorial help ##################################################################### use CGI qw(-compile :all); use strict; use diagnostics; #Comment out after first test drive!!! #use CGI::Carp qw(warningsToBrowser fatalsToBrowser); #Variables my $q = new CGI(); my $action = $q->param('action'); my $data_file = "data/data.dat"; my $t = $q->param('t'); #my $ipLogFile = "data/ip.dat"; my $page_title = "ScapeBook v1.0 --http://dreamscape.cjb.net--"; my $form_validate_script = "validate/form_data.js"; my $ipLog = 0; #the following is all the arrays that are used in this script #associative array for images #img tag will now look like this: #<img src="$images{logo};"> ############################################################## my %images = ('logo', '../../img/logo.gif', 'submit', 'img/submit.jpg', 'addTo', 'img/add.jpg', 'adminBook', 'img/adminBook.jpg', 'previewEntry', 'img/prev.jpg', 'linkLogo', 'img/lilLogo.jpg', 'bg', 'img/bg.jpg'); #associative array for URLS my %urls = ('DreamScape', 'http://dreamscape.cjb.net', 'admin', 'admin/admin.pl', 'sign_book', 'book.cgi?action=sign', 'preview_entry', 'book.cgi?action=preview', 'view_entries', 'book.cgi?action=view_entry', 'report_bug', 'http://dreamscape.cjb.net/bugs.cgi?action=ScapeBook', 'page_style_sheet', 'css/book.css', 'cgi_url', 'book.cgi'); # Initialize list of months my @month = ("January", "February", "March", "April", "May", "June", " +July", "August", "September", "October", "November", "December"); + #Okay, not an array, but it goes with the date procedure # Get the date and time information my ($Seconds, $Minutes, $Hours, $DayInMonth, $Month, $ShortYear, $DayO +fWeek, $DayOfYear, $IsDST); ($Seconds, $Minutes, $Hours, $DayInMonth, $Month, $ShortYear, $DayOfWe +ek, $DayOfYear, $IsDST) = localtime(time); # Fix the year to keep it Y2K compliant, as described in 'Perl and Y2K +' # http://perl.about.com/library/weekly/aa070299.htm my $Year = $ShortYear + 1900; my $EntryDate = "$month[$Month] $DayInMonth, $Year"; ################################################# #init subs for page $| = 1; main(); sub main { write_to_file() if ($q->param('do_it') eq 's'); print_page() if ($q->param('action') eq ''); print_form() if ($action eq 'sign'); } if ($action eq 'view_entry') { print_main(); } sub print_main { print qq( <html> <head> <title>Guestbook Entries</title> <link rel="stylesheet" type="text/css" href="$urls{'page_style_she +et'}"> </head> <body> <center> <img src="$images{'logo'}"> <hr> Guestbook entries:); show_book_entries(); print qq( <hr> <a href="$urls{'cgi_url'}?action=sign">Sign this book</a> | <a href="$ +urls{'cgi_url'}">Back to the guestbook main page</a><br>~; create_footer(); print qq( </body> </html> ); } ################################################ sub print_page{ print qq( <html> <head> <title>$page_title</title> <link rel="stylesheet" type="text/css" href="$urls{'page_style_sheet'} +"> </head> <body> <center> <img src="$images{'logo'}"> <hr> Welcome to my guestbook! I have worked very hard and put all of my per +l knowledge into this, so I hope you like it!<br> <br> -Dhoss <br> <br> <table> <tr> <td> Guestbook functions: </td> </tr> <tr> <td> <br> <ul> <li><a href="$urls{'sign_book'}">Sign the book</a> <li><a href="$urls{'view_entries'}">View the guestbook entries</a> <li><a href="$urls{'admin'}">Admin the guestbook (PASSWORD AUTHENTICAT +ION REQUIRED)</a> <li><a href="$urls{'report_bug'}">Report a bug</a> <li><a href="$urls{'DreamScape'}">Dreamscape.cjb.net</a> </ul> </tr> </td> </table> <hr>); create_footer(); print qq) </body> </html>); sub print_form { print qq( <html> <head> <title>Sign the guestbook!</title> <link rel="stylesheet" type="text/css" href="$urls{'page_style_she +et'}"> <script language="JavaScript" src="js/frm_validate.js"></script> </head> <body> <center> <img src="$images{'logo'}"><hr> <form action="$urls{'cgi_url'}" method="post" name="guest" onSubmit="r +eturn validateRateFrm();"> <input type="hidden" name="do_it" value="s"> <input type="hidden" name="t" value="sign_success"> <table width=150 cellspacing=0 cellpadding=5> <tr> <td>Your Name:&nbsp; <input type="text" name="name"></td> </tr> <tr> <td>Your Email:&nbsp; <input type="text" name="email"></td> </tr> <tr> <td>Your Country:&nbsp; <input type="text" name="country"></td> </tr> <tr> <td>Your state/province/territory:&nbsp; <input type="text" name="stat +e"></td> </tr> <tr> <td>Your city:&nbsp; <input type="text" name="city"></td> </tr> <tr> <td>Rate this site:&nbsp; <select name="rate" size=3> <option>RATE <option>10 <option>9 <option>8 <option>7 <option>6 <option>5 <option>4 <option>3 <option>2 <option>1 </select></td> </tr> <tr> <td>Your comments:</td> </tr> <tr><td><textarea rows="10" cols="65" name="comments"></textarea></td> </tr> <tr> <td><input type=image src="img/sub.jpg" value="Sign it!">&nbsp;<input +type=image src="img/era.jpg" value="Erase"></td> </tr> </table>); create_footer(); print qq( </body> </html> ); } sub show_book_entries { open (FILE, "$data_file") || die "Can't open file:$!"; my @arr = <FILE>; if (@arr eq '') { print qq~(No entries)~; } else { foreach my $stuff (@arr){ print "$stuff", $q->br, } } } close(FILE); if ($action eq 'sign') { print_form; } } sub dienice { my($msg) = @_; create_header("Error"); print qq( <h2>Error</h2>\n ); print qq( $msg\n ); create_footer(); exit; } sub create_footer { print qq(<br><a href="../../main.shtml">[back to the main page]</a +><br><small><small><i>&copy; Copyright 2003 DreamScape Designs. All +rights reserved. URL: <a href="http://dreamscapedesigns.cjb.net">http +://dreamscapedesigns.cjb.net</a> </small</small></i>); print $q->end_html; } my $has_header = 0; sub create_header { my ($page_title) = @_; if ($has_header == 0) { print $q->header; print $q->start_html( -title=>$page_title ); $has_header = 1; } } sub write_to_file { #uncomment this line and the line below that read flock (BOOK, LOCK_EX +) or dienice("Can't get an exclusive lock on $dataFile: $!"); #see read me for details. #use Fcntl qw{ :flock }; #I opted to use the "?:" conditional operator instead of the tradition +al #if (...){} else {...} statement. #Saved alot of time and code, especially after I've written once befor +e! #This code segment provided graciously by Chas at webhostingtalk.com open BOOK, "<$data_file" or dienice("Could read open $data_file. R +eason: $!"); #flock (BOOK, LOCK_EX) or dienice("Can't get an exclusive lock o +n $dataFile: $!"); read (BOOK, my $book, -s BOOK); close BOOK; open BOOK, ">$data_file" or dienice("Could write open $data_file. +Reason: $!"); # flock (BOOK, LOCK_EX) or dienice("Can't get an exclusive lock o +n $dataFile: $!"); print BOOK "<!--START:-->\n"; print BOOK "<table width=500 border=0 cellpadding=5 cellspacing=0 +>"; print BOOK "<tr>"; print BOOK "<td>"; print BOOK "Signed on:&nbsp;$EntryDate"; print BOOK "</td>"; print BOOK "</tr>"; print BOOK "<tr>"; print BOOK "<td>"; print BOOK "Name:" . $q->param('name') ; print BOOK "</td>"; print BOOK "</tr>"; print BOOK "<tr>"; print BOOK "<td>"; my $m = $q->param('email') ? print BOOK "Email:&nbsp; <a href='mai +lto:'".$q->param('email').">".$q->param('email')."</a></td></tr>" : p +rint BOOK "Email:&nbsp; (No email given)</td></tr>"; print BOOK "<tr>"; print BOOK "<td>"; print BOOK "Country:" . $q->param('country') . "</td>"; print BOOK "<tr>"; print BOOK "<td>"; my $n = $q->param('state') ? print BOOK "State/Province/Territory: +&nbsp;" . $q->param('state') . "</td>" : print BOOK "City:&nbsp;(No c +ity provided)</td>"; print BOOK "</tr>"; print BOOK "<tr>"; print BOOK "<td>"; my $o = $q->param('city') ? print BOOK "City:&nbsp;" . $q->param(' +city') . "</td>" : print BOOK "City:&nbsp;(No city provided)</td>\n"; print BOOK "</tr>"; print BOOK "<tr>"; print BOOK "<td>"; print BOOK "Site rating:&nbsp;" . $q->param('rate') . "</td>"; print BOOK "</tr>"; print BOOK "<tr>"; print BOOK "<td>"; print BOOK "Comments:<br>"; print BOOK $q->param('comments'); print BOOK "</tr>"; print BOOK "<tr>"; print BOOK "<td>"; print BOOK "</table>\n\n"; print BOOK "<!--END:-->"; print BOOK $book; } close(BOOK); print_thanks() if ($t eq 'sign_success'); sub print_thanks { print qq( <html> <head> <title>Thanks!</title> <link rel="stylesheet" type="text/css" href="css/book.css"> </head> <body background="$images{'bg'}"> <img src="$images{'logo'}"><hr> Thank you for signing my guestbook: <br> Here is what you entered:<br><br>); print "Name:" . $q->param('name') . "<br>\n"; my $mo = $q->param('email') ? print "Email:" . $q->param('email'). +"<br>\n" : print "Email:&nbsp; (No email given)<br>\n"; print "Country:" . $q->param('country') . "<br>\n"; my $no = $q->param('state') ? print "State/Province/Territory:&nb +sp;" . $q->param('state') . "<br>\n" : print "Country:&nbsp;(No coun +try provided)"; my $oo = $q->param('city') ? print "Citry:&nbsp;" . $q->param('cit +y') . "<br>\n" : print "City:&nbsp;(No city provided)"; print "Site rating:&nbsp;" . $q->param('rate') . "<br>\n"; print "Comments:<br>\n"; print $q->param('comments') . "<br>\n"; print qq( <br><br> <a href="$urls{'cgi_url'}?action=view_entry">View your entry</a>); create_footer(); print qq( </body> </html>); }
My last question, is there any way to change the MIME types on a remote server like jcwren's? I'm not totally familiar with Linux or most server stuff, so if someone could help me out that would be great.

Replies are listed 'Best First'.
Re: Linux server doesn't like me
by gmpassos (Priest) on Apr 24, 2003 at 04:33 UTC
    First, use the tag <readmore> for big nodes. Is better if you make a introducion text for your node, and put the readmore after it.

    Your error, that exist in most print that you make, is the qq(...), that uses () for quotes, but you use the () inside the text to be printed too. Use something like that for big print:

    print qq` <html> ... </html> ` ; ## or print <<HTMLDATA; <html> ... </html> HTMLDATA exit ;

    End you forgot some } to close some sub too! Before send the script to server make a check syntax:

    perl -c script.pl

    If you use Windows, get Perl from ActiveState.com

    Graciliano M. P.
    "The creativity is the expression of the liberty".

Re: Linux server doesn't like me
by graff (Chancellor) on Apr 24, 2003 at 04:39 UTC
    I don't think the server feels one way or another about you, but I could understand if perl gets a bit huffy about your code...

    I would guess that this is line 176 (or pretty close to it):

    </html>);
    Now, if you have an editor that knows how to find matching bracket-like characters, you'd find that this close paren at the end of your tag does not have a corresponding open paren anywhere above it.

    If you look at (or near) line 105, you'll find:

    sub print_main { print qq( ## line 105 (I think)
    and looking forward from that point for the matching close paren leads me to line 116 (I think), which shows:
    Guestbook entries:);
    That's where the trouble starts. I haven't looked in detail at all the rest of what you're doing here, but my initial (uninformed) impression is that it's probably a lot bulkier and more complicated-looking than it needs to be... e.g. you don't seem to be using CGI.pm's capabilities to their best advantage (perhaps others will comment in more detail on that).

    update: On closer inspection, the problems with open and close parens is more widespread (and line 116 was not the real start of the trouble). The earlier response about changing your habits with "qq" is certainly on the mark, but apart from that, you really need to use an editor that can help you to check for unbalanced parens and other kinds of brackets. (I use "Control-Meta-F" and "Control-Meta-B" in emacs -- the former, if applied when the cursor is on an open bracket, will try to jump to the matching close bracket, or ring the terminal bell if there is no close bracket; likewise for the latter, looking backwards from a close-bracket character.)

Re: Linux server doesn't like me
by submersible_toaster (Chaplain) on Apr 24, 2003 at 06:01 UTC

    In addition to the syntactic advice alread posted, you might find it useful to print $q->header() before printing your quoted document - Even if the HTML is valid, you will need the script to generate a header. May I also recommend HTML::Template.
    I can't believe it's not psellchecked

      Yeah, I think it is a bit bulky. I just found it easier to use the qq blocks. I'll make those modifications and check it out. Thanks alot guys, I know how hard that code can be to read.