A Conversation for The H2G2 Programmers' Corner

Perl Problem

Post 1

Researcher 209018

Hi all, First time here.
A good friend advised me to place my query in here for advice.
Here's hoping......

I'm trying to set up a chat room on a site using a perl script I found on the web.

The basic tutorial ( which I can no longer find on the web )said to include the file chat html in the main directory:



WebChat





Welcome to the
Chat Forum
Enter the Chat Forum
to leave a message for your friends, comment on this Web site, ask
a question about a problem you have and so on. It's entirely up
to you what you say, but please keep it clean, honest and truthfull.
Any bad language and the chat file will be cleared out, losing all
the messages.
Once you're inside you can click
the Go button to refresh the page.








 
 


Okay, so basic html.

Then there is a chat.pl file (that this refers to-and the redirection does work-no problem there!) that was to be put in the cgi bin along with two text files chathead.txt and chatfoot.txt , respectively:

chat.pl:

#!/usr/local/bin/perl

# This is a web chat facility. The chat file is created automatically
# and is inserted between CHATHEAD.TXT and CHATFOOT.TXT - the top and
# bottom half of a Web page. Messages are added using the form in
# chatfoot.txt. When the file is too big, earlier messages are
# removed (set $maxlines). Requires Steve Brenner's cgi-lib.pl


# Use cgi-lib.pl to put the form data into an array
push (@INC,"/cgi-bin/");
require("cgi-lib.cgi");
&ReadParse;

$mypath = $ENV{PATH_TRANSLATED}; # Path to my folder *** CHECK THIS IS OK ***
chop($mypath);
chop($mypath); # chop off the .pl from script filename
chop($mypath);

$header = $mypath . "head.txt"; # The top of the HTML page
$footer = $mypath . "foot.txt"; # The bottom of the HTML page
$maxlines = 100; # Num of lines allowed in the chat file

$chatfile = $mypath . ".txt";
$filelock = $mypath . ".lok"; # Used as a simple flag to show file is in use

# Check that someone else isn't already accessing the files we need
$i=0;
while ((-e "$filelock") && $i<30) {
sleep(1); # Wait up to 30 seconds if file is in use
$i++;
} # If there's a problem filelock may not be deleted last time
if ($i < 30 ) {
open(LOCK,">$filelock"); # Create a 0-bytes length file as a flag
close(LOCK);

}

# ----------------------------------------------------------------------------
# Get the date and time
# ----------------------------------------------------------------------------
@days = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
@months = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
if ($hour < 10) { $hour = "0$hour"; }
if ($min < 10) { $min = "0$min"; }
if ($sec < 10) { $sec = "0$sec"; }
$longdate = "$days[$wday], $months[$mon] $mday, 19$year at $hour\:$min\:$sec";
$shortdate = "$months[$mon] $mday $hour\:$min";

# If name and comments are both filled in then add comments to webchat file
if ( ($in{'name'} ne "") && ($in{'comments'} ne "") ) {
$in{'name'} =~ s/</&lt;/g; # remove HTML codes
$in{'name'} =~ s/>/&gt;/g; # remove HTML codes
$in{'comments'} =~ s/</&lt;/g; # remove HTML codes
$in{'comments'} =~ s/>/&gt;/g; # remove HTML codes
$in{'comments'} =~ s/\r\n//g; # remove double returns
$in{'comments'} =~ s/\n\r//g; # remove double returns
$in{'comments'} =~ s///g; # remove double returns
$in{'comments'} =~ s///g; # remove double returns
$in{'comments'} =~ s///g; # remove double returns
open(FILE,">>$chatfile"); # Add new comments to the end
print FILE "<!-- CHAT -->\n"; # put in the marker
$font = "+0";
if ($in{'size'} eq "Small") {
$font = "-1";
}
if ($in{'size'} eq "Big") {
$font = "+2";
}
$colour = "000000";
if ($in{'colour'} eq "Red") {
$colour = "FF0000";
}
if ($in{'colour'} eq "Blue") {
$colour = "0000FF";
}
if ($in{'colour'} eq "Green") {
$colour = "00FF00";
}
if ($in{'colour'} eq "Yellow") {
$colour = "FFFF00";
}
print FILE "\n";
print FILE "From: $in{'name'} ($shortdate)...........To: $in{'to'}\n";
print FILE "$in{'comments'}\n";
close(FILE);
}

