rename dist from HTTP-Body-Multipart to HTTP-Body
Christian Hansen [Tue, 19 Jul 2005 13:16:06 +0000 (13:16 +0000)]
27 files changed:
lib/HTTP/Body.pm [new file with mode: 0644]
lib/HTTP/Body/Multipart.pm
lib/HTTP/Body/Octetstream.pm [new file with mode: 0644]
lib/HTTP/Body/Urlencoded.pm [new file with mode: 0644]
t/data/multipart/001-content.dat [new file with mode: 0644]
t/data/multipart/001-headers.yml [new file with mode: 0644]
t/data/multipart/002-content.dat [new file with mode: 0644]
t/data/multipart/002-headers.yml [new file with mode: 0644]
t/data/multipart/003-content.dat [new file with mode: 0644]
t/data/multipart/003-headers.yml [new file with mode: 0644]
t/data/multipart/004-content.dat [new file with mode: 0644]
t/data/multipart/004-headers.yml [new file with mode: 0644]
t/data/multipart/005-content.dat [new file with mode: 0644]
t/data/multipart/005-headers.yml [new file with mode: 0644]
t/data/multipart/006-content.dat [new file with mode: 0644]
t/data/multipart/006-headers.yml [new file with mode: 0644]
t/data/multipart/007-content.dat [new file with mode: 0644]
t/data/multipart/007-headers.yml [new file with mode: 0644]
t/data/multipart/008-content.dat [new file with mode: 0644]
t/data/multipart/008-headers.yml [new file with mode: 0644]
t/data/multipart/009-content.dat [new file with mode: 0644]
t/data/multipart/009-headers.yml [new file with mode: 0644]
t/data/multipart/010-content.dat [new file with mode: 0644]
t/data/multipart/010-headers.yml [new file with mode: 0644]
t/data/multipart/011-content.dat [new file with mode: 0644]
t/data/multipart/011-headers.yml [new file with mode: 0644]
test.pl

diff --git a/lib/HTTP/Body.pm b/lib/HTTP/Body.pm
new file mode 100644 (file)
index 0000000..16864c2
--- /dev/null
@@ -0,0 +1,108 @@
+package HTTP::Body;
+
+use strict;
+
+use Carp         qw[ ];
+use List::Util   qw[ first ];
+use Scalar::Util qw[ blessed ];
+
+our $PARSERS = {
+    'application/octet-stream'          => 'HTTP::Body::Octetstream',
+    'application/x-www-form-urlencoded' => 'HTTP::Body::Urlencoded',
+    'multipart/form-data'               => 'HTTP::Body::Multipart'
+};
+
+sub new {
+    my ( $class, $content_type, $content_length ) = @_;
+
+    unless ( @_ == 3 ) {
+        Carp::croak( $class, '->new( $content_type, $content_length )' );
+    }
+    
+    my $type = first { index( lc($content_type), $_ ) >= 0 } keys %{ $PARSERS };
+    my $body = $PARSERS->{ $type || 'application/octet-stream' };
+    
+    eval "require $body";
+    
+    if ( $@ ) {
+        die $@;
+    }
+    
+    my $self = {
+        buffer         => '',
+        content_length => $content_length,
+        content_type   => $content_type,
+        param          => { },
+        upload         => { }
+    };
+
+    bless( $self, $body );
+    
+    return $self->init;
+}
+
+sub add {
+    Carp::croak('Define abstract method add() in implementation');
+}
+
+sub init {
+    return $_[0];
+}
+
+sub body {
+    my $self = shift;
+    $self->{body} = shift if @_;
+    return $self->{body};
+}
+
+sub content_length {
+    return shift->{content_length};
+}
+
+sub content_type {
+    return shift->{content_type};
+}
+
+sub param {
+    my $self = shift;
+
+    if ( @_ == 2 ) {
+
+        my ( $name, $value ) = @_;
+
+        if ( exists $self->{param}->{$name} ) {
+            for ( $self->{param}->{$name} ) {
+                $_ = [$_] unless ref($_) eq "ARRAY";
+                push( @$_, $value );
+            }
+        }
+        else {
+            $self->{param}->{$name} = $value;
+        }
+    }
+
+    return $self->{param};
+}
+
+sub upload {
+    my $self = shift;
+
+    if ( @_ == 2 ) {
+
+        my ( $name, $upload ) = @_;
+
+        if ( exists $self->{upload}->{$name} ) {
+            for ( $self->{upload}->{$name} ) {
+                $_ = [$_] unless ref($_) eq "ARRAY";
+                push( @$_, $upload );
+            }
+        }
+        else {
+            $self->{upload}->{$name} = $upload;
+        }
+    }
+
+    return $self->{upload};
+}
+
+1;
index 46d280c..89b88d2 100644 (file)
 package HTTP::Body::Multipart;
 
 use strict;
