Forum Moderators: coopster & phranque

Message Too Old, No Replies

Executing script - read/write to text

Read/Write to text file

         

Zath

4:38 pm on Oct 3, 2005 (gmt 0)

10+ Year Member



I am very new to perl scripting. My expertise is in .Net and some other languages. Have done some linux shell scripting, so, reading it is no problem.

I have this .pl script file that a flash (actionscript) file should read and write to. It isn't even reading the file. Just a game.

I am trying to trace down if the .pl file is even executing. I know it's being callsed because if I change the url of the file (purposely), I get an error.

First, is there a way to adjust the .pl file below so I can get a print to an html page?

And, does anyone see anything wrong with the script?

Also, I have set the permissions correctly....

Thanks everyone!

Zath


#!/usr/bin/perl

$hsfile = "invadersscores.txt";
# CHMOD this to 666 and this perl script to 755 - DONE

print "Cache-Control: max-age=0, must-revalidate\n";
print "Expires: Sun, 31 Oct 2006 12:00:00 GMT\n";
print "Content-Type: text/plain\n\n";

# Read input from POST http header into buffer
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
$len = length($buffer);

if ($len > 12) {
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($nm, $val) = split(/=/, $pair);
$NEWDATA{$nm} = $val;
}

open (FILE,"<$hsfile");
flock (FILE,2);
$line = <FILE>;

$count = 0;
$newline = "";
$ranked = 0;
@pairs = split(/&/, $line);
foreach $pair (@pairs) {
if ($count < 101) {
($nm, $val) = split(/=/, $pair);
if (substr($nm,0,4) eq "name") {
$newline .= "name$count=$val&";
}
else {
if ($ranked == 0 && $NEWDATA{'score'} > $val && $NEWDATA{'name'} ne "") {
$count++;
$newline .= "score$count=$NEWDATA{'score'}&name$count=$NEWDATA{'name'}&";
$ranked = 1;
}

$count++;
$newline .= "score$count=$val&";
}
}
}
print $newline;
close (FILE);

$lennew = length($newline);
if ($lennew > 12) {
open (FILE,">$hsfile");
flock (FILE,2);
print FILE "$newline";
close (FILE);
}
}
else {
open (FILE,"<$hsfile");
flock (FILE,2);
$line = <FILE>;
print "$line";
close (FILE);
}

Zath

7:42 pm on Oct 3, 2005 (gmt 0)

10+ Year Member



Update:

The path to the perl interpreter is

c:\perl\bin\

And, my cgi-bin folder seems to be on D:\somename\somenumber\

I've been trying to adjust the first line of the script to reflect this, but with no luck.

Any help?

Thanks,

rocknbil

11:35 pm on Oct 3, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Here's some assistance that will be most valuable. Paste this in your script, anywhere (bottom is good:)

sub error {
my ($error);
$error = shift(@_);
print "content-type: text/html\n\n";
print "An error has ocurred: $error\n";
exit 0;
}

Now alter your read-in line like so. Substitute the broken pipes for a solid pipe or use the word "or":

open (FILE,"<$hsfile") ¦¦ &error("Cannot open file $hsfile: $!");
flock (FILE,2);
$line = <FILE>;

with the or:

open (FILE,"<$hsfile") or &error("Cannot open file $hsfile: $!");
flock (FILE,2);
$line = <FILE>;

Do not remove the $!. That is a special variable that holds system error messages, if one gets fed back to your script. So some typical responses:

Cannot open file invadersscores.txt: permission denied
Cannot open file invadersscores.txt: no such file or directory

The next question will be why. Lots of reasons, a common one is that some systems need the FULL PATH to a file even if the file is in the same directory as your script, as in

$hsfile = '/path/from/root/to/yoursite.com/invadersscores.txt';

Use that error routine like so, it will help you out in many situations:

&doAnyFunction or &error('Cannot do any function');
if (! $logged_in) { &error('Not Logged In'); }

EDIT: Just saw this

And, my cgi-bin folder seems to be on D:\somename\somenumber\

The presence of backslashes tells me you are (probably?) on a Windblows server. It's a little more tricky with windows, you can't set your own permissions. You'll have to insure that the file you want to write to is in a writable directory, that the file itself is writable (that's the chmod 777, for Linux) and it's most likely you'll have to have the system admin set that for you.

Zath

12:28 am on Oct 4, 2005 (gmt 0)

10+ Year Member



Thanks so much for your reply. Haven't done any scripting like this in years.

But, I tried your suggestions, but with no luck.

The permissions are ok though. rwxrwxrwx.

I even purposely tried to change the name of the file in the script to throw an error, and it didn't. Did not print anything to the page when I opened the .pl file in the browser.

Is it possible it is not even getting to the perl.exe?

Here is the updated script with your suggestions.

