File Coverage

blib/lib/CGI/Utils.pm
Criterion Covered Total %
statement 134 759 17.6
branch 34 348 9.7
condition 15 125 12.0
subroutine 27 86 31.4
pod 38 42 90.4
total 248 1360 18.2


line stmt bran cond sub pod time code
1             # -*-perl-*-
2             # Creation date: 2003-08-13 20:23:50
3             # Authors: Don
4             # Change log:
5             # $Id: Utils.pm,v 1.73 2008/11/13 03:56:46 don Exp $
6              
7             # Copyright (c) 2003-2008 Don Owens
8              
9             # All rights reserved. This program is free software; you can
10             # redistribute it and/or modify it under the same terms as Perl
11             # itself.
12              
13             =pod
14              
15             =head1 NAME
16              
17             CGI::Utils - Utilities for retrieving information through the
18             Common Gateway Interface
19              
20             =head1 SYNOPSIS
21              
22             use CGI::Utils;
23             my $utils = CGI::Utils->new;
24              
25             my $fields = $utils->vars; # or $utils->Vars
26             my $field1 = $$fields{field1};
27              
28             or
29              
30             my $field1 = $utils->param('field1');
31              
32              
33             # File uploads
34             my $file_handle = $utils->param('file0'); # or $$fields{file0};
35             my $file_name = "$file_handle";
36              
37             =head1 DESCRIPTION
38              
39             This module can be used almost as a drop-in replacement for
40             CGI.pm for those of you who do not use the HTML generating
41             features of CGI.pm
42              
43             This module provides an object-oriented interface for retrieving
44             information provided by the Common Gateway Interface, as well as
45             url-encoding and decoding values, and parsing CGI
46             parameters. For example, CGI has a utility for escaping HTML,
47             but no public interface for url-encoding a value or for taking a
48             hash of values and returning a url-encoded query string suitable
49             for passing to a CGI script. This module does that, as well as
50             provide methods for creating a self-referencing url, converting
51             relative urls to absolute, adding CGI parameters to the end of a
52             url, etc. Please see the METHODS section below for more
53             detailed descriptions of functionality provided by this module.
54              
55             File uploads via the multipart/form-data encoding are supported.
56             The parameter for the field name corresponding to the file is a
57             file handle that, when evaluated in string context, returns the
58             name of the file uploaded. To get the contents of the file,
59             just read from the file handle.
60              
61             mod_perl is supported if a value for apache_request is passed to
62             new(), or if the apache request object is available via
63             Apache->request, or if running under HTML::Mason. See the
64             documentation for the new() method for details.
65              
66             If not running in a mod_perl or CGI environment, @ARGV will be
67             searched for key/value pairs in the format
68              
69             key1=val1 key2=val2
70              
71             If all command-line arguments are in this format, the key/value
72             pairs will be available as if they were passed via a CGI or
73             mod_perl interface.
74              
75             =head1 METHODS
76              
77             =cut
78              
79             # TODO
80             # modify CGI::Utils::UploadFile to use hidden attributes instead of making up class names
81             # cache values like parsed cookies
82             # NPH stuff for getHeader()
83              
84 6     6   64467 use strict;
  6         13  
  6         389  