-use base 'HTTP::Body::Multipart::Parser';
+use base 'HTTP::Body';
+use bytes;
 
 use File::Temp 0.14;
 
-sub new {
-    my $class = shift;
-    
-    my $self = $class->SUPER::new(@_);
-    $self->{param}  = {};
-    $self->{upload} = {};
+sub init {
+    my $self = shift;
+
+    unless ( $self->content_type =~ /boundary=\"?([^\";,]+)\"?/ ) {
+        my $content_type = $self->content_type;
+        Carp::croak("Invalid boudrary in content_type: '$content_type'");
+    }
+
+    $self->{boundary} = $1;
+    $self->{state}    = 'preamble';
+    $self->{length}   = $self->content_length - $self->content_length * 2;
 
     return $self;
 }
 
-sub handler {
-    my ( $self, $part ) = @_;
+sub add {
+    my ( $self, $buffer ) = @_;
 
-    if ( $part->{done} && $part->{size} == 0 ) {
+    unless ( defined $buffer ) {
+        $buffer = '';
+    }
+
+    $self->{buffer} .= $buffer;
+    $self->{length} += length($buffer);
+
+    while (1) {
+
+        if ( $self->{state} eq 'done' ) {
+            return 0;
+        }
+
+        elsif ( $self->{state} =~ /^(preamble|boundary|header|body)$/ ) {
+            my $method = "parse_$1";
+            return $self->{length} unless $self->$method;
+        }
+
+        else {
+            Carp::croak('Unknown state');
+        }
+    }
+}
+
+sub boundary {
+    my $self = shift;
+    $self->{boundary} = shift if @_;
+    return $self->{boundary};
+}
+
+sub boundary_begin {
+    return "--" . shift->boundary;
+}
+
+sub boundary_end {
+    return shift->boundary_begin . "--";
+}
+
+sub crlf {
+    return "\x0d\x0a";
+}
+
+sub delimiter_begin {
+    my $self = shift;
+    return $self->crlf . $self->boundary_begin;
+}
+
+sub delimiter_end {
+    my $self = shift;
+    return $self->crlf . $self->boundary_end;
+}
+
+sub parse_preamble {
+    my $self = shift;
+
+    my $index = index( $self->{buffer}, $self->boundary_begin );
+
+    unless ( $index >= 0 ) {
         return 0;
     }
 
-    unless ( $self->{seen}->{"$part"}++ ) {
+    # replace preamble with CRLF so we can match dash-boundary as delimiter
+    substr( $self->{buffer}, 0, $index, $self->crlf );
 
-        my $disposition = $part->{headers}->{'Content-Disposition'};
-        my ($name)      = $disposition =~ / name="?([^\";]+)"?"/;
-        my ($filename)  = $disposition =~ / filename="?([^\"]+)"?/;
+    $self->{state} = 'boundary';
 
-        $part->{name}     = $name;
-        $part->{filename} = $filename;
+    return 1;
+}
 
-        if ($filename) {
+sub parse_boundary {
+    my $self = shift;
 
-            my $fh = File::Temp->new( UNLINK => 0 );
+    if ( index( $self->{buffer}, $self->delimiter_begin . $self->crlf ) == 0 ) {
 
-            $part->{fh}       = $fh;
-            $part->{tempname} = $fh->filename;
-        }
+        substr( $self->{buffer}, 0, length( $self->delimiter_begin ) + 2, '' );
+        $self->{current}  = {};
+        $self->{state}    = 'header';
+
+        return 1;
     }
 
-    if ( $part->{filename} ) {
-        $part->{fh}->write( delete $part->{data} );
+    if ( index( $self->{buffer}, $self->delimiter_end . $self->crlf ) == 0 ) {
+        $self->{current}  = {};
+        $self->{state}    = 'done';
+        return 0;
+    }    
+
+    return 0;
+}
+
+sub parse_header {
+    my $self = shift;
+
+    my $crlf  = $self->crlf;
+    my $index = index( $self->{buffer}, $crlf . $crlf );
+
+    unless ( $index >= 0 ) {
+        return 0;
     }
 
-    if ( $part->{done} ) {
+    my $header = substr( $self->{buffer}, 0, $index );
 
-        if ( $part->{filename} ) {
-            $self->upload( $part->{name}, $part );
-        }
+    substr( $self->{buffer}, 0, $index + 4, '' );
 
+    my @headers;
+    for ( split /$crlf/, $header ) {
+        if (s/^[ \t]+//) {
+            $headers[-1] .= $_;
+        }
         else {
-            $self->param( $part->{name}, $part->{data} );
+            push @headers, $_;
         }
     }
-}
 
-sub param {
-    my $self = shift;
+    my $token = qr/[^][\x00-\x1f\x7f()<>@,;:\\"\/?={} \t]+/;
 
-    if ( @_ == 2 ) {
+    for my $header (@headers) {
 
-        my ( $name, $value ) = @_;
+        $header =~ s/^($token):[\t ]*//;
 
-        if ( exists $self->{param}->{$name} ) {
-            for ( $self->{param}->{$name} ) {
+        ( my $field = $1 ) =~ s/\b(\w)/uc($1)/eg;
+
+        if ( exists $self->{current}->{headers}->{$field} ) {
+            for ( $self->{current}->{headers}->{$field} ) {
                 $_ = [$_] unless ref($_) eq "ARRAY";
-                push( @$_, $value );
+                push( @$_, $header );
             }
         }
         else {
-            $self->{param}->{$name} = $value;
+            $self->{current}->{headers}->{$field} = $header;
         }
     }
 
-    return $self->{param};
+    $self->{state} = 'body';
+
+    return 1;
 }
 
-sub upload {
+sub parse_body {
     my $self = shift;
 
-    if ( @_ == 2 ) {
+    my $index = index( $self->{buffer}, $self->delimiter_begin );
 
-        my ( $name, $upload ) = @_;
+    if ( $index < 0 ) {
 
-        if ( exists $self->{upload}->{$name} ) {
-            for ( $self->{upload}->{$name} ) {
-                $_ = [$_] unless ref($_) eq "ARRAY";
-                push( @$_, $upload );
-            }
+        # make sure we have enough buffer to detect end delimiter
+        my $length = length( $self->{buffer} ) - ( length( $self->delimiter_end ) + 2 );
+
+        unless ( $length > 0 ) {
+            return 0;
         }
-        else {
-            $self->{upload}->{$name} = $upload;
+
+        $self->{current}->{data} .= substr( $self->{buffer}, 0, $length, '' );
+        $self->{current}->{size} += $length;
+        $self->{current}->{done}  = 0;
+
+        $self->handler( $self->{current} );
+
+        return 0;
+    }
+
+    $self->{current}->{data} .= substr( $self->{buffer}, 0, $index, '' );
+    $self->{current}->{size} += $index;
+    $self->{current}->{done}  = 1;
+
+    $self->handler( $self->{current} );
+
+    $self->{state} = 'boundary';
+
+    return 1;
+}
+
+sub handler {
+    my ( $self, $part ) = @_;
+
+    if ( $part->{done} && $part->{size} == 0 ) {
+        return 0;
+    }
+
+    unless ( $self->{seen}->{"$part"}++ ) {
+
+        my $disposition = $part->{headers}->{'Content-Disposition'};
+        my ($name)      = $disposition =~ / name="?([^\";]+)"?"/;
+        my ($filename)  = $disposition =~ / filename="?([^\"]+)"?/;
+
+        $part->{name}     = $name;
+        $part->{filename} = $filename;
+
+        if ($filename) {
+
+            my $fh = File::Temp->new( UNLINK => 0 );
+
+            $part->{fh}       = $fh;
+            $part->{tempname} = $fh->filename;
         }
     }
 
-    return $self->{upload};
+    if ( $part->{filename} ) {
+        $part->{fh}->write( delete $part->{data} );
+    }
+
+    if ( $part->{done} ) {
+
+        if ( $part->{filename} ) {
+            
+            my $fh = delete $part->{fh};
+            $fh->close;
+            
+            $self->upload( $part->{name}, $part );
+        }
+
+        else {
+            $self->param( $part->{name}, $part->{data} );
+        }
+    }
 }
 
 1;
diff --git a/lib/HTTP/Body/Octetstream.pm b/lib/HTTP/Body/Octetstream.pm
new file mode 100644 (file)
index 0000000..8c50264
--- /dev/null
@@ -0,0 +1,9 @@
+package HTTP::Body::Octetstream;
+
+use strict;
+use base 'HTTP::Body';
+use bytes;
+
+use File::Temp 0.14;
+
+1;
diff --git a/lib/HTTP/Body/Urlencoded.pm b/lib/HTTP/Body/Urlencoded.pm
new file mode 100644 (file)
index 0000000..e2a52c7
--- /dev/null
@@ -0,0 +1,7 @@
+package HTTP::Body::Urlencoded;
+
+use strict;
+use base 'HTTP::Body';
+use bytes;
+
+1;
diff --git a/t/data/multipart/001-content.dat b/t/data/multipart/001-content.dat
new file mode 100644 (file)
index 0000000..c45f909
--- /dev/null
@@ -0,0 +1,63 @@
+------------0xKhTmLbOuNdArY\r
+Content-Disposition: form-data; name="text1"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+------------0xKhTmLbOuNdArY\r
+Content-Disposition: form-data; name="text2"\r
+\r
+\r
+------------0xKhTmLbOuNdArY\r
+Content-Disposition: form-data; name="select"\r
+\r
+A\r
+------------0xKhTmLbOuNdArY\r
+Content-Disposition: form-data; name="select"\r
+\r
+B\r
+------------0xKhTmLbOuNdArY\r
+Content-Disposition: form-data; name="textarea"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+------------0xKhTmLbOuNdArY\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+Content-Type: application/octet-stream\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+------------0xKhTmLbOuNdArY\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+Content-Type: application/octet-stream\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+------------0xKhTmLbOuNdArY\r
+Content-Disposition: form-data; name="upload1"; filename=""\r
+\r
+\r
+------------0xKhTmLbOuNdArY\r
+Content-Disposition: form-data; name="upload2"; filename="hello.pl"\r
+Content-Type: application/octet-stream\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+------------0xKhTmLbOuNdArY--\r
diff --git a/t/data/multipart/001-headers.yml b/t/data/multipart/001-headers.yml
new file mode 100644 (file)
index 0000000..e2f5998
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1559
+Content-Type: multipart/form-data; boundary=----------0xKhTmLbOuNdArY
+User-Agent: 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312'
diff --git a/t/data/multipart/002-content.dat b/t/data/multipart/002-content.dat
new file mode 100644 (file)
index 0000000..e2e9299
--- /dev/null
@@ -0,0 +1,70 @@
+--LYNX\r
+Content-Disposition: form-data; name="text1"\r
+Content-Type: text/plain; charset=utf-8\r
+\r
+Ratione accusamus aspernatur aliquam\r
+--LYNX\r
+Content-Disposition: form-data; name="text2"\r
+Content-Type: text/plain; charset=utf-8\r
+\r
+\r
+--LYNX\r
+Content-Disposition: form-data; name="select"\r
+Content-Type: text/plain; charset=utf-8\r
+\r
+A\r
+--LYNX\r
+Content-Disposition: form-data; name="select"\r
+Content-Type: text/plain; charset=utf-8\r
+\r
+B\r
+--LYNX\r
+Content-Disposition: form-data; name="textarea"\r
+Content-Type: text/plain; charset=utf-8\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+\r
+--LYNX\r
+Content-Disposition: form-data; name="upload"; filename="/Users/chansen/hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+--LYNX\r
+Content-Disposition: form-data; name="upload"; filename="/Users/chansen/hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+--LYNX\r
+Content-Disposition: form-data; name="upload1"; filename=""\r
+Content-Type: text/plain\r
+\r
+\r
+--LYNX\r
+Content-Disposition: form-data; name="upload2"; filename="/Users/chansen/hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+--LYNX--\r
diff --git a/t/data/multipart/002-headers.yml b/t/data/multipart/002-headers.yml
new file mode 100644 (file)
index 0000000..bf95402
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1585
+Content-Type: multipart/form-data; boundary=LYNX
+User-Agent: Lynx/2.8.5rel.2 libwww-FM/2.14
diff --git a/t/data/multipart/003-content.dat b/t/data/multipart/003-content.dat
new file mode 100644 (file)
index 0000000..3461959
--- /dev/null
@@ -0,0 +1,60 @@
+--00000000000000000000000000000000\r
+Content-Disposition: form-data; name="text1"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+--00000000000000000000000000000000\r
+Content-Disposition: form-data; name="text2"\r
+\r
+\r
+--00000000000000000000000000000000\r
+Content-Disposition: form-data; name="select"\r
+\r
+A\r
+--00000000000000000000000000000000\r
+Content-Disposition: form-data; name="select"\r
+\r
+B\r
+--00000000000000000000000000000000\r
+Content-Disposition: form-data; name="textarea"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.
+
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+--00000000000000000000000000000000\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+--00000000000000000000000000000000\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+--00000000000000000000000000000000\r
+Content-Disposition: form-data; name="upload1"; filename=""\r
+\r
+\r
+--00000000000000000000000000000000\r
+Content-Disposition: form-data; name="upload2"; filename="hello.pl"\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+--00000000000000000000000000000000--\r
diff --git a/t/data/multipart/003-headers.yml b/t/data/multipart/003-headers.yml
new file mode 100644 (file)
index 0000000..9895c88
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1507
+Content-Type: multipart/form-data; boundary=00000000000000000000000000000000
+User-Agent: ELinks/0.9.2 (textmode; Darwin 7.9.0 Power Macintosh; 167x36)
diff --git a/t/data/multipart/004-content.dat b/t/data/multipart/004-content.dat
new file mode 100644 (file)
index 0000000..ea8b099
--- /dev/null
@@ -0,0 +1,69 @@
+-----------------------------168071508944249\r
+Content-Disposition: form-data; name="text1"\r
+Content-Type: text/plain; charset="utf-8"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+-----------------------------168071508944249\r
+Content-Disposition: form-data; name="text2"\r
+Content-Type: text/plain; charset="utf-8"\r
+\r
+\r
+-----------------------------168071508944249\r
+Content-Disposition: form-data; name="select"\r
+Content-Type: text/plain; charset="utf-8"\r
+\r
+A\r
+-----------------------------168071508944249\r
+Content-Disposition: form-data; name="select"\r
+Content-Type: text/plain; charset="utf-8"\r
+\r
+B\r
+-----------------------------168071508944249\r
+Content-Disposition: form-data; name="textarea"\r
+Content-Type: text/plain; charset="utf-8"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+-----------------------------168071508944249\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+Content-Type: application/octet-stream\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------168071508944249\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+Content-Type: application/octet-stream\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------168071508944249\r
+Content-Disposition: form-data; name="upload1"; filename=""\r
+Content-Type: text/plain; charset="utf-8"\r
+\r
+\r
+-----------------------------168071508944249\r
+Content-Disposition: form-data; name="upload2"; filename="hello.pl"\r
+Content-Type: application/octet-stream\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------168071508944249--\r
diff --git a/t/data/multipart/004-headers.yml b/t/data/multipart/004-headers.yml
new file mode 100644 (file)
index 0000000..f56c767
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1987
+Content-Type: multipart/form-data; boundary=---------------------------168071508944249
+User-Agent: Mozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC)
diff --git a/t/data/multipart/005-content.dat b/t/data/multipart/005-content.dat
new file mode 100644 (file)
index 0000000..c0132d2
--- /dev/null
@@ -0,0 +1,64 @@
+-----------------------------168072824752491622650073\r
+Content-Disposition: form-data; name="text1"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+-----------------------------168072824752491622650073\r
+Content-Disposition: form-data; name="text2"\r
+\r
+\r
+-----------------------------168072824752491622650073\r
+Content-Disposition: form-data; name="select"\r
+\r
+A\r
+-----------------------------168072824752491622650073\r
+Content-Disposition: form-data; name="select"\r
+\r
+B\r
+-----------------------------168072824752491622650073\r
+Content-Disposition: form-data; name="textarea"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+-----------------------------168072824752491622650073\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------168072824752491622650073\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------168072824752491622650073\r
+Content-Disposition: form-data; name="upload1"; filename=""\r
+Content-Type: application/octet-stream\r
+\r
+\r
+-----------------------------168072824752491622650073\r
+Content-Disposition: form-data; name="upload2"; filename="hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------168072824752491622650073--\r
diff --git a/t/data/multipart/005-headers.yml b/t/data/multipart/005-headers.yml
new file mode 100644 (file)
index 0000000..2041da1
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1817
+Content-Type: multipart/form-data; boundary=---------------------------168072824752491622650073
+User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4
diff --git a/t/data/multipart/006-content.dat b/t/data/multipart/006-content.dat
new file mode 100644 (file)
index 0000000..fbc3532
--- /dev/null
@@ -0,0 +1,64 @@
+-----------------------------7d53c2922c\r
+Content-Disposition: form-data; name="text1"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+-----------------------------7d53c2922c\r
+Content-Disposition: form-data; name="text2"\r
+\r
+\r
+-----------------------------7d53c2922c\r
+Content-Disposition: form-data; name="select"\r
+\r
+A\r
+-----------------------------7d53c2922c\r
+Content-Disposition: form-data; name="select"\r
+\r
+B\r
+-----------------------------7d53c2922c\r
+Content-Disposition: form-data; name="textarea"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+-----------------------------7d53c2922c\r
+Content-Disposition: form-data; name="upload"; filename="C:\WINDOWS\Skrivbord\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d53c2922c\r
+Content-Disposition: form-data; name="upload"; filename="C:\WINDOWS\Skrivbord\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d53c2922c\r
+Content-Disposition: form-data; name="upload1"; filename=""\r
+Content-Type: application/octet-stream\r
+\r
+\r
+-----------------------------7d53c2922c\r
+Content-Disposition: form-data; name="upload2"; filename="C:\WINDOWS\Skrivbord\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d53c2922c--\r
diff --git a/t/data/multipart/006-headers.yml b/t/data/multipart/006-headers.yml
new file mode 100644 (file)
index 0000000..af0a4f9
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1740
+Content-Type: multipart/form-data; boundary=---------------------------7d53c2922c
+User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
diff --git a/t/data/multipart/007-content.dat b/t/data/multipart/007-content.dat
new file mode 100644 (file)
index 0000000..da090f9
--- /dev/null
@@ -0,0 +1,63 @@
+------------Bv684bhJBhreYbdRAUxHhF\r
+Content-Disposition: form-data; name="text1"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+------------Bv684bhJBhreYbdRAUxHhF\r
+Content-Disposition: form-data; name="text2"\r
+\r
+\r
+------------Bv684bhJBhreYbdRAUxHhF\r
+Content-Disposition: form-data; name="select"\r
+\r
+A\r
+------------Bv684bhJBhreYbdRAUxHhF\r
+Content-Disposition: form-data; name="select"\r
+\r
+B\r
+------------Bv684bhJBhreYbdRAUxHhF\r
+Content-Disposition: form-data; name="textarea"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+------------Bv684bhJBhreYbdRAUxHhF\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+Content-Type: application/octet-stream\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+------------Bv684bhJBhreYbdRAUxHhF\r
+Content-Disposition: form-data; name="upload"; filename="hello.pl"\r
+Content-Type: application/octet-stream\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+------------Bv684bhJBhreYbdRAUxHhF\r
+Content-Disposition: form-data; name="upload1"; filename=""\r
+\r
+\r
+------------Bv684bhJBhreYbdRAUxHhF\r
+Content-Disposition: form-data; name="upload2"; filename="hello.pl"\r
+Content-Type: application/octet-stream\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+------------Bv684bhJBhreYbdRAUxHhF--\r
diff --git a/t/data/multipart/007-headers.yml b/t/data/multipart/007-headers.yml
new file mode 100644 (file)
index 0000000..1e7208a
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1629
+Content-Type: multipart/form-data; boundary=----------Bv684bhJBhreYbdRAUxHhF
+User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Mac_PowerPC Mac OS X; en) Opera 8.01
diff --git a/t/data/multipart/008-content.dat b/t/data/multipart/008-content.dat
new file mode 100644 (file)
index 0000000..59547b8
--- /dev/null
@@ -0,0 +1,64 @@
+-----------------------------7d52bc247fc\r
+Content-Disposition: form-data; name="text1"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+-----------------------------7d52bc247fc\r
+Content-Disposition: form-data; name="text2"\r
+\r
+\r
+-----------------------------7d52bc247fc\r
+Content-Disposition: form-data; name="select"\r
+\r
+A\r
+-----------------------------7d52bc247fc\r
+Content-Disposition: form-data; name="select"\r
+\r
+B\r
+-----------------------------7d52bc247fc\r
+Content-Disposition: form-data; name="textarea"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+-----------------------------7d52bc247fc\r
+Content-Disposition: form-data; name="upload"; filename="C:\WINDOWS\Skrivbord\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d52bc247fc\r
+Content-Disposition: form-data; name="upload"; filename="C:\WINDOWS\Skrivbord\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d52bc247fc\r
+Content-Disposition: form-data; name="upload1"; filename=""\r
+Content-Type: application/octet-stream\r
+\r
+\r
+-----------------------------7d52bc247fc\r
+Content-Disposition: form-data; name="upload2"; filename="C:\WINDOWS\Skrivbord\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d52bc247fc--\r
diff --git a/t/data/multipart/008-headers.yml b/t/data/multipart/008-headers.yml
new file mode 100644 (file)
index 0000000..b1f2567
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1750
+Content-Type: multipart/form-data; boundary=---------------------------7d52bc247fc
+User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
diff --git a/t/data/multipart/009-content.dat b/t/data/multipart/009-content.dat
new file mode 100644 (file)
index 0000000..285f5d5
--- /dev/null
@@ -0,0 +1,64 @@
+-----------------------------7d53941f40118\r
+Content-Disposition: form-data; name="text1"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+-----------------------------7d53941f40118\r
+Content-Disposition: form-data; name="text2"\r
+\r
+\r
+-----------------------------7d53941f40118\r
+Content-Disposition: form-data; name="select"\r
+\r
+A\r
+-----------------------------7d53941f40118\r
+Content-Disposition: form-data; name="select"\r
+\r
+B\r
+-----------------------------7d53941f40118\r
+Content-Disposition: form-data; name="textarea"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+-----------------------------7d53941f40118\r
+Content-Disposition: form-data; name="upload"; filename="C:\Documents and Settings\Administrator\Desktop\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d53941f40118\r
+Content-Disposition: form-data; name="upload"; filename="C:\Documents and Settings\Administrator\Desktop\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d53941f40118\r
+Content-Disposition: form-data; name="upload1"; filename=""\r
+Content-Type: application/octet-stream\r
+\r
+\r
+-----------------------------7d53941f40118\r
+Content-Disposition: form-data; name="upload2"; filename="C:\Documents and Settings\Administrator\Desktop\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d53941f40118--\r
diff --git a/t/data/multipart/009-headers.yml b/t/data/multipart/009-headers.yml
new file mode 100644 (file)
index 0000000..ec3b8e4
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1851
+Content-Type: multipart/form-data; boundary=---------------------------7d53941f40118
+User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
diff --git a/t/data/multipart/010-content.dat b/t/data/multipart/010-content.dat
new file mode 100644 (file)
index 0000000..6fc1771
--- /dev/null
@@ -0,0 +1,64 @@
+-----------------------------7d561c5012e\r
+Content-Disposition: form-data; name="text1"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+-----------------------------7d561c5012e\r
+Content-Disposition: form-data; name="text2"\r
+\r
+\r
+-----------------------------7d561c5012e\r
+Content-Disposition: form-data; name="select"\r
+\r
+A\r
+-----------------------------7d561c5012e\r
+Content-Disposition: form-data; name="select"\r
+\r
+B\r
+-----------------------------7d561c5012e\r
+Content-Disposition: form-data; name="textarea"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+-----------------------------7d561c5012e\r
+Content-Disposition: form-data; name="upload"; filename="C:\Documents and Settings\Administrator\Desktop\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d561c5012e\r
+Content-Disposition: form-data; name="upload"; filename=""\r
+Content-Type: application/octet-stream\r
+\r
+\r
+-----------------------------7d561c5012e\r
+Content-Disposition: form-data; name="upload1"; filename="C:\Documents and Settings\Administrator\Desktop\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d561c5012e\r
+Content-Disposition: form-data; name="upload2"; filename="C:\Documents and Settings\Administrator\Desktop\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d561c5012e--\r
diff --git a/t/data/multipart/010-headers.yml b/t/data/multipart/010-headers.yml
new file mode 100644 (file)
index 0000000..7dae7fe
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1831
+Content-Type: multipart/form-data; boundary=---------------------------7d561c5012e
+User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
diff --git a/t/data/multipart/011-content.dat b/t/data/multipart/011-content.dat
new file mode 100644 (file)
index 0000000..a4d29c3
--- /dev/null
@@ -0,0 +1,64 @@
+-----------------------------7d534d1d60150\r
+Content-Disposition: form-data; name="text1"\r
+\r
+Ratione accusamus aspernatur aliquam\r
+-----------------------------7d534d1d60150\r
+Content-Disposition: form-data; name="text2"\r
+\r
+\r
+-----------------------------7d534d1d60150\r
+Content-Disposition: form-data; name="select"\r
+\r
+A\r
+-----------------------------7d534d1d60150\r
+Content-Disposition: form-data; name="select"\r
+\r
+B\r
+-----------------------------7d534d1d60150\r
+Content-Disposition: form-data; name="textarea"\r
+\r
+Voluptatem cumque voluptate sit recusandae at. Et quas facere rerum unde esse. Sit est et voluptatem. Vel temporibus velit neque odio non.\r
+\r
+Molestias rerum ut sapiente facere repellendus illo. Eum nulla quis aut. Quidem voluptas vitae ipsam officia voluptatibus eveniet. Aspernatur cupiditate ratione aliquam quidem corrupti. Eos sunt rerum non optio culpa.\r
+-----------------------------7d534d1d60150\r
+Content-Disposition: form-data; name="upload"; filename="C:\Documents and Settings\Administrator\Desktop\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d534d1d60150\r
+Content-Disposition: form-data; name="upload"; filename=""\r
+Content-Type: application/octet-stream\r
+\r
+\r
+-----------------------------7d534d1d60150\r
+Content-Disposition: form-data; name="upload1"; filename="C:\Documents and Settings\Administrator\Desktop\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d534d1d60150\r
+Content-Disposition: form-data; name="upload2"; filename="C:\Documents and Settings\Administrator\Desktop\hello.pl"\r
+Content-Type: text/plain\r
+\r
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print "Hello World :)\n";
+
+\r
+-----------------------------7d534d1d60150--\r
diff --git a/t/data/multipart/011-headers.yml b/t/data/multipart/011-headers.yml
new file mode 100644 (file)
index 0000000..2ed7715
--- /dev/null
@@ -0,0 +1,4 @@
+---
+Content-Length: 1851
+Content-Type: multipart/form-data; boundary=---------------------------7d534d1d60150
+User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
diff --git a/test.pl b/test.pl
index d34e3c4..a9ef755 100644 (file)
--- a/test.pl
+++ b/test.pl
@@ -5,15 +5,17 @@ use warnings;
 use lib './lib';
 
 use Data::Dumper;
-use HTTP::Body::Multipart;
+use HTTP::Body;
 use IO::File;
 use YAML qw[LoadFile];
 
 my $test = shift(@ARGV) || 1;
 
-my $headers = LoadFile( sprintf( "t/data/%.3d-headers.yml", $test ) );
-my $content = IO::File->new( sprintf( "t/data/%.3d-content.dat", $test ), O_RDONLY );
-my $parser  = HTTP::Body::Multipart->new( $headers->{'Content-Type'}, $headers->{'Content-Length'} );
+my $headers = LoadFile( sprintf( "t/data/multipart/%.3d-headers.yml", $test ) );
+my $content = IO::File->new( sprintf( "t/data/multipart/%.3d-content.dat", $test ), O_RDONLY );
+my $parser  = HTTP::Body->new( $headers->{'Content-Type'}, $headers->{'Content-Length'} );
+
+warn ref($parser);
 
 binmode $content;
 
@@ -21,8 +23,8 @@ while ( $content->read( my $buffer, 1024 ) ) {
     last if $parser->add($buffer) == 0;
 }
 
-warn "length : $parser->{length}\n";
-warn "state  : $parser->{state}\n";
+warn "length   : $parser->{length}\n";
+warn "state    : $parser->{state}\n";
 
 warn Dumper( $parser->param );
 warn Dumper( $parser->upload );