468x60comp.hardware.ani.


| Содержание | Предисловие | В

Глава 19

    В этой главе:


СGІ-программирование

Если в течение последних нескольких лет вы не сидели взаперти в деревянной хижине без злектричества, то вы наверняка слышали о World Wide Web.Многие из самых интересных Web-страниц включают разного рода формы, предназначенные для ввода данных пользователем. Вы вводите данные в такую форму и щелкаете на кнопке или рисунке. Зто действие запускает некую программу на Web-сервере,

CGI-программы не просто обрабатывают данные, введенные в форму. Они вызываются и тогда, когда вы щелкаете на графическом изображении, и фактически могут использоваться для отображения всего того, что "видит" ваш броузер. Web-страницы с

Независимо от того, во что вас, возможно, заставят поверить все зти отскакивающие шарики и прыгающие обьявления, Web содержит также большой обіем текста. Поскольку мы имеем

В зтой главе мы не только изучим основы CGI-программирования, но и параллельно получим определенные начальные сведения о гипертекстовых ссылках, библиотечных модулях и обьектно-ориентированном программи-ровании на Perl. В конце главы мы

Если рассматривать зту главу как отдельное пособие, следует отметить, что ее (как и любого другого документа обьемом меньше пары сотен страниц) недостаточно для изучения более сложных тем, затронутых здесь, в частности обьектно-ориентир

Мы предполагаем, что вы уже в основном знакомы с HTML.

Модуль CGI.pm

Начиная с версии 5.004, в состав стандартного дистрибутива Perl вклю-чается модуль CGI.pm,Зтот модуль, который написал Линкольн Штейн, автор хорошо извест-ной книги How to Setup and Maintain Your Web Site, превращает процедуру создания CGI-программ на Perl

* Если у вас инсталлирована одна из более ранних версии Perl (но как минимум 5.001) и вы еще не собрались пе

Если CGI.pm уже инсталлирован у вас в системо, вы можете прочесть его полную документацию, воспользовавшись любым из способов, кот

Разрабатывая CGI-программы, держите зкземпляр man-страницы модуля CGI.pm под рукой. Она не только содержит описание функций зт

Ваша CGI-программа в контексте

На рис. 19.1 показаны взаимосвязи между Web-броузером, Web-сервером и CGI-программой. Когда вы, работая со своим броузером

