File Coverage

blib/lib/CGI/Ex.pm
Criterion Covered Total %
statement 161 318 50.6
branch 76 190 40.0
condition 34 110 30.9
subroutine 24 40 60.0
pod 18 31 58.0
total 313 689 45.4


line stmt bran cond sub pod time code
1             package CGI::Ex;
2              
3             =head1 NAME
4              
5             CGI::Ex - CGI utility suite - makes powerful application writing fun and easy
6              
7             =head1 VERSION
8              
9             version 2.54
10              
11             =for markdown [![master](https://travis-ci.org/ljepson/CGI-Ex.svg?branch=master)](https://travis-ci.org/ljepson/CGI-Ex)
12              
13             =for HTML
14              
15             =cut
16              
17             ###----------------------------------------------------------------###
18             # Copyright - Paul Seamons #
19             # Distributed under the Perl Artistic License without warranty #
20             ###----------------------------------------------------------------###
21              
22             ### See perldoc at bottom
23              
24 6     6   891 use 5.006;
  6         17  
25 6     6   32 use strict;
  6         8  
  6         458  
26             our $VERSION = '2.54'; # VERSION
27              
28             our ($PREFERRED_CGI_MODULE,
29             $PREFERRED_CGI_REQUIRED,
30             $AUTOLOAD,
31             $DEBUG_LOCATION_BOUNCE,
32             @EXPORT, @EXPORT_OK
33             );
34 6     6   33 use Exporter qw(import);
  6         9  
  6         2150  
35              
36 0         0 BEGIN {
37 6   50 6   60 $PREFERRED_CGI_MODULE ||= 'CGI';
38 6         9 @EXPORT = ();
39 6         14 @EXPORT_OK = qw(get_form
40             get_cookies
41             print_content_type
42             content_type
43             content_typed
44             set_cookie
45             location_bounce
46             );
47              
48             ### cache mod_perl version (light if or if not mod_perl)
49             my $v = (! $ENV{'MOD_PERL'}) ? 0
50             # mod_perl/1.27 or mod_perl/1.99_16 or mod_perl/2.0.1
51             # if MOD_PERL is set - don't die if regex fails - just assume 1.0
52 6 0       29 : ($ENV{'MOD_PERL'} =~ m{ ^ mod_perl / (\d+\.[\d_]+) (?: \.\d+)? $ }x) ? $1
    50          
53             : '1.0_0';
54 0     0   0 sub _mod_perl_version () { $v }
55 6 50   6   65 sub _is_mod_perl_1 () { $v < 1.98 && $v > 0 }
56 6     6   22 sub _is_mod_perl_2 () { $v >= 1.98 }
57              
58             ### cache apache request getter (light if or if not mod_perl)
59 6         9 my $sub;
60 6 50       18 if (_is_mod_perl_1) { # old mod_perl
    50          
61 0         0 require Apache;
62 0         0 $sub = sub { Apache->request };
  0         0  
63             } elsif (_is_mod_perl_2) {
64 0 0       0 if (eval { require Apache2::RequestRec }) { # debian style
  0         0  
65 0         0 require Apache2::RequestUtil;
66 0         0 $sub = sub { Apache2::RequestUtil->request };
  0         0  
67             } else { # fedora and mandrake style
68 0         0 require Apache::RequestUtil;
69 0         0 $sub = sub { Apache->request };
  0         0  
70             }
71             } else {
72 6         22442 $sub = sub {};
73             }
74 13     13 0 18 sub apache_request_sub () { $sub }
75             }
76              
77             ###----------------------------------------------------------------###
78              
79             # my $cgix = CGI::Ex->new;
80             sub new {
81 16   50 16 0 541 my $class = shift || die "Missing class name";
82 16 100       44 my $self = ref($_[0]) ? shift : {@_};
83 16         74 return bless $self, $class;
84             }
85              
86             ###----------------------------------------------------------------###
87              
88             ### allow for holding another classed CGI style object
89             # my $query = $cgix->object;
90             # $cgix->object(CGI->new);
91             sub object {
92 6   50 6 1 18 my $self = shift || die 'Usage: my $query = $cgix_obj->object';
93 6 50       23 $self->{'object'} = shift if $#_ != -1;
94              
95 6 100       20 if (! defined $self->{'object'}) {
96 3   33     12 $PREFERRED_CGI_REQUIRED ||= do {
97 3   33     15 my $file = $self->{'cgi_module'} || $PREFERRED_CGI_MODULE;
98 3         5 $file .= ".pm";
99 3         26 $file =~ s|::|/|g;
100 3         7 eval { require $file };
  3         1539  
101 3 50       54380 die "Couldn't require $PREFERRED_CGI_MODULE: $@" if $@;
102 3         12 1; # return of do
103             };
104 3         46 $self->{'object'} = $PREFERRED_CGI_MODULE->new;
105             }
106              
107 6         941 return $self->{'object'};
108             }
109              
110             ### allow for calling CGI MODULE methods
111             sub AUTOLOAD {
112 0     0   0 my $self = shift;
113 0 0       0 my $meth = ($AUTOLOAD =~ /(\w+)$/) ? $1 : die "Invalid method $AUTOLOAD";
114 0         0 return $self->object->$meth(@_);
115             }
116              
117       0     sub DESTROY { }
118              
119             ###----------------------------------------------------------------###
120              
121             ### Form getter that will act like CGI->new->Vars only it will return arrayrefs
122             ### for values that are arrays
123             # my $hash = $cgix->get_form;
124             # my $hash = $cgix->get_form(CGI->new);
125             # my $hash = get_form();
126             # my $hash = get_form(CGI->new);
127             sub get_form {
128 6   33 6 1 16 my $self = shift || __PACKAGE__->new;
129 6 50       34 if (! $self->isa(__PACKAGE__)) { # get_form(CGI->new) syntax
130 0         0 my $obj = $self;
131 0         0 $self = __PACKAGE__->new;
132 0         0 $self->object($obj);
133             }
134 6 100       26 return $self->{'form'} if $self->{'form'};
135              
136             ### get the info out of the object
137 4   66     14 my $obj = shift || $self->object;
138 4         8 my %hash = ();
139             ### this particular use of $cgi->param in list context is safe
140 4         26 local $CGI::LIST_CONTEXT_WARN = 0;
141 4 50       27 my $mp = $obj->can('multi_param') ? 1 : 0;
142 4         13 foreach my $key ($obj->param) {
143 5 50       57 my @val = $mp ? $obj->multi_param($key) : $obj->param($key);
144 5 100       111 $hash{$key} = ($#val <= 0) ? $val[0] : \@val;
145             }
146 4         36 return $self->{'form'} = \%hash;
147             }
148              
149             ### allow for a setter
150             ### $cgix->set_form(\%form);
151             sub set_form {
152 1   50 1 1 4 my $self = shift || die 'Usage: $cgix_obj->set_form(\%form)';
153 1   50     6 return $self->{'form'} = shift || {};
154             }
155              
156             ### Combined get and set form
157             # my $hash = $cgix->form;
158             # $cgix->form(\%form);
159             sub form {
160 3     3 1 28781 my $self = shift;
161 3 100       15 return $self->set_form(shift) if @_ == 1;
162 2         8 return $self->get_form;
163             }
164              
165             ### allow for creating a url encoded key value sequence
166             # my $str = $cgix->make_form(\%form);
167             # my $str = $cgix->make_form(\%form, \@keys_to_include);
168             sub make_form {
169 2   50 2 1 725 my $self = shift || die 'Usage: $cgix_obj->make_form(\%form)';
170 2   33     5 my $form = shift || $self->get_form;
171 2 100       10 my $keys = ref($_[0]) ? shift : [sort keys %$form];
172 2         4 my $str = '';
173 2         5 foreach (@$keys) {
174 3         4 my $key = $_; # make a copy
175 3         5 my $val = $form->{$key};
176 3         6 $key =~ s/([^\w.\-\ ])/sprintf('%%%02X', ord $1)/eg;
  0         0  
177 3         7 $key =~ y/ /+/;
178 3 100       23 foreach (ref($val) eq 'ARRAY' ? @$val : $val) {
179 5         9 my $_val = $_; # make a copy
180 5         7 $_val =~ s/([^\w.\-\ ])/sprintf('%%%02X', ord $1)/eg;
  0         0  
181 5         6 $_val =~ y/ /+/;
182 5         11 $str .= "$key=$_val&"; # intentionally not using join
183             }
184             }
185 2         4 chop $str;
186 2         5 return $str;
187             }
188              
189             ###----------------------------------------------------------------###
190              
191             ### like get_form - but a hashref of cookies
192             ### cookies are parsed depending upon the functionality of ->cookie
193             # my $hash = $cgix->get_cookies;
194             # my $hash = $cgix->get_cookies(CGI->new);
195             # my $hash = get_cookies();
196             # my $hash = get_cookies(CGI->new);
197             sub get_cookies {
198 3   33 3 1 11 my $self = shift || __PACKAGE__->new;
199 3 50       15 if (! $self->isa(__PACKAGE__)) { # get_cookies(CGI->new) syntax
200 0         0 my $obj = $self;
201 0         0 $self = __PACKAGE__->new;
202 0         0 $self->object($obj);
203             }
204 3 100       10 return $self->{'cookies'} if $self->{'cookies'};
205              
206 2   33     40 my $obj = shift || $self->object;
207 2         10 my %hash = ();
208 2         10 foreach my $key ($obj->cookie) {
209 2         3147 my @val = $obj->cookie($key);
210 2 50       863 $hash{$key} = ($#val == -1) ? "" : ($#val == 0) ? $val[0] : \@val;
    50          
211             }
212 2         2515 return $self->{'cookies'} = \%hash;
213             }
214              
215             ### Allow for a setter
216             ### $cgix->set_cookies(\%cookies);
217             sub set_cookies {
218 1   50 1 1 3 my $self = shift || die 'Usage: $cgix_obj->set_cookies(\%cookies)';
219 1   50     7 return $self->{'cookies'} = shift || {};
220             }
221              
222             ### Combined get and set cookies
223             # my $hash = $cgix->cookies;
224             # $cgix->cookies(\%cookies);
225             sub cookies {
226 3     3 0 1982 my $self = shift;
227 3 100       12 return $self->set_cookies(shift) if @_ == 1;
228 2         7 return $self->get_cookies;
229             }
230              
231             ###----------------------------------------------------------------###
232              
233             ### Allow for shared apache request object
234             # my $r = $cgix->apache_request
235             # $cgix->apache_request($r);
236             sub apache_request {
237 13   50 13 0 27 my $self = shift || die 'Usage: $cgix_obj->apache_request';
238 13 50       26 $self->{'apache_request'} = shift if $#_ != -1;
239              
240 13   33     35 return $self->{'apache_request'} ||= apache_request_sub()->();
241             }
242              
243             ### Get the version of mod_perl running (0 if not mod_perl)
244             # my $version = $cgix->mod_perl_version;
245 0     0 0 0 sub mod_perl_version { _mod_perl_version }
246 0     0 0 0 sub is_mod_perl_1 { _is_mod_perl_1 }
247 0     0 0 0 sub is_mod_perl_2 { _is_mod_perl_2 }
248              
249             ### Allow for a setter
250             # $cgix->set_apache_request($r)
251 0     0 0 0 sub set_apache_request { shift->apache_request(shift) }
252              
253             ###----------------------------------------------------------------###
254              
255             ### same signature as print_content_type
256 0     0 1 0 sub content_type { &print_content_type }
257              
258             ### will send the Content-type header
259             # $cgix->print_content_type;
260             # $cgix->print_content_type('text/plain');
261             # print_content_type();
262             # print_content_type('text/plain);
263             sub print_content_type {
264 10 100 100 10 0 2926 my ($self, $type, $charset) = (@_ && ref $_[0]) ? @_ : (undef, @_);
265 10 100       29 $self = __PACKAGE__->new if ! $self;
266              
267 10 100       13 if ($type) {
268 8 50       41 die "Invalid type: $type" if $type !~ m|^[\w\-\.]+/[\w\-\.\+]+$|; # image/vid.x-foo
269             } else {
270 2         3 $type = 'text/html';
271             }
272 10 100 66     28 $type .= "; charset=$charset" if $charset && $charset =~ m|^[\w\-\.\:\+]+$|;
273              
274 10 50       14 if (my $r = $self->apache_request) {
275 0 0       0 return if $r->bytes_sent;
276 0         0 $r->content_type($type);
277 0 0       0 $r->send_http_header if $self->is_mod_perl_1;
278             } else {
279 10 50       15 if (! $ENV{'CONTENT_TYPED'}) {
280 10         49 print "Content-Type: $type\r\n\r\n";
281 10         58 $ENV{'CONTENT_TYPED'} = '';
282             }
283 10         67 $ENV{'CONTENT_TYPED'} .= sprintf("%s, %d\n", (caller)[1,2]);
284             }
285             }
286              
287             ### Boolean check if content has been typed
288             # $cgix->content_typed;
289             # content_typed();
290             sub content_typed {
291 2   33 2 0 6 my $self = shift || __PACKAGE__->new;
292              
293 2 50       4 if (my $r = $self->apache_request) {
294 0         0 return $r->bytes_sent;
295             } else {
296 2 100       9 return $ENV{'CONTENT_TYPED'} ? 1 : undef;
297             }
298             }
299              
300             ###----------------------------------------------------------------###
301              
302             ### location bounce nicely - even if we have already sent content
303             ### may be called as function or a method
304             # $cgix->location_bounce($url);
305             # location_bounce($url);
306             sub location_bounce {
307 0 0   0 1 0 my ($self, $loc) = ($#_ == 1) ? (@_) : (undef, shift);
308 0 0       0 $self = __PACKAGE__->new if ! $self;
309 0 0       0 $loc =~ s{(\s)}{sprintf("%%%02X", ord $1)}xge if $loc;
  0         0  
310 0         0 my $html_loc = $loc;
311 0 0       0 if ($html_loc) {
312 0         0 $html_loc =~ s/&/&/g;
313 0         0 $html_loc =~ s/
314 0         0 $html_loc =~ s/>/>/g;
315 0         0 $html_loc =~ s/\"/"/g;
316             }
317              
318 0 0       0 if ($self->content_typed) {
    0          
319 0 0       0 if ($DEBUG_LOCATION_BOUNCE) {
320 0         0 print "Location: $html_loc
\n";
321             } else {
322 0         0 print "\n";
323             }
324              
325             } elsif (my $r = $self->apache_request) {
326 0         0 $r->status(302);
327 0 0       0 if ($self->is_mod_perl_1) {
328 0         0 $r->header_out("Location", $loc);
329 0         0 $r->content_type('text/html');
330 0         0 $r->send_http_header;
331 0         0 $r->print("Bounced to $html_loc\n");
332             } else {
333 0         0 $r->headers_out->add("Location", $loc);
334 0         0 $r->rflush;
335 0         0 $r->custom_response(302, "Bounced to $html_loc\n");
336             }
337              
338             } else {
339 0         0 print "Location: $loc\r\n",
340             "Status: 302 Bounce\r\n",
341             "Content-Type: text/html\r\n\r\n",
342             "Bounced to $html_loc\r\n";
343             }
344             }
345              
346             ### set a cookie nicely - even if we have already sent content
347             ### may be called as function or a method - fancy algo to allow for first argument of args hash
348             # $cgix->set_cookie({name => $name, ...});
349             # $cgix->set_cookie( name => $name, ... );
350             # set_cookie({name => $name, ...});
351             # set_cookie( name => $name, ... );
352             sub set_cookie {
353 2 50   2 1 3020 my $self = UNIVERSAL::isa($_[0], __PACKAGE__) ? shift : __PACKAGE__->new;
354              
355 2 50       8 my $args = ref($_[0]) ? shift : {@_};
356 2         8 foreach (keys %$args) {
357 4 50       10 next if /^-/;
358 4         11 $args->{"-$_"} = delete $args->{$_};
359             }
360              
361             ### default path to / and allow for 1hour instead of 1h
362 2   50     14 $args->{-path} ||= '/';
363 2 50       3 $args->{-expires} = time_calc($args->{-expires}) if $args->{-expires};
364              
365 2         6 my $obj = $self->object;
366 2         9 my $cookie = "" . $obj->cookie(%$args);
367              
368 2 100       649 if ($self->content_typed) {
369 1         5 print "\n";
370             } else {
371 1 50       2 if (my $r = $self->apache_request) {
372 0 0       0 if ($self->is_mod_perl_1) {
373 0         0 $r->header_out("Set-cookie", $cookie);
374             } else {
375 0         0 $r->headers_out->add("Set-Cookie", $cookie);
376             }
377             } else {
378 1         6 print "Set-Cookie: $cookie\r\n";
379             }
380             }
381             }
382              
383             ### print the last modified time
384             ### takes a time or filename and an optional keyname
385             # $cgix->last_modified; # now
386             # $cgix->last_modified((stat $file)[9]); # file's time
387             # $cgix->last_modified(time, 'Expires'); # different header
388             sub last_modified {
389 0   0 0 1 0 my $self = shift || die 'Usage: $cgix_obj->last_modified($time)'; # may be called as function or method
390 0   0     0 my $time = shift || time;
391 0   0     0 my $key = shift || 'Last-Modified';
392              
393             ### get a time string - looks like:
394             ### Mon Dec 9 18:03:21 2002
395             ### valid RFC (although not prefered)
396 0         0 $time = scalar gmtime time_calc($time);
397              
398 0 0       0 if ($self->content_typed) {
    0          
399 0         0 print "\n";
400             } elsif (my $r = $self->apache_request) {
401 0 0       0 if ($self->is_mod_perl_1) {
402 0         0 $r->header_out($key, $time);
403             } else {
404 0         0 $r->headers_out->add($key, $time);
405             }
406             } else {
407 0         0 print "$key: $time\r\n";
408             }
409             }
410              
411             ### add expires header
412             sub expires {
413 0 0   0 1 0 my $self = ref($_[0]) ? shift : __PACKAGE__->new; # may be called as a function or method
414 0   0     0 my $time = shift || time;
415 0         0 return $self->last_modified($time, 'Expires');
416             }
417              
418             ### similar to expires_calc from CGI::Util
419             ### allows for lenient calling, hour instead of just h, etc
420             ### takes time or 0 or now or filename or types of -23minutes
421             sub time_calc {
422 7     7 0 3328 my $time = shift; # may only be called as a function
423 7 100 66     63 if (! $time || lc($time) eq 'now') {
    100          
    100          
424 1         7 return time;
425             } elsif ($time =~ m/^\d+$/) {
426 1         6 return $time;
427             } elsif ($time =~ m/^([+-]?)\s*(\d+|\d*\.\d+)\s*([a-z])[a-z]*$/i) {
428 4         17 my $m = {
429             's' => 1,
430             'm' => 60,
431             'h' => 60 * 60,
432             'd' => 60 * 60 * 24,
433             'w' => 60 * 60 * 24 * 7,
434             'M' => 60 * 60 * 24 * 30,
435             'y' => 60 * 60 * 24 * 365,
436             };
437 4   50     43 return time + ($m->{lc($3)} || 1) * "$1$2";
438             } else {
439 1         35 my @stat = stat $time;
440 1 50       5 die "Could not find file \"$time\" for time_calc. You should pass one of \"now\", time(), \"[+-] \\d+ [smhdwMy]\" or a filename." if $#stat == -1;
441 1         7 return $stat[9];
442             }
443             }
444              
445              
446             ### allow for generic status send
447             sub send_status {
448 0   0 0 1 0 my $self = shift || die 'Usage: $cgix_obj->send_status(302 => "Bounced")';
449 0   0     0 my $code = shift || die "Missing status";
450 0         0 my $mesg = shift;
451 0 0       0 if (! defined $mesg) {
452 0         0 $mesg = "HTTP Status of $code received\n";
453             }
454 0 0       0 if ($self->content_typed) {
455 0         0 die "Cannot send a status ($code - $mesg) after content has been sent";
456             }
457 0 0       0 if (my $r = $self->apache_request) {
458 0         0 $r->status($code);
459 0 0       0 if ($self->is_mod_perl_1) {
460 0         0 $r->content_type('text/html');
461 0         0 $r->send_http_header;
462 0         0 $r->print($mesg);
463             } else {
464 0         0 $r->content_type('text/html');
465 0         0 $r->print($mesg);
466 0         0 $r->rflush;
467             }
468             } else {
469 0         0 print "Status: $code\r\n";
470 0         0 $self->print_content_type;
471 0         0 print $mesg;
472             }
473             }
474              
475             ### allow for sending a simple header
476             sub send_header {
477 0   0 0 1 0 my $self = shift || die 'Usage: $cgix_obj->send_header';
478 0         0 my $key = shift;
479 0         0 my $val = shift;
480 0 0       0 if ($self->content_typed) {
481 0         0 die "Cannot send a header ($key - $val) after content has been sent";
482             }
483 0 0       0 if (my $r = $self->apache_request) {
484 0 0       0 if ($self->is_mod_perl_1) {
485 0         0 $r->header_out($key, $val);
486             } else {
487 0         0 $r->headers_out->add($key, $val);
488             }
489             } else {
490 0         0 print "$key: $val\r\n";
491             }
492             }
493              
494             ###----------------------------------------------------------------###
495              
496             ### allow for printing out a static javascript file
497             ### for example $self->print_js("CGI::Ex::validate.js");
498             sub print_js {
499 0   0 0 1 0 my $self = shift || die 'Usage: $cgix_obj->print_js($js_file)';
500 0   0     0 my $js_file = shift || '';
501 0 0       0 $self = $self->new if ! ref $self;
502              
503             ### fix up the file - force .js on the end
504 0 0 0     0 $js_file .= '.js' if $js_file && $js_file !~ /\.js$/i;
505 0         0 $js_file =~ s|::|/|g;
506              
507             ### get file info
508 0         0 my $stat;
509 0 0 0     0 if ($js_file && $js_file =~ m|^/*(\w+(?:/+\w+)*\.js)$|i) {
510 0         0 foreach my $path (@INC) {
511 0         0 my $_file = "$path/$1";
512 0 0       0 next if ! -f $_file;
513 0         0 $js_file = $_file;
514 0         0 $stat = [stat _];
515 0         0 last;
516             }
517             }
518              
519             ### no file = 404
520 0 0       0 if (! $stat) {
521 0 0       0 if (! $self->content_typed) {
522 0         0 $self->send_status(404, "JS File not found for print_js\n");
523             } else {
524 0         0 print "

JS File not found for print_js

\n";
525             }
526 0         0 return;
527             }
528              
529             ### do headers
530 0 0       0 if (! $self->content_typed) {
531 0         0 $self->last_modified($stat->[9]);
532 0         0 $self->expires('+ 1 year');
533 0         0 $self->print_content_type('application/x-javascript');
534             }
535              
536 0 0 0     0 return if $ENV{'REQUEST_METHOD'} && $ENV{'REQUEST_METHOD'} eq 'HEAD';
537              
538             ### send the contents
539 0         0 local *FH;
540 0 0       0 open(FH, "<$js_file") || die "Couldn't open file $js_file: $!";
541 0         0 local $/ = undef;
542 0         0 print ;
543 0         0 close FH;
544             }
545              
546             ###----------------------------------------------------------------###
547              
548             ### form filler that will use either HTML::FillInForm, CGI::Ex::Fill
549             ### or another specified filler. Argument style is similar to
550             ### HTML::FillInForm. May be called as a method or a function.
551             sub fill {
552 10     10 1 2862 my $self = shift;
553 10         13 my $args = shift;
554 10 50       28 if (ref($args)) {
555 0 0       0 if (! UNIVERSAL::isa($args, 'HASH')) {
556 0         0 $args = {text => $args};
557 0         0 @$args{'form','target','fill_password','ignore_fields'} = @_;
558             }
559             } else {
560 10         28 $args = {$args, @_};
561             }
562              
563 10   50     35 my $module = $self->{'fill_module'} || 'CGI::Ex::Fill';
564              
565             ### allow for using the standard HTML::FillInForm
566             ### too bad it won't modify our file in place for us
567 10 50       19 if ($module eq 'HTML::FillInForm') {
568 0         0 eval { require HTML::FillInForm };
  0         0  
569 0 0       0 if ($@) {
570 0         0 die "Couldn't require HTML::FillInForm: $@";
571             }
572 0 0       0 $args->{scalarref} = $args->{text} if $args->{text};
573 0 0       0 $args->{fdat} = $args->{form} if $args->{form};
574 0         0 my $filled = HTML::FillInForm->new->fill(%$args);
575 0 0       0 if ($args->{text}) {
576 0         0 my $ref = $args->{text};
577 0         0 $$ref = $filled;
578 0         0 return 1;
579             }
580 0         0 return $filled;
581              
582             } else {
583 10         724 require CGI::Ex::Fill;
584              
585             ### get the text to work on
586 10         15 my $ref;
587 10 100       27 if ($args->{text}) { # preferred method - gets modified in place
    100          
    50          
    0          
588 1         2 $ref = $args->{text};
589             } elsif ($args->{scalarref}) { # copy to mimic HTML::FillInForm
590 8         9 my $str = ${ $args->{scalarref} };
  8         13  
591 8         35 $ref = \$str;
592             } elsif ($args->{arrayref}) { # joined together (copy)
593 1         2 my $str = join "", @{ $args->{arrayref} };
  1         5  
594 1         2 $ref = \$str;
595             } elsif ($args->{file}) { # read it in
596 0 0       0 open (IN, $args->{file}) || die "Couldn't open $args->{file}: $!";
597 0         0 my $str = '';
598 0 0       0 read(IN, $str, -s _) || die "Couldn't read $args->{file}: $!";
599 0         0 close IN;
600 0         0 $ref = \$str;
601             } else {
602 0         0 die "No suitable text found for fill.";
603             }
604              
605             ### allow for data to be passed many ways
606             my $form = $args->{form} || $args->{fobject}
607 10   0     32 || $args->{fdat} || $self->object;
608              
609             CGI::Ex::Fill::form_fill($ref,
610             $form,
611             $args->{target},
612             $args->{fill_password},
613             $args->{ignore_fields},
614 10         37 );
615 10 100       62 return ! $args->{text} ? $$ref : 1;
616             }
617              
618             }
619              
620             ###----------------------------------------------------------------###
621              
622             sub validate {
623 2   50 2 1 890 my $self = shift || die 'Usage: my $er = $cgix_obj->validate($form, $val_hash_or_file)';
624 2 50       9 my ($form, $file) = (@_ == 2) ? (shift, shift) : ($self->object, shift);
625              
626 2         723 require CGI::Ex::Validate;
627              
628 2         5 my $args = {};
629 2 50       8 $args->{raise_error} = 1 if $self->{raise_error};
630 2         11 return CGI::Ex::Validate->new($args)->validate($form, $file);
631             }
632              
633             ###----------------------------------------------------------------###
634              
635             sub conf_obj {
636 0   0 0 0 0 my $self = shift || die 'Usage: my $ob = $cgix_obj->conf_obj($args)';
637 0   0     0 return $self->{conf_obj} ||= do {
638 0         0 require CGI::Ex::Conf;
639 0         0 CGI::Ex::Conf->new(@_);
640             };
641             }
642              
643             sub conf_read {
644 0   0 0 0 0 my $self = shift || die 'Usage: my $conf = $cgix_obj->conf_read($file)';
645 0         0 return $self->conf_obj->read(@_);
646             }
647              
648             ###----------------------------------------------------------------###
649              
650             sub swap_template {
651 2   50 2 1 1096 my $self = shift || die 'Usage: my $out = $cgix_obj->swap_template($file, \%vars, $template_args)';
652 2         4 my $str = shift;
653 2         3 my $form = shift;
654 2   50     6 my $args = shift || {};
655 2 50 33     7 $form = $self if ! $form && ref($self);
656 2 50       8 $form = $self->get_form if UNIVERSAL::isa($form, __PACKAGE__);
657              
658 2 100       7 my ($ref, $return) = ref($str) ? ($str, 0) : (\$str, 1);
659              
660             ### look up the module
661 2   50     10 my $module = $self->{'template_module'} || 'CGI::Ex::Template';
662 2         6 my $pkg = "$module.pm";
663 2         17 $pkg =~ s|::|/|g;
664 2         592 require $pkg;
665              
666             ### swap it
667 2         6 my $out = '';
668 2         12 $module->new($args)->process($ref, $form, \$out);
669              
670 2 100       25334 if (! $return) {
671 1         3 $$ref = $out;
672 1         3 return 1;
673             } else {
674 1         7 return $out;
675             }
676             }
677              
678             ###----------------------------------------------------------------###
679              
680             1;
681              
682             __END__