File Coverage

blib/lib/CGI.pm
Criterion Covered Total %
statement 1289 1576 81.7
branch 629 1030 61.0
condition 330 532 62.0
subroutine 142 172 82.5
pod 36 134 26.8
total 2426 3444 70.4


line stmt bran cond sub pod time code
1             package CGI;
2             require 5.008001;
3 56     56   703031 use if $] >= 5.019, 'deprecate';
  56         423  
  56         259  
4 56     56   47392 use Carp 'croak';
  56         75  
  56         4172  
5              
6             my $appease_cpants_kwalitee = q/
7             use strict;
8             use warnings;
9             #/;
10              
11             $CGI::VERSION='4.36';
12              
13 56     56   18090 use CGI::Util qw(rearrange rearrange_header make_attributes unescape escape expires ebcdic2ascii ascii2ebcdic);
  56         104  
  56         1046480  
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 1925 $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         168 $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         110 $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         84 $NPH = 0;
57              
58             # Set this to 1 to enable debugging from @ARGV
59             # Set to 2 to enable debugging from STDIN
60 84         98 $DEBUG = 1;
61              
62             # Set this to 1 to generate automatic tab indexes
63 84         76 $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         77 $CLOSE_UPLOAD_FILES = 0;
74              
75             # Automatically determined -- don't change
76 84         80 $EBCDIC = 0;
77              
78             # Change this to 1 to suppress redundant HTTP headers
79 84         82 $HEADERS_ONCE = 0;
80              
81             # separate the name=value pairs by semicolons rather than ampersands
82 84         86 $USE_PARAM_SEMICOLONS = 1;
83              
84             # Do not include undefined params parsed from query string
85             # use CGI qw(-no_undef_params);
86 84         83 $NO_UNDEF_PARAMS = 0;
87              
88             # return everything as utf-8
89 84         94 $PARAM_UTF8 = 0;
90              
91             # make param('PUTDATA') act like file upload
92 84         85 $PUTDATA_UPLOAD = 0;
93              
94             # Other globals that you shouldn't worry about.
95 84         137 undef $Q;
96 84         71 $BEEN_THERE = 0;
97 84         113 $DTD_PUBLIC_IDENTIFIER = "";
98 84         136 undef @QUERY_PARAM;
99 84         108 undef %QUERY_PARAM;
100 84         153 undef %EXPORT;
101 84         85 undef $QUERY_CHARSET;
102 84         89 undef %QUERY_FIELDNAMES;
103 84         106 undef %QUERY_TMPFILES;
104              
105             # prevent complaints by mod_perl
106 84         932 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   1293 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         11 my @modes = grep { ! $default_layers{$_} }
  7         11  
