CGI (perl)

From HalfgeekKB
Jump to navigation Jump to search

Use

When using CGI on its own, don't be satisfied with the normal use. Prefer this:

use CGI 3.00;
$CGI::DISABLE_UPLOADS = 1;
$CGI::POST_MAX = 512 * 1024;

Version 3.00 introduced (as on 2005 April 12) the most recent XSS vulnerability fix.

$CGI::DISABLE_UPLOADS should be set high unless the script is intended to accept uploaded files.

$CGI::POST_MAX is the largest acceptable POST, in bytes.

Xana::CGI subclasses CGI::Safe, which sets the two variables already, and messes with %PATH for security. CGI::Safe itself is also pretty simple, if available (if it isn't, it's pure Perl so a compiler is not necessary to install).

use CGI::Safe 'taint';

Xana::CGI uses CGI::Safe with 'taint' already.

use Xana::CGI;

Instantiation

Using CGI:

my $cgi = new CGI;

Using CGI::Safe:

my $cgi = CGI::Safe->new( DISABLE_UPLOADS => 0, POST_MAX => 1024 * 1024 );

Those arguments are optional. Xana::CGI is-a CGI::Safe.

Typical Flow

# Setting cookies
my $cookie1 = $cgi->cookie(-name=>'sessionID',-value=>'m0m0',-expires=>'+30m');
my $cookie2 = $cgi->cookie(-name=>'user',-value=>'Jimmy');

print $cgi->header(-cookie=>[$cookie1,$cookie2]);

# CGI.pm can generate its own HTML. Do we need it? No.
print <<EOF ;
<html>
<head>
<title>Some title</title>
</head>
<body>
EOF

print $cgi->start_form;
# -method=>'POST', -action=>this script, -enctype=>'application/x-www-form-urlencoded'
# -enctype may be multipart/form-data.
# Set like -enctype => $cgi->URL_ENCODED (or $cgi->MULTIPART)
# -name and -onSubmit can be used with scripts.
# Abort submission by returning false from onSubmit.

# Previous value in fields in maintained across requests.
# Set -override=>1 to always use -value.

print $cgi->hidden('hidden1','value');
print $cgi->hidden(-name=>'hidden2',-default=>[qw/alpha beta gamma/]);
# Retrieve multi-valued fields in list context.
print $cgi->textfield('field1','A default value',50,80);
# -name, -value, -size, -maxlength
print $cgi->textarea('field2','A long default value',80,25);
# -name, -value, -rows, -columns
print $cgi->password_field('pass1','a pass!',50,80);
# Same as textfield


# Dropdown lists: Tricky!
my $labels = {
  red => 'The color red',
  green => 'The color green',
  blue => 'The color blue'
};
my $attributes = {
  red => { class => 'redStyle' },
  green => { class => 'greenStyle' },
  blue => { class => 'blueStyle' }
};
print $cgi->popup_menu('menu1',[qw/red green blue/],'red',$labels,$attributes);
# -name, -values, -default, -labels, -attributes
# -attributes sets plain HTML attributes, hence the outrageous syntax!


# Nested dropdown lists: Trickier!
my $labels2 = {};
my $attributes2 = {};
for(qw/red green blue silver lime/) {
  $labels2->{$_} = "The color $_";
  $attributes2->{$_} = { class => $_ . 'Style' };
}
print $cgi->popup_menu(-name => 'menu2',
  -values => [
    'red',
    'green',
    'blue',
    $cgi->optgroup(-name => 'Stranger colors',
       -values => ['silver','lime'],
       -labels => $labels2,
       -attributes => $attributes2)
  ],
  -labels => $labels2,
  -attributes => $attributes2);
# The list ends up looking like this:
# The color red
# The color green
# The color blue
# *Stranger colors*
#   The color silver
#   The color lime
# An option selected from the submenu is returned as the
# value of 'menu2'.  Note also that the submenu heading
# may also be classed by setting -class in optgroup().


# Scrolling lists
print $cgi->scrolling_list(-name => 'list1',
    -values => [
    'red',
    'green',
    'blue',
    ],
    -labels => $labels2,
    -attributes => $attributes2,
    -default => 'red',
    -size => 2,
    -multiple => 1);
# Note: It appears -default must be used instead of -value here.
# -default may be a list ref if -multiple is true.


# Checkbox groups
my @group1 = $cgi->checkbox_group(-name => 'group1',
  -values => [qw/red blue green/],
  -default => [qw/red green/],
  -labels => $labels2
  );

print "

$_

" foreach @group1;

# The return param is an array of the checked values.
# Note: -attributes is available here, but it only styles the
# checkbox itself--not the label--so it's pretty worthless.


# Single checkboxes
print $cgi->checkbox(-name=>'check1',
    -checked=>1,
    -value=>'A ludicrous string',
    -label=>'Isolated Decision'
    );
# The return param is -value if checked, undef else.
# -class only applies to the checkbox.


# Radio buttons
my @radios = $cgi->radio_group(-name => 'radio1',
  -values => [qw/red blue green/],
  -default => 'green',
  -labels => $labels2
  );

print "

$_

" foreach @radios;

# Again, -attributes is worthless.

 
print $cgi->filefield('upload1',,50,80)
# -name, -default, -size, -maxlength
# -default is typically ignored.
# DISABLE_UPLOADS must be false, form encoding must be $cgi->MULTIPART.


# Uploaded files are stuffed somewhere. upload() returns the filehandle
# of the file uploaded with the given parameter name, or undef if there
# wasn't one.
my $upload1 = $cgi->upload('upload1');
if(defined $upload1) {
  # ... Use $upload1 as a filehandle ...
  open(OUTFILE,">>/dev/null") or die;
  my $buffer;
  while(my $read=read($upload1,$buffer,1024) {
    print OUTFILE $buffer;
  }
} elsif($cgi->cgi_error) {
  # The HTTP error status 400 Bad Request is returned,
  # suitable for setting -status in header()
}


# Submit buttons
print $cgi->submit('submit1','Send');
# -name, -value
# Submitting with this button is var submit1=Send.
# More than one submit is allowed.

# Reset buttons... useless.  Forget them.

# Image buttons
print $cgi->image_button(-name=>'image1',
  -src=>'button.png',
  -alt=>'Alternate text');
# The button submits; it returns the coordinates of
# the click as parameters 'image1.x' and 'image1.y'.

Redirects

These statements generate entire headers. Don't print a $cgi->header as well.

# Generic 302
print $cgi->redirect('http://example.com/');
# 301: Moved Permanently
# 302: Found
# 303: See Other
print $cgi->redirect(-uri => 'http://example.com/', -status => 301);

Forms

See also Forms (CPAN).

print $cgi->start_form;
print $cgi->end_form;


See also