# Read the header file into an array
open(FILE,$header);
@header = ;
close(FILE);

# Read the webchat file into chat array
open(FILE,"$chatfile");
@chat = ;
close(FILE);

# Read the footer file into an array
open(FILE,$footer);
@footer = ;
close(FILE);

# Print the webchat HTML page
print "Content-type: text/html\n\n";
print "@header\n";
print "@chat\n";
print "@footer\n";

# See how many messages there are and prune the first one if necessary
$i = @chat; # number of lines of chat
if ( $i > $maxlines ) {
open(FILE,">$chatfile"); # re-write the chat file minus the first message
$flag = 0;
for $line (@chat) {
if ( $line eq "<!-- CHAT -->\n" ) {
++$flag;
}
if ( $flag>1 ) {
print FILE "$line";
}
}
close(FILE);
}

unlink("$filelock"); # Remove the file lock flag
exit;



Chathead.txt:





Web Chat





Web Chat Forum



Welcome
to the Web Chat page. The most recent messages are at the bottom
so scroll down the page. Enter your name and message in the form
at the bottom and click the Go button to add it to this page.
Clicking Go without entering a message updates the page by retrieving
the latest messages.








Chatfoot.txt:






&nbsp;



Add your own message!Fill in the boxes below with your name and message - keep it short


From: Colour: Black Red Blue
Green Yellow Size: Small Normal Big
To: Message: (Click with no message to update page)











The only other addition was the inclusion of Steve Brenner's cgi-lib.pl which I uploaded to the cgi bin as well.
cgi-lib.pl:


#!/usr/local/bin/perl

# Perl Routines to Manipulate CGI input
#
# Copyright (c) 1995 Steven E. Brenner
# Permission granted to use and modify this library so long as the
# copyright above is maintained, modifications are documented, and
# credit is given for any use of the library.
#
# Thanks are due to many people for reporting bugs and suggestions
# especially Meng Weng Wong, Maki Watanabe, Bo Frese Rasmussen,
# Andrew Dalke, Mark-Jason Dominus, Dave Dittrich, Jason Mathews
#
# For more information, see:
# http://cgi-lib.berkeley.edu/
#


# Minimalist http form and script (http://www.bio.cam.ac.uk/web/minimal.cgi):
#
# require "cgi-lib.pl";
# if (&ReadParse(*input)) {
# print &PrintHeader, &PrintVariables(%input);
# } else {
# print &PrintHeader,' Data: ';
#}

# ReadParse
# Reads in GET or POST data, converts it to unescaped text,
# creates key/value pairs in %in, using '\0' to separate multiple
# selections

# Returns TRUE if there was input, FALSE if there was no input
# UNDEF may be used in the future to indicate some failure.

# Now that cgi scripts can be put in the normal file space, it is useful
# to combine both the form and the script in one place. If no parameters
# are given (i.e., ReadParse returns FALSE), then a form could be output.

# If a variable-glob parameter (e.g., *cgi_input) is passed to ReadParse,
# information is stored there, rather than in $in, @in, and %in.

sub ReadParse {
local (*in) = @_ if @_;
local ($i, $key, $val);

# Read in text
if (&MethGet) {
$in = $ENV{'QUERY_STRING'};
} elsif (&MethPost) {
read(STDIN,$in,$ENV{'CONTENT_LENGTH'});
}

@in = split(/[&;]/,$in);

foreach $i (0 .. $#in) {
# Convert plus's to spaces
$in[$i] =~ s/\+/ /g;

# Split into key and value.
($key, $val) = split(/=/,$in[$i],2); # splits on the first =.

# Convert %XX from hex numbers to alphanumeric
$key =~ s/%(..)/pack("c",hex($1))/ge;
$val =~ s/%(..)/pack("c",hex($1))/ge;

# Associate key and value
$in{$key} .= "\0" if (defined($in{$key})); # \0 is the multiple separator
$in{$key} .= $val;

}

return scalar(@in);
}


