File Coverage

blib/lib/HTTP/Body/Builder/MultiPart.pm
Criterion Covered Total %
statement 55 63 87.3
branch 8 14 57.1
condition n/a
subroutine 14 15 93.3
pod 5 7 71.4
total 82 99 82.8


line stmt bran cond sub pod time code
1             package HTTP::Body::Builder::MultiPart;
2 1     1   22681 use strict;
  1         2  
  1         136  
3 1     1   5 use warnings;
  1         2  
  1         24  
4 1     1   4 use utf8;
  1         2  
  1         5  
5 1     1   44 use 5.008_005;
  1         3  
  1         48  
6              
7 1     1   5 use File::Basename ();
  1         1  
  1         728  
8              
9             my $CRLF = "\015\012";
10              
11             sub new {
12 3     3 1 3015 my $class = shift;
13 3 50       13 my %args = @_==1 ? %{$_[0]} : @_;
  0         0  
14 3         20 bless {
15             boundary => 'xYzZY',
16             buffer_size => 2048,
17             %args
18             }, $class;
19             }
20              
21             sub add_content {
22 3     3 1 14 my ($self, $name, $value) = @_;
23 3         3 push @{$self->{content}}, [$name, $value];
  3         16  
24             }
25              
26             sub add_file {
27 2     2 1 8 my ($self, $name, $filename) = @_;
28 2         4 push @{$self->{file}}, [$name, $filename];
  2         8  
29             }
30              
31             sub content_type {
32 3     3 0 11 my $self = shift;
33 3         13 return 'multipart/form-data';
34             }
35              
36             sub _gen {
37 3     3   6 my ($self, $code) = @_;
38              
39 3         4 for my $row (@{$self->{content}}) {
  3         7  
40 3         23 $code->(join('', "--$self->{boundary}$CRLF",
41             qq{Content-Disposition: form-data; name="$row->[0]"$CRLF},
42             "$CRLF",
43             $row->[1] . $CRLF
44             ));
45             }
46 3         6 for my $row (@{$self->{file}}) {
  3         6  
47 2         87 my $filename = File::Basename::basename($row->[1]);
48 2         15 $code->(join('', "--$self->{boundary}$CRLF",
49             qq{Content-Disposition: form-data; name="$row->[0]"; filename="$filename"$CRLF},
50             "Content-Type: text/plain$CRLF",
51             "$CRLF",
52             ));
53             open my $fh, '<:raw', $row->[1]
54 2 50       105 or do {
55 0         0 $self->{errstr} = "Cannot open '$row->[1]' for reading: $!";
56 0         0 return;
57             };
58 2         3 my $buf;
59 2         3 while (1) {
60 4         991 my $r = read $fh, $buf, $self->{buffer_size};
61 4 50       17 if (not defined $r) {
    100          
62 0         0 $self->{errstr} = "Cannot open '$row->[1]' for reading: $!";
63 0         0 return;
64             } elsif ($r == 0) { # eof
65 2         5 last;
66             } else {
67 2         7 $code->($buf);
68             }
69             }
70 2         3 $code->($CRLF);
71             }
72 3         10 $code->("--$self->{boundary}--$CRLF");
73 3         11 return 1;
74             }
75              
76             sub as_string {
77 2     2 1 3 my ($self) = @_;
78 2         2 my $buf = '';
79 7     7   36 $self->_gen(sub { $buf .= $_[0] })
80 2 50       10 or return;
81 2         23 $buf;
82             }
83              
84 0     0 0 0 sub errstr { shift->{errstr} }
85              
86             sub write_file {
87 1     1 1 797 my ($self, $filename) = @_;
88              
89             open my $fh, '>:raw', $filename
90 1 50       67 or do {
91 0         0 $self->{errstr} = "Cannot open '$filename' for writing: $!";
92 0         0 return;
93             };
94 5     5   6 $self->_gen(sub { print {$fh} $_[0] })
  5         59  
95 1 50       10 or return;
96 1         64 close $fh;
97             }
98              
99             1;
100             __END__