CGI-Simple

 view release on metacpan or  search on metacpan

lib/CGI/Simple.pm  view on Meta::CPAN

  for my $value ( @values ) {
    next
     if $value eq ''
       and $self->{'.globals'}->{'NO_UNDEF_PARAMS'};
    $value =~ tr/\000//d
     if $self->{'.globals'}->{'NO_NULL'} and $param ne 'PUTDATA' and $param ne 'POSTDATA';
    $value = Encode::decode( utf8 => $value )
     if $self->{'.globals'}->{PARAM_UTF8} and $param ne 'PUTDATA' and $param ne 'POSTDATA';
    push @{ $self->{$param} }, $value;
    unless ( $self->{'.fieldnames'}->{$param} ) {
      push @{ $self->{'.parameters'} }, $param;
      $self->{'.fieldnames'}->{$param}++;
    }
  }
  return scalar @values;    # for compatibility with CGI.pm request.t
}

sub _parse_keywordlist {
  my ( $self, $data ) = @_;
  return () unless defined $data;
  $data = $self->url_decode( $data );
  $data =~ tr/\000//d if $self->{'.globals'}->{'NO_NULL'};
  my @keywords = split /\s+/, $data;
  return @keywords;
}

sub _massage_boundary {
  my ( $self, $boundary ) = @_;

  # BUG: IE 3.01 on the Macintosh uses just the boundary,
  # forgetting the --
  $boundary = '--' . $boundary
   unless exists $ENV{'HTTP_USER_AGENT'}
     && $ENV{'HTTP_USER_AGENT'} =~ m/MSIE\s+3\.0[12];\s*Mac/i;

  return quotemeta $boundary;
}

sub _parse_multipart {
  my $self = shift;
  my $handle = shift or die "NEED A HANDLE!?";

  my ( $boundary )
   = $ENV{'CONTENT_TYPE'} =~ /boundary=\"?([^\";,]+)\"?/;

  $boundary = $self->_massage_boundary( $boundary ) if $boundary;

  my $got_data = 0;
  my $data     = '';
  my $length   = $ENV{'CONTENT_LENGTH'} || 0;
  my $CRLF     = $self->crlf;

  READ:

  while ( $got_data < $length ) {
    last READ unless _internal_read( $self, $handle, my $buffer );
    $data .= $buffer;
    $got_data += length $buffer;

    unless ( $boundary ) {
      # If we're going to guess the boundary we need a complete line.
      next READ unless $data =~ /^(.*)$CRLF/o;
      $boundary = $1;

      # Still no boundary? Give up...
      unless ( $boundary ) {
        $self->cgi_error(
          '400 No boundary supplied for multipart/form-data' );
        return 0;
      }
      $boundary = $self->_massage_boundary( $boundary );
    }

    BOUNDARY:

    while ( $data =~ m/^$boundary$CRLF/ ) {
      ## TAB and high ascii chars are definitivelly allowed in headers.
      ## Not accepting them in the following regex prevents the upload of
      ## files with filenames like "España.txt".
      # next READ unless $data =~ m/^([\040-\176$CRLF]+?$CRLF$CRLF)/o;
      next READ
       unless $data =~ m/^([\x20-\x7E\x80-\xFF\x09$CRLF]+?$CRLF$CRLF)/o;
      my $header = $1;
      ( my $unfold = $1 ) =~ s/$CRLF\s+/ /og;
      my ( $param ) = $unfold =~ m/form-data;\s+name="?([^\";]*)"?/;
      my ( $filename )
       = $unfold =~ m/name="?\Q$param\E"?;\s+filename="?([^\"]*)"?/;

      if ( defined $filename ) {
        my ( $mime ) = $unfold =~ m/Content-Type:\s+([-\w\+\.\/]+)/io;
        $data =~ s/^\Q$header\E//;
        ( $got_data, $data, my $fh, my $size )
         = $self->_save_tmpfile( $handle, $boundary, $filename,
          $got_data, $data );
        $self->_add_param( $param, $filename );
        $self->{'.upload_fields'}->{$param} = $filename;
        $self->{'.filehandles'}->{$filename} = $fh if $fh;
        $self->{'.tmpfiles'}->{$filename}
         = { 'size' => $size, 'mime' => $mime }
         if $size;
        next BOUNDARY;
      }
      next READ
       unless $data =~ s/^\Q$header\E(.*?)$CRLF(?=$boundary)//s;
      $self->_add_param( $param, $1 );
    }
    unless ( $data =~ m/^$boundary/ ) {
      ## In a perfect world, $data should always begin with $boundary.
      ## But sometimes, IE5 prepends garbage boundaries into POST(ed) data.
      ## Then, $data does not start with $boundary and the previous block
      ## never gets executed. The following fix attempts to remove those
      ## extra boundaries from readed $data and restart boundary parsing.
      ## Note about performance: with well formed data, previous check is
      ## executed (generally) only once, when $data value is "$boundary--"
      ## at end of parsing.
      goto BOUNDARY if ( $data =~ s/.*?$CRLF(?=$boundary$CRLF)//s );
    }
  }
  return $got_data;
}



( run in 3.081 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )