Hi David,

While I raise quite a few issues here, I have to say that I've rarely seen
anyone present a CGI.pm alternative that supports uploads.  I'm quite
impressed, so keep that in mind while I pick it apart :)

I'll ignore anything I may have covered in my discussion about the previous 
subroutine.  Further, there are quite a few thing that I would have done 
differently, but I'll try to focus specifically on those issues that I 
consider bugs (and I'll skip some issues that I *think* are problems but 
I'd prefer to research further before shooting my mouth off :).  I also won't 
bother on commenting on issues that I've seen you mention (DOS attacks,
for instance).

    sub parse_mform_input($) {
        my $input = shift;
        my (%form_vars, @name_file, @list, %var_count);
        if( $ENV{'CONTENT_TYPE'} =~ /multipart\/form-data; boundary=(.+)$/ ) {

            # snip

        } else { # if it is not mime
            return(parse_form_input($input)); # call the non-mime parser
        }
    }

Either you are parsing multipart/formdata (MFD) or you are not.  Your sub name
implies that this is for MFD, but then goes on to handle non-MFD.  Don't throw
curve balls at programmers :)

    if( $ENV{'CONTENT_TYPE'} =~ /multipart\/form-data; boundary=(.+)$/ ) {
        $boundary = '--'.$1;  # Using MIME to split out the form elements.

It turns out that IE 3.01 on Macintosh leaves off the initial '--' on the 
boundary.  Mac users with this version of IE won't be able to upload files.  
This may not seem like much of an issue, but it's important to realize that 
there can be numerous OS/server/browser issues and for a CGI form handling 
routine to be truly robust, it should attempt to address as many of these 
issues as it can.  If you want your code to be accepted for this, it has to 
be robust.  You'll get mysterious sporadic failures that can be very hard to
debug if you don't make sure to handle all of the special cases.

Further, if someone using your code notices odd, intermittant failures that
they don't get with CGI.pm, they'll probably *have* to go with CGI.pm.  Fast 
code that doesn't work almost always loses to slow code that does work.

    # split out each form variable into @list
    @list = split(/$boundary/, $input);

I see you're just going ahead and processing the data without any sanity
checks.  What happens if someone uploads a large file and hits "Esc" about
halfway through?  Does every Web server check this?  If your's doesn't,
$ENV{CONTENT_LENGTH} is not going to match the length of the data.  You need to
check this to ensure that you're not processing "partial" data and thereby
risking some data corruption.

    foreach $listitem (@list){

Again, you appear to not be using strict.

    # if the data has a filename in it then
    if ($listitem =~ / name=\"(.*)\"; filename=\"(.*?)\"[\r\n]{2}/){

I see some a bad regex here.  Items:

1.  I understand that some user agents do not wrap the values in quote marks.
Also, some versions of Netscape don't escape quotes in filenames.

2.  The dot star in your regex is bad.  Read "Death to Dot Star!" for more
information.  http://www.perlmonks.org/index.pl?node_id=24640.  This can
cause slow regexes, or worse, buggy ones.  

3.  You need to define the CRLF sequence.   What is the CRLF sequence that the
system that *this* version of your program is using?  Not every system is going
to use the same one.  Read through CGI.pm and see how it's handled there.  You
can search on $CRLF.

    # if the file name is not empty now
    if ($form_file{'file_name'} ne "") {
        # if the file is larger than 0 bytes
        if (length($form_file{'file_content'}) > 0){
            # creating a garanteed unique file name

Rather than going through all of you code to guarantee a unique name (which
will be thrown away anyway), why not just do some variation of this:

  use Digest::MD5;
  my $temp_file;
  do {
      $temp_file = Digest::MD5::md5_hex( $ENV{REMOTE_ADDR}, rand() );
  } until ( ! -e $upload_dir.$temp_file );

Much cleaner and easier to understand, though I confess that I was commenting
on style and not a bug, per se.

Also, I think you are overcommenting.  Your last snippet testing that the
filename isn't empty and the content length is greater than zero are good
examples.

Much of the rest of the code has issues similar to what I've outlined above.  I
would also strongly recommend breaking your subroutines up into much smaller
chunks.  They're easier to understand that way.

Cheers,
Curtis "Ovid" Poe

=====
"Ovid" on http://www.perlmonks.org/
Someone asked me how to count to 10 in Perl:
push@A,$_ for reverse q.e...q.n.;for(@A){$_=unpack(q|c|,$_);@a=split//;
shift@a;shift@a if $a[$[]eq$[;$_=join q||,@a};print $_,$/for reverse @A

__________________________________________________
Do You Yahoo!?
Sign up for SBC Yahoo! Dial - First Month Free
http://sbc.yahoo.com

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to