CGI-программирование.
Пример:
#!/usr/bin/perl5 -w
print <<END_of_Multiline_Text;
Content-type: text/html
<HTML>
<HEAD>
<Hello World!<TITLE>
</HEAD>
<BODY>
<H1>Greetings, Terrians!<H1>
</BODY>
</HTML>
End_of_Multiline_Text
Используется модуль CGI.pm. Программа, которая запрос:
serv.edu.kiae.ru/~gds/cgi-bin/test.cgi?flavor=mint:
#!/usr/bin/perl5 -w
use CGI qw(param);
print <<END_of_Multiline_Text;
Content-type: text/html
<HTML>
<HEAD>
<Hello World!<TITLE>
</HEAD>
<BODY>
<H1>Greetings, Terrians!<H1>
End_of_Multiline_Text
my $favorilte = param("flover");
print "<P>Your favorite flavor is $favorite.";
print <<All_Done;
</BODY>
</HTML>
All_Done
В модуле CGI.pm имеются директивы импорта - метки, которые обозначают
группы импортируемых функций. В модуле имеются следущие директивы:
:cgi, :form, :html2, :html3, :netscape, :shortcuts, :standard, :all.
Пример использования сокращений:
#!/usr/bin/perl5 -w
use CGI qw(:standard);
print header();
print start_html("Hello World!"), h1("Hello World!");
my $favorite = param("flavor");
print p("Your favorite flavor is $favorite");
print end_html();
HTML-страница, содержащая заполняемую форму:
<HTLM>
<HEAD>
<TITLE> Hello Ice Cream </TITLE>
</HEAD>
<BODY>
<H1>Hello Ice Cream!</H1>
<FORM ACTION="http://serv.edu.kiae.ru/~stsss/cgi-bin/ice_cream.cgi" METHOD="GET">
What is your flavor?<INPUT NAME="favorite" TYPE="text" VALUE="mint">
<P>
<INPUT TYPE="submit">
</FORM>
</BODY>
</HTLM>
Вариант с использованием одного CGI-файла:
#!/usr/bin/perl5 -w
use CGI qw(:standard);
my $favorite = param("flavor");
print header();
print start_html("Hello Ice Cream!"), h1("Hello Ice Cream!");
if($favorite) {
print p("Your favorite flavor is $favorite");
} else {
print hr, start_form;
print p("Pleace select a flavor: ", textfield("flavor", "mint"));
print end_form, hr
}
print end_html();
Пример:
#/usr/bin/perl5 -w
use strict;
use CGI qw(:standard);
print header;
print start_html("Ice Cream Stand"), h1("Ice Cream Stand");
if(param()) {
my $who = param("name");
my $flavor = param("flavor");
my $scoops = param("scoops");
my $taxrate = 1.0743;
my $cost = sprintf("%.2f", $taxrate * (1.00 + $scoops*0.25));
print p("Ok, $who, have $scoops scoops of $flavor for\$$cost.");
} else {
print hr();
print start_form();
print p("What is your name? ", textfield("name"));
print p("What flavor: ", popup_menu("flavor",
['mint', 'cherry', 'mocha']));
print p("How many scoops? ", popup_menu("scoops", [1..3]));
print p(submit("order"), reset("clear"));
print end_form(), hr();
}
print end_html();
В функции popup_menu() квадратные скобки создают ссылку
на анонимный массив. Другой способ создания ссылки на массив:
@choises = ('mint', 'cherry', 'mocha');
print p("What flavor: ", popup_menu("flavor",\@choises));
Ссылки работают примерно как ссылки в C. Они указывают на другие
значения или переменные. Сылки PERL нельзя приводить. Если область
памяти, на которую указывают ссылки, больше не используется, автоматически
возвращается в использование.
Методом \@array можно создавать ссылки на именованные
массивы, а посредством указания [ list ] - на анонимные
массивы.
Методом \%hesh можно создавать ссылки на именованные
хеши, а посредством указания { key1, val1, key2, val2, .. }
- на анонимные хеши.
Прокручиваемый список:
print scrolling_list(
-NAME => "flavors",
-VALUES => [qw(mint chocolate cherry vanilla peach)],
-LABELS => {
mint => "Mightly Mint",
chocolate => "Cherished Chocolate",
cherry => "Cherry Cherry",
vanilla => "Very Vanilla",
peach => "Perfectly Peach",
},
-SIZE => 3,
-MULTIPLE => 1 # 1 - true, 0 - false
);
-NAME - имя компонента формы,
-LABELS - ссылка на анонимный хеш,
-VALUES - ссылка на анонимный массивa ключей хеша,
-SIZE - сколько элементов списка видно одновременно,
-MULTIPLE - если 1 - можно выбирать более одного
элемента списка.
Если -MULTIPLE в положении истина, можно делать:
@choices = param("flavors");
Еще один способ:
%flavors = (
"mint", "Mightly Mint",
"chocolate", "Cherished Chocolate",
"cherry", "Cherry Cherry",
"vanilla", "Very Vanilla",
"peach", "Perfectly Peach",
);
print scrolling_list(
-NAME => "flavors",
-LABELS => \%flavors,
-VALUES => [keys %flavors],
-SIZE => 3,
-MULTIPLE => 1 # 1 - true, 0 - false
);
Создание файла:
touch /usr/tmp/chatfile
chmod 0666 /usr/tmp/chatfile
Блокирование доступа:
use Fcntl qw(:flock); # импортирует LOCK_EX, ...
...
flock(CHANDLE, LOCK_EX) || bail("Cannot flock $CHATNAME: !$");
Пусть модуль CGI возвращает обьект $query
$he_said = $query->param("answer");
Имя класса - имя модуля без расширения .pm (обычно).
Конструктор, необходимый для создания обьекта:
$query = CGI->new();
# or
$query = new() CGI;
CGI-модуль можно рассматривать либо как традиционный модуль с
экспортируемыми функциями, либо как обьектный модуль.
#!/usr/bin/perl5 -w
use 5.004;
use strict;
use CGI qw(:standard);
use Fcntl qw(:flock);
sub bail { # функция ошибок
my $error = "@_";
print h1("Unexpected Error"), p($error), end_html;
die $error;
}
my (
$CHATNAME, # имя файла гостевой книги
$MAXSAVE, # какое количество хранить
$TITLE, # название и заголовок страницы
$cur, # все текущие записи
$entry, # одна конкретная запись
);
$TITLE = "Simple Guestbook";
$SHATNAME = "/usr/tmp/chatfile";
$MAXSAVE = 10;
print header, start_html($TITLE); h1($TITLE);
my(@entries);
$cur = CGI -> new(); # текущий запрос
if($cur -> param("message")) { # мы получили сообщение
$cur -> param("data", scalar localtime); # установить текущее время
@entries = ($cur); # записать сообщение в массив
}
# открыть файл для чтения и записи (с сохранением предыдущего содержимого)
open(CHANDLE, "+< $CHATNAME") || bail("canot open $CHATNAME: $!");
# получить эксклюзивную блокировку на гостевую книгу
# (LOCK_EX == exclusive lock)
flock(CHANDLE, LOCK_EX) || bail("canot flock $CHATNAME: $!");
# занести в $MAXSAVE старые записи (первой - самую новую)
while(!eof(CHANDLE) && @entries < $MAXSAVE) {
$entry = CGI -> new(\*CHANDLE); # передать дескриптор файла по ссылке
push @entries, $entry;
}
seek(CHANDLE, 0, 0) || bail("canot rewind $CHATNAME: $!");
foreach $entry (@entries) {
$entry -> save(\*CHANDLE);
}
truncate(CHANDLE, tell(CHANDLE)) || bail("canot truncate $CHATNAME: $!");
close(CHANDLE) || bail("canot close $CHATNAME: $!");
print hr, start_form;
print p("Name:", $cur -> textfield(-NAME => "name"));
print p("Message:", $cur -> textfield(
-NAME => "message",
-OVERRIDE => 1, # стирает предыдущее сообщение
-SIZE => 50
)
);
print p(submit("send"), reset("clear"));
print end_form, hr;
print h2("Prior Messages");
foreach $entry (@entiries) {
printf("%s [%s]: %s",
$entry -> param("date"),
$entry -> param("name"),
$entry -> param("message"));
print br();
}
print end_html;
|