File Coverage

blib/lib/CGI/Test/Input.pm
Criterion Covered Total %
statement 53 93 56.9
branch 7 16 43.7
condition n/a
subroutine 14 21 66.6
pod 7 10 70.0
total 81 140 57.8


line stmt bran cond sub pod time code
1             #####################################################################
2             #
3             # Copyright (c) 2001, Raphael Manfredi
4             #
5             # You may redistribute only under the terms of the Artistic License,
6             # as specified in the README file that comes with the distribution.
7             #
8              
9             #
10             # Abstract representation of the POST input data, which is a list of incoming
11             # parameters that can be encoded differently.
12             #
13              
14             package CGI::Test::Input;
15              
16 13     13   55 use strict;
  13         12  
  13         334  
17 13     13   43 use warnings;
  13         13  
  13         252  
18 13     13   40 no warnings 'uninitialized';
  13         13  
  13         434  
19              
20 13     13   52 use Carp;
  13         18  
  13         3078  
21              
22             ############################################################
23             #
24             # ->new
25             #
26             # Creation routine
27             #
28             ############################################################
29             sub new
30             {
31 0     0 0 0 confess "deferred";
32             }
33              
34             ############################################################
35             #
36             # ->_init
37             #
38             # Initialization of common attributes
39             #
40             ############################################################
41             sub _init
42             {
43 19     19   32 my $this = shift;
44 19         70 $this->{stale} = 0;
45 19         32 $this->{fields} = []; # list of [name, value]
46 19         39 $this->{files} = []; # list of [name, value, content or undef]
47 19         24 $this->{length} = 0;
48 19         38 $this->{data} = '';
49 19         36 return;
50             }
51              
52             #
53             # Attribute access
54             #
55              
56             ############################################################
57             sub _stale
58             {
59 20     20   230 my $this = shift;
60 20         145 $this->{stale};
61             }
62             ############################################################
63             sub _fields
64             {
65 281     281   213 my $this = shift;
66 281         291 $this->{fields};
67             }
68             ############################################################
69             sub _files
70             {
71 38     38   66 my $this = shift;
72 38         87 $this->{files};
73             }
74             ############################################################
75             sub length
76             {
77 2     2 1 2 my $this = shift;
78 2 100       6 $this->_refresh() if $this->_stale();
79 2         17 $this->{length};
80             }
81             ############################################################
82             sub data
83             {
84 18     18 1 33 my $this = shift;
85 18 50       75 $this->_refresh() if $this->_stale();
86 18         146 $this->{data};
87             }
88              
89             ############################################################
90             #
91             # ->set_raw_data
92             #
93             # Set raw POST data for this input object
94             #
95             ############################################################
96             sub set_raw_data {
97 0     0 0 0 my ($this, $data) = @_;
98              
99 0         0 $this->{data} = $data;
100 13     13   166 $this->{length} = do { use bytes; CORE::length $data };
  13         15  
  13         230  
  0         0  
  0         0  
101 0         0 $this->{stale} = 0;
102              
103 0         0 return $this;
104             }
105              
106             ############################################################
107             #
108             # ->add_widget
109             #
110             # Add new input widget.
111             #
112             # This routine is called to build input data for POST requests issued in
113             # response to a submit button being pressed.
114             #
115             ############################################################
116             sub add_widget
117             {
118 281     281 1 228 my $this = shift;
119 281         192 my ($w) = @_;
120              
121             #
122             # Appart from the fact that file widgets get inserted in a dedicated list,
123             # the processing here is the same. The 3rd value of the entry for files
124             # will be undefined, meaning the file will be read at a later time, when
125             # the input data is built.
126             #
127              
128 281         833 my @tuples = $w->submit_tuples;
129 281 100       764 my $array = $w->is_file ? $this->_files : $this->_fields;
130              
131 281         579 while (my ($name, $value) = splice @tuples, 0, 2)
132             {
133 291 50       354 $value = '' unless defined $value;
134 291         848 push @$array, [ $name, $value ];
135             }
136              
137 281         210 $this->{stale} = 1;
138              
139 281         450 return;
140             }
141              
142             ############################################################
143             #
144             # ->add_field
145             #
146             # Add a new name/value pair to the input data.
147             #
148             # This routine is meant for manual input data building.
149             #
150             ############################################################
151             sub add_field
152             {
153 0     0 1 0 my $this = shift;
154 0         0 my ($name, $value) = @_;
155              
156 0 0       0 $value = '' unless defined $value;
157 0         0 push @{$this->_fields}, [ $name, $value ];
  0         0  
158 0         0 $this->{stale} = 1;
159              
160 0         0 return;
161             }
162              
163             ############################################################
164             #
165             # ->add_file
166             #
167             # Add a new upload-file information to the input data.
168             # The actual reading of the file is deferred up to the moment where we
169             # need to build the input data.
170             #
171             # This routine is meant for manual input data building.
172             #
173             ############################################################
174             sub add_file
175             {
176 0     0 1 0 my $this = shift;
177 0         0 my ($name, $value) = @_;
178              
179 0 0       0 $value = '' unless defined $value;
180 0         0 push @{$this->_files}, [ $name, $value ];
  0         0  
181 0         0 $this->{stale} = 1;
182              
183 0         0 return;
184             }
185              
186             ############################################################
187             #
188             # ->add_file_now
189             #
190             # Add a new upload-file information to the input data.
191             # The file is read immediately, and can be disposed of once we return.
192             #
193             # This routine is meant for manual input data building.
194             #
195             ############################################################
196             sub add_file_now
197             {
198 0     0 1 0 my $this = shift;
199 0         0 my ($name, $value) = @_;
200              
201 0 0       0 croak "unreadable file '$value'" unless -r $value;
202              
203 0         0 local *FILE;
204 0         0 open(FILE, $value);
205 0         0 binmode FILE;
206              
207 0         0 local $_;
208 0         0 my $content = '';
209              
210 0         0 while ()
211             {
212 0         0 $content .= $_;
213             }
214 0         0 close FILE;
215              
216 0         0 push @{$this->_files}, [ $name, $value, $content ];
  0         0  
217 0         0 $this->{stale} = 1;
218              
219 0         0 return;
220             }
221              
222             sub set_mime_type {
223 0     0 0 0 my ($this, $type) = @_;
224              
225 0         0 $this->{mime_type} = $type;
226              
227 0         0 return $this;
228             }
229              
230             #
231             # Interface to be implemented by heirs
232             #
233              
234             ############################################################
235             sub mime_type
236             {
237 17     17 1 29 my ($this) = @_;
238              
239 17         30 my $type = $this->{mime_type};
240              
241 17 50       48 confess "deferred" unless $type;
242              
243 17         57 return $type;
244             }
245              
246             ############################################################
247             sub _build_data
248             {
249 0     0   0 confess "deferred";
250             }
251              
252             #
253             # Internal routines
254             #
255              
256             ############################################################
257             #
258             # ->_refresh
259             #
260             # Recomputes `data' and `length' attributes when stale
261             #
262             ############################################################
263             sub _refresh
264             {
265 19     19   23 my $this = shift;
266              
267             # internal pre-condition
268              
269 19         294 my $data = $this->_build_data; # deferred
270              
271 19         41 $this->{data} = $data;
272 19         25 $this->{length} = CORE::length $data;
273 19         24 $this->{stale} = 0;
274              
275 19         40 return;
276             }
277              
278             1;
279              
280             =head1 NAME
281              
282             CGI::Test::Input - Abstract representation of POST input
283              
284             =head1 SYNOPSIS
285              
286             # Deferred class, only heirs can be created
287             # $input holds a CGI::Test::Input object
288              
289             $input->add_widget($w); # done internally for you
290              
291             $input->add_field("name", "value"); # manual input construction
292             $input->add_file("name", "path"); # deferred reading
293             $input->add_file_now("name", "/tmp/path"); # read file immediately
294              
295             syswrite INPUT, $input->data, $input->length; # if you really have to
296              
297             # $test is a CGI::Test object
298             $test->POST("http://server:70/cgi-bin/script", $input);
299              
300             =head1 DESCRIPTION
301              
302             The C class is deferred. It is an abstract representation
303             of HTTP POST request input, as expected by the C routine of C.
304              
305             Unless you wish to issue a C request manually to provide carefully
306             crafted input, you do not need to learn the interface of this hierarchy,
307             nor even bother knowing about it.
308              
309             Otherwise, you need to decide which MIME encoding you want, and create an
310             object of the appropriate type. Note that file uploading requires the use
311             of the C encoding:
312              
313             MIME Encoding Type to Create
314             --------------------------------- ---------------------------
315             application/x-www-form-urlencoded CGI::Test::Input::URL
316             multipart/form-data CGI::Test::Input::Multipart
317              
318             Once the object is created, you will be able to add name/value tuples
319             corresponding to the CGI parameters to submit.
320              
321             For instance:
322              
323             my $input = CGI::Test::Input::Multipart->new();
324             $input->add_field("login", "ram");
325             $input->add_field("password", "foobar");
326             $input->add_file("organization", "/etc/news/organization");
327              
328             Then, to inspect what is normally sent to the HTTP server:
329              
330             print "Content-Type: ", $input->mime_type, "\015\012";
331             print "Content-Length: ", $input->length, "\015\012";
332             print "\015\012";
333             print $input->data;
334              
335             But usually you'll hand out the $input object to the C routine
336             of C.
337              
338             =head1 INTERFACE
339              
340             =head2 Creation Routine
341              
342             It is called C as usual. All subclasses have
343             the same creation routine signature, which takes no parameter.
344              
345             =head2 Adding Parameters
346              
347             CGI parameter are name/value tuples. In case of file uploads, they can have
348             a content as well, the value being the file path on the client machine.
349              
350             =over 4
351              
352             =item C I, I
353              
354             Adds the CGI parameter I, whose value is I.
355              
356             =item add_file I, I
357              
358             Adds the file upload parameter I, located at I.
359              
360             The file is not read immediately, so it must remain available until
361             the I routine is called, at least. It is not an error if the file
362             cannot be read at that time.
363              
364             When not using the C encoding, only the name/path
365             tuple will be transmitted to the script.
366              
367             =item add_file_now I, I
368              
369             Same as C, but the file is immediately read and can therefore
370             be disposed of afterwards. However, the file B exist.
371              
372             =item add_widget I
373              
374             Add any widget, i.e. a C object. This routine
375             is called internally by C to construct the input data when
376             submiting a form via POST.
377              
378             =back
379              
380             =head2 Generation
381              
382             =over 4
383              
384             =item C
385              
386             Returns the data, under the proper encoding.
387              
388             =item C
389              
390             Returns the proper MIME encoding type, suitable for inclusion within
391             a Content-Type header.
392              
393             =item C
394              
395             Returns the data length.
396              
397             =back
398              
399             =head1 AUTHORS
400              
401             The original author is Raphael Manfredi.
402              
403             Steven Hilton was long time maintainer of this module.
404              
405             Current maintainer is Alexander Tokarev Ftokarev@cpan.orgE>.
406              
407             =head1 SEE ALSO
408              
409             CGI::Test(3), CGI::Test::Input::URL(3), CGI::Test::Input::Multipart(3).
410              
411             =cut
412