# PrintHeader
# Returns the magic line which tells WWW that we're an HTML document

sub PrintHeader {
return "Content-type: text/html\n\n";
}


# HtmlTop
# Returns the of a document and the beginning of the body
# with the title and a body header as specified by the parameter

sub HtmlTop
{
local ($title) = @_;

return <<END_OF_TEXT;


$title


$title
END_OF_TEXT
}

# Html Bot
# Returns the , codes for the bottom of every HTML page

sub HtmlBot
{
return "\n\n";
}


# MethGet
# Return true if this cgi call was using the GET request, false otherwise

sub MethGet {
return ($ENV{'REQUEST_METHOD'} eq "GET");
}


# MethPost
# Return true if this cgi call was using the POST request, false otherwise

sub MethPost {
return ($ENV{'REQUEST_METHOD'} eq "POST");
}


# MyURL
# Returns a URL to the script

sub MyURL {
local ($port);
$port = ":" . $ENV{'SERVER_PORT'} if $ENV{'SERVER_PORT'} != 80;
return 'http://' . $ENV{'SERVER_NAME'} . $port . $ENV{'SCRIPT_NAME'};
}


# CgiError
# Prints out an error message which which containes appropriate headers,
# markup, etcetera.
# Parameters:
# If no parameters, gives a generic error message
# Otherwise, the first parameter will be the title and the rest will
# be given as different paragraphs of the body

sub CgiError {
local (@msg) = @_;
local ($i,$name);

if (!@msg) {
$name = &MyURL;
@msg = ("Error: script $name encountered fatal error");
};

print &PrintHeader;
print "$msg[0]\n";
print "$msg[0]\n";
foreach $i (1 .. $#msg) {
print "$msg[$i]\n";
}
print "\n";
}


# CgiDie
# Identical to CgiError, but also quits with the passed error message.

sub CgiDie {
local (@msg) = @_;
&CgiError (@msg);
die @msg;
}


# PrintVariables
# Nicely formats variables in an associative array passed as a parameter
# And returns the HTML string.
sub PrintVariables {
local (%in) = @_;
local ($old, $out, $output);
$old = $*; $* =1;
$output .= "\n\n";
foreach $key (sort keys(%in)) {
foreach (split("\0", $in{$key})) {
($out = $_) =~ s/\n/\n/g;
$output .= "$key\n $out\n";
}
}
$output .= "\n";
$* = $old;

return $output;
}

# PrintVariablesShort
# Now obsolete; just calls PrintVariables

sub PrintVariablesShort {
return &PrintVariables(@_);
}

1; #return true




OK, so this is a lot of stuff, but I'll admit I am fairly novice at this but I need to get this finished asap. I know enough abot html and some javascript to change the look, feel and content of the finished thing but I just can't get it to work!!!!


I have tried to get help from the server, but although they were initially helpful, they are now just being difficult (I don't have the option to change).

Initially I had binary characters in some of the code, which has since been sorted, and then there was an error message when I checked via telnet saying:

Can't locate cgi-lib.pl in @INC (@INC contains:
> /usr/local/lib/perl5/5.6.1/i86pc-solaris /usr/local/lib/perl5/5.6.1
> /usr/local/lib/perl5/site_perl/5.6.1/i86pc-solaris
> /usr/local/lib/perl5/site_perl/5.6.1 /usr/local/lib/perl5/site_perl .
> /cgi-bin/) at chat.pl line 12.


If I'm not being stupid this should have worked.


So I used chmod to change them all to 777, and now I'm getting an error via the browser of:


Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator, [email protected] and inform them of the time the error occurred, and anything you might have done that may have caused the error.

More information about this error may be available in the server error log.


And when I use the telnet program to check the chat.pl file by typing:

perl chat.pl (enter)

I get:

Content-type: text/html


???????????????????????

