File Coverage

blib/lib/CGI.pm
Criterion Covered Total %
statement 1287 1574 81.7
branch 627 1026 61.1
condition 330 532 62.0
subroutine 142 172 82.5
pod 36 134 26.8
total 2422 3438 70.4


line stmt bran cond sub pod time code
1             package CGI;
2             require 5.008001;
3 56     56   663410 use if $] >= 5.019, 'deprecate';
  56         394  
  56         238  
4 56     56   43979 use Carp 'croak';
  56         73  
  56         3891  
5              
6             my $appease_cpants_kwalitee = q/
7             use strict;
8             use warnings;
9             #/;
10              
11             $CGI::VERSION='4.35_01';
12              
13 56     56   17170 use CGI::Util qw(rearrange rearrange_header make_attributes unescape escape expires ebcdic2ascii ascii2ebcdic);
  56         91  
  56         999008  
14              
15             $_XHTML_DTD = ['-//W3C//DTD XHTML 1.0 Transitional//EN',
16             'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'];
17              
18             {
19             local $^W = 0;
20             $TAINTED = substr("$0$^X",0,0);
21             }
22              
23             $MOD_PERL = 0; # no mod_perl by default
24              
25             #global settings
26             $POST_MAX = -1; # no limit to uploaded files
27             $DISABLE_UPLOADS = 0;
28             $UNLINK_TMP_FILES = 1;
29             $LIST_CONTEXT_WARN = 1;
30             $ENCODE_ENTITIES = q{&<>"'};
31             $ALLOW_DELETE_CONTENT = 0;
32              
33             @SAVED_SYMBOLS = ();
34              
35             # >>>>> Here are some globals that you might want to adjust <<<<<<
36             sub initialize_globals {
37             # Set this to 1 to generate XTML-compatible output
38 84     84 0 2146 $XHTML = 1;
39              
40             # Change this to the preferred DTD to print in start_html()
41             # or use default_dtd('text of DTD to use');
42 84         153 $DEFAULT_DTD = [ '-//W3C//DTD HTML 4.01 Transitional//EN',
43             'http://www.w3.org/TR/html4/loose.dtd' ] ;
44              
45             # Set this to 1 to enable NOSTICKY scripts
46             # or:
47             # 1) use CGI '-nosticky';
48             # 2) $CGI::NOSTICKY = 1;
49 84         101 $NOSTICKY = 0;
50              
51             # Set this to 1 to enable NPH scripts
52             # or:
53             # 1) use CGI qw(-nph)
54             # 2) CGI::nph(1)
55             # 3) print header(-nph=>1)
56 84         93 $NPH = 0;
57              
58             # Set this to 1 to enable debugging from @ARGV
59             # Set to 2 to enable debugging from STDIN
60 84         82 $DEBUG = 1;
61              
62             # Set this to 1 to generate automatic tab indexes
63 84         71 $TABINDEX = 0;
64              
65             # Set this to 1 to cause files uploaded in multipart documents
66             # to be closed, instead of caching the file handle
67             # or:
68             # 1) use CGI qw(:close_upload_files)
69             # 2) $CGI::close_upload_files(1);
70             # Uploads with many files run out of file handles.
71             # Also, for performance, since the file is already on disk,
72             # it can just be renamed, instead of read and written.
73 84         69 $CLOSE_UPLOAD_FILES = 0;
74              
75             # Automatically determined -- don't change
76 84         85 $EBCDIC = 0;
77              
78             # Change this to 1 to suppress redundant HTTP headers
79 84         66 $HEADERS_ONCE = 0;
80              
81             # separate the name=value pairs by semicolons rather than ampersands
82 84         83 $USE_PARAM_SEMICOLONS = 1;
83              
84             # Do not include undefined params parsed from query string
85             # use CGI qw(-no_undef_params);
86 84         75 $NO_UNDEF_PARAMS = 0;
87              
88             # return everything as utf-8
89 84         93 $PARAM_UTF8 = 0;
90              
91             # make param('PUTDATA') act like file upload
92 84         123 $PUTDATA_UPLOAD = 0;
93              
94             # Other globals that you shouldn't worry about.
95 84         118 undef $Q;
96 84         76 $BEEN_THERE = 0;
97 84         109 $DTD_PUBLIC_IDENTIFIER = "";
98 84         122 undef @QUERY_PARAM;
99 84         106 undef %QUERY_PARAM;
100 84         162 undef %EXPORT;
101 84         83 undef $QUERY_CHARSET;
102 84         80 undef %QUERY_FIELDNAMES;
103 84         101 undef %QUERY_TMPFILES;
104              
105             # prevent complaints by mod_perl
106 84         1023 1;
107             }
108              
109             # ------------------ START OF THE LIBRARY ------------
110              
111             # make mod_perlhappy
112             initialize_globals();
113              
114             # FIGURE OUT THE OS WE'RE RUNNING UNDER
115             # Some systems support the $^O variable. If not
116             # available then require() the Config library
117             unless ($OS) {
118             unless ($OS = $^O) {
119             require Config;
120             $OS = $Config::Config{'osname'};
121             }
122             }
123             if ($OS =~ /^MSWin/i) {
124             $OS = 'WINDOWS';
125             } elsif ($OS =~ /^VMS/i) {
126             $OS = 'VMS';
127             } elsif ($OS =~ /^dos/i) {
128             $OS = 'DOS';
129             } elsif ($OS =~ /^MacOS/i) {
130             $OS = 'MACINTOSH';
131             } elsif ($OS =~ /^os2/i) {
132             $OS = 'OS2';
133             } elsif ($OS =~ /^epoc/i) {
134             $OS = 'EPOC';
135             } elsif ($OS =~ /^cygwin/i) {
136             $OS = 'CYGWIN';
137             } elsif ($OS =~ /^NetWare/i) {
138             $OS = 'NETWARE';
139             } else {
140             $OS = 'UNIX';
141             }
142              
143             # Some OS logic. Binary mode enabled on DOS, NT and VMS
144             $needs_binmode = $OS=~/^(WINDOWS|DOS|OS2|MSWin|CYGWIN|NETWARE)/;
145              
146             # This is the default class for the CGI object to use when all else fails.
147             $DefaultClass = 'CGI' unless defined $CGI::DefaultClass;
148              
149             # The path separator is a slash, backslash or semicolon, depending
150             # on the platform.
151             $SL = {
152             UNIX => '/', OS2 => '\\', EPOC => '/', CYGWIN => '/', NETWARE => '/',
153             WINDOWS => '\\', DOS => '\\', MACINTOSH => ':', VMS => '/'
154             }->{$OS};
155              
156             # This no longer seems to be necessary
157             # Turn on NPH scripts by default when running under IIS server!
158             # $NPH++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/;
159             $IIS++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/;
160              
161             # Turn on special checking for ActiveState's PerlEx
162             $PERLEX++ if defined($ENV{'GATEWAY_INTERFACE'}) && $ENV{'GATEWAY_INTERFACE'} =~ /^CGI-PerlEx/;
163              
164             # Turn on special checking for Doug MacEachern's modperl
165             # PerlEx::DBI tries to fool DBI by setting MOD_PERL
166             if (exists $ENV{MOD_PERL} && ! $PERLEX) {
167             # mod_perl handlers may run system() on scripts using CGI.pm;
168             # Make sure so we don't get fooled by inherited $ENV{MOD_PERL}
169             if (exists $ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2) {
170             $MOD_PERL = 2;
171             require Apache2::Response;
172             require Apache2::RequestRec;
173             require Apache2::RequestUtil;
174             require Apache2::RequestIO;
175             require APR::Pool;
176             } else {
177             $MOD_PERL = 1;
178             require Apache;
179             }
180             }
181              
182             # Define the CRLF sequence. I can't use a simple "\r\n" because the meaning
183             # of "\n" is different on different OS's (sometimes it generates CRLF, sometimes LF
184             # and sometimes CR). The most popular VMS web server
185             # doesn't accept CRLF -- instead it wants a LR. EBCDIC machines don't
186             # use ASCII, so \015\012 means something different. I find this all
187             # really annoying.
188             $EBCDIC = "\t" ne "\011";
189             if ($OS eq 'VMS') {
190             $CRLF = "\n";
191             } elsif ($EBCDIC) {
192             $CRLF= "\r\n";
193             } else {
194             $CRLF = "\015\012";
195             }
196              
197             _set_binmode() if ($needs_binmode);
198              
199             sub _set_binmode {
200              
201             # rt #57524 - don't set binmode on filehandles if there are
202             # already none default layers set on them
203 1     1   675 my %default_layers = (
204             unix => 1,
205             perlio => 1,
206             stdio => 1,
207             crlf => 1,
208             );
209              
210 1         4 foreach my $fh (
211             \*main::STDOUT,
212             \*main::STDIN,
213             \*main::STDERR,
214             ) {
215 3         8 my @modes = grep { ! $default_layers{$_} }
  7         10  
216             PerlIO::get_layers( $fh );
217              
218 3 100       9 if ( ! @modes ) {
219 2         12 $CGI::DefaultClass->binmode( $fh );
220             }
221             }
222             }
223              
224             %EXPORT_TAGS = (
225             ':html2' => [ 'h1' .. 'h6', qw/
226             p br hr ol ul li dl dt dd menu code var strong em
227             tt u i b blockquote pre img a address cite samp dfn html head
228             base body Link nextid title meta kbd start_html end_html
229             input Select option comment charset escapeHTML
230             / ],
231             ':html3' => [ qw/
232             div table caption th td TR Tr sup Sub strike applet Param nobr
233             embed basefont style span layer ilayer font frameset frame script small big Area Map
234             / ],
235             ':html4' => [ qw/
236             abbr acronym bdo col colgroup del fieldset iframe
237             ins label legend noframes noscript object optgroup Q
238             thead tbody tfoot
239             / ],
240             ':form' => [ qw/
241             textfield textarea filefield password_field hidden checkbox checkbox_group
242             submit reset defaults radio_group popup_menu button autoEscape
243             scrolling_list image_button start_form end_form
244             start_multipart_form end_multipart_form isindex tmpFileName uploadInfo URL_ENCODED MULTIPART
245             / ],
246             ':cgi' => [ qw/
247             param multi_param upload path_info path_translated request_uri url self_url script_name
248             cookie Dump raw_cookie request_method query_string Accept user_agent remote_host content_type
249             remote_addr referer server_name server_software server_port server_protocol virtual_port
250             virtual_host remote_ident auth_type http append save_parameters restore_parameters param_fetch
251             remote_user user_name header redirect import_names put Delete Delete_all url_param cgi_error env_query_string
252             / ],
253             ':netscape' => [qw/blink fontsize center/],
254             ':ssl' => [qw/https/],
255             ':cgi-lib' => [qw/ReadParse PrintHeader HtmlTop HtmlBot SplitParam Vars/],
256             ':push' => [qw/multipart_init multipart_start multipart_end multipart_final/],
257              
258             # bulk export/import
259             ':html' => [qw/:html2 :html3 :html4 :netscape/],
260             ':standard' => [qw/:html2 :html3 :html4 :form :cgi :ssl/],
261             ':all' => [qw/:html2 :html3 :html4 :netscape :form :cgi :ssl :push/]
262             );
263              
264             # to import symbols into caller
265             sub import {
266 56     56   4585 my $self = shift;
267              
268             # This causes modules to clash.
269 56         226 undef %EXPORT_OK;
270 56         71 undef %EXPORT;
271              
272 56         160 $self->_setup_symbols(@_);
273 56         177 my ($callpack, $callfile, $callline) = caller;
274              
275 56 50       165 if ( $callpack eq 'CGI::Fast' ) {
276             # fixes GH #11 (and GH #12 in CGI::Fast since
277             # sub import was added to CGI::Fast in 9537f90
278             # so we need to move up a level to export the
279             # routines to the namespace of whatever is using
280             # CGI::Fast
281 0         0 ($callpack, $callfile, $callline) = caller(1);
282             }
283              
284             # To allow overriding, search through the packages
285             # Till we find one in which the correct subroutine is defined.
286 56         72 my @packages = ($self,@{"$self\:\:ISA"});
  56         305  
287 56         24993 for $sym (keys %EXPORT) {
288 2038         1120 my $pck;
289 2038         1231 my $def = $DefaultClass;
290 2038         1319 for $pck (@packages) {
291 2038 50       1131 if (defined(&{"$pck\:\:$sym"})) {
  2038         3304  
292 2038         1239 $def = $pck;
293 2038         1249 last;
294             }
295             }
296 2038         1065 *{"${callpack}::$sym"} = \&{"$def\:\:$sym"};
  2038         23868  
  2038         1990  
297             }
298             }
299              
300             sub expand_tags {
301 2256     2256 0 1464 my($tag) = @_;
302 2256 100       3099 return ("start_$1","end_$1") if $tag=~/^(?:\*|start_|end_)(.+)/;
303 2128         1155 my(@r);
304 2128 100       3332 return ($tag) unless $EXPORT_TAGS{$tag};
305 93         62 for (@{$EXPORT_TAGS{$tag}}) {
  93         117  
306 2173         1827 push(@r,&expand_tags($_));
307             }
308 93         745 return @r;
309             }
310              
311             #### Method: new
312             # The new routine. This will check the current environment
313             # for an existing query string, and initialize itself, if so.
314             ####
315             sub new {
316 138     138 1 20164 my($class,@initializer) = @_;
317 138         229 my $self = {};
318              
319 138   33     766 bless $self,ref $class || $class || $DefaultClass;
320              
321             # always use a tempfile
322 138         474 $self->{'use_tempfile'} = 1;
323              
324 138 50 33     380 if (ref($initializer[0])
      66        
325             && (UNIVERSAL::isa($initializer[0],'Apache')
326             ||
327             UNIVERSAL::isa($initializer[0],'Apache2::RequestRec')
328             )) {
329 0         0 $self->r(shift @initializer);
330             }
331 138 100 100     376 if (ref($initializer[0])
332             && (UNIVERSAL::isa($initializer[0],'CODE'))) {
333 3         7 $self->upload_hook(shift @initializer, shift @initializer);
334 3 50       6 $self->{'use_tempfile'} = shift @initializer if (@initializer > 0);
335             }
336 138 50       307 if ($MOD_PERL) {
337 0 0       0 if ($MOD_PERL == 1) {
338 0 0       0 $self->r(Apache->request) unless $self->r;
339 0         0 my $r = $self->r;
340 0         0 $r->register_cleanup(\&CGI::_reset_globals);
341 0 0       0 $self->_setup_symbols(@SAVED_SYMBOLS) if @SAVED_SYMBOLS;
342             }
343             else {
344             # XXX: once we have the new API
345             # will do a real PerlOptions -SetupEnv check
346 0 0       0 $self->r(Apache2::RequestUtil->request) unless $self->r;
347 0         0 my $r = $self->r;
348 0 0       0 $r->subprocess_env unless exists $ENV{REQUEST_METHOD};
349 0         0 $r->pool->cleanup_register(\&CGI::_reset_globals);
350 0 0       0 $self->_setup_symbols(@SAVED_SYMBOLS) if @SAVED_SYMBOLS;
351             }
352 0         0 undef $NPH;
353             }
354 138 50       269 $self->_reset_globals if $PERLEX;
355 138         410 $self->init(@initializer);
356 138         325 return $self;
357             }
358              
359             sub r {
360 2     2 0 3 my $self = shift;
361 2         2 my $r = $self->{'.r'};
362 2 100       5 $self->{'.r'} = shift if @_;
363 2         5 $r;
364             }
365              
366             sub upload_hook {
367 3     3 0 3 my $self;
368 3 50       8 if (ref $_[0] eq 'CODE') {
369 0         0 $CGI::Q = $self = $CGI::DefaultClass->new(@_);
370             } else {
371 3         2 $self = shift;
372             }
373 3         4 my ($hook,$data,$use_tempfile) = @_;
374 3         4 $self->{'.upload_hook'} = $hook;
375 3         3 $self->{'.upload_data'} = $data;
376 3 50       14 $self->{'use_tempfile'} = $use_tempfile if defined $use_tempfile;
377             }
378              
379             #### Method: param / multi_param
380             # Returns the value(s)of a named parameter.
381             # If invoked in a list context, returns the
382             # entire list. Otherwise returns the first
383             # member of the list.
384             # If name is not provided, return a list of all
385             # the known parameters names available.
386             # If more than one argument is provided, the
387             # second and subsequent arguments are used to
388             # set the value of the parameter.
389             #
390             # note that calling param() in list context
391             # will raise a warning about potential bad
392             # things, hence the multi_param method
393             ####
394             sub multi_param {
395             # we don't need to set $LIST_CONTEXT_WARN to 0 here
396             # because param() will check the caller before warning
397 17     17 0 7003 my @list_of_params = param( @_ );
398 17         22 return @list_of_params;
399             }
400              
401             sub param {
402 1095     1095 0 9061 my($self,@p) = self_or_default(@_);
403              
404 1095 100       2022 return $self->all_parameters unless @p;
405              
406             # list context can be dangerous so warn:
407             # http://blog.gerv.net/2014.10/new-class-of-vulnerability-in-perl-web-applications
408 656 100 100     1579 if ( wantarray && $LIST_CONTEXT_WARN == 1 ) {
409 183         432 my ( $package, $filename, $line ) = caller;
410 183 100       431 if ( $package ne 'CGI' ) {
411 1         1 $LIST_CONTEXT_WARN++; # only warn once
412 1         18 warn "CGI::param called in list context from $filename line $line, this can lead to vulnerabilities. "
413             . 'See the warning in "Fetching the value or values of a single named parameter"';
414             }
415             }
416              
417 656         521 my($name,$value,@other);
418              
419             # For compatibility between old calling style and use_named_parameters() style,
420             # we have to special case for a single parameter present.
421 656 100       854 if (@p > 1) {
422 59         183 ($name,$value,@other) = rearrange([NAME,[DEFAULT,VALUE,VALUES]],@p);
423 59         72 my(@values);
424              
425 59 100       98 if (substr($p[0],0,1) eq '-') {
426 47 100 66     166 @values = defined($value) ? (ref($value) && ref($value) eq 'ARRAY' ? @{$value} : $value) : ();
  37 100       48  
427             } else {
428 12         19 for ($value,@other) {
429 12 100       26 push(@values,$_) if defined($_);
430             }
431             }
432             # If values is provided, then we set it.
433 59 100 66     155 if (@values or defined $value) {
434 47         80 $self->add_parameter($name);
435 47         96 $self->{param}{$name}=[@values];
436             }
437             } else {
438 597         510 $name = $p[0];
439             }
440              
441 656 100 66     2233 return unless defined($name) && $self->{param}{$name};
442              
443 326         245 my @result = @{$self->{param}{$name}};
  326         460  
444              
445 326 50 66     617 if ($PARAM_UTF8 && $name ne 'PUTDATA' && $name ne 'POSTDATA' && $name ne 'PATCHDATA') {
      66        
      33        
446 5 50       28 eval "require Encode; 1;" unless Encode->can('decode'); # bring in these functions
447 5 50       6 @result = map {ref $_ ? $_ : $self->_decode_utf8($_) } @result;
  5         13  
448             }
449              
450 326 100       1100 return wantarray ? @result : $result[0];
451             }
452              
453             sub _decode_utf8 {
454 5     5   6 my ($self, $val) = @_;
455              
456 5 100       10 if (Encode::is_utf8($val)) {
457 2         7 return $val;
458             }
459             else {
460 3         7 return Encode::decode(utf8 => $val);
461             }
462             }
463              
464             sub self_or_default {
465 3860 100 100 3860 0 13444 return @_ if defined($_[0]) && (!ref($_[0])) &&($_[0] eq 'CGI');
      100        
466 3859 100 100     10109 unless (defined($_[0]) &&
      66        
467             (ref($_[0]) eq 'CGI' || UNIVERSAL::isa($_[0],'CGI')) # slightly optimized for common case
468             ) {
469 374 100       686 $Q = $CGI::DefaultClass->new unless defined($Q);
470 374         514 unshift(@_,$Q);
471             }
472 3859 50       7244 return wantarray ? @_ : $Q;
473             }
474              
475             sub self_or_CGI {
476 187     187 0 249 local $^W=0; # prevent a warning
477 187 100 100     795 if (defined($_[0]) &&
      33        
478             (substr(ref($_[0]),0,3) eq 'CGI'
479             || UNIVERSAL::isa($_[0],'CGI'))) {
480 131         221 return @_;
481             } else {
482 56         112 return ($DefaultClass,@_);
483             }
484             }
485              
486             ########################################
487             # THESE METHODS ARE MORE OR LESS PRIVATE
488             # GO TO THE __DATA__ SECTION TO SEE MORE
489             # PUBLIC METHODS
490             ########################################
491              
492             # Initialize the query object from the environment.
493             # If a parameter list is found, this object will be set
494             # to a hash in which parameter names are keys
495             # and the values are stored as lists
496             # If a keyword list is found, this method creates a bogus
497             # parameter list with the single parameter 'keywords'.
498              
499             sub init {
500 138     138 0 162 my $self = shift;
501 138         294 my($query_string,$meth,$content_length,$fh,@lines) = ('','','','');
502              
503 138         133 my $is_xforms;
504              
505 138         133 my $initializer = shift; # for backward compatibility
506 138         473 local($/) = "\n";
507              
508             # set autoescaping on by default
509 138         224 $self->{'escape'} = 1;
510              
511             # if we get called more than once, we want to initialize
512             # ourselves from the original query (which may be gone
513             # if it was read from STDIN originally.)
514 138 100 100     444 if (@QUERY_PARAM && !defined($initializer)) {
515 5         11 for my $name (@QUERY_PARAM) {
516 18         23 my $val = $QUERY_PARAM{$name}; # always an arrayref;
517 18         29 $self->param('-name'=>$name,'-value'=> $val);
518 18 50 33     64 if (defined $val and ref $val eq 'ARRAY') {
519 18 100 66     19 for my $fh (grep {defined($_) && ref($_) && defined(fileno($_))} @$val) {
  23         120  
520 20         49 seek($fh,0,0); # reset the filehandle.
521             }
522              
523             }
524             }
525 5         99 $self->charset($QUERY_CHARSET);
526 5         11 $self->{'.fieldnames'} = {%QUERY_FIELDNAMES};
527 5         26 $self->{'.tmpfiles'} = {%QUERY_TMPFILES};
528 5         14 return;
529             }
530              
531 133 100       367 $meth=$ENV{'REQUEST_METHOD'} if defined($ENV{'REQUEST_METHOD'});
532 133 100       324 $content_length = defined($ENV{'CONTENT_LENGTH'}) ? $ENV{'CONTENT_LENGTH'} : 0;
533              
534 133 100       253 $fh = to_filehandle($initializer) if $initializer;
535              
536             # set charset to the safe ISO-8859-1
537 133         350 $self->charset('ISO-8859-1');
538              
539             METHOD: {
540              
541             # avoid unreasonably large postings
542 133 50 33     127 if (($POST_MAX > 0) && ($content_length > $POST_MAX)) {
  133         338  
543             #discard the post, unread
544 0         0 $self->cgi_error("413 Request entity too large");
545 0         0 last METHOD;
546             }
547              
548             # Process multipart postings, but only if the initializer is
549             # not defined.
550 133 100 100     473 if ($meth eq 'POST'
      100        
      66        
551             && defined($ENV{'CONTENT_TYPE'})
552             && $ENV{'CONTENT_TYPE'}=~m|^multipart/form-data|
553             && !defined($initializer)
554             ) {
555 2         12 my($boundary) = $ENV{'CONTENT_TYPE'} =~ /boundary=\"?([^\";,]+)\"?/;
556 2         8 $self->read_multipart($boundary,$content_length);
557 2         5 last METHOD;
558             }
559              
560             # Process XForms postings. We know that we have XForms in the
561             # following cases:
562             # method eq 'POST' && content-type eq 'application/xml'
563             # method eq 'POST' && content-type =~ /multipart\/related.+start=/
564             # There are more cases, actually, but for now, we don't support other
565             # methods for XForm posts.
566             # In a XForm POST, the QUERY_STRING is parsed normally.
567             # If the content-type is 'application/xml', we just set the param
568             # XForms:Model (referring to the xml syntax) param containing the
569             # unparsed XML data.
570             # In the case of multipart/related we set XForms:Model as above, but
571             # the other parts are available as uploads with the Content-ID as the
572             # the key.
573             # See the URL below for XForms specs on this issue.
574             # http://www.w3.org/TR/2006/REC-xforms-20060314/slice11.html#submit-options
575 131 100 100     359 if ($meth eq 'POST' && defined($ENV{'CONTENT_TYPE'})) {
576 12 100       82 if ($ENV{'CONTENT_TYPE'} eq 'application/xml') {
    100          
577 1         3 my($param) = 'XForms:Model';
578 1         2 my($value) = '';
579 1         6 $self->add_parameter($param);
580 1 50       7 $self->read_from_client(\$value,$content_length,0)
581             if $content_length > 0;
582 1         2 push (@{$self->{param}{$param}},$value);
  1         5  
583 1         1 $is_xforms = 1;
584             } elsif ($ENV{'CONTENT_TYPE'} =~ /multipart\/related.+boundary=\"?([^\";,]+)\"?.+start=\"?\]+)\>?\"?/) {
585 8         23 my($boundary,$start) = ($1,$2);
586 8         9 my($param) = 'XForms:Model';
587 8         19 $self->add_parameter($param);
588 8         22 my($value) = $self->read_multipart_related($start,$boundary,$content_length,0);
589 8         15 push (@{$self->{param}{$param}},$value);
  8         18  
590 8         15 $query_string = $self->_get_query_string_from_env;
591 8         11 $is_xforms = 1;
592             }
593             }
594              
595              
596             # If initializer is defined, then read parameters
597             # from it.
598 131 100 100     507 if (!$is_xforms && defined($initializer)) {
599 12 50       48 if (UNIVERSAL::isa($initializer,'CGI')) {
600 0         0 $query_string = $initializer->query_string;
601 0         0 last METHOD;
602             }
603 12 100 100     53 if (ref($initializer) && ref($initializer) eq 'HASH') {
604 1         3 for (keys %$initializer) {
605 2         5 $self->param('-name'=>$_,'-value'=>$initializer->{$_});
606             }
607 1         2 last METHOD;
608             }
609              
610 11 100 66     43 if (defined($fh) && ($fh ne '')) {
611 4         51 while (my $line = <$fh>) {
612 9         16 chomp $line;
613 9 100       57 last if $line =~ /^=$/;
614 8         31 push(@lines,$line);
615             }
616             # massage back into standard format
617 4 50       24 if ("@lines" =~ /=/) {
618 4         10 $query_string=join("&",@lines);
619             } else {
620 0         0 $query_string=join("+",@lines);
621             }
622 4         9 last METHOD;
623             }
624              
625             # last chance -- treat it as a string
626 7 50       20 $initializer = $$initializer if ref($initializer) eq 'SCALAR';
627 7         9 $query_string = $initializer;
628              
629 7         12 last METHOD;
630             }
631              
632             # If method is GET, HEAD or DELETE, fetch the query from
633             # the environment.
634 119 100 100     745 if ($is_xforms || $meth=~/^(GET|HEAD|DELETE)$/) {
635 28         99 $query_string = $self->_get_query_string_from_env;
636 28 100       72 $self->param($meth . 'DATA', $self->param('XForms:Model'))
637             if $is_xforms;
638 28         55 last METHOD;
639             }
640              
641 91 100 100     622 if ($meth eq 'POST' || $meth eq 'PUT' || $meth eq 'PATCH') {
      100        
642 14 100       46 if ( $content_length > 0 ) {
643 13 100 66     182 if ( ( $PUTDATA_UPLOAD || $self->{'.upload_hook'} ) && !$is_xforms && ($meth eq 'POST' || $meth eq 'PUT' || $meth eq 'PATCH')
      66        
      66        
      66        
      33        
      33        
      33        
644             && defined($ENV{'CONTENT_TYPE'})
645             && $ENV{'CONTENT_TYPE'} !~ m|^application/x-www-form-urlencoded|
646             && $ENV{'CONTENT_TYPE'} !~ m|^multipart/form-data| ){
647 6         12 my $postOrPut = $meth . 'DATA' ; # POSTDATA/PUTDATA
648 6         13 $self->read_postdata_putdata( $postOrPut, $content_length, $ENV{'CONTENT_TYPE'} );
649 6         9 $meth = ''; # to skip xform testing
650 6         7 undef $query_string ;
651             } else {
652 7         47 $self->read_from_client(\$query_string,$content_length,0);
653             }
654             }
655             # Some people want to have their cake and eat it too!
656             # Uncomment this line to have the contents of the query string
657             # APPENDED to the POST data.
658             # $query_string .= (length($query_string) ? '&' : '') . $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'};
659 14         32 last METHOD;
660             }
661              
662             # If $meth is not of GET, POST, PUT or HEAD, assume we're
663             # being debugged offline.
664             # Check the command line and then the standard input for data.
665             # We use the shellwords package in order to behave the way that
666             # UN*X programmers expect.
667 77 100       237 if ($DEBUG)
668             {
669 74         161 my $cmdline_ret = read_from_cmdline();
670 74         109 $query_string = $cmdline_ret->{'query_string'};
671 74 50       210 if (defined($cmdline_ret->{'subpath'}))
672             {
673 0         0 $self->path_info($cmdline_ret->{'subpath'});
674             }
675             }
676             }
677              
678             # YL: Begin Change for XML handler 10/19/2001
679 133 100 100     1112 if (!$is_xforms && ($meth eq 'POST' || $meth eq 'PUT' || $meth eq 'PATCH')
      66        
      100        
      66        
      100        
680             && defined($ENV{'CONTENT_TYPE'})
681             && $ENV{'CONTENT_TYPE'} !~ m|^application/x-www-form-urlencoded|
682             && $ENV{'CONTENT_TYPE'} !~ m|^multipart/form-data| ) {
683 3         5 my($param) = $meth . 'DATA' ;
684 3         9 $self->add_parameter($param) ;
685 3         3 push (@{$self->{param}{$param}},$query_string);
  3         7  
686 3         4 undef $query_string ;
687             }
688             # YL: End Change for XML handler 10/19/2001
689              
690             # We now have the query string in hand. We do slightly
691             # different things for keyword lists and parameter lists.
692 133 100 100     585 if (defined $query_string && length $query_string) {
693 39 100       150 if ($query_string =~ /[&=;]/) {
694 34         105 $self->parse_params($query_string);
695             } else {
696 5         12 $self->add_parameter('keywords');
697 5         15 $self->{param}{'keywords'} = [$self->parse_keywordlist($query_string)];
698             }
699             }
700              
701             # Special case. Erase everything if there is a field named
702             # .defaults.
703 133 50       355 if ($self->param('.defaults')) {
704 0         0 $self->delete_all();
705             }
706              
707             # hash containing our defined fieldnames
708 133         223 $self->{'.fieldnames'} = {};
709 133         259 for ($self->param('.cgifields')) {
710 0         0 $self->{'.fieldnames'}->{$_}++;
711             }
712            
713             # Clear out our default submission button flag if present
714 133         396 $self->delete('.submit');
715 133         204 $self->delete('.cgifields');
716              
717 133 100       506 $self->save_request unless defined $initializer;
718             }
719              
720             sub _get_query_string_from_env {
721 36     36   88 my $self = shift;
722 36         42 my $query_string = '';
723              
724 36 50       62 if ( $MOD_PERL ) {
725 0         0 $query_string = $self->r->args;
726 0 0 0     0 if ( ! $query_string && $MOD_PERL == 2 ) {
727             # possibly a redirect, inspect prev request
728             # (->prev only supported under mod_perl2)
729 0 0       0 if ( my $prev = $self->r->prev ) {
730 0         0 $query_string = $prev->args;
731             }
732             }
733             }
734              
735             $query_string ||= $ENV{'QUERY_STRING'}
736 36 100 66     118 if defined $ENV{'QUERY_STRING'};
737              
738 36 100       76 if ( ! $query_string ) {
739             # try to get from REDIRECT_ env variables, support
740             # 5 levels of redirect and no more (RT #36312)
741 16         27 REDIRECT: foreach my $r ( 1 .. 5 ) {
742 60         70 my $key = join( '',( 'REDIRECT_' x $r ) );
743             $query_string ||= $ENV{"${key}QUERY_STRING"}
744 60 100 33     123 if defined $ENV{"${key}QUERY_STRING"};
745 60 100       82 last REDIRECT if $query_string;
746             }
747             }
748              
749 36         57 return $query_string;
750             }
751              
752             # FUNCTIONS TO OVERRIDE:
753             # Turn a string into a filehandle
754             sub to_filehandle {
755 13     13 0 16 my $thingy = shift;
756 13 50       34 return undef unless $thingy;
757 13 100       58 return $thingy if UNIVERSAL::isa($thingy,'GLOB');
758 8 50       29 return $thingy if UNIVERSAL::isa($thingy,'FileHandle');
759 8 100       17 if (!ref($thingy)) {
760 7         7 my $caller = 1;
761 7         24 while (my $package = caller($caller++)) {
762 14 50       47 my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy";
763 14 50       89 return $tmp if defined(fileno($tmp));
764             }
765             }
766 8         11 return undef;
767             }
768              
769             # send output to the browser
770             sub put {
771 0     0 0 0 my($self,@p) = self_or_default(@_);
772 0         0 $self->print(@p);
773             }
774              
775             # print to standard output (for overriding in mod_perl)
776             sub print {
777 0     0 0 0 shift;
778 0         0 CORE::print(@_);
779             }
780              
781             # get/set last cgi_error
782             sub cgi_error {
783 0     0 0 0 my ($self,$err) = self_or_default(@_);
784 0 0       0 $self->{'.cgi_error'} = $err if defined $err;
785 0         0 return $self->{'.cgi_error'};
786             }
787              
788             sub save_request {
789 114     114 0 129 my($self) = @_;
790             # We're going to play with the package globals now so that if we get called
791             # again, we initialize ourselves in exactly the same way. This allows
792             # us to have several of these objects.
793 114         175 @QUERY_PARAM = $self->param; # save list of parameters
794 114         188 for (@QUERY_PARAM) {
795 61 50       94 next unless defined $_;
796 61         103 $QUERY_PARAM{$_}=$self->{param}{$_};
797             }
798 114         186 $QUERY_CHARSET = $self->charset;
799 114         122 %QUERY_FIELDNAMES = %{$self->{'.fieldnames'}};
  114         260  
800 114 100       99 %QUERY_TMPFILES = %{ $self->{'.tmpfiles'} || {} };
  114         732  
801             }
802              
803             sub parse_params {
804 34     34 0 47 my($self,$tosplit) = @_;
805 34         173 my(@pairs) = split(/[&;]/,$tosplit);
806 34         34 my($param,$value);
807 34         66 for (@pairs) {
808 82         166 ($param,$value) = split('=',$_,2);
809 82 50       133 next unless defined $param;
810 82 50 33     152 next if $NO_UNDEF_PARAMS and not defined $value;
811 82 50       122 $value = '' unless defined $value;
812 82         175 $param = unescape($param);
813 82         121 $value = unescape($value);
814 82         138 $self->add_parameter($param);
815 82         102 push (@{$self->{param}{$param}},$value);
  82         214  
816             }
817             }
818              
819             sub add_parameter {
820 164     164 0 170 my($self,$param)=@_;
821 164 50       254 return unless defined $param;
822 130         357 push (@{$self->{'.parameters'}},$param)
823 164 100       334 unless defined($self->{param}{$param});
824             }
825              
826             sub all_parameters {
827 439     439 0 353 my $self = shift;
828 439 100 33     1234 return () unless defined($self) && $self->{'.parameters'};
829 358 100       240 return () unless @{$self->{'.parameters'}};
  358         693  
830 196         147 return @{$self->{'.parameters'}};
  196         449  
831             }
832              
833             # put a filehandle into binary mode (DOS)
834             sub binmode {
835 5 50 66 5 0 34 return unless defined($_[1]) && ref ($_[1]) && defined fileno($_[1]);
      66        
836 2         5 CORE::binmode($_[1]);
837             }
838              
839             # back compatibility html tag generation functions - noop
840             # since this is now the default having removed AUTOLOAD
841 1     1 0 233 sub compile { 1; }
842              
843             sub _all_html_tags {
844 57     57   715 return qw/
845             a abbr acronym address applet Area
846             b base basefont bdo big blink blockquote body br
847             caption center cite code col colgroup
848             dd del dfn div dl dt
849             em embed
850             fieldset font fontsize frame frameset
851             h1 h2 h3 h4 h5 h6 head hr html
852             i iframe ilayer img input ins
853             kbd
854             label layer legend li Link
855             Map menu meta
856             nextid nobr noframes noscript
857             object ol option
858             p Param pre
859             Q
860             samp script Select small span
861             strike strong style Sub sup
862             table tbody td tfoot th thead title Tr TR tt
863             u ul
864             var
865             /
866             }
867              
868             foreach my $tag ( _all_html_tags() ) {
869 441     441   21606 *$tag = sub { return _tag_func($tag,@_); };
870              
871             # start_html and end_html already exist as custom functions
872             next if ($tag eq 'html');
873              
874             foreach my $start_end ( qw/ start end / ) {
875             my $start_end_function = "${start_end}_${tag}";
876 320     320   549 *$start_end_function = sub { return _tag_func($start_end_function,@_); };
877             }
878             }
879              
880             sub _tag_func {
881 761     761   740 my $tagname = shift;
882 761         1063 my ($q,$a,@rest) = self_or_default(@_);
883              
884 761         802 my($attr) = '';
885              
886 761 100 66     1700 if (ref($a) && ref($a) eq 'HASH') {
887 245         504 my(@attr) = make_attributes($a,$q->{'escape'});
888 245 50       599 $attr = " @attr" if @attr;
889             } else {
890 516 100       861 unshift @rest,$a if defined $a;
891             }
892              
893 761         785 $tagname = lc( $tagname );
894              
895 761 100       1902 if ($tagname=~/start_(\w+)/i) {
    100          
896 183         853 return "<$1$attr>";
897             } elsif ($tagname=~/end_(\w+)/i) {
898 137         617 return "";
899             } else {
900 441 50       1342 return $XHTML ? "<$tagname$attr />" : "<$tagname$attr>" unless @rest;
    100          
901 253         445 my($tag,$untag) = ("<$tagname$attr>","");
902 255         599 my @result = map { "$tag$_$untag" }
903 253 100       550 (ref($rest[0]) eq 'ARRAY') ? @{$rest[0]} : "@rest";
  2         5  
904 253         1040 return "@result";
905             }
906             }
907              
908             sub _selected {
909 29     29   24 my $self = shift;
910 29         39 my $value = shift;
911 29 100       56 return '' unless $value;
912 10 50       31 return $XHTML ? qq(selected="selected" ) : qq(selected );
913             }
914              
915             sub _checked {
916 42     42   35 my $self = shift;
917 42         43 my $value = shift;
918 42 100       68 return '' unless $value;
919 22 100       37 return $XHTML ? qq(checked="checked" ) : qq(checked );
920             }
921              
922 19     19   6512 sub _reset_globals { initialize_globals(); }
923              
924             sub _setup_symbols {
925 57     57   69 my $self = shift;
926              
927             # to avoid reexporting unwanted variables
928 57         64 undef %EXPORT;
929              
930 57         119 for (@_) {
931              
932 92 50       169 if ( /^[:-]any$/ ) {
933 0         0 warn "CGI -any pragma has been REMOVED. You should audit your code for any use "
934             . "of none supported / incorrectly spelled tags and remove them"
935             ;
936 0         0 next;
937             }
938 92 50       121 $HEADERS_ONCE++, next if /^[:-]unique_headers$/;
939 92 50       129 $NPH++, next if /^[:-]nph$/;
940 92 50       122 $NOSTICKY++, next if /^[:-]nosticky$/;
941 92 100       144 $DEBUG=0, next if /^[:-]no_?[Dd]ebug$/;
942 88 50       121 $DEBUG=2, next if /^[:-][Dd]ebug$/;
943 88 50       113 $USE_PARAM_SEMICOLONS++, next if /^[:-]newstyle_urls$/;
944 88 100       154 $PUTDATA_UPLOAD++, next if /^[:-](?:putdata_upload|postdata_upload|patchdata_upload)$/;
945 85 50       107 $PARAM_UTF8++, next if /^[:-]utf8$/;
946 85 50       114 $XHTML++, next if /^[:-]xhtml$/;
947 85 100       109 $XHTML=0, next if /^[:-]no_?xhtml$/;
948 84 50       110 $USE_PARAM_SEMICOLONS=0, next if /^[:-]oldstyle_urls$/;
949 84 100       111 $TABINDEX++, next if /^[:-]tabindex$/;
950 83 50       108 $CLOSE_UPLOAD_FILES++, next if /^[:-]close_upload_files$/;
951 83 50       136 $NO_UNDEF_PARAMS++, next if /^[:-]no_undef_params$/;
952            
953 83         105 for (&expand_tags($_)) {
954 2291         1507 tr/a-zA-Z0-9_//cd; # don't allow weird function names
955 2291         2086 $EXPORT{$_}++;
956             }
957             }
958 57         179 @SAVED_SYMBOLS = @_;
959             }
960              
961             sub charset {
962 352     352 0 1090 my ($self,$charset) = self_or_default(@_);
963 352 100       707 $self->{'.charset'} = $charset if defined $charset;
964 352         456 $self->{'.charset'};
965             }
966              
967             sub element_id {
968 12     12 0 20 my ($self,$new_value) = self_or_default(@_);
969 12 50       34 $self->{'.elid'} = $new_value if defined $new_value;
970 12         41 sprintf('%010d',$self->{'.elid'}++);
971             }
972              
973             sub element_tab {
974 90     90 0 108 my ($self,$new_value) = self_or_default(@_);
975 90   100     170 $self->{'.etab'} ||= 1;
976 90 100       135 $self->{'.etab'} = $new_value if defined $new_value;
977 90         85 my $tab = $self->{'.etab'}++;
978 90 100 100     292 return '' unless $TABINDEX or defined $new_value;
979 39         82 return qq(tabindex="$tab" );
980             }
981              
982             #####
983             # subroutine: read_postdata_putdata
984             #
985             # Unless file uploads are disabled
986             # Reads BODY of POST/PUT request and stuffs it into tempfile
987             # accessible as param POSTDATA/PUTDATA
988             #
989             # Also respects upload_hook
990             #
991             # based on subroutine read_multipart_related
992             #####
993             sub read_postdata_putdata {
994 6     6 0 9 my ( $self, $postOrPut, $content_length, $content_type ) = @_;
995 6         14 my %header = (
996             "Content-Type" => $content_type,
997             );
998 6         6 my $param = $postOrPut;
999             # add this parameter to our list
1000 6         11 $self->add_parameter($param);
1001            
1002            
1003             UPLOADS: {
1004              
1005             # If we get here, then we are dealing with a potentially large
1006             # uploaded form. Save the data to a temporary file, then open
1007             # the file for reading.
1008              
1009             # skip the file if uploads disabled
1010 6 50       4 if ($DISABLE_UPLOADS) {
  6         13  
1011            
1012             # while (defined($data = $buffer->read)) { }
1013 0         0 my $buff;
1014 0         0 my $unit = $CGI::MultipartBuffer::INITIAL_FILLUNIT;
1015 0         0 my $len = $content_length;
1016 0         0 while ( $len > 0 ) {
1017 0         0 my $read = $self->read_from_client( \$buf, $unit, 0 );
1018 0         0 $len -= $read;
1019             }
1020 0         0 last UPLOADS;
1021             }
1022              
1023             # SHOULD PROBABLY SKIP THIS IF NOT $self->{'use_tempfile'}
1024             # BUT THE REST OF CGI.PM DOESN'T, SO WHATEVER
1025             my $tmp_dir = $CGI::OS eq 'WINDOWS'
1026 6 50 0     9 ? ( $ENV{TEMP} || $ENV{TMP} || ( $ENV{WINDIR} ? ( $ENV{WINDIR} . $SL . 'TEMP' ) : undef ) )
1027             : undef; # File::Temp defaults to TMPDIR
1028              
1029 6         482 require CGI::File::Temp;
1030 6         24 my $filehandle = CGI::File::Temp->new(
1031             UNLINK => $UNLINK_TMP_FILES,
1032             DIR => $tmp_dir,
1033             );
1034 6         1752 $filehandle->_mp_filename( $postOrPut );
1035              
1036 6 50 33     12 $CGI::DefaultClass->binmode($filehandle)
1037             if $CGI::needs_binmode
1038             && defined fileno($filehandle);
1039              
1040 6         6 my ($data);
1041 6         13 local ($\) = '';
1042 6         4 my $totalbytes;
1043 6         7 my $unit = $CGI::MultipartBuffer::INITIAL_FILLUNIT;
1044 6         5 my $len = $content_length;
1045 6         5 $unit = $len;
1046 6         6 my $ZERO_LOOP_COUNTER =0;
1047              
1048 6         9 while( $len > 0 )
1049             {
1050            
1051 6         12 my $bytesRead = $self->read_from_client( \$data, $unit, 0 );
1052 6         5 $len -= $bytesRead ;
1053              
1054             # An apparent bug in the Apache server causes the read()
1055             # to return zero bytes repeatedly without blocking if the
1056             # remote user aborts during a file transfer. I don't know how
1057             # they manage this, but the workaround is to abort if we get
1058             # more than SPIN_LOOP_MAX consecutive zero reads.
1059 6 50       11 if ($bytesRead <= 0) {
1060 0 0       0 die "CGI.pm: Server closed socket during read_postdata_putdata (client aborted?).\n" if $ZERO_LOOP_COUNTER++ >= $SPIN_LOOP_MAX;
1061             } else {
1062 6         5 $ZERO_LOOP_COUNTER = 0;
1063             }
1064            
1065 6 100       14 if ( defined $self->{'.upload_hook'} ) {
1066 3         4 $totalbytes += length($data);
1067 3         10 &{ $self->{'.upload_hook'} }( $param, $data, $totalbytes,
1068 3         2 $self->{'.upload_data'} );
1069             }
1070 6 50       54 print $filehandle $data if ( $self->{'use_tempfile'} );
1071 6         14 undef $data;
1072             }
1073              
1074             # back up to beginning of file
1075 6         156 seek( $filehandle, 0, 0 );
1076              
1077             ## Close the filehandle if requested this allows a multipart MIME
1078             ## upload to contain many files, and we won't die due to too many
1079             ## open file handles. The user can access the files using the hash
1080             ## below.
1081 6 50       9 close $filehandle if $CLOSE_UPLOAD_FILES;
1082 6 50       11 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;
1083              
1084             # Save some information about the uploaded file where we can get
1085             # at it later.
1086             # Use the typeglob + filename as the key, as this is guaranteed to be
1087             # unique for each filehandle. Don't use the file descriptor as
1088             # this will be re-used for each filehandle if the
1089             # close_upload_files feature is used.
1090 6         66 $self->{'.tmpfiles'}->{$$filehandle . $filehandle} = {
1091             hndl => $filehandle,
1092             name => $filehandle->filename,
1093             info => {%header},
1094             };
1095 6         10 push( @{ $self->{param}{$param} }, $filehandle );
  6         25  
1096             }
1097 6         12 return;
1098             }
1099              
1100 3     3 0 8 sub URL_ENCODED { 'application/x-www-form-urlencoded'; }
1101              
1102 9     9 0 38 sub MULTIPART { 'multipart/form-data'; }
1103              
1104 6     6 0 9 sub SERVER_PUSH { 'multipart/x-mixed-replace;boundary="' . shift() . '"'; }
1105              
1106             # Create a new multipart buffer
1107             sub new_MultipartBuffer {
1108 3     3 0 6 my($self,$boundary,$length) = @_;
1109 3         23 return CGI::MultipartBuffer->new($self,$boundary,$length);
1110             }
1111              
1112             # Read data from a file handle
1113             sub read_from_client {
1114 53     53 0 62 my($self, $buff, $len, $offset) = @_;
1115 53         120 local $^W=0; # prevent a warning
1116 53 50       406 return $MOD_PERL
1117             ? $self->r->read($$buff, $len, $offset)
1118             : read(\*STDIN, $$buff, $len, $offset);
1119             }
1120              
1121             #### Method: delete
1122             # Deletes the named parameter entirely.
1123             ####
1124             sub delete {
1125 271     271 0 383 my($self,@p) = self_or_default(@_);
1126 271         907 my(@names) = rearrange([NAME],@p);
1127 271 50       546 my @to_delete = ref($names[0]) eq 'ARRAY' ? @$names[0] : @names;
1128 271         212 my %to_delete;
1129 271         352 for my $name (@to_delete)
1130             {
1131 271         298 CORE::delete $self->{param}{$name};
1132 271         681 CORE::delete $self->{'.fieldnames'}->{$name};
1133 271         481 $to_delete{$name}++;
1134             }
1135 271         383 @{$self->{'.parameters'}}=grep { !exists($to_delete{$_}) } $self->param();
  271         414  
  210         310  
1136 271         420 return;
1137             }
1138              
1139             #### Method: import_names
1140             # Import all parameters into the given namespace.
1141             # Assumes namespace 'Q' if not specified
1142             ####
1143             sub import_names {
1144 0     0 0 0 my($self,$namespace,$delete) = self_or_default(@_);
1145 0 0       0 $namespace = 'Q' unless defined($namespace);
1146 0 0       0 die "Can't import names into \"main\"\n" if \%{"${namespace}::"} == \%::;
  0         0  
1147 0 0 0     0 if ($delete || $MOD_PERL || exists $ENV{'FCGI_ROLE'}) {
      0        
1148             # can anyone find an easier way to do this?
1149 0         0 for (keys %{"${namespace}::"}) {
  0         0  
1150 0         0 local *symbol = "${namespace}::${_}";
1151 0         0 undef $symbol;
1152 0         0 undef @symbol;
1153 0         0 undef %symbol;
1154             }
1155             }
1156 0         0 my($param,@value,$var);
1157 0         0 for $param ($self->param) {
1158             # protect against silly names
1159 0         0 ($var = $param)=~tr/a-zA-Z0-9_/_/c;
1160 0         0 $var =~ s/^(?=\d)/_/;
1161 0         0 local *symbol = "${namespace}::$var";
1162 0         0 @value = $self->param($param);
1163 0         0 @symbol = @value;
1164 0         0 $symbol = $value[0];
1165             }
1166             }
1167              
1168             #### Method: keywords
1169             # Keywords acts a bit differently. Calling it in a list context
1170             # returns the list of keywords.
1171             # Calling it in a scalar context gives you the size of the list.
1172             ####
1173             sub keywords {
1174 3     3 1 37 my($self,@values) = self_or_default(@_);
1175             # If values is provided, then we set it.
1176 3 50       9 $self->{param}{'keywords'}=[@values] if @values;
1177 3 50       12 my(@result) = defined($self->{param}{'keywords'}) ? @{$self->{param}{'keywords'}} : ();
  3         98  
1178 3         20 @result;
1179             }
1180              
1181             # These are some tie() interfaces for compatibility
1182             # with Steve Brenner's cgi-lib.pl routines
1183             sub Vars {
1184 4     4 0 5 my $q = shift;
1185 4         5 my %in;
1186 4         16 tie(%in,CGI,$q);
1187 4 50       8 return %in if wantarray;
1188 4         8 return \%in;
1189             }
1190              
1191             # These are some tie() interfaces for compatibility
1192             # with Steve Brenner's cgi-lib.pl routines
1193             sub ReadParse {
1194 1     1 0 3 local(*in);
1195 1 50       2 if (@_) {
1196 1         3 *in = $_[0];
1197             } else {
1198 0         0 my $pkg = caller();
1199 0         0 *in=*{"${pkg}::in"};
  0         0  
1200             }
1201 1         6 tie(%in,CGI);
1202 1         7 return scalar(keys %in);
1203             }
1204              
1205             sub PrintHeader {
1206 1     1 0 3 my($self) = self_or_default(@_);
1207 1         4 return $self->header();
1208             }
1209              
1210             sub HtmlTop {
1211 1     1 0 3 my($self,@p) = self_or_default(@_);
1212 1         5 return $self->start_html(@p);
1213             }
1214              
1215             sub HtmlBot {
1216 1     1 0 3 my($self,@p) = self_or_default(@_);
1217 1         4 return $self->end_html(@p);
1218             }
1219              
1220             sub SplitParam {
1221 1     1 0 2 my ($param) = @_;
1222 1         5 my (@params) = split ("\0", $param);
1223 1 50       11 return (wantarray ? @params : $params[0]);
1224             }
1225              
1226             sub MethGet {
1227 1     1 0 4 return request_method() eq 'GET';
1228             }
1229              
1230             sub MethPatch {
1231 0     0 0 0 return request_method() eq 'PATCH';
1232             }
1233              
1234             sub MethPost {
1235 1     1 0 2 return request_method() eq 'POST';
1236             }
1237              
1238             sub MethPut {
1239 1     1 0 5 return request_method() eq 'PUT';
1240             }
1241              
1242             sub TIEHASH {
1243 5     5   7 my $class = shift;
1244 5         7 my $arg = $_[0];
1245 5 100 66     34 if (ref($arg) && UNIVERSAL::isa($arg,'CGI')) {
1246 4         11 return $arg;
1247             }
1248 1   33     6 return $Q ||= $class->new(@_);
1249             }
1250              
1251             sub STORE {
1252 19     19   269 my $self = shift;
1253 19         17 my $tag = shift;
1254 19         14 my $vals = shift;
1255 19 100 66     86 my @vals = defined($vals) && index($vals,"\0")!=-1 ? split("\0",$vals) : $vals;
1256 19         46 $self->param(-name=>$tag,-value=>\@vals);
1257             }
1258              
1259             sub FETCH {
1260 37 50   37   81 return $_[0] if $_[1] eq 'CGI';
1261 37 100       61 return undef unless defined $_[0]->param($_[1]);
1262 22         33 return join("\0",$_[0]->param($_[1]));
1263             }
1264              
1265             sub FIRSTKEY {
1266 2     2   7 $_[0]->{'.iterator'}=0;
1267 2         8 $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
1268             }
1269              
1270             sub NEXTKEY {
1271 3     3   12 $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
1272             }
1273              
1274             sub EXISTS {
1275 2     2   11 exists $_[0]->{param}{$_[1]};
1276             }
1277              
1278             sub DELETE {
1279 1     1   2 my ($self, $param) = @_;
1280 1         2 my $value = $self->FETCH($param);
1281 1         3 $self->delete($param);
1282 1         5 return $value;
1283             }
1284              
1285             sub CLEAR {
1286 2     2   3 %{$_[0]}=();
  2         18  
1287             }
1288             ####
1289              
1290             ####
1291             # Append a new value to an existing query
1292             ####
1293             sub append {
1294 0     0 0 0 my($self,@p) = self_or_default(@_);
1295 0         0 my($name,$value) = rearrange([NAME,[VALUE,VALUES]],@p);
1296 0 0       0 my(@values) = defined($value) ? (ref($value) ? @{$value} : $value) : ();
  0 0       0  
1297 0 0       0 if (@values) {
1298 0         0 $self->add_parameter($name);
1299 0         0 push(@{$self->{param}{$name}},@values);
  0         0  
1300             }
1301 0         0 return $self->param($name);
1302             }
1303              
1304             #### Method: delete_all
1305             # Delete all parameters
1306             ####
1307             sub delete_all {
1308 0     0 0 0 my($self) = self_or_default(@_);
1309 0         0 my @param = $self->param();
1310 0         0 $self->delete(@param);
1311             }
1312              
1313             sub Delete {
1314 2     2 0 4 my($self,@p) = self_or_default(@_);
1315 2         6 $self->delete(@p);
1316             }
1317              
1318             sub Delete_all {
1319 0     0 0 0 my($self,@p) = self_or_default(@_);
1320 0         0 $self->delete_all(@p);
1321             }
1322              
1323             #### Method: autoescape
1324             # If you want to turn off the autoescaping features,
1325             # call this method with undef as the argument
1326             sub autoEscape {
1327 6     6 0 472 my($self,$escape) = self_or_default(@_);
1328 6         8 my $d = $self->{'escape'};
1329 6         16 $self->{'escape'} = $escape;
1330 6         8 $d;
1331             }
1332              
1333             #### Method: version
1334             # Return the current version
1335             ####
1336             sub version {
1337 1     1 0 4 return $VERSION;
1338             }
1339              
1340             #### Method: url_param
1341             # Return a parameter in the QUERY_STRING, regardless of
1342             # whether this was a POST or a GET
1343             ####
1344             sub url_param {
1345 17     17 0 724 my ($self,@p) = self_or_default(@_);
1346 17         22 my $name = shift(@p);
1347 17 50       39 return undef unless exists($ENV{QUERY_STRING});
1348 17 100       25 unless (exists($self->{'.url_param'})) {
1349 15         24 $self->{'.url_param'}={}; # empty hash
1350 15 100       58 if ($ENV{QUERY_STRING} =~ /=/) {
1351 13         52 my(@pairs) = split(/[&;]/,$ENV{QUERY_STRING});
1352 13         15 my($param,$value);
1353 13         19 for (@pairs) {
1354 40         58 ($param,$value) = split('=',$_,2);
1355 40 100       61 next if ! defined($param);
1356 30         52 $param = unescape($param);
1357 30         45 $value = unescape($value);
1358 30         25 push(@{$self->{'.url_param'}->{$param}},$value);
  30         84  
1359             }
1360             } else {
1361 2         4 my @keywords = $self->parse_keywordlist($ENV{QUERY_STRING});
1362 2 100       6 $self->{'.url_param'}{'keywords'} = \@keywords if @keywords;
1363             }
1364             }
1365 17 100       27 return keys %{$self->{'.url_param'}} unless defined($name);
  5         26  
1366 12 50       26 return () unless $self->{'.url_param'}->{$name};
1367 1         6 return wantarray ? @{$self->{'.url_param'}->{$name}}
1368 12 100       65 : $self->{'.url_param'}->{$name}->[0];
1369             }
1370              
1371             #### Method: Dump
1372             # Returns a string in which all the known parameter/value
1373             # pairs are represented as nested lists, mainly for the purposes
1374             # of debugging.
1375             ####
1376             sub Dump {
1377 3     3 0 11 my($self) = self_or_default(@_);
1378 3         5 my($param,$value,@result);
1379 3 100       6 return '
    ' unless $self->param;
    1380 2         4 push(@result,"
      ");
    1381 2         3 for $param ($self->param) {
    1382 2         6 my($name)=$self->_maybe_escapeHTML($param);
    1383 2         194 push(@result,"
  • $name
  • ");
    1384 2         2 push(@result,"
      ");
    1385 2         5 for $value ($self->param($param)) {
    1386 2         5 $value = $self->_maybe_escapeHTML($value);
    1387 2         62 $value =~ s/\n/
    \n/g;
    1388 2         6 push(@result,"
  • $value
  • ");
    1389             }
    1390 2         3 push(@result,"");
    1391             }
    1392 2         3 push(@result,"");
    1393 2         16 return join("\n",@result);
    1394             }
    1395              
    1396             #### Method as_string
    1397             #
    1398             # synonym for "dump"
    1399             ####
    1400             sub as_string {
    1401 1     1 0 5 &Dump(@_);
    1402             }
    1403              
    1404             #### Method: save
    1405             # Write values out to a filehandle in such a way that they can
    1406             # be reinitialized by the filehandle form of the new() method
    1407             ####
    1408             sub save {
    1409 1     1 0 655 my($self,$filehandle) = self_or_default(@_);
    1410 1         2 $filehandle = to_filehandle($filehandle);
    1411 1         1 my($param);
    1412 1         2 local($,) = ''; # set print field separator back to a sane value
    1413 1         3 local($\) = ''; # set output line separator to a sane value
    1414 1         3 for $param ($self->param) {
    1415 3         6 my($escaped_param) = escape($param);
    1416 3         4 my($value);
    1417 3         5 for $value ($self->param($param)) {
    1418 4 100 100     18 print $filehandle "$escaped_param=",escape("$value"),"\n"
    1419             if length($escaped_param) or length($value);
    1420             }
    1421             }
    1422 1         1 for (keys %{$self->{'.fieldnames'}}) {
      1         4  
    1423 0         0 print $filehandle ".cgifields=",escape("$_"),"\n";
    1424             }
    1425 1         3 print $filehandle "=\n"; # end of record
    1426             }
    1427              
    1428             #### Method: save_parameters
    1429             # An alias for save() that is a better name for exportation.
    1430             # Only intended to be used with the function (non-OO) interface.
    1431             ####
    1432             sub save_parameters {
    1433 0     0 0 0 my $fh = shift;
    1434 0         0 return save(to_filehandle($fh));
    1435             }
    1436              
    1437             #### Method: restore_parameters
    1438             # A way to restore CGI parameters from an initializer.
    1439             # Only intended to be used with the function (non-OO) interface.
    1440             ####
    1441             sub restore_parameters {
    1442 0     0 0 0 $Q = $CGI::DefaultClass->new(@_);
    1443             }
    1444              
    1445             #### Method: multipart_init
    1446             # Return a Content-Type: style header for server-push
    1447             # This has to be NPH on most web servers, and it is advisable to set $| = 1
    1448             #
    1449             # Many thanks to Ed Jordan for this
    1450             # contribution, updated by Andrew Benham (adsb@bigfoot.com)
    1451             ####
    1452             sub multipart_init {
    1453 6     6 1 1474 my($self,@p) = self_or_default(@_);
    1454 6         18 my($boundary,$charset,@other) = rearrange_header([BOUNDARY,CHARSET],@p);
    1455 6 100       8 if (!$boundary) {
    1456 4         5 $boundary = '------- =_';
    1457 4         42 my @chrs = ('0'..'9', 'A'..'Z', 'a'..'z');
    1458 4         7 for (1..17) {
    1459 68         96 $boundary .= $chrs[rand(scalar @chrs)];
    1460             }
    1461             }
    1462              
    1463 6         12 $self->{'separator'} = "$CRLF--$boundary$CRLF";
    1464 6         9 $self->{'final_separator'} = "$CRLF--$boundary--$CRLF";
    1465 6         10 $type = SERVER_PUSH($boundary);
    1466             return $self->header(
    1467             -nph => 0,
    1468             -type => $type,
    1469             -charset => $charset,
    1470 6         19 (map { split "=", $_, 2 } @other),
      0         0  
    1471             ) . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $self->multipart_end;
    1472             }
    1473              
    1474             #### Method: multipart_start
    1475             # Return a Content-Type: style header for server-push, start of section
    1476             #
    1477             # Many thanks to Ed Jordan for this
    1478             # contribution, updated by Andrew Benham (adsb@bigfoot.com)
    1479             ####
    1480             sub multipart_start {
    1481 4     4 1 9 my(@header);
    1482 4         8 my($self,@p) = self_or_default(@_);
    1483 4         13 my($type,$charset,@other) = rearrange([TYPE,CHARSET],@p);
    1484 4   100     13 $type = $type || 'text/html';
    1485 4 100       5 if ($charset) {
    1486 2         6 push(@header,"Content-Type: $type; charset=$charset");
    1487             } else {
    1488 2         4 push(@header,"Content-Type: $type");
    1489             }
    1490              
    1491             # rearrange() was designed for the HTML portion, so we
    1492             # need to fix it up a little.
    1493 4         5 for (@other) {
    1494             # Don't use \s because of perl bug 21951
    1495 0 0       0 next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/;
    1496 0         0 ($_ = $header) =~ s/^(\w)(.*)/$1 . lc ($2) . ': '.$self->unescapeHTML($value)/e;
      0         0  
    1497             }
    1498 4         4 push(@header,@other);
    1499 4         7 my $header = join($CRLF,@header)."${CRLF}${CRLF}";
    1500 4         83 return $header;
    1501             }
    1502              
    1503             #### Method: multipart_end
    1504             # Return a MIME boundary separator for server-push, end of section
    1505             #
    1506             # Many thanks to Ed Jordan for this
    1507             # contribution
    1508             ####
    1509             sub multipart_end {
    1510 6     6 1 11 my($self,@p) = self_or_default(@_);
    1511 6         21 return $self->{'separator'};
    1512             }
    1513              
    1514             #### Method: multipart_final
    1515             # Return a MIME boundary separator for server-push, end of all sections
    1516             #
    1517             # Contributed by Andrew Benham (adsb@bigfoot.com)
    1518             ####
    1519             sub multipart_final {
    1520 0     0 1 0 my($self,@p) = self_or_default(@_);
    1521 0         0 return $self->{'final_separator'} . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $CRLF;
    1522             }
    1523              
    1524             #### Method: header
    1525             # Return a Content-Type: style header
    1526             #
    1527             ####
    1528             sub header {
    1529 91     91 1 2614 my($self,@p) = self_or_default(@_);
    1530 91         102 my(@header);
    1531              
    1532 91 50 66     272 return "" if $self->{'.header_printed'}++ and $HEADERS_ONCE;
    1533              
    1534 91         410 my($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) =
    1535             rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE'],
    1536             'STATUS',['COOKIE','COOKIES','SET-COOKIE'],'TARGET',
    1537             'EXPIRES','NPH','CHARSET',
    1538             'ATTACHMENT','P3P'],@p);
    1539              
    1540             # Since $cookie and $p3p may be array references,
    1541             # we must stringify them before CR escaping is done.
    1542 91         164 my @cookie;
    1543 91 100       178 for (ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie) {
      6         8  
    1544 96 100       235 my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_;
    1545 96 100 100     252 push(@cookie,$cs) if defined $cs and $cs ne '';
    1546             }
    1547 91 100       155 $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY';
    1548              
    1549             # CR escaping for values, per RFC 822
    1550 91         116 for my $header ($type,$status,@cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) {
    1551 738 100       899 if (defined $header) {
    1552             # From RFC 822:
    1553             # Unfolding is accomplished by regarding CRLF immediately
    1554             # followed by a LWSP-char as equivalent to the LWSP-char.
    1555 153         503 $header =~ s/$CRLF(\s)/$1/g;
    1556              
    1557             # All other uses of newlines are invalid input.
    1558 153 100       817 if ($header =~ m/$CRLF|\015|\012/) {
    1559             # shorten very long values in the diagnostic
    1560 9 50       14 $header = substr($header,0,72).'...' if (length $header > 72);
    1561 9         68 die "Invalid header value contains a newline not followed by whitespace: $header";
    1562             }
    1563             }
    1564             }
    1565              
    1566 82   66     246 $nph ||= $NPH;
    1567              
    1568 82 100 50     214 $type ||= 'text/html' unless defined($type);
    1569              
    1570             # sets if $charset is given, gets if not
    1571 82         144 $charset = $self->charset( $charset );
    1572              
    1573             # rearrange() was designed for the HTML portion, so we
    1574             # need to fix it up a little.
    1575 82         120 for (@other) {
    1576             # Don't use \s because of perl bug 21951
    1577 10 50       104 next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/s;
    1578 10         50 ($_ = $header) =~ s/^(\w)(.*)/"\u$1\L$2" . ': '.$self->unescapeHTML($value)/e;
      10         59  
    1579             }
    1580              
    1581 82 100 100     685 $type .= "; charset=$charset"
          100        
          100        
    1582             if $type ne ''
    1583             and $type !~ /\bcharset\b/
    1584             and defined $charset
    1585             and $charset ne '';
    1586              
    1587             # Maybe future compatibility. Maybe not.
    1588 82   100     281 my $protocol = $ENV{SERVER_PROTOCOL} || 'HTTP/1.0';
    1589 82 100 100     152 push(@header,$protocol . ' ' . ($status || '200 OK')) if $nph;
    1590 82 100       122 push(@header,"Server: " . &server_software()) if $nph;
    1591              
    1592 82 100       130 push(@header,"Status: $status") if $status;
    1593 82 100       116 push(@header,"Window-Target: $target") if $target;
    1594 82 100       118 push(@header,"P3P: policyref=\"/w3c/p3p.xml\", CP=\"$p3p\"") if $p3p;
    1595             # push all the cookies -- there may be several
    1596 82         105 push(@header,map {"Set-Cookie: $_"} @cookie);
      14         83  
    1597             # if the user indicates an expiration time, then we need
    1598             # both an Expires and a Date header (so that the browser is
    1599             # uses OUR clock)
    1600 82 50       116 push(@header,"Expires: " . expires($expires,'http'))
    1601             if $expires;
    1602 82 100 66     432 push(@header,"Date: " . expires(0,'http')) if $expires || $cookie || $nph;
          100        
    1603 82 50       149 push(@header,"Pragma: no-cache") if $self->cache();
    1604 82 100       140 push(@header,"Content-Disposition: attachment; filename=\"$attachment\"") if $attachment;
    1605 82         87 push(@header,map {ucfirst $_} @other);
      10         31  
    1606 82 100       201 push(@header,"Content-Type: $type") if $type ne '';
    1607 82         191 my $header = join($CRLF,@header)."${CRLF}${CRLF}";
    1608 82 50 33     171 if (($MOD_PERL >= 1) && !$nph) {
    1609 0         0 $self->r->send_cgi_header($header);
    1610 0         0 return '';
    1611             }
    1612 82         430 return $header;
    1613             }
    1614              
    1615             #### Method: cache
    1616             # Control whether header() will produce the no-cache
    1617             # Pragma directive.
    1618             ####
    1619             sub cache {
    1620 82     82 0 112 my($self,$new_value) = self_or_default(@_);
    1621 82 50       172 $new_value = '' unless $new_value;
    1622 82 50       136 if ($new_value ne '') {
    1623 0         0 $self->{'cache'} = $new_value;
    1624             }
    1625 82         162 return $self->{'cache'};
    1626             }
    1627              
    1628             #### Method: redirect
    1629             # Return a Location: style header
    1630             #
    1631             ####
    1632             sub redirect {
    1633 10     10 0 1560 my($self,@p) = self_or_default(@_);
    1634 10         77 my($url,$target,$status,$cookie,$nph,@other) =
    1635             rearrange([[LOCATION,URI,URL],TARGET,STATUS,['COOKIE','COOKIES','SET-COOKIE'],NPH],@p);
    1636 10 50       34 $status = '302 Found' unless defined $status;
    1637 10   66     30 $url ||= $self->self_url;
    1638 10         9 my(@o);
    1639 10         17 for (@other) { tr/\"//d; push(@o,split("=",$_,2)); }
      4         8  
      4         13  
    1640 10         27 unshift(@o,
    1641             '-Status' => $status,
    1642             '-Location'=> $url,
    1643             '-nph' => $nph);
    1644 10 50       40 unshift(@o,'-Target'=>$target) if $target;
    1645 10         17 unshift(@o,'-Type'=>'');
    1646 10         10 my @unescaped;
    1647 10 100       19 unshift(@unescaped,'-Cookie'=>$cookie) if $cookie;
    1648 10         13 return $self->header((map {$self->unescapeHTML($_)} @o),@unescaped);
      88         121  
    1649             }
    1650              
    1651             #### Method: start_html
    1652             # Canned HTML header
    1653             #
    1654             # Parameters:
    1655             # $title -> (optional) The title for this HTML document (-title)
    1656             # $author -> (optional) e-mail address of the author (-author)
    1657             # $base -> (optional) if set to true, will enter the BASE address of this document
    1658             # for resolving relative references (-base)
    1659             # $xbase -> (optional) alternative base at some remote location (-xbase)
    1660             # $target -> (optional) target window to load all links into (-target)
    1661             # $script -> (option) Javascript code (-script)
    1662             # $no_script -> (option) Javascript
    1663             # $meta -> (optional) Meta information tags
    1664             # $head -> (optional) any other elements you'd like to incorporate into the tag
    1665             # (a scalar or array ref)
    1666             # $style -> (optional) reference to an external style sheet
    1667             # @other -> (optional) any other named parameters you'd like to incorporate into
    1668             # the tag.
    1669             ####
    1670             sub start_html {
    1671 12     12 0 1088 my($self,@p) = &self_or_default(@_);
    1672 12         61 my($title,$author,$base,$xbase,$script,$noscript,
    1673             $target,$meta,$head,$style,$dtd,$lang,$encoding,$declare_xml,@other) =
    1674             rearrange([TITLE,AUTHOR,BASE,XBASE,SCRIPT,NOSCRIPT,TARGET,
    1675             META,HEAD,STYLE,DTD,LANG,ENCODING,DECLARE_XML],@p);
    1676              
    1677 12         37 $self->element_id(0);
    1678 12         26 $self->element_tab(0);
    1679              
    1680 12 50       59 $encoding = lc($self->charset) unless defined $encoding;
    1681              
    1682             # Need to sort out the DTD before it's okay to call escapeHTML().
    1683 12         12 my(@result,$xml_dtd);
    1684 12 100       21 if ($dtd) {
    1685 5 50 33     18 if (defined(ref($dtd)) and (ref($dtd) eq 'ARRAY')) {
    1686 0 0       0 $dtd = $DEFAULT_DTD unless $dtd->[0] =~ m|^-//|;
    1687             } else {
    1688 5 50       17 $dtd = $DEFAULT_DTD unless $dtd =~ m|^-//|;
    1689             }
    1690             } else {
    1691 7 50       14 $dtd = $XHTML ? $_XHTML_DTD : $DEFAULT_DTD;
    1692             }
    1693              
    1694 12 100 66     75 $xml_dtd++ if ref($dtd) eq 'ARRAY' && $dtd->[0] =~ /\bXHTML\b/i;
    1695 12 50 66     59 $xml_dtd++ if ref($dtd) eq '' && $dtd =~ /\bXHTML\b/i;
    1696 12 50 66     83 push @result,qq() if $xml_dtd && $declare_xml;
    1697              
    1698 12 100 66     41 if (ref($dtd) && ref($dtd) eq 'ARRAY') {
    1699 7         26 push(@result,qq([0]"\n\t "$dtd->[1]">));
    1700 7         12 $DTD_PUBLIC_IDENTIFIER = $dtd->[0];
    1701             } else {
    1702 5         11 push(@result,qq());
    1703 5         6 $DTD_PUBLIC_IDENTIFIER = $dtd;
    1704             }
    1705              
    1706             # Now that we know whether we're using the HTML 3.2 DTD or not, it's okay to
    1707             # call escapeHTML(). Strangely enough, the title needs to be escaped as
    1708             # HTML while the author needs to be escaped as a URL.
    1709 12   100     60 $title = $self->_maybe_escapeHTML($title || 'Untitled Document');
    1710 12         682 $author = $self->escape($author);
    1711              
    1712 12 100       64 if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML (2\.0|3\.2|4\.01?)/i) {
    1713 4 50       6 $lang = "" unless defined $lang;
    1714 4         5 $XHTML = 0;
    1715             }
    1716             else {
    1717 8 100       18 $lang = 'en-US' unless defined $lang;
    1718             }
    1719              
    1720 12 50       35 my $lang_bits = $lang ne '' ? qq( lang="$lang" xml:lang="$lang") : '';
    1721 12 100 100     61 my $meta_bits = qq()
          66        
    1722             if $XHTML && $encoding && !$declare_xml;
    1723              
    1724 12 50       42 push(@result,$XHTML ? qq(\n\n$title)
        100          
    1725             : ($lang ? qq() : "")
    1726             . "$title");
    1727 12 50       20 if (defined $author) {
    1728 0 0       0 push(@result,$XHTML ? ""
    1729             : "");
    1730             }
    1731              
    1732 12 50 33     65 if ($base || $xbase || $target) {
          33        
    1733 0   0     0 my $href = $xbase || $self->url('-path'=>1);
    1734 0 0       0 my $t = $target ? qq/ target="$target"/ : '';
    1735 0 0       0 push(@result,$XHTML ? qq() : qq());
    1736             }
    1737              
    1738 12 50 66     36 if ($meta && ref($meta) && (ref($meta) eq 'HASH')) {
          66        
    1739 2 50       10 for (sort keys %$meta) { push(@result,$XHTML ? qq()
      11         22  
    1740             : qq()); }
    1741             }
    1742              
    1743 12         10 my $meta_bits_set = 0;
    1744 12 50       21 if( $head ) {
    1745 0 0       0 if( ref $head ) {
    1746 0         0 push @result, @$head;
    1747 0 0       0 $meta_bits_set = 1 if grep { /http-equiv=["']Content-Type/i }@$head;
      0         0  
    1748             }
    1749             else {
    1750 0         0 push @result, $head;
    1751 0 0       0 $meta_bits_set = 1 if $head =~ /http-equiv=["']Content-Type/i;
    1752             }
    1753             }
    1754              
    1755             # handle the infrequently-used -style and -script parameters
    1756 12 50       18 push(@result,$self->_style($style)) if defined $style;
    1757 12 100       24 push(@result,$self->_script($script)) if defined $script;
    1758 12 100 66     36 push(@result,$meta_bits) if defined $meta_bits and !$meta_bits_set;
    1759              
    1760             # handle -noscript parameter
    1761 12 50       21 push(@result,<
    1762            
    1763             $noscript
    1764            
    1765             END
    1766             ;
    1767 12 50       25 my($other) = @other ? " @other" : '';
    1768 12         24 push(@result,"\n\n");
    1769 12         97 return join("\n",@result);
    1770             }
    1771              
    1772             ### Method: _style
    1773             # internal method for generating a CSS style section
    1774             ####
    1775             sub _style {
    1776 1     1   2 my ($self,$style) = @_;
    1777 1         2 my (@result);
    1778              
    1779 1         2 my $type = 'text/css';
    1780 1         1 my $rel = 'stylesheet';
    1781              
    1782              
    1783 1 50       3 my $cdata_start = $XHTML ? "\n\n" : " -->\n";
    1785              
    1786 1 50       4 my @s = ref($style) eq 'ARRAY' ? @$style : $style;
    1787 1         1 my $other = '';
    1788              
    1789 1         3 for my $s (@s) {
    1790 1 50       2 if (ref($s)) {
    1791 0 0       0 my($src,$code,$verbatim,$stype,$alternate,$foo,@other) =
    1792             rearrange([qw(SRC CODE VERBATIM TYPE ALTERNATE FOO)],
    1793             ('-foo'=>'bar',
    1794             ref($s) eq 'ARRAY' ? @$s : %$s));
    1795 0 0       0 my $type = defined $stype ? $stype : 'text/css';
    1796 0 0       0 my $rel = $alternate ? 'alternate stylesheet' : 'stylesheet';
    1797 0 0       0 $other = "@other" if @other;
    1798              
    1799 0 0       0 if (ref($src) eq "ARRAY") # Check to see if the $src variable is an array reference
    1800             { # If it is, push a LINK tag for each one
    1801 0         0 for $src (@$src)
    1802             {
    1803 0 0       0 push(@result,$XHTML ? qq()
        0          
    1804             : qq()) if $src;
    1805             }
    1806             }
    1807             else
    1808             { # Otherwise, push the single -src, if it exists.
    1809 0 0       0 push(@result,$XHTML ? qq()
        0          
    1810             : qq()
    1811             ) if $src;
    1812             }
    1813 0 0       0 if ($verbatim) {
    1814 0 0       0 my @v = ref($verbatim) eq 'ARRAY' ? @$verbatim : $verbatim;
    1815 0         0 push(@result, "") for @v;
    1816             }
    1817 0 0       0 if ($code) {
    1818 0 0       0 my @c = ref($code) eq 'ARRAY' ? @$code : $code;
    1819 0         0 push(@result,style({'type'=>$type},"$cdata_start\n$_\n$cdata_end")) for @c;
    1820             }
    1821              
    1822             } else {
    1823 1         1 my $src = $s;
    1824 1 50       6 push(@result,$XHTML ? qq()
    1825             : qq());
    1826             }
    1827             }
    1828 1         4 @result;
    1829             }
    1830              
    1831             sub _script {
    1832 1     1   2 my ($self,$script) = @_;
    1833 1         1 my (@result);
    1834              
    1835 1 50       5 my (@scripts) = ref($script) eq 'ARRAY' ? @$script : ($script);
    1836 1         2 for $script (@scripts) {
    1837 1         2 my($src,$code,$language,$charset);
    1838 1 50       2 if (ref($script)) { # script is a hash
    1839 1 50       8 ($src,$code,$type,$charset) =
    1840             rearrange(['SRC','CODE',['LANGUAGE','TYPE'],'CHARSET'],
    1841             '-foo'=>'bar', # a trick to allow the '-' to be omitted
    1842             ref($script) eq 'ARRAY' ? @$script : %$script);
    1843 1   50     6 $type ||= 'text/javascript';
    1844 1 50       5 unless ($type =~ m!\w+/\w+!) {
    1845 0         0 $type =~ s/[\d.]+$//;
    1846 0         0 $type = "text/$type";
    1847             }
    1848             } else {
    1849 0         0 ($src,$code,$type,$charset) = ('',$script, 'text/javascript', '');
    1850             }
    1851              
    1852 1         1 my $comment = '//'; # javascript by default
    1853 1 50       6 $comment = '#' if $type=~/perl|tcl/i;
    1854 1 50       2 $comment = "'" if $type=~/vbscript/i;
    1855              
    1856 1         1 my ($cdata_start,$cdata_end);
    1857 1 50       2 if ($XHTML) {
    1858 1         2 $cdata_start = "$comment
    1859 1         2 $cdata_end .= "\n$comment]]>";
    1860             } else {
    1861 0         0 $cdata_start = "\n\n";
    1864             }
    1865 1         1 my(@satts);
    1866 1 50       2 push(@satts,'src'=>$src) if $src;
    1867 1         2 push(@satts,'type'=>$type);
    1868 1 50 33     5 push(@satts,'charset'=>$charset) if ($src && $charset);
    1869 1 50       2 $code = $cdata_start . $code . $cdata_end if defined $code;
    1870 1   50     7 push(@result,$self->script({@satts},$code || ''));
    1871             }
    1872 1         2 @result;
    1873             }
    1874              
    1875             #### Method: end_html
    1876             # End an HTML document.
    1877             # Trivial method for completeness. Just returns ""
    1878             ####
    1879             sub end_html {
    1880 3     3 0 23 return "\n\n";
    1881             }
    1882              
    1883             ################################
    1884             # METHODS USED IN BUILDING FORMS
    1885             ################################
    1886              
    1887             #### Method: isindex
    1888             # Just prints out the isindex tag.
    1889             # Parameters:
    1890             # $action -> optional URL of script to run
    1891             # Returns:
    1892             # A string containing a tag
    1893             sub isindex {
    1894 0     0 0 0 my($self,@p) = self_or_default(@_);
    1895 0         0 my($action,@other) = rearrange([ACTION],@p);
    1896 0 0       0 $action = qq/ action="$action"/ if $action;
    1897 0 0       0 my($other) = @other ? " @other" : '';
    1898 0 0       0 return $XHTML ? "" : "";
    1899             }
    1900              
    1901             #### Method: start_form
    1902             # Start a form
    1903             # Parameters:
    1904             # $method -> optional submission method to use (GET or POST)
    1905             # $action -> optional URL of script to run
    1906             # $enctype ->encoding to use (URL_ENCODED or MULTIPART)
    1907             sub start_form {
    1908 12     12 0 56 my($self,@p) = self_or_default(@_);
    1909              
    1910 12         47 my($method,$action,$enctype,@other) =
    1911             rearrange([METHOD,ACTION,ENCTYPE],@p);
    1912              
    1913 12   100     85 $method = $self->_maybe_escapeHTML(lc($method || 'post'));
    1914              
    1915 12 100       470 if( $XHTML ){
    1916 7   66     26 $enctype = $self->_maybe_escapeHTML($enctype || &MULTIPART);
    1917             }else{
    1918 5   66     14 $enctype = $self->_maybe_escapeHTML($enctype || &URL_ENCODED);
    1919             }
    1920              
    1921 12 50       302 if (defined $action) {
    1922 12         17 $action = $self->_maybe_escapeHTML($action);
    1923             }
    1924             else {
    1925 0   0     0 $action = $self->_maybe_escapeHTML($self->request_uri || $self->self_url);
    1926             }
    1927 12         289 $action = qq(action="$action");
    1928 12 100       36 my($other) = @other ? " @other" : '';
    1929 12         22 $self->{'.parametersToAdd'}={};
    1930 12         62 return qq/
    /;
    1931             }
    1932              
    1933             #### Method: start_multipart_form
    1934             sub start_multipart_form {
    1935 4     4 0 9 my($self,@p) = self_or_default(@_);
    1936 4 50 33     20 if (defined($p[0]) && substr($p[0],0,1) eq '-') {
    1937 0         0 return $self->start_form(-enctype=>&MULTIPART,@p);
    1938             } else {
    1939 4         11 my($method,$action,@other) =
    1940             rearrange([METHOD,ACTION],@p);
    1941 4         8 return $self->start_form($method,$action,&MULTIPART,@other);
    1942             }
    1943             }
    1944              
    1945             #### Method: end_form
    1946             # End a form
    1947             # Note: This repeated below under the older name.
    1948             sub end_form {
    1949 1     1 0 11 my($self,@p) = self_or_default(@_);
    1950 1 50       2 if ( $NOSTICKY ) {
    1951 0 0       0 return wantarray ? ("") : "\n";
    1952             } else {
    1953 1 50       3 if (my @fields = $self->get_fields) {
    1954 0 0       0 return wantarray ? ("
    ",@fields,"
    ","")
    1955             : "
    ".(join '',@fields)."
    \n";
    1956             } else {
    1957 1         6 return "";
    1958             }
    1959             }
    1960             }
    1961              
    1962             #### Method: end_multipart_form
    1963             # end a multipart form
    1964             sub end_multipart_form {
    1965 0     0 0 0 &end_form;
    1966             }
    1967              
    1968             sub _textfield {
    1969 8     8   18 my($self,$tag,@p) = self_or_default(@_);
    1970 8         38 my($name,$default,$size,$maxlength,$override,$tabindex,@other) =
    1971             rearrange([NAME,[DEFAULT,VALUE,VALUES],SIZE,MAXLENGTH,[OVERRIDE,FORCE],TABINDEX],@p);
    1972              
    1973 8 100       30 my $current = $override ? $default :
        100          
    1974             (defined($self->param($name)) ? $self->param($name) : $default);
    1975              
    1976 8 50       24 $current = defined($current) ? $self->_maybe_escapeHTML($current,1) : '';
    1977 8 100       212 $name = defined($name) ? $self->_maybe_escapeHTML($name) : '';
    1978 8 50       181 my($s) = defined($size) ? qq/ size="$size"/ : '';
    1979 8 50       14 my($m) = defined($maxlength) ? qq/ maxlength="$maxlength"/ : '';
    1980 8 100       19 my($other) = @other ? " @other" : '';
    1981             # this entered at cristy's request to fix problems with file upload fields
    1982             # and WebTV -- not sure it won't break stuff
    1983 8 50       21 my($value) = $current ne '' ? qq(value="$current") : '';
    1984 8         16 $tabindex = $self->element_tab($tabindex);
    1985 8 50       52 return $XHTML ? qq()
    1986             : qq();
    1987             }
    1988              
    1989             #### Method: textfield
    1990             # Parameters:
    1991             # $name -> Name of the text field
    1992             # $default -> Optional default value of the field if not
    1993             # already defined.
    1994             # $size -> Optional width of field in characaters.
    1995             # $maxlength -> Optional maximum number of characters.
    1996             # Returns:
    1997             # A string containing a field
    1998             #
    1999             sub textfield {
    2000 7     7 0 26 my($self,@p) = self_or_default(@_);
    2001 7         20 $self->_textfield('text',@p);
    2002             }
    2003              
    2004             #### Method: filefield
    2005             # Parameters:
    2006             # $name -> Name of the file upload field
    2007             # $size -> Optional width of field in characaters.
    2008             # $maxlength -> Optional maximum number of characters.
    2009             # Returns:
    2010             # A string containing a field
    2011             #
    2012             sub filefield {
    2013 0     0 0 0 my($self,@p) = self_or_default(@_);
    2014 0         0 $self->_textfield('file',@p);
    2015             }
    2016              
    2017             #### Method: password
    2018             # Create a "secret password" entry field
    2019             # Parameters:
    2020             # $name -> Name of the field
    2021             # $default -> Optional default value of the field if not
    2022             # already defined.
    2023             # $size -> Optional width of field in characters.
    2024             # $maxlength -> Optional maximum characters that can be entered.
    2025             # Returns:
    2026             # A string containing a field
    2027             #
    2028             sub password_field {
    2029 1     1 0 4 my ($self,@p) = self_or_default(@_);
    2030 1         3 $self->_textfield('password',@p);
    2031             }
    2032              
    2033             #### Method: textarea
    2034             # Parameters:
    2035             # $name -> Name of the text field
    2036             # $default -> Optional default value of the field if not
    2037             # already defined.
    2038             # $rows -> Optional number of rows in text area
    2039             # $columns -> Optional number of columns in text area
    2040             # Returns:
    2041             # A string containing a tag
    2042             #
    2043             sub textarea {
    2044 2     2 0 6 my($self,@p) = self_or_default(@_);
    2045 2         14 my($name,$default,$rows,$cols,$override,$tabindex,@other) =
    2046             rearrange([NAME,[DEFAULT,VALUE],ROWS,[COLS,COLUMNS],[OVERRIDE,FORCE],TABINDEX],@p);
    2047              
    2048 2 50       11 my($current)= $override ? $default :
        50          
    2049             (defined($self->param($name)) ? $self->param($name) : $default);
    2050              
    2051 2 50       12 $name = defined($name) ? $self->_maybe_escapeHTML($name) : '';
    2052 2 50       34 $current = defined($current) ? $self->_maybe_escapeHTML($current) : '';
    2053 2 50       32 my($r) = $rows ? qq/ rows="$rows"/ : '';
    2054 2 50       7 my($c) = $cols ? qq/ cols="$cols"/ : '';
    2055 2 100       7 my($other) = @other ? " @other" : '';
    2056 2         4 $tabindex = $self->element_tab($tabindex);
    2057 2         13 return qq{};
    2058             }
    2059              
    2060             #### Method: button
    2061             # Create a javascript button.
    2062             # Parameters:
    2063             # $name -> (optional) Name for the button. (-name)
    2064             # $value -> (optional) Value of the button when selected (and visible name) (-value)
    2065             # $onclick -> (optional) Text of the JavaScript to run when the button is
    2066             # clicked.
    2067             # Returns:
    2068             # A string containing a tag
    2069             ####
    2070             sub button {
    2071 4     4 0 742 my($self,@p) = self_or_default(@_);
    2072              
    2073 4         20 my($label,$value,$script,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL],
    2074             [ONCLICK,SCRIPT],TABINDEX],@p);
    2075              
    2076 4         16 $label=$self->_maybe_escapeHTML($label);
    2077 4         238 $value=$self->_maybe_escapeHTML($value,1);
    2078 4         7 $script=$self->_maybe_escapeHTML($script);
    2079              
    2080 4   100     12 $script ||= '';
    2081              
    2082 4         5 my($name) = '';
    2083 4 100       10 $name = qq/ name="$label"/ if $label;
    2084 4   66     11 $value = $value || $label;
    2085 4         3 my($val) = '';
    2086 4 100       9 $val = qq/ value="$value"/ if $value;
    2087 4 100       8 $script = qq/ onclick="$script"/ if $script;
    2088 4 100       9 my($other) = @other ? " @other" : '';
    2089 4         8 $tabindex = $self->element_tab($tabindex);
    2090 4 50       25 return $XHTML ? qq()
    2091             : qq();
    2092             }
    2093              
    2094             #### Method: submit
    2095             # Create a "submit query" button.
    2096             # Parameters:
    2097             # $name -> (optional) Name for the button.
    2098             # $value -> (optional) Value of the button when selected (also doubles as label).
    2099             # $label -> (optional) Label printed on the button(also doubles as the value).
    2100             # Returns:
    2101             # A string containing a tag
    2102             ####
    2103             sub submit {
    2104 7     7 0 352 my($self,@p) = self_or_default(@_);
    2105              
    2106 7         29 my($label,$value,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL],TABINDEX],@p);
    2107              
    2108 7         21 $label=$self->_maybe_escapeHTML($label);
    2109 7         252 $value=$self->_maybe_escapeHTML($value,1);
    2110              
    2111 7 50       305 my $name = $NOSTICKY ? '' : 'name=".submit" ';
    2112 7 100       21 $name = qq/name="$label" / if defined($label);
    2113 7 100       20 $value = defined($value) ? $value : $label;
    2114 7         6 my $val = '';
    2115 7 100       15 $val = qq/value="$value" / if defined($value);
    2116 7         18 $tabindex = $self->element_tab($tabindex);
    2117 7 100       18 my($other) = @other ? "@other " : '';
    2118 7 50       46 return $XHTML ? qq()
    2119             : qq();
    2120             }
    2121              
    2122             #### Method: reset
    2123             # Create a "reset" button.
    2124             # Parameters:
    2125             # $name -> (optional) Name for the button.
    2126             # Returns:
    2127             # A string containing a tag
    2128             ####
    2129             sub reset {
    2130 0     0 0 0 my($self,@p) = self_or_default(@_);
    2131 0         0 my($label,$value,$tabindex,@other) = rearrange(['NAME',['VALUE','LABEL'],TABINDEX],@p);
    2132 0         0 $label=$self->_maybe_escapeHTML($label);
    2133 0         0 $value=$self->_maybe_escapeHTML($value,1);
    2134 0         0 my ($name) = ' name=".reset"';
    2135 0 0       0 $name = qq/ name="$label"/ if defined($label);
    2136 0 0       0 $value = defined($value) ? $value : $label;
    2137 0         0 my($val) = '';
    2138 0 0       0 $val = qq/ value="$value"/ if defined($value);
    2139 0 0       0 my($other) = @other ? " @other" : '';
    2140 0         0 $tabindex = $self->element_tab($tabindex);
    2141 0 0       0 return $XHTML ? qq()
    2142             : qq();
    2143             }
    2144              
    2145             #### Method: defaults
    2146             # Create a "defaults" button.
    2147             # Parameters:
    2148             # $name -> (optional) Name for the button.
    2149             # Returns:
    2150             # A string containing a tag
    2151             #
    2152             # Note: this button has a special meaning to the initialization script,
    2153             # and tells it to ERASE the current query string so that your defaults
    2154             # are used again!
    2155             ####
    2156             sub defaults {
    2157 0     0 0 0 my($self,@p) = self_or_default(@_);
    2158              
    2159 0         0 my($label,$tabindex,@other) = rearrange([[NAME,VALUE],TABINDEX],@p);
    2160              
    2161 0         0 $label=$self->_maybe_escapeHTML($label,1);
    2162 0   0     0 $label = $label || "Defaults";
    2163 0         0 my($value) = qq/ value="$label"/;
    2164 0 0       0 my($other) = @other ? " @other" : '';
    2165 0         0 $tabindex = $self->element_tab($tabindex);
    2166 0 0       0 return $XHTML ? qq()
    2167             : qq//;
    2168             }
    2169              
    2170             #### Method: comment
    2171             # Create an HTML
    2172             # Parameters: a string
    2173             sub comment {
    2174 0     0 0 0 my($self,@p) = self_or_CGI(@_);
    2175 0         0 return "";
    2176             }
    2177              
    2178             #### Method: checkbox
    2179             # Create a checkbox that is not logically linked to any others.
    2180             # The field value is "on" when the button is checked.
    2181             # Parameters:
    2182             # $name -> Name of the checkbox
    2183             # $checked -> (optional) turned on by default if true
    2184             # $value -> (optional) value of the checkbox, 'on' by default
    2185             # $label -> (optional) a user-readable label printed next to the box.
    2186             # Otherwise the checkbox name is used.
    2187             # Returns:
    2188             # A string containing a field
    2189             ####
    2190             sub checkbox {
    2191 9     9 0 21 my($self,@p) = self_or_default(@_);
    2192              
    2193 9         46 my($name,$checked,$value,$label,$labelattributes,$override,$tabindex,@other) =
    2194             rearrange([NAME,[CHECKED,SELECTED,ON],VALUE,LABEL,LABELATTRIBUTES,
    2195             [OVERRIDE,FORCE],TABINDEX],@p);
    2196              
    2197 9 50       25 $value = defined $value ? $value : 'on';
    2198              
    2199 9 100 66     41 if (!$override && ($self->{'.fieldnames'}->{$name} ||
          66        
    2200             defined $self->param($name))) {
    2201 6 100       10 $checked = grep($_ eq $value,$self->param($name)) ? $self->_checked(1) : '';
    2202             } else {
    2203 3         12 $checked = $self->_checked($checked);
    2204             }
    2205 9 100       17 my($the_label) = defined $label ? $label : $name;
    2206 9         19 $name = $self->_maybe_escapeHTML($name);
    2207 9         248 $value = $self->_maybe_escapeHTML($value,1);
    2208 9         209 $the_label = $self->_maybe_escapeHTML($the_label);
    2209 9 100       235 my($other) = @other ? "@other " : '';
    2210 9         16 $tabindex = $self->element_tab($tabindex);
    2211 9         20 $self->register_parameter($name);
    2212 9 50       40 return $XHTML ? CGI::label($labelattributes,
    2213             qq{$the_label})
    2214             : qq{$the_label};
    2215             }
    2216              
    2217             # Escape HTML
    2218             sub escapeHTML {
    2219 251     251 0 6528 require HTML::Entities;
    2220             # hack to work around earlier hacks
    2221 251 100 100     43904 push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
    2222 251         285 my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_);
    2223 251 50       368 return undef unless defined($toencode);
    2224 251         220 my $encode_entities = $ENCODE_ENTITIES;
    2225 251 100 100     693 $encode_entities .= "\012\015" if ( $encode_entities && $newlinestoo );
    2226 251         420 return HTML::Entities::encode_entities($toencode,$encode_entities);
    2227             }
    2228              
    2229             # unescape HTML -- used internally
    2230             sub unescapeHTML {
    2231 105     105 0 2730 require HTML::Entities;
    2232             # hack to work around earlier hacks
    2233 105 50 66     15971 push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
    2234 105         128 my ($self,$string) = CGI::self_or_default(@_);
    2235 105 100       192 return undef unless defined($string);
    2236 95         357 return HTML::Entities::decode_entities($string);
    2237             }
    2238              
    2239             # Internal procedure - don't use
    2240             sub _tableize {
    2241 1     1   3 my($rows,$columns,$rowheaders,$colheaders,@elements) = @_;
    2242 1 50       3 my @rowheaders = $rowheaders ? @$rowheaders : ();
    2243 1 50       2 my @colheaders = $colheaders ? @$colheaders : ();
    2244 1         2 my($result);
    2245              
    2246 1 50       2 if (defined($columns)) {
    2247 1 50       2 $rows = int(0.99 + @elements/$columns) unless defined($rows);
    2248             }
    2249 1 50       7 if (defined($rows)) {
    2250 1 50       3 $columns = int(0.99 + @elements/$rows) unless defined($columns);
    2251             }
    2252              
    2253             # rearrange into a pretty table
    2254 1         2 $result = ""; " if @colheaders; "; "; " if @rowheaders; " ";
    2255 1         1 my($row,$column);
    2256 1 50 33     2 unshift(@colheaders,'') if @colheaders && @rowheaders;
    2257 1 50       2 $result .= "
    2258 1         2 for (@colheaders) {
    2259 0         0 $result .= "$_
    2260             }
    2261 1         3 for ($row=0;$row<$rows;$row++) {
    2262 2         3 $result .= "
    2263 2 50       3 $result .= "$rowheaders[$row]
    2264 2         6 for ($column=0;$column<$columns;$column++) {
    2265 4 50       15 $result .= "" . $elements[$column*$rows + $row] . "
    2266             if defined($elements[$column*$rows + $row]);
    2267             }
    2268 2         3 $result .= "
    2269             }
    2270 1         1 $result .= "
    ";
    2271 1         7 return $result;
    2272             }
    2273              
    2274             #### Method: radio_group
    2275             # Create a list of logically-linked radio buttons.
    2276             # Parameters:
    2277             # $name -> Common name for all the buttons.
    2278             # $values -> A pointer to a regular array containing the
    2279             # values for each button in the group.
    2280             # $default -> (optional) Value of the button to turn on by default. Pass '-'
    2281             # to turn _nothing_ on.
    2282             # $linebreak -> (optional) Set to true to place linebreaks
    2283             # between the buttons.
    2284             # $labels -> (optional)
    2285             # A pointer to a hash of labels to print next to each checkbox
    2286             # in the form $label{'value'}="Long explanatory label".
    2287             # Otherwise the provided values are used as the labels.
    2288             # Returns:
    2289             # An ARRAY containing a series of fields
    2290             ####
    2291             sub radio_group {
    2292 5     5 0 13 my($self,@p) = self_or_default(@_);
    2293 5         20 $self->_box_group('radio',@p);
    2294             }
    2295              
    2296             #### Method: checkbox_group
    2297             # Create a list of logically-linked checkboxes.
    2298             # Parameters:
    2299             # $name -> Common name for all the check boxes
    2300             # $values -> A pointer to a regular array containing the
    2301             # values for each checkbox in the group.
    2302             # $defaults -> (optional)
    2303             # 1. If a pointer to a regular array of checkbox values,
    2304             # then this will be used to decide which
    2305             # checkboxes to turn on by default.
    2306             # 2. If a scalar, will be assumed to hold the
    2307             # value of a single checkbox in the group to turn on.
    2308             # $linebreak -> (optional) Set to true to place linebreaks
    2309             # between the buttons.
    2310             # $labels -> (optional)
    2311             # A pointer to a hash of labels to print next to each checkbox
    2312             # in the form $label{'value'}="Long explanatory label".
    2313             # Otherwise the provided values are used as the labels.
    2314             # Returns:
    2315             # An ARRAY containing a series of fields
    2316             ####
    2317              
    2318             sub checkbox_group {
    2319 8     8 0 30 my($self,@p) = self_or_default(@_);
    2320 8         28 $self->_box_group('checkbox',@p);
    2321             }
    2322              
    2323             sub _box_group {
    2324 13     13   13 my $self = shift;
    2325 13         14 my $box_type = shift;
    2326              
    2327 13         87 my($name,$values,$defaults,$linebreak,$labels,$labelattributes,
    2328             $attributes,$rows,$columns,$rowheaders,$colheaders,
    2329             $override,$nolabels,$tabindex,$disabled,@other) =
    2330             rearrange([NAME,[VALUES,VALUE],[DEFAULT,DEFAULTS],LINEBREAK,LABELS,LABELATTRIBUTES,
    2331             ATTRIBUTES,ROWS,[COLUMNS,COLS],[ROWHEADERS,ROWHEADER],[COLHEADERS,COLHEADER],
    2332             [OVERRIDE,FORCE],NOLABELS,TABINDEX,DISABLED
    2333             ],@_);
    2334              
    2335              
    2336 13         33 my($result,$checked,@elements,@values);
    2337              
    2338 13         33 @values = $self->_set_values_and_labels($values,\$labels,$name);
    2339 13         33 my %checked = $self->previous_or_default($name,$defaults,$override);
    2340              
    2341             # If no check array is specified, check the first by default
    2342 13 100 100     45 $checked{$values[0]}++ if $box_type eq 'radio' && !%checked;
    2343              
    2344 13         22 $name=$self->_maybe_escapeHTML($name);
    2345              
    2346 13         441 my %tabs = ();
    2347 13 50 66     49 if ($TABINDEX && $tabindex) {
    2348 0 0       0 if (!ref $tabindex) {
        0          
        0          
    2349 0         0 $self->element_tab($tabindex);
    2350             } elsif (ref $tabindex eq 'ARRAY') {
    2351 0         0 %tabs = map {$_=>$self->element_tab} @$tabindex;
      0         0  
    2352             } elsif (ref $tabindex eq 'HASH') {
    2353 0         0 %tabs = %$tabindex;
    2354             }
    2355             }
    2356 13 50       30 %tabs = map {$_=>$self->element_tab} @values unless %tabs;
      37         50  
    2357 13 100       32 my $other = @other ? "@other " : '';
    2358 13         13 my $radio_checked;
    2359              
    2360             # for disabling groups of radio/checkbox buttons
    2361             my %disabled;
    2362 13         12 for (@{$disabled}) {
      13         23  
    2363 1         2 $disabled{$_}=1;
    2364             }
    2365              
    2366 13         17 for (@values) {
    2367 37         32 my $disable="";
    2368 37 100       59 if ($disabled{$_}) {
    2369 1         1 $disable="disabled='1'";
    2370             }
    2371              
    2372             my $checkit = $self->_checked($box_type eq 'radio' ? ($checked{$_} && !$radio_checked++)
    2373 37 100 100     125 : $checked{$_});
    2374 37         39 my($break);
    2375 37 100       42 if ($linebreak) {
    2376 4 50       6 $break = $XHTML ? "
    " : "
    ";
    2377             }
    2378             else {
    2379 33         23 $break = '';
    2380             }
    2381 37         33 my($label)='';
    2382 37 50 33     78 unless (defined($nolabels) && $nolabels) {
    2383 37         30 $label = $_;
    2384 37 100 100     72 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2385 37         54 $label = $self->_maybe_escapeHTML($label,1);
    2386 37 100       951 $label = "$label" if $disabled{$_};
    2387             }
    2388 37         58 my $attribs = $self->_set_attributes($_, $attributes);
    2389 37         35 my $tab = $tabs{$_};
    2390 37         86 $_=$self->_maybe_escapeHTML($_);
    2391              
    2392 37 100       726 if ($XHTML) {
    2393 34         110 push @elements,
    2394             CGI::label($labelattributes,
    2395             qq($label)).${break};
    2396             } else {
    2397 3         12 push(@elements,qq/${label}${break}/);
    2398             }
    2399             }
    2400 13         25 $self->register_parameter($name);
    2401 13 50 66     134 return wantarray ? @elements : "@elements"
        100          
    2402             unless defined($columns) || defined($rows);
    2403 1         4 return _tableize($rows,$columns,$rowheaders,$colheaders,@elements);
    2404             }
    2405              
    2406             #### Method: popup_menu
    2407             # Create a popup menu.
    2408             # Parameters:
    2409             # $name -> Name for all the menu
    2410             # $values -> A pointer to a regular array containing the
    2411             # text of each menu item.
    2412             # $default -> (optional) Default item to display
    2413             # $labels -> (optional)
    2414             # A pointer to a hash of labels to print next to each checkbox
    2415             # in the form $label{'value'}="Long explanatory label".
    2416             # Otherwise the provided values are used as the labels.
    2417             # Returns:
    2418             # A string containing the definition of a popup menu.
    2419             ####
    2420             sub popup_menu {
    2421 8     8 0 300 my($self,@p) = self_or_default(@_);
    2422              
    2423 8         49 my($name,$values,$default,$labels,$attributes,$override,$tabindex,@other) =
    2424             rearrange([NAME,[VALUES,VALUE],[DEFAULT,DEFAULTS],LABELS,
    2425             ATTRIBUTES,[OVERRIDE,FORCE],TABINDEX],@p);
    2426 8         18 my($result,%selected);
    2427              
    2428 8 50 66     38 if (!$override && defined($self->param($name))) {
        100          
    2429 0         0 $selected{$self->param($name)}++;
    2430             } elsif (defined $default) {
    2431 7 50       18 %selected = map {$_=>1} ref($default) eq 'ARRAY'
      7         22  
    2432             ? @$default
    2433             : $default;
    2434             }
    2435 8         17 $name=$self->_maybe_escapeHTML($name);
    2436             # RT #30057 - ignore -multiple, if you need this
    2437             # then use scrolling_list
    2438 8         275 @other = grep { $_ !~ /^multiple=/i } @other;
      3         11  
    2439 8 100       21 my($other) = @other ? " @other" : '';
    2440              
    2441 8         21 my(@values);
    2442 8         23 @values = $self->_set_values_and_labels($values,\$labels,$name);
    2443 8         18 $tabindex = $self->element_tab($tabindex);
    2444 8 100       17 $name = q{} if ! defined $name;
    2445 8         20 $result = qq/
    2446 8         13 for (@values) {
    2447 22 100       35 if (/
    2448 3         12 for my $v (split(/\n/)) {
    2449 11 50       18 my $selectit = $XHTML ? 'selected="selected"' : 'selected';
    2450 11         16 for my $selected (keys %selected) {
    2451 11         70 $v =~ s/(value="\Q$selected\E")/$selectit $1/;
    2452             }
    2453 11         18 $result .= "$v\n";
    2454             }
    2455             }
    2456             else {
    2457 19         36 my $attribs = $self->_set_attributes($_, $attributes);
    2458 19         58 my($selectit) = $self->_selected($selected{$_});
    2459 19         27 my($label) = $_;
    2460 19 100 66     45 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2461 19         27 my($value) = $self->_maybe_escapeHTML($_);
    2462 19         342 $label = $self->_maybe_escapeHTML($label,1);
    2463 19         472 $result .= "$label\n";
    2464             }
    2465             }
    2466              
    2467 8         11 $result .= "";
    2468 8         43 return $result;
    2469             }
    2470              
    2471             #### Method: optgroup
    2472             # Create a optgroup.
    2473             # Parameters:
    2474             # $name -> Label for the group
    2475             # $values -> A pointer to a regular array containing the
    2476             # values for each option line in the group.
    2477             # $labels -> (optional)
    2478             # A pointer to a hash of labels to print next to each item
    2479             # in the form $label{'value'}="Long explanatory label".
    2480             # Otherwise the provided values are used as the labels.
    2481             # $labeled -> (optional)
    2482             # A true value indicates the value should be used as the label attribute
    2483             # in the option elements.
    2484             # The label attribute specifies the option label presented to the user.
    2485             # This defaults to the content of the
    2486             # attribute allows authors to more easily use optgroup without sacrificing
    2487             # compatibility with browsers that do not support option groups.
    2488             # $novals -> (optional)
    2489             # A true value indicates to suppress the val attribute in the option elements
    2490             # Returns:
    2491             # A string containing the definition of an option group.
    2492             ####
    2493             sub optgroup {
    2494 3     3 0 11 my($self,@p) = self_or_default(@_);
    2495 3         20 my($name,$values,$attributes,$labeled,$noval,$labels,@other)
    2496             = rearrange([NAME,[VALUES,VALUE],ATTRIBUTES,LABELED,NOVALS,LABELS],@p);
    2497              
    2498 3         6 my($result,@values);
    2499 3         13 @values = $self->_set_values_and_labels($values,\$labels,$name,$labeled,$novals);
    2500 3 100       11 my($other) = @other ? " @other" : '';
    2501              
    2502 3   100     9 $name = $self->_maybe_escapeHTML($name) || q{};
    2503 3         46 $result = qq/\n/;
    2504 3         8 for (@values) {
    2505 5 50       11 if (/
    2506 0         0 for (split(/\n/)) {
    2507 0 0       0 my $selectit = $XHTML ? 'selected="selected"' : 'selected';
    2508 0 0       0 s/(value="$selected")/$selectit $1/ if defined $selected;
    2509 0         0 $result .= "$_\n";
    2510             }
    2511             }
    2512             else {
    2513 5         11 my $attribs = $self->_set_attributes($_, $attributes);
    2514 5         8 my($label) = $_;
    2515 5 50 33     15 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2516 5         11 $label=$self->_maybe_escapeHTML($label);
    2517 5         102 my($value)=$self->_maybe_escapeHTML($_,1);
    2518 5 0       95 $result .= $labeled ? $novals ? "$label\n"
        50          
        50          
    2519             : "$label\n"
    2520             : $novals ? "$label\n"
    2521             : "$label\n";
    2522             }
    2523             }
    2524 3         6 $result .= "";
    2525 3         16 return $result;
    2526             }
    2527              
    2528             #### Method: scrolling_list
    2529             # Create a scrolling list.
    2530             # Parameters:
    2531             # $name -> name for the list
    2532             # $values -> A pointer to a regular array containing the
    2533             # values for each option line in the list.
    2534             # $defaults -> (optional)
    2535             # 1. If a pointer to a regular array of options,
    2536             # then this will be used to decide which
    2537             # lines to turn on by default.
    2538             # 2. Otherwise holds the value of the single line to turn on.
    2539             # $size -> (optional) Size of the list.
    2540             # $multiple -> (optional) If set, allow multiple selections.
    2541             # $labels -> (optional)
    2542             # A pointer to a hash of labels to print next to each checkbox
    2543             # in the form $label{'value'}="Long explanatory label".
    2544             # Otherwise the provided values are used as the labels.
    2545             # Returns:
    2546             # A string containing the definition of a scrolling list.
    2547             ####
    2548             sub scrolling_list {
    2549 3     3 0 7 my($self,@p) = self_or_default(@_);
    2550 3         19 my($name,$values,$defaults,$size,$multiple,$labels,$attributes,$override,$tabindex,@other)
    2551             = rearrange([NAME,[VALUES,VALUE],[DEFAULTS,DEFAULT],
    2552             SIZE,MULTIPLE,LABELS,ATTRIBUTES,[OVERRIDE,FORCE],TABINDEX],@p);
    2553              
    2554 3         6 my($result,@values);
    2555 3         9 @values = $self->_set_values_and_labels($values,\$labels,$name);
    2556              
    2557 3   100     9 $size = $size || scalar(@values);
    2558              
    2559 3         9 my(%selected) = $self->previous_or_default($name,$defaults,$override);
    2560              
    2561 3 100       7 my($is_multiple) = $multiple ? qq/ multiple="multiple"/ : '';
    2562 3 50       10 my($has_size) = $size ? qq/ size="$size"/: '';
    2563 3 100       8 my($other) = @other ? " @other" : '';
    2564              
    2565 3         6 $name=$self->_maybe_escapeHTML($name);
    2566 3         64 $tabindex = $self->element_tab($tabindex);
    2567 3         10 $result = qq/
    2568 3         6 for (@values) {
    2569 11 100       18 if (/
    2570 1         6 for my $v (split(/\n/)) {
    2571 4 50       6 my $selectit = $XHTML ? 'selected="selected"' : 'selected';
    2572 4         6 for my $selected (keys %selected) {
    2573 4         16 $v =~ s/(value="$selected")/$selectit $1/;
    2574             }
    2575 4         8 $result .= "$v\n";
    2576             }
    2577             }
    2578             else {
    2579 10         15 my $attribs = $self->_set_attributes($_, $attributes);
    2580 10         21 my($selectit) = $self->_selected($selected{$_});
    2581 10         12 my($label) = $_;
    2582 10 100 66     26 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2583 10         14 my($value) = $self->_maybe_escapeHTML($_);
    2584 10         165 $label = $self->_maybe_escapeHTML($label,1);
    2585 10         180 $result .= "$label\n";
    2586             }
    2587             }
    2588              
    2589 3         4 $result .= "";
    2590 3         6 $self->register_parameter($name);
    2591 3         15 return $result;
    2592             }
    2593              
    2594             #### Method: hidden
    2595             # Parameters:
    2596             # $name -> Name of the hidden field
    2597             # @default -> (optional) Initial values of field (may be an array)
    2598             # or
    2599             # $default->[initial values of field]
    2600             # Returns:
    2601             # A string containing a
    2602             ####
    2603             sub hidden {
    2604 7     7 0 17 my($self,@p) = self_or_default(@_);
    2605              
    2606             # this is the one place where we departed from our standard
    2607             # calling scheme, so we have to special-case (darn)
    2608 7         9 my(@result,@value);
    2609 7         28 my($name,$default,$override,@other) =
    2610             rearrange([NAME,[DEFAULT,VALUE,VALUES],[OVERRIDE,FORCE]],@p);
    2611              
    2612 7         12 my $do_override = 0;
    2613 7 100 66     30 if ( ref($p[0]) || substr($p[0],0,1) eq '-') {
    2614 5 100       10 @value = ref($default) ? @{$default} : $default;
      4         9  
    2615 5         6 $do_override = $override;
    2616             } else {
    2617 2         4 for ($default,$override,@other) {
    2618 6 100       9 push(@value,$_) if defined($_);
    2619             }
    2620 2         4 undef @other;
    2621             }
    2622              
    2623             # use previous values if override is not set
    2624 7         12 my @prev = $self->param($name);
    2625 7 50 66     27 @value = @prev if !$do_override && @prev;
    2626              
    2627 7         19 $name=$self->_maybe_escapeHTML($name);
    2628 7         458 for (@value) {
    2629 18 50       37 $_ = defined($_) ? $self->_maybe_escapeHTML($_,1) : '';
    2630 18 50       616 push @result,$XHTML ? qq()
    2631             : qq();
    2632             }
    2633 7 100       44 return wantarray ? @result : join('',@result);
    2634             }
    2635              
    2636             #### Method: image_button
    2637             # Parameters:
    2638             # $name -> Name of the button
    2639             # $src -> URL of the image source
    2640             # $align -> Alignment style (TOP, BOTTOM or MIDDLE)
    2641             # Returns:
    2642             # A string containing a
    2643             ####
    2644             sub image_button {
    2645 1     1 0 3 my($self,@p) = self_or_default(@_);
    2646              
    2647 1         5 my($name,$src,$alignment,@other) =
    2648             rearrange([NAME,SRC,ALIGN],@p);
    2649              
    2650 1 50       5 my($align) = $alignment ? " align=\L\"$alignment\"" : '';
    2651 1 50       5 my($other) = @other ? " @other" : '';
    2652 1         2 $name=$self->_maybe_escapeHTML($name);
    2653 1 50       7 return $XHTML ? qq()
    2654             : qq//;
    2655             }
    2656              
    2657             #### Method: self_url
    2658             # Returns a URL containing the current script and all its
    2659             # param/value pairs arranged as a query. You can use this
    2660             # to create a link that, when selected, will reinvoke the
    2661             # script with all its state information preserved.
    2662             ####
    2663             sub self_url {
    2664 7     7 0 17 my($self,@p) = self_or_default(@_);
    2665 7         25 return $self->url('-path_info'=>1,'-query'=>1,'-full'=>1,@p);
    2666             }
    2667              
    2668             # This is provided as a synonym to self_url() for people unfortunate
    2669             # enough to have incorporated it into their programs already!
    2670             sub state {
    2671 1     1 1 3 &self_url;
    2672             }
    2673              
    2674             #### Method: url
    2675             # Like self_url, but doesn't return the query string part of
    2676             # the URL.
    2677             ####
    2678             sub url {
    2679 44     44 1 87 my($self,@p) = self_or_default(@_);
    2680 44         173 my ($relative,$absolute,$full,$path_info,$query,$base,$rewrite) =
    2681             rearrange(['RELATIVE','ABSOLUTE','FULL',['PATH','PATH_INFO'],['QUERY','QUERY_STRING'],'BASE','REWRITE'],@p);
    2682 44         75 my $url = '';
    2683 44 100 100     209 $full++ if $base || !($relative || $absolute);
          66        
    2684 44 100       66 $rewrite++ unless defined $rewrite;
    2685              
    2686 44         73 my $path = $self->path_info;
    2687 44         69 my $script_name = $self->script_name;
    2688 44   100     65 my $request_uri = $self->request_uri || '';
    2689 44 100       74 my $query_str = $query ? $self->query_string : '';
    2690              
    2691 44         75 $request_uri =~ s/\?.*$//s; # remove query string
    2692 44         71 $request_uri = unescape($request_uri);
    2693              
    2694 44 100 100     142 my $uri = $rewrite && $request_uri ? $request_uri : $script_name;
    2695 44         45 $uri =~ s/\?.*$//s; # remove query string
    2696              
    2697 44 100       71 if ( defined( $ENV{PATH_INFO} ) ) {
    2698             # IIS sometimes sets PATH_INFO to the same value as SCRIPT_NAME so only sub it out
    2699             # if SCRIPT_NAME isn't defined or isn't the same value as PATH_INFO
    2700             $uri =~ s/\Q$ENV{PATH_INFO}\E$//
    2701 38 100 66     331 if ( ! defined( $ENV{SCRIPT_NAME} ) or $ENV{PATH_INFO} ne $ENV{SCRIPT_NAME} );
    2702              
    2703             # if we're not IIS then keep to spec, the relevant info is here:
    2704             # https://tools.ietf.org/html/rfc3875#section-4.1.13, namely
    2705             # "No PATH_INFO segment (see section 4.1.5) is included in the
    2706             # SCRIPT_NAME value." (see GH #126, GH #152, GH #176)
    2707 38 100       63 if ( ! $IIS ) {
    2708 37         104 $uri =~ s/\Q$ENV{PATH_INFO}\E$//;
    2709             }
    2710             }
    2711              
    2712 44 100       80 if ($full) {
        100          
        50          
    2713 27         55 my $protocol = $self->protocol();
    2714 27         35 $url = "$protocol://";
    2715 27   100     33 my $vh = http('x_forwarded_host') || http('host') || '';
    2716 27         38 $vh =~ s/^.*,\s*//; # x_forwarded_host may be a comma-separated list (e.g. when the request has
    2717             # passed through multiple reverse proxies. Take the last one.
    2718 27         26 $vh =~ s/\:\d+$//; # some clients add the port number (incorrectly). Get rid of it.
    2719              
    2720 27   66     64 $url .= $vh || server_name();
    2721              
    2722 27         45 my $port = $self->virtual_port;
    2723              
    2724             # add the port to the url unless it's the protocol's default port
    2725 27 50 66     145 $url .= ':' . $port unless (lc($protocol) eq 'http' && $port == 80)
          33        
          66        
    2726             or (lc($protocol) eq 'https' && $port == 443);
    2727              
    2728 27 50       41 return $url if $base;
    2729              
    2730 27         35 $url .= $uri;
    2731             } elsif ($relative) {
    2732 12         53 ($url) = $uri =~ m!([^/]+)$!;
    2733             } elsif ($absolute) {
    2734 5         6 $url = $uri;
    2735             }
    2736              
    2737 44 100 66     112 $url .= $path if $path_info and defined $path;
    2738 44 100 100     99 $url .= "?$query_str" if $query and $query_str ne '';
    2739 44   50     73 $url ||= '';
    2740 44         84 $url =~ s/([^a-zA-Z0-9_.%;&?\/\\:+=~-])/sprintf("%%%02X",ord($1))/eg;
      0         0  
    2741 44         158 return $url;
    2742             }
    2743              
    2744             #### Method: cookie
    2745             # Set or read a cookie from the specified name.
    2746             # Cookie can then be passed to header().
    2747             # Usual rules apply to the stickiness of -value.
    2748             # Parameters:
    2749             # -name -> name for this cookie (optional)
    2750             # -value -> value of this cookie (scalar, array or hash)
    2751             # -path -> paths for which this cookie is valid (optional)
    2752             # -domain -> internet domain in which this cookie is valid (optional)
    2753             # -secure -> if true, cookie only passed through secure channel (optional)
    2754             # -expires -> expiry date in format Wdy, DD-Mon-YYYY HH:MM:SS GMT (optional)
    2755             ####
    2756             sub cookie {
    2757 2     2 0 363 my($self,@p) = self_or_default(@_);
    2758 2         10 my($name,$value,$path,$domain,$secure,$expires,$httponly) =
    2759             rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES,HTTPONLY],@p);
    2760              
    2761 2         472 require CGI::Cookie;
    2762              
    2763             # if no value is supplied, then we retrieve the
    2764             # value of the cookie, if any. For efficiency, we cache the parsed
    2765             # cookies in our state variables.
    2766 2 50       5 unless ( defined($value) ) {
    2767 0         0 $self->{'.cookies'} = CGI::Cookie->fetch;
    2768            
    2769             # If no name is supplied, then retrieve the names of all our cookies.
    2770 0 0       0 return () unless $self->{'.cookies'};
    2771 0 0       0 return keys %{$self->{'.cookies'}} unless $name;
      0         0  
    2772 0 0       0 return () unless $self->{'.cookies'}->{$name};
    2773 0 0 0     0 return $self->{'.cookies'}->{$name}->value if defined($name) && $name ne '';
    2774             }
    2775              
    2776             # If we get here, we're creating a new cookie
    2777 2 50 33     12 return undef unless defined($name) && $name ne ''; # this is an error
    2778              
    2779 2         2 my @param;
    2780 2         4 push(@param,'-name'=>$name);
    2781 2         3 push(@param,'-value'=>$value);
    2782 2 50       4 push(@param,'-domain'=>$domain) if $domain;
    2783 2 50       6 push(@param,'-path'=>$path) if $path;
    2784 2 50       5 push(@param,'-expires'=>$expires) if $expires;
    2785 2 50       5 push(@param,'-secure'=>$secure) if $secure;
    2786 2 50       4 push(@param,'-httponly'=>$httponly) if $httponly;
    2787              
    2788 2         8 return CGI::Cookie->new(@param);
    2789             }
    2790              
    2791             sub parse_keywordlist {
    2792 7     7 0 8 my($self,$tosplit) = @_;
    2793 7         17 $tosplit = unescape($tosplit); # unescape the keywords
    2794 7         11 $tosplit=~tr/+/ /; # pluses to spaces
    2795 7         31 my(@keywords) = split(/\s+/,$tosplit);
    2796 7         22 return @keywords;
    2797             }
    2798              
    2799             sub param_fetch {
    2800 9     9 0 22 my($self,@p) = self_or_default(@_);
    2801 9         25 my($name) = rearrange([NAME],@p);
    2802 9 100       17 return [] unless defined $name;
    2803              
    2804 8 50       16 unless (exists($self->{param}{$name})) {
    2805 0         0 $self->add_parameter($name);
    2806 0         0 $self->{param}{$name} = [];
    2807             }
    2808            
    2809 8         29 return $self->{param}{$name};
    2810             }
    2811              
    2812             ###############################################
    2813             # OTHER INFORMATION PROVIDED BY THE ENVIRONMENT
    2814             ###############################################
    2815              
    2816             #### Method: path_info
    2817             # Return the extra virtual path information provided
    2818             # after the URL (if any)
    2819             ####
    2820             sub path_info {
    2821 45     45 1 53 my ($self,$info) = self_or_default(@_);
    2822 45 50       118 if (defined($info)) {
        100          
    2823 0 0 0     0 $info = "/$info" if $info ne '' && substr($info,0,1) ne '/';
    2824 0         0 $self->{'.path_info'} = $info;
    2825             } elsif (! defined($self->{'.path_info'}) ) {
    2826 10         24 my (undef,$path_info) = $self->_name_and_path_from_env;
    2827 10   100     56 $self->{'.path_info'} = $path_info || '';
    2828             }
    2829 45         59 return $self->{'.path_info'};
    2830             }
    2831              
    2832             # This function returns a potentially modified version of SCRIPT_NAME
    2833             # and PATH_INFO. Some HTTP servers do sanitise the paths in those
    2834             # variables. It is the case of at least Apache 2. If for instance the
    2835             # user requests: /path/./to/script.cgi/x//y/z/../x?y, Apache will set:
    2836             # REQUEST_URI=/path/./to/script.cgi/x//y/z/../x?y
    2837             # SCRIPT_NAME=/path/to/env.cgi
    2838             # PATH_INFO=/x/y/x
    2839             #
    2840             # This is all fine except that some bogus CGI scripts expect
    2841             # PATH_INFO=/http://foo when the user requests
    2842             # http://xxx/script.cgi/http://foo
    2843             #
    2844             # Old versions of this module used to accomodate with those scripts, so
    2845             # this is why we do this here to keep those scripts backward compatible.
    2846             # Basically, we accomodate with those scripts but within limits, that is
    2847             # we only try to preserve the number of / that were provided by the user
    2848             # if $REQUEST_URI and "$SCRIPT_NAME$PATH_INFO" only differ by the number
    2849             # of consecutive /.
    2850             #
    2851             # So for instance, in: http://foo/x//y/script.cgi/a//b, we'll return a
    2852             # script_name of /x//y/script.cgi and a path_info of /a//b, but in:
    2853             # http://foo/./x//z/script.cgi/a/../b//c, we'll return the versions
    2854             # possibly sanitised by the HTTP server, so in the case of Apache 2:
    2855             # script_name == /foo/x/z/script.cgi and path_info == /b/c.
    2856             #
    2857             # Future versions of this module may no longer do that, so one should
    2858             # avoid relying on the browser, proxy, server, and CGI.pm preserving the
    2859             # number of consecutive slashes as no guarantee can be made there.
    2860             sub _name_and_path_from_env {
    2861 20     20   21 my $self = shift;
    2862 20   100     59 my $script_name = $ENV{SCRIPT_NAME} || '';
    2863 20   100     45 my $path_info = $ENV{PATH_INFO} || '';
    2864 20   100     40 my $uri = $self->request_uri || '';
    2865              
    2866 20         39 $uri =~ s/\?.*//s;
    2867 20         44 $uri = unescape($uri);
    2868              
    2869 20 100       156 if ( $IIS ) {
        100          
    2870             # IIS doesn't set $ENV{PATH_INFO} correctly. It sets it to
    2871             # $ENV{SCRIPT_NAME}path_info
    2872             # IIS also doesn't set $ENV{REQUEST_URI} so we don't want to do
    2873             # the test below, hence this comes first
    2874 2         23 $path_info =~ s/^\Q$script_name\E(.*)/$1/;
    2875             } elsif ($uri ne "$script_name$path_info") {
    2876 8         12 my $script_name_pattern = quotemeta($script_name);
    2877 8         10 my $path_info_pattern = quotemeta($path_info);
    2878 8         47 $script_name_pattern =~ s{(?:\\/)+}{/+}g;
    2879 8         24 $path_info_pattern =~ s{(?:\\/)+}{/+}g;
    2880              
    2881 8 50       105 if ($uri =~ /^($script_name_pattern)($path_info_pattern)$/s) {
    2882             # REQUEST_URI and SCRIPT_NAME . PATH_INFO only differ by the
    2883             # numer of consecutive slashes, so we can extract the info from
    2884             # REQUEST_URI:
    2885 0         0 ($script_name, $path_info) = ($1, $2);
    2886             }
    2887             }
    2888 20         42 return ($script_name,$path_info);
    2889             }
    2890              
    2891             #### Method: request_method
    2892             # Returns 'POST', 'GET', 'PUT', 'PATCH' or 'HEAD'
    2893             ####
    2894             sub request_method {
    2895 7 50   7 1 1052 return (defined $ENV{'REQUEST_METHOD'}) ? $ENV{'REQUEST_METHOD'} : undef;
    2896             }
    2897              
    2898             #### Method: content_type
    2899             # Returns the content_type string
    2900             ####
    2901             sub content_type {
    2902 0 0   0 1 0 return (defined $ENV{'CONTENT_TYPE'}) ? $ENV{'CONTENT_TYPE'} : undef;
    2903             }
    2904              
    2905             #### Method: path_translated
    2906             # Return the physical path information provided
    2907             # by the URL (if any)
    2908             ####
    2909             sub path_translated {
    2910 0 0   0 1 0 return (defined $ENV{'PATH_TRANSLATED'}) ? $ENV{'PATH_TRANSLATED'} : undef;
    2911             }
    2912              
    2913             #### Method: request_uri
    2914             # Return the literal request URI
    2915             ####
    2916             sub request_uri {
    2917 64 100   64 1 192 return (defined $ENV{'REQUEST_URI'}) ? $ENV{'REQUEST_URI'} : undef;
    2918             }
    2919              
    2920             #### Method: query_string
    2921             # Synthesize a query string from our current
    2922             # parameters
    2923             ####
    2924             sub query_string {
    2925 29     29 0 69 my($self) = self_or_default(@_);
    2926 29         31 my($param,$value,@pairs);
    2927 29         51 for $param ($self->param) {
    2928 61         97 my($eparam) = escape($param);
    2929 61         76 for $value ($self->param($param)) {
    2930 79         114 $value = escape($value);
    2931 79 100       109 next unless defined $value;
    2932 72         129 push(@pairs,"$eparam=$value");
    2933             }
    2934             }
    2935 29         33 for (keys %{$self->{'.fieldnames'}}) {
      29         58  
    2936 0         0 push(@pairs,".cgifields=".escape("$_"));
    2937             }
    2938 29 50       128 return join($USE_PARAM_SEMICOLONS ? ';' : '&',@pairs);
    2939             }
    2940              
    2941             sub env_query_string {
    2942 1 50   1 1 9 return (defined $ENV{'QUERY_STRING'}) ? $ENV{'QUERY_STRING'} : undef;
    2943             }
    2944              
    2945             #### Method: accept
    2946             # Without parameters, returns an array of the
    2947             # MIME types the browser accepts.
    2948             # With a single parameter equal to a MIME
    2949             # type, will return undef if the browser won't
    2950             # accept it, 1 if the browser accepts it but
    2951             # doesn't give a preference, or a floating point
    2952             # value between 0.0 and 1.0 if the browser
    2953             # declares a quantitative score for it.
    2954             # This handles MIME type globs correctly.
    2955             ####
    2956             sub Accept {
    2957 0     0 1 0 my($self,$search) = self_or_CGI(@_);
    2958 0         0 my(%prefs,$type,$pref,$pat);
    2959            
    2960 0 0       0 my(@accept) = defined $self->http('accept')
    2961             ? split(',',$self->http('accept'))
    2962             : ();
    2963              
    2964 0         0 for (@accept) {
    2965 0         0 ($pref) = /q=(\d\.\d+|\d+)/;
    2966 0         0 ($type) = m#(\S+/[^;]+)#;
    2967 0 0       0 next unless $type;
    2968 0   0     0 $prefs{$type}=$pref || 1;
    2969             }
    2970              
    2971 0 0       0 return keys %prefs unless $search;
    2972            
    2973             # if a search type is provided, we may need to
    2974             # perform a pattern matching operation.
    2975             # The MIME types use a glob mechanism, which
    2976             # is easily translated into a perl pattern match
    2977              
    2978             # First return the preference for directly supported
    2979             # types:
    2980 0 0       0 return $prefs{$search} if $prefs{$search};
    2981              
    2982             # Didn't get it, so try pattern matching.
    2983 0         0 for (keys %prefs) {
    2984 0 0       0 next unless /\*/; # not a pattern match
    2985 0         0 ($pat = $_) =~ s/([^\w*])/\\$1/g; # escape meta characters
    2986 0         0 $pat =~ s/\*/.*/g; # turn it into a pattern
    2987 0 0       0 return $prefs{$_} if $search=~/$pat/;
    2988             }
    2989             }
    2990              
    2991             #### Method: user_agent
    2992             # If called with no parameters, returns the user agent.
    2993             # If called with one parameter, does a pattern match (case
    2994             # insensitive) on the user agent.
    2995             ####
    2996             sub user_agent {
    2997 7     7 1 22 my($self,$match)=self_or_CGI(@_);
    2998 7         22 my $user_agent = $self->http('user_agent');
    2999 7 100 66     55 return $user_agent unless defined $match && $match && $user_agent;
          100        
    3000 4         89 return $user_agent =~ /$match/i;
    3001             }
    3002              
    3003             #### Method: raw_cookie
    3004             # Returns the magic cookies for the session.
    3005             # The cookies are not parsed or altered in any way, i.e.
    3006             # cookies are returned exactly as given in the HTTP
    3007             # headers. If a cookie name is given, only that cookie's
    3008             # value is returned, otherwise the entire raw cookie
    3009             # is returned.
    3010             ####
    3011             sub raw_cookie {
    3012 0     0 1 0 my($self,$key) = self_or_CGI(@_);
    3013              
    3014 0         0 require CGI::Cookie;
    3015              
    3016 0 0       0 if (defined($key)) {
    3017             $self->{'.raw_cookies'} = CGI::Cookie->raw_fetch
    3018 0 0       0 unless $self->{'.raw_cookies'};
    3019              
    3020 0 0       0 return () unless $self->{'.raw_cookies'};
    3021 0 0       0 return () unless $self->{'.raw_cookies'}->{$key};
    3022 0         0 return $self->{'.raw_cookies'}->{$key};
    3023             }
    3024 0   0     0 return $self->http('cookie') || $ENV{'COOKIE'} || '';
    3025             }
    3026              
    3027             #### Method: virtual_host
    3028             # Return the name of the virtual_host, which
    3029             # is not always the same as the server
    3030             ######
    3031             sub virtual_host {
    3032 0   0 0 1 0 my $vh = http('x_forwarded_host') || http('host') || server_name();
    3033 0         0 $vh =~ s/:\d+$//; # get rid of port number
    3034 0         0 return $vh;
    3035             }
    3036              
    3037             #### Method: remote_host
    3038             # Return the name of the remote host, or its IP
    3039             # address if unavailable. If this variable isn't
    3040             # defined, it returns "localhost" for debugging
    3041             # purposes.
    3042             ####
    3043             sub remote_host {
    3044 0   0 0 1 0 return $ENV{'REMOTE_HOST'} || $ENV{'REMOTE_ADDR'}
    3045             || 'localhost';
    3046             }
    3047              
    3048             #### Method: remote_addr
    3049             # Return the IP addr of the remote host.
    3050             ####
    3051             sub remote_addr {
    3052 0   0 0 1 0 return $ENV{'REMOTE_ADDR'} || '127.0.0.1';
    3053             }
    3054              
    3055             #### Method: script_name
    3056             # Return the partial URL to this script for
    3057             # self-referencing scripts. Also see
    3058             # self_url(), which returns a URL with all state information
    3059             # preserved.
    3060             ####
    3061             sub script_name {
    3062 48     48 1 70 my ($self,@p) = self_or_default(@_);
    3063 48 50       128 if (@p) {
        100          
    3064 0         0 $self->{'.script_name'} = shift @p;
    3065             } elsif (!exists $self->{'.script_name'}) {
    3066 10         30 my ($script_name,$path_info) = $self->_name_and_path_from_env();
    3067 10         25 $self->{'.script_name'} = $script_name;
    3068             }
    3069 48         63 return $self->{'.script_name'};
    3070             }
    3071              
    3072             #### Method: referer
    3073             # Return the HTTP_REFERER: useful for generating
    3074             # a GO BACK button.
    3075             ####
    3076             sub referer {
    3077 0     0 1 0 my($self) = self_or_CGI(@_);
    3078 0         0 return $self->http('referer');
    3079             }
    3080              
    3081             #### Method: server_name
    3082             # Return the name of the server
    3083             ####
    3084             sub server_name {
    3085 11   100 11 1 50 return $ENV{'SERVER_NAME'} || 'localhost';
    3086             }
    3087              
    3088             #### Method: server_software
    3089             # Return the name of the server software
    3090             ####
    3091             sub server_software {
    3092 5   50 5 1 28 return $ENV{'SERVER_SOFTWARE'} || 'cmdline';
    3093             }
    3094              
    3095             #### Method: virtual_port
    3096             # Return the server port, taking virtual hosts into account
    3097             ####
    3098             sub virtual_port {
    3099 28     28 1 59 my($self) = self_or_default(@_);
    3100 28   100     40 my $vh = $self->http('x_forwarded_host') || $self->http('host');
    3101 28         47 my $protocol = $self->protocol;
    3102 28 100       39 if ($vh) {
    3103 17   66     65 return ($vh =~ /:(\d+)$/)[0] || ($protocol eq 'https' ? 443 : 80);
    3104             } else {
    3105 11         18 return $self->server_port();
    3106             }
    3107             }
    3108              
    3109             #### Method: server_port
    3110             # Return the tcp/ip port the server is running on
    3111             ####
    3112             sub server_port {
    3113 67   100 67 1 210 return $ENV{'SERVER_PORT'} || 80; # for debugging
    3114             }
    3115              
    3116             #### Method: server_protocol
    3117             # Return the protocol (usually HTTP/1.0)
    3118             ####
    3119             sub server_protocol {
    3120 55   100 55 1 125 return $ENV{'SERVER_PROTOCOL'} || 'HTTP/1.0'; # for debugging
    3121             }
    3122              
    3123             #### Method: http
    3124             # Return the value of an HTTP variable, or
    3125             # the list of variables if none provided
    3126             ####
    3127             sub http {
    3128 118     118 1 552 my ($self,$parameter) = self_or_CGI(@_);
    3129 118 100       168 if ( defined($parameter) ) {
    3130 116         105 $parameter =~ tr/-a-z/_A-Z/;
    3131 116 100       204 if ( $parameter =~ /^HTTP(?:_|$)/ ) {
    3132 1         5 return $ENV{$parameter};
    3133             }
    3134 115         351 return $ENV{"HTTP_$parameter"};
    3135             }
    3136 2         9 return grep { /^HTTP(?:_|$)/ } keys %ENV;
      45         40  
    3137             }
    3138              
    3139             #### Method: https
    3140             # Return the value of HTTPS, or
    3141             # the value of an HTTPS variable, or
    3142             # the list of variables
    3143             ####
    3144             sub https {
    3145 58     58 1 659 my ($self,$parameter) = self_or_CGI(@_);
    3146 58 50       95 if ( defined($parameter) ) {
    3147 0         0 $parameter =~ tr/-a-z/_A-Z/;
    3148 0 0       0 if ( $parameter =~ /^HTTPS(?:_|$)/ ) {
    3149 0         0 return $ENV{$parameter};
    3150             }
    3151 0         0 return $ENV{"HTTPS_$parameter"};
    3152             }
    3153             return wantarray
    3154 24         27 ? grep { /^HTTPS(?:_|$)/ } keys %ENV
    3155 58 100       158 : $ENV{'HTTPS'};
    3156             }
    3157              
    3158             #### Method: protocol
    3159             # Return the protocol (http or https currently)
    3160             ####
    3161             sub protocol {
    3162 55     55 0 104 local($^W)=0;
    3163 55         46 my $self = shift;
    3164 55 50       66 return 'https' if uc($self->https()) eq 'ON';
    3165 55 50       90 return 'https' if $self->server_port == 443;
    3166 55         77 my $prot = $self->server_protocol;
    3167 55         107 my($protocol,$version) = split('/',$prot);
    3168 55         103 return "\L$protocol\E";
    3169             }
    3170              
    3171             #### Method: remote_ident
    3172             # Return the identity of the remote user
    3173             # (but only if his host is running identd)
    3174             ####
    3175             sub remote_ident {
    3176 0 0   0 1 0 return (defined $ENV{'REMOTE_IDENT'}) ? $ENV{'REMOTE_IDENT'} : undef;
    3177             }
    3178              
    3179             #### Method: auth_type
    3180             # Return the type of use verification/authorization in use, if any.
    3181             ####
    3182             sub auth_type {
    3183 0 0   0 1 0 return (defined $ENV{'AUTH_TYPE'}) ? $ENV{'AUTH_TYPE'} : undef;
    3184             }
    3185              
    3186             #### Method: remote_user
    3187             # Return the authorization name used for user
    3188             # verification.
    3189             ####
    3190             sub remote_user {
    3191 0 0   0 1 0 return (defined $ENV{'REMOTE_USER'}) ? $ENV{'REMOTE_USER'} : undef;
    3192             }
    3193              
    3194             #### Method: user_name
    3195             # Try to return the remote user's name by hook or by
    3196             # crook
    3197             ####
    3198             sub user_name {
    3199 0     0 1 0 my ($self) = self_or_CGI(@_);
    3200 0   0     0 return $self->http('from') || $ENV{'REMOTE_IDENT'} || $ENV{'REMOTE_USER'};
    3201             }
    3202              
    3203             #### Method: nosticky
    3204             # Set or return the NOSTICKY global flag
    3205             ####
    3206             sub nosticky {
    3207 1     1 0 2 my ($self,$param) = self_or_CGI(@_);
    3208 1 50       3 $CGI::NOSTICKY = $param if defined($param);
    3209 1         3 return $CGI::NOSTICKY;
    3210             }
    3211              
    3212             #### Method: nph
    3213             # Set or return the NPH global flag
    3214             ####
    3215             sub nph {
    3216 1     1 1 4 my ($self,$param) = self_or_CGI(@_);
    3217 1 50       4 $CGI::NPH = $param if defined($param);
    3218 1         3 return $CGI::NPH;
    3219             }
    3220              
    3221             #### Method: private_tempfiles
    3222             # Set or return the private_tempfiles global flag
    3223             ####
    3224             sub private_tempfiles {
    3225 1     1 0 16 warn "private_tempfiles has been deprecated";
    3226 1         3 return 0;
    3227             }
    3228             #### Method: close_upload_files
    3229             # Set or return the close_upload_files global flag
    3230             ####
    3231             sub close_upload_files {
    3232 1     1 0 2 my ($self,$param) = self_or_CGI(@_);
    3233 1 50       4 $CGI::CLOSE_UPLOAD_FILES = $param if defined($param);
    3234 1         3 return $CGI::CLOSE_UPLOAD_FILES;
    3235             }
    3236              
    3237             #### Method: default_dtd
    3238             # Set or return the default_dtd global
    3239             ####
    3240             sub default_dtd {
    3241 1     1 0 4 my ($self,$param,$param2) = self_or_CGI(@_);
    3242 1 50 33     7 if (defined $param2 && defined $param) {
        50          
    3243 0         0 $CGI::DEFAULT_DTD = [ $param, $param2 ];
    3244             } elsif (defined $param) {
    3245 0         0 $CGI::DEFAULT_DTD = $param;
    3246             }
    3247 1         5 return $CGI::DEFAULT_DTD;
    3248             }
    3249              
    3250             # -------------- really private subroutines -----------------
    3251             sub _maybe_escapeHTML {
    3252             # hack to work around earlier hacks
    3253 318 50 33 318   590 push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
    3254 318         379 my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_);
    3255 318 100       491 return undef unless defined($toencode);
    3256 304 100 66     926 return $toencode if ref($self) && !$self->{'escape'};
    3257 244         339 return $self->escapeHTML($toencode, $newlinestoo);
    3258             }
    3259              
    3260             sub previous_or_default {
    3261 16     16 0 19 my($self,$name,$defaults,$override) = @_;
    3262 16         13 my(%selected);
    3263              
    3264 16 100 66     85 if (!$override && ($self->{'.fieldnames'}->{$name} ||
        100 66        
          100        
          66        
    3265             defined($self->param($name)) ) ) {
    3266 7         10 $selected{$_}++ for $self->param($name);
    3267             } elsif (defined($defaults) && ref($defaults) &&
    3268             (ref($defaults) eq 'ARRAY')) {
    3269 6         10 $selected{$_}++ for @{$defaults};
      6         16  
    3270             } else {
    3271 3 100       8 $selected{$defaults}++ if defined($defaults);
    3272             }
    3273              
    3274 16         48 return %selected;
    3275             }
    3276              
    3277             sub register_parameter {
    3278 25     25 0 69 my($self,$param) = @_;
    3279 25         45 $self->{'.parametersToAdd'}->{$param}++;
    3280             }
    3281              
    3282             sub get_fields {
    3283 1     1 0 2 my($self) = @_;
    3284             return $self->CGI::hidden('-name'=>'.cgifields',
    3285 1         1 '-values'=>[keys %{$self->{'.parametersToAdd'}}],
      1         7  
    3286             '-override'=>1);
    3287             }
    3288              
    3289             sub read_from_cmdline {
    3290 74     74 0 173 my($input,@words);
    3291 0         0 my($query_string);
    3292 0         0 my($subpath);
    3293 74 50 33     372 if ($DEBUG && @ARGV) {
        50          
    3294 0         0 @words = @ARGV;
    3295             } elsif ($DEBUG > 1) {
    3296 0         0 require Text::ParseWords;
    3297 0         0 print STDERR "(offline mode: enter name=value pairs on standard input; press ^D or ^Z when done)\n";
    3298 0         0 chomp(@lines = ); # remove newlines
    3299 0         0 $input = join(" ",@lines);
    3300 0         0 @words = &Text::ParseWords::old_shellwords($input);
    3301             }
    3302 74         156 for (@words) {
    3303 0         0 s/\\=/%3D/g;
    3304 0         0 s/\\&/%26/g;
    3305             }
    3306              
    3307 74 50       229 if ("@words"=~/=/) {
    3308 0         0 $query_string = join('&',@words);
    3309             } else {
    3310 74         145 $query_string = join('+',@words);
    3311             }
    3312 74 50       138 if ($query_string =~ /^(.*?)\?(.*)$/)
    3313             {
    3314 0         0 $query_string = $2;
    3315 0         0 $subpath = $1;
    3316             }
    3317 74         214 return { 'query_string' => $query_string, 'subpath' => $subpath };
    3318             }
    3319              
    3320             #####
    3321             # subroutine: read_multipart
    3322             #
    3323             # Read multipart data and store it into our parameters.
    3324             # An interesting feature is that if any of the parts is a file, we
    3325             # create a temporary file and open up a filehandle on it so that the
    3326             # caller can read from it if necessary.
    3327             #####
    3328             sub read_multipart {
    3329 2     2 0 4 my($self,$boundary,$length) = @_;
    3330 2         6 my($buffer) = $self->new_MultipartBuffer($boundary,$length);
    3331 2 50       6 return unless $buffer;
    3332 2         2 my(%header,$body);
    3333 2         2 my $filenumber = 0;
    3334 2         5 while (!$buffer->eof) {
    3335 10         18 %header = $buffer->readHeader;
    3336              
    3337 10 50       23 unless (%header) {
    3338 0         0 $self->cgi_error("400 Bad request (malformed multipart POST)");
    3339 0         0 return;
    3340             }
    3341              
    3342 10   50     15 $header{'Content-Disposition'} ||= ''; # quench uninit variable warning
    3343              
    3344 10         42 my($param)= $header{'Content-Disposition'}=~/[\s;]name="([^"]*)"/;
    3345 10         12 $param .= $TAINTED;
    3346              
    3347             # See RFC 1867, 2183, 2045
    3348             # NB: File content will be loaded into memory should
    3349             # content-disposition parsing fail.
    3350 10         36 my ($filename) = $header{'Content-Disposition'}
    3351             =~/ filename=(("[^"]*")|([a-z\d!\#'\*\+,\.^_\`\{\}\|\~]*))/i;
    3352              
    3353 10   50     17 $filename ||= ''; # quench uninit variable warning
    3354              
    3355 10         31 $filename =~ s/^"([^"]*)"$/$1/;
    3356             # Test for Opera's multiple upload feature
    3357             my($multipart) = ( defined( $header{'Content-Type'} ) &&
    3358 10 50 33     43 $header{'Content-Type'} =~ /multipart\/mixed/ ) ?
    3359             1 : 0;
    3360              
    3361             # add this parameter to our list
    3362 10         19 $self->add_parameter($param);
    3363              
    3364             # If no filename specified, then just read the data and assign it
    3365             # to our parameter list.
    3366 10 50 33     55 if ( ( !defined($filename) || $filename eq '' ) && !$multipart ) {
          33        
    3367 0         0 my($value) = $buffer->readBody;
    3368 0         0 $value .= $TAINTED;
    3369 0         0 push(@{$self->{param}{$param}},$value);
      0         0  
    3370 0         0 next;
    3371             }
    3372              
    3373             UPLOADS: {
    3374             # If we get here, then we are dealing with a potentially large
    3375             # uploaded form. Save the data to a temporary file, then open
    3376             # the file for reading.
    3377              
    3378             # skip the file if uploads disabled
    3379 10 50       6 if ($DISABLE_UPLOADS) {
      10         17  
    3380 0         0 while (defined($data = $buffer->read)) { }
    3381 0         0 last UPLOADS;
    3382             }
    3383              
    3384             # set the filename to some recognizable value
    3385 10 50 33     35 if ( ( !defined($filename) || $filename eq '' ) && $multipart ) {
          33        
    3386 0         0 $filename = "multipart/mixed";
    3387             }
    3388              
    3389             my $tmp_dir = $CGI::OS eq 'WINDOWS'
    3390 10 50 0     15 ? ( $ENV{TEMP} || $ENV{TMP} || ( $ENV{WINDIR} ? ( $ENV{WINDIR} . $SL . 'TEMP' ) : undef ) )
    3391             : undef; # File::Temp defaults to TMPDIR
    3392              
    3393 10         826 require CGI::File::Temp;
    3394 10         36 my $filehandle = CGI::File::Temp->new(
    3395             UNLINK => $UNLINK_TMP_FILES,
    3396             DIR => $tmp_dir,
    3397             );
    3398 10         3007 $filehandle->_mp_filename( $filename );
    3399              
    3400 10 50 33     25 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode
    3401             && defined fileno($filehandle);
    3402              
    3403             # if this is an multipart/mixed attachment, save the header
    3404             # together with the body for later parsing with an external
    3405             # MIME parser module
    3406 10 50       15 if ( $multipart ) {
    3407 0         0 for ( keys %header ) {
    3408 0         0 print $filehandle "$_: $header{$_}${CRLF}";
    3409             }
    3410 0         0 print $filehandle "${CRLF}";
    3411             }
    3412              
    3413 10         10 my ($data);
    3414 10         23 local($\) = '';
    3415 10         9 my $totalbytes = 0;
    3416 10         17 while (defined($data = $buffer->read)) {
    3417 10 50       19 if (defined $self->{'.upload_hook'})
    3418             {
    3419 0         0 $totalbytes += length($data);
    3420 0         0 &{$self->{'.upload_hook'}}($filename ,$data, $totalbytes, $self->{'.upload_data'});
      0         0  
    3421             }
    3422 10 50       83 print $filehandle $data if ($self->{'use_tempfile'});
    3423             }
    3424              
    3425             # back up to beginning of file
    3426 10         215 seek($filehandle,0,0);
    3427              
    3428             ## Close the filehandle if requested this allows a multipart MIME
    3429             ## upload to contain many files, and we won't die due to too many
    3430             ## open file handles. The user can access the files using the hash
    3431             ## below.
    3432 10 50       21 close $filehandle if $CLOSE_UPLOAD_FILES;
    3433 10 50       14 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;
    3434              
    3435             # Save some information about the uploaded file where we can get
    3436             # at it later.
    3437             # Use the typeglob + filename as the key, as this is guaranteed to be
    3438             # unique for each filehandle. Don't use the file descriptor as
    3439             # this will be re-used for each filehandle if the
    3440             # close_upload_files feature is used.
    3441 10         29 $self->{'.tmpfiles'}->{$$filehandle . $filehandle} = {
    3442             hndl => $filehandle,
    3443             name => $filehandle->filename,
    3444             info => {%header},
    3445             };
    3446 10         14 push(@{$self->{param}{$param}},$filehandle);
      10         51  
    3447             }
    3448             }
    3449             }
    3450              
    3451             #####
    3452             # subroutine: read_multipart_related
    3453             #
    3454             # Read multipart/related data and store it into our parameters. The
    3455             # first parameter sets the start of the data. The part identified by
    3456             # this Content-ID will not be stored as a file upload, but will be
    3457             # returned by this method. All other parts will be available as file
    3458             # uploads accessible by their Content-ID
    3459             #####
    3460             sub read_multipart_related {
    3461 1     1 0 1 my($self,$start,$boundary,$length) = @_;
    3462 1         4 my($buffer) = $self->new_MultipartBuffer($boundary,$length);
    3463 1 50       3 return unless $buffer;
    3464 1         1 my(%header,$body);
    3465 1         1 my $filenumber = 0;
    3466 1         1 my $returnvalue;
    3467 1         3 while (!$buffer->eof) {
    3468 2         7 %header = $buffer->readHeader;
    3469              
    3470 2 50       6 unless (%header) {
    3471 0         0 $self->cgi_error("400 Bad request (malformed multipart POST)");
    3472 0         0 return;
    3473             }
    3474              
    3475 2         8 my($param) = $header{'Content-ID'}=~/\<([^\>]*)\>/;
    3476 2         3 $param .= $TAINTED;
    3477              
    3478             # If this is the start part, then just read the data and assign it
    3479             # to our return variable.
    3480 2 50       6 if ( $param eq $start ) {
    3481 0         0 $returnvalue = $buffer->readBody;
    3482 0         0 $returnvalue .= $TAINTED;
    3483 0         0 next;
    3484             }
    3485              
    3486             # add this parameter to our list
    3487 2         6 $self->add_parameter($param);
    3488              
    3489             UPLOADS: {
    3490             # If we get here, then we are dealing with a potentially large
    3491             # uploaded form. Save the data to a temporary file, then open
    3492             # the file for reading.
    3493              
    3494             # skip the file if uploads disabled
    3495 2 50       2 if ($DISABLE_UPLOADS) {
      2         4  
    3496 0         0 while (defined($data = $buffer->read)) { }
    3497 0         0 last UPLOADS;
    3498             }
    3499              
    3500             my $tmp_dir = $CGI::OS eq 'WINDOWS'
    3501 2 50 0     5 ? ( $ENV{TEMP} || $ENV{TMP} || ( $ENV{WINDIR} ? ( $ENV{WINDIR} . $SL . 'TEMP' ) : undef ) )
    3502             : undef; # File::Temp defaults to TMPDIR
    3503              
    3504 2         393 require CGI::File::Temp;
    3505 2         9 my $filehandle = CGI::File::Temp->new(
    3506             UNLINK => $UNLINK_TMP_FILES,
    3507             DIR => $tmp_dir,
    3508             );
    3509 2         802 $filehandle->_mp_filename( $filehandle->filename );
    3510              
    3511 2 50 33     7 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode
    3512             && defined fileno($filehandle);
    3513              
    3514 2         2 my ($data);
    3515 2         5 local($\) = '';
    3516 2         3 my $totalbytes;
    3517 2         5 while (defined($data = $buffer->read)) {
    3518 2 50       4 if (defined $self->{'.upload_hook'})
    3519             {
    3520 0         0 $totalbytes += length($data);
    3521 0         0 &{$self->{'.upload_hook'}}($param ,$data, $totalbytes, $self->{'.upload_data'});
      0         0  
    3522             }
    3523 2 50       18 print $filehandle $data if ($self->{'use_tempfile'});
    3524             }
    3525              
    3526             # back up to beginning of file
    3527 2         69 seek($filehandle,0,0);
    3528              
    3529             ## Close the filehandle if requested this allows a multipart MIME
    3530             ## upload to contain many files, and we won't die due to too many
    3531             ## open file handles. The user can access the files using the hash
    3532             ## below.
    3533 2 50       6 close $filehandle if $CLOSE_UPLOAD_FILES;
    3534 2 50       3 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;
    3535              
    3536             # Save some information about the uploaded file where we can get
    3537             # at it later.
    3538             # Use the typeglob + filename as the key, as this is guaranteed to be
    3539             # unique for each filehandle. Don't use the file descriptor as
    3540             # this will be re-used for each filehandle if the
    3541             # close_upload_files feature is used.
    3542 2         6 $self->{'.tmpfiles'}->{$$filehandle . $filehandle} = {
    3543             hndl => $filehandle,
    3544             name => $filehandle->filename,
    3545             info => {%header},
    3546             };
    3547 2         3 push(@{$self->{param}{$param}},$filehandle);
      2         12  
    3548             }
    3549             }
    3550 1         9 return $returnvalue;
    3551             }
    3552              
    3553             sub upload {
    3554 16     16 1 2580 my($self,$param_name) = self_or_default(@_);
    3555 16 50       22 my @param = grep {ref($_) && defined(fileno($_))} $self->param($param_name);
      18         74  
    3556 16 50       27 return unless @param;
    3557 16 100       43 return wantarray ? @param : $param[0];
    3558             }
    3559              
    3560             sub tmpFileName {
    3561 11     11 0 201 my($self,$filename) = self_or_default(@_);
    3562              
    3563             # preferred calling convention: $filename came directly from param or upload
    3564 11 100       20 if (ref $filename) {
    3565 7   50     38 return $self->{'.tmpfiles'}->{$$filename . $filename}->{name} || '';
    3566             }
    3567              
    3568             # backwards compatible with older versions: $filename is merely equal to
    3569             # one of our filenames when compared as strings
    3570 4         8 foreach my $param_name ($self->param) {
    3571 16         19 foreach my $filehandle ($self->multi_param($param_name)) {
    3572 20 100       27 if ($filehandle eq $filename) {
    3573 4   50     13 return $self->{'.tmpfiles'}->{$$filehandle . $filehandle}->{name} || '';
    3574             }
    3575             }
    3576             }
    3577              
    3578 0         0 return '';
    3579             }
    3580              
    3581             sub uploadInfo {
    3582 19     19 0 517 my($self,$filename) = self_or_default(@_);
    3583 19 100       48 return if ! defined $$filename;
    3584 16         76 return $self->{'.tmpfiles'}->{$$filename . $filename}->{info};
    3585             }
    3586              
    3587             # internal routine, don't use
    3588             sub _set_values_and_labels {
    3589 27     27   29 my $self = shift;
    3590 27         30 my ($v,$l,$n) = @_;
    3591 27 50 33     60 $$l = $v if ref($v) eq 'HASH' && !ref($$l);
    3592 27 100       48 return $self->param($n) if !defined($v);
    3593 23 50       33 return $v if !ref($v);
    3594 23 50       65 return ref($v) eq 'HASH' ? keys %$v : @$v;
    3595             }
    3596              
    3597             # internal routine, don't use
    3598             sub _set_attributes {
    3599 71     71   60 my $self = shift;
    3600 71         65 my($element, $attributes) = @_;
    3601 71 100       171 return '' unless defined($attributes->{$element});
    3602 2         8 $attribs = ' ';
    3603 2         4 for my $attrib (keys %{$attributes->{$element}}) {
      2         8  
    3604 2         4 (my $clean_attrib = $attrib) =~ s/^-//;
    3605 2         4 $attribs .= "@{[lc($clean_attrib)]}=\"$attributes->{$element}{$attrib}\" ";
      2         11  
    3606             }
    3607 2         7 $attribs =~ s/ $//;
    3608 2         3 return $attribs;
    3609             }
    3610              
    3611             #########################################################
    3612             # Globals and stubs for other packages that we use.
    3613             #########################################################
    3614              
    3615             ######################## CGI::MultipartBuffer ####################
    3616              
    3617             package CGI::MultipartBuffer;
    3618              
    3619             $_DEBUG = 0;
    3620              
    3621             # how many bytes to read at a time. We use
    3622             # a 4K buffer by default.
    3623             $MultipartBuffer::INITIAL_FILLUNIT ||= 1024 * 4;
    3624             $MultipartBuffer::TIMEOUT ||= 240*60; # 4 hour timeout for big files
    3625             $MultipartBuffer::SPIN_LOOP_MAX ||= 2000; # bug fix for some Netscape servers
    3626             $MultipartBuffer::CRLF ||= $CGI::CRLF;
    3627              
    3628             $INITIAL_FILLUNIT = $MultipartBuffer::INITIAL_FILLUNIT;
    3629             $TIMEOUT = $MultipartBuffer::TIMEOUT;
    3630             $SPIN_LOOP_MAX = $MultipartBuffer::SPIN_LOOP_MAX;
    3631             $CRLF = $MultipartBuffer::CRLF;
    3632              
    3633             sub new {
    3634 3     3   58 my($package,$interface,$boundary,$length) = @_;
    3635 3         7 $FILLUNIT = $INITIAL_FILLUNIT;
    3636 3         13 $CGI::DefaultClass->binmode($IN); # if $CGI::needs_binmode; # just do it always
    3637              
    3638             # If the user types garbage into the file upload field,
    3639             # then Netscape passes NOTHING to the server (not good).
    3640             # We may hang on this read in that case. So we implement
    3641             # a read timeout. If nothing is ready to read
    3642             # by then, we return.
    3643              
    3644             # Netscape seems to be a little bit unreliable
    3645             # about providing boundary strings.
    3646 3         3 my $boundary_read = 0;
    3647 3 50       8 if ($boundary) {
    3648              
    3649             # Under the MIME spec, the boundary consists of the
    3650             # characters "--" PLUS the Boundary string
    3651              
    3652             # BUG: IE 3.01 on the Macintosh uses just the boundary -- not
    3653             # the two extra hyphens. We do a special case here on the user-agent!!!!
    3654 3 50       12 $boundary = "--$boundary" unless CGI::user_agent('MSIE\s+3\.0[12];\s*Mac|DreamPassport');
    3655              
    3656             } else { # otherwise we find it ourselves
    3657 0         0 my($old);
    3658 0         0 ($old,$/) = ($/,$CRLF); # read a CRLF-delimited line
    3659 0         0 $boundary = ; # BUG: This won't work correctly under mod_perl
    3660 0         0 $length -= length($boundary);
    3661 0         0 chomp($boundary); # remove the CRLF
    3662 0         0 $/ = $old; # restore old line separator
    3663 0         0 $boundary_read++;
    3664             }
    3665              
    3666 3         19 my $self = {LENGTH=>$length,
    3667             CHUNKED=>!$length,
    3668             BOUNDARY=>$boundary,
    3669             INTERFACE=>$interface,
    3670             BUFFER=>'',
    3671             };
    3672              
    3673 3 50       8 $FILLUNIT = length($boundary)
    3674             if length($boundary) > $FILLUNIT;
    3675              
    3676 3   33     13 my $retval = bless $self,ref $package || $package;
    3677              
    3678             # Read the preamble and the topmost (boundary) line plus the CRLF.
    3679 3 50       9 unless ($boundary_read) {
    3680 3         9 while ($self->read(0)) { }
    3681             }
    3682 3 50       12 die "Malformed multipart POST: data truncated\n" if $self->eof;
    3683              
    3684 3         8 return $retval;
    3685             }
    3686              
    3687             sub readHeader {
    3688 12     12   12 my($self) = @_;
    3689 12         11 my($end);
    3690 12         11 my($ok) = 0;
    3691 12         11 my($bad) = 0;
    3692              
    3693 12 50 33     38 local($CRLF) = "\015\012" if $CGI::OS eq 'VMS' || $CGI::EBCDIC;
    3694              
    3695 12   33     12 do {
    3696 12         16 $self->fillBuffer($FILLUNIT);
    3697 12 50       39 $ok++ if ($end = index($self->{BUFFER},"${CRLF}${CRLF}")) >= 0;
    3698 12 50       22 $ok++ if $self->{BUFFER} eq '';
    3699 12 50 33     49 $bad++ if !$ok && $self->{LENGTH} <= 0;
    3700             # this was a bad idea
    3701             # $FILLUNIT *= 2 if length($self->{BUFFER}) >= $FILLUNIT;
    3702             } until $ok || $bad;
    3703 12 50       21 return () if $bad;
    3704              
    3705             #EBCDIC NOTE: translate header into EBCDIC, but watch out for continuation lines!
    3706              
    3707 12         24 my($header) = substr($self->{BUFFER},0,$end+2);
    3708 12         16 substr($self->{BUFFER},0,$end+4) = '';
    3709 12         12 my %return;
    3710              
    3711 12 50       18 if ($CGI::EBCDIC) {
    3712 0 0       0 warn "untranslated header=$header\n" if $_DEBUG;
    3713 0         0 $header = CGI::Util::ascii2ebcdic($header);
    3714 0 0       0 warn "translated header=$header\n" if $_DEBUG;
    3715             }
    3716              
    3717             # See RFC 2045 Appendix A and RFC 822 sections 3.4.8
    3718             # (Folding Long Header Fields), 3.4.3 (Comments)
    3719             # and 3.4.5 (Quoted-Strings).
    3720              
    3721 12         13 my $token = '[-\w!\#$%&\'*+.^_\`|{}~]';
    3722 12         81 $header=~s/$CRLF\s+/ /og; # merge continuation lines
    3723              
    3724 12         229 while ($header=~/($token+):\s+([^$CRLF]*)/mgox) {
    3725 35         67 my ($field_name,$field_value) = ($1,$2);
    3726 35         71 $field_name =~ s/\b(\w)/uc($1)/eg; #canonicalize
      72         127  
    3727 35         118 $return{$field_name}=$field_value;
    3728             }
    3729 12         56 return %return;
    3730             }
    3731              
    3732             # This reads and returns the body as a single scalar value.
    3733             sub readBody {
    3734 0     0   0 my($self) = @_;
    3735 0         0 my($data);
    3736 0         0 my($returnval)='';
    3737              
    3738             #EBCDIC NOTE: want to translate returnval into EBCDIC HERE
    3739              
    3740 0         0 while (defined($data = $self->read)) {
    3741 0         0 $returnval .= $data;
    3742             }
    3743              
    3744 0 0       0 if ($CGI::EBCDIC) {
    3745 0 0       0 warn "untranslated body=$returnval\n" if $_DEBUG;
    3746 0         0 $returnval = CGI::Util::ascii2ebcdic($returnval);
    3747 0 0       0 warn "translated body=$returnval\n" if $_DEBUG;
    3748             }
    3749 0         0 return $returnval;
    3750             }
    3751              
    3752             # This will read $bytes or until the boundary is hit, whichever happens
    3753             # first. After the boundary is hit, we return undef. The next read will
    3754             # skip over the boundary and begin reading again;
    3755             sub read {
    3756 27     27   28 my($self,$bytes) = @_;
    3757              
    3758             # default number of bytes to read
    3759 27   33     60 $bytes = $bytes || $FILLUNIT;
    3760              
    3761             # Fill up our internal buffer in such a way that the boundary
    3762             # is never split between reads.
    3763 27         39 $self->fillBuffer($bytes);
    3764              
    3765 27 50       42 my $boundary_start = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}) : $self->{BOUNDARY};
    3766 27 50       44 my $boundary_end = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}.'--') : $self->{BOUNDARY}.'--';
    3767              
    3768             # Find the boundary in the buffer (it may not be there).
    3769 27         45 my $start = index($self->{BUFFER},$boundary_start);
    3770              
    3771 27 50       36 warn "boundary=$self->{BOUNDARY} length=$self->{LENGTH} start=$start\n" if $_DEBUG;
    3772              
    3773             # protect against malformed multipart POST operations
    3774 27 50 33     69 die "Malformed multipart POST\n" unless $self->{CHUNKED} || ($start >= 0 || $self->{LENGTH} > 0);
          66        
    3775              
    3776             #EBCDIC NOTE: want to translate boundary search into ASCII here.
    3777              
    3778             # If the boundary begins the data, then skip past it
    3779             # and return undef.
    3780 27 100       42 if ($start == 0) {
    3781              
    3782             # clear us out completely if we've hit the last boundary.
    3783 15 100       107 if (index($self->{BUFFER},$boundary_end)==0) {
    3784 3         3 $self->{BUFFER}='';
    3785 3         6 $self->{LENGTH}=0;
    3786 3         8 return undef;
    3787             }
    3788              
    3789             # just remove the boundary.
    3790 12         18 substr($self->{BUFFER},0,length($boundary_start))='';
    3791 12         21 $self->{BUFFER} =~ s/^\012\015?//;
    3792 12         30 return undef;
    3793             }
    3794              
    3795 12         11 my $bytesToReturn;
    3796 12 50       17 if ($start > 0) { # read up to the boundary
    3797 12 50       21 $bytesToReturn = $start-2 > $bytes ? $bytes : $start;
    3798             } else { # read the requested number of bytes
    3799             # leave enough bytes in the buffer to allow us to read
    3800             # the boundary. Thanks to Kevin Hendrick for finding
    3801             # this one.
    3802 0         0 $bytesToReturn = $bytes - (length($boundary_start)+1);
    3803             }
    3804              
    3805 12         27 my $returnval=substr($self->{BUFFER},0,$bytesToReturn);
    3806 12         17 substr($self->{BUFFER},0,$bytesToReturn)='';
    3807            
    3808             # If we hit the boundary, remove the CRLF from the end.
    3809 12 50       43 return ($bytesToReturn==$start)
    3810             ? substr($returnval,0,-2) : $returnval;
    3811             }
    3812              
    3813             # This fills up our internal buffer in such a way that the
    3814             # boundary is never split between reads
    3815             sub fillBuffer {
    3816 39     39   35 my($self,$bytes) = @_;
    3817 39 50 66     141 return unless $self->{CHUNKED} || $self->{LENGTH};
    3818              
    3819 39         41 my($boundaryLength) = length($self->{BOUNDARY});
    3820 39         35 my($bufferLength) = length($self->{BUFFER});
    3821 39         48 my($bytesToRead) = $bytes - $bufferLength + $boundaryLength + 2;
    3822 39 100 66     124 $bytesToRead = $self->{LENGTH} if !$self->{CHUNKED} && $self->{LENGTH} < $bytesToRead;
    3823              
    3824             # Try to read some data. We may hang here if the browser is screwed up.
    3825             my $bytesRead = $self->{INTERFACE}->read_from_client(\$self->{BUFFER},
    3826 39         64 $bytesToRead,
    3827             $bufferLength);
    3828 39 50       64 warn "bytesToRead=$bytesToRead, bufferLength=$bufferLength, buffer=$self->{BUFFER}\n" if $_DEBUG;
    3829 39 50       58 $self->{BUFFER} = '' unless defined $self->{BUFFER};
    3830              
    3831             # An apparent bug in the Apache server causes the read()
    3832             # to return zero bytes repeatedly without blocking if the
    3833             # remote user aborts during a file transfer. I don't know how
    3834             # they manage this, but the workaround is to abort if we get
    3835             # more than SPIN_LOOP_MAX consecutive zero reads.
    3836 39 100       47 if ($bytesRead <= 0) {
    3837             die "CGI.pm: Server closed socket during multipart read (client aborted?).\n"
    3838 36 50       61 if ($self->{ZERO_LOOP_COUNTER}++ >= $SPIN_LOOP_MAX);
    3839             } else {
    3840 3         5 $self->{ZERO_LOOP_COUNTER}=0;
    3841             }
    3842              
    3843 39 100 100     115 $self->{LENGTH} -= $bytesRead if !$self->{CHUNKED} && $bytesRead;
    3844             }
    3845              
    3846             # Return true when we've finished reading
    3847             sub eof {
    3848 18     18   18 my($self) = @_;
    3849             return 1 if (length($self->{BUFFER}) == 0)
    3850 18 100 66     72 && ($self->{LENGTH} <= 0);
    3851 15         28 undef;
    3852             }
    3853              
    3854             1;
    3855              
    3856             package CGI;
    3857              
    3858             # We get a whole bunch of warnings about "possibly uninitialized variables"
    3859             # when running with the -w switch. Touch them all once to get rid of the
    3860             # warnings. This is ugly and I hate it.
    3861             if ($^W) {
    3862             $CGI::CGI = '';
    3863             $CGI::CGI=<
    3864             $CGI::VERSION;
    3865             $CGI::MultipartBuffer::SPIN_LOOP_MAX;
    3866             $CGI::MultipartBuffer::CRLF;
    3867             $CGI::MultipartBuffer::TIMEOUT;
    3868             $CGI::MultipartBuffer::INITIAL_FILLUNIT;
    3869             EOF
    3870             ;
    3871             }
    3872              
    3873             1;