Thanks,

Zath....

#!c:\perl\bin\perl.exe

# $hsfile = "http://www.example.com/cgi-bin/invadersscores.txt";
# $hsfile = "D:/INETPUB/023/cgi-bin/invadersscores.txt";
$hsfile = "invadersscores.txt";
# CHMOD this to 666 and this perl script to 755

print "Cache-Control: max-age=0, must-revalidate\n";
print "Expires: Sun, 31 Oct 2006 12:00:00 GMT\n";
print "Content-Type: text/plain\n\n";

# Read input from POST http header into buffer
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
$len = length($buffer);

if ($len > 12) {
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($nm, $val) = split(/=/, $pair);
$NEWDATA{$nm} = $val;
}

open (FILE,"<$hsfile") ¦¦ &error("Cannot open file $hsfile: $!");
flock (FILE,2);
$line = <FILE>;

$count = 0;
$newline = "";
$ranked = 0;
@pairs = split(/&/, $line);
foreach $pair (@pairs) {
if ($count < 101) {
($nm, $val) = split(/=/, $pair);
if (substr($nm,0,4) eq "name") {
$newline .= "name$count=$val&";
}
else {
if ($ranked == 0 && $NEWDATA{'score'} > $val && $NEWDATA{'name'} ne "") {
$count++;
$newline .= "score$count=$NEWDATA{'score'}&name$count=$NEWDATA{'name'}&";
$ranked = 1;
}

$count++;
$newline .= "score$count=$val&";
}
}
}
print $newline;
close (FILE);

$lennew = length($newline);
if ($lennew > 12) {
open (FILE,">$hsfile");
flock (FILE,2);
print FILE "$newline";
close (FILE);
}
}
else {
open (FILE,"<$hsfile");
flock (FILE,2);
$line = <FILE>;
print "$line";
close (FILE);
}

sub error {
my ($error);
$error = shift(@_);
print "content-type: text/html\n\n";
print "An error has ocurred: $error\n";
exit 0;
}

[edited by: coopster at 12:49 am (utc) on Oct. 4, 2005]
[edit reason] generalized ulr per TOS [webmasterworld.com] [/edit]

Zath

2:35 am on Oct 4, 2005 (gmt 0)

10+ Year Member



Sorry about the url coopster. I read about that and forgot.

Ok, I have an idea here and been searching around for a sample, so, if someone can help me out.

A simple script to open an html file I can make. Read the file, and print it out to the page via a perl script.

That way, it's very simple and I can see if I am actually accessing the perl.exe on my hosting server.

Thanks,

Zath

KevinADC

3:26 am on Oct 4, 2005 (gmt 0)

10+ Year Member



flock() is not supported on windows and might be causing the script to abort.

flock (FILE,2);

remove the flock functions and try again

KevinADC

3:38 am on Oct 4, 2005 (gmt 0)

10+ Year Member



just try a simple hello world script to see if your script is getting executed by perl:

#!c:/perl/bin/perl.exe
print "Content-Type: text/plain\n\n";
print "Hello world!";

Zath

1:55 pm on Oct 4, 2005 (gmt 0)

10+ Year Member



The simple hello world script works, even without the very first line accessin the perl.exe.

With running the script directly, and not accessing it via the flash app, only this part is being executed, as I can see (due to no info being passed into script)

else {
open (FILE,"<$hsfile");
flock (FILE,2);
$line = <FILE>;
print "$line";
close (FILE);
}

I put in an extra print:

print "7 test";

And put this line in many places, only other place it printed was right before:

print "1 test";
# Read input.......

So, I am assuming that it is not opening the file and printing it.

No errors either and even tried to comment out the flock.

And the server is running windows 2000 or 2003.

So, any more suggestions? This is starting to drive me crazy :D

Zath

KevinADC

4:35 pm on Oct 4, 2005 (gmt 0)

10+ Year Member



comment out flock() and keep commented out. flock() is not supported on windows. Try this, you have:

open (FILE,"<$hsfile");

change to this:

open (FILE,"<$hsfile") or die "Can't open $hsfile: $!";

also check your server error log and see if there is any indication of the problem in the log.

Zath

6:05 pm on Oct 4, 2005 (gmt 0)

10+ Year Member



I tried what you suggested and still no luck.

But it did not print out the test string I put in there earlier this time, so, it died?

It still seems it won't open a file.

Also, no errors in the log. Just logged access.

Zath

KevinADC

9:52 pm on Oct 4, 2005 (gmt 0)

10+ Year Member



try a bare-bones script, no if/else conditions. Just write a script that opens a file and writes to a file and see if it runs OK. If it does, then there is probably a flaw in the flow/logic of your script somewhere.

Zath

1:53 pm on Oct 5, 2005 (gmt 0)

