9 Replies - 4757 Views - Last Post: 17 October 2009 - 04:46 PM

#1 blitzfx  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 16-August 09

perl & cgi - cannot write to a file

Posted 12 October 2009 - 06:44 AM

Hi guys,

I've got a cgi script written in perl and I'm attempting to write data to a file but it isn't working

#!/usr/bin/perl -w

&print_HTTP_header;
&print_head;
&print_body;
&print_tail;

sub print_HTTP_header
{
	print "Content-type: text/html\n\n";
}

#  ---- print HTML stuff at head
sub print_head
{
	print <<END;
	<HTML><HEAD>
	<TITLE>test script</TITLE>
	<BODY bgcolor="#ffffff" text="#000000">
	<H4>test script</H4>
END
}

sub print_body
{
	use IO::File;
	use Fcntl ":flock";
	
	open (MYFILE, ">>../data.txt"); 
	flock MYFILE, LOCK_SH;
	print MYFILE "Matthias\nLucius\nKadmiel\nAradiel\nEzekiel\nOctavius\n";
	close (MYFILE); 

	open (INPUT, "<../data.txt");
	$variable = <INPUT>;
	while(<INPUT>)
	{
		print $_;
	}
}

sub print_tail
{
	print "<BR><BR>";
	print "</BODY></HTML>";
}




Basically I've got this script on my university server running unix, under my account. I've verified the perl address is correct as well.
It's located under the cgi-bin folder and all I need to do is just call http://WWW.....cgi-bin/test/write.cgi (is the name of the file) and it should keep appending the names into a file and then display the result.
I've uploaded an empty data.txt file one level up from the test folder (ie. placed into cgi-bin).
So now when I run the script, absolutely nothing happens to the file and all i get is "test script" printed out (in H4).
I've set every single file permission to 777 (highest possible for every user) and it still doesn't work.

I went and uploaded the same files to my own server and it works fine so now I have no idea what's going on.
Not sure if my script has been written correctly or not, so some help would be most appreciated.

Is This A Good Question/Topic? 0
  • +

Replies To: perl & cgi - cannot write to a file

#2 winracer  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 141
  • Joined: 02-March 09

Re: perl & cgi - cannot write to a file

Posted 12 October 2009 - 07:47 PM

View Postblitzfx, on 12 Oct, 2009 - 05:44 AM, said:

Hi guys,

I've got a cgi script written in perl and I'm attempting to write data to a file but it isn't working

#!/usr/bin/perl -w

&print_HTTP_header;
&print_head;
&print_body;
&print_tail;

sub print_HTTP_header
{
	print "Content-type: text/html\n\n";
}

#  ---- print HTML stuff at head
sub print_head
{
	print <<END;
	<HTML><HEAD>
	<TITLE>test script</TITLE>
	<BODY bgcolor="#ffffff" text="#000000">
	<H4>test script</H4>
END
}

sub print_body
{
	use IO::File;
	use Fcntl ":flock";
	
	open (MYFILE, ">>../data.txt"); 
	flock MYFILE, LOCK_SH;
	print MYFILE "Matthias\nLucius\nKadmiel\nAradiel\nEzekiel\nOctavius\n";
	close (MYFILE); 

	open (INPUT, "<../data.txt");
	$variable = <INPUT>;
	while(<INPUT>)
	{
		print $_;
	}
}

sub print_tail
{
	print "<BR><BR>";
	print "</BODY></HTML>";
}




Basically I've got this script on my university server running unix, under my account. I've verified the perl address is correct as well.
It's located under the cgi-bin folder and all I need to do is just call http://WWW.....cgi-bin/test/write.cgi (is the name of the file) and it should keep appending the names into a file and then display the result.
I've uploaded an empty data.txt file one level up from the test folder (ie. placed into cgi-bin).
So now when I run the script, absolutely nothing happens to the file and all i get is "test script" printed out (in H4).
I've set every single file permission to 777 (highest possible for every user) and it still doesn't work.

I went and uploaded the same files to my own server and it works fine so now I have no idea what's going on.
Not sure if my script has been written correctly or not, so some help would be most appreciated.



have you tried to use the absoloute path to the file like


open (MYFILE, ">>/xxxxxxx/cgi-bin/test/data.txt"); 


This post has been edited by winracer: 12 October 2009 - 07:48 PM

Was This Post Helpful? 0
  • +
  • -

#3 blitzfx  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 16-August 09

Re: perl & cgi - cannot write to a file

Posted 12 October 2009 - 10:38 PM

just tried it and it doesn't work :(
Was This Post Helpful? 0
  • +
  • -

#4 dsherohman  Icon User is offline

  • Perl Parson
  • member icon

Reputation: 226
  • View blog
  • Posts: 654
  • Joined: 29-March 09

Re: perl & cgi - cannot write to a file

Posted 13 October 2009 - 03:58 AM

View Postblitzfx, on 12 Oct, 2009 - 01:44 PM, said:

#!/usr/bin/perl -w

&print_HTTP_header;
&print_head;
&print_body;
&print_tail;


Two side notes here:

