File Coverage

blib/lib/CGI.pm
Criterion Covered Total %
statement 1291 1576 81.9
branch 629 1030 61.0
condition 338 532 63.5
subroutine 142 172 82.5
pod 36 134 26.8
total 2436 3444 70.7


line stmt bran cond sub pod time code
1             package CGI;
2             require 5.008001;
3 56     56   3164856 use if $] >= 5.019, 'deprecate';
  56         1573  
  56         427  
4 56     56   57959 use Carp 'croak';
  56         151  
  56         5321  
5              
6             my $appease_cpants_kwalitee = q/
7             use strict;
8             use warnings;
9             #/;
10              
11             $CGI::VERSION='4.37';
12              
13 56     56   20855 use CGI::Util qw(rearrange rearrange_header make_attributes unescape escape expires ebcdic2ascii ascii2ebcdic);
  56         220  
  56         1545279  
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 6010 $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         307 $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         241 $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         216 $NPH = 0;
57              
58             # Set this to 1 to enable debugging from @ARGV
59             # Set to 2 to enable debugging from STDIN
60 84         193 $DEBUG = 1;
61              
62             # Set this to 1 to generate automatic tab indexes
63 84         178 $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         185 $CLOSE_UPLOAD_FILES = 0;
74              
75             # Automatically determined -- don't change
76 84         195 $EBCDIC = 0;
77              
78             # Change this to 1 to suppress redundant HTTP headers
79 84         183 $HEADERS_ONCE = 0;
80              
81             # separate the name=value pairs by semicolons rather than ampersands
82 84         193 $USE_PARAM_SEMICOLONS = 1;
83              
84             # Do not include undefined params parsed from query string
85             # use CGI qw(-no_undef_params);
86 84         177 $NO_UNDEF_PARAMS = 0;
87              
88             # return everything as utf-8
89 84         175 $PARAM_UTF8 = 0;
90              
91             # make param('PUTDATA') act like file upload
92 84         219 $PUTDATA_UPLOAD = 0;
93              
94             # Other globals that you shouldn't worry about.
95 84         239 undef $Q;
96 84         178 $BEEN_THERE = 0;
97 84         205 $DTD_PUBLIC_IDENTIFIER = "";
98 84         288 undef @QUERY_PARAM;
99 84         230 undef %QUERY_PARAM;
100 84         254 undef %EXPORT;
101 84         186 undef $QUERY_CHARSET;
102 84         198 undef %QUERY_FIELDNAMES;
103 84         221 undef %QUERY_TMPFILES;
104              
105             # prevent complaints by mod_perl
106 84         2894 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   1768 my %default_layers = (
204             unix => 1,
205             perlio => 1,
206             stdio => 1,
207             crlf => 1,
208             );
209              
210 1         3 foreach my $fh (
211             \*main::STDOUT,
212             \*main::STDIN,
213             \*main::STDERR,
214             ) {
215 3         16 my @modes = grep { ! $default_layers{$_} }
  7         24  
216             PerlIO::get_layers( $fh );
217              
218 3 100       11 if ( ! @modes ) {
219 2         11 $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   2212 my $self = shift;
267              
268             # This causes modules to clash.
269 56         212 undef %EXPORT_OK;
270 56         146 undef %EXPORT;
271              
272 56         316 $self->_setup_symbols(@_);
273 56         331 my ($callpack, $callfile, $callline) = caller;
274              
275 56 50       277 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         150 my @packages = ($self,@{"$self\:\:ISA"});
  56         503  
287 56         35562 for $sym (keys %EXPORT) {
288 2038         3038 my $pck;
289 2038         2577 my $def = $DefaultClass;
290 2038         3214 for $pck (@packages) {
291 2038 50       2409 if (defined(&{"$pck\:\:$sym"})) {
  2038         6187  
292 2038         3063 $def = $pck;
293 2038         2673 last;
294             }
295             }
296 2038         2494 *{"${callpack}::$sym"} = \&{"$def\:\:$sym"};
  2038         41012  
  2038         4061  
297             }
298             }
299              
300             sub expand_tags {
301 2256     2256 0 3685 my($tag) = @_;
302 2256 100       5526 return ("start_$1","end_$1") if $tag=~/^(?:\*|start_|end_)(.+)/;
303 2128         2802 my(@r);
304 2128 100       5797 return ($tag) unless $EXPORT_TAGS{$tag};
305 93         143 for (@{$EXPORT_TAGS{$tag}}) {
  93         231  
306 2173         3855 push(@r,&expand_tags($_));
307             }
308 93         1261 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 139     139 1 51885 my($class,@initializer) = @_;
317 139         485 my $self = {};
318              
319 139   33     1077 bless $self,ref $class || $class || $DefaultClass;
320              
321             # always use a tempfile
322 139         725 $self->{'use_tempfile'} = 1;
323              
324 139 50 33     770 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 139 100 100     587 if (ref($initializer[0])
332             && (UNIVERSAL::isa($initializer[0],'CODE'))) {
333 3         21 $self->upload_hook(shift @initializer, shift @initializer);
334 3 50       11 $self->{'use_tempfile'} = shift @initializer if (@initializer > 0);
335             }
336 139 50       478 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 139 50       400 $self->_reset_globals if $PERLEX;
355 139         862 $self->init(@initializer);
356 139         743 return $self;
357             }
358              
359             sub r {
360 2     2 0 6 my $self = shift;
361 2         6 my $r = $self->{'.r'};
362 2 100       10 $self->{'.r'} = shift if @_;
363 2         8 $r;
364             }
365              
366             sub upload_hook {
367 3     3 0 6 my $self;
368 3 50       16 if (ref $_[0] eq 'CODE') {
369 0         0 $CGI::Q = $self = $CGI::DefaultClass->new(@_);
370             } else {
371 3         10 $self = shift;
372             }
373 3         10 my ($hook,$data,$use_tempfile) = @_;
374 3         9 $self->{'.upload_hook'} = $hook;
375 3         10 $self->{'.upload_data'} = $data;
376 3 50       12 $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 10169 my @list_of_params = param( @_ );
398 17         57 return @list_of_params;
399             }
400              
401             sub param {
402 1100     1100 0 23539 my($self,@p) = self_or_default(@_);
403              
404 1100 100       3550 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 658 100 100     2232 if ( wantarray && $LIST_CONTEXT_WARN == 1 ) {
409 184         814 my ( $package, $filename, $line ) = caller;
410 184 100       714 if ( $package ne 'CGI' ) {
411 1         2 $LIST_CONTEXT_WARN++; # only warn once
412 1         14 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 658         1477 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 658 100       1512 if (@p > 1) {
422 59         316 ($name,$value,@other) = rearrange([NAME,[DEFAULT,VALUE,VALUES]],@p);
423 59         165 my(@values);
424              
425 59 100       191 if (substr($p[0],0,1) eq '-') {
426 47 100 66     259 @values = defined($value) ? (ref($value) && ref($value) eq 'ARRAY' ? @{$value} : $value) : ();
  37 100       106  
427             } else {
428 12         36 for ($value,@other) {
429 12 100       56 push(@values,$_) if defined($_);
430             }
431             }
432             # If values is provided, then we set it.
433 59 100 66     236 if (@values or defined $value) {
434 47         179 $self->add_parameter($name);
435 47         188 $self->{param}{$name}=[@values];
436             }
437             } else {
438 599         1299 $name = $p[0];
439             }
440              
441 658 100 100     3778 return unless defined($name) && $self->{param}{$name};
442              
443 326         538 my @result = @{$self->{param}{$name}};
  326         857  
444              
445 326 50 66     936 if ($PARAM_UTF8 && $name ne 'PUTDATA' && $name ne 'POSTDATA' && $name ne 'PATCHDATA') {
      66        
      33        
446 5 50       52 eval "require Encode; 1;" unless Encode->can('decode'); # bring in these functions
447 5 50       14 @result = map {ref $_ ? $_ : $self->_decode_utf8($_) } @result;
  5         21  
448             }
449              
450 326 100       1852 return wantarray ? @result : $result[0];
451             }
452              
453             sub _decode_utf8 {
454 5     5   14 my ($self, $val) = @_;
455              
456 5 100       24 if (Encode::is_utf8($val)) {
457 2         12 return $val;
458             }
459             else {
460 3         13 return Encode::decode(utf8 => $val);
461             }
462             }
463              
464             sub self_or_default {
465 3872 100 100 3872 0 17873 return @_ if defined($_[0]) && (!ref($_[0])) &&($_[0] eq 'CGI');
      100        
466 3871 100 100     14546 unless (defined($_[0]) &&
      100        
467             (ref($_[0]) eq 'CGI' || UNIVERSAL::isa($_[0],'CGI')) # slightly optimized for common case
468             ) {
469 374 100       1054 $Q = $CGI::DefaultClass->new unless defined($Q);
470 374         881 unshift(@_,$Q);
471             }
472 3871 50       12841 return wantarray ? @_ : $Q;
473             }
474              
475             sub self_or_CGI {
476 187     187 0 869 local $^W=0; # prevent a warning
477 187 100 100     1236 if (defined($_[0]) &&
      66        
478             (substr(ref($_[0]),0,3) eq 'CGI'
479             || UNIVERSAL::isa($_[0],'CGI'))) {
480 131         512 return @_;
481             } else {
482 56         254 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 139     139 0 326 my $self = shift;
501 139         640 my($query_string,$meth,$content_length,$fh,@lines) = ('','','','');
502              
503 139         260 my $is_xforms;
504              
505 139         417 my $initializer = shift; # for backward compatibility
506 139         738 local($/) = "\n";
507              
508             # set autoescaping on by default
509 139         522 $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 139 100 100     597 if (@QUERY_PARAM && !defined($initializer)) {
515 5         24 for my $name (@QUERY_PARAM) {
516 18         53 my $val = $QUERY_PARAM{$name}; # always an arrayref;
517 18         65 $self->param('-name'=>$name,'-value'=> $val);
518 18 50 33     95 if (defined $val and ref $val eq 'ARRAY') {
519 18 100 66     48 for my $fh (grep {defined($_) && ref($_) && defined(fileno($_))} @$val) {
  23         201  
520 20         118 seek($fh,0,0); # reset the filehandle.
521             }
522              
523             }
524             }
525 5         43 $self->charset($QUERY_CHARSET);
526 5         22 $self->{'.fieldnames'} = {%QUERY_FIELDNAMES};
527 5         47 $self->{'.tmpfiles'} = {%QUERY_TMPFILES};
528 5         31 return;
529             }
530              
531 134 100       582 $meth=$ENV{'REQUEST_METHOD'} if defined($ENV{'REQUEST_METHOD'});
532 134 100       543 $content_length = defined($ENV{'CONTENT_LENGTH'}) ? $ENV{'CONTENT_LENGTH'} : 0;
533              
534 134 100       402 $fh = to_filehandle($initializer) if $initializer;
535              
536             # set charset to the safe ISO-8859-1
537 134         579 $self->charset('ISO-8859-1');
538              
539             METHOD: {
540              
541             # avoid unreasonably large postings
542 134 50 33     233 if (($POST_MAX > 0) && ($content_length > $POST_MAX)) {
  134         499  
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 134 100 100     625 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         13 my($boundary) = $ENV{'CONTENT_TYPE'} =~ /boundary=\"?([^\";,]+)\"?/;
556 2         13 $self->read_multipart($boundary,$content_length);
557 2         11 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 132 100 100     508 if ($meth eq 'POST' && defined($ENV{'CONTENT_TYPE'})) {
576 12 100       98 if ($ENV{'CONTENT_TYPE'} eq 'application/xml') {
    100          
577 1         3 my($param) = 'XForms:Model';
578 1         3 my($value) = '';
579 1         6 $self->add_parameter($param);
580 1 50       9 $self->read_from_client(\$value,$content_length,0)
581             if $content_length > 0;
582 1         3 push (@{$self->{param}{$param}},$value);
  1         6  
583 1         3 $is_xforms = 1;
584             } elsif ($ENV{'CONTENT_TYPE'} =~ /multipart\/related.+boundary=\"?([^\";,]+)\"?.+start=\"?\]+)\>?\"?/) {
585 8         29 my($boundary,$start) = ($1,$2);
586 8         15 my($param) = 'XForms:Model';
587 8         28 $self->add_parameter($param);
588 8         32 my($value) = $self->read_multipart_related($start,$boundary,$content_length,0);
589 8         22 push (@{$self->{param}{$param}},$value);
  8         30  
590 8         24 $query_string = $self->_get_query_string_from_env;
591 8         18 $is_xforms = 1;
592             }
593             }
594              
595              
596             # If initializer is defined, then read parameters
597             # from it.
598 132 100 100     695 if (!$is_xforms && defined($initializer)) {
599 12 50       84 if (UNIVERSAL::isa($initializer,'CGI')) {
600 0         0 $query_string = $initializer->query_string;
601 0         0 last METHOD;
602             }
603 12 100 100     82 if (ref($initializer) && ref($initializer) eq 'HASH') {
604 1         4 for (keys %$initializer) {
605 2         6 $self->param('-name'=>$_,'-value'=>$initializer->{$_});
606             }
607 1         3 last METHOD;
608             }
609              
610 11 100 66     62 if (defined($fh) && ($fh ne '')) {
611 4         49 while (my $line = <$fh>) {
612 9         20 chomp $line;
613 9 100       32 last if $line =~ /^=$/;
614 8         32 push(@lines,$line);
615             }
616             # massage back into standard format
617 4 50       33 if ("@lines" =~ /=/) {
618 4         18 $query_string=join("&",@lines);
619             } else {
620 0         0 $query_string=join("+",@lines);
621             }
622 4         16 last METHOD;
623             }
624              
625             # last chance -- treat it as a string
626 7 50       27 $initializer = $$initializer if ref($initializer) eq 'SCALAR';
627 7         18 $query_string = $initializer;
628              
629 7         23 last METHOD;
630             }
631              
632             # If method is GET, HEAD or DELETE, fetch the query from
633             # the environment.
634 120 100 100     792 if ($is_xforms || $meth=~/^(GET|HEAD|DELETE)$/) {
635 28         99 $query_string = $self->_get_query_string_from_env;
636 28 100       186 $self->param($meth . 'DATA', $self->param('XForms:Model'))
637             if $is_xforms;
638 28         66 last METHOD;
639             }
640              
641 92 100 100     699 if ($meth eq 'POST' || $meth eq 'PUT' || $meth eq 'PATCH') {
      100        
642 14 100       66 if ( $content_length > 0 ) {
643 13 100 100     198 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         24 my $postOrPut = $meth . 'DATA' ; # POSTDATA/PUTDATA
648 6         35 $self->read_postdata_putdata( $postOrPut, $content_length, $ENV{'CONTENT_TYPE'} );
649 6         17 $meth = ''; # to skip xform testing
650 6         15 undef $query_string ;
651             } else {
652 7         39 $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         43 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 78 100       257 if ($DEBUG)
668             {
669 75         306 my $cmdline_ret = read_from_cmdline();
670 75         214 $query_string = $cmdline_ret->{'query_string'};
671 75 50       335 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 134 100 100     1403 if (!$is_xforms && ($meth eq 'POST' || $meth eq 'PUT' || $meth eq 'PATCH')
      100        
      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         25 my($param) = $meth . 'DATA' ;
684 3         17 $self->add_parameter($param) ;
685 3         9 push (@{$self->{param}{$param}},$query_string);
  3         14  
686 3         44 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 134 100 100     761 if (defined $query_string && length $query_string) {
693 39 100       195 if ($query_string =~ /[&=;]/) {
694 34         152 $self->parse_params($query_string);
695             } else {
696 5         15 $self->add_parameter('keywords');
697 5         17 $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 134 50       584 if ($self->param('.defaults')) {
704 0         0 $self->delete_all();
705             }
706              
707             # hash containing our defined fieldnames
708 134         501 $self->{'.fieldnames'} = {};
709 134         497 for ($self->param('.cgifields')) {
710 0         0 $self->{'.fieldnames'}->{$_}++;
711             }
712            
713             # Clear out our default submission button flag if present
714 134         662 $self->delete('.submit');
715 134         421 $self->delete('.cgifields');
716              
717 134 100       657 $self->save_request unless defined $initializer;
718             }
719              
720             sub _get_query_string_from_env {
721 36     36   55 my $self = shift;
722 36         69 my $query_string = '';
723              
724 36 50       114 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     176 if defined $ENV{'QUERY_STRING'};
737              
738 36 100       89 if ( ! $query_string ) {
739             # try to get from REDIRECT_ env variables, support
740             # 5 levels of redirect and no more (RT #36312)
741 16         40 REDIRECT: foreach my $r ( 1 .. 5 ) {
742 60         117 my $key = join( '',( 'REDIRECT_' x $r ) );
743             $query_string ||= $ENV{"${key}QUERY_STRING"}
744 60 100 33     175 if defined $ENV{"${key}QUERY_STRING"};
745 60 100       123 last REDIRECT if $query_string;
746             }
747             }
748              
749 36         88 return $query_string;
750             }
751              
752             # FUNCTIONS TO OVERRIDE:
753             # Turn a string into a filehandle
754             sub to_filehandle {
755 13     13 0 29 my $thingy = shift;
756 13 50       49 return undef unless $thingy;
757 13 100       73 return $thingy if UNIVERSAL::isa($thingy,'GLOB');
758 8 50       37 return $thingy if UNIVERSAL::isa($thingy,'FileHandle');
759 8 100       27 if (!ref($thingy)) {
760 7         13 my $caller = 1;
761 7         35 while (my $package = caller($caller++)) {
762 14 50       74 my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy";
763 14 50       110 return $tmp if defined(fileno($tmp));
764             }
765             }
766 8         23 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 115     115 0 296 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 115         342 @QUERY_PARAM = $self->param; # save list of parameters
794 115         343 for (@QUERY_PARAM) {
795 61 50       144 next unless defined $_;
796 61         242 $QUERY_PARAM{$_}=$self->{param}{$_};
797             }
798 115         336 $QUERY_CHARSET = $self->charset;
799 115         253 %QUERY_FIELDNAMES = %{$self->{'.fieldnames'}};
  115         399  
800 115 100       229 %QUERY_TMPFILES = %{ $self->{'.tmpfiles'} || {} };
  115         1116  
801             }
802              
803             sub parse_params {
804 34     34 0 181 my($self,$tosplit) = @_;
805 34         314 my(@pairs) = split(/[&;]/,$tosplit);
806 34         142 my($param,$value);
807 34         106 for (@pairs) {
808 82         279 ($param,$value) = split('=',$_,2);
809 82 50       203 next unless defined $param;
810 82 50 33     210 next if $NO_UNDEF_PARAMS and not defined $value;
811 82 50       163 $value = '' unless defined $value;
812 82         240 $param = unescape($param);
813 82         193 $value = unescape($value);
814 82         249 $self->add_parameter($param);
815 82         119 push (@{$self->{param}{$param}},$value);
  82         307  
816             }
817             }
818              
819             sub add_parameter {
820 164     164 0 380 my($self,$param)=@_;
821 164 50       490 return unless defined $param;
822 130         418 push (@{$self->{'.parameters'}},$param)
823 164 100       518 unless defined($self->{param}{$param});
824             }
825              
826             sub all_parameters {
827 442     442 0 791 my $self = shift;
828 442 100 66     2045 return () unless defined($self) && $self->{'.parameters'};
829 360 100       581 return () unless @{$self->{'.parameters'}};
  360         1126  
830 196         291 return @{$self->{'.parameters'}};
  196         720  
831             }
832              
833             # put a filehandle into binary mode (DOS)
834             sub binmode {
835 5 50 66 5 0 39 return unless defined($_[1]) && ref ($_[1]) && defined fileno($_[1]);
      66        
836 2         8 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 595 sub compile { 1; }
842              
843             sub _all_html_tags {
844 57     57   1410 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   64470 *$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   1182 *$start_end_function = sub { return _tag_func($start_end_function,@_); };
877             }
878             }
879              
880             sub _tag_func {
881 761     761   1412 my $tagname = shift;
882 761         1537 my ($q,$a,@rest) = self_or_default(@_);
883              
884 761         1564 my($attr) = '';
885              
886 761 100 66     2277 if (ref($a) && ref($a) eq 'HASH') {
887 245         980 my(@attr) = make_attributes($a,$q->{'escape'});
888 245 50       935 $attr = " @attr" if @attr;
889             } else {
890 516 100       1432 unshift @rest,$a if defined $a;
891             }
892              
893 761         1529 $tagname = lc( $tagname );
894              
895 761 100       3148 if ($tagname=~/start_(\w+)/i) {
    100          
896 183         1534 return "<$1$attr>";
897             } elsif ($tagname=~/end_(\w+)/i) {
898 137         1169 return "";
899             } else {
900 441 50       2331 return $XHTML ? "<$tagname$attr />" : "<$tagname$attr>" unless @rest;
    100          
901 253         948 my($tag,$untag) = ("<$tagname$attr>","");
902 255         1014 my @result = map { "$tag$_$untag" }
903 253 100       1201 (ref($rest[0]) eq 'ARRAY') ? @{$rest[0]} : "@rest";
  2         6  
904 253         2056 return "@result";
905             }
906             }
907              
908             sub _selected {
909 29     29   62 my $self = shift;
910 29         67 my $value = shift;
911 29 100       91 return '' unless $value;
912 10 50       47 return $XHTML ? qq(selected="selected" ) : qq(selected );
913             }
914              
915             sub _checked {
916 42     42   102 my $self = shift;
917 42         89 my $value = shift;
918 42 100       124 return '' unless $value;
919 22 100       86 return $XHTML ? qq(checked="checked" ) : qq(checked );
920             }
921              
922 19     19   11290 sub _reset_globals { initialize_globals(); }
923              
924             sub _setup_symbols {
925 57     57   159 my $self = shift;
926              
927             # to avoid reexporting unwanted variables
928 57         146 undef %EXPORT;
929              
930 57         232 for (@_) {
931              
932 92 50       268 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       202 $HEADERS_ONCE++, next if /^[:-]unique_headers$/;
939 92 50       202 $NPH++, next if /^[:-]nph$/;
940 92 50       188 $NOSTICKY++, next if /^[:-]nosticky$/;
941 92 100       230 $DEBUG=0, next if /^[:-]no_?[Dd]ebug$/;
942 88 50       189 $DEBUG=2, next if /^[:-][Dd]ebug$/;
943 88 50       225 $USE_PARAM_SEMICOLONS++, next if /^[:-]newstyle_urls$/;
944 88 100       214 $PUTDATA_UPLOAD++, next if /^[:-](?:putdata_upload|postdata_upload|patchdata_upload)$/;
945 85 50       173 $PARAM_UTF8++, next if /^[:-]utf8$/;
946 85 50       170 $XHTML++, next if /^[:-]xhtml$/;
947 85 100       172 $XHTML=0, next if /^[:-]no_?xhtml$/;
948 84 50       160 $USE_PARAM_SEMICOLONS=0, next if /^[:-]oldstyle_urls$/;
949 84 100       154 $TABINDEX++, next if /^[:-]tabindex$/;
950 83 50       202 $CLOSE_UPLOAD_FILES++, next if /^[:-]close_upload_files$/;
951 83 50       156 $NO_UNDEF_PARAMS++, next if /^[:-]no_undef_params$/;
952            
953 83         171 for (&expand_tags($_)) {
954 2291         3534 tr/a-zA-Z0-9_//cd; # don't allow weird function names
955 2291         4501 $EXPORT{$_}++;
956             }
957             }
958 57         271 @SAVED_SYMBOLS = @_;
959             }
960              
961             sub charset {
962 354     354 0 2251 my ($self,$charset) = self_or_default(@_);
963 354 100       1131 $self->{'.charset'} = $charset if defined $charset;
964 354         903 $self->{'.charset'};
965             }
966              
967             sub element_id {
968 12     12 0 38 my ($self,$new_value) = self_or_default(@_);
969 12 50       63 $self->{'.elid'} = $new_value if defined $new_value;
970 12         70 sprintf('%010d',$self->{'.elid'}++);
971             }
972              
973             sub element_tab {
974 90     90 0 248 my ($self,$new_value) = self_or_default(@_);
975 90   100     396 $self->{'.etab'} ||= 1;
976 90 100       259 $self->{'.etab'} = $new_value if defined $new_value;
977 90         234 my $tab = $self->{'.etab'}++;
978 90 100 100     434 return '' unless $TABINDEX or defined $new_value;
979 39         165 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 26 my ( $self, $postOrPut, $content_length, $content_type ) = @_;
995 6         27 my %header = (
996             "Content-Type" => $content_type,
997             );
998 6         14 my $param = $postOrPut;
999             # add this parameter to our list
1000 6         28 $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       16 if ($DISABLE_UPLOADS) {
  6         23  
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     25 ? ( $ENV{TEMP} || $ENV{TMP} || ( $ENV{WINDIR} ? ( $ENV{WINDIR} . $SL . 'TEMP' ) : undef ) )
1027             : undef; # File::Temp defaults to TMPDIR
1028              
1029 6         646 require CGI::File::Temp;
1030 6         61 my $filehandle = CGI::File::Temp->new(
1031             UNLINK => $UNLINK_TMP_FILES,
1032             DIR => $tmp_dir,
1033             );
1034 6         3836 $filehandle->_mp_filename( $postOrPut );
1035              
1036 6 50 33     29 $CGI::DefaultClass->binmode($filehandle)
1037             if $CGI::needs_binmode
1038             && defined fileno($filehandle);
1039              
1040 6         12 my ($data);
1041 6         32 local ($\) = '';
1042 6         13 my $totalbytes;
1043 6         17 my $unit = $CGI::MultipartBuffer::INITIAL_FILLUNIT;
1044 6         13 my $len = $content_length;
1045 6         12 $unit = $len;
1046 6         12 my $ZERO_LOOP_COUNTER =0;
1047              
1048 6         23 while( $len > 0 )
1049             {
1050            
1051 6         24 my $bytesRead = $self->read_from_client( \$data, $unit, 0 );
1052 6         17 $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       19 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         14 $ZERO_LOOP_COUNTER = 0;
1063             }
1064            
1065 6 100       23 if ( defined $self->{'.upload_hook'} ) {
1066 3         7 $totalbytes += length($data);
1067 3         13 &{ $self->{'.upload_hook'} }( $param, $data, $totalbytes,
1068 3         10 $self->{'.upload_data'} );
1069             }
1070 6 50       79 print $filehandle $data if ( $self->{'use_tempfile'} );
1071 6         28 undef $data;
1072             }
1073              
1074             # back up to beginning of file
1075 6         178 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       27 close $filehandle if $CLOSE_UPLOAD_FILES;
1082 6 50       18 $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         35 $self->{'.tmpfiles'}->{$$filehandle . $filehandle} = {
1091             hndl => $filehandle,
1092             name => $filehandle->filename,
1093             info => {%header},
1094             };
1095 6         22 push( @{ $self->{param}{$param} }, $filehandle );
  6         47  
1096             }
1097 6         24 return;
1098             }
1099              
1100 3     3 0 15 sub URL_ENCODED { 'application/x-www-form-urlencoded'; }
1101              
1102 9     9 0 49 sub MULTIPART { 'multipart/form-data'; }
1103              
1104 6     6 0 19 sub SERVER_PUSH { 'multipart/x-mixed-replace;boundary="' . shift() . '"'; }
1105              
1106             # Create a new multipart buffer
1107             sub new_MultipartBuffer {
1108 3     3 0 9 my($self,$boundary,$length) = @_;
1109 3         23 return CGI::MultipartBuffer->new($self,$boundary,$length);
1110             }
1111              
1112             # Read data from a file handle
1113             sub read_from_client {
1114 53     53 0 139 my($self, $buff, $len, $offset) = @_;
1115 53         206 local $^W=0; # prevent a warning
1116 53 50       433 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 273     273 0 612 my($self,@p) = self_or_default(@_);
1126 273         1259 my(@names) = rearrange([NAME],@p);
1127 273 50       1057 my @to_delete = ref($names[0]) eq 'ARRAY' ? @$names[0] : @names;
1128 273         481 my %to_delete;
1129 273         602 for my $name (@to_delete)
1130             {
1131 273         630 CORE::delete $self->{param}{$name};
1132 273         449 CORE::delete $self->{'.fieldnames'}->{$name};
1133 273         862 $to_delete{$name}++;
1134             }
1135 273         747 @{$self->{'.parameters'}}=grep { !exists($to_delete{$_}) } $self->param();
  273         787  
  210         590  
1136 273         851 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 11 my($self,@values) = self_or_default(@_);
1175             # If values is provided, then we set it.
1176 3 50       14 $self->{param}{'keywords'}=[@values] if @values;
1177 3 50       12 my(@result) = defined($self->{param}{'keywords'}) ? @{$self->{param}{'keywords'}} : ();
  3         13  
1178 3         34 @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 13 my $q = shift;
1185 4         9 my %in;
1186 4         28 tie(%in,CGI,$q);
1187 4 50       17 return %in if wantarray;
1188 4         13 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 5 local(*in);
1195 1 50       5 if (@_) {
1196 1         3 *in = $_[0];
1197             } else {
1198 0         0 my $pkg = caller();
1199 0         0 *in=*{"${pkg}::in"};
  0         0  
1200             }
1201 1         8 tie(%in,CGI);
1202 1         9 return scalar(keys %in);
1203             }
1204              
1205             sub PrintHeader {
1206 1     1 0 5 my($self) = self_or_default(@_);
1207 1         6 return $self->header();
1208             }
1209              
1210             sub HtmlTop {
1211 1     1 0 6 my($self,@p) = self_or_default(@_);
1212 1         8 return $self->start_html(@p);
1213             }
1214              
1215             sub HtmlBot {
1216 1     1 0 5 my($self,@p) = self_or_default(@_);
1217 1         8 return $self->end_html(@p);
1218             }
1219              
1220             sub SplitParam {
1221 1     1 0 5 my ($param) = @_;
1222 1         6 my (@params) = split ("\0", $param);
1223 1 50       16 return (wantarray ? @params : $params[0]);
1224             }
1225              
1226             sub MethGet {
1227 1     1 0 7 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 4 return request_method() eq 'POST';
1236             }
1237              
1238             sub MethPut {
1239 1     1 0 3 return request_method() eq 'PUT';
1240             }
1241              
1242             sub TIEHASH {
1243 5     5   13 my $class = shift;
1244 5         12 my $arg = $_[0];
1245 5 100 66     42 if (ref($arg) && UNIVERSAL::isa($arg,'CGI')) {
1246 4         16 return $arg;
1247             }
1248 1   33     8 return $Q ||= $class->new(@_);
1249             }
1250              
1251             sub STORE {
1252 19     19   587 my $self = shift;
1253 19         39 my $tag = shift;
1254 19         37 my $vals = shift;
1255 19 100 66     123 my @vals = defined($vals) && index($vals,"\0")!=-1 ? split("\0",$vals) : $vals;
1256 19         85 $self->param(-name=>$tag,-value=>\@vals);
1257             }
1258              
1259             sub FETCH {
1260 37 50   37   183 return $_[0] if $_[1] eq 'CGI';
1261 37 100       125 return undef unless defined $_[0]->param($_[1]);
1262 22         65 return join("\0",$_[0]->param($_[1]));
1263             }
1264              
1265             sub FIRSTKEY {
1266 2     2   13 $_[0]->{'.iterator'}=0;
1267 2         15 $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
1268             }
1269              
1270             sub NEXTKEY {
1271 3     3   20 $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
1272             }
1273              
1274             sub EXISTS {
1275 2     2   21 exists $_[0]->{param}{$_[1]};
1276             }
1277              
1278             sub DELETE {
1279 1     1   4 my ($self, $param) = @_;
1280 1         5 my $value = $self->FETCH($param);
1281 1         4 $self->delete($param);
1282 1         6 return $value;
1283             }
1284              
1285             sub CLEAR {
1286 2     2   3 %{$_[0]}=();
  2         22  
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         8 $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 979 my($self,$escape) = self_or_default(@_);
1328 6         25 my $d = $self->{'escape'};
1329 6         17 $self->{'escape'} = $escape;
1330 6         19 $d;
1331             }
1332              
1333             #### Method: version
1334             # Return the current version
1335             ####
1336             sub version {
1337 1     1 0 6 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 1211 my ($self,@p) = self_or_default(@_);
1346 17         37 my $name = shift(@p);
1347 17 50       45 return undef unless exists($ENV{QUERY_STRING});
1348 17 100       33 unless (exists($self->{'.url_param'})) {
1349 15         33 $self->{'.url_param'}={}; # empty hash
1350 15 100       70 if ($ENV{QUERY_STRING} =~ /=/) {
1351 13         74 my(@pairs) = split(/[&;]/,$ENV{QUERY_STRING});
1352 13         24 my($param,$value);
1353 13         25 for (@pairs) {
1354 40         96 ($param,$value) = split('=',$_,2);
1355 40 100       83 next if ! defined($param);
1356 30         61 $param = unescape($param);
1357 30         61 $value = unescape($value);
1358 30         41 push(@{$self->{'.url_param'}->{$param}},$value);
  30         108  
1359             }
1360             } else {
1361 2         6 my @keywords = $self->parse_keywordlist($ENV{QUERY_STRING});
1362 2 100       6 $self->{'.url_param'}{'keywords'} = \@keywords if @keywords;
1363             }
1364             }
1365 17 100       34 return keys %{$self->{'.url_param'}} unless defined($name);
  5         33  
1366 12 50       39 return () unless $self->{'.url_param'}->{$name};
1367 1         6 return wantarray ? @{$self->{'.url_param'}->{$name}}
1368 12 100       64 : $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 17 my($self) = self_or_default(@_);
1378 3         8 my($param,$value,@result);
1379 3 100       8 return '
    ' unless $self->param;
    1380 2         6 push(@result,"
      ");
    1381 2         10 for $param ($self->param) {
    1382 2         9 my($name)=$self->_maybe_escapeHTML($param);
    1383 2         377 push(@result,"
  • $name
  • ");
    1384 2         7 push(@result,"
      ");
    1385 2         9 for $value ($self->param($param)) {
    1386 2         13 $value = $self->_maybe_escapeHTML($value);
    1387 2         124 $value =~ s/\n/
    \n/g;
    1388 2         9 push(@result,"
  • $value
  • ");
    1389             }
    1390 2         5 push(@result,"");
    1391             }
    1392 2         6 push(@result,"");
    1393 2         24 return join("\n",@result);
    1394             }
    1395              
    1396             #### Method as_string
    1397             #
    1398             # synonym for "dump"
    1399             ####
    1400             sub as_string {
    1401 1     1 0 5 &Dump(@_);
    1402             }
    1403              
    1404             #### Method: save
    1405             # Write values out to a filehandle in such a way that they can
    1406             # be reinitialized by the filehandle form of the new() method
    1407             ####
    1408             sub save {
    1409 1     1 0 1230 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         5 local($\) = ''; # set output line separator to a sane value
    1414 1         3 for $param ($self->param) {
    1415 3         7 my($escaped_param) = escape($param);
    1416 3         4 my($value);
    1417 3         5 for $value ($self->param($param)) {
    1418 4 100 100     18 print $filehandle "$escaped_param=",escape("$value"),"\n"
    1419             if length($escaped_param) or length($value);
    1420             }
    1421             }
    1422 1         3 for (keys %{$self->{'.fieldnames'}}) {
      1         3  
    1423 0         0 print $filehandle ".cgifields=",escape("$_"),"\n";
    1424             }
    1425 1         5 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 4388 my($self,@p) = self_or_default(@_);
    1454 6         32 my($boundary,$charset,@other) = rearrange_header([BOUNDARY,CHARSET],@p);
    1455 6 100       18 if (!$boundary) {
    1456 4         10 $boundary = '------- =_';
    1457 4         51 my @chrs = ('0'..'9', 'A'..'Z', 'a'..'z');
    1458 4         13 for (1..17) {
    1459 68         168 $boundary .= $chrs[rand(scalar @chrs)];
    1460             }
    1461             }
    1462              
    1463 6         26 $self->{'separator'} = "$CRLF--$boundary$CRLF";
    1464 6         17 $self->{'final_separator'} = "$CRLF--$boundary--$CRLF";
    1465 6         17 $type = SERVER_PUSH($boundary);
    1466             return $self->header(
    1467             -nph => 0,
    1468             -type => $type,
    1469             -charset => $charset,
    1470 6         30 (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 14 my(@header);
    1482 4         9 my($self,@p) = self_or_default(@_);
    1483 4         15 my($type,$charset,@other) = rearrange([TYPE,CHARSET],@p);
    1484 4   100     35 $type = $type || 'text/html';
    1485 4 100       9 if ($charset) {
    1486 2         6 push(@header,"Content-Type: $type; charset=$charset");
    1487             } else {
    1488 2         5 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         7 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         5 push(@header,@other);
    1499 4         10 my $header = join($CRLF,@header)."${CRLF}${CRLF}";
    1500 4         72 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 15 my($self,@p) = self_or_default(@_);
    1511 6         33 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 7991 my($self,@p) = self_or_default(@_);
    1530 91         209 my(@header);
    1531              
    1532 91 50 66     450 return "" if $self->{'.header_printed'}++ and $HEADERS_ONCE;
    1533              
    1534 91         658 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         326 my @cookie;
    1543 91 100       318 for (ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie) {
      6         18  
    1544 96 100       388 my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_;
    1545 96 100 100     406 push(@cookie,$cs) if defined $cs and $cs ne '';
    1546             }
    1547 91 100       256 $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY';
    1548              
    1549             # CR escaping for values, per RFC 822
    1550 91         250 for my $header ($type,$status,@cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) {
    1551 738 100       1521 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         758 $header =~ s/$CRLF(\s)/$1/g;
    1556              
    1557             # All other uses of newlines are invalid input.
    1558 153 100       1262 if ($header =~ m/$CRLF|\015|\012/) {
    1559             # shorten very long values in the diagnostic
    1560 9 50       32 $header = substr($header,0,72).'...' if (length $header > 72);
    1561 9         118 die "Invalid header value contains a newline not followed by whitespace: $header";
    1562             }
    1563             }
    1564             }
    1565              
    1566 82   66     452 $nph ||= $NPH;
    1567              
    1568 82 100 50     321 $type ||= 'text/html' unless defined($type);
    1569              
    1570             # sets if $charset is given, gets if not
    1571 82         262 $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         229 for (@other) {
    1576             # Don't use \s because of perl bug 21951
    1577 10 50       136 next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/s;
    1578 10         75 ($_ = $header) =~ s/^(\w)(.*)/"\u$1\L$2" . ': '.$self->unescapeHTML($value)/e;
      10         89  
    1579             }
    1580              
    1581 82 100 100     819 $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     475 my $protocol = $ENV{SERVER_PROTOCOL} || 'HTTP/1.0';
    1589 82 100 100     242 push(@header,$protocol . ' ' . ($status || '200 OK')) if $nph;
    1590 82 100       217 push(@header,"Server: " . &server_software()) if $nph;
    1591              
    1592 82 100       247 push(@header,"Status: $status") if $status;
    1593 82 100       196 push(@header,"Window-Target: $target") if $target;
    1594 82 100       210 push(@header,"P3P: policyref=\"/w3c/p3p.xml\", CP=\"$p3p\"") if $p3p;
    1595             # push all the cookies -- there may be several
    1596 82         187 push(@header,map {"Set-Cookie: $_"} @cookie);
      14         58  
    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       234 push(@header,"Expires: " . expires($expires,'http'))
    1601             if $expires;
    1602 82 100 66     513 push(@header,"Date: " . expires(0,'http')) if $expires || $cookie || $nph;
          100        
    1603 82 50       286 push(@header,"Pragma: no-cache") if $self->cache();
    1604 82 100       238 push(@header,"Content-Disposition: attachment; filename=\"$attachment\"") if $attachment;
    1605 82         205 push(@header,map {ucfirst $_} @other);
      10         49  
    1606 82 100       357 push(@header,"Content-Type: $type") if $type ne '';
    1607 82         379 my $header = join($CRLF,@header)."${CRLF}${CRLF}";
    1608 82 50 33     299 if (($MOD_PERL >= 1) && !$nph) {
    1609 0         0 $self->r->send_cgi_header($header);
    1610 0         0 return '';
    1611             }
    1612 82         1006 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 228 my($self,$new_value) = self_or_default(@_);
    1621 82 50       239 $new_value = '' unless $new_value;
    1622 82 50       262 if ($new_value ne '') {
    1623 0         0 $self->{'cache'} = $new_value;
    1624             }
    1625 82         295 return $self->{'cache'};
    1626             }
    1627              
    1628             #### Method: redirect
    1629             # Return a Location: style header
    1630             #
    1631             ####
    1632             sub redirect {
    1633 10     10 0 5567 my($self,@p) = self_or_default(@_);
    1634 10         101 my($url,$target,$status,$cookie,$nph,@other) =
    1635             rearrange([[LOCATION,URI,URL],TARGET,STATUS,['COOKIE','COOKIES','SET-COOKIE'],NPH],@p);
    1636 10 50       89 $status = '302 Found' unless defined $status;
    1637 10   66     44 $url ||= $self->self_url;
    1638 10         24 my(@o);
    1639 10         29 for (@other) { tr/\"//d; push(@o,split("=",$_,2)); }
      4         12  
      4         19  
    1640 10         44 unshift(@o,
    1641             '-Status' => $status,
    1642             '-Location'=> $url,
    1643             '-nph' => $nph);
    1644 10 50       31 unshift(@o,'-Target'=>$target) if $target;
    1645 10         32 unshift(@o,'-Type'=>'');
    1646 10         24 my @unescaped;
    1647 10 100       32 unshift(@unescaped,'-Cookie'=>$cookie) if $cookie;
    1648 10         29 return $self->header((map {$self->unescapeHTML($_)} @o),@unescaped);
      88         232  
    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 3754 my($self,@p) = &self_or_default(@_);
    1672 12         97 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         82 $self->element_id(0);
    1678 12         62 $self->element_tab(0);
    1679              
    1680 12 50       67 $encoding = lc($self->charset) unless defined $encoding;
    1681              
    1682             # Need to sort out the DTD before it's okay to call escapeHTML().
    1683 12         35 my(@result,$xml_dtd);
    1684 12 100       39 if ($dtd) {
    1685 5 50 33     26 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       33 $dtd = $DEFAULT_DTD unless $dtd =~ m|^-//|;
    1689             }
    1690             } else {
    1691 7 50       34 $dtd = $XHTML ? $_XHTML_DTD : $DEFAULT_DTD;
    1692             }
    1693              
    1694 12 100 66     108 $xml_dtd++ if ref($dtd) eq 'ARRAY' && $dtd->[0] =~ /\bXHTML\b/i;
    1695 12 50 66     78 $xml_dtd++ if ref($dtd) eq '' && $dtd =~ /\bXHTML\b/i;
    1696 12 50 66     56 push @result,qq() if $xml_dtd && $declare_xml;
    1697              
    1698 12 100 66     77 if (ref($dtd) && ref($dtd) eq 'ARRAY') {
    1699 7         63 push(@result,qq([0]"\n\t "$dtd->[1]">));
    1700 7         24 $DTD_PUBLIC_IDENTIFIER = $dtd->[0];
    1701             } else {
    1702 5         21 push(@result,qq());
    1703 5         12 $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     82 $title = $self->_maybe_escapeHTML($title || 'Untitled Document');
    1710 12         1249 $author = $self->escape($author);
    1711              
    1712 12 100       109 if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML (2\.0|3\.2|4\.01?)/i) {
    1713 4 50       13 $lang = "" unless defined $lang;
    1714 4         10 $XHTML = 0;
    1715             }
    1716             else {
    1717 8 100       38 $lang = 'en-US' unless defined $lang;
    1718             }
    1719              
    1720 12 50       72 my $lang_bits = $lang ne '' ? qq( lang="$lang" xml:lang="$lang") : '';
    1721 12 100 100     87 my $meta_bits = qq()
          66        
    1722             if $XHTML && $encoding && !$declare_xml;
    1723              
    1724 12 50       73 push(@result,$XHTML ? qq(\n\n$title)
        100          
    1725             : ($lang ? qq() : "")
    1726             . "$title");
    1727 12 50       41 if (defined $author) {
    1728 0 0       0 push(@result,$XHTML ? ""
    1729             : "");
    1730             }
    1731              
    1732 12 50 33     86 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     49 if ($meta && ref($meta) && (ref($meta) eq 'HASH')) {
          66        
    1739 2 50       13 for (sort keys %$meta) { push(@result,$XHTML ? qq()
      11         34  
    1740             : qq()); }
    1741             }
    1742              
    1743 12         27 my $meta_bits_set = 0;
    1744 12 50       32 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       54 push(@result,$self->_style($style)) if defined $style;
    1757 12 100       42 push(@result,$self->_script($script)) if defined $script;
    1758 12 100 66     64 push(@result,$meta_bits) if defined $meta_bits and !$meta_bits_set;
    1759              
    1760             # handle -noscript parameter
    1761 12 50       34 push(@result,<
    1762            
    1763             $noscript
    1764            
    1765             END
    1766             ;
    1767 12 50       45 my($other) = @other ? " @other" : '';
    1768 12         46 push(@result,"\n\n");
    1769 12         169 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   3 my ($self,$style) = @_;
    1777 1         3 my (@result);
    1778              
    1779 1         2 my $type = 'text/css';
    1780 1         2 my $rel = 'stylesheet';
    1781              
    1782              
    1783 1 50       3 my $cdata_start = $XHTML ? "\n\n" : " -->\n";
    1785              
    1786 1 50       4 my @s = ref($style) eq 'ARRAY' ? @$style : $style;
    1787 1         3 my $other = '';
    1788              
    1789 1         2 for my $s (@s) {
    1790 1 50       3 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         2 my $src = $s;
    1824 1 50       56 push(@result,$XHTML ? qq()
    1825             : qq());
    1826             }
    1827             }
    1828 1         33 @result;
    1829             }
    1830              
    1831             sub _script {
    1832 1     1   4 my ($self,$script) = @_;
    1833 1         3 my (@result);
    1834              
    1835 1 50       9 my (@scripts) = ref($script) eq 'ARRAY' ? @$script : ($script);
    1836 1         62 for $script (@scripts) {
    1837 1         35 my($src,$code,$language,$charset);
    1838 1 50       8 if (ref($script)) { # script is a hash
    1839 1 50       16 ($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     11 $type ||= 'text/javascript';
    1844 1 50       11 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         4 my $comment = '//'; # javascript by default
    1853 1 50       10 $comment = '#' if $type=~/perl|tcl/i;
    1854 1 50       5 $comment = "'" if $type=~/vbscript/i;
    1855              
    1856 1         3 my ($cdata_start,$cdata_end);
    1857 1 50       6 if ($XHTML) {
    1858 1         4 $cdata_start = "$comment
    1859 1         5 $cdata_end .= "\n$comment]]>";
    1860             } else {
    1861 0         0 $cdata_start = "\n\n";
    1864             }
    1865 1         3 my(@satts);
    1866 1 50       5 push(@satts,'src'=>$src) if $src;
    1867 1         4 push(@satts,'type'=>$type);
    1868 1 50 33     10 push(@satts,'charset'=>$charset) if ($src && $charset);
    1869 1 50       5 $code = $cdata_start . $code . $cdata_end if defined $code;
    1870 1   50     12 push(@result,$self->script({@satts},$code || ''));
    1871             }
    1872 1         5 @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 25 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 199 my($self,@p) = self_or_default(@_);
    1909              
    1910 12         63 my($method,$action,$enctype,@other) =
    1911             rearrange([METHOD,ACTION,ENCTYPE],@p);
    1912              
    1913 12   100     101 $method = $self->_maybe_escapeHTML(lc($method || 'post'));
    1914              
    1915 12 100       860 if( $XHTML ){
    1916 7   66     63 $enctype = $self->_maybe_escapeHTML($enctype || &MULTIPART);
    1917             }else{
    1918 5   66     27 $enctype = $self->_maybe_escapeHTML($enctype || &URL_ENCODED);
    1919             }
    1920              
    1921 12 50       644 if (defined $action) {
    1922 12         43 $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         586 $action = qq(action="$action");
    1928 12 100       53 my($other) = @other ? " @other" : '';
    1929 12         41 $self->{'.parametersToAdd'}={};
    1930 12         104 return qq/
    /;
    1931             }
    1932              
    1933             #### Method: start_multipart_form
    1934             sub start_multipart_form {
    1935 4     4 0 17 my($self,@p) = self_or_default(@_);
    1936 4 50 33     34 if (defined($p[0]) && substr($p[0],0,1) eq '-') {
    1937 0         0 return $self->start_form(-enctype=>&MULTIPART,@p);
    1938             } else {
    1939 4         24 my($method,$action,@other) =
    1940             rearrange([METHOD,ACTION],@p);
    1941 4         15 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 74 my($self,@p) = self_or_default(@_);
    1950 1 50       3 if ( $NOSTICKY ) {
    1951 0 0       0 return wantarray ? ("") : "\n";
    1952             } else {
    1953 1 50       4 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   64 my($self,$tag,@p) = self_or_default(@_);
    1970 8         59 my($name,$default,$size,$maxlength,$override,$tabindex,@other) =
    1971             rearrange([NAME,[DEFAULT,VALUE,VALUES],SIZE,MAXLENGTH,[OVERRIDE,FORCE],TABINDEX],@p);
    1972              
    1973 8 100       52 my $current = $override ? $default :
        100          
    1974             (defined($self->param($name)) ? $self->param($name) : $default);
    1975              
    1976 8 50       37 $current = defined($current) ? $self->_maybe_escapeHTML($current,1) : '';
    1977 8 100       362 $name = defined($name) ? $self->_maybe_escapeHTML($name) : '';
    1978 8 50       310 my($s) = defined($size) ? qq/ size="$size"/ : '';
    1979 8 50       31 my($m) = defined($maxlength) ? qq/ maxlength="$maxlength"/ : '';
    1980 8 100       31 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       41 my($value) = $current ne '' ? qq(value="$current") : '';
    1984 8         28 $tabindex = $self->element_tab($tabindex);
    1985 8 50       88 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 37 my($self,@p) = self_or_default(@_);
    2001 7         34 $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 7 my ($self,@p) = self_or_default(@_);
    2030 1         6 $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 11 my($self,@p) = self_or_default(@_);
    2045 2         25 my($name,$default,$rows,$cols,$override,$tabindex,@other) =
    2046             rearrange([NAME,[DEFAULT,VALUE],ROWS,[COLS,COLUMNS],[OVERRIDE,FORCE],TABINDEX],@p);
    2047              
    2048 2 50       18 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       54 $current = defined($current) ? $self->_maybe_escapeHTML($current) : '';
    2053 2 50       43 my($r) = $rows ? qq/ rows="$rows"/ : '';
    2054 2 50       14 my($c) = $cols ? qq/ cols="$cols"/ : '';
    2055 2 100       12 my($other) = @other ? " @other" : '';
    2056 2         10 $tabindex = $self->element_tab($tabindex);
    2057 2         27 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 1786 my($self,@p) = self_or_default(@_);
    2072              
    2073 4         33 my($label,$value,$script,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL],
    2074             [ONCLICK,SCRIPT],TABINDEX],@p);
    2075              
    2076 4         25 $label=$self->_maybe_escapeHTML($label);
    2077 4         396 $value=$self->_maybe_escapeHTML($value,1);
    2078 4         14 $script=$self->_maybe_escapeHTML($script);
    2079              
    2080 4   100     23 $script ||= '';
    2081              
    2082 4         12 my($name) = '';
    2083 4 100       18 $name = qq/ name="$label"/ if $label;
    2084 4   66     22 $value = $value || $label;
    2085 4         11 my($val) = '';
    2086 4 100       16 $val = qq/ value="$value"/ if $value;
    2087 4 100       14 $script = qq/ onclick="$script"/ if $script;
    2088 4 100       17 my($other) = @other ? " @other" : '';
    2089 4         18 $tabindex = $self->element_tab($tabindex);
    2090 4 50       43 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 657 my($self,@p) = self_or_default(@_);
    2105              
    2106 7         45 my($label,$value,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL],TABINDEX],@p);
    2107              
    2108 7         35 $label=$self->_maybe_escapeHTML($label);
    2109 7         427 $value=$self->_maybe_escapeHTML($value,1);
    2110              
    2111 7 50       601 my $name = $NOSTICKY ? '' : 'name=".submit" ';
    2112 7 100       32 $name = qq/name="$label" / if defined($label);
    2113 7 100       33 $value = defined($value) ? $value : $label;
    2114 7         18 my $val = '';
    2115 7 100       25 $val = qq/value="$value" / if defined($value);
    2116 7         33 $tabindex = $self->element_tab($tabindex);
    2117 7 100       34 my($other) = @other ? "@other " : '';
    2118 7 50       71 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 37 my($self,@p) = self_or_default(@_);
    2192              
    2193 9         67 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       47 $value = defined $value ? $value : 'on';
    2198              
    2199 9 100 66     70 if (!$override && ($self->{'.fieldnames'}->{$name} ||
          100        
    2200             defined $self->param($name))) {
    2201 6 100       18 $checked = grep($_ eq $value,$self->param($name)) ? $self->_checked(1) : '';
    2202             } else {
    2203 3         20 $checked = $self->_checked($checked);
    2204             }
    2205 9 100       39 my($the_label) = defined $label ? $label : $name;
    2206 9         34 $name = $self->_maybe_escapeHTML($name);
    2207 9         410 $value = $self->_maybe_escapeHTML($value,1);
    2208 9         378 $the_label = $self->_maybe_escapeHTML($the_label);
    2209 9 100       398 my($other) = @other ? "@other " : '';
    2210 9         36 $tabindex = $self->element_tab($tabindex);
    2211 9         39 $self->register_parameter($name);
    2212 9 50       67 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 6562 require HTML::Entities;
    2220             # hack to work around earlier hacks
    2221 251 100 100     75623 push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
    2222 251         567 my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_);
    2223 251 50       720 return undef unless defined($toencode);
    2224 251         502 my $encode_entities = $ENCODE_ENTITIES;
    2225 251 100 100     972 $encode_entities .= "\012\015" if ( $encode_entities && $newlinestoo );
    2226 251         810 return HTML::Entities::encode_entities($toencode,$encode_entities);
    2227             }
    2228              
    2229             # unescape HTML -- used internally
    2230             sub unescapeHTML {
    2231 105     105 0 2434 require HTML::Entities;
    2232             # hack to work around earlier hacks
    2233 105 50 66     23428 push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
    2234 105         234 my ($self,$string) = CGI::self_or_default(@_);
    2235 105 100       316 return undef unless defined($string);
    2236 95         575 return HTML::Entities::decode_entities($string);
    2237             }
    2238              
    2239             # Internal procedure - don't use
    2240             sub _tableize {
    2241 1     1   6 my($rows,$columns,$rowheaders,$colheaders,@elements) = @_;
    2242 1 50       6 my @rowheaders = $rowheaders ? @$rowheaders : ();
    2243 1 50       5 my @colheaders = $colheaders ? @$colheaders : ();
    2244 1         4 my($result);
    2245              
    2246 1 50       8 if (defined($columns)) {
    2247 1 50       7 $rows = int(0.99 + @elements/$columns) unless defined($rows);
    2248             }
    2249 1 50       5 if (defined($rows)) {
    2250 1 50       5 $columns = int(0.99 + @elements/$rows) unless defined($columns);
    2251             }
    2252              
    2253             # rearrange into a pretty table
    2254 1         4 $result = ""; " if @colheaders; "; "; " if @rowheaders; " ";
    2255 1         2 my($row,$column);
    2256 1 50 33     6 unshift(@colheaders,'') if @colheaders && @rowheaders;
    2257 1 50       6 $result .= "
    2258 1         4 for (@colheaders) {
    2259 0         0 $result .= "$_
    2260             }
    2261 1         7 for ($row=0;$row<$rows;$row++) {
    2262 2         7 $result .= "
    2263 2 50       8 $result .= "$rowheaders[$row]
    2264 2         8 for ($column=0;$column<$columns;$column++) {
    2265 4 50       25 $result .= "" . $elements[$column*$rows + $row] . "
    2266             if defined($elements[$column*$rows + $row]);
    2267             }
    2268 2         15 $result .= "
    2269             }
    2270 1         3 $result .= "
    ";
    2271 1         15 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 22 my($self,@p) = self_or_default(@_);
    2293 5         31 $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 177 my($self,@p) = self_or_default(@_);
    2320 8         51 $self->_box_group('checkbox',@p);
    2321             }
    2322              
    2323             sub _box_group {
    2324 13     13   34 my $self = shift;
    2325 13         33 my $box_type = shift;
    2326              
    2327 13         150 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         68 my($result,$checked,@elements,@values);
    2337              
    2338 13         91 @values = $self->_set_values_and_labels($values,\$labels,$name);
    2339 13         64 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     89 $checked{$values[0]}++ if $box_type eq 'radio' && !%checked;
    2343              
    2344 13         64 $name=$self->_maybe_escapeHTML($name);
    2345              
    2346 13         761 my %tabs = ();
    2347 13 50 66     74 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       54 %tabs = map {$_=>$self->element_tab} @values unless %tabs;
      37         115  
    2357 13 100       122 my $other = @other ? "@other " : '';
    2358 13         60 my $radio_checked;
    2359              
    2360             # for disabling groups of radio/checkbox buttons
    2361             my %disabled;
    2362 13         28 for (@{$disabled}) {
      13         49  
    2363 1         5 $disabled{$_}=1;
    2364             }
    2365              
    2366 13         36 for (@values) {
    2367 37         84 my $disable="";
    2368 37 100       103 if ($disabled{$_}) {
    2369 1         2 $disable="disabled='1'";
    2370             }
    2371              
    2372             my $checkit = $self->_checked($box_type eq 'radio' ? ($checked{$_} && !$radio_checked++)
    2373 37 100 100     224 : $checked{$_});
    2374 37         84 my($break);
    2375 37 100       91 if ($linebreak) {
    2376 4 50       13 $break = $XHTML ? "
    " : "
    ";
    2377             }
    2378             else {
    2379 33         61 $break = '';
    2380             }
    2381 37         76 my($label)='';
    2382 37 50 33     109 unless (defined($nolabels) && $nolabels) {
    2383 37         67 $label = $_;
    2384 37 100 100     173 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2385 37         135 $label = $self->_maybe_escapeHTML($label,1);
    2386 37 100       1531 $label = "$label" if $disabled{$_};
    2387             }
    2388 37         121 my $attribs = $self->_set_attributes($_, $attributes);
    2389 37         87 my $tab = $tabs{$_};
    2390 37         93 $_=$self->_maybe_escapeHTML($_);
    2391              
    2392 37 100       1325 if ($XHTML) {
    2393 34         201 push @elements,
    2394             CGI::label($labelattributes,
    2395             qq($label)).${break};
    2396             } else {
    2397 3         16 push(@elements,qq/${label}${break}/);
    2398             }
    2399             }
    2400 13         71 $self->register_parameter($name);
    2401 13 50 66     237 return wantarray ? @elements : "@elements"
        100          
    2402             unless defined($columns) || defined($rows);
    2403 1         7 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 1065 my($self,@p) = self_or_default(@_);
    2422              
    2423 8         80 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         40 my($result,%selected);
    2427              
    2428 8 50 66     64 if (!$override && defined($self->param($name))) {
        100          
    2429 0         0 $selected{$self->param($name)}++;
    2430             } elsif (defined $default) {
    2431 7 50       36 %selected = map {$_=>1} ref($default) eq 'ARRAY'
      7         48  
    2432             ? @$default
    2433             : $default;
    2434             }
    2435 8         38 $name=$self->_maybe_escapeHTML($name);
    2436             # RT #30057 - ignore -multiple, if you need this
    2437             # then use scrolling_list
    2438 8         506 @other = grep { $_ !~ /^multiple=/i } @other;
      3         26  
    2439 8 100       49 my($other) = @other ? " @other" : '';
    2440              
    2441 8         20 my(@values);
    2442 8         40 @values = $self->_set_values_and_labels($values,\$labels,$name);
    2443 8         42 $tabindex = $self->element_tab($tabindex);
    2444 8 100       36 $name = q{} if ! defined $name;
    2445 8         44 $result = qq/
    2446 8         25 for (@values) {
    2447 22 100       79 if (/
    2448 3         20 for my $v (split(/\n/)) {
    2449 11 50       45 my $selectit = $XHTML ? 'selected="selected"' : 'selected';
    2450 11         34 for my $selected (keys %selected) {
    2451 11         107 $v =~ s/(value="\Q$selected\E")/$selectit $1/;
    2452             }
    2453 11         45 $result .= "$v\n";
    2454             }
    2455             }
    2456             else {
    2457 19         67 my $attribs = $self->_set_attributes($_, $attributes);
    2458 19         104 my($selectit) = $self->_selected($selected{$_});
    2459 19         56 my($label) = $_;
    2460 19 100 66     85 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2461 19         81 my($value) = $self->_maybe_escapeHTML($_);
    2462 19         718 $label = $self->_maybe_escapeHTML($label,1);
    2463 19         1028 $result .= "$label\n";
    2464             }
    2465             }
    2466              
    2467 8         29 $result .= "";
    2468 8         94 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 19 my($self,@p) = self_or_default(@_);
    2495 3         29 my($name,$values,$attributes,$labeled,$noval,$labels,@other)
    2496             = rearrange([NAME,[VALUES,VALUE],ATTRIBUTES,LABELED,NOVALS,LABELS],@p);
    2497              
    2498 3         16 my($result,@values);
    2499 3         23 @values = $self->_set_values_and_labels($values,\$labels,$name,$labeled,$novals);
    2500 3 100       22 my($other) = @other ? " @other" : '';
    2501              
    2502 3   100     17 $name = $self->_maybe_escapeHTML($name) || q{};
    2503 3         81 $result = qq/\n/;
    2504 3         11 for (@values) {
    2505 5 50       21 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         23 my $attribs = $self->_set_attributes($_, $attributes);
    2514 5         15 my($label) = $_;
    2515 5 50 33     26 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2516 5         17 $label=$self->_maybe_escapeHTML($label);
    2517 5         196 my($value)=$self->_maybe_escapeHTML($_,1);
    2518 5 0       215 $result .= $labeled ? $novals ? "$label\n"
        50          
        50          
    2519             : "$label\n"
    2520             : $novals ? "$label\n"
    2521             : "$label\n";
    2522             }
    2523             }
    2524 3         14 $result .= "";
    2525 3         44 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 17 my($self,@p) = self_or_default(@_);
    2550 3         38 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         16 my($result,@values);
    2555 3         21 @values = $self->_set_values_and_labels($values,\$labels,$name);
    2556              
    2557 3   100     19 $size = $size || scalar(@values);
    2558              
    2559 3         76 my(%selected) = $self->previous_or_default($name,$defaults,$override);
    2560              
    2561 3 100       22 my($is_multiple) = $multiple ? qq/ multiple="multiple"/ : '';
    2562 3 50       17 my($has_size) = $size ? qq/ size="$size"/: '';
    2563 3 100       14 my($other) = @other ? " @other" : '';
    2564              
    2565 3         15 $name=$self->_maybe_escapeHTML($name);
    2566 3         133 $tabindex = $self->element_tab($tabindex);
    2567 3         16 $result = qq/
    2568 3         11 for (@values) {
    2569 11 100       41 if (/
    2570 1         7 for my $v (split(/\n/)) {
    2571 4 50       14 my $selectit = $XHTML ? 'selected="selected"' : 'selected';
    2572 4         9 for my $selected (keys %selected) {
    2573 4         33 $v =~ s/(value="$selected")/$selectit $1/;
    2574             }
    2575 4         15 $result .= "$v\n";
    2576             }
    2577             }
    2578             else {
    2579 10         31 my $attribs = $self->_set_attributes($_, $attributes);
    2580 10         41 my($selectit) = $self->_selected($selected{$_});
    2581 10         23 my($label) = $_;
    2582 10 100 66     37 $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
    2583 10         25 my($value) = $self->_maybe_escapeHTML($_);
    2584 10         372 $label = $self->_maybe_escapeHTML($label,1);
    2585 10         353 $result .= "$label\n";
    2586             }
    2587             }
    2588              
    2589 3         8 $result .= "";
    2590 3         24 $self->register_parameter($name);
    2591 3         28 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 53 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         24 my(@result,@value);
    2609 7         74 my($name,$default,$override,@other) =
    2610             rearrange([NAME,[DEFAULT,VALUE,VALUES],[OVERRIDE,FORCE]],@p);
    2611              
    2612 7         31 my $do_override = 0;
    2613 7 100 66     64 if ( ref($p[0]) || substr($p[0],0,1) eq '-') {
    2614 5 100       23 @value = ref($default) ? @{$default} : $default;
      4         16  
    2615 5         14 $do_override = $override;
    2616             } else {
    2617 2         14 for ($default,$override,@other) {
    2618 6 100       23 push(@value,$_) if defined($_);
    2619             }
    2620 2         9 undef @other;
    2621             }
    2622              
    2623             # use previous values if override is not set
    2624 7         43 my @prev = $self->param($name);
    2625 7 50 66     46 @value = @prev if !$do_override && @prev;
    2626              
    2627 7         44 $name=$self->_maybe_escapeHTML($name);
    2628 7         846 for (@value) {
    2629 18 50       88 $_ = defined($_) ? $self->_maybe_escapeHTML($_,1) : '';
    2630 18 50       1348 push @result,$XHTML ? qq()
    2631             : qq();
    2632             }
    2633 7 100       102 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 4 my($self,@p) = self_or_default(@_);
    2646              
    2647 1         6 my($name,$src,$alignment,@other) =
    2648             rearrange([NAME,SRC,ALIGN],@p);
    2649              
    2650 1 50       7 my($align) = $alignment ? " align=\L\"$alignment\"" : '';
    2651 1 50       6 my($other) = @other ? " @other" : '';
    2652 1         4 $name=$self->_maybe_escapeHTML($name);
    2653 1 50       8 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 33 my($self,@p) = self_or_default(@_);
    2665 7         38 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 14 &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 45     45 1 164 my($self,@p) = self_or_default(@_);
    2680 45         279 my ($relative,$absolute,$full,$path_info,$query,$base,$rewrite) =
    2681             rearrange(['RELATIVE','ABSOLUTE','FULL',['PATH','PATH_INFO'],['QUERY','QUERY_STRING'],'BASE','REWRITE'],@p);
    2682 45         161 my $url = '';
    2683 45 100 100     291 $full++ if $base || !($relative || $absolute);
          66        
    2684 45 100       130 $rewrite++ unless defined $rewrite;
    2685              
    2686 45         148 my $path = $self->path_info;
    2687 45         143 my $script_name = $self->script_name;
    2688 45   100     119 my $request_uri = $self->request_uri || '';
    2689 45 100       146 my $query_str = $query ? $self->query_string : '';
    2690              
    2691 45         115 $script_name =~ s/\?.*$//s; # remove query string
    2692 45         111 $request_uri =~ s/\?.*$//s; # remove query string
    2693 45         136 $request_uri = unescape($request_uri);
    2694              
    2695 45 100 100     196 my $uri = $rewrite && $request_uri ? $request_uri : $script_name;
    2696              
    2697 45 100       148 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 39 100 66     429 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 39 100       108 if ( ! $IIS ) {
    2708 37         177 $uri =~ s/\Q$ENV{PATH_INFO}\E$//;
    2709             }
    2710             }
    2711              
    2712 45 100       141 if ($full) {
        100          
        50          
    2713 27         87 my $protocol = $self->protocol();
    2714 27         80 $url = "$protocol://";
    2715 27   100     73 my $vh = http('x_forwarded_host') || http('host') || '';
    2716 27         86 $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         83 $vh =~ s/\:\d+$//; # some clients add the port number (incorrectly). Get rid of it.
    2719              
    2720 27   66     124 $url .= $vh || server_name();
    2721              
    2722 27         111 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     225 $url .= ':' . $port unless (lc($protocol) eq 'http' && $port == 80)
          33        
          66        
    2726             or (lc($protocol) eq 'https' && $port == 443);
    2727              
    2728 27 50       84 return $url if $base;
    2729              
    2730 27         76 $url .= $uri;
    2731             } elsif ($relative) {
    2732 12         171 ($url) = $uri =~ m!([^/]+)$!;
    2733             } elsif ($absolute) {
    2734 6         19 $url = $uri;
    2735             }
    2736              
    2737 45 100 66     239 $url .= $path if $path_info and defined $path;
    2738 45 100 100     164 $url .= "?$query_str" if $query and $query_str ne '';
    2739 45   50     110 $url ||= '';
    2740 45         147 $url =~ s/([^a-zA-Z0-9_.%;&?\/\\:+=~-])/sprintf("%%%02X",ord($1))/eg;
      0         0  
    2741 45         293 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 1000 my($self,@p) = self_or_default(@_);
    2758 2         22 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         662 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       11 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     18 return undef unless defined($name) && $name ne ''; # this is an error
    2778              
    2779 2         5 my @param;
    2780 2         8 push(@param,'-name'=>$name);
    2781 2         7 push(@param,'-value'=>$value);
    2782 2 50       7 push(@param,'-domain'=>$domain) if $domain;
    2783 2 50       11 push(@param,'-path'=>$path) if $path;
    2784 2 50       8 push(@param,'-expires'=>$expires) if $expires;
    2785 2 50       8 push(@param,'-secure'=>$secure) if $secure;
    2786 2 50       7 push(@param,'-httponly'=>$httponly) if $httponly;
    2787 2 50       8 push(@param,'-max_age'=>$max_age) if $max_age;
    2788 2 50       8 push(@param,'-samesite'=>$samesite) if $samesite;
    2789              
    2790 2         13 return CGI::Cookie->new(@param);
    2791             }
    2792              
    2793             sub parse_keywordlist {
    2794 7     7 0 16 my($self,$tosplit) = @_;
    2795 7         15 $tosplit = unescape($tosplit); # unescape the keywords
    2796 7         12 $tosplit=~tr/+/ /; # pluses to spaces
    2797 7         41 my(@keywords) = split(/\s+/,$tosplit);
    2798 7         33 return @keywords;
    2799             }
    2800              
    2801             sub param_fetch {
    2802 9     9 0 38 my($self,@p) = self_or_default(@_);
    2803 9         41 my($name) = rearrange([NAME],@p);
    2804 9 100       33 return [] unless defined $name;
    2805              
    2806 8 50       24 unless (exists($self->{param}{$name})) {
    2807 0         0 $self->add_parameter($name);
    2808 0         0 $self->{param}{$name} = [];
    2809             }
    2810            
    2811 8         55 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 46     46 1 115 my ($self,$info) = self_or_default(@_);
    2824 46 50       188 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 11         47 my (undef,$path_info) = $self->_name_and_path_from_env;
    2829 11   100     128 $self->{'.path_info'} = $path_info || '';
    2830             }
    2831 46         137 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 22     22   46 my $self = shift;
    2864 22   100     94 my $script_name = $ENV{SCRIPT_NAME} || '';
    2865 22   100     87 my $path_info = $ENV{PATH_INFO} || '';
    2866 22   100     76 my $uri = $self->request_uri || '';
    2867              
    2868 22         74 $uri =~ s/\?.*//s;
    2869 22         86 $uri = unescape($uri);
    2870              
    2871 22 100       109 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 4         69 $path_info =~ s/^\Q$script_name\E(.*)/$1/;
    2877             } elsif ($uri ne "$script_name$path_info") {
    2878 8         34 my $script_name_pattern = quotemeta($script_name);
    2879 8         21 my $path_info_pattern = quotemeta($path_info);
    2880 8         72 $script_name_pattern =~ s{(?:\\/)+}{/+}g;
    2881 8         46 $path_info_pattern =~ s{(?:\\/)+}{/+}g;
    2882              
    2883 8 50       166 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 22         105 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 1455 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 67 100   67 1 382 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 100 my($self) = self_or_default(@_);
    2928 29         58 my($param,$value,@pairs);
    2929 29         86 for $param ($self->param) {
    2930 61         145 my($eparam) = escape($param);
    2931 61         131 for $value ($self->param($param)) {
    2932 79         159 $value = escape($value);
    2933 79 100       150 next unless defined $value;
    2934 72         199 push(@pairs,"$eparam=$value");
    2935             }
    2936             }
    2937 29         52 for (keys %{$self->{'.fieldnames'}}) {
      29         111  
    2938 0         0 push(@pairs,".cgifields=".escape("$_"));
    2939             }
    2940 29 50       164 return join($USE_PARAM_SEMICOLONS ? ';' : '&',@pairs);
    2941             }
    2942              
    2943             sub env_query_string {
    2944 1 50   1 1 8 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 56 my($self,$match)=self_or_CGI(@_);
    3000 7         31 my $user_agent = $self->http('user_agent');
    3001 7 100 66     59 return $user_agent unless defined $match && $match && $user_agent;
          100        
    3002 4         111 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 49     49 1 115 my ($self,@p) = self_or_default(@_);
    3065 49 50       188 if (@p) {
        100          
    3066 0         0 $self->{'.script_name'} = shift @p;
    3067             } elsif (!exists $self->{'.script_name'}) {
    3068 11         46 my ($script_name,$path_info) = $self->_name_and_path_from_env();
    3069 11         49 $self->{'.script_name'} = $script_name;
    3070             }
    3071 49         129 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 81 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 40 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 208 my($self) = self_or_default(@_);
    3102 28   100     104 my $vh = $self->http('x_forwarded_host') || $self->http('host');
    3103 28         91 my $protocol = $self->protocol;
    3104 28 100       85 if ($vh) {
    3105 17   66     141 return ($vh =~ /:(\d+)$/)[0] || ($protocol eq 'https' ? 443 : 80);
    3106             } else {
    3107 11         34 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 364 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 285 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 2002 my ($self,$parameter) = self_or_CGI(@_);
    3131 118 100       382 if ( defined($parameter) ) {
    3132 116         234 $parameter =~ tr/-a-z/_A-Z/;
    3133 116 100       353 if ( $parameter =~ /^HTTP(?:_|$)/ ) {
    3134 1         7 return $ENV{$parameter};
    3135             }
    3136 115         662 return $ENV{"HTTP_$parameter"};
    3137             }
    3138 2         25 return grep { /^HTTP(?:_|$)/ } keys %ENV;
      67         154  
    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 2427 my ($self,$parameter) = self_or_CGI(@_);
    3148 58 50       177 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 35         78 ? grep { /^HTTPS(?:_|$)/ } keys %ENV
    3157 58 100       293 : $ENV{'HTTPS'};
    3158             }
    3159              
    3160             #### Method: protocol
    3161             # Return the protocol (http or https currently)
    3162             ####
    3163             sub protocol {
    3164 55     55 0 220 local($^W)=0;
    3165 55         113 my $self = shift;
    3166 55 50       143 return 'https' if uc($self->https()) eq 'ON';
    3167 55 50       186 return 'https' if $self->server_port == 443;
    3168 55         151 my $prot = $self->server_protocol;
    3169 55         234 my($protocol,$version) = split('/',$prot);
    3170 55         256 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       4 $CGI::NOSTICKY = $param if defined($param);
    3211 1         5 return $CGI::NOSTICKY;
    3212             }
    3213              
    3214             #### Method: nph
    3215             # Set or return the NPH global flag
    3216             ####
    3217             sub nph {
    3218 1     1 1 4 my ($self,$param) = self_or_CGI(@_);
    3219 1 50       4 $CGI::NPH = $param if defined($param);
    3220 1         4 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 24 warn "private_tempfiles has been deprecated";
    3228 1         5 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 4 my ($self,$param) = self_or_CGI(@_);
    3235 1 50       5 $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 5 my ($self,$param,$param2) = self_or_CGI(@_);
    3244 1 50 33     10 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         11 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   1017 push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
    3256 318         723 my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_);
    3257 318 100       833 return undef unless defined($toencode);
    3258 304 100 66     1420 return $toencode if ref($self) && !$self->{'escape'};
    3259 244         750 return $self->escapeHTML($toencode, $newlinestoo);
    3260             }
    3261              
    3262             sub previous_or_default {
    3263 16     16 0 60 my($self,$name,$defaults,$override) = @_;
    3264 16         36 my(%selected);
    3265              
    3266 16 100 66     201 if (!$override && ($self->{'.fieldnames'}->{$name} ||
        100 100        
          100        
          66        
    3267             defined($self->param($name)) ) ) {
    3268 7         26 $selected{$_}++ for $self->param($name);
    3269             } elsif (defined($defaults) && ref($defaults) &&
    3270             (ref($defaults) eq 'ARRAY')) {
    3271 6         22 $selected{$_}++ for @{$defaults};
      6         39  
    3272             } else {
    3273 3 100       21 $selected{$defaults}++ if defined($defaults);
    3274             }
    3275              
    3276 16         98 return %selected;
    3277             }
    3278              
    3279             sub register_parameter {
    3280 25     25 0 67 my($self,$param) = @_;
    3281 25         89 $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         2 '-values'=>[keys %{$self->{'.parametersToAdd'}}],
      1         6  
    3288             '-override'=>1);
    3289             }
    3290              
    3291             sub read_from_cmdline {
    3292 75     75 0 311 my($input,@words);
    3293 75         0 my($query_string);
    3294 75         0 my($subpath);
    3295 75 50 33     498 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 75         227 for (@words) {
    3305 0         0 s/\\=/%3D/g;
    3306 0         0 s/\\&/%26/g;
    3307             }
    3308              
    3309 75 50       312 if ("@words"=~/=/) {
    3310 0         0 $query_string = join('&',@words);
    3311             } else {
    3312 75         202 $query_string = join('+',@words);
    3313             }
    3314 75 50       291 if ($query_string =~ /^(.*?)\?(.*)$/)
    3315             {
    3316 0         0 $query_string = $2;
    3317 0         0 $subpath = $1;
    3318             }
    3319 75         394 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 7 my($self,$boundary,$length) = @_;
    3332 2         9 my($buffer) = $self->new_MultipartBuffer($boundary,$length);
    3333 2 50       7 return unless $buffer;
    3334 2         4 my(%header,$body);
    3335 2         3 my $filenumber = 0;
    3336 2         6 while (!$buffer->eof) {
    3337 10         37 %header = $buffer->readHeader;
    3338              
    3339 10 50       35 unless (%header) {
    3340 0         0 $self->cgi_error("400 Bad request (malformed multipart POST)");
    3341 0         0 return;
    3342             }
    3343              
    3344 10   50     28 $header{'Content-Disposition'} ||= ''; # quench uninit variable warning
    3345              
    3346 10         63 my($param)= $header{'Content-Disposition'}=~/[\s;]name="([^"]*)"/;
    3347 10         29 $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         53 my ($filename) = $header{'Content-Disposition'}
    3353             =~/ filename=(("[^"]*")|([a-z\d!\#'\*\+,\.^_\`\{\}\|\~]*))/i;
    3354              
    3355 10   50     35 $filename ||= ''; # quench uninit variable warning
    3356              
    3357 10         53 $filename =~ s/^"([^"]*)"$/$1/;
    3358             # Test for Opera's multiple upload feature
    3359             my($multipart) = ( defined( $header{'Content-Type'} ) &&
    3360 10 50 33     65 $header{'Content-Type'} =~ /multipart\/mixed/ ) ?
    3361             1 : 0;
    3362              
    3363             # add this parameter to our list
    3364 10         44 $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     54 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       18 if ($DISABLE_UPLOADS) {
      10         28  
    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     57 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     31 ? ( $ENV{TEMP} || $ENV{TMP} || ( $ENV{WINDIR} ? ( $ENV{WINDIR} . $SL . 'TEMP' ) : undef ) )
    3393             : undef; # File::Temp defaults to TMPDIR
    3394              
    3395 10         804 require CGI::File::Temp;
    3396 10         58 my $filehandle = CGI::File::Temp->new(
    3397             UNLINK => $UNLINK_TMP_FILES,
    3398             DIR => $tmp_dir,
    3399             );
    3400 10         4754 $filehandle->_mp_filename( $filename );
    3401              
    3402 10 50 33     38 $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       26 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         17 my ($data);
    3416 10         44 local($\) = '';
    3417 10         19 my $totalbytes = 0;
    3418 10         39 while (defined($data = $buffer->read)) {
    3419 10 50       32 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       119 print $filehandle $data if ($self->{'use_tempfile'});
    3425             }
    3426              
    3427             # back up to beginning of file
    3428 10         231 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       41 close $filehandle if $CLOSE_UPLOAD_FILES;
    3435 10 50       26 $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         59 $self->{'.tmpfiles'}->{$$filehandle . $filehandle} = {
    3444             hndl => $filehandle,
    3445             name => $filehandle->filename,
    3446             info => {%header},
    3447             };
    3448 10         26 push(@{$self->{param}{$param}},$filehandle);
      10         73  
    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 4 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         2 my $filenumber = 0;
    3468 1         1 my $returnvalue;
    3469 1         2 while (!$buffer->eof) {
    3470 2         8 %header = $buffer->readHeader;
    3471              
    3472 2 50       8 unless (%header) {
    3473 0         0 $self->cgi_error("400 Bad request (malformed multipart POST)");
    3474 0         0 return;
    3475             }
    3476              
    3477 2         11 my($param) = $header{'Content-ID'}=~/\<([^\>]*)\>/;
    3478 2         6 $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       7 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         11 $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       4 if ($DISABLE_UPLOADS) {
      2         7  
    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     7 ? ( $ENV{TEMP} || $ENV{TMP} || ( $ENV{WINDIR} ? ( $ENV{WINDIR} . $SL . 'TEMP' ) : undef ) )
    3504             : undef; # File::Temp defaults to TMPDIR
    3505              
    3506 2         318 require CGI::File::Temp;
    3507 2         18 my $filehandle = CGI::File::Temp->new(
    3508             UNLINK => $UNLINK_TMP_FILES,
    3509             DIR => $tmp_dir,
    3510             );
    3511 2         1184 $filehandle->_mp_filename( $filehandle->filename );
    3512              
    3513 2 50 33     10 $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode
    3514             && defined fileno($filehandle);
    3515              
    3516 2         4 my ($data);
    3517 2         10 local($\) = '';
    3518 2         5 my $totalbytes;
    3519 2         10 while (defined($data = $buffer->read)) {
    3520 2 50       11 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       30 print $filehandle $data if ($self->{'use_tempfile'});
    3526             }
    3527              
    3528             # back up to beginning of file
    3529 2         89 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       10 close $filehandle if $CLOSE_UPLOAD_FILES;
    3536 2 50       5 $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         10 $self->{'.tmpfiles'}->{$$filehandle . $filehandle} = {
    3545             hndl => $filehandle,
    3546             name => $filehandle->filename,
    3547             info => {%header},
    3548             };
    3549 2         9 push(@{$self->{param}{$param}},$filehandle);
      2         15  
    3550             }
    3551             }
    3552 1         15 return $returnvalue;
    3553             }
    3554              
    3555             sub upload {
    3556 16     16 1 6769 my($self,$param_name) = self_or_default(@_);
    3557 16 50       54 my @param = grep {ref($_) && defined(fileno($_))} $self->param($param_name);
      18         136  
    3558 16 50       50 return unless @param;
    3559 16 100       79 return wantarray ? @param : $param[0];
    3560             }
    3561              
    3562             sub tmpFileName {
    3563 11     11 0 480 my($self,$filename) = self_or_default(@_);
    3564              
    3565             # preferred calling convention: $filename came directly from param or upload
    3566 11 100       44 if (ref $filename) {
    3567 7   50     63 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         15 foreach my $param_name ($self->param) {
    3573 16         55 foreach my $filehandle ($self->multi_param($param_name)) {
    3574 20 100       79 if ($filehandle eq $filename) {
    3575 4   50     31 return $self->{'.tmpfiles'}->{$$filehandle . $filehandle}->{name} || '';
    3576             }
    3577             }
    3578             }
    3579              
    3580 0         0 return '';
    3581             }
    3582              
    3583             sub uploadInfo {
    3584 19     19 0 1054 my($self,$filename) = self_or_default(@_);
    3585 19 100       78 return if ! defined $$filename;
    3586 16         116 return $self->{'.tmpfiles'}->{$$filename . $filename}->{info};
    3587             }
    3588              
    3589             # internal routine, don't use
    3590             sub _set_values_and_labels {
    3591 27     27   76 my $self = shift;
    3592 27         84 my ($v,$l,$n) = @_;
    3593 27 50 33     137 $$l = $v if ref($v) eq 'HASH' && !ref($$l);
    3594 27 100       96 return $self->param($n) if !defined($v);
    3595 23 50       75 return $v if !ref($v);
    3596 23 50       133 return ref($v) eq 'HASH' ? keys %$v : @$v;
    3597             }
    3598              
    3599             # internal routine, don't use
    3600             sub _set_attributes {
    3601 71     71   142 my $self = shift;
    3602 71         184 my($element, $attributes) = @_;
    3603 71 100       319 return '' unless defined($attributes->{$element});
    3604 2         6 $attribs = ' ';
    3605 2         7 for my $attrib (keys %{$attributes->{$element}}) {
      2         16  
    3606 2         10 (my $clean_attrib = $attrib) =~ s/^-//;
    3607 2         5 $attribs .= "@{[lc($clean_attrib)]}=\"$attributes->{$element}{$attrib}\" ";
      2         20  
    3608             }
    3609 2         16 $attribs =~ s/ $//;
    3610 2         10 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   10 my($package,$interface,$boundary,$length) = @_;
    3637 3         8 $FILLUNIT = $INITIAL_FILLUNIT;
    3638 3         16 $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         6 my $boundary_read = 0;
    3649 3 50       35 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       13 $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         24 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       9 unless ($boundary_read) {
    3682 3         15 while ($self->read(0)) { }
    3683             }
    3684 3 50       12 die "Malformed multipart POST: data truncated\n" if $self->eof;
    3685              
    3686 3         10 return $retval;
    3687             }
    3688              
    3689             sub readHeader {
    3690 12     12   28 my($self) = @_;
    3691 12         19 my($end);
    3692 12         26 my($ok) = 0;
    3693 12         22 my($bad) = 0;
    3694              
    3695 12 50 33     68 local($CRLF) = "\015\012" if $CGI::OS eq 'VMS' || $CGI::EBCDIC;
    3696              
    3697 12   33     26 do {
    3698 12         36 $self->fillBuffer($FILLUNIT);
    3699 12 50       66 $ok++ if ($end = index($self->{BUFFER},"${CRLF}${CRLF}")) >= 0;
    3700 12 50       35 $ok++ if $self->{BUFFER} eq '';
    3701 12 50 33     62 $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       31 return () if $bad;
    3706              
    3707             #EBCDIC NOTE: translate header into EBCDIC, but watch out for continuation lines!
    3708              
    3709 12         45 my($header) = substr($self->{BUFFER},0,$end+2);
    3710 12         30 substr($self->{BUFFER},0,$end+4) = '';
    3711 12         22 my %return;
    3712              
    3713 12 50       35 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         26 my $token = '[-\w!\#$%&\'*+.^_\`|{}~]';
    3724 12         107 $header=~s/$CRLF\s+/ /og; # merge continuation lines
    3725              
    3726 12         270 while ($header=~/($token+):\s+([^$CRLF]*)/mgox) {
    3727 35         135 my ($field_name,$field_value) = ($1,$2);
    3728 35         142 $field_name =~ s/\b(\w)/uc($1)/eg; #canonicalize
      72         262  
    3729 35         180 $return{$field_name}=$field_value;
    3730             }
    3731 12         82 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   65 my($self,$bytes) = @_;
    3759              
    3760             # default number of bytes to read
    3761 27   33     119 $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         82 $self->fillBuffer($bytes);
    3766              
    3767 27 50       79 my $boundary_start = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}) : $self->{BOUNDARY};
    3768 27 50       76 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         82 my $start = index($self->{BUFFER},$boundary_start);
    3772              
    3773 27 50       62 warn "boundary=$self->{BOUNDARY} length=$self->{LENGTH} start=$start\n" if $_DEBUG;
    3774              
    3775             # protect against malformed multipart POST operations
    3776 27 50 33     99 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       65 if ($start == 0) {
    3783              
    3784             # clear us out completely if we've hit the last boundary.
    3785 15 100       85 if (index($self->{BUFFER},$boundary_end)==0) {
    3786 3         11 $self->{BUFFER}='';
    3787 3         8 $self->{LENGTH}=0;
    3788 3         18 return undef;
    3789             }
    3790              
    3791             # just remove the boundary.
    3792 12         31 substr($self->{BUFFER},0,length($boundary_start))='';
    3793 12         28 $self->{BUFFER} =~ s/^\012\015?//;
    3794 12         45 return undef;
    3795             }
    3796              
    3797 12         24 my $bytesToReturn;
    3798 12 50       30 if ($start > 0) { # read up to the boundary
    3799 12 50       31 $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         63 my $returnval=substr($self->{BUFFER},0,$bytesToReturn);
    3808 12         32 substr($self->{BUFFER},0,$bytesToReturn)='';
    3809            
    3810             # If we hit the boundary, remove the CRLF from the end.
    3811 12 50       62 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   84 my($self,$bytes) = @_;
    3819 39 50 66     177 return unless $self->{CHUNKED} || $self->{LENGTH};
    3820              
    3821 39         83 my($boundaryLength) = length($self->{BOUNDARY});
    3822 39         65 my($bufferLength) = length($self->{BUFFER});
    3823 39         90 my($bytesToRead) = $bytes - $bufferLength + $boundaryLength + 2;
    3824 39 100 66     161 $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         124 $bytesToRead,
    3829             $bufferLength);
    3830 39 50       103 warn "bytesToRead=$bytesToRead, bufferLength=$bufferLength, buffer=$self->{BUFFER}\n" if $_DEBUG;
    3831 39 50       127 $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       88 if ($bytesRead <= 0) {
    3839             die "CGI.pm: Server closed socket during multipart read (client aborted?).\n"
    3840 36 50       95 if ($self->{ZERO_LOOP_COUNTER}++ >= $SPIN_LOOP_MAX);
    3841             } else {
    3842 3         8 $self->{ZERO_LOOP_COUNTER}=0;
    3843             }
    3844              
    3845 39 100 100     149 $self->{LENGTH} -= $bytesRead if !$self->{CHUNKED} && $bytesRead;
    3846             }
    3847              
    3848             # Return true when we've finished reading
    3849             sub eof {
    3850 18     18   45 my($self) = @_;
    3851             return 1 if (length($self->{BUFFER}) == 0)
    3852 18 100 66     99 && ($self->{LENGTH} <= 0);
    3853 15         47 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;