85              
86             { package CGI::Utils;
87              
88 6     6   32 use vars qw($VERSION @ISA @EXPORT_OK @EXPORT %EXPORT_TAGS $AUTOLOAD);
  6         1890  
  6         577  
89              
90 6     6   6557 use CGI::Utils::UploadFile;
  6         20  
  6         493  
91            
92             BEGIN {
93 6     6   15 $VERSION = '0.12'; # update below in POD as well
94              
95 6         25 local($SIG{__DIE__});
96 6 50 33     202 if (defined($ENV{MOD_PERL}) and $ENV{MOD_PERL} ne '') {
97 0         0 eval q{
98             use mod_perl;
99             $CGI::Utils::MP2 = $mod_perl::VERSION >= 1.99;
100             if (defined($CGI::Utils::MP2)) {
101             if ($CGI::Utils::MP2) {
102             require Apache2::Const;
103             require Apache2::RequestUtil;
104             }
105             else {
106             require Apache::Constants;
107             }
108             $CGI::Utils::Loaded_Apache_Constants = 1;
109             }
110             };
111             }
112             }
113              
114 6     6   42 use constant MP2 => $CGI::Utils::MP2;
  6         10  
  6         9772  
115            
116             require Exporter;
117             @ISA = 'Exporter';
118             @EXPORT = ();
119             @EXPORT_OK = qw(urlEncode urlDecode urlEncodeVars urlDecodeVars getSelfRefHostUrl
120             getSelfRefUrl getSelfRefUrlWithQuery getSelfRefUrlDir addParamsToUrl
121             getParsedCookies escapeHtml escapeHtmlFormValue convertRelativeUrlWithParams
122             convertRelativeUrlWithArgs getSelfRefUri);
123             $EXPORT_TAGS{all_utils} = [ qw(urlEncode urlDecode urlEncodeVars urlDecodeVars
124             getSelfRefHostUrl
125             getSelfRefUrl getSelfRefUrlWithQuery getSelfRefUrlDir
126             addParamsToUrl getParsedCookies escapeHtml escapeHtmlFormValue
127             convertRelativeUrlWithParams convertRelativeUrlWithArgs
128             getSelfRefUri)
129             ];
130              
131             =pod
132              
133             =head2 new(\%params)
134              
135             Returns a new CGI::Utils object. Parameters are optional.
136             CGI::Utils supports mod_perl if the Apache request object is
137             passed as $params{apache_request}, or if it is available via
138             Apache->request (or Apache2::RequestUtil->request), or if running
139             under HTML::Mason.
140              
141             You may also pass max_post_size in %params.
142              
143             =cut
144             sub new {
145 3     3 1 90 my ($proto, $args) = @_;
146 3 50       17 $args = {} unless ref($args) eq 'HASH';
147 3         33 my $self = { _params => {}, _param_order => [], _upload_info => {},
148             _max_post_size => $$args{max_post_size},
149             _apache_request => $$args{apache_request},
150             _mason => $$args{mason},
151             };
152 3   33     35 bless $self, ref($proto) || $proto;
153 3         18 return $self;
154             }
155              
156             # added for v0.07
157             sub _getApacheRequest {
158 0     0   0 my ($self) = @_;
159 0         0 my $r;
160 0 0       0 $r = $self->{_apache_request} if ref($self);
161 0 0       0 return $r if $r;
162              
163 0 0       0 if ($ENV{MOD_PERL}) {
164 0 0       0 if ($self->_getMasonObject) {
    0          
165             # we're running under mason
166 0         0 return $self->_getApacheRequestFromMason;
167             } elsif (defined($mod_perl::VERSION)) {
168 0         0 if (MP2) {
169             $r = Apache2::RequestUtil->request;
170             }
171             else {
172 0         0 $r = Apache->request;
173             }
174 0 0       0 return $r if $r;
175             }
176             }
177              
178 0         0 return;
179             }
180              
181             sub _getModPerlVersion {
182 0 0   0   0 if (defined($mod_perl::VERSION)) {
183 0 0       0 if ($mod_perl::VERSION >= 1.99) {
184 0         0 return 2;
185             } else {
186 0         0 return 1;
187             }
188             } else {
189 0         0 return undef;
190             }
191             }
192              
193             sub _isModPerl {
194 41 50 33 41   107 if ($ENV{MOD_PERL} and defined $mod_perl::VERSION) {
195 0         0 return 1;
196             }
197 41         120 return undef;
198             }
199            
200             # added for v0.07
201             sub _getMasonObject {
202 0     0   0 my $self = shift;
203 0 0       0 if (defined ${'HTML::Mason::Commands::m'}) {
  0         0  
204 0         0 return $HTML::Mason::Commands::m; #; fix parsing bug in cperl
205             }
206 0         0 return undef;
207             }
208              
209             # added for v0.07
210             sub _getMasonArgs {
211 0     0   0 my $self = shift;
212 0         0 my $m = $self->_getMasonObject;
213 0 0       0 if ($m) {
214 0         0 return $m->request_args;
215             }
216 0         0 return undef;
217             }
218              
219             # added for v0.07
220             sub _getApacheRequestFromMason {
221 0     0   0 my ($self) = @_;
222 0 0       0 if (defined ${'HTML::Mason::Commands::r'}) {
  0         0  
223 0         0 return $HTML::Mason::Commands::r; #; fix parsing bug in cperl
224             }
225 0         0 return undef;
226             }
227            
228             # added for v0.07
229             sub _isCgi {
230 39 50   39   81 if ($ENV{GATEWAY_INTERFACE}
231             # and $ENV{GATEWAY_INTERFACE} !~ /perl/i # don't count cgi env vars under mod_perl
232             ) {
233 39         87 return 1;
234             }
235 0         0 return undef;
236             }
237              
238             # added for v0.07
239             sub _fromCgiOrModPerl {
240 30     30   40 my ($self, $apache_request_method, $cgi_env_var) = @_;
241 30 50       54 if ($self->_isModPerl) {
    50          
242 0         0 my $r = $self->_getApacheRequest;
243 0 0       0 return $r->$apache_request_method() if $r;
244             } elsif ($self->_isCgi) {
245 30         95 return $ENV{$cgi_env_var};
246             }
247 0         0 return undef;
248             }
249              
250             # added for v0.07
251             sub _fromCgiOrModPerlConnection {
252 0     0   0 my ($self, $apache_connection_method, $cgi_env_var) = @_;
253 0 0       0 if ($self->_isModPerl) {
    0          
254 0         0 my $r = $self->_getApacheRequest;
255 0 0       0 if ($r) {
256 0         0 my $c = $r->connection;
257 0         0 return $c->$apache_connection_method();
258             }
259             } elsif ($self->_isCgi) {
260 0         0 return $ENV{$cgi_env_var};
261             }
262 0         0 return undef;
263             }
264              
265             # added for v0.07
266             sub _getHttpHeader {
267 0     0   0 my $self = shift;
268 0         0 my $header = shift;
269 0 0       0 if ($self->_isModPerl) {
    0          
270 0         0 my $r = $self->_getApacheRequest;
271 0 0       0 if ($r) {
272 0         0 return $r->headers_in()->{$header};
273             }
274             } elsif ($self->_isCgi) {
275 0         0 $header =~ s/-/_/g;
276 0         0 return $ENV{'HTTP_' . uc($header)};
277             }
278 0         0 return undef;
279             }
280              
281             =pod
282              
283             =head2 urlEncode($str)
284              
285             Returns the fully URL-encoded version of the given string. It
286             does not convert space characters to '+' characters.
287              
288             Aliases: url_encode()
289              
290             =cut
291             BEGIN {
292 6 50   6   36 if ($] >= 5.006) {
293 6     6 1 542 eval q{
  6     46   8504  
  6         205  
  6         32  
  46         1860  
  46         86  
  11         53  
  46         176  
294             sub urlEncode {
295             my ($self, $str) = @_;
296            
297             use bytes;
298             $str =~ s{([^A-Za-z0-9_])}{sprintf("%%%02x", ord($1))}eg;
299             return $str;
300             }
301             *url_encode = \&urlEncode;
302             };
303             } else {
304 0         0 eval q{
305             sub urlEncode {
306             my ($self, $str) = @_;
307              
308             $str =~ s{([^A-Za-z0-9_])}{sprintf("%%%02x", ord($1))}eg;
309             return $str;
310             }
311             *url_encode = \&urlEncode;
312             };
313             }
314             }
315              
316             =pod
317              
318             =head2 urlUnicodeEncode($str)
319              
320             Returns the fully URL-encoded version of the given string as
321             unicode characters. It does not convert space characters to '+'
322             characters.
323              
324             Aliases: url_unicode_encode()
325              
326             =cut
327             sub urlUnicodeEncode {
328 0     0 1 0 my ($self, $str) = @_;
329 0         0 $str =~ s{([^A-Za-z0-9_])}{sprintf("%%u%04x", ord($1))}eg;
  0         0  
330 0         0 return $str;
331             }
332             *url_unicode_encode = \&urlUnicodeEncode;
333              
334             =pod
335              
336             =head2 urlDecode($url_encoded_str)
337              
338             Returns the decoded version of the given URL-encoded string.
339              
340             Aliases: url_decode()
341              
342             =cut
343             sub urlDecode {
344 23     23 1 41 my ($self, $str) = @_;
345 23         35 $str =~ tr/+/ /;
346 23         42 $str =~ s|%([A-Fa-f0-9]{2})|chr(hex($1))|eg;
  4         21  
347 23         72 return $str;
348             }
349             *url_decode = \&urlDecode;
350              
351             =pod
352              
353             =head2 urlUnicodeDecode($url_encoded_str)
354              
355             Returns the decoded version of the given URL-encoded string,
356             with unicode support.
357              
358             Aliases: url_unicode_decode()
359              
360             =cut
361             sub urlUnicodeDecode {
362 0     0 1 0 my ($self, $str) = @_;
363 0         0 $str =~ tr/+/ /;
364 0         0 $str =~ s|%([A-Fa-f0-9]{2})|chr(hex($1))|eg;
  0         0  
365 0         0 $str =~ s|%u([A-Fa-f0-9]{2,4})|chr(hex($1))|eg;
  0         0  
366 0         0 return $str;
367             }
368             *url_unicode_decode = \&urlUnicodeDecode;
369              
370             =pod
371              
372             =head2 urlEncodeVars($var_hash, $sep)
373              
374             Takes a hash of name/value pairs and returns a fully URL-encoded
375             query string suitable for passing in a URL. By default, uses
376             the newer separator, a semicolon, as recommended by the W3C. If
377             you pass in a second argument, it is used as the separator
378             between key/value pairs.
379              
380             Aliases: url_encode_vars()
381              
382             =cut
383             sub urlEncodeVars {
384 11     11 1 250 my ($self, $var_hash, $sep) = @_;
385 11 100       35 $sep = ';' unless defined $sep;
386 11         13 my @pairs;
387 11         47 foreach my $key (sort keys %$var_hash) {
388 21         31 my $val = $$var_hash{$key};
389 21         31 my $ref = ref($val);
390 21 100 66     89 if ($ref eq 'ARRAY' or $ref =~ /=ARRAY/) {
391 1         2 push @pairs, map { $self->urlEncode($key) . "=" . $self->urlEncode($_) } @$val;
  2         73  
392             } else {
393 20         521 push @pairs, $self->urlEncode($key) . "=" . $self->urlEncode($val);
394             }
395             }
396              
397 11         45 return join($sep, @pairs);
398             }
399             *url_encode_vars = \&urlEncodeVars;
400              
401             =pod
402              
403             =head2 urlDecodeVars($query_string)
404              
405             Takes a URL-encoded query string, decodes it, and returns a
406             reference to a hash of name/value pairs. For multivalued
407             fields, the value is an array of values. If called in array
408             context, it returns a reference to a hash of name/value pairs,
409             and a reference to an array of field names in the order they
410             appear in the query string.
411              
412             Aliases: url_decode_vars()
413              
414             =cut
415             sub urlDecodeVars {
416 2     2 1 10 my ($self, $query) = @_;
417 2         5 my $var_hash = {};
418 2         16 my @pairs = split /[;&]/, $query;
419 2         5 my $var_order = [];
420            
421 2         6 foreach my $pair (@pairs) {
422 8         21 my ($name, $value) = map { $self->urlDecode($_) } split /=/, $pair, 2;
  16         36  
423 8 100       23 if (exists($$var_hash{$name})) {
424 2         6 my $this_val = $$var_hash{$name};
425 2 50       7 if (ref($this_val) eq 'ARRAY') {
426 0         0 push @$this_val, $value;
427             } else {
428 2         24 $$var_hash{$name} = [ $this_val, $value ];
429             }
430             } else {
431 6         13 $$var_hash{$name} = $value;
432 6         15 push @$var_order, $name;
433             }
434             }
435            
436 2 50       13 return wantarray ? ($var_hash, $var_order) : $var_hash;
437             }
438             *url_decode_vars = \&urlDecodeVars;
439              
440             =pod
441              
442             =head2 escapeHtml($text)
443              
444             Escapes the given text so that it is not interpreted as HTML. &,
445             <, >, and " characters are escaped.
446              
447             Aliases: escape_html()
448              
449             =cut
450             # added for v0.05
451             sub escapeHtml {
452 0     0 1 0 my ($self, $text) = @_;
453 0 0       0 return undef unless defined $text;
454            
455 0         0 $text =~ s/\&/\&/g;
456 0         0 $text =~ s/
457 0         0 $text =~ s/>/\>/g;
458 0         0 $text =~ s/\"/\"/g;
459 0         0 $text =~ s/\'/\'/g;
460              
461 0         0 return $text;
462             }
463             *escape_html = \&escapeHtml;
464              
465             =pod
466              
467             =head2 escapeHtmlFormValue($text)
468              
469             Escapes the given text so that it is valid to put in a form
470             field.
471              
472             Aliases: escape_html_form_value()
473              
474             =cut
475             # added for v0.05
476             sub escapeHtmlFormValue {
477 0     0 1 0 my ($self, $str) = @_;
478 0         0 $str =~ s/\"/"/g;
479 0         0 $str =~ s/>/>/g;
480 0         0 $str =~ s/
481            
482 0         0 return $str;
483             }
484             *escape_html_form_value = \&escapeHtmlFormValue;
485              
486              
487             =pod
488              
489             =head2 getSelfRefHostUrl()
490              
491             Returns a url referencing top level directory in the current
492             domain, e.g., http://mydomain.com
493              
494             Aliases: get_self_ref_host_url()
495              
496             =cut
497             sub getSelfRefHostUrl {
498 10     10 1 61 my ($self) = @_;
499 10         17 my $https = $ENV{HTTPS};
500 10         25 my $port = $self->_fromCgiOrModPerl('get_server_port', 'SERVER_PORT');
501             # my $scheme = (defined($https) and lc($https) eq 'on') ? 'https' : 'http';
502             # $scheme = 'https' if defined($port) and $port == 443;
503 10         26 my $scheme = $self->getProtocol;
504 10         23 my $host = $self->getHost;
505 10         22 my $host_url = "$scheme://$host";
506              
507 10 50 33     27 if ($port != 80 and $port != 443) {
508 0 0       0 $host_url .= ":$port" unless $host_url =~ /:\d+$/;
509             }
510            
511 10         41 return $host_url;
512             }
513             *get_self_ref_host_url = \&getSelfRefHostUrl;
514             *get_self_host_url = \&getSelfRefHostUrl;
515              
516             =pod
517              
518             =head2 getSelfRefUrl()
519              
520             Returns a url referencing the current script (without any query
521             string).
522              
523             Aliases: get_self_ref_url
524              
525             =cut
526             sub getSelfRefUrl {
527 5     5 1 7 my ($self) = @_;
528 5         9 return $self->getSelfRefHostUrl . $self->getSelfRefUri;
529             }
530             *get_self_ref_url = \&getSelfRefUrl;
531              
532             =pod
533              
534             =head2 getSelfRefUri()
535              
536             Returns the current URI.
537              
538             Aliases: get_self_ref_uri()
539              
540             =cut
541             sub getSelfRefUri {
542 9     9 1 210 my ($self) = @_;
543 9         8 my $uri;
544 9 50       16 if ($self->_isModPerl) {
    50          
545 0         0 my $r = $self->_getApacheRequest;
546 0   0     0 $uri = $r->uri || $r->path_info;
547             } elsif ($self->_isCgi) {
548 9   33     26 $uri = $ENV{REQUEST_URI} || $ENV{PATH_INFO};
549             }
550            
551 9         57 $uri =~ s/^(.*?)\?.*$/$1/;
552 9         30 return $uri;
553             }
554             *get_self_ref_uri = \&getSelfRefUri;
555              
556             =pod
557              
558             =head2 getSelfRefUrlWithQuery()
559              
560             Returns a url referencing the current script along with any
561             query string parameters passed via a GET method.
562              
563             Aliases: get_self_ref_url_with_query()
564              
565             =cut
566             sub getSelfRefUrlWithQuery {
567 1     1 1 2 my ($self) = @_;
568              
569 1         3 my $url = $self->getSelfRefUrl;
570 1         2 my $query_str;
571 1 50       4 if ($self->_isModPerl) {
572 0         0 my $r = $self->_getApacheRequest;
573 0 0       0 $query_str = $r ? $r->args : $ENV{QUERY_STRING};
574             }
575             else {
576 1         3 $query_str = $ENV{QUERY_STRING};
577             }
578 1 50 33     15 if (defined($query_str) and $query_str ne '') {
579 1         7 return $url . '?' . $query_str;
580             }
581 0         0 return $url;
582             }
583             *get_self_ref_url_with_query = \&getSelfRefUrlWithQuery;
584              
585             =pod
586              
587             =head2 getSelfRefUrlWithParams($params, $sep)
588              
589             Returns a url reference the current script along with the given
590             hash of parameters added onto the end of url as a query string.
591              
592             If the optional $sep parameter is passed, it is used as the
593             parameter separator instead of ';', unless the URL already
594             contains '&' chars, in which case it will use '&' for the
595             separator.
596              
597             Aliases: get_self_ref_url_with_params()
598              
599             =cut
600             # added for 0.06
601             sub getSelfRefUrlWithParams {
602 2     2 1 5 my ($self, $args, $sep) = @_;
603              
604 2         5 return $self->addParamsToUrl($self->getSelfRefUrl, $args, $sep);
605             }
606             *get_self_ref_url_with_params = \&getSelfRefUrlWithParams;
607              
608             =pod
609              
610             =head2 getSelfRefUrlDir()
611              
612             Returns a url referencing the directory part of the current url.
613              
614             Aliases: get_self_ref_url_dir()
615              
616             =cut
617             sub getSelfRefUrlDir {
618 1     1 1 41 my ($self) = @_;
619 1         4 my $url = $self->getSelfRefUrl;
620 1         3 $url =~ s{^(.+?)\?.*$}{$1};
621 1         7 $url =~ s{/[^/]+$}{};
622 1         5 return $url;
623             }
624             *get_self_ref_url_dir = \&getSelfRefUrlDir;
625              
626             =pod
627              
628             =head2 convertRelativeUrlWithParams($relative_url, $params, $sep)
629              
630             Converts a relative URL to an absolute one based on the current
631             URL, then adds the parameters in the given hash $params as a
632             query string.
633              
634             If the optional $sep parameter is passed, it is used as the
635             parameter separator instead of ';', unless the URL already
636             contains '&' chars, in which case it will use '&' for the
637             separator.
638              
639             Aliases: convertRelativeUrlWithArgs(), convert_relative_url_with_params(),
640             convert_relative_url_with_args()
641              
642             =cut
643             # Takes $rel_url as a url relative to the current directory,
644             # e.g., a script name, and adds the given cgi params to it.
645             # added for v0.05
646             sub convertRelativeUrlWithParams {
647 3     3 1 626 my ($self, $rel_url, $args, $sep) = @_;
648 3         8 my $host_url = $self->getSelfRefHostUrl;
649 3         9 my $uri = $self->getSelfRefUri;
650 3         7 $uri =~ s{^(.+?)\?.*$}{$1};
651 3         14 $uri =~ s{/[^/]+$}{};
652              
653 3 50       9 if ($rel_url =~ m{^/}) {
654 0         0 $uri = $rel_url;
655             } else {
656 3         12 while ($rel_url =~ m{^\.\./}) {
657 2         7 $rel_url =~ s{^\.\./}{}; # pop dir off front
658 2         11 $uri =~ s{/[^/]+$}{}; # pop dir off end
659             }
660 3         5 $uri .= '/' . $rel_url;
661             }
662              
663 3         11 return $self->addParamsToUrl($host_url . $uri, $args, $sep);
664             }
665             *convertRelativeUrlWithArgs = \&convertRelativeUrlWithParams;
666             *convert_relative_url_with_params = \&convertRelativeUrlWithParams;
667             *convert_relative_url_with_args = \&convertRelativeUrlWithParams;
668              
669             =pod
670              
671             =head2 addParamsToUrl($url, $param_hash, $sep)
672              
673             Takes a url and reference to a hash of parameters to be added
674             onto the url as a query string and returns a url with those
675             parameters. It checks whether or not the url already contains a
676             query string and modifies it accordingly. If you want to add a
677             multivalued parameter, pass it as a reference to an array
678             containing all the values.
679              
680             If the optional $sep parameter is passed, it is used as the
681             parameter separator instead of ';', unless the URL already
682             contains '&' chars, in which case it will use '&' for the
683             separator.
684              
685             Aliases: add_params_to_url()
686              
687             =cut
688             sub addParamsToUrl {
689 10     10 1 730 my ($self, $url, $param_hash, $sep) = @_;
690 10 50 33     75 return $url unless ref($param_hash) eq 'HASH' and %$param_hash;
691 10 100 66     37 $sep = ';' unless defined($sep) and $sep ne '';
692 10 100       33 if ($url =~ /^([^?]+)\?(.*)$/) {
693 3         7 my $query = $2;
694             # if query uses & for separator, then keep it consistent
695 3 100       9 if ($query =~ /\&/) {
696 1         2 $sep = '&';
697             }
698 3 100       11 $url .= $sep unless $url =~ /\?$/;
699             } else {
700 7         14 $url .= '?';
701             }
702              
703 10         25 $url .= $self->urlEncodeVars($param_hash, $sep);
704 10         31 return $url;
705             }
706             *add_params_to_url = \&addParamsToUrl;
707              
708             sub _getRawCookie {
709 1     1   3 my $self = shift;
710              
711 1 50       4 if ($self->_isModPerl) {
712 0         0 my $r = $self->_getApacheRequest;
713 0 0 0     0 return $r ? $r->headers_in()->{Cookie} : ($ENV{HTTP_COOKIE} || $ENV{COOKIE} || '');
714             }
715             else {
716 1   50     33 return $ENV{HTTP_COOKIE} || $ENV{COOKIE} || '';
717             }
718             }
719              
720             =pod
721              
722             =head2 getParsedCookies()
723              
724             Parses the cookies passed to the server. Returns a hash of
725             key/value pairs representing the cookie names and values.
726              
727             Aliases: get_parsed_cookies
728              
729             =cut
730             sub getParsedCookies {
731 1     1 1 9 my ($self) = @_;
732 1         6 my %cookies = map { (map { $self->urlDecode($_) } split(/=/, $_, 2)) }
  3         11  
  6         17  
733             split(/;\s*/, $self->_getRawCookie);
734 1         6 return \%cookies;
735             }
736             *get_parsed_cookies = \&getParsedCookies;
737              
738             # added for v0.06
739             # for compatibility with CGI.pm
740             # may want to create an object here
741             sub cookie {
742 0     0 0 0 my ($self, @args) = @_;
743 0         0 my $map_list = [ 'name', [ 'value', 'values' ], 'path', 'expires', 'domain', 'secure' ];
744 0         0 my $params = $self->_parse_sub_params($map_list, \@args);
745 0 0       0 if (exists($$params{value})) {
746 0         0 return $params;
747             } else {
748 0         0 my $cookies = $self->getParsedCookies;
749 0 0 0     0 if ($cookies and %$cookies) {
750 0         0 return $$cookies{$$params{name}};
751             }
752 0         0 return '';
753             }
754 0         0 return $params;
755             }
756              
757             # =pod
758              
759             # =head2 parse({ max_post_size => $max_bytes })
760              
761             # Parses the CGI parameters. GET and POST (both url-encoded and
762             # multipart/form-data encodings), including file uploads, are
763             # supported. If the request method is POST, you may pass a
764             # maximum number of bytes to accept via POST. This can be used to
765             # limit the size of file uploads, for example.
766              
767             # =cut
768             sub parse {
769 0     0 0 0 my ($self, $args) = @_;
770              
771 0 0       0 return 1 if $$self{_already_parsed};
772 0         0 $$self{_already_parsed} = 1;
773              
774 0 0       0 $args = {} unless ref($args) eq 'HASH';
775              
776 0 0       0 if ($self->_isModPerl) {
    0          
777             # If running under mod_perl, grab the GET or POST data
778 0         0 my $rv = $self->_modPerlParse($args);
779 0 0       0 return $rv if $rv;
780             } elsif (not $ENV{'GATEWAY_INTERFACE'}) {
781             # Not CGI, so must be commandline
782 0 0       0 if (scalar(@ARGV)) {
783 0         0 return $self->_cmdLineParse(\@ARGV);
784             }
785             }
786              
787              
788             # check for mod_perl - GATEWAY_INTERFACE =~ m{^CGI-Perl/}
789             # check for PerlEx - GATEWAY_INTERFACE =~ m{^CGI-PerlEx}
790              
791 0         0 return $self->_cgiParse($args);
792             }
793              
794             sub _cmdLineParse {
795 0     0   0 my $self = shift;
796 0         0 my $args = shift;
797              
798 0         0 my %params;
799 0         0 foreach my $arg (@$args) {
800 0 0       0 if ($arg =~ /^([^=]+)=(.*)$/s) {
801 0         0 my $key = $1;
802 0         0 my $val = $2;
803 0         0 $params{$key} = $val;
804             }
805             else {
806             # bad param, drop them all
807 0         0 return;
808             }
809             }
810              
811 0         0 $self->{_params} = \%params;
812            
813 0         0 return 1;
814             }
815            
816             sub _cgiParse {
817 0     0   0 my $self = shift;
818 0         0 my $args = shift;
819            
820 0         0 my $method = lc($ENV{REQUEST_METHOD});
821 0   0     0 my $content_length = $ENV{CONTENT_LENGTH} || 0;
822              
823 0 0       0 if ($method eq 'post') {
824 0   0     0 my $max_size = $$args{max_post_size} || $$self{_max_post_size};
825 0 0       0 $max_size = 0 unless defined($max_size);
826 0 0 0     0 if ($max_size > 0 and $content_length > $max_size) {
827 0         0 return undef;
828             }
829             }
830              
831 0 0 0     0 if ($method eq 'post' and $ENV{CONTENT_TYPE} =~ m|^multipart/form-data|) {
    0 0        
    0          
832 0 0       0 if ($ENV{CONTENT_TYPE} =~ /boundary=(\"?)([^\";,]+)\1/) {
833 0         0 my $boundary = $2;
834 0         0 $self->_readMultipartData($boundary, $content_length, \*STDIN);
835             } else {
836 0         0 return undef;
837             }
838             } elsif ($method eq 'get' or $method eq 'head') {
839 0         0 my $query_string = $ENV{QUERY_STRING};
840 0         0 $self->_parseParams($query_string);
841             } elsif ($method eq 'post') {
842 0         0 my $query_string;
843 0 0       0 $self->_readPostData(\*STDIN, \$query_string, $content_length) if $content_length > 0;
844 0         0 $self->_parseParams($query_string);
845             # FIXME: may want to append anything in query string
846             # to POST data, so can do a post with an action that
847             # contains a query string.
848             }
849              
850 0         0 return 1;
851             }
852              
853             sub _modPerlParse {
854 0     0   0 my $self = shift;
855 0         0 my $args = shift;
856              
857 0         0 my $r;
858 0 0       0 if ($self->_getMasonObject) {
    0          
859 0         0 $self->{_params} = $self->_getMasonArgs;
860 0         0 my $method = $self->getRequestMethod;
861 0 0 0     0 if (lc($method) eq 'post' and $self->getContentType =~ m|^multipart/form-data|) {
862 0         0 $r = $self->_getApacheRequest;
863 0         0 my @uploads = $r->upload; # $r is really an Apache::Request obj in this case
864 0 0       0 if (@uploads) {
865             # make a copy so we don't mess around with Mason
866 0         0 %{$self->{_params}} = %{$self->{_params}};
  0         0  
  0         0  
867 0         0 foreach my $upload (@uploads) {
868 0         0 my $field_name = $upload->name;
869 0         0 my $fh = $upload->fh;
870             # seek($fh, 0, 0);
871 0         0 my $filename = $upload->filename;
872 0         0 my $cgi_style_fh =
873             CGI::Utils::UploadFile->new_from_handle($filename, $fh);
874 0         0 $self->{_params}->{$field_name} = $cgi_style_fh;
875 0         0 my $info = { 'Content-Type' => $upload->type };
876 0         0 $self->{_upload_info}->{$filename} = $info;
877             }
878             }
879             }
880 0         0 return 1;
881             } elsif ($r = $self->_getApacheRequest) {
882 0         0 my $query_string = $r->args;
883 0         0 $self->_parseParams($query_string);
884 0         0 my $method = $self->getRequestMethod;
885 0 0       0 if (lc($method) eq 'post') {
886 0 0       0 unless (defined $CGI::Utils::Has_Apache_Request) {
887 0         0 local($SIG{__DIE__});
888 0         0 if (MP2) {
889             eval 'require Apache2::Request';
890             # my $apr = Apache2::RequestUtil->request($r)
891             } else {
892 0         0 eval 'require Apache::Request';
893             }
894 0 0       0 if ($@) {
895 0         0 $CGI::Utils::Has_Apache_Request = 0;
896             } else {
897 0         0 $CGI::Utils::Has_Apache_Request = 1;
898             }
899             }
900              
901 0 0       0 if ($CGI::Utils::Has_Apache_Request) {
    0          
902 0         0 my $apr = Apache::Request->new($r);
903 0         0 my $cur_params = $self->{_params};
904 0         0 my @params = $apr->param;
905 0         0 foreach my $key (@params) {
906 0         0 my @vals = $apr->param($key);
907 0 0       0 if (scalar(@vals) > 1) {
908 0         0 $cur_params->{$key} = \@vals;
909             } else {
910 0         0 $cur_params->{$key} = $vals[0];
911             }
912             }
913              
914 0 0       0 if ($self->getContentType =~ m|^multipart/form-data|) {
915 0         0 my @uploads = $apr->upload;
916 0         0 foreach my $upload (@uploads) {
917 0         0 my $field_name = $upload->name;
918 0         0 my $fh = $upload->fh;
919 0         0 my $filename = $upload->filename;
920 0         0 my $cgi_style_fh =
921             CGI::Utils::UploadFile->new_from_handle($filename, $fh);
922 0         0 $self->{_params}->{$field_name} = $cgi_style_fh;
923 0         0 my $info = { 'Content-Type' => $upload->type };
924 0         0 $self->{_upload_info}->{$filename} = $info;
925             }
926             }
927             } elsif ($self->_isCgi) {
928             # Using the perl-script handler that provides
929             # a CGI environment under mod_perl. So fall
930             # back to getting everything from the CGI
931             # environment.
932 0         0 return $self->_cgiParse($args);
933             } else {
934 0         0 return undef;
935             }
936             }
937              
938 0         0 return 1;
939             }
940              
941 0         0 return undef;
942             }
943              
944             =pod
945              
946             =head2 param($name)
947              
948             Returns the CGI parameter with name $name. If called in array
949             context, it returns an array. In scalar context, it returns an
950             array reference for multivalued fields, and a scalar for
951             single-valued fields.
952              
953             =cut
954             sub param {
955 0     0 1 0 my ($self, $name) = @_;
956 0         0 $self->parse;
957            
958 0 0 0     0 if (scalar(@_) == 1 and wantarray()) {
959 0         0 my $params = $$self{_params};
960 0         0 my $order = $$self{_param_order};
961 0         0 return grep { exists($$params{$_}) } @$order;
  0         0  
962             }
963 0 0       0 return undef unless defined($name);
964 0         0 my $val = $$self{_params}{$name};
965              
966 0 0       0 if (wantarray()) {
967 0 0       0 return ref($val) eq 'ARRAY' ? @$val : ($val);
968             } else {
969 0         0 return $val;
970             }
971             }
972              
973             =pod
974              
975             =head2 getVars($delimiter)
976              
977             Also Vars() to be compatible with CGI.pm. Returns a reference
978             to a tied hash containing key/value pairs corresponding to each
979             CGI parameter. For multivalued fields, the value is an array
980             ref, with each element being one of the values. If you pass in
981             a value for the delimiter, multivalued fields will be returned
982             as a string of values delimited by the delimiter you passed in.
983              
984             Aliases: vars(), Vars(), get_args(), args()
985              
986             =cut
987             sub getVars {
988 0     0 1 0 my ($self, $multivalue_delimiter) = @_;
989 0 0 0     0 if (defined($$self{_multivalue_delimiter}) and $$self{_multivalue_delimiter} ne '') {
    0 0        
990 0 0 0     0 $multivalue_delimiter = $$self{_multivalue_delimiter}
991             if not defined($multivalue_delimiter) or $multivalue_delimiter eq '';
992             } elsif (defined($multivalue_delimiter) and $multivalue_delimiter ne '') {
993 0         0 $$self{_multivalue_delimiter} = $multivalue_delimiter;
994             }
995              
996 0         0 $self->parse;
997            
998 0 0       0 if (wantarray()) {
999 0         0 my $params = $$self{_params};
1000 0         0 my %vars = %$params;
1001 0         0 foreach my $key (keys %vars) {
1002 0 0       0 if (ref($vars{$key}) eq 'ARRAY') {
1003 0 0       0 if ($multivalue_delimiter ne '') {
1004 0         0 $vars{$key} = join($multivalue_delimiter, @{$vars{$key}});
  0         0  
1005             } else {
1006 0         0 my @copy = @{$vars{$key}};
  0         0  
1007 0         0 $vars{$key} = \@copy;
1008             }
1009             }
1010             }
1011 0         0 return %vars;
1012             }
1013            
1014 0         0 my $vars = $$self{_vars_hash};
1015 0 0       0 return $vars if $vars;
1016              
1017 0         0 my %vars;
1018 0         0 tie %vars, 'CGI::Utils', $self;
1019              
1020 0         0 return \%vars;
1021             }
1022             *vars = \&getVars;
1023             *Vars = \&getVars;
1024             *get_vars = \&getVars;
1025             *get_args = \&getVars;
1026             *args = \&getVars;
1027              
1028             =pod
1029              
1030             # Other information provided by the CGI environment
1031              
1032             =head2 getPathInfo(), path_info(), get_path_info();
1033              
1034             Returns additional virtual path information from the URL (if
1035             any) after your script.
1036              
1037             =cut
1038             # added for 0.06
1039             sub getPathInfo {
1040 0     0 1 0 my ($self) = @_;
1041 0 0       0 return $$self{_path_info} if defined($$self{_path_info});
1042            
1043 0         0 my $r = $self->_getApacheRequest;
1044              
1045 0 0       0 my $path_info = $r ? $r->path_info : (defined($ENV{PATH_INFO}) ? $ENV{PATH_INFO} : '');
    0          
1046 0         0 $$self{_path_info} = $path_info;
1047 0         0 return $path_info;
1048             }
1049             *path_info = \&getPathInfo;
1050             *get_path_info = \&getPathInfo;
1051              
1052             =pod
1053              
1054             =head2 getRemoteAddr(), remote_addr(), get_remote_addr()
1055              
1056             Returns the dotted decimal representation of the remote client's
1057             IP address.
1058              
1059             =cut
1060             # added for v0.07
1061             sub getRemoteAddr {
1062 0     0 1 0 my $self = shift;
1063 0         0 return $self->_fromCgiOrModPerlConnection('remote_ip', 'REMOTE_ADDR');
1064             }
1065             *remote_addr = \&getRemoteAddr;
1066             *get_remote_addr = \&getRemoteAddr;
1067              
1068             =pod
1069              
1070             =head2 getRemoteHost(), remote_host(), get_remote_host()
1071              
1072             Returns the name of the remote host, or its IP address if the
1073             name is unavailable.
1074              
1075             =cut
1076             # added for v0.07
1077             sub getRemoteHost {
1078 0     0 1 0 my $self = shift;
1079              
1080 0         0 my $host = $self->_fromCgiOrModPerl('remote_host', 'REMOTE_HOST');
1081 0 0 0     0 unless (defined($host) and $host ne '') {
1082 0         0 $host = $self->_fromCgiOrModPerlConnection('remote_ip', 'REMOTE_ADDR');
1083             }
1084              
1085 0         0 return $host;
1086             }
1087             *remote_host = \&getRemoteHost;
1088             *get_remote_host = \&getRemoteHost;
1089              
1090             =pod
1091              
1092             =head2 getHost(), host(), virtual_host(), get_host()
1093              
1094             Returns the name of the host in the URL being accessed. This is
1095             sent as the Host header by the web browser.
1096              
1097             =cut
1098             # added for v0.07
1099             sub getHost {
1100 10     10 1 11 my $self = shift;
1101 10         19 return $self->_fromCgiOrModPerl('hostname', 'HTTP_HOST');
1102             }
1103             *host = \&getHost;
1104             *virtual_host = \&getHost;
1105             *get_host = \&getHost;
1106              
1107             =pod
1108              
1109             =head2 getReferer(), referer(), get_referer(), getReferrer(), referrer(), get_referrer()
1110              
1111             Returns the referring URL.
1112              
1113             =cut
1114             # added for v0.07
1115             sub getReferer {
1116 0     0 1 0 my $self = shift;
1117              
1118 0         0 return $self->_getHttpHeader('Referer');
1119             }
1120             *referer = \&getReferer;
1121             *get_referer = \&getReferer;
1122             *getReferrer = \&getReferer;
1123             *referrer = \&getReferer;
1124             *get_referrer = \&getReferer;
1125              
1126             =pod
1127              
1128             =head2 getProtocol(), protocol(), get_protocol()
1129              
1130             Returns the protocol, i.e., http or https.
1131              
1132             =cut
1133             # added for v0.07
1134             sub getProtocol {
1135 10     10 1 12 my $self = shift;
1136 10         16 my $https = $ENV{HTTPS};
1137 10 100 66     43 my $proto = (defined($https) and lc($https) eq 'on') ? 'https' : 'http';
1138 10         18 my $port = $self->_fromCgiOrModPerl('get_server_port', 'SERVER_PORT');
1139 10 50 33     62 $proto = 'https' if defined($port) and $port == 443;
1140            
1141 10         17 return $proto;
1142             }
1143             *protocol = \&getProtocol;
1144             *get_protocol = \&getProtocol;
1145              
1146             =pod
1147              
1148             =head2 getRequestMethod(), request_method(), get_request_method()
1149              
1150             Returns the request method, i.e., GET, POST, HEAD, or PUT.
1151              
1152             =cut
1153             # added for 0.06
1154             sub getRequestMethod {
1155 0     0 1   my $self = shift;
1156 0           return $self->_fromCgiOrModPerl('method', 'REQUEST_METHOD');
1157             }
1158             *request_method = \&getRequestMethod;
1159             *get_request_method = \&getRequestMethod;
1160              
1161             =pod
1162              
1163             =head2 getContentType(), content_type(), get_content_type()
1164              
1165             Returns the content type.
1166              
1167             =cut
1168             # added for 0.06
1169             sub getContentType {
1170 0     0 1   my $self = shift;
1171 0 0         if ($self->_isModPerl) {
1172 0           return $self->_getHttpHeader('Content-Type');
1173             } else {
1174 0           return $ENV{CONTENT_TYPE};
1175             }
1176             }
1177             *content_type = \&getContentType;
1178             *get_content_type = \&getContentType;
1179              
1180             =pod
1181              
1182             =head2 getPathTranslated(), path_translated(), get_path_translated()
1183              
1184             Returns the physical path information if provided in the CGI environment.
1185              
1186             =cut
1187             # added for 0.06
1188             sub getPathTranslated {
1189 0     0 1   my $self = shift;
1190 0           return $self->_fromCgiOrModPerl('filename', 'PATH_TRANSLATED');
1191             }
1192             *path_translated = \&getPathTranslated;
1193             *get_path_translated = \&getPathTranslated;
1194              
1195             =pod
1196              
1197             =head2 getQueryString(), query_string(), get_query_string()
1198              
1199             Returns a query string created from the current parameters.
1200              
1201             =cut
1202             # create a query string from current CGI params
1203             # added for 0.06
1204             sub getQueryString {
1205 0     0 1   my ($self) = @_;
1206 0           my $fields = $self->getVars;
1207 0           return $self->urlEncodeVars($fields);
1208             }
1209             *query_string = \&getQueryString;
1210             *get_query_string = \&getQueryString;
1211              
1212             =pod
1213              
1214             =head2 getHeader(@args)
1215              
1216             Generates HTTP headers. Standard arguments are content_type,
1217             cookie, target, expires, and charset. These should be passed as
1218             name/value pairs. If only one argument is passed, it is assumed
1219             to be the 'content_type' argument. If no values are passed, the
1220             content type is assumed to be 'text/html'. The charset defaults
1221             to ISO-8859-1. A hash reference can also be passed. E.g.,
1222              
1223             print $cgi_obj->getHeader({ content_type => 'text/html', expires => '+3d' });
1224              
1225             The names 'content-type', and 'type' are aliases for
1226             'content_type'. The arguments may also be passed CGI.pm style
1227             with a '-' in front, e.g.
1228              
1229             print $cgi_obj->getHeader( -content_type => 'text/html', -expires => '+3d' );
1230              
1231             Cookies may be passed with the 'cookies' key either as a string,
1232             a hash ref, or as a CGI::Cookies object, e.g.
1233              
1234             my $cookie = { name => 'my_cookie', value => 'cookie_val' };
1235             print $cgi_obj->getHeader(cookies => $cookie);
1236              
1237             You may also pass an array of cookies, e.g.,
1238              
1239             print $cgi_obj->getHeader(cookies => [ $cookie1, $cookie2 ]);
1240              
1241             Aliases: header(), get_header
1242              
1243             =cut
1244             sub getHeader {
1245 0     0 1   my ($self, @args) = @_;
1246 0           my $arg_count = scalar(@args);
1247 0 0         if ($arg_count == 0) {
1248 0           return "Content-Type: text/html\r\n\r\n";
1249             }
1250 0 0 0       if ($arg_count == 1 and ref($args[0]) ne 'HASH') {
1251             # content-type provided
1252 0           return "Content-Type: $args[0]\r\n\r\n";
1253             }
1254              
1255 0           my $map_list = [ [ 'type', 'content-type', 'content_type' ],
1256             'status',
1257             [ 'cookie', 'cookies' ],
1258             'target', 'expires', 'nph', 'charset', 'attachment',
1259             'mod_perl',
1260             ];
1261 0           my ($params, $extras) = $self->_parse_sub_params($map_list, \@args);
1262            
1263 0   0       my $charset = $$params{charset} || 'ISO-8859-1';
1264 0           my $content_type = $$params{type};
1265 0 0 0       $content_type ||= 'text/html' unless defined($content_type);
1266 0 0 0       $content_type .= "; charset=$charset"
1267             if $content_type =~ /^text/ and $content_type !~ /\bcharset\b/;
1268              
1269             # FIXME: handle NPH stuff
1270              
1271 0           my $headers = [];
1272 0 0         push @$headers, "Status: $$params{status}" if defined($$params{status});
1273 0 0         push @$headers, "Window-Target: $$params{target}" if defined($$params{target});
1274            
1275 0           my $cookies = $$params{cookie};
1276 0 0 0       if (defined($cookies) and $cookies) {
1277 0 0         my $cookie_array = ref($cookies) eq 'ARRAY' ? $cookies : [ $cookies ];
1278 0           foreach my $cookie (@$cookie_array) {
1279             # handle plain strings as well as CGI::Cookie objects and hashes
1280 0           my $str = '';
1281 0 0         if (UNIVERSAL::isa($cookie, 'CGI::Cookie')) {
    0          
1282 0           $str = $cookie->as_string;
1283             } elsif (ref($cookie) eq 'HASH') {
1284 0           $str = $self->_createCookieStrFromHash($cookie);
1285             } else {
1286 0           $str = $cookie;
1287             }
1288 0 0         push @$headers, "Set-Cookie: $str" unless $str eq '';
1289             }
1290             }
1291              
1292 0 0         if (defined($$params{expires})) {
1293 0           my $expire = $self->_canonicalizeHttpDate($$params{expires});
1294 0           push @$headers, "Expires: $expire";
1295             }
1296              
1297 0 0 0       if (defined($$params{expires}) or (defined($cookies) and $cookies)) {
      0        
1298 0           push @$headers, "Date: " . $self->_canonicalizeHttpDate(0);
1299             }
1300            
1301 0 0         push @$headers, qq{Content-Disposition: attachment; filename="$$params{attachment}"}
1302             if defined($$params{attachment});
1303 0 0 0       push @$headers, "Content-Type: $content_type" if defined($content_type) and $content_type ne '';
1304              
1305 0 0         if ($params->{mod_perl}) {
1306 0           my $header_list = [];
1307            
1308 0           foreach my $field (sort keys %$extras) {
1309 0           my $val = $$extras{$field};
1310 0           $field =~ s/\b(.)/\U$1/g;
1311 0           $field = ucfirst($field);
1312 0           push @$header_list, [ $field, $val ];
1313             }
1314              
1315 0           return $header_list;
1316             }
1317            
1318 0           foreach my $field (sort keys %$extras) {
1319 0           my $val = $$extras{$field};
1320 0           $field =~ s/\b(.)/\U$1/g;
1321 0           $field = ucfirst($field);
1322 0           push @$headers, "$field: $val";
1323             }
1324            
1325             # FIXME: make line endings work on windoze
1326 0           return join("\r\n", @$headers) . "\r\n\r\n";
1327             }
1328             *header = \&getHeader;
1329             *get_header = \&getHeader;
1330              
1331             =pod
1332              
1333             =head2 sendHeader(@args)
1334              
1335             Like getHeader() above, except sends it. Under mod_perl, this
1336             sends the header(s) via the Apache request object. In a CGI
1337             environment, this prints the header(s) to STDOUT.
1338              
1339             Aliases: send_header()
1340              
1341             =cut
1342             sub sendHeader {
1343 0     0 1   my ($self, @args) = @_;
1344 0           my $mod_perl = 0;
1345 0           my $r;
1346 0 0 0       if ($self->_isModPerl and $r = $self->_getApacheRequest) {
1347 0           $mod_perl = 1;
1348             }
1349            
1350 0           my $arg_count = scalar(@args);
1351 0 0         if ($arg_count == 0) {
1352 0 0         if ($mod_perl) {
1353 0           $r->err_header_out('Content-Type' => 'text/html');
1354             } else {
1355 0           print STDOUT "Content-Type: text/html\r\n\r\n";
1356             }
1357 0           return 1;
1358             }
1359            
1360 0 0 0       if ($arg_count == 1 and ref($args[0]) ne 'HASH') {
1361             # content-type provided
1362 0 0         if ($mod_perl) {
1363 0           $r->err_header_out('Content-Type' => $args[0]);
1364             } else {
1365 0           print STDOUT "Content-Type: $args[0]\r\n\r\n";
1366             }
1367            
1368 0           return 1;
1369             }
1370              
1371 0 0         unless ($mod_perl) {
1372 0           my $str = $self->getHeader(@args);
1373 0           print STDOUT $str;
1374 0           return 1;
1375             }
1376              
1377 0 0         return undef unless $r;
1378              
1379 0           my $headers = [];
1380 0 0         if (ref($args[0]) eq 'HASH') {
1381 0           my %args = %{$args[0]};
  0            
1382 0           $args{mod_perl} = 1;
1383 0           $headers = $self->getHeader(\%args);
1384             } else {
1385 0           push @args, 'mod_perl', 1;
1386 0           $headers = $self->getHeader(@args);
1387             }
1388              
1389 0           my $rv = $self->apache_ok;
1390 0           foreach my $header (@$headers) {
1391 0 0         if (lc($header->[0]) eq 'set-cookie') {
1392 0           $r->err_headers_out()->add(@$header);
1393             }
1394             else {
1395 0 0         if (lc($header->[0]) eq 'location') {
1396 0           $rv = $self->apache_redirect;
1397             }
1398 0           $r->err_header_out(@$header);
1399             }
1400             }
1401              
1402 0           return $rv;
1403             }
1404             *send_header = \&sendHeader;
1405              
1406             sub load_apache_constants {
1407 0 0   0 0   unless (defined $CGI::Utils::Loaded_Apache_Constants) {
1408 0           local($SIG{__DIE__});
1409 0           eval q{
1410             use mod_perl;
1411             use constant MP2 => $mod_perl::VERSION >= 1.99;
1412             if (defined(MP2)) {
1413             if (MP2) {
1414             require Apache2;
1415             require Apache::Const;
1416             }
1417             else {
1418             require Apache::Constants;
1419             }
1420             $CGI::Utils::Loaded_Apache_Constants = 1;
1421             }
1422             };
1423             }
1424             }
1425            
1426              
1427             =pod
1428              
1429             =head2 getRedirect($url)
1430              
1431             Returns the header required to do a redirect. This method also
1432             accepts named arguments, e.g.,
1433              
1434             print $cgi_obj->getRedirect(url => $url, status => 302,
1435             cookie => \%cookie_params);
1436              
1437             You may also pass a cookies argument as in getHeader().
1438              
1439             Aliases: redirect()
1440              
1441             =cut
1442             sub getRedirect {
1443 0     0 1   my ($self, @args) = @_;
1444 0           my $map_list = [ [ 'location', 'uri', 'url' ],
1445             'status',
1446             [ 'cookie', 'cookies' ],
1447             'target',
1448             ];
1449 0           my ($params, $extras) = $self->_parse_sub_params($map_list, \@args);
1450 0 0         $params->{status} = 302 unless $params->{status};
1451 0           return $self->header({ type => '', %$params, %$extras });
1452             }
1453             *redirect = \&getRedirect;
1454              
1455             =pod
1456              
1457             =head2 sendRedirect($url)
1458              
1459             Like getRedirect(), but in a CGI environment the output is sent
1460             to STDOUT, and in a mod_perl environment, the appropriate
1461             headers are set. The return value is 1 for a CGI environment
1462             when successful, and Apache::Constants::REDIRECT in a mod_perl
1463             environment, so you can do something like
1464              
1465             return $utils->sendRedirect($url)
1466              
1467             n a mod_perl handler.
1468              
1469             Aliases: send_redirect()
1470              
1471             =cut
1472             sub send_redirect {
1473 0     0 0   my ($self, @args) = @_;
1474 0           my $map_list = [ [ 'location', 'uri', 'url' ],
1475             'status',
1476             [ 'cookie', 'cookies' ],
1477             'target',
1478             ];
1479 0           my ($params, $extras) = $self->_parse_sub_params($map_list, \@args);
1480 0 0         $params->{status} = 302 unless $params->{status};
1481 0           return $self->send_header({ type => '', %$params, %$extras });
1482             }
1483             *sendRedirect = \&send_redirect;
1484              
1485             =pod
1486              
1487             =head2 getLocalRedirect(), local_redirect(), get_local_redirect()
1488              
1489             Like getRedirect(), except that the redirect URL is converted
1490             from relative to absolute, including the host.
1491              
1492             =cut
1493             # Added for v0.07
1494             sub getLocalRedirect {
1495 0     0 1   my ($self, @args) = @_;
1496 0           my $map_list = [ [ 'location', 'uri', 'url' ],
1497             'status',
1498             [ 'cookie', 'cookies' ],
1499             'target',
1500             ];
1501 0           my ($params, $extras) = $self->_parse_sub_params($map_list, \@args);
1502 0 0         unless ($params->{location} =~ m{^https?://}) {
1503 0           $params->{location} = $self->convertRelativeUrlWithParams($params->{location}, {});
1504             }
1505 0           return $self->getRedirect(%$params);
1506             }
1507             *local_redirect = \&getLocalRedirect;
1508             *get_local_redirect = \&getLocalRedirect;
1509              
1510             =pod
1511              
1512             =head2 getCookieString(\%hash), get_cookie_string(\%hash);
1513              
1514             Returns a string to pass as the value of a 'Set-Cookie' header.
1515              
1516             =cut
1517             sub getCookieString {
1518 0     0 1   my ($self, $hash) = @_;
1519 0           return $self->_createCookieStrFromHash($hash);
1520             }
1521             *get_cookie_string = \&getCookieString;
1522              
1523             =pod
1524              
1525             =head2 getSetCookieString(\%params), getSetCookieString([ \%params1, \%params2 ])
1526              
1527             Returns a string to pass as the 'Set-Cookie' header(s), including
1528             the line ending(s). Also accepts a simple hash with key/value pairs.
1529              
1530             =cut
1531             sub getSetCookieString {
1532 0     0 1   my ($self, $cookies) = @_;
1533 0 0         if (ref($cookies) eq 'HASH') {
1534 0           my $array = [ map { { name => $_, value => $cookies->{$_} } } keys %$cookies ];
  0            
1535 0           $cookies = $array;
1536             }
1537 0 0         my $cookie_array = ref($cookies) eq 'ARRAY' ? $cookies : [ $cookies ];
1538              
1539 0           my $headers = [];
1540 0           foreach my $cookie (@$cookie_array) {
1541             # handle plain strings as well as CGI::Cookie objects and hashes
1542 0           my $str = '';
1543 0 0         if (UNIVERSAL::isa($cookie, 'CGI::Cookie')) {
    0          
1544 0           $str = $cookie->as_string;
1545             } elsif (ref($cookie) eq 'HASH') {
1546 0           $str = $self->_createCookieStrFromHash($cookie);
1547             } else {
1548 0           $str = $cookie;
1549             }
1550 0 0         push @$headers, "Set-Cookie: $str" unless $str eq '';
1551             }
1552              
1553             # FIXME: make line endings work on windoze
1554 0           return join("\r\n", @$headers) . "\r\n";
1555             }
1556             *get_set_cookie_string = \&getSetCookieString;
1557              
1558             =pod
1559              
1560             =head2 setCookie(\%params), set_cookie(\%params);
1561              
1562             Sets the cookie generated by getCookieString. That is, in a
1563             mod_perl environment, it adds an outgoing header to set the
1564             cookie. In a CGI environment, it prints the value of
1565             getSetCookieString to STDOUT (including the end-of-line
1566             sequence).
1567              
1568             =cut
1569             sub setCookie {
1570 0     0 1   my $self = shift;
1571 0           my $params = shift;
1572              
1573 0           my $str = $self->_createCookieStrFromHash($params);
1574 0           my $r = $self->_getApacheRequest;
1575              
1576 0 0         if ($r) {
1577 0           $r->err_headers_out()->add('Set-Cookie' => $str);
1578             }
1579             else {
1580 0           print STDOUT "Set-Cookie: $str\r\n";
1581             }
1582             }
1583             *set_cookie = \&setCookie;
1584            
1585             sub _createCookieStrFromHash {
1586 0     0     my ($self, $hash) = @_;
1587 0           my $pairs = [];
1588              
1589 0           my $map_list = [ 'name', [ 'value', 'values', 'val' ],
1590             'path', 'expires', 'domain', 'secure',
1591             ];
1592 0           my $params = $self->_parse_sub_params($map_list, [ $hash ]);
1593              
1594 0           my $value = $$params{value};
1595 0 0         if (my $ref = ref($value)) {
1596 0 0         if ($ref eq 'ARRAY') {
    0          
1597 0           $value = join('&', map { $self->urlEncode($_) } @$value);
  0            
1598             } elsif ($ref eq 'HASH') {
1599 0           $value = join('&', map { $self->urlEncode($_) } %$value);
  0            
1600             }
1601             } else {
1602 0           $value = $self->urlEncode($value);
1603             }
1604 0           push @$pairs, qq{$$params{name}=$value};
1605              
1606 0   0       my $path = $$params{path} || '/';
1607 0           push @$pairs, qq{path=$path};
1608            
1609 0 0         push @$pairs, qq{domain=$$params{domain}} if $$params{domain};
1610              
1611 0 0         if ($$params{expires}) {
1612 0           my $expire = $self->_canonicalizeCookieDate($$params{expires});
1613 0           push @$pairs, qq{expires=$expire};
1614             }
1615              
1616 0 0         push @$pairs, qq{secure} if $$params{secure};
1617              
1618 0           return join('; ', @$pairs);
1619             }
1620            
1621             sub _canonicalizeCookieDate {
1622 0     0     my ($self, $expire) = @_;
1623 0           return $self->_canonicalizeDate('-', $expire);
1624             }
1625            
1626             sub _canonicalizeHttpDate {
1627 0     0     my ($self, $expire) = @_;
1628 0           return $self->_canonicalizeDate(' ', $expire);
1629            
1630 0           my $time = $self->_get_expire_time_from_offset($expire);
1631 0 0         return $time unless $time =~ /^\d+$/;
1632              
1633 0           my $wdays = [ qw(Sun Mon Tue Wed Thu Fri Sat) ];
1634 0           my $months = [ qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) ];
1635            
1636 0           my $sep = ' ';
1637              
1638 0           my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time);
1639 0 0         $year += 1900 unless $year > 1000;
1640 0           return sprintf "%s, %02d$sep%s$sep%04d %02d:%02d:%02d GMT",
1641             $$wdays[$wday], $mday, $$months[$mon], $year, $hour, $min, $sec;
1642             }
1643              
1644             sub _canonicalizeDate {
1645 0     0     my ($self, $sep, $expire) = @_;
1646 0           my $time = $self->_get_expire_time_from_offset($expire);
1647 0 0         return $time unless $time =~ /^\d+$/;
1648              
1649 0           my $wdays = [ qw(Sun Mon Tue Wed Thu Fri Sat) ];
1650 0           my $months = [ qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) ];
1651              
1652 0           my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time);
1653 0 0         $year += 1900 unless $year > 1000;
1654 0           return sprintf "%s, %02d$sep%s$sep%04d %02d:%02d:%02d GMT",
1655             $$wdays[$wday], $mday, $$months[$mon], $year, $hour, $min, $sec;
1656              
1657             }
1658              
1659             sub _get_expire_time_from_offset {
1660 0     0     my ($self, $offset) = @_;
1661 0           my $ret_offset = 0;
1662 0 0 0       if (not $offset or lc($offset) eq 'now') {
    0          
    0          
1663 0           $ret_offset = 0;
1664             } elsif ($offset =~ /^\d+$/) {
1665 0           return $offset;
1666             } elsif ($offset =~ /^([-+]?(?:\d+|\d*\.\d*))([mhdMy]?)/) {
1667 0           my $map = { 's' => 1,
1668             'm' => 60,
1669             'h' => 60 * 60,
1670             'd' => 60 * 60 * 24,
1671             'M' => 60 * 60 * 24 * 30,
1672             'y' => 60 * 60 * 24 * 365,
1673             };
1674 0   0       $ret_offset = ($$map{$2} || 1) * $1;
1675             } else {
1676 0           $ret_offset = $offset;
1677             }
1678              
1679 0           return time() + $ret_offset;
1680             }
1681            
1682             # canonicalize parameters so we can be compatible with CGI.pm
1683             sub _parse_sub_params {
1684 0     0     my ($self, $map_list, $args) = @_;
1685              
1686 0           my $arg_count = scalar(@$args);
1687 0 0         return {} if $arg_count == 0;
1688              
1689 0           my $hash;
1690 0 0         if ($arg_count == 1) {
1691 0 0         if (ref($$args[0]) eq 'HASH') {
1692 0           $hash = $$args[0];
1693             } else {
1694 0           my $rv;
1695 0 0         if (ref($$map_list[0]) eq 'ARRAY') {
1696 0           $rv = { $$map_list[0][0] => $$args[0] };
1697             } else {
1698 0           $rv = { $$map_list[0] => $$args[0] };
1699             }
1700 0 0         return wantarray ? ($rv, {}) : $rv;
1701             }
1702             } else {
1703 0           $hash = { @$args };
1704             }
1705              
1706 0           my $return_hash = {};
1707 0           my $found = {};
1708 0           foreach my $key (keys %$hash) {
1709 0           my $orig_key = $key;
1710 0           $key =~ s/^-{1,2}//;
1711 0           $key = lc($key);
1712 0           foreach my $e (@$map_list) {
1713 0 0         if (ref($e) eq 'ARRAY') {
1714 0           my $canon_key = $$e[0];
1715 0           foreach my $e2 (@$e) {
1716 0 0         if ($e2 eq $key) {
1717 0           $$return_hash{$canon_key} = $$hash{$orig_key};
1718 0           $$found{$orig_key} = 1;
1719             }
1720             }
1721             } else {
1722 0 0         if ($e eq $key) {
1723 0           $$return_hash{$e} = $$hash{$orig_key};
1724 0           $$found{$orig_key} = 1;
1725             }
1726             }
1727             }
1728             }
1729              
1730 0           my $left_overs = {};
1731 0           while (my ($key, $value) = each %$hash) {
1732 0 0         $$left_overs{$key} = $value unless exists($$found{$key});
1733             }
1734              
1735 0 0         return wantarray ? ($return_hash, $left_overs) : $return_hash;
1736             }
1737            
1738             sub TIEHASH {
1739 0     0     my ($proto, $obj) = @_;
1740 0           return $obj;
1741             }
1742              
1743             sub STORE {
1744 0     0     my ($self, $key, $val) = @_;
1745 0           my $params = $$self{_params};
1746             # FIXME: memory leak here - need to compress the array if has empty slots
1747             # push(@{$$self{_param_order}}, $key) unless exists($$params{$key});
1748 0           $$params{$key} = $val;
1749             }
1750              
1751             sub FETCH {
1752 0     0     my ($self, $key) = @_;
1753 0           my $params = $$self{_params};
1754 0           my $val = $$params{$key};
1755 0 0         if (ref($val) eq 'ARRAY') {
1756 0           my $delimiter = $$self{_multivalue_delimiter};
1757 0 0         $val = join($delimiter, @$val) unless $delimiter eq '';
1758             }
1759 0           return $val;
1760             }
1761              
1762             sub FIRSTKEY {
1763 0     0     my ($self) = @_;
1764 0           my @keys = keys %{$$self{_params}};
  0            
1765 0           $$self{_keys} = \@keys;
1766 0           return shift @keys;
1767             }
1768              
1769             sub NEXTKEY {
1770 0     0     my ($self) = @_;
1771 0           return shift(@{$$self{_keys}});
  0            
1772             }
1773              
1774             sub EXISTS {
1775 0     0     my ($self, $key) = @_;
1776 0           my $params = $$self{_params};
1777 0           return exists($$params{$key});
1778             }
1779              
1780             sub DELETE {
1781 0     0     my ($self, $key) = @_;
1782 0           my $params = $$self{_params};
1783 0           delete $$params{$key};
1784             }
1785              
1786             sub CLEAR {
1787 0     0     my ($self) = @_;
1788 0           %{$$self{_params}} = ();
  0            
1789             }
1790              
1791             sub _parseParams {
1792 0     0     my ($self, $query_string) = @_;
1793 0           ($$self{_params}, $$self{_param_order}) = $self->urlDecodeVars($query_string);
1794             }
1795              
1796             sub _readPostData {
1797 0     0     my ($self, $fh, $buf, $len) = @_;
1798 0           return CORE::read($fh, $$buf, $len);
1799             }
1800              
1801             sub _readMultipartData {
1802 0     0     my ($self, $boundary, $content_length, $fh) = @_;
1803 0           my $line;
1804 0           my $eol = $self->_getEndOfLineSeq;
1805 0           my $end_char = substr($eol, -1, 1);
1806 0           my $buf;
1807 0           my $len = 1024;
1808 0           my $amt_read = 0;
1809 0           my $sep = "--$boundary$eol";
1810              
1811 0           my $params = {};
1812 0           my $param_order = [];
1813              
1814 0           while (my $size = $self->_read($fh, $buf, $len, 0, $end_char)) {
1815 0           $amt_read += $size;
1816 0 0         if ($buf eq $sep) {
1817 0           last;
1818             }
1819 0 0         last unless $amt_read < $content_length;
1820             }
1821              
1822 0           while ($amt_read < $content_length) {
1823 0           my ($headers, $amt) = $self->_readMultipartHeader($fh);
1824 0           $amt_read += $amt;
1825 0           my $disp = $$headers{'content-disposition'};
1826 0           my ($type, @fields) = split /;\s*/, $disp;
1827 0           my %disp_fields = map { s/^(\")(.+)\1$/$2/; $_ } map { split(/=/, $_, 2) } @fields;
  0            
  0            
  0            
1828 0           my $name = $disp_fields{name};
1829 0           my ($body, $body_size) = $self->_readMultipartBody($boundary, $fh, $headers, \%disp_fields);
1830 0           $amt_read += $body_size;
1831              
1832 0 0         next if $name eq '';
1833              
1834 0 0         if (exists($$params{$name})) {
1835 0           my $val = $$params{$name};
1836 0 0         if (ref($val) eq 'ARRAY') {
1837 0           push @$val, $body;
1838             } else {
1839 0           my $array = [ $val, $body ];
1840 0           $$params{$name} = $array;
1841             }
1842             } else {
1843 0           $$params{$name} = $body;
1844 0           push @$param_order, $name;
1845             }
1846              
1847             }
1848              
1849 0           $$self{_params} = $params;
1850 0           $$self{_param_order} = $param_order;
1851              
1852 0           return 1;
1853             }
1854              
1855             sub _readMultipartBody {
1856 0     0     my ($self, $boundary, $fh, $headers, $disposition_fields) = @_;
1857              
1858 0           local($^W) = 0; # turn off lame warnings
1859            
1860 0 0         if ($$disposition_fields{filename} ne '') {
1861 0           return $self->_readMultipartBodyToFile($boundary, $fh, $headers, $disposition_fields);
1862             }
1863            
1864 0           my $amt_read = 0;
1865 0           my $eol = $self->_getEndOfLineSeq;
1866 0           my $end_char = substr($eol, -1, 1);
1867 0           my $buf;
1868             my $body;
1869              
1870 0           while (my $size = $self->_read($fh, $buf, 4096, 0, $end_char)) {
1871 0           $amt_read += $size;
1872 0 0 0       if (substr($buf, -1, 1) eq $end_char and $buf =~ /^--$boundary(?:--)?$eol$/
      0        
1873             and $body =~ /$eol$/
1874             ) {
1875 0           $body =~ s/$eol$//;
1876 0           last;
1877             }
1878 0           $body .= $buf;
1879             }
1880              
1881 0 0         return wantarray ? ($body, $amt_read) : $body;
1882             }
1883              
1884             sub _readMultipartBodyToFile {
1885 0     0     my ($self, $boundary, $fh, $headers, $disposition_fields) = @_;
1886              
1887 0           my $amt_read = 0;
1888 0           my $body;
1889 0           my $eol = $self->_getEndOfLineSeq;
1890 0           my $end_char = substr($eol, -1, 1);
1891 0           my $buf = '';
1892 0           my $buf2 = '';
1893              
1894 0           my $file_name = $$disposition_fields{filename};
1895 0           my $info = { 'Content-Type' => $$headers{'content-type'} };
1896 0           $$self{_upload_info}{$file_name} = $info;
1897              
1898 0           my $out_fh = CGI::Utils::UploadFile->new_tmpfile($file_name);
1899            
1900 0           while (my $size = $self->_read($fh, $buf, 4096, 0, $end_char)) {
1901 0           $amt_read += $size;
1902 0 0 0       if (substr($buf, -1, 1) eq $end_char and $buf =~ /^--$boundary(?:--)?$eol$/
      0        
1903             and $buf2 =~ /$eol$/
1904             ) {
1905 0           $buf2 =~ s/$eol$//;
1906 0           $buf = '';
1907 0           print $out_fh $buf2;
1908 0           last;
1909             }
1910 0           print $out_fh $buf2;
1911 0           $buf2 = $buf;
1912 0           $buf = '';
1913             }
1914 0 0         if ($buf ne '') {
1915 0           print $out_fh $buf;
1916             }
1917 0           select((select($out_fh), $| = 1)[0]);
1918 0           seek($out_fh, 0, 0); # seek back to beginning of file
1919            
1920 0 0         return wantarray ? ($out_fh, $amt_read) : $out_fh;
1921             }
1922              
1923             =pod
1924              
1925             =head2 uploadInfo($file_name)
1926              
1927             Returns a reference to a hash containing the header information
1928             sent along with a file upload.
1929              
1930             =cut
1931             # provided for compatibility with CGI.pm
1932             sub uploadInfo {
1933 0     0 1   my ($self, $file_name) = @_;
1934 0           $self->parse;
1935 0           return $$self{_upload_info}{$file_name};
1936             }
1937              
1938             sub _readMultipartHeader {
1939 0     0     my ($self, $fh) = @_;
1940 0           my $amt_read = 0;
1941 0           my $eol = $self->_getEndOfLineSeq;
1942 0           my $end_char = substr($eol, -1, 1);
1943 0           my $buf;
1944             my $header_str;
1945 0           while (my $size = $self->_read($fh, $buf, 4096, 0, $end_char)) {
1946 0           $amt_read += $size;
1947 0 0         last if $buf eq $eol;
1948 0           $header_str .= $buf;
1949             }
1950              
1951 0           my $headers = {};
1952 0           my $last_header;
1953 0           foreach my $line (split($eol, $header_str)) {
1954 0 0         if ($line =~ /^(\S+):\s*(.+)$/) {
    0          
1955 0           $last_header = lc($1);
1956 0           $$headers{$last_header} = $2;
1957             } elsif ($line =~ /^\s+/) {
1958 0           $$headers{$last_header} .= $eol . $line;
1959             }
1960             }
1961              
1962 0 0         return wantarray ? ($headers, $amt_read) : $headers;
1963             }
1964              
1965             sub _getEndOfLineSeq {
1966 0     0     return "\x0d\x0a"; # "\015\012" in octal
1967             }
1968              
1969             sub _read {
1970 0     0     my ($self, $fh, $buf, $len, $offset, $end_char) = @_;
1971 0 0         return '' if $len == 0;
1972 0           my $cur_len = 0;
1973 0           my $buffer;
1974 0           my $buf_ref = \$buffer;
1975 0           my $char;
1976 0           while (defined($char = CORE::getc($fh))) {
1977 0           $$buf_ref .= $char;
1978 0           $cur_len++;
1979 0 0 0       if ($char eq $end_char or $cur_len == $len) {
1980 0 0         if ($offset > 0) {
1981 0           substr($_[2], $offset, $cur_len) = $$buf_ref;
1982             } else {
1983 0           $_[2] = $$buf_ref;
1984             }
1985 0           return $cur_len;
1986             }
1987             }
1988 0           return 0;
1989             }
1990              
1991             =pod
1992              
1993             =head1 Apache constants under mod_perl
1994              
1995             Shortcut methods are provided for returning Apache constants
1996             under mod_perl. The methods figure out if they are running under
1997             mod_perl 1 or 2 and make the appropriate call to get the right
1998             constant back, e.g., Apache::Constants::OK() versus Apache::OK().
1999             The methods are created on the fly using AUTOLOAD. The method
2000             names are in the format apache_$name where $name is the
2001             lowercased constant name, e.g., $utils->apache_ok,
2002             $utils->apache_forbidden. See
2003             L for
2004             a list of constants available.
2005              
2006             =cut
2007            
2008             sub AUTOLOAD {
2009 0     0     my $self = shift;
2010 0           (my $method = $AUTOLOAD) =~ s{\A.*\:\:([^:]+)\Z}{$1};
2011              
2012 0 0         if ($method eq 'DESTROY') {
2013 0           return;
2014             }
2015              
2016 0 0         if ($method =~ /\Aapache_(.+)/) {
2017 0           my $const = uc($1);
2018 0           eval "sub $method "
2019             . "{ return MP2 ? Apache\:\:$const() : Apache\:\:Constants\:\:$const(); }";
2020 0 0         unless ($@) {
2021 0           return $self->$method;
2022             }
2023              
2024 0           return;
2025             }
2026              
2027 0           die "no such method $method in package " . __PACKAGE__;
2028             }
2029             }
2030              
2031             1;
2032              
2033             =pod
2034              
2035             =head1 EXPORTS
2036              
2037             You can export methods into your namespace in the usual way.
2038             All of the util methods are available for export, e.g.,
2039             getSelfRefUrl(), addParamsToUrl(), etc. Beware, however, that
2040             these methods expect to be called as methods. You can also use
2041             the tag :all_utils to import all of the util methods into your
2042             namespace. This allows for incorporating these methods into
2043             your class without having to inherit from CGI::Utils.
2044              
2045             =head1 ACKNOWLEDGEMENTS
2046              
2047             Other people who have contributed ideas and/or code for this module:
2048              
2049             Kevin Wilson
2050              
2051             =head1 AUTHOR
2052              
2053             Don Owens
2054              
2055             =head1 COPYRIGHT
2056              
2057             Copyright (c) 2003-2008 Don Owens
2058              
2059             All rights reserved. This program is free software; you can
2060             redistribute it and/or modify it under the same terms as Perl
2061             itself.
2062              
2063             =head1 VERSION
2064              
2065             0.12
2066              
2067             =cut