主從式架構
一個好的主從式的應用程式, 應該在使用者輸入時便立即確認其輸入值是否為 valid (可用 VBScript, JScript, JavaScript, PerlScript 等.), 然後才將 確認過的資料後傳至伺服器端處理程式 (如 CGI, ASP 等)。在以下範例中,使用者 可以在郵遞區號內輸入“aaa“,然後按”確定“,網頁會告訴你輸入的郵遞區號必須是數字。
範例:
<form method="POST" action="comments.pl"> <strong>E-mail:</strong> <input type="text" name="address" size="30" maxlength="50"> <br>您的意見:<br> <textarea name="comments" rows="8" cols="50"> </textarea> <p><input type="submit" value="Sent Comments"> </form>
#!/usr/local/bin/perl
# forms-lib.pl
# Decodes URLs and unpacks from input.
# Read the form contents into $input, decodes it, unpacks it,
# and returns it as an associative array.
sub GetFormInput
{
my(%input);
$input = &ReadInput();
%input = &ParseInput($input) if $input;
return(%input);
}
sub ReadInput
{
my($method, $input, $length);
$method = $ENV{'REQUEST_METHOD'};
if($method eq 'GET')
{
$input = $ENV{'QUERY_STRING'};
}
elsif ($method eq 'POST')
{
$length = $ENV{'CONTENT_LENGTH'};
read(STDIN, $input, $length);
}
return($input);
}
sub ParseInput
{
my($input) = @_;
my(@pairs);
my(%input);
@pairs = split('&',$input);
foreach $pair (@pairs)
{
# convert all plus signs to spaces.
$pair =~ s/\+/ /g;
# split into a key and a value.
($key, $value) = split('=', $pair, 2);
# Convert hex numbers to alphanumeric.
$key =~ s/%(..)/pack("c", hex($1))/ge;
#$value =~ s/%(..)/pack("c", hex($1))/ge;
$value =~ s/%([\da-fA-F][\da-fA-F])/pack("c", hex($1))/ge;
# handle multiple values, separated by newlines.
$input{$key} .= "\n" if defined($input{$key});
# associate keys and values
$input{$key} = $value;
}
return (%input);
}
return true;
address email@address comments 使用者輸入的意見
#!/usr/local/bin/perl
require 'forms-lib.pl';
print "content-type: text/html\n\n";
%input = &GetFormInput();
$recipient = $input{'address'} || "jllu\@nchu.edu.tw";
$message = $input{'comments'};
$sender = $ENV{'HTTP_FROM'} || "jllu\@nchu.edu.tw";
print <<EndofMessage;
<html>
<head><title>Comment Tests<title><head>
<body>
<h3>Your Comment is to be sent<h3>
<pre>
To: $recipient
From: $sender
Subject: Comments on your web page
$message
</pre>
</body>
</html>
EndofMessage
#!/usr/bin/perl
sub Footer
{
print "<h2>Perl Program Using Functions</h2>\n";
print "\n</body>\n";
print "</html>\n";
}
print "Content-type: text/html\n\n";
print "<html>\n";
print "<head>\n";
print "<title>Perl Program Using Functions</title>\n";
print "</head>\n\n";
&Footer;
#!/usr/bin/perl
sub Header
{
print "Content-type: text/html\n\n";
print "<html>\n";
print "<head>\n";
print "<title>@_</title>\n";
print "</head>\n\n";
}
sub Footer
{
print "<h2>Perl Program Using Functions</h2>\n";
print "\n</body>\n";
print "</html>\n";
}
&Header("Perl Program Using Functions");
&Footer;
#!/usr/bin/perl
sub Root
{
my($a, $b, $c) = @_;
my($tmp, $x1, $x2);
$tmp = sqrt($b ** 2 - 4.0 * $a * $c);
$x1 = (-$b + $tmp) / (2.0 * $a);
$x2 = (-$b - $tmp) / (2.0 * $a);
return ($x1, $x2);
}
$a = 1.0;
$b = -2.0;
$c = 1.0;
@x = &Root($a, $b, $c);
print "Content-type: text/html\n\n";
print "x1 = $x[0]; and x2 = $x[1]\n";
#!/usr/bin/perl
require "req.pl";
&Header("Perl Program Using Functions");
&Footer;
#!/usr/bin/perl
sub Header
{
print "Content-type: text/html\n\n";
print "<html>\n";
print "<head>\n";
print "<title>@_</title>\n";
print "</head>\n\n";
}
sub Footer
{
print "<h2>Perl Program Using Functions</h2>\n";
print "\n</body>\n";
print "</html>\n";
}
return 1; # this is required.
#!/usr/bin/perl ($sec, $min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); print "秒: $sec\n"; print "分: $min\n"; print "時: $hour\n"; print "一個月的第幾天: $mday\n"; print "月: $mon 範圍是 0-11,而一月為 0\n"; print "距離 1900 年的第幾年: $year\n"; print "一周內的第幾天: $wday 範圍是 0-6,而星期日為 0\n"; print "一年內的第幾天: $yday\n"; # 如果我只想要當天的日期, ($_,$_,$_, $mday, $mon, $year, $_,$_,$_) = localtime(time); $year = $year + 1900; $mon = $mon + 1; print "今天是西元 $year 年 $mon 月 $mday 日\n";
#!/usr/local/bin/perl
$url = 'www.nchu.edu.tw';
# Usage: /pattern/[g][o][i]
# g for global, o for only once, and i for case-insentitive
# url 是否包含 nchu 字串
if ( $url =~ /nchu/ )
{
print "$url is 國立中興大學.\n";
}
# 將 'edu' 取代為 EDU
# Can you use tr? (ie. tr/edu/EDU/)
$url =~ s/edu/EDU/;
print "\$url is now $url.\n";
#!/usr/local/bin/perl $names = "fred and mary"; $names =~ tr/a-z/A-Z/; print "$names\n";
#!/usr/local/bin/perl $count = "fred and mary"; # # 若不使用 =~, tr 傳回轉換的字元總數 $count = tr/a-z //; print "$count\n";
| Character | URL-encoded characters |
|---|---|
| Tab | %09 |
| 空格 | + |
| ! | %21 |
| + | %2B |
#!/usr/local/bin/perl
print "Content-type: text/plain\n\n";
$input = $ENV{'QUERY_STRING'};
# translate + into space.
$input =~ tr/+/ /;
print "$input.\n";
# s: substitute
# \d: a number, A-F: A,B,C,D,E,F, a-f: a,b,c,d,e,f
# [\dA-Fa-f]: either a number, A, B, ... , F, a, b, ..., or f.
# pack("c", hex($1)): transform %[][] into a character ("c").
# e: treat pack() as an expression instead of a string.
# $input =~ s/%(..)/pack("c", hex($1))/eg;
$input =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("c", hex($1))/eg;
print "$input.\n";
#!/usr/local/bin/perl $s = "My name is Eric."; $n = 5400; $r = 123.456; // 結果是 "My Name is Eric ^5400 ^^^^123.46" printf "%15s %5d %10.2f\n", $s, $n, $r;
$newr = sprintf("%.2f", $r);
#!/usr/local/bin/perl $str = "th Perl"; $str .= " CGI program.\n"; $num = 1; $num++; $num += 1; $num = $num + 1; print "My $num$str";
@addr = ("www.cyut.edu.tw", 80, "/~jlu/");
print "http://$addr[0]$addr[2]\n"; # @addr and $addr
split(/pattern/, $line)
$addr = "www.cyut.edu.tw";
@tmp = split(/\./, $addr); # 以後討論
print '$tmp[2] is ', $tmp[2], "\n";
練習: 若 $time = "18:30:32";, 請將結果
「下午6點30分32秒」印出。
$url{"address"} = "www.cyut.edu.tw";
$url{"port"} = 80;
$url{"path"} = "/~jlu/";
# @url_list gets (key1, value1, key2, value2, ...) @url_list = %url; # create %newurl like %url %newurl = @url_list; # easier and faster. %newurl = %url; # easier and faster.
$eric = "Eric";
@eric = ("Hello", "Carol");
%eric = ("Last Name", "Lu", "First Name", "Eric");
@tmp = keys(%eric);
print '$eric is ', $eric, "\n";;
print '@eric[1] is ', $eric[1], "\n";
print '$eric{"First Name"} is ',
$eric{"First Name"}, "\n";
print '$eric{$tmp[0]} is ',
$eric{$tmp[0]}, "\n";
if ($url{"address"} eq "www.cyut.edu.tw")
{
print "You're pointing to CYUT.\n";
}
if ($url{"port"} == 80)
{
print "Port is 80.\n";
}
else
{
print "Wrong port number.\n";
}
foreach $key (keys(%url))
{
print "key is $key.\n";
}
while (($key, $value) = each(%url))
{
print "$key is $value.\n";
}
# if there are 6 elements in @url_list, when @url_list
# compares with an integer, it will return 6.
for ( $i = 0; $i < @url_list; $i++)
{
print "$url_list[$i] ";
}
print "\n";
# $#addr: size of addr - 1
for ( $i = 0; $i <= $#addr; $i++ )
{
print "$addr[$i]\n";
}
<form action="1st.pl"> <input type="submit" value="Hello World"> </form>
#!/usr/bin/perl print "Content-type: text/html\n\n"; print "<html><head><title>My First Perl Program</title></head>\n"; print "<body><h1>Hello World</h1></body></html>\n";
01: <form method="GET" action="2nd.pl"> 02: 請輸入文字:<input type="text" name="input"> 03: <input type="submit" value="Submit"> 04: <input type="reset" value="Clear"> 05: </form>
#!/usr/local/bin/perl
print "Content-type: text/plain\n\n";
$input = $ENV{'QUERY_STRING'};
print "$input\n";
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "AUTH_TYPE is $ENV{'AUTH_TYPE'} <br>";
print "CONTENT_LENGTH is $ENV{'CONTENT_LENGTH'} <br>";
print "GATEWAY_INTERFACE is $ENV{'GATEWAY_INTERFACE'} <br>";
print "HTTP_USER_AGENT is $ENV{'HTTP_USER_AGENT'} <br>";
print "HTTP_REFERER is $ENV{'HTTP_REFERER'} <br>";
print "QUERY_STRING is $ENV{'QUERY_STRING'} <br>";
print "REMOTE_ADDR is $ENV{'REMOTE_ADDR'} <br>";
print "REMOTE_HOST is $ENV{'REMOTE_HOST'} <br>";
print "REMOTE_IDENT is $ENV{'REMOTE_IDENT'} <br>";
print "REMOTE_USER is $ENV{'REMOTE_USER'} <br>";
print "REQUEST_METHOD is $ENV{'REQUEST_METHOD'} <br>";
print "SCRIPT_NAME is $ENV{'SCRIPT_NAME'} <br>";
print "SERVER_SOFTWARE is $ENV{'SERVER_SOFTWARE'} <br>";
print "SERVER_NAME is $ENV{'SERVER_NAME'} <br>";
print "SERVER_PROTOCOL is $ENV{'SERVER_PROTOCOL'} <br>";
#!/usr/local/bin/perl
print "Content-type: text/plain\n\n";
$length=$ENV{'CONTENT_LENGTH'};
read(STDIN, $input, $length);
print "$input\n";
set PATH=c:\perl\bin;%PATH% ppm install http://cpan.uwinnipeg.ca/PPMPackages/10xx/mod_perl.ppd
LoadFile "c:/perl/bin/perl510.dll" LoadModule perl_module modules/mod_perl.so
<Files ~ "\.(pl)$">
SetHandler perl-script
PerlResponseHandler ModPerl::Registry
Options +ExecCGI
PerlOptions +ParseHeaders
</Files>
#!/usr/local/bin/perl print "Content-type: text/html\n\n"; print "<html><head><title>My First Perl Program</title></head>\n"; print "<body><h1>Hello World</h1></body></html>\n";
代碼 作業一(50) 作業二(50) 作業三(75) 專題 期中考(128) 成績 ABC 25 30 45 75 74 70 Kevin_C 30 40 45 70 103 79 Tina 40 25 60 80 105 85 totoro 30 30 57 85 95 83 wei-jen 30 25 62 70 85 74
| Grades | |
|---|---|
#!/usr/local/bin/perl
require 'req.pl';
require 'forms-lib.pl';
# open a file called "sa4a.txt" and assign it
# a filehandler called INP.
# if file cannot open, execute die().
open(INP, "sa4a.txt") || die("Cannot open sa4a.txt.\n");
@recs = <INP>;
# get the first record
$record = $recs[0];
# get rid of consecutive whitespaces
# \s: whitespace, +: one or more.
@fields = split(/\s+/, $record);
$num_field = @fields;
# a way of printing what we got.
#print "Record is @fields.\n";
#print "Number of field is $num_field.\n";
&Header("Grades");
# print table header
print "$record\n";
# read data till the end of the file
for($row=1; $row < @recs; $row++)
{
$record = $recs[$row];
print "$record\n";
}
&Footer;
#!/usr/bin/perl $a1 = "Eric"; $a2 = 80; $a3 = 75; # ">sa4a.txt" 產生輸出檔 # ">>sa4a.txt" 產生附加式的輸出檔 open(OUTP, ">sa4a.txt") || die "Cannot open file\n"; print OUTP "$a1 $a2 $a3\n"; close OUTP;
「開始」 --> 「設定」 --> 「控制台」 --> 「ODBC」 --> 「系統資料來源名稱」 --> 「新增」 --> 「Microsoft Access Driver (*.mdb)」 --> 「完成」在 "資料來源名稱" 欄, 輸入 Samples, 並 「選擇」 samples.mdb 後按 OK。
insert into Product values ('5','燒錄器', 15000, 10)
select * from Product
select * from Product where Name='燒錄器'
select Name, Qty from Product where Name='燒錄器'
select * from Product where Price < 2500
select * from Product where Price >= 300 and Price < 10000
update Product set Qty=20 where Name='燒錄器'
delete from Product where Name='燒錄器'
use Win32::OLE;
# setup the names of DSN and Table.
$DSN = "Samples";
$Table = "Product";
# Connect and open the database
$Conn = new Win32::OLE "ADODB.Connection";
$Conn->Open("DSN=$DSN;UID=;PWD=");
#$Conn->Open("$DSN", "", "");
#$Conn->Open("$DSN");
# The followings don't work well.
#$Conn->Open("DSN=Samples;UID=;PWD=") || die "Cannot connect";
#$Conn or die "Cannot connect";
# Execute the SQL statement
$RS = $Conn->Execute("SELECT * FROM $Table");
if(!$RS) {
$Errors = $Conn->Errors();
print "Errors:\n";
foreach $error (keys %$Errors) {
print $error->{Description}, "\n";
}
die;
}
# Retrieving records from Table.
while ( !$RS->EOF ) {
my($ID, $Name, $Price, $Qty) = (
$RS->Fields('ID')->value,
$RS->Fields('Name')->value,
$RS->Fields('Price')->value,
$RS->Fields('Qty')->value );
print $ID, " : ", $Name, " : ", $Price, " : ", $Qty, "\n";
$RS->MoveNext;
}
# Close the connection.
$RS->Close;
$Conn->Close;
use Win32::ODBC;
# set Data Source Name
$DSN = "Samples";
# Open connection to DSN
if (!($O = new Win32::ODBC($DSN))){
print "Failure. \n\n";
exit();
}
# set Table name
$Table = Product;
# Get the content of the table.
if (! $O->Sql("SELECT * FROM $Table"))
{
# print out the field names.
@FieldNames = $O->FieldNames();
$Cols = $#FieldNames + 1;
for ($iTemp = 0; $iTemp < $Cols; $iTemp++){
$FmH2 .= "$FieldNames[$iTemp] ";
}
chop $FmH2;
print "$FmH2\n";
# Fetch the next rowset
while($O->FetchRow()){
undef %Data;
%Data = $O->DataHash();
print $Data{'ID'}, " ", $Data{'Name'}, " ",
$Data{'Price'}, " ", $Data{'Qty'}, "\n";
}
}
# Close Connection.
$O->Close();
#!/usr/bin/perl
use DBI;
# initialize datasourcename. for details, perldoc DBD::mSQL.
# to connect to a DB server on another host such as sun20,
#$dsn = 'db_test:sun20';
$dsn = 'db_test';
# 1. to connect to other DB such as Oracle, all you need to
# do is to replace "mSQL" with "Oracle". (assume that
# Oracle driver has been installed.)
#
# 2. to connect to MS Access, simply change DSN to 'dbi:ODBC:Samples'
#
$dbh = DBI->connect("dbi:mSQL:$dsn", "", "")
|| die "Can't connect to $data_source: $DBI::errstr";
$sth = $dbh->prepare("SELECT * FROM Product")
|| die "Can't prepare statement: $DBI::errstr";
$rc = $sth->execute
|| die "Can't execute statement: $DBI::errstr";
print "Query will return $sth->{NUM_OF_FIELDS} fields.\n\n";
print "Field names: @{ $sth->{NAME} }\n";
while (($ID, $Name, $Price, $Qty) = $sth->fetchrow_array)
{
print "$ID, $Name, $Price, $Qty\n";
}
# check for problems which may have terminated the fetch early
die $sth->errstr if $sth->err;
$sth->finish;
另外, 你也可以安裝 mSQL 專用的模組 (如 Msql), 使用以下程式
也可以達到上述範例的結果。 欲知 Msql 的細節, 請執行 perldoc Msql。
[註: 安裝 Msql 模組前, 需先安裝 DBI]
#!/usr/bin/perl
use Msql;
# Connect to DB, db_test, located at the local host.
# mSQL is also available on sun20.im.cyut.edu.tw. Therefore, you
# can also connect to db_test on sun20 by
# $db = Msql->connect("sun20","db_test") or
# die "Cannot connect to db_test on sun20.";
# When using with CGI, it is a perfect example of 3-tier architecture.
#
$db = Msql->connect("","db_test") or die "Cannot connect to db_test";
# you can insert a row
#$db->query("insert into Product values('11', '數據機', 5000, 10)");
# or you can delete what you just inserted
#$db->query("delete from Product where ID='11'");
# submit the query.
$sth = $db->query("select * from Product") or die "Cannot Quety.";
# obtain various info about this table.
print "Number of rows: ", $sth->numrows, "\n";
print "Number of columns: ", $sth->numfields, "\n";
print "\n";
# obtain field names
@fnames = $sth->name;
@ftypes = $sth->type;
for($i=0; $i<$sth->numfields; $i++)
{
print $fnames[$i], " is of type ", $ftypes[$i], "\n";
}
print "\n";
# fetch records from the table
#
# Case 1: fetch a row at a time.
#while(@arr = $sth->fetchrow)
#{
# # print out field values of each row.
# foreach $arr (@arr)
# {
# print $arr, " ";
# }
# print "\n";
#}
#
# Case 2: fetch entire row, including field names, into a hash
while(%hash = $sth->fetchhash)
{
print $hash{'ID'}, " ", $hash{'Name'}, " ", $hash{'Price'},
" ", $hash{'Qty'}, "\n";
}