diff --git a/FU/MultipartFormData.pm b/FU/MultipartFormData.pm index a92e4d7..7d9d77e 100644 --- a/FU/MultipartFormData.pm +++ b/FU/MultipartFormData.pm @@ -3,7 +3,7 @@ use v5.36; use Carp 'confess'; use FU::Util 'utf8_decode'; -sub _arg($d) { $d =~ s/^\s+//r =~ s/\s+$//r =~ s/^"(.+)"$/$1/r } +sub _arg($d) { $d =~ s{^"(.+)"$}{$1 =~ s/\\([\\"])/$1/rg}er } sub parse($pkg, $header, $data) { confess "Invalid multipart header '$header'" @@ -26,13 +26,14 @@ sub parse($pkg, $header, $data) { start => pos $data, }, $pkg; - confess "Missing content-disposition header" if $hdrs !~ /content-disposition:\s*form-data;(.+)/i; + confess "Missing content-disposition header" if $hdrs !~ /content-disposition:\s*form-data(.+)/i; my $v = $1; - confess "Missing 'name' parameter" if $v !~ /[;\s]name=([^[;\s]+)/; + my $pvalue = qr/("(?:\\[\\"]|[^\\"\r\n]+)*"|[^\s;"]*)/; + confess "Missing 'name' parameter" if $v !~ /;\s*name\s*=\s*$pvalue/; $d->{name} = utf8_decode _arg $1; - $d->{filename} = utf8_decode _arg $1 if $v =~ /[;\s]filename=([^;\s]+)/; + $d->{filename} = utf8_decode _arg $1 if $v =~ /;\s*filename\s*=\s*$pvalue/; - if ($hdrs =~ /content-type:\s*([^;\s]+)(?:\s*;\s*charset=([^;\s]+))?/i) { + if ($hdrs =~ /content-type:\s*$pvalue(?:\s*;\s*charset\s*=\s*$pvalue)?/i) { $d->{mime} = utf8_decode _arg $1; $d->{charset} = utf8_decode _arg $2 if $2; } diff --git a/t/multipart.t b/t/multipart.t index 842b9cd..e045ff1 100644 --- a/t/multipart.t +++ b/t/multipart.t @@ -14,12 +14,17 @@ Content-Type: text Content-Disposition: form-data; filename="example.txt"; name=field2 value2 +--delimiter12345 +Content-Type: something; charset = " a b \\ c " +Content-Disposition: form-data; name = "field \" name" ;filename= "月姫.jpg" + + --delimiter12345-- _ my $l = FU::MultipartFormData->parse('multipart/form-data;boundary="delimiter12345"', $t); -is scalar @$l, 2; +is scalar @$l, 3; my $v = $l->[0]; is $v->name, 'field1'; @@ -44,4 +49,12 @@ is $v->charset, undef; is $v->length, 6; is $v->data, 'value2'; +$v = $l->[2]; +is $v->name, 'field " name'; +is $v->filename, "\x{6708}\x{59eb}.jpg"; +is $v->mime, 'something'; +is $v->charset, ' a b \ c '; +is $v->length, 0; +is $v->data, ''; + done_testing;