proposal to fix problem when we lose multipart meta info
[catagits/HTTP-Body.git] / lib / HTTP / Body / MultiPart.pm
index 6e7a21e..cecc5d6 100644 (file)
@@ -4,7 +4,9 @@ use strict;
 use base 'HTTP::Body';
 use bytes;
 
+use IO::File;
 use File::Temp 0.14;
+use File::Spec;
 
 =head1 NAME
 
@@ -29,7 +31,7 @@ HTTP Body Multipart Parser.
 sub init {
     my $self = shift;
 
-    unless ( $self->content_type =~ /boundary=\"?([^\";,]+)\"?/ ) {
+    unless ( $self->content_type =~ /boundary=\"?([^\";]+)\"?/ ) {
         my $content_type = $self->content_type;
         Carp::croak("Invalid boundary in content_type: '$content_type'");
     }
@@ -88,7 +90,7 @@ sub boundary_end {
 
 =cut
 
-sub crlf {
+sub crlf () {
     return "\x0d\x0a";
 }
 
@@ -253,49 +255,56 @@ sub parse_body {
 
 =cut
 
+our $basename_regexp = qr/[^.]+(\.[^\\\/]+)$/;
+#our $basename_regexp = qr/(\.\w+(?:\.\w+)*)$/;
+
 sub handler {
     my ( $self, $part ) = @_;
 
-    # skip parts without content
-    if ( $part->{done} && $part->{size} == 0 ) {
-        return 0;
-    }
-
     unless ( exists $part->{name} ) {
 
         my $disposition = $part->{headers}->{'Content-Disposition'};
-        my ($name)     = $disposition =~ / name="?([^\";]+)"?/;
-        my ($filename) = $disposition =~ / filename="?([^\"]+)"?/;
+        my ($name)      = $disposition =~ / name="?([^\";]+)"?/;
+        my ($filename)  = $disposition =~ / filename="?([^\"]*)"?/;
+        # Need to match empty filenames above, so this part is flagged as an upload type
+
+        $part->{name} = $name;
 
-        $part->{name}     = $name;
-        $part->{filename} = $filename;
+        if ( defined $filename ) {
+            $part->{filename} = $filename;
 
-        if ($filename) {
+            if ( $filename ne "" ) {
+                my $basename = (File::Spec->splitpath($filename))[2];
+                my $suffix = $basename =~ $basename_regexp ? $1 : q{};
 
-            my $fh = File::Temp->new( UNLINK => 0 );
+                my $fh = File::Temp->new( UNLINK => 0, DIR => $self->tmpdir, SUFFIX => $suffix );
 
-            $part->{fh}       = $fh;
-            $part->{tempname} = $fh->filename;
+                $part->{fh}       = $fh;
+                $part->{tempname} = $fh->filename;
+            }
         }
     }
 
-    if ( $part->{filename} && ( my $length = length( $part->{data} ) ) ) {
+    if ( $part->{fh} && ( my $length = length( $part->{data} ) ) ) {
         $part->{fh}->write( substr( $part->{data}, 0, $length, '' ), $length );
     }
 
     if ( $part->{done} ) {
 
-        if ( $part->{filename} ) {
-
-            $part->{fh}->close;
+        if ( exists $part->{filename} ) {
+            if ( $part->{filename} ne "" ) {
+                $part->{fh}->close if defined $part->{fh};
 
-            delete @{$part}{qw[ data done fh ]};
+                delete @{$part}{qw[ data done fh ]};
 
-            $self->upload( $part->{name}, $part );
+                $self->upload( $part->{name}, $part );
+            }
         }
-
+        # If we have more than the content-disposition, we need to create a
+        # data key so that we don't waste the headers.
         else {
             $self->param( $part->{name}, $part->{data} );
+            $self->part_data( $part->{name}, $part )
         }
     }
 }