Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: New and need help in cgi, perl

by CharlesClarkson (Curate)
on Feb 05, 2002 at 07:10 UTC ( #143371=note: print w/ replies, xml ) Need Help??


in reply to New and need help in cgi, perl

Hi all, I am new to Perl, just learn this code in Essential Web Perl5

Please throw this book away. It is teaching you Bad Things™. Pick one of these Perl Books instead.

when i submit it it will write to 1.html, 2.html or number+.html. But i would like to have it write to title.html so i can look it easier. (ex. Title 020212 file will save as 020212.html.)

If you do this you will lose whatever is already in 020212.html. Is there some other name you would like to use instead?

Let's take a closer look at what you presented:

#!/usr/bin/perl5/perl

In modern perl a beginner would most likely start with:

#!/usr/bin/perl5/perl -T use strict; use warnings; use diagnostics;

And if your using a perl version prior to 5.6.0:

#!/usr/bin/perl5/perl -wT use strict; use diagnostics;

Take a look at Use strict and warnings for some excellent reasons.

&get_form_data;

When you write your own subroutine for retreiving form data it is often referred to as rolling your own or re-inventing the wheel. Many much more experienced programmers have tweaked most of the errors out of common tasks. These programmers often place their experience into modules.

Modules are available for perl on CPAN. We can avoid the most common mistakes by re-using this code instead of rolling our own. For CGI applications, you'd do best with CGI.pm:

use CGI qw/:standard center/;
print "Content-type: text/html\n\n";

We'll skip this for how, but you should know that it's sending headers to the browser by printing them. The browser is waiting for us to print something.

opendir(DIR, "./Data"); while($name = readdir(DIR)) { next if $name !~ /^\d*.html/; push(@files, $name); } close(DIR);

Personally, I prefer indentation to create order and improve readability:

opendir(DIR, "./Data"); while( $name = readdir(DIR) ) { next if $name !~ /^\d*.html/; push(@files, $name); } close(DIR);

Unfornately this will not work because we enforced strict in the beginning of the program. There are also a few other glaring mistakes which is why I encouraged you to rid yourself of the book you were reading.

When we open a file or dir it is a Good Thing™ to check for success.

opendir (DIR, "./Data") || die "Couldn't open directory ./Data: $!"; OR: opendir DIR, "./Data" or die "Couldn't open directory ./Data: $!";

I prefer the second one as I don't like the extra parenthesis. This is a question of style and you might have a look at perlsyn for style suggestions.

When we use strict we enforce certain rules about variable use. One rule is that we may have to use my the first time we use a variable. It also means we have to pay attention to what scope we first <tt class='inlinecode'>my</tt> it in.

while( $name = readdir(DIR) ) { next if $name !~ /^\d*.html/; push(@files, $name); }

Might be re-written as:

my @files while( my $name = readdir DIR ) { next if $name !~ /^\d*.html/; push(@files, $name); }

When you become more experienced, you might shorten it to:

my @files while( readdir DIR ) { push @files, $_ if /^\d*.html/; }

When we close a file or dir it is a Good Thing™ to check for success just as we did with opendir above. Here we use closedir

closedir(DIR) || die "Couldn't close directory './Data': $!"; OR: closedir DIR or die "Couldn't close directory './Data': $!";

The following if-else block determines the value of $nextfile which is the name of the file to be written to. According to your message, you would like this to be named the same as the last file in the directory. That would write over whatever is already there, so let's just name it "testing.html". Look in the directory to make certain we're not overwriting some other file named "testing.html".

my $next_file = 'testing.html';

Because we accessed CGI.pm with Use CGI qw/:standard center/; we are prepared to use its function oriented mode and can re-write the next section. Note: I am not using flock, but you should read up on it when you can.

open OUT, ">Data/$nextfile" or die "Cannot open 'Data/$nextfile': $!"; print OUT start_html( -title => param('title'), -bgcolor => '#FFFFFF'), center( h1( param('heading') ) ), br, p( param('body') ), end_html; close OUT or die "Cannot close 'Data/$nextfile': $!";;

Actually, we should have put a check in there for the existence of param('title') , param('heading'), and param('body'). Our new code will fail if they don't all exist.

The rest of the script, properly indented, looks like:

push(@files, $nextfile); print "<HTML>\n<BODY>\n"; foreach $file (@files) { print "<A HREF=\"Data/$file\">$file</A>\n"; print "<BR>\n"; } print "</BODY>\n</HTML>\n"; exit;

And might be re-written as:

push @files, $nextfile; print headers, start_html( -title => 'File Listing'); print a({ -href => "Data/$_" }, $_ ), br for @files; print end_html; exit;

Let's look at it all together:

#!/usr/bin/perl5/perl -T use strict; use warnings; use diagnostics; use CGI qw/:standard center/; opendir DIR, "./Data" or die "Couldn't open directory ./Data: $!"; my @files; while ( my $name = readdir DIR ) { next if $name !~ /^\d*.html/; push(@files, $name); } closedir DIR or die "Couldn't close directory './Data': $!"; my $next_file = 'testing.html'; open OUT, ">Data/$next_file" or die "Cannot open 'Data/$next_file': $! +"; print OUT start_html( -title => param('title'), -bgcolor => '#FFFFFF'), center( h1( param('heading') ) ), br, p( param('body') ), end_html; close OUT or die "Cannot close 'Data/$next_file': $!"; push @files, $next_file; print header, start_html( -title => 'File Listing'); print a({ -href => "Data/$_" }, $_ ), br for @files; print end_html;



HTH,
Charles K. Clarkson
Clarkson Energy Homes, Inc.


Comment on Re: New and need help in cgi, perl
Select or Download Code
Re: Re: New and need help in cgi, perl
by britney (Acolyte) on Feb 05, 2002 at 23:52 UTC
    Hi Charles, My system have perl 5.001, and somehow when i run your code i get error.
    webhome: 19% write.cgi Global symbol "name" requires explicit package name at write.cgi line +10. Global symbol "name" requires explicit package name at write.cgi line +11. No comma allowed after filehandle at write.cgi line 28.
    Here are the code i used:
    #!/usr/bin/perl -T use strict; # use warnings; # use diagnostics; use CGI qw/:standard center/; opendir DIR, "./Data" or die "Couldn't open directory ./Data: + $!"; my @files; while ( my $name = readdir DIR ) { next if $name !~ /^\d*.html/; push(@files, $name); } closedir DIR or die "Couldn't close directory './Data': $!"; my $next_file = 'testing.html'; open OUT, ">Data/$next_file" or die "Cannot open 'Data/$next_ +file': $!"; print OUT start_html( -title => param('title'), -bgcolor => '#FFFFFF'), center( h1( param('heading') ) ), br, p( param('body') ), end_html; close OUT or die "Cannot close 'Data/$next_file': $!"; push @files, $next_file; print header, start_html( -title => 'File Listing'); print a({ -href => "Data/$_" }, $_ ), br for @files; print end_html; exit;

      Hi Charles, My system have perl 5.001, and somehow when i run your code i get error.

      My best recommendation would be to upgrade to a more modern perl. I have my domain name on a server that refuses to upgade past 5.003, though, so I understand that may not be possible for you. I am sure they will understand when I move my domain next month.

      Unfortunately, I have never programmed in perl below 5.003, so I can only guess what is happening. You might try posting your question again as a new question. Title it as "Need to run this in perl 5.001" or something. There should be some others who are familiar with that version. You may as well explain in your message why it is not possible to upgrade your perl version. If you can get the version number of CGI.pm installed on your system, people will find that helpful too.

      In an effort to save face, perhaps I can help with the CGI.pm version info. In the CGI version I have this works:

      use CGI 'version'; print version;

      I'm sorry. It never occurred to me to find out which perl version you were using. I was recently admonished by crazyinsomniac for doing something similar.




      HTH more,
      Charles K. Clarkson
      Clarkson Energy Homes, Inc.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://143371]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2014-09-22 22:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (206 votes), past polls