216             PerlIO::get_layers( $fh );
217              
218 3 100       8 if ( ! @modes ) {
219 2         9 $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   4839 my $self = shift;
267              
268             # This causes modules to clash.
269 56         109 undef %EXPORT_OK;
270 56         69 undef %EXPORT;
271              
272 56         187 $self->_setup_symbols(@_);
273 56         191 my ($callpack, $callfile, $callline) = caller;
274              
275 56 50       170 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         77 my @packages = ($self,@{"$self\:\:ISA"});
  56         364  
287 56         26143 for $sym (keys %EXPORT) {
288 2038         1143 my $pck;
289 2038         1263 my $def = $DefaultClass;
290 2038         1315 for $pck (@packages) {
291 2038 50       1097 if (defined(&{"$pck\:\:$sym"})) {
  2038         3360  
292 2038         1274 $def = $pck;
293 2038         1234 last;
294             }
295             }
296 2038         1117 *{"${callpack}::$sym"} = \&{"$def\:\:$sym"};
  2038         24641  
  2038         1986  
297             }
298             }
299              
300             sub expand_tags {
301 2256     2256 0 1485 my($tag) = @_;
302 2256 100       3253 return ("start_$1","end_$1") if $tag=~/^(?:\*|start_|end_)(.+)/;
303 2128         1186 my(@r);
304 2128 100       3410 return ($tag) unless $EXPORT_TAGS{$tag};
305 93         59 for (@{$EXPORT_TAGS{$tag}}) {
  93         136  
306 2173         1877 push(@r,&expand_tags($_));
307             }
308 93         793 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 20098 my($class,@initializer) = @_;
317 138         232 my $self = {};
318              
319 138   33     792 bless $self,ref $class || $class || $DefaultClass;
320              
321             # always use a tempfile
322 138         490 $self->{'use_tempfile'} = 1;
323              
324 138 50 33     387 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     385 if (ref($initializer[0])
332             && (UNIVERSAL::isa($initializer[0],'CODE'))) {
333 3         8 $self->upload_hook(shift @initializer, shift @initializer);
334 3 50       6 $self->{'use_tempfile'} = shift @initializer if (@initializer > 0);
335             }
336 138 50       314 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       286 $self->_reset_globals if $PERLEX;
355 138         428 $self->init(@initializer);
356 138         385 return $self;
357             }
358              
359             sub r {
360 2     2 0 2 my $self = shift;
361 2         3 my $r = $self->{'.r'};
362 2 100       6 $self->{'.r'} = shift if @_;
363 2         5 $r;
364             }
365              
366             sub upload_hook {
367 3     3 0 3 my $self;
368 3 50       7 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       13 $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 8375 my @list_of_params = param( @_ );
398 17         24 return @list_of_params;
399             }
400              
401             sub param {
402 1095     1095 0 9446 my($self,@p) = self_or_default(@_);
403              
404 1095 100       2107 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     1528 if ( wantarray && $LIST_CONTEXT_WARN == 1 ) {
409 183         438 my ( $package, $filename, $line ) = caller;
410 183 100       457 if ( $package ne 'CGI' ) {
411 1         4 $LIST_CONTEXT_WARN++; # only warn once
412 1         27 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         533 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       829 if (@p > 1) {
422 59         184 ($name,$value,@other) = rearrange([NAME,[DEFAULT,VALUE,VALUES]],@p);
423 59         78 my(@values);
424              
425 59 100       101 if (substr($p[0],0,1) eq '-') {
426 47 100 66     159 @values = defined($value) ? (ref($value) && ref($value) eq 'ARRAY' ? @{$value} : $value) : ();
  37 100       53  
427             } else {
428 12         20 for ($value,@other) {
429 12 100       30 push(@values,$_) if defined($_);
430             }
431             }
432             # If values is provided, then we set it.
433 59 100 66     213 if (@values or defined $value) {
434 47         83 $self->add_parameter($name);
435 47         96 $self->{param}{$name}=[@values];
436             }
437             } else {
438 597         500 $name = $p[0];
439             }
440              
441 656 100 66     2275 return unless defined($name) && $self->{param}{$name};
442              
443 326         232 my @result = @{$self->{param}{$name}};
  326         467  
444              
445 326 50 66     641 if ($PARAM_UTF8 && $name ne 'PUTDATA' && $name ne 'POSTDATA' && $name ne 'PATCHDATA') {
      66        
      33        
446 5 50       25 eval "require Encode; 1;" unless Encode->can('decode'); # bring in these functions
447 5 50       5 @result = map {ref $_ ? $_ : $self->_decode_utf8($_) } @result;
  5         10  
448             }
449              
450 326 100       1080 return wantarray ? @result : $result[0];
451             }
452              
453             sub _decode_utf8 {
454 5     5   4 my ($self, $val) = @_;
455              
456 5 100       10 if (Encode::is_utf8($val)) {
457 2         6 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 13420 return @_ if defined($_[0]) && (!ref($_[0])) &&($_[0] eq 'CGI');
      100        
466 3859 100 100     10155 unless (defined($_[0]) &&
      66        
467             (ref($_[0]) eq 'CGI' || UNIVERSAL::isa($_[0],'CGI')) # slightly optimized for common case
468             ) {
469 374 100       674 $Q = $CGI::DefaultClass->new unless defined($Q);
470 374         539 unshift(@_,$Q);
471             }
472 3859 50       7182 return wantarray ? @_ : $Q;
473             }
474              
475             sub self_or_CGI {
476 187     187 0 253 local $^W=0; # prevent a warning
477 187 100 100     790 if (defined($_[0]) &&
      33        
478             (substr(ref($_[0]),0,3) eq 'CGI'
479             || UNIVERSAL::isa($_[0],'CGI'))) {
480 131         217 return @_;
481             } else {
482 56         140 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 171 my $self = shift;
501 138         311 my($query_string,$meth,$content_length,$fh,@lines) = ('','','','');
502              
503 138         124 my $is_xforms;
504              
505 138         165 my $initializer = shift; # for backward compatibility
506 138         427 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     471 if (@QUERY_PARAM && !defined($initializer)) {
515 5         10 for my $name (@QUERY_PARAM) {
516 18         21 my $val = $QUERY_PARAM{$name}; # always an arrayref;
517 18         33 $self->param('-name'=>$name,'-value'=> $val);
518 18 50 33     66 if (defined $val and ref $val eq 'ARRAY') {
519 18 100 66     19 for my $fh (grep {defined($_) && ref($_) && defined(fileno($_))} @$val) {
  23         135  
520 20         48 seek($fh,0,0); # reset the filehandle.
521             }
522              
523             }
524             }
525 5         120 $self->charset($QUERY_CHARSET);
526 5         12 $self->{'.fieldnames'} = {%QUERY_FIELDNAMES};
527 5         29 $self->{'.tmpfiles'} = {%QUERY_TMPFILES};
528 5         18 return;
529             }
530              
531 133 100       368 $meth=$ENV{'REQUEST_METHOD'} if defined($ENV{'REQUEST_METHOD'});
532 133 100       352 $content_length = defined($ENV{'CONTENT_LENGTH'}) ? $ENV{'CONTENT_LENGTH'} : 0;
533              
534 133 100       256 $fh = to_filehandle($initializer) if $initializer;
535              
536             # set charset to the safe ISO-8859-1
537 133         395 $self->charset('ISO-8859-1');
538              
539             METHOD: {
540              
541             # avoid unreasonably large postings
542 133 50 33     117 if (($POST_MAX > 0) && ($content_length > $POST_MAX)) {
  133         342  
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     440 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         16 my($boundary) = $ENV{'CONTENT_TYPE'} =~ /boundary=\"?([^\";,]+)\"?/;
556 2         10 $self->read_multipart($boundary,$content_length);
557 2         7 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     341 if ($meth eq 'POST' && defined($ENV{'CONTENT_TYPE'})) {
576 12 100       75 if ($ENV{'CONTENT_TYPE'} eq 'application/xml') {
    100          
577 1         2 my($param) = 'XForms:Model';
578 1         1 my($value) = '';
579 1         5 $self->add_parameter($param);
580 1 50       7 $self->read_from_client(\$value,$content_length,0)
581             if $content_length > 0;
582 1         1 push (@{$self->{param}{$param}},$value);
  1         4  
583 1         2 $is_xforms = 1;
584             } elsif ($ENV{'CONTENT_TYPE'} =~ /multipart\/related.+boundary=\"?([^\";,]+)\"?.+start=\"?\]+)\>?\"?/) {
585 8         19 my($boundary,$start) = ($1,$2);
586 8         7 my($param) = 'XForms:Model';
587 8         19 $self->add_parameter($param);
588 8         19 my($value) = $self->read_multipart_related($start,$boundary,$content_length,0);
589 8         13 push (@{$self->{param}{$param}},$value);
  8         17  
590 8         14 $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     516 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     48 if (ref($initializer) && ref($initializer) eq 'HASH') {
604 1         2 for (keys %$initializer) {
605 2         6 $self->param('-name'=>$_,'-value'=>$initializer->{$_});
606             }
607 1         2 last METHOD;
608             }
609              
610 11 100 66     47 if (defined($fh) && ($fh ne '')) {
611 4         49 while (my $line = <$fh>) {
612 9         11 chomp $line;
613 9 100       21 last if $line =~ /^=$/;
614 8         22 push(@lines,$line);
615             }
616             # massage back into standard format
617 4 50       24 if ("@lines" =~ /=/) {
618 4         9 $query_string=join("&",@lines);
619             } else {
620 0         0 $query_string=join("+",@lines);
621             }
622 4         7 last METHOD;
623             }
624              
625             # last chance -- treat it as a string
626 7 50       17 $initializer = $$initializer if ref($initializer) eq 'SCALAR';
627 7         11 $query_string = $initializer;
628              
629 7         11 last METHOD;
630             }
631              
632             # If method is GET, HEAD or DELETE, fetch the query from
633             # the environment.
634 119 100 100     741 if ($is_xforms || $meth=~/^(GET|HEAD|DELETE)$/) {
635 28         61 $query_string = $self->_get_query_string_from_env;
636 28 100       77 $self->param($meth . 'DATA', $self->param('XForms:Model'))
637             if $is_xforms;
638 28         45 last METHOD;
639             }
640              
641 91 100 100     583 if ($meth eq 'POST' || $meth eq 'PUT' || $meth eq 'PATCH') {
      100        
642 14 100       37 if ( $content_length > 0 ) {
643 13 100 66     151 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         15 my $postOrPut = $meth . 'DATA' ; # POSTDATA/PUTDATA
648 6         14 $self->read_postdata_putdata( $postOrPut, $content_length, $ENV{'CONTENT_TYPE'} );
649 6         7 $meth = ''; # to skip xform testing
650 6         7 undef $query_string ;
651             } else {
652 7         45 $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         27 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       207 if ($DEBUG)
668             {
669 74         186 my $cmdline_ret = read_from_cmdline();
670 74         121 $query_string = $cmdline_ret->{'query_string'};
671 74 50       226 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     1131 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         8 $self->add_parameter($param) ;
685 3         4 push (@{$self->{param}{$param}},$query_string);
  3         6  
686 3         3 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     539 if (defined $query_string && length $query_string) {
693 39 100       157 if ($query_string =~ /[&=;]/) {
694 34         115 $self->parse_params($query_string);
695             } else {
696 5         13 $self->add_parameter('keywords');
697 5         13 $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       330 if ($self->param('.defaults')) {
704 0         0 $self->delete_all();
705             }
706              
707             # hash containing our defined fieldnames
708 133         224 $self->{'.fieldnames'} = {};
709 133         291 for ($self->param('.cgifields')) {
710 0         0 $self->{'.fieldnames'}->{$_}++;
711             }
712            
713             # Clear out our default submission button flag if present
714 133         382 $self->delete('.submit');
715 133         217 $self->delete('.cgifields');
716              
717 133 100       431 $self->save_request unless defined $initializer;
718             }
719              
720             sub _get_query_string_from_env {
721 36     36   128 my $self = shift;
722 36         43 my $query_string = '';
723              
724 36 50       60 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     137 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         26 REDIRECT: foreach my $r ( 1 .. 5 ) {
742 60         71 my $key = join( '',( 'REDIRECT_' x $r ) );
743             $query_string ||= $ENV{"${key}QUERY_STRING"}
744 60 100 33     131 if defined $ENV{"${key}QUERY_STRING"};
745 60 100       81 last REDIRECT if $query_string;
746             }
747             }
748              
749 36         54 return $query_string;
750             }
751              
752             # FUNCTIONS TO OVERRIDE:
753             # Turn a string into a filehandle
754             sub to_filehandle {
755 13     13 0 20 my $thingy = shift;
756 13 50       40 return undef unless $thingy;
757 13 100       66 return $thingy if UNIVERSAL::isa($thingy,'GLOB');
758 8 50       33 return $thingy if UNIVERSAL::isa($thingy,'FileHandle');
759 8 100       21 if (!ref($thingy)) {
760 7         9 my $caller = 1;
761 7         32 while (my $package = caller($caller++)) {
762 14 50       58 my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy";
763 14 50       96 return $tmp if defined(fileno($tmp));
764             }
765             }
766 8         15 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 139 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         189 @QUERY_PARAM = $self->param; # save list of parameters
794 114         191 for (@QUERY_PARAM) {
795 61 50       88 next unless defined $_;
796 61         159 $QUERY_PARAM{$_}=$self->{param}{$_};
797             }
798 114         185 $QUERY_CHARSET = $self->charset;
799 114         130 %QUERY_FIELDNAMES = %{$self->{'.fieldnames'}};
  114         246  
800 114 100       109 %QUERY_TMPFILES = %{ $self->{'.tmpfiles'} || {} };
  114         800  
801             }
802              
803             sub parse_params {
804 34     34 0 56 my($self,$tosplit) = @_;
805 34         159 my(@pairs) = split(/[&;]/,$tosplit);
806 34         35 my($param,$value);
807 34         64 for (@pairs) {
808 82         159 ($param,$value) = split('=',$_,2);
809 82 50       135 next unless defined $param;
810 82 50 33     171 next if $NO_UNDEF_PARAMS and not defined $value;
811 82 50       142 $value = '' unless defined $value;
812 82         185 $param = unescape($param);
813 82         140 $value = unescape($value);
814 82         150 $self->add_parameter($param);
815 82         88 push (@{$self->{param}{$param}},$value);
  82         217  
816             }
817             }
818              
819             sub add_parameter {
820 164     164 0 175 my($self,$param)=@_;
821 164 50       247 return unless defined $param;
822 130         340 push (@{$self->{'.parameters'}},$param)
823 164 100       341 unless defined($self->{param}{$param});
824             }
825              
826             sub all_parameters {
827 439     439 0 358 my $self = shift;
828 439 100 33     1236 return () unless defined($self) && $self->{'.parameters'};
829 358 100       256 return () unless @{$self->{'.parameters'}};
  358         727  
830 196         150 return @{$self->{'.parameters'}};
  196         484  
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 257 sub compile { 1; }
842              
843             sub _all_html_tags {
844 57     57   829 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   22865 *$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   557 *$start_end_function = sub { return _tag_func($start_end_function,@_); };
877             }
878             }
879              
880             sub _tag_func {
881 761     761   1024 my $tagname = shift;
882 761         1031 my ($q,$a,@rest) = self_or_default(@_);
883              
884 761         865 my($attr) = '';
885              
886 761 100 66     1689 if (ref($a) && ref($a) eq 'HASH') {
887 245         571 my(@attr) = make_attributes($a,$q->{'escape'});
888 245 50       599 $attr = " @attr" if @attr;
889             } else {
890 516 100       901 unshift @rest,$a if defined $a;
891             }
892              
893 761         833 $tagname = lc( $tagname );
894              
895 761 100       1863 if ($tagname=~/start_(\w+)/i) {
    100          
896 183         893 return "<$1$attr>";
897             } elsif ($tagname=~/end_(\w+)/i) {
898 137         654 return "";
899             } else {
900 441 50       1346 return $XHTML ? "<$tagname$attr />" : "<$tagname$attr>" unless @rest;
    100          
901 253         443 my($tag,$untag) = ("<$tagname$attr>","");
902 255         573 my @result = map { "$tag$_$untag" }
903 253 100       560 (ref($rest[0]) eq 'ARRAY') ? @{$rest[0]} : "@rest";
  2         2  
904 253         1050 return "@result";
905             }
906             }
907              
908             sub _selected {
909 29     29   24 my $self = shift;
910 29         38 my $value = shift;
911 29 100       47 return '' unless $value;
912 10 50       38 return $XHTML ? qq(selected="selected" ) : qq(selected );
913             }
914              
915             sub _checked {
916 42     42   37 my $self = shift;
917 42         36 my $value = shift;
918 42 100       69 return '' unless $value;
919 22 100       36 return $XHTML ? qq(checked="checked" ) : qq(checked );
920             }
921              
922 19     19   6841 sub _reset_globals { initialize_globals(); }
923              
924             sub _setup_symbols {
925 57     57   116 my $self = shift;
926              
927             # to avoid reexporting unwanted variables
928 57         70 undef %EXPORT;
929              
930 57         129 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       152 $HEADERS_ONCE++, next if /^[:-]unique_headers$/;
939 92 50       125 $NPH++, next if /^[:-]nph$/;
940 92 50       126 $NOSTICKY++, next if /^[:-]nosticky$/;
941 92 100       218 $DEBUG=0, next if /^[:-]no_?[Dd]ebug$/;
942 88 50       114 $DEBUG=2, next if /^[:-][Dd]ebug$/;
943 88 50       390 $USE_PARAM_SEMICOLONS++, next if /^[:-]newstyle_urls$/;
944 88 100       149 $PUTDATA_UPLOAD++, next if /^[:-](?:putdata_upload|postdata_upload|patchdata_upload)$/;
945 85 50       116 $PARAM_UTF8++, next if /^[:-]utf8$/;
946 85 50       110 $XHTML++, next if /^[:-]xhtml$/;
947 85 100       108 $XHTML=0, next if /^[:-]no_?xhtml$/;
948 84 50       103 $USE_PARAM_SEMICOLONS=0, next if /^[:-]oldstyle_urls$/;
949 84 100       100 $TABINDEX++, next if /^[:-]tabindex$/;
950 83 50       96 $CLOSE_UPLOAD_FILES++, next if /^[:-]close_upload_files$/;
951 83 50       96 $NO_UNDEF_PARAMS++, next if /^[:-]no_undef_params$/;
952            
953 83         111 for (&expand_tags($_)) {
954 2291         1506 tr/a-zA-Z0-9_//cd; # don't allow weird function names
955 2291         2059 $EXPORT{$_}++;
956             }
957             }
958 57         136 @SAVED_SYMBOLS = @_;
959             }
960              
961             sub charset {
962 352     352 0 1023 my ($self,$charset) = self_or_default(@_);
963 352 100       702 $self->{'.charset'} = $charset if defined $charset;
964 352         457 $self->{'.charset'};
965             }
966              
967             sub element_id {
968 12     12 0 21 my ($self,$new_value) = self_or_default(@_);
969 12 50       36 $self->{'.elid'} = $new_value if defined $new_value;
970 12         40 sprintf('%010d',$self->{'.elid'}++);
971             }
972              
973             sub element_tab {
974 90     90 0 112 my ($self,$new_value) = self_or_default(@_);
975 90   100     175 $self->{'.etab'} ||= 1;
976 90 100       142 $self->{'.etab'} = $new_value if defined $new_value;
977 90         87 my $tab = $self->{'.etab'}++;
978 90 100 100     284 return '' unless $TABINDEX or defined $new_value;
979 39         77 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 7 my ( $self, $postOrPut, $content_length, $content_type ) = @_;
995 6         13 my %header = (
996             "Content-Type" => $content_type,
997             );
998 6         4 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       6 if ($DISABLE_UPLOADS) {
  6         9  
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         455 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         1708 $filehandle->_mp_filename( $postOrPut );
1035              
1036 6 50 33     15 $CGI::DefaultClass->binmode($filehandle)
1037             if $CGI::needs_binmode
1038             && defined fileno($filehandle);
1039              
1040 6         6 my ($data);
1041 6         14 local ($\) = '';
1042 6         4 my $totalbytes;
1043 6         6 my $unit = $CGI::MultipartBuffer::INITIAL_FILLUNIT;
1044 6         6 my $len = $content_length;
1045 6         5 $unit = $len;
1046 6         3 my $ZERO_LOOP_COUNTER =0;
1047              
1048 6         11 while( $len > 0 )
1049             {
1050            
1051 6         14 my $bytesRead = $self->read_from_client( \$data, $unit, 0 );
1052 6         7 $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       9 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         6 $ZERO_LOOP_COUNTER = 0;
1063             }
1064            
1065 6 100       10 if ( defined $self->{'.upload_hook'} ) {
1066 3         3 $totalbytes += length($data);
1067 3         9 &{ $self->{'.upload_hook'} }( $param, $data, $totalbytes,
1068 3         4 $self->{'.upload_data'} );
1069             }
1070 6 50       48 print $filehandle $data if ( $self->{'use_tempfile'} );
1071 6         11 undef $data;
1072             }
1073              
1074             # back up to beginning of file
1075 6         141 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       11 close $filehandle if $CLOSE_UPLOAD_FILES;
1082 6 50       8 $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         16 $self->{'.tmpfiles'}->{$$filehandle . $filehandle} = {
1091             hndl => $filehandle,
1092             name => $filehandle->filename,
1093             info => {%header},
1094             };
1095 6         7 push( @{ $self->{param}{$param} }, $filehandle );
  6         24  
1096             }
1097 6         12 return;
1098             }
1099              
1100 3     3 0 10 sub URL_ENCODED { 'application/x-www-form-urlencoded'; }
1101              
1102 9     9 0 31 sub MULTIPART { 'multipart/form-data'; }
1103              
1104 6     6 0 12 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         19 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 66 my($self, $buff, $len, $offset) = @_;
1115 53         128 local $^W=0; # prevent a warning
1116 53 50       355 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 365 my($self,@p) = self_or_default(@_);
1126 271         866 my(@names) = rearrange([NAME],@p);
1127 271 50       560 my @to_delete = ref($names[0]) eq 'ARRAY' ? @$names[0] : @names;
1128 271         202 my %to_delete;
1129 271         366 for my $name (@to_delete)
1130             {
1131 271         267 CORE::delete $self->{param}{$name};
1132 271         692 CORE::delete $self->{'.fieldnames'}->{$name};
1133 271         484 $to_delete{$name}++;
1134             }
1135 271         430 @{$self->{'.parameters'}}=grep { !exists($to_delete{$_}) } $self->param();
  271         409  
  210         313  
1136 271         427 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 26 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         97  
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 6 my $q = shift;
1185 4         5 my %in;
1186 4         16 tie(%in,CGI,$q);
1187 4 50       12 return %in if wantarray;
1188 4         6 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 2 local(*in);
1195 1 50       3 if (@_) {
1196 1         2 *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         5 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         4 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         4 my (@params) = split ("\0", $param);
1223 1 50       9 return (wantarray ? @params : $params[0]);
1224             }
1225              
1226             sub MethGet {
1227 1     1 0 3 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 4 return request_method() eq 'PUT';
1240             }
1241              
1242             sub TIEHASH {
1243 5     5   5 my $class = shift;
1244 5         7 my $arg = $_[0];
1245 5 100 66     33 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   252 my $self = shift;
1253 19         15 my $tag = shift;
1254 19         19 my $vals = shift;
1255 19 100 66     78 my @vals = defined($vals) && index($vals,"\0")!=-1 ? split("\0",$vals) : $vals;
1256 19         45 $self->param(-name=>$tag,-value=>\@vals);
1257             }
1258              
1259             sub FETCH {
1260 37 50   37   80 return $_[0] if $_[1] eq 'CGI';
1261 37 100       53 return undef unless defined $_[0]->param($_[1]);
1262 22         32 return join("\0",$_[0]->param($_[1]));
1263             }
1264              
1265             sub FIRSTKEY {
1266 2     2   8 $_[0]->{'.iterator'}=0;
1267 2         12 $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
1268             }
1269              
1270             sub NEXTKEY {
1271 3     3   11 $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
1272             }
1273              
1274             sub EXISTS {
1275 2     2   10 exists $_[0]->{param}{$_[1]};
1276             }
1277              
1278             sub DELETE {
1279 1     1   2 my ($self, $param) = @_;
1280 1         3 my $value = $self->FETCH($param);
1281 1         2 $self->delete($param);
1282 1         4 return $value;
1283             }
1284              
1285             sub CLEAR {
1286 2     2   2 %{$_[0]}=();
  2         17  
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         4 $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 456 my($self,$escape) = self_or_default(@_);
1328 6         10 my $d = $self->{'escape'};
1329 6         6 $self->{'escape'} = $escape;
1330 6         7 $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 697 my ($self,@p) = self_or_default(@_);
1346 17         23 my $name = shift(@p);
1347 17 50       36 return undef unless exists($ENV{QUERY_STRING});
1348 17 100       31 unless (exists($self->{'.url_param'})) {
1349 15         25 $self->{'.url_param'}={}; # empty hash
1350 15 100       60 if ($ENV{QUERY_STRING} =~ /=/) {
1351 13         60 my(@pairs) = split(/[&;]/,$ENV{QUERY_STRING});
1352 13         14 my($param,$value);
1353 13         22 for (@pairs) {
1354 40         55 ($param,$value) = split('=',$_,2);
1355 40 100       62 next if ! defined($param);
1356 30         43 $param = unescape($param);
1357 30         44 $value = unescape($value);
1358 30         27 push(@{$self->{'.url_param'}->{$param}},$value);
  30         74  
1359             }
1360             } else {
1361 2         5 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         23  
1366 12 50       23 return () unless $self->{'.url_param'}->{$name};
1367 1         6 return wantarray ? @{$self->{'.url_param'}->{$name}}
1368 12 100       56 : $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 10 my($self) = self_or_default(@_);
1378 3         3 my($param,$value,@result);
1379 3 100       8 return '
    ' unless $self->param;
    1380 2         3 push(@result,"
      ");
    1381 2         3 for $param ($self->param) {
    1382 2         6 my($name)=$self->_maybe_escapeHTML($param);
    1383 2         186 push(@result,"
  • $name
  • ");
    1384 2         3 push(@result,"
      ");
    1385 2         4 for $value ($self->param($param)) {
    1386 2         3 $value = $self->_maybe_escapeHTML($value);
    1387 2         62 $value =~ s/\n/
    \n/g;
    1388 2         4 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 6 &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 725 my($self,$filehandle) = self_or_default(@_);
    1410 1         3 $filehandle = to_filehandle($filehandle);
    1411 1         2 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         2 my($value);
    1417 3         6 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         2 for (keys %{$self->{'.fieldnames'}}) {
      1         2  
    1423 0         0 print $filehandle ".cgifields=",escape("$_"),"\n";
    1424             }
    1425 1         4 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 1420 my($self,@p) = self_or_default(@_);
    1454 6         17 my($boundary,$charset,@other) = rearrange_header([BOUNDARY,CHARSET],@p);
    1455 6 100       11 if (!$boundary) {
    1456 4         4 $boundary = '------- =_';
    1457 4         42 my @chrs = ('0'..'9', 'A'..'Z', 'a'..'z');
    1458 4         6 for (1..17) {
    1459 68         97 $boundary .= $chrs[rand(scalar @chrs)];
    1460             }
    1461             }
    1462              
    1463 6         10 $self->{'separator'} = "$CRLF--$boundary$CRLF";
    1464 6         9 $self->{'final_separator'} = "$CRLF--$boundary--$CRLF";
    1465 6         9 $type = SERVER_PUSH($boundary);
    1466             return $self->header(
    1467             -nph => 0,
    1468             -type => $type,
    1469             -charset => $charset,
    1470 6         20 (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 11 my(@header);
    1482 4         14 my($self,@p) = self_or_default(@_);
    1483 4         14 my($type,$charset,@other) = rearrange([TYPE,CHARSET],@p);
    1484 4   100     12 $type = $type || 'text/html';
    1485 4 100       5 if ($charset) {
    1486 2         5 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         6 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         3 push(@header,@other);
    1499 4         8 my $header = join($CRLF,@header)."${CRLF}${CRLF}";
    1500 4         77 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 8 my($self,@p) = self_or_default(@_);
    1511 6         16 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 2705 my($self,@p) = self_or_default(@_);
    1530 91         96 my(@header);
    1531              
    1532 91 50 66     256 return "" if $self->{'.header_printed'}++ and $HEADERS_ONCE;
    1533              
    1534 91         391 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         153 my @cookie;
    1543 91 100       178 for (ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie) {
      6         9  
    1544 96 100       234 my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_;
    1545 96 100 100     251 push(@cookie,$cs) if defined $cs and $cs ne '';
    1546             }
    1547 91 100       152 $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY';
    1548              
    1549             # CR escaping for values, per RFC 822
    1550 91         115 for my $header ($type,$status,@cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) {
    1551 738 100       871 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         508 $header =~ s/$CRLF(\s)/$1/g;
    1556              
    1557             # All other uses of newlines are invalid input.
    1558 153 100       776 if ($header =~ m/$CRLF|\015|\012/) {
    1559             # shorten very long values in the diagnostic
    1560 9 50       16 $header = substr($header,0,72).'...' if (length $header > 72);
    1561 9         91 die "Invalid header value contains a newline not followed by whitespace: $header";
    1562             }
    1563             }
    1564             }
    1565              
    1566 82   66     247 $nph ||= $NPH;
    1567              
    1568 82 100 50     202 $type ||= 'text/html' unless defined($type);
    1569              
    1570             # sets if $charset is given, gets if not
    1571 82         136 $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         113 for (@other) {
    1576             # Don't use \s because of perl bug 21951
    1577 10 50       81 next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/s;
    1578 10         43 ($_ = $header) =~ s/^(\w)(.*)/"\u$1\L$2" . ': '.$self->unescapeHTML($value)/e;
      10         62  
    1579             }
    1580              
    1581 82 100 100     598 $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     246 my $protocol = $ENV{SERVER_PROTOCOL} || 'HTTP/1.0';
    1589 82 100 100     148 push(@header,$protocol . ' ' . ($status || '200 OK')) if $nph;
    1590 82 100       120 push(@header,"Server: " . &server_software()) if $nph;
    1591              
    1592 82 100       125 push(@header,"Status: $status") if $status;
    1593 82 100       113 push(@header,"Window-Target: $target") if $target;
    1594 82 100       130 push(@header,"P3P: policyref=\"/w3c/p3p.xml\", CP=\"$p3p\"") if $p3p;
    1595             # push all the cookies -- there may be several
    1596 82         85 push(@header,map {"Set-Cookie: $_"} @cookie);
      14         25  
    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       124 push(@header,"Expires: " . expires($expires,'http'))
    1601             if $expires;
    1602 82 100 66     400 push(@header,"Date: " . expires(0,'http')) if $expires || $cookie || $nph;
          100        
    1603 82 50       146 push(@header,"Pragma: no-cache") if $self->cache();
    1604 82 100       128 push(@header,"Content-Disposition: attachment; filename=\"$attachment\"") if $attachment;
    1605 82         80 push(@header,map {ucfirst $_} @other);
      10         23  
    1606 82 100       192 push(@header,"Content-Type: $type") if $type ne '';
    1607 82         161 my $header = join($CRLF,@header)."${CRLF}${CRLF}";
    1608 82 50 33     177 if (($MOD_PERL >= 1) && !$nph) {
    1609 0         0 $self->r->send_cgi_header($header);
    1610 0         0 return '';
    1611             }
    1612 82         378 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 109 my($self,$new_value) = self_or_default(@_);
    1621 82 50       146 $new_value = '' unless $new_value;
    1622 82 50       129 if ($new_value ne '') {
    1623 0         0 $self->{'cache'} = $new_value;
    1624             }
    1625 82         157 return $self->{'cache'};
    1626             }
    1627              
    1628             #### Method: redirect
    1629             # Return a Location: style header
    1630             #
    1631             ####
    1632             sub redirect {
    1633 10     10 0 1678 my($self,@p) = self_or_default(@_);
    1634 10         58 my($url,$target,$status,$cookie,$nph,@other) =
    1635             rearrange([[LOCATION,URI,URL],TARGET,STATUS,['COOKIE','COOKIES','SET-COOKIE'],NPH],@p);
    1636 10 50       44 $status = '302 Found' unless defined $status;
    1637 10   66     29 $url ||= $self->self_url;
    1638 10         8 my(@o);
    1639 10         15 for (@other) { tr/\"//d; push(@o,split("=",$_,2)); }
      4         8  
      4         12  
    1640 10         22 unshift(@o,
    1641             '-Status' => $status,
    1642             '-Location'=> $url,
    1643             '-nph' => $nph);
    1644 10 50       17 unshift(@o,'-Target'=>$target) if $target;
    1645 10         23 unshift(@o,'-Type'=>'');
    1646 10         9 my @unescaped;
    1647 10 100       20 unshift(@unescaped,'-Cookie'=>$cookie) if $cookie;
    1648 10         14 return $self->header((map {$self->unescapeHTML($_)} @o),@unescaped);
      88         112  
    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 1084 my($self,@p) = &self_or_default(@_);
    1672 12         55 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         38 $self->element_id(0);
    1678 12         23 $self->element_tab(0);
    1679              
    1680 12 50       34 $encoding = lc($self->charset) unless defined $encoding;
    1681              
    1682             # Need to sort out the DTD before it's okay to call escapeHTML().
    1683 12         13 my(@result,$xml_dtd);
    1684 12 100       20 if ($dtd) {
    1685 5 50 33     14 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       15 $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     65 $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     40 push @result,qq() if $xml_dtd && $declare_xml;
    1697              
    1698 12 100 66     46 if (ref($dtd) && ref($dtd) eq 'ARRAY') {
    1699 7         23 push(@result,qq([0]"\n\t "$dtd->[1]">));
    1700 7         9 $DTD_PUBLIC_IDENTIFIER = $dtd->[0];
    1701             } else {
    1702 5         7 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     59 $title = $self->_maybe_escapeHTML($title || 'Untitled Document');
    1710 12         733 $author = $self->escape($author);
    1711              
    1712 12 100       62 if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML (2\.0|3\.2|4\.01?)/i) {
    1713 4 50       7 $lang = "" unless defined $lang;
    1714 4         3 $XHTML = 0;
    1715             }
    1716             else {
    1717 8 100       17 $lang = 'en-US' unless defined $lang;
    1718             }
    1719              
    1720 12 50       31 my $lang_bits = $lang ne '' ? qq( lang="$lang" xml:lang="$lang") : '';
    1721 12 100 100     58 my $meta_bits = qq()
          66        
    1722             if $XHTML && $encoding && !$declare_xml;
    1723              
    1724 12 50       40 push(@result,$XHTML ? qq(\n\n$title)
        100          
    1725             : ($lang ? qq() : "")
    1726             . "$title");
    1727 12 50       21 if (defined $author) {
    1728 0 0       0 push(@result,$XHTML ? ""
    1729             : "");
    1730             }
    1731              
    1732 12 50 33     69 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     37 if ($meta && ref($meta) && (ref($meta) eq 'HASH')) {
          66        
    1739 2 50       14 for (sort keys %$meta) { push(@result,$XHTML ? qq()
      11         33  
    1740             : qq()); }
    1741             }
    1742              
    1743 12         11 my $meta_bits_set = 0;
    1744 12 50       17 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       20 push(@result,$self->_style($style)) if defined $style;
    1757 12 100       20 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       18 push(@result,<
    1762            
    1763             $noscript
    1764            
    1765             END
    1766             ;
    1767 12 50       22 my($other) = @other ? " @other" : '';
    1768 12         23 push(@result,"\n\n");
    1769 12         103 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       4 my $cdata_start = $XHTML ? "\n\n" : " -->\n";
    1785              
    1786 1 50       3 my @s = ref($style) eq 'ARRAY' ? @$style : $style;
    1787 1         2 my $other = '';
    1788              
    1789 1         2 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       9 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       4 my (@scripts) = ref($script) eq 'ARRAY' ? @$script : ($script);
    1836 1         3 for $script (@scripts) {
    1837 1         1 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     5 $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         2 my $comment = '//'; # javascript by default
    1853 1 50       5 $comment = '#' if $type=~/perl|tcl/i;
    1854 1 50       3 $comment = "'" if $type=~/vbscript/i;
    1855              
    1856 1         1 my ($cdata_start,$cdata_end);
    1857 1 50       2 if ($XHTML) {
    1858 1         3 $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       3 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       3 $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 12 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 53 my($self,@p) = self_or_default(@_);
    1909              
    1910 12         40 my($method,$action,$enctype,@other) =
    1911             rearrange([METHOD,ACTION,ENCTYPE],@p);
    1912              
    1913 12   100     56 $method = $self->_maybe_escapeHTML(lc($method || 'post'));
    1914              
    1915 12 100       454 if( $XHTML ){
    1916 7   66     25 $enctype = $self->_maybe_escapeHTML($enctype || &MULTIPART);
    1917             }else{
    1918 5   66     13 $enctype = $self->_maybe_escapeHTML($enctype || &URL_ENCODED);
    1919             }
    1920              
    1921 12 50       286 if (defined $action) {
    1922 12         15 $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         264 $action = qq(action="$action");
    1928 12 100       27 my($other) = @other ? " @other" : '';
    1929 12         23 $self->{'.parametersToAdd'}={};
    1930 12         58 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     18 if (defined($p[0]) && substr($p[0],0,1) eq '-') {
    1937 0         0 return $self->start_form(-enctype=>&MULTIPART,@p);
    1938             } else {
    1939 4         12 my($method,$action,@other) =
    1940             rearrange([METHOD,ACTION],@p);
    1941 4         7 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 9 my($self,@p) = self_or_default(@_);
    1950 1 50       4 if ( $NOSTICKY ) {
    1951 0 0       0 return wantarray ? ("") : "\n";
    1952             } else {
    1953 1 50       6 if (my @fields = $self->get_fields) {
    1954 0 0       0 return wantarray ? ("
    ",@fields,"
    ","")
    1955             : "
    ".(join '',@fields)."
    \n";
    1956             } else {
    1957 1         7 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         40 my($name,$default,$size,$maxlength,$override,$tabindex,@other) =
    1971             rearrange([NAME,[DEFAULT,VALUE,VALUES],SIZE,MAXLENGTH,[OVERRIDE,FORCE],TABINDEX],@p);
    1972              
    1973 8 100       29 my $current = $override ? $default :
        100          
    1974             (defined($self->param($name)) ? $self->param($name) : $default);
    1975              
    1976 8 50       21 $current = defined($current) ? $self->_maybe_escapeHTML($current,1) : '';
    1977 8 100       202 $name = defined($name) ? $self->_maybe_escapeHTML($name) : '';
    1978 8 50       164 my($s) = defined($size) ? qq/ size="$size"/ : '';
    1979 8 50       14 my($m) = defined($maxlength) ? qq/ maxlength="$maxlength"/ : '';
    1980 8 100       17 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         15 $tabindex = $self->element_tab($tabindex);
    1985 8 50       58 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 21 my($self,@p) = self_or_default(@_);
    2001 7         21 $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 3 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 7 my($self,@p) = self_or_default(@_);
    2045 2         13 my($name,$default,$rows,$cols,$override,$tabindex,@other) =
    2046             rearrange([NAME,[DEFAULT,VALUE],ROWS,[COLS,COLUMNS],[OVERRIDE,FORCE],TABINDEX],@p);
    2047              
    2048 2 50       12 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       29 my($r) = $rows ? qq/ rows="$rows"/ : '';
    2054 2 50       7 my($c) = $cols ? qq/ cols="$cols"/ : '';
    2055 2 100       9 my($other) = @other ? " @other" : '';
    2056 2         4 $tabindex = $self->element_tab($tabindex);
    2057 2         14 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 741 my($self,@p) = self_or_default(@_);
    2072              
    2073 4         19 my($label,$value,$script,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL],
    2074             [ONCLICK,SCRIPT],TABINDEX],@p);
    2075              
    2076 4         10 $label=$self->_maybe_escapeHTML($label);
    2077 4         178 $value=$self->_maybe_escapeHTML($value,1);
    2078 4         6 $script=$self->_maybe_escapeHTML($script);
    2079              
    2080 4   100     11 $script ||= '';
    2081              
    2082 4         4 my($name) = '';
    2083 4 100       9 $name = qq/ name="$label"/ if $label;
    2084 4   66     11 $value = $value || $label;
    2085 4         3 my($val) = '';
    2086 4 100       8 $val = qq/ value="$value"/ if $value;
    2087 4 100       7 $script = qq/ onclick="$script"/ if $script;
    2088 4 100       7 my($other) = @other ? " @other" : '';
    2089 4         7 $tabindex = $self->element_tab($tabindex);
    2090 4 50       19 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 382 my($self,@p) = self_or_default(@_);
    2105              
    2106 7         33 my($label,$value,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL],TABINDEX],@p);
    2107              
    2108 7         20 $label=$self->_maybe_escapeHTML($label);
    2109 7         241 $value=$self->_maybe_escapeHTML($value,1);
    2110              
    2111 7 50       294 my $name = $NOSTICKY ? '' : 'name=".submit" ';
    2112 7 100       20 $name = qq/name="$label" / if defined($label);
    2113 7 100       12 $value = defined($value) ? $value : $label;
    2114 7         8 my $val = '';
    2115 7 100       19 $val = qq/value="$value" / if defined($value);
    2116 7         21 $tabindex = $self->element_tab($tabindex);
    2117 7 100       17 my($other) = @other ? "@other " : '';
    2118 7 50       39 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 18 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       24 $value = defined $value ? $value : 'on';
    2198              
    2199 9 100 66     39 if (!$override && ($self->{'.fieldnames'}->{$name} ||
          66        
    2200             defined $self->param($name))) {
    2201 6 100       9 $checked = grep($_ eq $value,$self->param($name)) ? $self->_checked(1) : '';
    2202             } else {
    2203 3         12 $checked = $self->_checked($checked);
    2204             }
    2205 9 100       20 my($the_label) = defined $label ? $label : $name;
    2206 9         16 $name = $self->_maybe_escapeHTML($name);
    2207 9         229 $value = $self->_maybe_escapeHTML($value,1);
    2208 9         185 $the_label = $self->_maybe_escapeHTML($the_label);
    2209 9 100       188 my($other) = @other ? "@other " : '';
    2210 9         14 $tabindex = $self->element_tab($tabindex);
    2211 9         15 $self->register_parameter($name);
    2212 9 50       31 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 6146 require HTML::Entities;
    2220             # hack to work around earlier hacks
    2221 251 100 100     44435 push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
    2222 251         294 my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_);
    2223 251 50       357 return undef unless defined($toencode);
    2224 251         211 my $encode_entities = $ENCODE_ENTITIES;
    2225 251 100 100     670 $encode_entities .= "\012\015" if ( $encode_entities && $newlinestoo );
    2226 251         403 return HTML::Entities::encode_entities($toencode,$encode_entities);
    2227             }
    2228              
    2229             # unescape HTML -- used internally
    2230             sub unescapeHTML {
    2231 105     105 0 2302 require HTML::Entities;
    2232             # hack to work around earlier hacks
    2233 105 50 66     13210 push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
    2234 105         118 my ($self,$string) = CGI::self_or_default(@_);
    2235 105 100       165 return undef unless defined($string);
    2236 95         313 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       2 my @rowheaders = $rowheaders ? @$rowheaders : ();
    2243 1 50       2 my @colheaders = $colheaders ? @$colheaders : ();
    2244 1         1 my($result);
    2245              
    2246 1 50       3 if (defined($columns)) {
    2247 1 50       3 $rows = int(0.99 + @elements/$columns) unless defined($rows);
    2248             }
    2249 1 50       2 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         1 $result = ""; " if @colheaders; "; "; " if @rowheaders; " ";
    2255 1         1 my($row,$column);
    2256 1 50 33     2 unshift(@colheaders,'') if @colheaders && @rowheaders;
    2257 1 50       3 $result .= "
    2258 1         1 for (@colheaders) {
    2259 0         0 $result .= "$_
    2260             }
    2261 1         3 for ($row=0;$row<$rows;$row++) {
    2262 2         2 $result .= "
    2263 2 50       3 $result .= "$rowheaders[$row]
    2264 2         9 for ($column=0;$column<$columns;$column++) {
    2265 4 50       14 $result .= "" . $elements[$column*$rows + $row] . "
    2266             if defined($elements[$column*$rows + $row]);
    2267             }
    2268 2         5 $result .= "
    2269             }
    2270 1         1 $result .= "
    ";
    2271 1         8 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 12 my($self,@p) = self_or_default(@_);
    2293 5         18 $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 27 my($self,@p) = self_or_default(@_);
    2320 8         25 $self->_box_group('checkbox',@p);
    2321             }
    2322              
    2323             sub _box_group {
    2324 13     13   11 my $self = shift;
    2325 13         13 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         34 my($result,$checked,@elements,@values);
    2337              
    2338 13         33 @values = $self->_set_values_and_labels($values,\$labels,$name);
    2339 13         32 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     41 $checked{$values[0]}++ if $box_type eq 'radio' && !%checked;
    2343              
    2344 13         29 $name=$self->_maybe_escapeHTML($name);
    2345              
    2346 13         428 my %tabs = ();
    2347 13 50 66     56 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       32 %tabs = map {$_=>$self->element_tab} @values unless %tabs;
      37         48  
    2357 13 100       30 my $other = @other ? "@other " : '';
    2358 13         13 my $radio_checked;
    2359              
    2360             # for disabling groups of radio/checkbox buttons
    2361             my %disabled;
    2362 13         11 for (@{$disabled}) {
      13         23  
    2363 1         2 $disabled{$_}=1;
    2364             }
    2365              
    2366 13         15 for (@values) {
    2367 37         28 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     114 : $checked{$_});
    2374 37         38 my($break);
    2375 37 100       42 if ($linebreak) {
    2376 4 50       5 $break = $XHTML ? "
    " : "
    ";
    2377             }
    2378             else {
    2379 33         31 $break = '';
    2380             }
    2381 37         30 my($label)='';
    2382 37 50 33     63 unless (defined($nolabels) && $nolabels) {
    2383 37         41 $label = $_;
    2384 37 100 100     70 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2385 37         48 $label = $self->_maybe_escapeHTML($label,1);
    2386 37 100       847 $label = "$label" if $disabled{$_};
    2387             }
    2388 37         52 my $attribs = $self->_set_attributes($_, $attributes);
    2389 37         37 my $tab = $tabs{$_};
    2390 37         83 $_=$self->_maybe_escapeHTML($_);
    2391              
    2392 37 100       664 if ($XHTML) {
    2393 34         99 push @elements,
    2394             CGI::label($labelattributes,
    2395             qq($label)).${break};
    2396             } else {
    2397 3         13 push(@elements,qq/${label}${break}/);
    2398             }
    2399             }
    2400 13         28 $self->register_parameter($name);
    2401 13 50 66     132 return wantarray ? @elements : "@elements"
        100          
    2402             unless defined($columns) || defined($rows);
    2403 1         3 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 295 my($self,@p) = self_or_default(@_);
    2422              
    2423 8         54 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         16 my($result,%selected);
    2427              
    2428 8 50 66     32 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         23  
    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         328 @other = grep { $_ !~ /^multiple=/i } @other;
      3         11  
    2439 8 100       21 my($other) = @other ? " @other" : '';
    2440              
    2441 8         9 my(@values);
    2442 8         19 @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         19 $result = qq/
    2446 8         13 for (@values) {
    2447 22 100       34 if (/
    2448 3         10 for my $v (split(/\n/)) {
    2449 11 50       16 my $selectit = $XHTML ? 'selected="selected"' : 'selected';
    2450 11         14 for my $selected (keys %selected) {
    2451 11         66 $v =~ s/(value="\Q$selected\E")/$selectit $1/;
    2452             }
    2453 11         19 $result .= "$v\n";
    2454             }
    2455             }
    2456             else {
    2457 19         30 my $attribs = $self->_set_attributes($_, $attributes);
    2458 19         44 my($selectit) = $self->_selected($selected{$_});
    2459 19         29 my($label) = $_;
    2460 19 100 66     46 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2461 19         24 my($value) = $self->_maybe_escapeHTML($_);
    2462 19         374 $label = $self->_maybe_escapeHTML($label,1);
    2463 19         449 $result .= "$label\n";
    2464             }
    2465             }
    2466              
    2467 8         12 $result .= "";
    2468 8         42 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 9 my($self,@p) = self_or_default(@_);
    2495 3         18 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         12 @values = $self->_set_values_and_labels($values,\$labels,$name,$labeled,$novals);
    2500 3 100       13 my($other) = @other ? " @other" : '';
    2501              
    2502 3   100     8 $name = $self->_maybe_escapeHTML($name) || q{};
    2503 3         37 $result = qq/\n/;
    2504 3         6 for (@values) {
    2505 5 50       10 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         9 my $attribs = $self->_set_attributes($_, $attributes);
    2514 5         7 my($label) = $_;
    2515 5 50 33     12 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2516 5         12 $label=$self->_maybe_escapeHTML($label);
    2517 5         85 my($value)=$self->_maybe_escapeHTML($_,1);
    2518 5 0       93 $result .= $labeled ? $novals ? "$label\n"
        50          
        50          
    2519             : "$label\n"
    2520             : $novals ? "$label\n"
    2521             : "$label\n";
    2522             }
    2523             }
    2524 3         5 $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 8 my($self,@p) = self_or_default(@_);
    2550 3         20 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         8 @values = $self->_set_values_and_labels($values,\$labels,$name);
    2556              
    2557 3   100     10 $size = $size || scalar(@values);
    2558              
    2559 3         7 my(%selected) = $self->previous_or_default($name,$defaults,$override);
    2560              
    2561 3 100       6 my($is_multiple) = $multiple ? qq/ multiple="multiple"/ : '';
    2562 3 50       10 my($has_size) = $size ? qq/ size="$size"/: '';
    2563 3 100       7 my($other) = @other ? " @other" : '';
    2564              
    2565 3         4 $name=$self->_maybe_escapeHTML($name);
    2566 3         63 $tabindex = $self->element_tab($tabindex);
    2567 3         7 $result = qq/
    2568 3         5 for (@values) {
    2569 11 100       16 if (/
    2570 1         4 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         7 $result .= "$v\n";
    2576             }
    2577             }
    2578             else {
    2579 10         14 my $attribs = $self->_set_attributes($_, $attributes);
    2580 10         20 my($selectit) = $self->_selected($selected{$_});
    2581 10         11 my($label) = $_;
    2582 10 100 66     24 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2583 10         14 my($value) = $self->_maybe_escapeHTML($_);
    2584 10         161 $label = $self->_maybe_escapeHTML($label,1);
    2585 10         152 $result .= "$label\n";
    2586             }
    2587             }
    2588              
    2589 3         5 $result .= "";
    2590 3         7 $self->register_parameter($name);
    2591 3         14 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 24 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         8 my(@result,@value);
    2609 7         28 my($name,$default,$override,@other) =
    2610             rearrange([NAME,[DEFAULT,VALUE,VALUES],[OVERRIDE,FORCE]],@p);
    2611              
    2612 7         13 my $do_override = 0;
    2613 7 100 66     33 if ( ref($p[0]) || substr($p[0],0,1) eq '-') {
    2614 5 100       12 @value = ref($default) ? @{$default} : $default;
      4         8  
    2615 5         4 $do_override = $override;
    2616             } else {
    2617 2         3 for ($default,$override,@other) {
    2618 6 100       11 push(@value,$_) if defined($_);
    2619             }
    2620 2         2 undef @other;
    2621             }
    2622              
    2623             # use previous values if override is not set
    2624 7         14 my @prev = $self->param($name);
    2625 7 50 66     23 @value = @prev if !$do_override && @prev;
    2626              
    2627 7         14 $name=$self->_maybe_escapeHTML($name);
    2628 7         452 for (@value) {
    2629 18 50       35 $_ = defined($_) ? $self->_maybe_escapeHTML($_,1) : '';
    2630 18 50       527 push @result,$XHTML ? qq()
    2631             : qq();
    2632             }
    2633 7 100       40 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         3 $name=$self->_maybe_escapeHTML($name);
    2653 1 50       6 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 18 my($self,@p) = self_or_default(@_);
    2665 7         30 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 86 my($self,@p) = self_or_default(@_);
    2680 44         201 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         77 my $url = '';
    2683 44 100 100     206 $full++ if $base || !($relative || $absolute);
          66        
    2684 44 100       70 $rewrite++ unless defined $rewrite;
    2685              
    2686 44         89 my $path = $self->path_info;
    2687 44         77 my $script_name = $self->script_name;
    2688 44   100     71 my $request_uri = $self->request_uri || '';
    2689 44 100       76 my $query_str = $query ? $self->query_string : '';
    2690              
    2691 44         79 $request_uri =~ s/\?.*$//s; # remove query string
    2692 44         84 $request_uri = unescape($request_uri);
    2693              
    2694 44 100 100     139 my $uri = $rewrite && $request_uri ? $request_uri : $script_name;
    2695 44         47 $uri =~ s/\?.*$//s; # remove query string
    2696              
    2697 44 100       75 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     299 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       65 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         53 my $protocol = $self->protocol();
    2714 27         34 $url = "$protocol://";
    2715 27   100     38 my $vh = http('x_forwarded_host') || http('host') || '';
    2716 27         40 $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         28 $vh =~ s/\:\d+$//; # some clients add the port number (incorrectly). Get rid of it.
    2719              
    2720 27   66     67 $url .= $vh || server_name();
    2721              
    2722 27         46 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     138 $url .= ':' . $port unless (lc($protocol) eq 'http' && $port == 80)
          33        
          66        
    2726             or (lc($protocol) eq 'https' && $port == 443);
    2727              
    2728 27 50       60 return $url if $base;
    2729              
    2730 27         35 $url .= $uri;
    2731             } elsif ($relative) {
    2732 12         49 ($url) = $uri =~ m!([^/]+)$!;
    2733             } elsif ($absolute) {
    2734 5         6 $url = $uri;
    2735             }
    2736              
    2737 44 100 66     118 $url .= $path if $path_info and defined $path;
    2738 44 100 100     111 $url .= "?$query_str" if $query and $query_str ne '';
    2739 44   50     66 $url ||= '';
    2740 44         85 $url =~ s/([^a-zA-Z0-9_.%;&?\/\\:+=~-])/sprintf("%%%02X",ord($1))/eg;
      0         0  
    2741 44         159 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 292 my($self,@p) = self_or_default(@_);
    2758 2         11 my($name,$value,$path,$domain,$secure,$expires,$httponly,$max_age,$samesite) =
    2759             rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES,HTTPONLY,'MAX-AGE',SAMESITE],@p);
    2760              
    2761 2         505 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       4 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     10 return undef unless defined($name) && $name ne ''; # this is an error
    2778              
    2779 2         2 my @param;
    2780 2         3 push(@param,'-name'=>$name);
    2781 2         3 push(@param,'-value'=>$value);
    2782 2 50       4 push(@param,'-domain'=>$domain) if $domain;
    2783 2 50       5 push(@param,'-path'=>$path) if $path;
    2784 2 50       4 push(@param,'-expires'=>$expires) if $expires;
    2785 2 50       3 push(@param,'-secure'=>$secure) if $secure;
    2786 2 50       2 push(@param,'-httponly'=>$httponly) if $httponly;
    2787 2 50       4 push(@param,'-max_age'=>$max_age) if $max_age;
    2788 2 50       2 push(@param,'-samesite'=>$samesite) if $samesite;
    2789              
    2790 2         6 return CGI::Cookie->new(@param);
    2791             }
    2792              
    2793             sub parse_keywordlist {
    2794 7     7 0 10 my($self,$tosplit) = @_;
    2795 7         17 $tosplit = unescape($tosplit); # unescape the keywords
    2796 7         8 $tosplit=~tr/+/ /; # pluses to spaces
    2797 7         31 my(@keywords) = split(/\s+/,$tosplit);
    2798 7         38 return @keywords;
    2799             }
    2800              
    2801             sub param_fetch {
    2802 9     9 0 26 my($self,@p) = self_or_default(@_);
    2803 9         29 my($name) = rearrange([NAME],@p);
    2804 9 100       20 return [] unless defined $name;
    2805              
    2806 8 50       16 unless (exists($self->{param}{$name})) {
    2807 0         0 $self->add_parameter($name);
    2808 0         0 $self->{param}{$name} = [];
    2809             }
    2810            
    2811 8         39 return $self->{param}{$name};
    2812             }
    2813              
    2814             ###############################################
    2815             # OTHER INFORMATION PROVIDED BY THE ENVIRONMENT
    2816             ###############################################
    2817              
    2818             #### Method: path_info
    2819             # Return the extra virtual path information provided
    2820             # after the URL (if any)
    2821             ####
    2822             sub path_info {
    2823 45     45 1 60 my ($self,$info) = self_or_default(@_);
    2824 45 50       105 if (defined($info)) {
        100          
    2825 0 0 0     0 $info = "/$info" if $info ne '' && substr($info,0,1) ne '/';
    2826 0         0 $self->{'.path_info'} = $info;
    2827             } elsif (! defined($self->{'.path_info'}) ) {
    2828 10         24 my (undef,$path_info) = $self->_name_and_path_from_env;
    2829 10   100     51 $self->{'.path_info'} = $path_info || '';
    2830             }
    2831 45         55 return $self->{'.path_info'};
    2832             }
    2833              
    2834             # This function returns a potentially modified version of SCRIPT_NAME
    2835             # and PATH_INFO. Some HTTP servers do sanitise the paths in those
    2836             # variables. It is the case of at least Apache 2. If for instance the
    2837             # user requests: /path/./to/script.cgi/x//y/z/../x?y, Apache will set:
    2838             # REQUEST_URI=/path/./to/script.cgi/x//y/z/../x?y
    2839             # SCRIPT_NAME=/path/to/env.cgi
    2840             # PATH_INFO=/x/y/x
    2841             #
    2842             # This is all fine except that some bogus CGI scripts expect
    2843             # PATH_INFO=/http://foo when the user requests
    2844             # http://xxx/script.cgi/http://foo
    2845             #
    2846             # Old versions of this module used to accomodate with those scripts, so
    2847             # this is why we do this here to keep those scripts backward compatible.
    2848             # Basically, we accomodate with those scripts but within limits, that is
    2849             # we only try to preserve the number of / that were provided by the user
    2850             # if $REQUEST_URI and "$SCRIPT_NAME$PATH_INFO" only differ by the number
    2851             # of consecutive /.
    2852             #
    2853             # So for instance, in: http://foo/x//y/script.cgi/a//b, we'll return a
    2854             # script_name of /x//y/script.cgi and a path_info of /a//b, but in:
    2855             # http://foo/./x//z/script.cgi/a/../b//c, we'll return the versions
    2856             # possibly sanitised by the HTTP server, so in the case of Apache 2:
    2857             # script_name == /foo/x/z/script.cgi and path_info == /b/c.
    2858             #
    2859             # Future versions of this module may no longer do that, so one should
    2860             # avoid relying on the browser, proxy, server, and CGI.pm preserving the
    2861             # number of consecutive slashes as no guarantee can be made there.
    2862             sub _name_and_path_from_env {
    2863 20     20   19 my $self = shift;
    2864 20   100     64 my $script_name = $ENV{SCRIPT_NAME} || '';
    2865 20   100     47 my $path_info = $ENV{PATH_INFO} || '';
    2866 20   100     38 my $uri = $self->request_uri || '';
    2867              
    2868 20         40 $uri =~ s/\?.*//s;
    2869 20         54 $uri = unescape($uri);
    2870              
    2871 20 100       119 if ( $IIS ) {
        100          
    2872             # IIS doesn't set $ENV{PATH_INFO} correctly. It sets it to
    2873             # $ENV{SCRIPT_NAME}path_info
    2874             # IIS also doesn't set $ENV{REQUEST_URI} so we don't want to do
    2875             # the test below, hence this comes first
    2876 2         22 $path_info =~ s/^\Q$script_name\E(.*)/$1/;
    2877             } elsif ($uri ne "$script_name$path_info") {
    2878 8         13 my $script_name_pattern = quotemeta($script_name);
    2879 8         11 my $path_info_pattern = quotemeta($path_info);
    2880 8         45 $script_name_pattern =~ s{(?:\\/)+}{/+}g;
    2881 8         19 $path_info_pattern =~ s{(?:\\/)+}{/+}g;
    2882              
    2883 8 50       115 if ($uri =~ /^($script_name_pattern)($path_info_pattern)$/s) {
    2884             # REQUEST_URI and SCRIPT_NAME . PATH_INFO only differ by the
    2885             # numer of consecutive slashes, so we can extract the info from
    2886             # REQUEST_URI:
    2887 0         0 ($script_name, $path_info) = ($1, $2);
    2888             }
    2889             }
    2890 20         41 return ($script_name,$path_info);
    2891             }
    2892              
    2893             #### Method: request_method
    2894             # Returns 'POST', 'GET', 'PUT', 'PATCH' or 'HEAD'
    2895             ####
    2896             sub request_method {
    2897 7 50   7 1 1079 return (defined $ENV{'REQUEST_METHOD'}) ? $ENV{'REQUEST_METHOD'} : undef;
    2898             }
    2899              
    2900             #### Method: content_type
    2901             # Returns the content_type string
    2902             ####
    2903             sub content_type {
    2904 0 0   0 1 0 return (defined $ENV{'CONTENT_TYPE'}) ? $ENV{'CONTENT_TYPE'} : undef;
    2905             }
    2906              
    2907             #### Method: path_translated
    2908             # Return the physical path information provided
    2909             # by the URL (if any)
    2910             ####
    2911             sub path_translated {
    2912 0 0   0 1 0 return (defined $ENV{'PATH_TRANSLATED'}) ? $ENV{'PATH_TRANSLATED'} : undef;
    2913             }
    2914              
    2915             #### Method: request_uri
    2916             # Return the literal request URI
    2917             ####
    2918             sub request_uri {
    2919 64 100   64 1 208 return (defined $ENV{'REQUEST_URI'}) ? $ENV{'REQUEST_URI'} : undef;
    2920             }
    2921              
    2922             #### Method: query_string
    2923             # Synthesize a query string from our current
    2924             # parameters
    2925             ####
    2926             sub query_string {
    2927 29     29 0 70 my($self) = self_or_default(@_);
    2928 29         29 my($param,$value,@pairs);
    2929 29         49 for $param ($self->param) {
    2930 61         102 my($eparam) = escape($param);
    2931 61         87 for $value ($self->param($param)) {
    2932 79         107 $value = escape($value);
    2933 79 100       120 next unless defined $value;
    2934 72         144 push(@pairs,"$eparam=$value");
    2935             }
    2936             }
    2937 29         30 for (keys %{$self->{'.fieldnames'}}) {
      29         109  
    2938 0         0 push(@pairs,".cgifields=".escape("$_"));
    2939             }
    2940 29 50       139 return join($USE_PARAM_SEMICOLONS ? ';' : '&',@pairs);
    2941             }
    2942              
    2943             sub env_query_string {
    2944 1 50   1 1 5 return (defined $ENV{'QUERY_STRING'}) ? $ENV{'QUERY_STRING'} : undef;
    2945             }
    2946              
    2947             #### Method: accept
    2948             # Without parameters, returns an array of the
    2949             # MIME types the browser accepts.
    2950             # With a single parameter equal to a MIME
    2951             # type, will return undef if the browser won't
    2952             # accept it, 1 if the browser accepts it but
    2953             # doesn't give a preference, or a floating point
    2954             # value between 0.0 and 1.0 if the browser
    2955             # declares a quantitative score for it.
    2956             # This handles MIME type globs correctly.
    2957             ####
    2958             sub Accept {
    2959 0     0 1 0 my($self,$search) = self_or_CGI(@_);
    2960 0         0 my(%prefs,$type,$pref,$pat);
    2961            
    2962 0 0       0 my(@accept) = defined $self->http('accept')
    2963             ? split(',',$self->http('accept'))
    2964             : ();
    2965              
    2966 0         0 for (@accept) {
    2967 0         0 ($pref) = /q=(\d\.\d+|\d+)/;
    2968 0         0 ($type) = m#(\S+/[^;]+)#;
    2969 0 0       0 next unless $type;
    2970 0   0     0 $prefs{$type}=$pref || 1;
    2971             }
    2972              
    2973 0 0       0 return keys %prefs unless $search;
    2974            
    2975             # if a search type is provided, we may need to
    2976             # perform a pattern matching operation.
    2977             # The MIME types use a glob mechanism, which
    2978             # is easily translated into a perl pattern match
    2979              
    2980             # First return the preference for directly supported
    2981             # types:
    2982 0 0       0 return $prefs{$search} if $prefs{$search};
    2983              
    2984             # Didn't get it, so try pattern matching.
    2985 0         0 for (keys %prefs) {
    2986 0 0       0 next unless /\*/; # not a pattern match
    2987 0         0 ($pat = $_) =~ s/([^\w*])/\\$1/g; # escape meta characters
    2988 0         0 $pat =~ s/\*/.*/g; # turn it into a pattern
    2989 0 0       0 return $prefs{$_} if $search=~/$pat/;
    2990             }
    2991             }
    2992              
    2993             #### Method: user_agent
    2994             # If called with no parameters, returns the user agent.
    2995             # If called with one parameter, does a pattern match (case
    2996             # insensitive) on the user agent.
    2997             ####
    2998             sub user_agent {
    2999 7     7 1 22 my($self,$match)=self_or_CGI(@_);
    3000 7         21 my $user_agent = $self->http('user_agent');
    3001 7 100 66     52 return $user_agent unless defined $match && $match && $user_agent;
          100        
    3002 4         99 return $user_agent =~ /$match/i;
    3003             }
    3004              
    3005             #### Method: raw_cookie
    3006             # Returns the magic cookies for the session.
    3007             # The cookies are not parsed or altered in any way, i.e.
    3008             # cookies are returned exactly as given in the HTTP
    3009             # headers. If a cookie name is given, only that cookie's
    3010             # value is returned, otherwise the entire raw cookie
    3011             # is returned.
    3012             ####
    3013             sub raw_cookie {
    3014 0     0 1 0 my($self,$key) = self_or_CGI(@_);
    3015              
    3016 0         0 require CGI::Cookie;
    3017              
    3018 0 0       0 if (defined($key)) {
    3019             $self->{'.raw_cookies'} = CGI::Cookie->raw_fetch
    3020 0 0       0 unless $self->{'.raw_cookies'};
    3021              
    3022 0 0       0 return () unless $self->{'.raw_cookies'};
    3023 0 0       0 return () unless $self->{'.raw_cookies'}->{$key};
    3024 0         0 return $self->{'.raw_cookies'}->{$key};
    3025             }
    3026 0   0     0 return $self->http('cookie') || $ENV{'COOKIE'} || '';
    3027             }
    3028              
    3029             #### Method: virtual_host
    3030             # Return the name of the virtual_host, which
    3031             # is not always the same as the server
    3032             ######
    3033             sub virtual_host {
    3034 0   0 0 1 0 my $vh = http('x_forwarded_host') || http('host') || server_name();
    3035 0         0 $vh =~ s/:\d+$//; # get rid of port number
    3036 0         0 return $vh;
    3037             }
    3038              
    3039             #### Method: remote_host
    3040             # Return the name of the remote host, or its IP
    3041             # address if unavailable. If this variable isn't
    3042             # defined, it returns "localhost" for debugging
    3043             # purposes.
    3044             ####
    3045             sub remote_host {
    3046 0   0 0 1 0 return $ENV{'REMOTE_HOST'} || $ENV{'REMOTE_ADDR'}
    3047             || 'localhost';
    3048             }
    3049              
    3050             #### Method: remote_addr
    3051             # Return the IP addr of the remote host.
    3052             ####
    3053             sub remote_addr {
    3054 0   0 0 1 0 return $ENV{'REMOTE_ADDR'} || '127.0.0.1';
    3055             }
    3056              
    3057             #### Method: script_name
    3058             # Return the partial URL to this script for
    3059             # self-referencing scripts. Also see
    3060             # self_url(), which returns a URL with all state information
    3061             # preserved.
    3062             ####
    3063             sub script_name {
    3064 48     48 1 69 my ($self,@p) = self_or_default(@_);
    3065 48 50       125 if (@p) {
        100          
    3066 0         0 $self->{'.script_name'} = shift @p;
    3067             } elsif (!exists $self->{'.script_name'}) {
    3068 10         31 my ($script_name,$path_info) = $self->_name_and_path_from_env();
    3069 10         26 $self->{'.script_name'} = $script_name;
    3070             }
    3071 48         70 return $self->{'.script_name'};
    3072             }
    3073              
    3074             #### Method: referer
    3075             # Return the HTTP_REFERER: useful for generating
    3076             # a GO BACK button.
    3077             ####
    3078             sub referer {
    3079 0     0 1 0 my($self) = self_or_CGI(@_);
    3080 0         0 return $self->http('referer');
    3081             }
    3082              
    3083             #### Method: server_name
    3084             # Return the name of the server
    3085             ####
    3086             sub server_name {
    3087 11   100 11 1 47 return $ENV{'SERVER_NAME'} || 'localhost';
    3088             }
    3089              
    3090             #### Method: server_software
    3091             # Return the name of the server software
    3092             ####
    3093             sub server_software {
    3094 5   50 5 1 26 return $ENV{'SERVER_SOFTWARE'} || 'cmdline';
    3095             }
    3096              
    3097             #### Method: virtual_port
    3098             # Return the server port, taking virtual hosts into account
    3099             ####
    3100             sub virtual_port {
    3101 28     28 1 58 my($self) = self_or_default(@_);
    3102 28   100     46 my $vh = $self->http('x_forwarded_host') || $self->http('host');
    3103 28         50 my $protocol = $self->protocol;
    3104 28 100       50 if ($vh) {
    3105 17   66     61 return ($vh =~ /:(\d+)$/)[0] || ($protocol eq 'https' ? 443 : 80);
    3106             } else {
    3107 11         21 return $self->server_port();
    3108             }
    3109             }
    3110              
    3111             #### Method: server_port
    3112             # Return the tcp/ip port the server is running on
    3113             ####
    3114             sub server_port {
    3115 67   100 67 1 243 return $ENV{'SERVER_PORT'} || 80; # for debugging
    3116             }
    3117              
    3118             #### Method: server_protocol
    3119             # Return the protocol (usually HTTP/1.0)
    3120             ####
    3121             sub server_protocol {
    3122 55   100 55 1 117 return $ENV{'SERVER_PROTOCOL'} || 'HTTP/1.0'; # for debugging
    3123             }
    3124              
    3125             #### Method: http
    3126             # Return the value of an HTTP variable, or
    3127             # the list of variables if none provided
    3128             ####
    3129             sub http {
    3130 118     118 1 563 my ($self,$parameter) = self_or_CGI(@_);
    3131 118 100       182 if ( defined($parameter) ) {
    3132 116         111 $parameter =~ tr/-a-z/_A-Z/;
    3133 116 100       189 if ( $parameter =~ /^HTTP(?:_|$)/ ) {
    3134 1         4 return $ENV{$parameter};
    3135             }
    3136 115         371 return $ENV{"HTTP_$parameter"};
    3137             }
    3138 2         10 return grep { /^HTTP(?:_|$)/ } keys %ENV;
      45         42  
    3139             }
    3140              
    3141             #### Method: https
    3142             # Return the value of HTTPS, or
    3143             # the value of an HTTPS variable, or
    3144             # the list of variables
    3145             ####
    3146             sub https {
    3147 58     58 1 652 my ($self,$parameter) = self_or_CGI(@_);
    3148 58 50       85 if ( defined($parameter) ) {
    3149 0         0 $parameter =~ tr/-a-z/_A-Z/;
    3150 0 0       0 if ( $parameter =~ /^HTTPS(?:_|$)/ ) {
    3151 0         0 return $ENV{$parameter};
    3152             }
    3153 0         0 return $ENV{"HTTPS_$parameter"};
    3154             }
    3155             return wantarray
    3156 24         27 ? grep { /^HTTPS(?:_|$)/ } keys %ENV
    3157 58 100       174 : $ENV{'HTTPS'};
    3158             }
    3159              
    3160             #### Method: protocol
    3161             # Return the protocol (http or https currently)
    3162             ####
    3163             sub protocol {
    3164 55     55 0 105 local($^W)=0;
    3165 55         48 my $self = shift;
    3166 55 50       72 return 'https' if uc($self->https()) eq 'ON';
    3167 55 50       82 return 'https' if $self->server_port == 443;
    3168 55         69 my $prot = $self->server_protocol;
    3169 55         111 my($protocol,$version) = split('/',$prot);
    3170 55         102 return "\L$protocol\E";
    3171             }
    3172              
    3173             #### Method: remote_ident
    3174             # Return the identity of the remote user
    3175             # (but only if his host is running identd)
    3176             ####
    3177             sub remote_ident {
    3178 0 0   0 1 0 return (defined $ENV{'REMOTE_IDENT'}) ? $ENV{'REMOTE_IDENT'} : undef;
    3179             }
    3180              
    3181             #### Method: auth_type
    3182             # Return the type of use verification/authorization in use, if any.
    3183             ####
    3184             sub auth_type {
    3185 0 0   0 1 0 return (defined $ENV{'AUTH_TYPE'}) ? $ENV{'AUTH_TYPE'} : undef;
    3186             }
    3187              
    3188             #### Method: remote_user
    3189             # Return the authorization name used for user
    3190             # verification.
    3191             ####
    3192             sub remote_user {
    3193 0 0   0 1 0 return (defined $ENV{'REMOTE_USER'}) ? $ENV{'REMOTE_USER'} : undef;
    3194             }
    3195              
    3196             #### Method: user_name
    3197             # Try to return the remote user's name by hook or by
    3198             # crook
    3199             ####
    3200             sub user_name {
    3201 0     0 1 0 my ($self) = self_or_CGI(@_);
    3202 0   0     0 return $self->http('from') || $ENV{'REMOTE_IDENT'} || $ENV{'REMOTE_USER'};
    3203             }
    3204              
    3205             #### Method: nosticky
    3206             # Set or return the NOSTICKY global flag
    3207             ####
    3208             sub nosticky {
    3209 1     1 0 3 my ($self,$param) = self_or_CGI(@_);
    3210 1 50       3 $CGI::NOSTICKY = $param if defined($param);
    3211 1         4 return $CGI::NOSTICKY;
    3212             }
    3213              
    3214             #### Method: nph
    3215             # Set or return the NPH global flag
    3216             ####
    3217             sub nph {
    3218 1     1 1 3 my ($self,$param) = self_or_CGI(@_);
    3219 1 50       3 $CGI::NPH = $param if defined($param);
    3220 1         3 return $CGI::NPH;
    3221             }
    3222              
    3223             #### Method: private_tempfiles
    3224             # Set or return the private_tempfiles global flag
    3225             ####
    3226             sub private_tempfiles {
    3227 1     1 0 18 warn "private_tempfiles has been deprecated";
    3228 1         4 return 0;
    3229             }
    3230             #### Method: close_upload_files
    3231             # Set or return the close_upload_files global flag
    3232             ####
    3233             sub close_upload_files {
    3234 1     1 0 3 my ($self,$param) = self_or_CGI(@_);
    3235 1 50       4 $CGI::CLOSE_UPLOAD_FILES = $param if defined($param);
    3236 1         3 return $CGI::CLOSE_UPLOAD_FILES;
    3237             }
    3238              
    3239             #### Method: default_dtd
    3240             # Set or return the default_dtd global
    3241             ####
    3242             sub default_dtd {
    3243 1     1 0 4 my ($self,$param,$param2) = self_or_CGI(@_);
    3244 1 50 33     6 if (defined $param2 && defined $param) {
        50          
    3245 0         0 $CGI::DEFAULT_DTD = [ $param, $param2 ];
    3246             } elsif (defined $param) {
    3247 0         0 $CGI::DEFAULT_DTD = $param;
    3248             }
    3249 1         4 return $CGI::DEFAULT_DTD;
    3250             }
    3251              
    3252             # -------------- really private subroutines -----------------
    3253             sub _maybe_escapeHTML {
    3254             # hack to work around earlier hacks
    3255 318 50 33 318   561 push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
    3256 318         338 my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_);
    3257 318 100       457 return undef unless defined($toencode);
    3258 304 100 66     909 return $toencode if ref($self) && !$self->{'escape'};
    3259 244         316 return $self->escapeHTML($toencode, $newlinestoo);
    3260             }
    3261              
    3262             sub previous_or_default {
    3263 16     16 0 19 my($self,$name,$defaults,$override) = @_;
    3264 16         14 my(%selected);
    3265              
    3266 16 100 66     85 if (!$override && ($self->{'.fieldnames'}->{$name} ||
        100 66        
          100        
          66        
    3267             defined($self->param($name)) ) ) {
    3268 7         10 $selected{$_}++ for $self->param($name);
    3269             } elsif (defined($defaults) && ref($defaults) &&
    3270             (ref($defaults) eq 'ARRAY')) {
    3271 6         5 $selected{$_}++ for @{$defaults};
      6         17  
    3272             } else {
    3273 3 100       6 $selected{$defaults}++ if defined($defaults);
    3274             }
    3275              
    3276 16         49 return %selected;
    3277             }
    3278              
    3279             sub register_parameter {
    3280 25     25 0 64 my($self,$param) = @_;
    3281 25         41 $self->{'.parametersToAdd'}->{$param}++;
    3282             }
    3283              
    3284             sub get_fields {
    3285 1     1 0 2 my($self) = @_;
    3286             return $self->CGI::hidden('-name'=>'.cgifields',
    3287 1         12 '-values'=>[keys %{$self->{'.parametersToAdd'}}],
      1         8  
    3288             '-override'=>1);
    3289             }
    3290              
    3291             sub read_from_cmdline {
    3292 74     74 0 167 my($input,@words);
    3293 0         0 my($query_string);
    3294 0         0 my($subpath);
    3295 74 50 33     369 if ($DEBUG && @ARGV) {
        50          
    3296 0         0 @words = @ARGV;
    3297             } elsif ($DEBUG > 1) {
    3298 0         0 require Text::ParseWords;
    3299 0         0 print STDERR "(offline mode: enter name=value pairs on standard input; press ^D or ^Z when done)\n";
    3300 0         0 chomp(@lines = ); # remove newlines
    3301 0         0 $input = join(" ",@lines);
    3302 0         0 @words = &Text::ParseWords::old_shellwords($input);
    3303             }
    3304 74         153 for (@words) {
    3305 0         0 s/\\=/%3D/g;
    3306 0         0 s/\\&/%26/g;
    3307             }
    3308              
    3309 74 50       238 if ("@words"=~/=/) {
    3310 0         0 $query_string = join('&',@words);
    3311             } else {
    3312 74         129 $query_string = join('+',@words);
    3313             }
    3314 74 50       168 if ($query_string =~ /^(.*?)\?(.*)$/)
    3315             {
    3316 0         0 $query_string = $2;
    3317 0         0 $subpath = $1;
    3318             }
    3319 74         208 return { 'query_string' => $query_string, 'subpath' => $subpath };
    3320             }
    3321              
    3322             #####
    3323             # subroutine: read_multipart
    3324             #
    3325             # Read multipart data and store it into our parameters.
    3326             # An interesting feature is that if any of the parts is a file, we
    3327             # create a temporary file and open up a filehandle on it so that the
    3328             # caller can read from it if necessary.
    3329             #####
    3330             sub read_multipart {
    3331 2     2 0 5 my($self,$boundary,$length) = @_;
    3332 2         7 my($buffer) = $self->new_MultipartBuffer($boundary,$length);
    3333 2 50       5 return unless $buffer;
    3334 2         3 my(%header,$body);
    3335 2         2 my $filenumber = 0;
    3336 2         4 while (!$buffer->eof) {
    3337 10         19 %header = $buffer->readHeader;
    3338              
    3339 10 50       24 unless (%header) {
    3340 0         0 $self->cgi_error("400 Bad request (malformed multipart POST)");
    3341 0         0 return;
    3342             }
    3343              
    3344 10   50     18 $header{'Content-Disposition'} ||= ''; # quench uninit variable warning
    3345              
    3346 10         40 my($param)= $header{'Content-Disposition'}=~/[\s;]name="([^"]*)"/;
    3347 10         14 $param .= $TAINTED;
    3348              
    3349             # See RFC 1867, 2183, 2045
    3350             # NB: File content will be loaded into memory should
    3351             # content-disposition parsing fail.
    3352 10         36 my ($filename) = $header{'Content-Disposition'}
    3353             =~/ filename=(("[^"]*")|([a-z\d!\#'\*\+,\.^_\`\{\}\|\~]*))/i;
    3354              
    3355 10   50     19 $filename ||= ''; # quench uninit variable warning
    3356              
    3357 10         28 $filename =~ s/^"([^"]*)"$/$1/;
    3358             # Test for Opera's multiple upload feature
    3359             my($multipart) = ( defined( $header{'Content-Type'} ) &&
    3360 10 50 33     47 $header{'Content-Type'} =~ /multipart\/mixed/ ) ?
    3361             1 : 0;
    3362              
    3363             # add this parameter to our list
    3364 10         24 $self->add_parameter($param);
    3365              
    3366             # If no filename specified, then just read the data and assign it
    3367             # to our parameter list.
    3368 10 50 33     55 if ( ( !defined($filename) || $filename eq '' ) && !$multipart ) {
          33        
    3369 0         0 my($value) = $buffer->readBody;
    3370 0         0 $value .= $TAINTED;
    3371 0         0 push(@{$self->{param}{$param}},$value);
      0         0  
    3372 0         0 next;
    3373             }
    3374              
    3375             UPLOADS: {
    3376             # If we get here, then we are dealing with a potentially large
    3377             # uploaded form. Save the data to a temporary file, then open
    3378             # the file for reading.
    3379              
    3380             # skip the file if uploads disabled
    3381 10 50       8 if ($DISABLE_UPLOADS) {
      10         17  
    3382 0         0 while (defined($data = $buffer->read)) { }
    3383 0         0 last UPLOADS;
    3384             }
    3385              
    3386             # set the filename to some recognizable value
    3387 10 50 33     37 if ( ( !defined($filename) || $filename eq '' ) && $multipart ) {
          33        
    3388 0         0 $filename = "multipart/mixed";
    3389             }
    3390              
    3391             my $tmp_dir = $CGI::OS eq 'WINDOWS'
    3392 10 50 0     16 ? ( $ENV{TEMP} || $ENV{TMP} || ( $ENV{WINDIR} ? ( $ENV{WINDIR} . $SL . 'TEMP' ) : undef ) )
    3393             : undef; # File::Temp defaults to TMPDIR
    3394              
    3395 10         984 require CGI::File::Temp;
    3396 10         37 my $filehandle = CGI::File::Temp->new(
    3397             UNLINK => $UNLINK_TMP_FILES,
    3398             DIR => $tmp_dir,
    3399             );
    3400 10         3246 $filehandle->_mp_filename( $filename );
    3401              
    3402 10 50 33     26 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode
    3403             && defined fileno($filehandle);
    3404              
    3405             # if this is an multipart/mixed attachment, save the header
    3406             # together with the body for later parsing with an external
    3407             # MIME parser module
    3408 10 50       16 if ( $multipart ) {
    3409 0         0 for ( keys %header ) {
    3410 0         0 print $filehandle "$_: $header{$_}${CRLF}";
    3411             }
    3412 0         0 print $filehandle "${CRLF}";
    3413             }
    3414              
    3415 10         9 my ($data);
    3416 10         26 local($\) = '';
    3417 10         11 my $totalbytes = 0;
    3418 10         22 while (defined($data = $buffer->read)) {
    3419 10 50       22 if (defined $self->{'.upload_hook'})
    3420             {
    3421 0         0 $totalbytes += length($data);
    3422 0         0 &{$self->{'.upload_hook'}}($filename ,$data, $totalbytes, $self->{'.upload_data'});
      0         0  
    3423             }
    3424 10 50       93 print $filehandle $data if ($self->{'use_tempfile'});
    3425             }
    3426              
    3427             # back up to beginning of file
    3428 10         299 seek($filehandle,0,0);
    3429              
    3430             ## Close the filehandle if requested this allows a multipart MIME
    3431             ## upload to contain many files, and we won't die due to too many
    3432             ## open file handles. The user can access the files using the hash
    3433             ## below.
    3434 10 50       21 close $filehandle if $CLOSE_UPLOAD_FILES;
    3435 10 50       17 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;
    3436              
    3437             # Save some information about the uploaded file where we can get
    3438             # at it later.
    3439             # Use the typeglob + filename as the key, as this is guaranteed to be
    3440             # unique for each filehandle. Don't use the file descriptor as
    3441             # this will be re-used for each filehandle if the
    3442             # close_upload_files feature is used.
    3443 10         34 $self->{'.tmpfiles'}->{$$filehandle . $filehandle} = {
    3444             hndl => $filehandle,
    3445             name => $filehandle->filename,
    3446             info => {%header},
    3447             };
    3448 10         16 push(@{$self->{param}{$param}},$filehandle);
      10         47  
    3449             }
    3450             }
    3451             }
    3452              
    3453             #####
    3454             # subroutine: read_multipart_related
    3455             #
    3456             # Read multipart/related data and store it into our parameters. The
    3457             # first parameter sets the start of the data. The part identified by
    3458             # this Content-ID will not be stored as a file upload, but will be
    3459             # returned by this method. All other parts will be available as file
    3460             # uploads accessible by their Content-ID
    3461             #####
    3462             sub read_multipart_related {
    3463 1     1 0 2 my($self,$start,$boundary,$length) = @_;
    3464 1         4 my($buffer) = $self->new_MultipartBuffer($boundary,$length);
    3465 1 50       3 return unless $buffer;
    3466 1         2 my(%header,$body);
    3467 1         1 my $filenumber = 0;
    3468 1         1 my $returnvalue;
    3469 1         2 while (!$buffer->eof) {
    3470 2         8 %header = $buffer->readHeader;
    3471              
    3472 2 50       6 unless (%header) {
    3473 0         0 $self->cgi_error("400 Bad request (malformed multipart POST)");
    3474 0         0 return;
    3475             }
    3476              
    3477 2         10 my($param) = $header{'Content-ID'}=~/\<([^\>]*)\>/;
    3478 2         4 $param .= $TAINTED;
    3479              
    3480             # If this is the start part, then just read the data and assign it
    3481             # to our return variable.
    3482 2 50       4 if ( $param eq $start ) {
    3483 0         0 $returnvalue = $buffer->readBody;
    3484 0         0 $returnvalue .= $TAINTED;
    3485 0         0 next;
    3486             }
    3487              
    3488             # add this parameter to our list
    3489 2         7 $self->add_parameter($param);
    3490              
    3491             UPLOADS: {
    3492             # If we get here, then we are dealing with a potentially large
    3493             # uploaded form. Save the data to a temporary file, then open
    3494             # the file for reading.
    3495              
    3496             # skip the file if uploads disabled
    3497 2 50       2 if ($DISABLE_UPLOADS) {
      2         5  
    3498 0         0 while (defined($data = $buffer->read)) { }
    3499 0         0 last UPLOADS;
    3500             }
    3501              
    3502             my $tmp_dir = $CGI::OS eq 'WINDOWS'
    3503 2 50 0     5 ? ( $ENV{TEMP} || $ENV{TMP} || ( $ENV{WINDIR} ? ( $ENV{WINDIR} . $SL . 'TEMP' ) : undef ) )
    3504             : undef; # File::Temp defaults to TMPDIR
    3505              
    3506 2         509 require CGI::File::Temp;
    3507 2         12 my $filehandle = CGI::File::Temp->new(
    3508             UNLINK => $UNLINK_TMP_FILES,
    3509             DIR => $tmp_dir,
    3510             );
    3511 2         1029 $filehandle->_mp_filename( $filehandle->filename );
    3512              
    3513 2 50 33     6 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode
    3514             && defined fileno($filehandle);
    3515              
    3516 2         3 my ($data);
    3517 2         6 local($\) = '';
    3518 2         2 my $totalbytes;
    3519 2         7 while (defined($data = $buffer->read)) {
    3520 2 50       4 if (defined $self->{'.upload_hook'})
    3521             {
    3522 0         0 $totalbytes += length($data);
    3523 0         0 &{$self->{'.upload_hook'}}($param ,$data, $totalbytes, $self->{'.upload_data'});
      0         0  
    3524             }
    3525 2 50       20 print $filehandle $data if ($self->{'use_tempfile'});
    3526             }
    3527              
    3528             # back up to beginning of file
    3529 2         37359 seek($filehandle,0,0);
    3530              
    3531             ## Close the filehandle if requested this allows a multipart MIME
    3532             ## upload to contain many files, and we won't die due to too many
    3533             ## open file handles. The user can access the files using the hash
    3534             ## below.
    3535 2 50       17 close $filehandle if $CLOSE_UPLOAD_FILES;
    3536 2 50       6 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;
    3537              
    3538             # Save some information about the uploaded file where we can get
    3539             # at it later.
    3540             # Use the typeglob + filename as the key, as this is guaranteed to be
    3541             # unique for each filehandle. Don't use the file descriptor as
    3542             # this will be re-used for each filehandle if the
    3543             # close_upload_files feature is used.
    3544 2         19 $self->{'.tmpfiles'}->{$$filehandle . $filehandle} = {
    3545             hndl => $filehandle,
    3546             name => $filehandle->filename,
    3547             info => {%header},
    3548             };
    3549 2         5 push(@{$self->{param}{$param}},$filehandle);
      2         18  
    3550             }
    3551             }
    3552 1         14 return $returnvalue;
    3553             }
    3554              
    3555             sub upload {
    3556 16     16 1 2869 my($self,$param_name) = self_or_default(@_);
    3557 16 50       29 my @param = grep {ref($_) && defined(fileno($_))} $self->param($param_name);
      18         90  
    3558 16 50       23 return unless @param;
    3559 16 100       51 return wantarray ? @param : $param[0];
    3560             }
    3561              
    3562             sub tmpFileName {
    3563 11     11 0 204 my($self,$filename) = self_or_default(@_);
    3564              
    3565             # preferred calling convention: $filename came directly from param or upload
    3566 11 100       20 if (ref $filename) {
    3567 7   50     39 return $self->{'.tmpfiles'}->{$$filename . $filename}->{name} || '';
    3568             }
    3569              
    3570             # backwards compatible with older versions: $filename is merely equal to
    3571             # one of our filenames when compared as strings
    3572 4         7 foreach my $param_name ($self->param) {
    3573 16         21 foreach my $filehandle ($self->multi_param($param_name)) {
    3574 20 100       28 if ($filehandle eq $filename) {
    3575 4   50     42 return $self->{'.tmpfiles'}->{$$filehandle . $filehandle}->{name} || '';
    3576             }
    3577             }
    3578             }
    3579              
    3580 0         0 return '';
    3581             }
    3582              
    3583             sub uploadInfo {
    3584 19     19 0 524 my($self,$filename) = self_or_default(@_);
    3585 19 100       48 return if ! defined $$filename;
    3586 16         77 return $self->{'.tmpfiles'}->{$$filename . $filename}->{info};
    3587             }
    3588              
    3589             # internal routine, don't use
    3590             sub _set_values_and_labels {
    3591 27     27   26 my $self = shift;
    3592 27         28 my ($v,$l,$n) = @_;
    3593 27 50 33     62 $$l = $v if ref($v) eq 'HASH' && !ref($$l);
    3594 27 100       48 return $self->param($n) if !defined($v);
    3595 23 50       39 return $v if !ref($v);
    3596 23 50       65 return ref($v) eq 'HASH' ? keys %$v : @$v;
    3597             }
    3598              
    3599             # internal routine, don't use
    3600             sub _set_attributes {
    3601 71     71   59 my $self = shift;
    3602 71         63 my($element, $attributes) = @_;
    3603 71 100       163 return '' unless defined($attributes->{$element});
    3604 2         2 $attribs = ' ';
    3605 2         15 for my $attrib (keys %{$attributes->{$element}}) {
      2         6  
    3606 2         3 (my $clean_attrib = $attrib) =~ s/^-//;
    3607 2         3 $attribs .= "@{[lc($clean_attrib)]}=\"$attributes->{$element}{$attrib}\" ";
      2         11  
    3608             }
    3609 2         6 $attribs =~ s/ $//;
    3610 2         4 return $attribs;
    3611             }
    3612              
    3613             #########################################################
    3614             # Globals and stubs for other packages that we use.
    3615             #########################################################
    3616              
    3617             ######################## CGI::MultipartBuffer ####################
    3618              
    3619             package CGI::MultipartBuffer;
    3620              
    3621             $_DEBUG = 0;
    3622              
    3623             # how many bytes to read at a time. We use
    3624             # a 4K buffer by default.
    3625             $MultipartBuffer::INITIAL_FILLUNIT ||= 1024 * 4;
    3626             $MultipartBuffer::TIMEOUT ||= 240*60; # 4 hour timeout for big files
    3627             $MultipartBuffer::SPIN_LOOP_MAX ||= 2000; # bug fix for some Netscape servers
    3628             $MultipartBuffer::CRLF ||= $CGI::CRLF;
    3629              
    3630             $INITIAL_FILLUNIT = $MultipartBuffer::INITIAL_FILLUNIT;
    3631             $TIMEOUT = $MultipartBuffer::TIMEOUT;
    3632             $SPIN_LOOP_MAX = $MultipartBuffer::SPIN_LOOP_MAX;
    3633             $CRLF = $MultipartBuffer::CRLF;
    3634              
    3635             sub new {
    3636 3     3   64 my($package,$interface,$boundary,$length) = @_;
    3637 3         7 $FILLUNIT = $INITIAL_FILLUNIT;
    3638 3         14 $CGI::DefaultClass->binmode($IN); # if $CGI::needs_binmode; # just do it always
    3639              
    3640             # If the user types garbage into the file upload field,
    3641             # then Netscape passes NOTHING to the server (not good).
    3642             # We may hang on this read in that case. So we implement
    3643             # a read timeout. If nothing is ready to read
    3644             # by then, we return.
    3645              
    3646             # Netscape seems to be a little bit unreliable
    3647             # about providing boundary strings.
    3648 3         4 my $boundary_read = 0;
    3649 3 50       9 if ($boundary) {
    3650              
    3651             # Under the MIME spec, the boundary consists of the
    3652             # characters "--" PLUS the Boundary string
    3653              
    3654             # BUG: IE 3.01 on the Macintosh uses just the boundary -- not
    3655             # the two extra hyphens. We do a special case here on the user-agent!!!!
    3656 3 50       14 $boundary = "--$boundary" unless CGI::user_agent('MSIE\s+3\.0[12];\s*Mac|DreamPassport');
    3657              
    3658             } else { # otherwise we find it ourselves
    3659 0         0 my($old);
    3660 0         0 ($old,$/) = ($/,$CRLF); # read a CRLF-delimited line
    3661 0         0 $boundary = ; # BUG: This won't work correctly under mod_perl
    3662 0         0 $length -= length($boundary);
    3663 0         0 chomp($boundary); # remove the CRLF
    3664 0         0 $/ = $old; # restore old line separator
    3665 0         0 $boundary_read++;
    3666             }
    3667              
    3668 3         22 my $self = {LENGTH=>$length,
    3669             CHUNKED=>!$length,
    3670             BOUNDARY=>$boundary,
    3671             INTERFACE=>$interface,
    3672             BUFFER=>'',
    3673             };
    3674              
    3675 3 50       12 $FILLUNIT = length($boundary)
    3676             if length($boundary) > $FILLUNIT;
    3677              
    3678 3   33     18 my $retval = bless $self,ref $package || $package;
    3679              
    3680             # Read the preamble and the topmost (boundary) line plus the CRLF.
    3681 3 50       7 unless ($boundary_read) {
    3682 3         12 while ($self->read(0)) { }
    3683             }
    3684 3 50       9 die "Malformed multipart POST: data truncated\n" if $self->eof;
    3685              
    3686 3         7 return $retval;
    3687             }
    3688              
    3689             sub readHeader {
    3690 12     12   10 my($self) = @_;
    3691 12         11 my($end);
    3692 12         14 my($ok) = 0;
    3693 12         14 my($bad) = 0;
    3694              
    3695 12 50 33     46 local($CRLF) = "\015\012" if $CGI::OS eq 'VMS' || $CGI::EBCDIC;
    3696              
    3697 12   33     11 do {
    3698 12         22 $self->fillBuffer($FILLUNIT);
    3699 12 50       38 $ok++ if ($end = index($self->{BUFFER},"${CRLF}${CRLF}")) >= 0;
    3700 12 50       28 $ok++ if $self->{BUFFER} eq '';
    3701 12 50 33     43 $bad++ if !$ok && $self->{LENGTH} <= 0;
    3702             # this was a bad idea
    3703             # $FILLUNIT *= 2 if length($self->{BUFFER}) >= $FILLUNIT;
    3704             } until $ok || $bad;
    3705 12 50       21 return () if $bad;
    3706              
    3707             #EBCDIC NOTE: translate header into EBCDIC, but watch out for continuation lines!
    3708              
    3709 12         32 my($header) = substr($self->{BUFFER},0,$end+2);
    3710 12         18 substr($self->{BUFFER},0,$end+4) = '';
    3711 12         12 my %return;
    3712              
    3713 12 50       21 if ($CGI::EBCDIC) {
    3714 0 0       0 warn "untranslated header=$header\n" if $_DEBUG;
    3715 0         0 $header = CGI::Util::ascii2ebcdic($header);
    3716 0 0       0 warn "translated header=$header\n" if $_DEBUG;
    3717             }
    3718              
    3719             # See RFC 2045 Appendix A and RFC 822 sections 3.4.8
    3720             # (Folding Long Header Fields), 3.4.3 (Comments)
    3721             # and 3.4.5 (Quoted-Strings).
    3722              
    3723 12         11 my $token = '[-\w!\#$%&\'*+.^_\`|{}~]';
    3724 12         102 $header=~s/$CRLF\s+/ /og; # merge continuation lines
    3725              
    3726 12         257 while ($header=~/($token+):\s+([^$CRLF]*)/mgox) {
    3727 35         77 my ($field_name,$field_value) = ($1,$2);
    3728 35         83 $field_name =~ s/\b(\w)/uc($1)/eg; #canonicalize
      72         139  
    3729 35         128 $return{$field_name}=$field_value;
    3730             }
    3731 12         61 return %return;
    3732             }
    3733              
    3734             # This reads and returns the body as a single scalar value.
    3735             sub readBody {
    3736 0     0   0 my($self) = @_;
    3737 0         0 my($data);
    3738 0         0 my($returnval)='';
    3739              
    3740             #EBCDIC NOTE: want to translate returnval into EBCDIC HERE
    3741              
    3742 0         0 while (defined($data = $self->read)) {
    3743 0         0 $returnval .= $data;
    3744             }
    3745              
    3746 0 0       0 if ($CGI::EBCDIC) {
    3747 0 0       0 warn "untranslated body=$returnval\n" if $_DEBUG;
    3748 0         0 $returnval = CGI::Util::ascii2ebcdic($returnval);
    3749 0 0       0 warn "translated body=$returnval\n" if $_DEBUG;
    3750             }
    3751 0         0 return $returnval;
    3752             }
    3753              
    3754             # This will read $bytes or until the boundary is hit, whichever happens
    3755             # first. After the boundary is hit, we return undef. The next read will
    3756             # skip over the boundary and begin reading again;
    3757             sub read {
    3758 27     27   32 my($self,$bytes) = @_;
    3759              
    3760             # default number of bytes to read
    3761 27   33     65 $bytes = $bytes || $FILLUNIT;
    3762              
    3763             # Fill up our internal buffer in such a way that the boundary
    3764             # is never split between reads.
    3765 27         40 $self->fillBuffer($bytes);
    3766              
    3767 27 50       48 my $boundary_start = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}) : $self->{BOUNDARY};
    3768 27 50       49 my $boundary_end = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}.'--') : $self->{BOUNDARY}.'--';
    3769              
    3770             # Find the boundary in the buffer (it may not be there).
    3771 27         46 my $start = index($self->{BUFFER},$boundary_start);
    3772              
    3773 27 50       39 warn "boundary=$self->{BOUNDARY} length=$self->{LENGTH} start=$start\n" if $_DEBUG;
    3774              
    3775             # protect against malformed multipart POST operations
    3776 27 50 33     74 die "Malformed multipart POST\n" unless $self->{CHUNKED} || ($start >= 0 || $self->{LENGTH} > 0);
          66        
    3777              
    3778             #EBCDIC NOTE: want to translate boundary search into ASCII here.
    3779              
    3780             # If the boundary begins the data, then skip past it
    3781             # and return undef.
    3782 27 100       42 if ($start == 0) {
    3783              
    3784             # clear us out completely if we've hit the last boundary.
    3785 15 100       73 if (index($self->{BUFFER},$boundary_end)==0) {
    3786 3         6 $self->{BUFFER}='';
    3787 3         5 $self->{LENGTH}=0;
    3788 3         9 return undef;
    3789             }
    3790              
    3791             # just remove the boundary.
    3792 12         21 substr($self->{BUFFER},0,length($boundary_start))='';
    3793 12         25 $self->{BUFFER} =~ s/^\012\015?//;
    3794 12         28 return undef;
    3795             }
    3796              
    3797 12         12 my $bytesToReturn;
    3798 12 50       19 if ($start > 0) { # read up to the boundary
    3799 12 50       21 $bytesToReturn = $start-2 > $bytes ? $bytes : $start;
    3800             } else { # read the requested number of bytes
    3801             # leave enough bytes in the buffer to allow us to read
    3802             # the boundary. Thanks to Kevin Hendrick for finding
    3803             # this one.
    3804 0         0 $bytesToReturn = $bytes - (length($boundary_start)+1);
    3805             }
    3806              
    3807 12         29 my $returnval=substr($self->{BUFFER},0,$bytesToReturn);
    3808 12         16 substr($self->{BUFFER},0,$bytesToReturn)='';
    3809            
    3810             # If we hit the boundary, remove the CRLF from the end.
    3811 12 50       57 return ($bytesToReturn==$start)
    3812             ? substr($returnval,0,-2) : $returnval;
    3813             }
    3814              
    3815             # This fills up our internal buffer in such a way that the
    3816             # boundary is never split between reads
    3817             sub fillBuffer {
    3818 39     39   41 my($self,$bytes) = @_;
    3819 39 50 66     143 return unless $self->{CHUNKED} || $self->{LENGTH};
    3820              
    3821 39         40 my($boundaryLength) = length($self->{BOUNDARY});
    3822 39         47 my($bufferLength) = length($self->{BUFFER});
    3823 39         52 my($bytesToRead) = $bytes - $bufferLength + $boundaryLength + 2;
    3824 39 100 66     133 $bytesToRead = $self->{LENGTH} if !$self->{CHUNKED} && $self->{LENGTH} < $bytesToRead;
    3825              
    3826             # Try to read some data. We may hang here if the browser is screwed up.
    3827             my $bytesRead = $self->{INTERFACE}->read_from_client(\$self->{BUFFER},
    3828 39         84 $bytesToRead,
    3829             $bufferLength);
    3830 39 50       61 warn "bytesToRead=$bytesToRead, bufferLength=$bufferLength, buffer=$self->{BUFFER}\n" if $_DEBUG;
    3831 39 50       66 $self->{BUFFER} = '' unless defined $self->{BUFFER};
    3832              
    3833             # An apparent bug in the Apache server causes the read()
    3834             # to return zero bytes repeatedly without blocking if the
    3835             # remote user aborts during a file transfer. I don't know how
    3836             # they manage this, but the workaround is to abort if we get
    3837             # more than SPIN_LOOP_MAX consecutive zero reads.
    3838 39 100       48 if ($bytesRead <= 0) {
    3839             die "CGI.pm: Server closed socket during multipart read (client aborted?).\n"
    3840 36 50       64 if ($self->{ZERO_LOOP_COUNTER}++ >= $SPIN_LOOP_MAX);
    3841             } else {
    3842 3         6 $self->{ZERO_LOOP_COUNTER}=0;
    3843             }
    3844              
    3845 39 100 100     118 $self->{LENGTH} -= $bytesRead if !$self->{CHUNKED} && $bytesRead;
    3846             }
    3847              
    3848             # Return true when we've finished reading
    3849             sub eof {
    3850 18     18   17 my($self) = @_;
    3851             return 1 if (length($self->{BUFFER}) == 0)
    3852 18 100 66     75 && ($self->{LENGTH} <= 0);
    3853 15         30 undef;
    3854             }
    3855              
    3856             1;
    3857              
    3858             package CGI;
    3859              
    3860             # We get a whole bunch of warnings about "possibly uninitialized variables"
    3861             # when running with the -w switch. Touch them all once to get rid of the
    3862             # warnings. This is ugly and I hate it.
    3863             if ($^W) {
    3864             $CGI::CGI = '';
    3865             $CGI::CGI=<
    3866             $CGI::VERSION;
    3867             $CGI::MultipartBuffer::SPIN_LOOP_MAX;
    3868             $CGI::MultipartBuffer::CRLF;
    3869             $CGI::MultipartBuffer::TIMEOUT;
    3870             $CGI::MultipartBuffer::INITIAL_FILLUNIT;
    3871             EOF
    3872             ;
    3873             }
    3874              
    3875             1;