10+ Year Member



Yes, did a simple script....

#!c:/perl/bin/perl.exe

$stuff="D:/folder/folder/cgi-bin/invadersscores.txt";

print "Cache-Control: max-age=0, must-revalidate\n";
print "Expires: Tue, 31 Oct 2006 12:00:00 GMT\n";
print "Content-Type: text/plain\n\n";

open STUFF, $stuff or die "Cannot open $stuff for read :$!";

while (<STUFF>) {
print "Line $. is : $_";

It actually read the file and printed it!

So, now I know I have the perl.exe path right, and the path to the file right!

But, changed those in the original script and no luck. Won't print or won't work for the flash app accessing it.

And, I am very new to perl scripting. I program in .Net (C++, C#, VB, javascript, to name a few)

So, if anyone can see the problem with the script itself, any help is appreciated.

Here is the script as it is so far....

#!c:/perl/bin/perl.exe

$hsfile = "D:/INETPUB/023/cgi-bin/invadersscores.txt";

# CHMOD this to 666 and this perl script to 755

print "Cache-Control: max-age=0, must-revalidate\n";
print "Expires: Tue, 31 Oct 2006 12:00:00 GMT\n";
print "Content-Type: text/plain\n\n";

# Read input from POST http header into buffer
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
$len = length($buffer);

if ($len > 12) {
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($nm, $val) = split(/=/, $pair);
$NEWDATA{$nm} = $val;

}

open (FILE,"<$hsfile") ¦¦ &error("Cannot open file $hsfile: $!");
#flock (FILE,2);
$line = <FILE>;

$count = 0;
$newline = "";
$ranked = 0;
@pairs = split(/&/, $line);
foreach $pair (@pairs) {
if ($count < 101) {
($nm, $val) = split(/=/, $pair);
if (substr($nm,0,4) eq "name") {
$newline .= "name$count=$val&";

}
else {
if ($ranked == 0 && $NEWDATA{'score'} > $val && $NEWDATA{'name'} ne "") {
$count++;
$newline .= "score$count=$NEWDATA{'score'}&name$count=$NEWDATA{'name'}&";
$ranked = 1;

}

$count++;
$newline .= "score$count=$val&";

}
}
}
print $newline;
close (FILE);

$lennew = length($newline);
if ($lennew > 12) {
open (FILE,">$hsfile");
#flock (FILE,2);
print FILE "$newline";
close (FILE);

}
}
else {
open (FILE,"<$hsfile") or die "Can't open $hsfile: $!";
#open (FILE,"<$hsfile");
#flock (FILE,2);
$line = <FILE>;
print "$line";
close (FILE);

}

sub error {
my ($error);
$error = shift(@_);
print "content-type: text/html\n\n";
print "An error has ocurred: $error\n";
exit 0;

}

Zath

4:11 pm on Oct 5, 2005 (gmt 0)

10+ Year Member



BTW, the windows server is using ActiveState PERL 5.6.1.629

JollyK

9:56 pm on Oct 5, 2005 (gmt 0)

10+ Year Member



Zath, silly question, but is your form using the GET or POST method? Looks to me as though your script only supports POST so it will lose all data sent through GET.

Nowadays, most people would use CGI.pm to parse the form data instead of parsing it manually. (It should have come bundled with ActiveState Perl.) Something like:

use CGI;
my $formdata = new CGI;
my(%NEWDATA);
foreach my $nm ($formdata->param()){
$NEWDATA{$nm} = $formdata->param($nm);
}

instead of

# Read input from POST http header into buffer
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
$len = length($buffer);

if ($len > 12) {
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($nm, $val) = split(/=/, $pair);
$NEWDATA{$nm} = $val;

}

will get both GET and POST data.

It's also got that "if ($len > 12)" thing going on, so that if the length of whatever it's testing is less than 12 characters, stuff won't happen. Is it possible your data is too short?

You've probably already thought of this, but just in case ... :-)

[edit]

Oh, and is the first line of the file blank? If so, that may be part of the problem. In order for it not to stop reading after the first line, you really need to do

while (<FILE>){
(do all your stuff with $line here for each line)
}

If you just do $line = <FILE> you'll get just the first line unless you've undefined the input record separator which I don't think you want to do (that would read the entire file into $line as one long string whereas the "while" loop will look at one line at a time.

JK

KevinADC

12:16 am on Oct 6, 2005 (gmt 0)

10+ Year Member



post some sample lines from the file $hsfile. Also, this reads only the first line of the file:

$line = <FILE>;

if it's just one line then no problem, but if it's more than one line....

KevinADC

12:32 am on Oct 6, 2005 (gmt 0)

10+ Year Member



I would do it a bit different but I agree in principal (and in practice for the most part) with JollyK. Use the CGI module to get your form data.