1) You should be calling your subs with "print_HTTP_header()" rather than "&print_HTTP_header". Using an & prefix on sub calls is a holdover from Perl 4 and, in addition to no longer being necessary in Perl 5, it has side effects which are generally not what you intended.

2) Good on you for using "-w" to enable warnings, but you should also include "use strict" at the beginning of your code. Stylistically, "use warnings" is generally preferred over "-w", but, in practice, they're generally equivalent, although "use warnings" does give you finer control over what warnings are emitted and where.

View Postblitzfx, on 12 Oct, 2009 - 01:44 PM, said:

	open (MYFILE, ">>../data.txt"); 
...
	open (INPUT, "<../data.txt");


This is where you need to start looking for the cause of your problem. One or both of your opens is (presumably) failing, but you don't know which one because you're not checking to see whether they succeed and you don't know why because you're not reporting the error messages when they fail.

Also, although it's not particularly significant when you're using a static filename with no user-entered data, you should get into the habit of using the three-argument form of "open":
open(my $my_file, '>>', '../data.txt')
  or die "Unable to open file for output: $!\n";
...
open(my $input, '<', '../data.txt')
  or die "Unable to open file for input: $!\n";


The error messages from "die" will be written to the web server's error log by default. That's also where any warnings emitted by your code will be sent, so watching the error log when developing/testing web-based code is extremely valuable. If you don't have (and can't get) read-only access to the error log, you can add "use CGI::Carp qw(fatalsToBrowser);" to your code and the messages from "die" will be sent to your browser. (If this were a real application, it would be important to remove that line before going into production, so that you wouldn't end up telling attackers how to break your code.)

Note that I also used lexical filehandles ($my_file) rather than glob filehandles (MYFILE). Like "use warnings" vs. "-w", either way works as well, but the lexical filehandle is more flexible. Perhaps more importantly, by being non-global, it saves you from having to worry that you might one day start getting strange errors if you use a module which also uses a filehandle called "MYFILE" or "INPUT".
Was This Post Helpful? 0
  • +
  • -

#5 blitzfx  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 16-August 09

Re: perl & cgi - cannot write to a file

Posted 14 October 2009 - 03:43 AM

Quote

1) You should be calling your subs with "print_HTTP_header()" rather than "&print_HTTP_header". Using an & prefix on sub calls is a holdover from Perl 4 and, in addition to no longer being necessary in Perl 5, it has side effects which are generally not what you intended.

Oh dear. I've been using & to call sub routines because all the examples my lecturer are showing us have an &. Someone's being lazy and not updating his examples it seems...
I overlooked him using capitals when using <HTML> tags instead of lowercase but if there are other things in this course that aren't right...

I used strict; and it threw, mostly, errors saying Global symbol "[something]" requires explicit package name. So I chucked 'my' infront of every single variable, not knowing what it does....and still dont.

Changed how the file is opened.
open(my $my_file, '>>', '../data.txt') or errorFunction();

where errorFunction is
sub errorFunction
{
	print   header(),
		start_html(ERROR),
		"ERROR - file could not be opened <br/ > ", 
		a({-href => "http://....../index.html"}, "Click here to go to main site"),
		end_html();
}


and it's throwing an error saying "Bareword "ERROR" not allowed while "strict subs in use". I don't know how to fix this so i've disabled strict in the mean time.

one more thing:
├─Folder1
│  └─main.html
└─cgi-bin
	└─file.cgi


How do I specify the location of file.cgi from main.html ?

Thanks for the advice. I also found out the file writing issue was due to some strange permission thing due to the university server using apache and the scripts being called under a user called 'apache'.

This post has been edited by blitzfx: 14 October 2009 - 03:44 AM

Was This Post Helpful? 0
  • +
  • -

#6 dsherohman  Icon User is offline

  • Perl Parson
  • member icon

Reputation: 226
  • View blog
  • Posts: 654
  • Joined: 29-March 09

Re: perl & cgi - cannot write to a file

Posted 14 October 2009 - 06:38 AM

View Postblitzfx, on 14 Oct, 2009 - 10:43 AM, said:

Quote

1) You should be calling your subs with "print_HTTP_header()" rather than "&print_HTTP_header". Using an & prefix on sub calls is a holdover from Perl 4 and, in addition to no longer being necessary in Perl 5, it has side effects which are generally not what you intended.

Oh dear. I've been using & to call sub routines because all the examples my lecturer are showing us have an &. Someone's being lazy and not updating his examples it seems...

It's not that uncommon, unfortunately. Perl has been around for 22 years and had a lot of online tutorials published in the mid-90s when CGI and Perl were the backbone of dynamic web content. Most of those examples were sloppy and poorly-engineered at the time and they tend to rely on structures which are obsolete today, but they still run, so the examples continue circulating and promoting obsolete, sloppy, and even grievously insecure practices.

One of the things I like about Perl is its tradition of maintaining backwards compatibility, but this is one area in which the lack of any real deprecation policy has probably harmed the language.

View Postblitzfx, on 14 Oct, 2009 - 10:43 AM, said:

I used strict; and it threw, mostly, errors saying Global symbol "[something]" requires explicit package name. So I chucked 'my' infront of every single variable, not knowing what it does....and still dont.

