File Coverage

blib/lib/CGI/Ex.pm
Criterion Covered Total %
statement 161 319 50.4
branch 76 190 40.0
condition 34 110 30.9
subroutine 24 40 60.0
pod 18 31 58.0
total 313 690 45.3


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.52
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   787 use 5.006;
  6         17  
25 6     6   28 use strict;
  6         8  
  6         442  
26             our $VERSION = '2.52'; # 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   31 use Exporter qw(import);
  6         11  
  6         1984  
35              
36 0         0 BEGIN {
37 6   50 6   60 $PREFERRED_CGI_MODULE ||= 'CGI';
38 6         9 @EXPORT = ();
39 6         21 @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       23 : ($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   83 sub _is_mod_perl_1 () { $v < 1.98 && $v > 0 }
56 6     6   18 sub _is_mod_perl_2 () { $v >= 1.98 }
57              
58             ### cache apache request getter (light if or if not mod_perl)
59 6         8 my $sub;
60 6 50       12 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         21899 $sub = sub {};
73             }
74 13     13 0 20 sub apache_request_sub () { $sub }
75             }
76              
77             ###----------------------------------------------------------------###
78              
79             # my $cgix = CGI::Ex->new;
80             sub new {
81 16   50 16 0 441 my $class = shift || die "Missing class name";
82 16 100       56 my $self = ref($_[0]) ? shift : {@_};
83 16         63 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 17 my $self = shift || die 'Usage: my $query = $cgix_obj->object';
93 6 50       19 $self->{'object'} = shift if $#_ != -1;
94              
95 6 100       17 if (! defined $self->{'object'}) {
96 3   33     11 $PREFERRED_CGI_REQUIRED ||= do {
97 3   33     14 my $file = $self->{'cgi_module'} || $PREFERRED_CGI_MODULE;
98 3         7 $file .= ".pm";
99 3         20 $file =~ s|::|/|g;
100 3         4 eval { require $file };
  3         1589  
101 3 50       54004 die "Couldn't require $PREFERRED_CGI_MODULE: $@" if $@;
102 3         15 1; # return of do
103             };
104 3         73 $self->{'object'} = $PREFERRED_CGI_MODULE->new;
105             }
106              
107 6         905 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 13 my $self = shift || __PACKAGE__->new;
129 6 50       27 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       19 return $self->{'form'} if $self->{'form'};
135              
136             ### get the info out of the object
137 4   66     12 my $obj = shift || $self->object;
138 4         7 my %hash = ();
139             ### this particular use of $cgi->param in list context is safe
140 4         13 local $CGI::LIST_CONTEXT_WARN = 0;
141 4 50       23 my $mp = $obj->can('multi_param') ? 1 : 0;
142 4         10 foreach my $key ($obj->param) {
143 5 50       59 my @val = $mp ? $obj->multi_param($key) : $obj->param($key);
144 5 100       103 $hash{$key} = ($#val <= 0) ? $val[0] : \@val;
145             }
146 4         30 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 3 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 27535 my $self = shift;
161 3 100       9 return $self->set_form(shift) if @_ == 1;
162 2         4 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 745 my $self = shift || die 'Usage: $cgix_obj->make_form(\%form)';
170 2   33     4 my $form = shift || $self->get_form;
171 2 100       7 my $keys = ref($_[0]) ? shift : [sort keys %$form];
172 2         4 my $str = '';
173 2         3 foreach (@$keys) {
174 3         3 my $key = $_; # make a copy
175 3         5 my $val = $form->{$key};
176 3         7 $key =~ s/([^\w.\-\ ])/sprintf('%%%02X', ord $1)/eg;
  0         0  
177 3         4 $key =~ y/ /+/;
178 3 100       8 foreach (ref($val) eq 'ARRAY' ? @$val : $val) {
179 5         16 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         5 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 8 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       18 return $self->{'cookies'} if $self->{'cookies'};
205              
206 2   33     26 my $obj = shift || $self->object;
207 2         8 my %hash = ();
208 2         20 foreach my $key ($obj->cookie) {
209 2         2791 my @val = $obj->cookie($key);
210 2 50       859 $hash{$key} = ($#val == -1) ? "" : ($#val == 0) ? $val[0] : \@val;
    50          
211             }
212 2         2657 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 2 my $self = shift || die 'Usage: $cgix_obj->set_cookies(\%cookies)';
219 1   50     5 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 1833 my $self = shift;
227 3 100       9 return $self->set_cookies(shift) if @_ == 1;
228 2         4 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 22 my $self = shift || die 'Usage: $cgix_obj->apache_request';
238 13 50       22 $self->{'apache_request'} = shift if $#_ != -1;
239              
240 13   33     33 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 2841 my ($self, $type, $charset) = (@_ && ref $_[0]) ? @_ : (undef, @_);
265 10 100       28 $self = __PACKAGE__->new if ! $self;
266              
267 10 100       16 if ($type) {
268 8 50       39 die "Invalid type: $type" if $type !~ m|^[\w\-\.]+/[\w\-\.\+]+$|; # image/vid.x-foo
269             } else {
270 2         4 $type = 'text/html';
271             }
272 10 100 66     34 $type .= "; charset=$charset" if $charset && $charset =~ m|^[\w\-\.\:\+]+$|;
273              
274 10 50       21 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       16 if (! $ENV{'CONTENT_TYPED'}) {
280 10         33 print "Content-Type: $type\r\n\r\n";
281 10         52 $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 5 my $self = shift || __PACKAGE__->new;
292              
293 2 50       3 if (my $r = $self->apache_request) {
294 0         0 return $r->bytes_sent;
295             } else {
296 2 100       7 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->content_type('text/html');
335 0         0 $r->print("Bounced to $html_loc\n");
336 0         0 $r->rflush;
337             }
338              
339             } else {
340 0         0 print "Location: $loc\r\n",
341             "Status: 302 Bounce\r\n",
342             "Content-Type: text/html\r\n\r\n",
343             "Bounced to $html_loc\r\n";
344             }
345             }
346              
347             ### set a cookie nicely - even if we have already sent content
348             ### may be called as function or a method - fancy algo to allow for first argument of args hash
349             # $cgix->set_cookie({name => $name, ...});
350             # $cgix->set_cookie( name => $name, ... );
351             # set_cookie({name => $name, ...});
352             # set_cookie( name => $name, ... );
353             sub set_cookie {
354 2 50   2 1 2607 my $self = UNIVERSAL::isa($_[0], __PACKAGE__) ? shift : __PACKAGE__->new;
355              
356 2 50       6 my $args = ref($_[0]) ? shift : {@_};
357 2         6 foreach (keys %$args) {
358 4 50       11 next if /^-/;
359 4         10 $args->{"-$_"} = delete $args->{$_};
360             }
361              
362             ### default path to / and allow for 1hour instead of 1h
363 2   50     10 $args->{-path} ||= '/';
364 2 50       4 $args->{-expires} = time_calc($args->{-expires}) if $args->{-expires};
365              
366 2         6 my $obj = $self->object;
367 2         8 my $cookie = "" . $obj->cookie(%$args);
368              
369 2 100       617 if ($self->content_typed) {
370 1         5 print "\n";
371             } else {
372 1 50       2 if (my $r = $self->apache_request) {
373 0 0       0 if ($self->is_mod_perl_1) {
374 0         0 $r->header_out("Set-cookie", $cookie);
375             } else {
376 0         0 $r->headers_out->add("Set-Cookie", $cookie);
377             }
378             } else {
379 1         5 print "Set-Cookie: $cookie\r\n";
380             }
381             }
382             }
383              
384             ### print the last modified time
385             ### takes a time or filename and an optional keyname
386             # $cgix->last_modified; # now
387             # $cgix->last_modified((stat $file)[9]); # file's time
388             # $cgix->last_modified(time, 'Expires'); # different header
389             sub last_modified {
390 0   0 0 1 0 my $self = shift || die 'Usage: $cgix_obj->last_modified($time)'; # may be called as function or method
391 0   0     0 my $time = shift || time;
392 0   0     0 my $key = shift || 'Last-Modified';
393              
394             ### get a time string - looks like:
395             ### Mon Dec 9 18:03:21 2002
396             ### valid RFC (although not prefered)
397 0         0 $time = scalar gmtime time_calc($time);
398              
399 0 0       0 if ($self->content_typed) {
    0          
400 0         0 print "\n";
401             } elsif (my $r = $self->apache_request) {
402 0 0       0 if ($self->is_mod_perl_1) {
403 0         0 $r->header_out($key, $time);
404             } else {
405 0         0 $r->headers_out->add($key, $time);
406             }
407             } else {
408 0         0 print "$key: $time\r\n";
409             }
410             }
411              
412             ### add expires header
413             sub expires {
414 0 0   0 1 0 my $self = ref($_[0]) ? shift : __PACKAGE__->new; # may be called as a function or method
415 0   0     0 my $time = shift || time;
416 0         0 return $self->last_modified($time, 'Expires');
417             }
418              
419             ### similar to expires_calc from CGI::Util
420             ### allows for lenient calling, hour instead of just h, etc
421             ### takes time or 0 or now or filename or types of -23minutes
422             sub time_calc {
423 7     7 0 3255 my $time = shift; # may only be called as a function
424 7 100 66     58 if (! $time || lc($time) eq 'now') {
    100          
    100          
425 1         6 return time;
426             } elsif ($time =~ m/^\d+$/) {
427 1         7 return $time;
428             } elsif ($time =~ m/^([+-]?)\s*(\d+|\d*\.\d+)\s*([a-z])[a-z]*$/i) {
429 4         16 my $m = {
430             's' => 1,
431             'm' => 60,
432             'h' => 60 * 60,
433             'd' => 60 * 60 * 24,
434             'w' => 60 * 60 * 24 * 7,
435             'M' => 60 * 60 * 24 * 30,
436             'y' => 60 * 60 * 24 * 365,
437             };
438 4   50     49 return time + ($m->{lc($3)} || 1) * "$1$2";
439             } else {
440 1         18 my @stat = stat $time;
441 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;
442 1         7 return $stat[9];
443             }
444             }
445              
446              
447             ### allow for generic status send
448             sub send_status {
449 0   0 0 1 0 my $self = shift || die 'Usage: $cgix_obj->send_status(302 => "Bounced")';
450 0   0     0 my $code = shift || die "Missing status";
451 0         0 my $mesg = shift;
452 0 0       0 if (! defined $mesg) {
453 0         0 $mesg = "HTTP Status of $code received\n";
454             }
455 0 0       0 if ($self->content_typed) {
456 0         0 die "Cannot send a status ($code - $mesg) after content has been sent";
457             }
458 0 0       0 if (my $r = $self->apache_request) {
459 0         0 $r->status($code);
460 0 0       0 if ($self->is_mod_perl_1) {
461 0         0 $r->content_type('text/html');
462 0         0 $r->send_http_header;
463 0         0 $r->print($mesg);
464             } else {
465 0         0 $r->content_type('text/html');
466 0         0 $r->print($mesg);
467 0         0 $r->rflush;
468             }
469             } else {
470 0         0 print "Status: $code\r\n";
471 0         0 $self->print_content_type;
472 0         0 print $mesg;
473             }
474             }
475              
476             ### allow for sending a simple header
477             sub send_header {
478 0   0 0 1 0 my $self = shift || die 'Usage: $cgix_obj->send_header';
479 0         0 my $key = shift;
480 0         0 my $val = shift;
481 0 0       0 if ($self->content_typed) {
482 0         0 die "Cannot send a header ($key - $val) after content has been sent";
483             }
484 0 0       0 if (my $r = $self->apache_request) {
485 0 0       0 if ($self->is_mod_perl_1) {
486 0         0 $r->header_out($key, $val);
487             } else {
488 0         0 $r->headers_out->add($key, $val);
489             }
490             } else {
491 0         0 print "$key: $val\r\n";
492             }
493             }
494              
495             ###----------------------------------------------------------------###
496              
497             ### allow for printing out a static javascript file
498             ### for example $self->print_js("CGI::Ex::validate.js");
499             sub print_js {
500 0   0 0 1 0 my $self = shift || die 'Usage: $cgix_obj->print_js($js_file)';
501 0   0     0 my $js_file = shift || '';
502 0 0       0 $self = $self->new if ! ref $self;
503              
504             ### fix up the file - force .js on the end
505 0 0 0     0 $js_file .= '.js' if $js_file && $js_file !~ /\.js$/i;
506 0         0 $js_file =~ s|::|/|g;
507              
508             ### get file info
509 0         0 my $stat;
510 0 0 0     0 if ($js_file && $js_file =~ m|^/*(\w+(?:/+\w+)*\.js)$|i) {
511 0         0 foreach my $path (@INC) {
512 0         0 my $_file = "$path/$1";
513 0 0       0 next if ! -f $_file;
514 0         0 $js_file = $_file;
515 0         0 $stat = [stat _];
516 0         0 last;
517             }
518             }
519              
520             ### no file = 404
521 0 0       0 if (! $stat) {
522 0 0       0 if (! $self->content_typed) {
523 0         0 $self->send_status(404, "JS File not found for print_js\n");
524             } else {
525 0         0 print "

JS File not found for print_js

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