Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CGI.pm questions

3 views
Skip to first unread message

MatthewOliverius

unread,
Aug 29, 2002, 10:56:06 AM8/29/02
to
Hi everyone,

I am a newbie with the Perl/CGI stuff, however I do have some familiarity
with Perl. I am currently working on a system that provides the client the
capability to upload a text file on a web page, the web form calls an
external perl application through cgi that parses and checks the uploaded
text file and outputs an html page. I originally took this code almost
verbatim from O'Reilly's CGI Programming with Perl book. However, I soon
found out that there were several bugs in the program that had to be fixed.
I've posted the program below and here are the problems I am having:

1) The upload of the file appears to work fine, provided that a unique
filename is entered every time. If a filename that already exists in the
upload directory is input, then I get an error which states "filename isn't
numeric in numeric ge (>=) at uploadwork line 44.

2) The upload method utilized in this script is only available on cgi.pm
version 2.47 or later. However, at work we have version 2.46. How would I
modify this code so that it works on version 2.46?

3) The code below launches an external application through a cgi script.
If you run this external application manually, it is set up to output
results to the screen on STDOUT and it creates a file with these same
results embedded between HTML tags. Which is better to return to the code
below? How do I modify the code below to return the html page and to ensure
that the client browser won't cache the Results.html page?

4) Is there a more secure way to launch this external application besides a
system call? How would this be done?

Any help you can provide me would be highly appreciated. Thank you.


#!/usr/bin/perl -w

use strict;
use CGI;
use CGI::Carp qw( fatalsToBrowser );
use Fcntl qw( :DEFAULT :flock );

use constant UPLOAD_DIR => "/var/www/uploads";
use constant BUFFER_SIZE => 16_384;
use constant MAX_FILE_SIZE => 1_048_576; # Limit each upload to 1 MB
use constant MAX_DIR_SIZE => 100 * 1_048_576; # Limit total uploads to
100MB
use constant MAX_OPEN_TRIES => 100;

$CGI::DISABLE_UPLOADS = 0;
$CGI::POST_MAX = MAX_FILE_SIZE;

my $q = new CGI;
$q->cgi_error and error( $q, "Error transferring file: " . $q->cgi_error );

my $file = $q->param( "file" ) || error( $q, "No file received." );
my $filename = $q->param( "filename" ) || error( $q, "No filename
entered." );
my $fh = $q->upload( "file" );
my $buffer = "";

if ( dir_size( UPLOAD_DIR ) + $ENV{CONTENT_LENGTH} > MAX_DIR_SIZE ) {
error( $q, "Upload directory is full." );
}

#Allow letters, digits, periods, underscores, dashes
#Convert anything else to an underscore
$filename =~ s/[^\w.-]/_/g;
if ( $filename =~ /^(\w[\w.-]*)/ ) {
$filename = $1;
}
else {
error( $q, "Invalid file name; files must start with a letter or
number." );
}

# Open output file, making sure the name is unique
until ( sysopen OUTPUT, UPLOAD_DIR . "/$filename", O_CREAT | O_RDWR |
O_EXCL ) {
$filename =~ s/(\d*)(\.\w+)$/($1||0) + 1 . $2/e;
$1 >= MAX_OPEN_TRIES and error( $q, "Unable to save your file." );
}

# This is necessary for non-Unix systems; does nothing on UNIX
binmode $fh; # LINE 46
binmode OUTPUT;

# Write contents to output file
while ( read( $fh, $buffer, BUFFER_SIZE ) ) {


print OUTPUT $buffer;
}


close OUTPUT;


system("/var/www/uploads/PLS_check_beta_HTML", "/var/www/uploads/$filename >
deleteme");

print "Location: http://localhost/Results.html";

sub dir_size {
my $dir = shift;
my $dir_size = 0;

# Loop through files and sum the sizes; doesn't descend down subdirs
opendir DIR, $dir or die "Unable to open $dir: $!";
while ( readdir DIR ) {
$dir_size += -s "$dir/$_"; # LINE 66
}
return $dir_size;
}


sub error {
my( $q, $reason ) = @_;


print $q->header( "text/html" ),
$q->start_html( "Error" ),
$q->h1( "Error" ),
$q->p( "Your upload was not processed because the following error",
"occured: " ),
$q->p( $q->i( $reason ) ),
$q->end_html;
exit;
}


bengee

unread,
Aug 29, 2002, 11:14:09 AM8/29/02
to
Fuck off.

"MatthewOliverius" <moliv...@msn.com> wrote in message
news:O#S33p2TCHA.2272@cpimsnntpa03...

DaBootlegga

unread,
Aug 29, 2002, 12:59:38 PM8/29/02
to

"bengee" <postm...@localhost.localdomain> wrote in message
news:akldmc$cea$1...@news0.ifb.net...
> Fuck off.
>
<snip>

What is the reason for this outburst of aggression? Perhaps you should look
into some anger management seminars.


Wayne

unread,
Aug 29, 2002, 10:41:13 PM8/29/02
to
Hello,

Here are some suggestions that may help you overcome your obstacles:

1. Check to see if the file exists before attempting to write it:

if (-e "myfile.txt") { error($q,"File already exists!");}
else { # write the file }


2. Visit www.cpan.org and download & install the latest version of CGI.pm
(2.81). See the readme file for installation instructions if necessary.

3. I'm not exactly sure what you are asking here. As for not caching a web
page the browser itself should have caching disabled. Other than that I
don't know of any way to do it. Once you send an HTML page to a client it
is theirs to do with what they will!

4. For system calls I believe that one of the biggest security issues is in
the filename itself. Validating it before executing the system call is
always a good idea. Also, starting perl with the -T option will force taint
checks of your input.


Hope this helps,

Wayne

MatthewOliverius

unread,
Aug 30, 2002, 12:04:48 AM8/30/02
to
Wow,


I guess you aren't exactly the brightest crayon in the box are you?


"bengee" <postm...@localhost.localdomain> wrote in message
news:akldmc$cea$1...@news0.ifb.net...

0 new messages