In this immediate case, using strict and declaring your variables properly (with "my", "our", or "use vars" - but "my" is the one you want 99% of the time, so just use that until you hit a case where it won't work for you) protects you from accidentally creating a new variable because of a typo when you meant to access an existing one.

In the broader picture, "my" creates lexically-scoped variables, which is (more or less) just a fancy way of saying variables that stop existing at the end of the block they were defined in:
use strict;
use warnings;

sub foo {
  my $x = 1;
  print "$x\n";  # prints 1

  if ($x) {
	my $x = 2;  # we're in a different block, so this is a different $x
	print "$x\n";  # prints 2
  }

  print "$x\n";  # prints 1 because we're back in the first block, with the first $x
}

print "$x\n";  # $x no longer exists, so strict throws an error and dies


Like glob-style filehandles, global variables can cause problems that are extremely difficult to debug because changing $x in one part of the program (if it's global) will also change $x in any other parts of the program that use $x, even if they're completely unrelated. Using "my" to create lexical variables protects you against this and using strict ensures that you won't accidentally use globals if you don't really need to.

View Postblitzfx, on 14 Oct, 2009 - 10:43 AM, said:

sub errorFunction
{
	print   header(),
		start_html(ERROR),
		"ERROR - file could not be opened <br/ > ", 
		a({-href => "http://....../index.html"}, "Click here to go to main site"),
		end_html();
}


and it's throwing an error saying "Bareword "ERROR" not allowed while "strict subs in use". I don't know how to fix this so i've disabled strict in the mean time.

You forgot the quotes around "ERROR". :) You might also want to assign the string passed in to a variable and include a description of what went wrong on the error page:
sub errorFunction
{
	my $error = shift;

	print   header(),
	start_html('ERROR'),
	"ERROR - file could not be opened:<br/ >$error", 
	a({-href => "http://....../index.html"}, "Click here to go to main site"),
	end_html();
}


View Postblitzfx, on 14 Oct, 2009 - 10:43 AM, said:

one more thing:
├─Folder1
│  └─main.html
└─cgi-bin
	└─file.cgi


How do I specify the location of file.cgi from main.html ?

The same way you'd specify it in your browser's address bar. With that type of setup, it would most often be /cgi-bin/file.cgi, but I personally never segregate my code into a separate cgi-bin directory, so it's not something I normally need to deal with.

View Postblitzfx, on 14 Oct, 2009 - 10:43 AM, said:

Thanks for the advice. I also found out the file writing issue was due to some strange permission thing due to the university server using apache and the scripts being called under a user called 'apache'.

That's a pretty common practice for limiting the amount of damage that can be done if an attacker is able to compromise the web server process or any subprocesses it might start up (like, say, CGI scripts). Creating the output file (using "touch filename") and then setting it to be world-writable ("chmod a+w filename") should allow the apache user to write to it.
Was This Post Helpful? 0
  • +
  • -

#7 programble  Icon User is offline

  • (cons :dic :head)

Reputation: 49
  • View blog
  • Posts: 1,315
  • Joined: 21-February 09

Re: perl & cgi - cannot write to a file

Posted 14 October 2009 - 12:35 PM

Has no one suggested that the file is not writable?

chmod 666 filename
Was This Post Helpful? 0
  • +
  • -

#8 blitzfx  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 16-August 09

Re: perl & cgi - cannot write to a file

Posted 15 October 2009 - 01:58 AM

Quote

Has no one suggested that the file is not writable?

chmod 666 filename

I had already set the file to chmod 777, and I have already fixed the problem but thanks.

Quote

Like glob-style filehandles, global variables can cause problems that are extremely difficult to debug because changing $x in one part of the program (if it's global) will also change $x in any other parts of the program that use $x, even if they're completely unrelated. Using "my" to create lexical variables protects you against this and using strict ensures that you won't accidentally use globals if you don't really need to.

I appreciate the explanation(s) a lot. I found it was almost like java encapsulation where "my $var" is just like "this.var" or setting variables to "private" ensuring nothing else outside it's scope can write to it.

cheers!
Was This Post Helpful? 0
  • +
  • -

#9 dsherohman  Icon User is offline

  • Perl Parson
  • member icon

Reputation: 226
  • View blog
  • Posts: 654
  • Joined: 29-March 09

Re: perl & cgi - cannot write to a file

Posted 15 October 2009 - 02:34 AM

View Postblitzfx, on 15 Oct, 2009 - 08:58 AM, said:

I appreciate the explanation(s) a lot. I found it was almost like java encapsulation where "my $var" is just like "this.var" or setting variables to "private" ensuring nothing else outside it's scope can write to it.

No problem - that's what I come here for. :)

And it's good to hear that you've got your problems sorted out. Welcome to Perl; I hope you like it enough to stay. Happy hacking!
Was This Post Helpful? 0
  • +
  • -

#10 chorny_cpan  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 2
  • View blog
  • Posts: 52
  • Joined: 13-May 09

Re: perl & cgi - cannot write to a file

Posted 17 October 2009 - 04:46 PM

A good tutorial to read is Ovid's CGI Course.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1