I am really confused. I have some basic programming knowledge, but am finding myself a bit out of depth here, however if I can get some help to get this running, I'd like to go further into this kind of stuff.

Sorry it's so long, and many thanks in advance for any comments/pointers/help.

Thanks.


Perl Problem

Post 2

Tango

Have you tried making a very simple Hello World style perl script just to test the server is processing the perl correctly?

Tango


Perl Problem

Post 3

Ion the Naysayer

Perl is working - the error message you've gotten is a message generated by the Perl compiler.

The problem is that the script isn't finding cgi-lib.pl. The script is looking for the file in /cgi-bin/ which is off the root and probably NOT where you want it to be looking.

Change the line

require("cgi-lib.cgi");

to

require("/cgi-lib.cgi");

where is the full local path to the cgi-lib file. Also, check the extension on cgi-lib because the require is .cgi and the error is .pl.


Perl Problem

Post 4

Researcher 209018

But should I need to change the path if both the chat.pl and the chat-lib.pl(sorry -my mistake!) are both in the same directory - the cgi bin itself?
And if I do will it be just to

require("/cgi-bin/cgi-lib.pl");

or when you say full path, how far back do I have to include?
You see, I expected that, with them both existing already in the same directory, the line would only have to read

require("cgi-lib.pl");

as it would only need an extended path if it was looking beyond the directory it sat in itself?


Perl Problem

Post 5

Researcher 209018

Ooopss!
Listen, this is my first on hand experience with the differences between windows and unix - would the path possibly have to be of the kind /usr/local/bin/cgi-lib ?


Perl Problem

Post 6

Ion the Naysayer

*grin* No problem.

Unix stores everything off of the root directory rather than by drive. So instead of c:\, you have /.

That's exactly the sort of path it will be. To find the full path, go to the directory where you've placed the file you're "require"ing and type "pwd". This will give you the current path name which you can then put in the require statement.

Keep in mind this is a bit of a no-no as far as designing a good script goes. It's a quick fix, that's all. If you get more into writing your own scripts, don't write code like this.

Q: What happens if you move the file? A: You have to change every occurance in every script you've written. See what I mean?


Perl Problem

Post 7

Ion the Naysayer

As a side note,

require("/cgi-bin/cgi-lib.pl");

in Unix is equivalent to writing

require("c:/cgi-bin/cgi-lib.pl");

in Windows (using / instead of \ only because Perl uses Unix style directory delimiters).


Perl Problem

Post 8

Researcher 209018

Thanks very much for the advice Ion, unfortunately, I'm still getting the same error in the browser, however telnet seems to be telling me there is no longer a problem finding the file?


Perl Problem

Post 9

DoctorMO (Keeper of the Computer, Guru, Community Artist)

*wades in* I should have no problem here. smiley - smiley

btw, it's windows that only has a back slash (\) for it's directory deliminators, EVERY other OS has forward slashes (/). who knows, it's like the stupid carage return line feed promlems you get if you try and upload your scripts that have been developed in windows to a unix server. anyway...

develop in linux if you can, run an apache web server, even if you don't have a network you can still look at pages though the localhost. it's the best thing I ever did, learning perl.

now I'm developing a whole e-comerce site smiley - winkeye.

hmm, I mubling a bit.

so is there any chanch you could just stick the script in your cgi-bin? I usualy stick my libaries (pl and pm files) in a ./lib/ folder off the cgi-bin, but it's just prefrance and you have to know how to change the permitions,

-- DoctorMO --


Perl Problem

Post 10

Researcher 209018

Sorry! - but I'm still having no luck - any more suggestions?


Perl Problem

Post 11

Ion the Naysayer

Ask the webmaster for the relevant sections of the error logs. I would need the error message from those logs to figure out why it's not working in the browser.


Perl Problem

Post 12

DoctorMO (Keeper of the Computer, Guru, Community Artist)

I have a bit of code that may help...

put this at the top of your script.

BEGIN {
open (STDERR, ">error.txt");
}

you will beable to view any errors that the script causes.

-- DoctorMO --


Key: Complain about this post