CGI Web Programming Notes
iDog
HTTP
Print HTML Doc
Using shell:
# HTTP header
echo "Content-type: text/html; charset=iso-8859-1"
echo
echo
cat << END_OF_HTML
<ht ml>
<he ad>
<ti tle>my title</ti tle>
</he ad>
<bo dy>
<h1>My Title</h1>
My article.
</bo dy>
</ht ml>
END_OF_HTML
Using CGI.pm:
use CGI;
use CGI::Carp qw(fatalsToBrowser);
sub getParamValue() {
my ($q, $varName, $defaultValue) = @_;
my $value = $q->param($varName);
if(defined $value) {
return $value;
}
if($defaultValue) {
return $defaultValue;
}
return '';
}
my $q = new CGI;
my $varValue = &getParamValue($q, 'varName', 'my default value'); # from form or URL
my $title = "My Title";
print $q->header;
print $q->start_html($title);
print $q->h1($title);
print << "END_OF_HTML";
My article goes here...
END_OF_HTML
print $q->end_html;
SQL
When generating SQL using user's input, it's very important to escape single quote. Otherwise, it's easy to get affected by SQL injection attack.
sub trim {
($_) = @_;
if(! defined $_) {
return '';
}
s/^\s+//;
s/\s+$//;
$_;
}
sub processSqlStr() {
my ($str) = @_;
$str = &trim($str);
if($str eq '') {
return 'null';
}
$str =~ s/'/''/g;
return "'$str'";
}
my $sql = 'update Users set name = ' . &processSqlStr($name) . " where id=0";
Thus if user's input ($name) is "Tim O'Reilly", it still works well.
Explanation of SQL injection
For example, if the login validation code is as follows:
my $sql = "select count(*) from Users where login = '$login' and pwd = '$pwd'";
# query database, if return value > 0, then validation passes
A cracker can input "' or pwd <> '" as the password to pass the validation.
URL
Special chars in URL should be escaped with their ASCII code.
my $url = "/cgi-bin/query.cgi?";
$url .= "name=$name&";
$url .= "phone=$phone";
# escape special chars
$url =~ s/\+/%2B/g;
$url =~ s/\s/+/g;
Thus a url like
/cgi-bin/query.cgi?name=Bruce Lee&phone=+1-1111-2222
becomes
/cgi-bin/query.cgi?name=Bruce+Lee&phone=%2B1-1111-2222
Or do it in a better way:
$url =~ s/([^0-9A-Za-z_ \/\?\=&])/'%'.unpack('H2',$1)/geo;
$url =~ s/\s/+/g;
Or encode/decode variables seperately:
#encode var
my $var = $q->param('varName');
$var =~ s/(\W)/'%'.unpack("H2", $1)/ego;
my $url = "http://www.example.com/my.cgi?varName=$var";
In my.cgi who accepts the variable:
my $var = $q->param('varName');
$var =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/ego;
# ...
print "the variable is $var";
Redirection
my $q = new CGI;
print $q->redirect($url);
By default, $q->redirect do a 302 jump. If 301 is desired, specify it explicitly:
print $q->redirect(-url => $url, -status => '301 Moved');
'-target' (target window) can also be specified.
More Options in HTML Head
use CGI;
my $q = CGI->new;
print $q->header(-charset => 'euc-jp');
print $q->start_html(
-title => "My title",
-charset => 'euc-jp',
-encoding => 'euc-jp',
-lang => 'ja-JP'
);