Каждое предназначенное для ввода текста поле в зтой форме имеет имя (указанное в HTML-коде формы) и соответствующее значение, которым является все, что вы вводите в зтом поле. Сама форма связана (через HTML-директиву

http://www.SOMEWHERE.org/cgi-bin/some_cgi_prog?flavor=vanilla&size=double

Вы видите здесь две пары имя=значение. Такие пары отделяются друг от друга амперсандом (&). Работая с модулем

* Pod сокращенно обозначает plain old documentation ("обычная старая документация"). Зто упрощенная форма пр

Рис. 19.1. Заполнение форми с привлечением CGI

Когда Web-сервер (в данном случае www.SOMEWHERE.org) получает URL "Переговоры" между броузером и сервером, а также между сервером и CGI-программой ведутся в соответствии с протоколом, известным как HTTP. При написаний CGI-программы об зтом

Способ получения CGI-программой ее аргументов (й другой информа-ции) от броузера через сервер описывается спецификацией Common Gateway Interface. Об зтом тоже не нужно беспо

Наконец, вам следует знать, что CGI-программы могут работать с любым HTML-документом, а не только с формой. Например, вы могли бы написать такой HTML-код:

Click <a href="http://www.SOMEWHERE.org/cgi-bin/fortune.cgi">here</a> to receive your fortune.

Зцесь fortune.cgi — программа, которая просто вызывает программу fortune

href="http://www.SOMEWHERE.org/agi-bin/fortune_or_date?fortune"> <a href="http://www.SOMEWHERE.org/cgi-bin/fortune_or_date?date">

CGI-программа (в данном случае fortune_or_date) определила бы, какой из двух возможных аргументов получен, и вьшолнила бы с

Как видите, аргументи вовсе не должны иметь формат имя=значение, характерний для HTML-форм. Вы можете написать CGI-программу,

В зтой главе мы будем, главным образом, рассматривать применение HTML-форм. При зтом мы предполагаем, что вы уже знакомы с простими HTML-кодами.

Простейшая CGI-программа

Вот исходный код вашей первой CGI-программы. Она настолько проста, что в ней даже не пришлось использовать модуль CGI.pm:

#!/usr/bin/perlS -w

#самая легкая из CGI-програми print “END of Multiple Text;

Content-type: text/html

<HTML>

<HEAD>

<TITLE>Hello World</TITLE>

</HEAD>

<BODY>

<Hl>Greetings, Terrans!</Hl>

</BODY </HTML>

END_of_Multiline_Text

Каждый раз, когда зта программа вызывается, она выдает на зкран одно и то же. Зто, конечно, не особенно интересно, но позднее мы сделаем ее более занимательной.

Зта программка содержит всего один оператор: вызов функции print. Несколько забавно вьп-лядящий аргумент зто

Первая часть зтого строкового значення определенно самая важная:

строка Content-Type задает тип генерируемой выходной информации. Сразу за ней идет пустая строка, которая не должна содержать пробелов и знаков табуляции.

У большинства новичков первые CGI-программы отказываются рабо-тать, потому что пользователи забывают об зтой пустой строке, отделяющей заголовок (нечто вроде заголовка сообщ

Сначала добейтесь, чтобы ваша программа правильно вьшолнялась при вызове ее из командной строки. Зто необходимый, но не достаточный шаг для того, чтобы обеспечить функционирование вашей программы как сценария, работающего на сервере. Ош

см. ниже раздел "Поиск и устранение ошибок в CGI-программах".

Если программа должным образом работает при вызове ее из командной строки, необходимо инсталлировать ее на компьютере-сервере. Приемлемые места размещения зависят от сервера, хотя для CGI-сценариев часто исполь-зуется каталогПосле завершення инсталляции вашей программы в CGI-каталоге ее можно выполнять, указывая броузеру ее путевое имя в составе URL. Напри-мер, если ваша программа называется

http://vww.SOMEWHERE.org/cgi-bin/howdy.

Сервери обычно позволяют использовать вместо ддинных путевых имен псевдонимы. Сервер, имеющий адрес www.SOMEWHERE.org,

* Зтот заголовок необходим для протокола HTTP, о котором мы упоминали выше.

Передача параметров через CGI

Для передачи параметров в CGI-программы (точнее, в большинство CGI-программ) никакие формы не нужны. Чтобы убедиться в этом, замените URL

Когда вы "нацеливаете" свой броузер на этот URL, броузер не только просит Web-сервер вызвать программу

К вашим услугам модуль CGI.pm, который всегда разбирает входящий CGI-запрос правильно. Чтобы вставить этот м

use CGI;

где-нибудь в начале программы*.

Оператор use похож на оператор # include языка С тем, что в процессе компиляции извлекает код из другого файла

В данном случае все, что нам нужно использовать из модуля CGI.pm — это функция param () **.

Если аргументы не указаны, функция param () возвращает список всех полей, имевшихся в HTML-форме, на которую отвечает данный CGI-с

* Имена всех Perl-модулей имеют расширение рт. Более того, оператор use подразумевает это расширение. О том,

** Некоторые модули автоматически экспортируют все свои функции, но, поскольку CGI.pm — это на самом деле объектный модуль, за

Несмотря на то что в нашем списке для оператора use имеется всего один элемент, мы будем использовать запись q

#!/usr/local/bin/perlS -w

# программа ответа на форму о любимом сорте мороженого (версия 1) use CGI qw(param);

print “END_of_Start;

Content-type: text/html

<HTML>

<HEAD>

<TITLE>Hello World</TITLE>

</HEAD>

<BODY>

<Hl>Greetings, Terrans!</H1> END_of_Start

my $favorite = param("flavor");

print "<P>Your favorite flavor is $favorite. print “All_Done;

</BODY>

</HTML> All Done

Как сократить объем вводимого текста

Вводить все равно приходится очень много, но в CGI.pm есть множество удобных функций, упрощающих набор. Каждая из этих фун

Мы могли бы перечислить все эти функции в списке, прилагаемом к оператору use, но такой список разросся бы до небывалых размеров. В CGI.pm,

: cgi

Импортировать все методы обработки аргументов, например param ().

: form

Импортировать все методы создания заполняемых форм, например text-field().

:html2

Импортировать все методы, которые генерируют стандартные элементы HTML 2.0.

:htmi3

Импортировать все методы, которые генерируют элементы, предложенные в HTML 3.0 (такие как <table>, <super><

:netscape

Импортировать все методы, которые генерируют расширения HTML, характерные для Netscape.

:shortcuts

Импортировать все сокращения, генерируемые HTML (т.е. "html2" + "html3" + "netscape").

:standard

Импортировать "стандартные" возможности: "html2", "form" и "cgi".

:all

Импортировать все имеющиеся методы. Полный список приведен в модуле CGI.pm, где определяется переменная %tags.

Мы будем использовать только директиву : standard. (Подробная информация об импортировании функций и переменных из модулей приведе

Вот как выглядит наша программа со всеми сокращениями, которые используются в CGI.pm:

#!/usr/local/bin/perlS -w

# cgi-bin/ice_cream # программа ответа на форму о любимом

t сорте мороженого (версия 2) use CGI qw(:standard);

print header() ;

print start_html("Hello World"), hi ("Hello World");

my $favorite = param("flavor");

print p("Your favorite flavor is $favorite.");

print end_html();

Видите, насколько это проще? Вам не нужно беспокоиться о декодировании данных формы, о заголовках и HTML-тексте, если вы этого не хотите.

Генерирование формы

Если вам надоело вводить параметры своей программы в броузерсоздайте заполняемую форму. К таким формам привыкли большин

Создайте следующую HTML-страницу, которая включает форму с одним компонентом "текстовое поле" и кнопкой передачи. Когда пользователь щелкает на кнопке передачи*, вызывается сценарий ice_cream,

<!-- ice_cream.html —> <HTML>

<HEAD>

<TITLE>HeUo Ice Cream</TITLE>

</HEAD>

<BODY>

<Hl>Hello Ice Cream!</Hl>

<FORM ACTION-"http://www.SOMEWHERE.org/cgi-bin/ice_cream">

What's your flavor? <INPUT NAME="favorite" VALUE="mint">

<P>

<INPUT TYPE="submit">

</FORM>

</BODY> </HTML>

Помните, что CGI-программа может выдавать ту выходную HTML-информацию, которую вы ей укажете. Эта информация будет затем передаваться в тот броузер, который обратится к URL<

* Некоторые броузеры позволяют обходиться без кнопки передачи, если форма содержит только одно поле для ввода текста. Если курсор находится в этом поле и пользователь нажи

При размещении всех компонентов программы в одном CGI-файле упрощается ее сопровождение. Цена незначительное увеличение времени

#!/usr/local/bin/perlS -w

# программа ответа на форму о любимом сорте мороженого

# *и генерирования этой формы* (версия 3) use CGI qw(:standard);

my $favorite = param("flavor");

print header;

print start_html("Hello Ice Cream"), hi ("Hello Ice Cream");

if ($favorite) {

print p("Your favorite flavor is $favorite. ");

} else {

print hr, start_form;

print p ("Please select a flavor: ", textfield("flavor","mint"));

print end form, hr;

Если во время работы с броузером вы щелкнете на ссылке, которая указывает на эту программу (и если ссылка в конце URL не содержит

Рис. 19.2. Исходная заполняемая форма

Теперь заполните поле Please select a flavor, нажмите клавишу [Enter],

Рис. 19.3. Результат обработки переданного с использованием формы запроса

Другие компоненты формы

Теперь, когда вы знаете, как создавать в форме простые текстовые поля и заполнять их, вам, наверное, интересно будет узнать, как создавать компоненты формы других типовСейчас мы рассмотрим более развитую версию нашей программы. В частности, мы включили в нее новые компоненты формы: всплывающие меню, кнопку передачи (которая называется order)

#!/usr/local/bin/perl5 -w

# программа ответа на форму заказа мороженого и генерирования этой формы (версия 4) use strict;

# ввести объявления переменных и выполнить заключение в кавычки use CGI qw(:standard);

print header;

print start html("Ice Cream Stand"), hi ("Ice Cream Stand");

if (paramO) ( # форма уже заполнена

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("0k, $who, have $scoops scoops of $flavor for \$$cost.");

} else ( # первый проход, представить незаполненную форму

print hr() ;

print start_form();

print p("What's 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;

На рис. 19.4 представлено изображение начальной формы, которую создает рассматриваемая программа.

Ice Cream Stand

What's your name? |

What flavor: |t"ii4 How many scoops? 11

Рис. 19.4. Более сложная форма

Как вы помните, функция param() при вызове ее без аргументов возвращает имена всех полей формы, которые были заполнены. Таким обра

Ссылки

Вы, возможно, заметили, что обе функции popup_menu () в предыдущем примере имеют весьма странные аргументы. Что означают

@choises = ('mint',"cherry','mocha');

print pC'What flavor: ", popup_menu ("flavor", \@choises));

работает так же хорошо, как этот:

print pC'What flavor: ", popup_menu ("flavor", ['mint','cherry','mocha']));

Ссылки функционируют примерно так, как указатели в других языках, но с меньшей вероятностью появления ошибок. Они представляют собой значения, которые указывают на другие значения (или переменн

Также, как методом \@массив можно создавать ссылки на именованные массивы и посредством указания [ список ] —

( ключ1, значение!, ключ2, значение2, ... }

на анонимные*.

Да, фигурные скобки теперь используются в Perl с различными целями. Их функцию определяет контекст, в котором используются фигурные скобки.

Подробнее о ссылках вы прочитаете в главе 4 книги Programming Perl

Более сложные вызывающие последовательности

Мы закончим наш рассказ о компонентах форм созданием одного очень полезного компонента, который позволяет пользователю выбирать любое число элементов этого компонента. ФункцияЧтобы ввести в форму прокручиваемый список, нужно сделать следующее:

print scrolling_list(

-NAME => "flavors",

-VALUES => [ qw(mint chocolate cherry vanilla peach) ],

-LABELS => {

mint => "Mighty Mint",

chocolate => "Cherished Chocolate",

cherry => "Cherry Cherry",

vanilla => "Very Vanilla",

peach => "Perfectly Peachy", },

-SIZE =>3,

-MULTIPLE => 1, tl for true , 0 for false

Значения параметров имеют следующий смысл:

-NAME

Имя компонента формы. Значение этого параметра можно использовать позже для выборки пользовательских данных из формы с помощью функции param().

-LABELS

Ссылка на анонимный хеш. Значения хеша это метки (элементы списка), которые видит пользователь формы. Когда пользователь выбирае

-VALUES

Ссылка на анонимный массив. Этот массив состоит из ключей хеша, на которые ссылается -labels.

-SIZE

Число, определяющее, сколько элементов списка пользователь будет видеть одновременно.

-MULTIPLE

Истинное или ложное значение (в том смысле, который принят для этих понятий в Perl), показывающее, можно ли будет пользователю фор

Если -multiple установлена в значение "истина", вы можете присвоить список, возвращаемый функцией param(), мас

@choices = param("flavors");

Вот другой способ создания этого прокручиваемого списка с передачей ссылки на существующий хеш вместо создания такого хеша "на х

%flavors = (

"mint", "Mighty Mint",

"chocolate", "Cherished Chocolate",

"cherry", "Cherry Cherry",

"vanilla", "Very Vanilla",

"peach", "Perfectly Peachy",

);

print scrolling list(

-NAME => "flavors",

-LABELS => \%flavors,

-VALUES => [ keys %flavors ],

-SIZE => 3,

-MULTIPLE => 1, #1 for true , 0 for false ) ;

На этот раз мы передаем в функцию значения, вычисленные по ключам хеша %flavors, ссылка на который выполняется с помощью операции

Создание CGI-программы гостевой книги

Если вы внимательно изучили примеры, приведенные выше, то уже должны быть способны заставить работать простые CGI-программы. А как насчет более сложных? Одна из распространенных задач

* Как мы отметим ниже, это приложение можно было бы назвать программой Webchat (переговоров через

Форма, используемая для создания гостевой книги, довольно проста, она даже проще, чем некоторые из наших форм, посвященных мороженому. Она, правда, имеет некоторые особенности, но не беспокойте

Вероятно, вы хотите, чтобы сообщения в гостевой книге сохранялись и по завершении посещения вашего узла тем или иным пользователем, поэтому вам нужен файл, куда они будут записываться. Гостевая CGI-программа (вероятно) работает не под в

touch /usr/tmp/chatfile chmod 0666 /usr/tmp/chatfile

Отлично, но как обеспечить одновременную работу с программой гостевой книги нескольких пользователей? Операционная система не блокирует попытки одновременного доступа к файлам, поэтому если вы

use Fcnti qw(:flock); # импортирует LOCK_EX, LOCKJ3H, LOCK_NB flock(CHANDLE, LOCK_EX) || bail ("cannot flock $CHATNAME: $!");

Аргумент lock_ex функции flock — вот что позволяет нам обеспечить м

Функция flock представляет собой простой, но универсальный механизм блокировки, несмотря на то, что его базовая реализация существенно изменяется от системы к системе. Она н

* В версиях Perl до 5.004 вы должны превратит

Объектно-ориентированное программирование на Perl

Наконец пришло время научить вас пользоваться объектами и классами и это важнее всего. Хотя решение задачи построения ва

Мы не будем углубляться здесь в теорию объектов, и вы можете просто считать их пакетами (чем они и являются!) удивительных, великолепных вещей, вызываемых косвенно. Объекты содержат подпрог

Пусть, например, модуль CGI.pm возвращает объект $query, который представляет собой входные данные пользовател

$query->param("answer");

Данная запись означает: "Выполнить подпрограмму param () с объектом $query,Если вы хотите получить значение, возвращенное подпрограммой param (), воспользуйтесь обычным оператором присваивания и сохраните это значение в обычной переменной

$he_said = $query->param("answer");

Объекты выглядят как скаляры; они хранятся в скалярных переменных (таких как переменная $ query в нашем примере), и из них можно с

Тип конкретного объекта известен как его класс. Имя класса обычно состоит из имени модуля без расширения рт, и к тому же термины "класс" и "модуль" часто используются как эквиваленты. Таким образом, мы можем говорить о CGI-модуле или о

Доступ к классам осуществляется путем загрузки модуля, который выглядит точно так же, как любой другой модуль, за исключением того что объектно-ориентированные модули обычно ничего не экспортируют. Вы можете рассматривать класс как фабр

Вот пример:

$query = CGI->new(); # вызвать метод new() в классе "CGI"

Здесь мы имеем дело с вызовом метода класса. Метод класса выглядит точно так же, как метод объекта (о котором мы говорили секунду назад), за исключением того что вместо использова

Иногда то же самое записывается так:

$query = new CGI; # то же самое

Вторая форма по принципу действия идентична первой. Здесь меньше знаков препинания, благодаря чему в некоторых случаях она более предпочтительна. Однако она менее удобна в качестве компонента б

С точки зрения разработчика объектных модулей, объект это ссылка на определяемую пользователем структуру данных, часто на анонимный хеш. Внутри этой структуры хранится все

Объекты в модуле CGI.pm

CGI-модуль необычен в том смысле, что его можно рассматривать либо как традиционный модуль с экспортируемыми функциями, либо как объектный модуль. Некоторые программы пишутся гораздо легче с п

Сначала, однако, нам нужно создать этот объект явно. Для CGI.pm, как и для многих других классов, метод, который позволяет создавать объекты,— это метод класса

* В отличие от C++ Perl не считает new ключев

Данный метод конструирует и возвращает новый CGI-объект, соответствующий заполненной форме. Этот объект содержит все данные, введенные пользователем в форму. Будучи вызванным без аргументов, ме

Через минуту мы покажем вам эту программу и поясним ее работу. Давайте предположим, что она называется guestbook и находится в каталоге cgi-bin

Please sign our HREF="http://www.SOMEWHERE.org/cgi-bin/guestbook">guestbook</A>.

Затем программа загружает в броузер HTML-форму и, на всякий случай, предыдущие сообщения гостей (в ограниченном количестве), чтобы пользователь мог их просмотреть. Пользователь заполняет форму,

Вот наша программа. Перед тем как разбирать ее поэтапно, вы, возможно, захотите просмотреть программу целиком.

#!/usr/bin/peri -w

use 5.004;

use strict; # установить объявления и взятие в кавычки use CGI qw(:standard); # импортировать сокращения согласно

sub bail ( # функция обработки ошибок

my $error = "@ ";

print hi("Unexpected Error"), p($error), end html;

die $error;

!

my(

$CHATNAME, # имя файла гостевой книги $MAXSAVE, # какое количество хранить $TITLE, #

Sentry, # одна конкретная запись ) ;

$TITLE = "Simple Guestbook";

$CHATNAME = "/usr/tmp/chatfile"; # где все это в системе находится $MAXSAVE =10;

print header, start_html($TITLE), hi ($TITLE);

$cur ” CGI->new(); # текущий запрос if ($cur->param("message")) ( # хорошо, мы получили сообщение

• $cur->param("date", scalar localtime); # установить текущее время Sentries = ($cur); #

# открыть файл для чтения и записи (с сохранением предыдущего содержимого) open(CHANDLE, "+< $CHATNAME") II bail("cannot open $CHATNAME: $!");

# получить эксклюзивную блокировку на гостевую книгу

# (LOCK_EX == exclusive lock)

flock(CHANDLE, LOCK_EX) || bail("cannot flock $CHATNAME: $!");

# занести в $MAXSAVE старые записи (первой самую новую)

$entry = CGI->new(\*CHANDLE); t передать дескриптор файла по ссылке

push Sentries, $entry;

}

seek(CHANDLE, 0, 0) 11 bail("cannot rewind $CHATNAME: $!");

foreach $entry (Sentries) (

$entry->save(\*CHANDLE); # передать дескриптор файла по ссылке } truncate(CHANDLE, tell(CHANDLE)) || bail("cannot truncate $CHATNAME: $!");

close(CHANDLE) || bail ("cannot close $CHATNAME: $!");

print hr, start form; # hr()проводит горизонтальную линию: <HR> 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 (Sentries) f

printf("%s [%s]: %s",

$entry->param("date"),

$entry->param("name"),

$entry->param("message")) ;

print br() ;

} print end_html;

На рис. 19.5 вы видите изображение, которое появляется на экране после запуска этой программы.

Рис. 19.5. Форма простой гостевой книги

Обратите внимание на то, что программа начинается с оператора

usa 5.004;

Если вы хотите запускать ее с помощью более ранние версии Perl 5, то нужно превратить в комментарий строку

use Fcnti qw(:flock)

и заменить lock_ex в первом вызове flock на z.

Поскольку каждое выполнение программы приводит к возврату HTML-формы в броузер, который обратился к программе, то программа начинается с задания HTML-кода:

print header, start_html($TITLE), hi($TITLE) ;

Затем создается новый CGI-объект:

$cur = CGI->new(); # текущий запрос

if ($cur->param("message")) ( # хорошо, мы получили сообщение

$cur->param("date", scalar localtime); # установить текущее время

Sentries = ($cur); # записать сообщение в массив

>

Если нас вызывают посредством заполнения и передачи формы, то объект $cur должен содержать информацию о тексте, введенном в форму.

Если нас вызывают не посредством передачи формы, а выполняя щелчок мышью на ссылке Please sign our guestbook, то объект запроса, который мы создаем, будет пуст. ПроверкаВ любом случае мы переходим к проверке наличия записей, созданных ранее в нашем сохраняемом файле. Эти записи мы будем считывать в массив @entries. (Вспомните о том, что мы

open(CHANDLE, "+< $CHATNAME") || bail("cannot open $CHATNAME: $!");

Эта функция открывает файл в режиме неразрушающего чтения-записи. Вместо open можно использовать sysopen ().

# нужно импортировать две "константы" из модуля Fcnti для sysopen use Fcnti qw( 0_RDWR 0_CREAT );

sysopen(CHANDLE, $CHATFILE, 0_RDWRI0_CREAT, 0666) || bail "can't open $CHATFILE: $!";

Затем мы блокируем файл, как описывалось выше, и переходим к считыванию текущих записей из $ мах save <

flock(CHANDLE, LOCK_EX) 11 bail("cannot flock $CHATNAME: $!");

while (!eof(CHANDLE) &S Sentries < $MAXSAVE) {

$entry = CGI ->new(\*CHANDLE); # передать дескриптор файла по ссылке

push Sentries, $entry;

}

Функция eof — встроенная Perl-функция, которая сообщает о достижении конца файла. Многократно передавая в метод

seek(CHANDLE, 0, 0) || bail("cannot rewind $CHATNAME: $!");

foreach $entry (Sentries) {

$entry->save(\*CHANDLE); # передать дескриптор файла по ссылке } truncate(CHANDLE, tell (CHANDLE)) || bail("cannot truncate $CHATNAME: $!");

close (CHANDLE) || bailC'cannot close $CHATNAME: $!");

Функции seek, truncate и tell —встроенные Perl-функции, описания ко

Метод save () обеспечивает собственно создание записей. Его можно вызвать здесь как $entry->save, поскольку

Формат записи сохраняемого файла выглядит следующим образом (запись завершается знаком "=", стоящим в отдельной строке):

ИМЯ1=ЗНАЧЕНИЕ1 ИМЯ2=ЗНАЧЕНИЕ2 ИМЯЗ=ЗНАЧЕНИЕЗ

Теперь пора возвратить обновленную форму броузеру и его пользователю. (Это будет, конечно, первая форма, которую он видит, в том случае, если он щелкнул на ссылке Please sig

print hr, start_form; # hr() проводит горизонтальную линию: <HR>

Как мы уже упоминали, CGI.pm позволяет нам использовать либо прямые вызовы функций, либо вызовы методов через CGI-объект. В нашей

print pC'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;

* Фактически она представляет собой glob-ссылку, а не ссылку на дескриптор файла, но в данном случае это почти то же самое.

Метод textfieid() возвращает поле ввода текста для нашей формы. Первый из двух приведенных выше вызовов генерирует HTML-код поля в

Компоненты формы, создаваемые модулем CGI.pm, по умолчанию устойчивы: они сохраняют свои значения до следующего вызова. (Но лишь в

NAME="name" VALUE="Sam Smith"

Совсем другое дело второй вызов text field (). Мы не хотим, чтобы

Наконец, к удовольствию пользователя, мы выводим текущий перечень сохраняемых сообщений, включающий, естественно, то, которое он только что передал:

print h2("Prior Messages");

foreach $entry (Sentries) {

printf("%s [%s]: %s",

$entry->param("date"),

$entry->param("name"),

$entry->param("message"));

print br ();

} print end_html;

Как вы, без сомнения, догадываетесь, функция h2 задает HTML-заголовок второго уровня. В остальной части кода мы просто последовате

Пользователи могут работать с этой формой гостевой книги, непрерывно набирая сообщения и нажимая кнопку передачи. Это имитирует электронную доску объявлений, позволяя пользователям видеть новые сообщения друг друга сразу же после их пер

предыдущие значения компонентов формы автоматически сохраняются до следующего вызова. Это особенно удобно при создании многоступенчатых форм например, тех, которые использ

Поиск и устранение ошибок в CGI-программах

CGI-программы, запускаемые с Web-сервера, функционируют в совершенно иной среде, нежели та, в которой они работают при вызове из командной строки. Конечно, вы всегда должны добиваться,

Помогут вам разобраться в этом сборник часто задаваемых вопросов по CGI и хорошая книга по CGI-программированию. Некоторые из источников перечислены в конце главы.

Вот краткий перечень проблем, часто встречающихся в CGI-программи-ровании. При возникновении почти каждой из них выдается раздражающе-бесполезное сообщение 500 Server Error,

Если, посылая HTML-код в броузер, вы забыли о пустой строке между HTTP-заголовком (т.е. строкой Content-type)

Серверу необходим доступ к сценарию с правом чтения и выполнения, поэтому он, как правило, должен иметь режим 0555, Каталог, в котором находится сценарий, сам должен быть выполняемым, поэтому присвойте ему режим доступа 0111, а лучше Сценарий должен быть инсталлирован в соответствующем конфигурации вашего сервера каталоге. В некоторых системах, например, это может быть

Советы по отладке в режиме командной строки приведены в документации на CGI.pm.

Возможно, в имя файла вашего сценария понадобится вводить определенное расширение, например cgiwivipl. Мы возражаем проти

Помните: расширение р1 означает, что это Perl-библиотека, а не исполняемый Perl-файл. Не путайте эти понятия, иначе вашей судьбе не позавидуешь. Если у вас безуслов

Конфигурация вашего сервера требует особого разрешения на выполнение CGI для каталога, в который вы поместил

• Web-сервер не выполняет ваш сценарий при запуске с вашим идентификатором пользователя. Убедитесь в том, что файлы и каталоги, к которым обращается сценарий, открыты для всех пользователей, для которых Web-сервер выполняет сценарии, та

Всегда запускайте свой сценарий с Perl-флагом -w, чтобы иметь возможность получать предупреждения. Они напра

Убедитесь, что версии программ и пути к каталогам с Perl и всем используемым вами библиотекам (вроде CGI.pm)

В начале своего сценария включите режим autoflush для дескриптора файла stdout, <

use FileHandle;

STDOUT->autoflush(l) ;

Проверяйте возвращаемое значение каждого системного вызова, который производит ваша программа, и в случае неудачного исхода выполняйте соответствующее действие.

Perl и Web: не только <

Perl используется не только в CGI-программировании. Среди других направлений его применения анализ ф

Специализированные издательские системы

Коммерческие издательские Web-системы могут сделать трудные вещи легкими, особенно для непрограммистов, но они не столь гибки, как настоящие языки программирования. Без исходного кода в

Perl — идеальный язык для создания специализированных издательских систем, приспособленных под ваши уникальные потребности. С его помощью можно одним махом преобразовать нео

* Perl-интерфейс к графической библиотеке gd Томаса Баутелла содержится в модуле GD.pm,

Встроенный Perl

Самый быстрый, самый дешевый (дешевле бесплатного уже ничего быть не может) и самый популярный Web-сервер в Internet, Apache, мож

Другой способ ускорить выполнение CGI — использовать стандартный модуль CGI::Fast. В отличие от описанного выш

Если Web-сервер у вас работает под Windows NT, вам определенно следует посетить Web-сервер ActiveWare, www.acf

Автоматизация работы в Web с помощью LWP

Ставили ли вы когда-нибудь перед собой задачу проверить Web-документ на предмет наличия "мертвых" ссылок, найти его название или выяснить, какие из его ссылок обновлялись с прошлого чет

* Стандартный дистрибутив Perl версии 5.004 п

Сейчас вы могли бы сделать все это вручную с помощью броузера, но, поскольку графические интерфейсы совершенно не приспособлены для автоматизации программирования, это был бы медленный и

Модули LWP (Library for WWW access in Perl — библиотека для доступа к WWW на Perl)

peri -MLWP::Simple -e "getprint 'http://www.perl.com/perl/index.html'"

За исключением модуля LWP: :Simple, большинство модулей комплекта LWP

#!/usr/local/bin/peri use LWP;

$browser = LWP::UserAgent->new(); # создать виртуальный броузер $browser->agent("Mothra/126-Paladium:); # дать ему имя f

# сделать GET-запрос по URL через виртуальный броузер

$webdoc = $browser->request(HTTP::Request->new(GET => $url));

if($webdoc->is success) ( # нашли

print STDOUT "$url: :, $result->title, "\n";

} else { # что-то не так

print STDERR "$0: Couldn't fetch $url\n";

” }

Как видите, усилия, потраченные на изучение объектов Perl, не пропали даром. Но не забывайте, что, как и модульЭтот сценарий работает так. Сначала создается объект пользовательский агент (нечто вроде автоматизированного виртуального броузера). Этот объект используется для выдачи за

* Помните, что по Ларри Уоллу три главных достоинства программиста есть Леность, Нетерпение и Гордость.

Вот программа, которая выводит рассортированный список уникальных ссылок и изображений, содержащихся в URL, переданных в виде аргу

#!/usr/local/bin/peri -w use strict;

use LWP 5.000;

use URI::URL;

use HTML::LinkExtor;

my($url, $browser, %saw);

$browser ” LPW::UserAgent->new(); # создать виртуальный броузер fо reach $url ( @ARGV ) (

# выбрать документ через виртуальный броузер

my $webdoc = $browser->request (HTTP: :Request->new (GET => $url).);

next unless $webdoc->is_success;

next unless $webdoc->content_type eq 'text/html';

# не могу разобрать GIF-файлы

my $base = $webdoc->base;

# теперь извлечь все ссылки типа <А ...> и <IMG ..•> foreach (HTML::LinkExtor->new->parse($webdoc->

next unless $tag eq "a" or $tag eq "img";

my $link;

foreach $link (values %links) (

$saw{ uri($link,$base)->abs->as_string }++;

} } ) print join("\n",sort keys %saw), "\n";

На первый взгляд все кажется очень сложным, но вызвано это, скорее всего, недостаточно четким пониманием того, как работают различные объекты и их методы. Мы не собираемся здесь давать пояснени

Дополнительная литература

Естественно, о модулях, ссылках, объектах и Web-программировании можно рассказать гораздо больше, чем вы узнали из этой маленькой главы. О CGI-программировании можно написать отдельную

Файлы документации CGI.pm.

Библиотека LWP из CPAN.

CGI Programming on the World Wide Web by Shishir Gundavaram (O'Reilly & Associates).

Web Client Programming with Perl by Clinton Wong (O'Reilly & Associates).

HTML: The Definitive Guide by Chuck Musciano and Bill Kennedy (O'Reilly & Associates).

How to Setup and Maintain a Web Site by Lincoln Stein (Addison-Wesley).

CGI Programming in С and Perl by Thomas Boutell (Addison-Wesley).

Сборник FAQ no CGI Ника Кью.

• Man-страницы: perltoot, perlref, perlmod, perlobj.

Упражнение


Ответ см. в приложении А.

1. Напишите программу для создания формы, содержащей два поля ввода, которые при передаче данных формы объединяются.

2. Напишите CGI-сценарий, который определяет тип броузера, делающего запрос, и сообщает что-нибудь в ответ. (Совет: воспользуйтесь переменной среды HTTP_




|     Назад     |  

| Содержание | Предисловие | В



Сайт создан в системе uCoz