File Coverage

blib/lib/CGI/Upload.pm
Criterion Covered Total %
statement 80 83 96.3
branch 21 28 75.0
condition 6 9 66.6
subroutine 13 14 92.8
pod 3 3 100.0
total 123 137 89.7


line stmt bran cond sub pod time code
1             package CGI::Upload;
2 9     9   93133 use strict;
  9         21  
  9         301  
3 9     9   87 use warnings;
  9         17  
  9         301  
4              
5 9     9   47 use Carp;
  9         18  
  9         824  
6 9     9   55 use File::Basename;
  9         16  
  9         984  
7 9     9   12205 use File::MMagic;
  9         242727  
  9         422  
8 9     9   12206 use HTTP::BrowserDetect;
  9         165507  
  9         430  
9 9     9   647 use IO::File;
  9         21  
  9         1772  
10              
11 9     9   57 use vars qw/ $AUTOLOAD $VERSION @ISA @EXPORT_OK /;
  9         15  
  9         8913  
12              
13             require Exporter;
14              
15             @ISA = qw/ Exporter /;
16             @EXPORT_OK = qw/ file_handle file_name file_type mime_magic mime_type query /;
17              
18             $VERSION = '1.11';
19              
20              
21             sub AUTOLOAD {
22 19     19   4717 my ( $self, $param ) = @_;
23              
24             # Parse method name from $AUTOLOAD variable
25              
26 19         47 my $property = $AUTOLOAD;
27 19         192 $property =~ s/.*:://;
28              
29 19         63 my @properties = qw/ file_handle file_name file_type mime_type /;
30              
31 19 100       43 unless ( grep { $property eq $_ } @properties ) {
  76         192  
32 4         1089 croak( __PACKAGE__, '->AUTOLOAD : Unsupported object method within module - ', $property );
33             }
34              
35             # Return undef if the requested parameter does not exist within
36             # CGI object
37              
38 15         60 my $cgi = $self->query;
39 15 100       77 return unless defined $cgi->param( $param );
40              
41             # The determination of all information about the uploaded file is
42             # performed by a private subroutine called _handle_file - This subroutine
43             # returns a hash of all information determined about the uploaded file
44             # which is be cached for subsequent requests.
45              
46 10 100       314 $self->{'_CACHE'}->{$param} = $self->_handle_file( $param ) unless exists $self->{'_CACHE'};
47              
48             # Return the requested property of the uploaded file
49              
50 10         103 return $self->{'_CACHE'}->{$param}->{$property};
51             }
52              
53              
54 0     0   0 sub DESTROY {}
55              
56              
57             sub _handle_file {
58 5     5   13 my ( $self, $param ) = @_;
59 5         22 my $cgi = $self->query;
60              
61             # Determine and set the appropriate file system parsing routines for the
62             # uploaded path name based upon the HTTP client header information.
63              
64 5         169 my $client_os = $^O;
65 5         118 my $browser = HTTP::BrowserDetect->new;
66 5 100       5546 $client_os = 'MSWin32' if $browser->windows;
67 5 50       81 $client_os = 'MacOS' if $browser->mac;
68 5         533 fileparse_set_fstype($client_os);
69 5         30 my @file = fileparse( $cgi->param( $param ), '\.[^.]*' );
70              
71             # Return an undefined value if the file name cannot be parsed from the
72             # file field form parameter.
73              
74 5 50       1741 return unless $file[0];
75              
76             # Determine whether binary mode is required in the handling of uploaded
77             # files -
78             # Binary mode is deemed to be required when we (the server) are running one one
79             # of these platforms: for Windows, OS/2 and VMS
80              
81 5         39 my $binmode = $^O =~ /OS2|VMS|Win|DOS|Cygwin/i;
82              
83             # Pass uploaded file into temporary file handle - This is somewhat
84             # redundant given the temporary file generation within CGI.pm, however is
85             # included to reduce dependence upon the CGI.pm module.
86              
87 5         9 my $buffer;
88 5         1330 my $fh = IO::File->new_tmpfile;
89 5 50       27 binmode( $fh ) if $binmode;
90              
91              
92             # it seems that in CGI::Simple for every call to ->upload it somehow resets
93             # the file handle. or I don't really know what is the problem with this code:
94             # while ( read( $cgi->upload( $param ) , $buffer, 1024 ) ) {
95 5         54 my $ourfh = $cgi->upload( $param );
96 5         1490 while ( read( $ourfh , $buffer, 1024 ) ) {
97 5         69 $fh->write( $buffer, length( $buffer ) );
98             }
99              
100             # Hold temporary file open, move file pointer to start - As the temporary
101             # file handle returned by the IO::File::new_tmpfile method is only
102             # accessible via this handle, the file handle must be held open for all
103             # operations.
104              
105 5         264 $fh->seek( 0, 0 );
106              
107             # Retrieve the MIME magic file, if this has been defined, and construct
108             # the File::MMagic object for the identification of the MIME type of the
109             # uploaded file.
110              
111 5         358 my $mime_magic = $self->mime_magic;
112 5 50       70 my $magic = length $mime_magic ? File::MMagic->new( $mime_magic ) : File::MMagic->new;
113              
114 5         2617 my $properties = {
115             'file_handle' => $fh,
116             'file_name' => $file[0] . $file[2],
117             'file_type' => lc substr( $file[2], 1 ),
118             'mime_type' => $magic->checktype_filehandle($fh)
119             };
120              
121             # Hold temporary file open, move file pointer to start - As the temporary
122             # file handle returned by the IO::File::new_tmpfile method is only
123             # accessible via this handle, the file handle must be held open for all
124             # operations.
125             #
126             # The importance of this operation here is due to the MIME type
127             # identification routine of File::MMagic on the open file handle
128             # (File::MMagic->checktype_filehandle), which may or may not reset the
129             # file pointer following its operation.
130              
131 5         138359 $fh->seek( 0, 0 );
132            
133 5         1060 return $properties;
134             }
135              
136              
137             sub mime_magic {
138 5     5 1 13 my ( $self, $magic ) = @_;
139              
140             # If a filename is passed to this subroutine as an argument, this filename
141             # is taken to be the file containing file MIME types and magic numbers
142             # which File::MMagic uses for determining file MIME types.
143            
144 5 50       21 $self->{'_MIME'} = $magic if defined $magic;
145 5         19 return $self->{'_MIME'};
146             }
147              
148              
149             sub new {
150 8     8 1 35521 my ( $class, $args ) = @_;
151              
152 8 100 100     80 if ($args and 'HASH' ne ref $args) {
153 1         302 croak( __PACKAGE__, 'Argument to new should be a HASH reference');
154             }
155 7         13 my $query;
156 7         20 my $module = "CGI"; # default module is CGI.pm if for nothing else for backword compatibility
157            
158 7 100 66     65 if ($args and $args->{query}) {
159 3         10 $module = $args->{query};
160             }
161              
162 7 100       423 if (ref $module) { # an object was passed to us
163 1         3 $query = $module;
164 1         3 $module = ref $module;
165             } else { # assuming a name of a module was passed to us
166            
167             # load the requested module
168 6         31 (my $file = $module) =~ s{::}{/}g;
169 6         16 $file .= ".pm";
170 6         11804 require $file;
171              
172              
173 5 50       98506 if ("CGI::Simple" eq $module) {
174 0         0 $CGI::Simple::DISABLE_UPLOADS = 0;
175             }
176 5         42 $query = new $module;
177             }
178            
179 6 50 33     66207 if ($module eq "CGI::Simple" and $CGI::Simple::VERSION < '0.075') {
180 0         0 die "CGI::Simple must be at least version 0.075\n";
181             }
182              
183 6         54 my $self = bless {
184             # '_CACHE' => {},
185             '_CGI' => $query,
186             '_MIME' => ''
187             }, $class;
188 6         33 return $self;
189             }
190              
191              
192             sub query {
193 20     20 1 38 my ( $self ) = @_;
194 20         77 return $self->{'_CGI'};
195             }
196              
197              
198             1;
199              
200              
201             __END__